Skip to content

form to upload a plugin jar in plugin tab#768

Merged
arvindsv merged 14 commits intogocd:masterfrom
pwen:plugin
Dec 19, 2014
Merged

form to upload a plugin jar in plugin tab#768
arvindsv merged 14 commits intogocd:masterfrom
pwen:plugin

Conversation

@pwen
Copy link
Contributor

@pwen pwen commented Dec 12, 2014

This is the initial commit for "enable plugin install/uninstall on the UI" feature. Work in Progress. Please feel free to give us feedback along the way.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Take a look at tests for this.

@arvindsv
Copy link
Member

I like it! I think it's looking good. My thoughts:

The call to addPlugin() doesn't yet make the plugin visible to Go, right? By default, Go does not check for new plugins in that directory, till a server restart. How it works is, during startup, these things happen, in order:

  1. Start plugin infrastructure.
  2. That starts a monitor thread which monitors the plugins' location.
  3. On change (meaning a file is added, removed or updated), it notifies listeners of the change. The DefaultPluginJarChangeListener gets notified and it does a bunch of checks and then adds a plugin.

In case you haven't seen it, some plugin architecture documentation is here.

To see whether the upload works, you can also set the system property (pluginLocationMonitor.sleepTimeInSecs) to something other than -1. It affects the timer used here, so that Go actually checks every few seconds to see if there are new plugins on the filesystem.

@arvindsv
Copy link
Member

Maybe in a later iteration of this, it'll be useful to surface up errors found during adding of the plugin, to the UI? I think that'll be nice (along with preventing the plugin from being written to the file system). It'll take a little more work around the infrastructure though. I don't want to introduce scope creep into your chosen feature. :)

I think it's looking good! Keep going. Let me know how I can help.

@pwen
Copy link
Contributor Author

pwen commented Dec 12, 2014

@arvindsv Yup, it's work in progress, and how I tested it was indeed to set the pluginLocationMonitor.sleepTimeInSecs variable to > 0. That way when I refreshed the browser, the monitor thread kicks in, and the plugin shows.

My next steps are -

  1. Instead of returning true or false, I want to return a response that has both success and error messages. And of course this should percolate to the UI.
  2. I want to add some sort of validation on the file (e.g. check it's a jar file, etc). Right now the monitor does the validation whenever it detects updated/added/removed plugins, but I want to make sure on the input side we're doing validation as well.
  3. I want to kick off the restart mechanism after a plugin is successfully uploaded, so people don't have to restart the server on the box themselves. It seems like there're multiple ways of achieving - I could, for example, start a new monitor thread whenever there's an uploaded plugin. Any ideas? On a related note, I was wondering why we designed the Monitor & its internal Thread the way they are. It seems to me that Thread knows too much (logic, environment variables, etc). Do you think there's a way we can improve this?

pamo and others added 5 commits December 14, 2014 15:35
method for better test coverage; a better way is to have a wrapper class
around the fileUtil so we can test the shit out of every
exception we'd like, but that'd a good follow-up refactoring commit.
@pamo
Copy link
Contributor

pamo commented Dec 15, 2014

@arvindsv worked on file type validation today with @pwen. Still thinking about the restart mechanism. Any thoughts on improving the current way the monitor handles threading?

@arvindsv
Copy link
Member

@pamo and @pwen, sorry was away on Saturday and a little busy today. Will respond tomorrow. At a very high level, I feel that it can (needs to) be changed a bit as well. I'll think about it a bit more and respond tomorrow.

@pwen
Copy link
Contributor Author

pwen commented Dec 15, 2014

@arvindsv Don't worry about it, not expecting you to work on weekends. :-p

We should definitely have a conversation about the monitor thread and the restart mechanism in general. But I think what we have done so far - creating a form to let the user upload the jar directly from the UI - is already an improvement from the current workflow (aka access the box and drop the jar file there manually). Already some value added, what do y'all think? Yeah, they still have to restart the server, and yea, and we should continue to work on this, maybe in another pull request?

@pamo
Copy link
Contributor

pamo commented Dec 15, 2014

Yea I agree. Restarting the machine should be broken out into another PR. @danielsiwiec suggested using file change notifications as the mechanism to restart the machine. https://docs.oracle.com/javase/tutorial/essential/io/notification.html

@arvindsv
Copy link
Member

I suppose my ideal approach would be to remove the file system monitor, completely. Upload should be possible through the UI and through a well-documented and easy API. Watching the file system for changes should not even be needed (it should be read once, at startup, obviously).

About your (@pwen's) thoughts about changing parts of the monitor and thread: Yes, sure. There's room for improvement there, and reducing the amount of knowledge of each of those classes. It, kind of, gets hard to name classes well. But, if you have ideas for change, propose them, and we can talk about it.

I think I'd start tackling it at around here. I think there should be one way to add a plugin to the system. This new way should provide facilities such as validateBeforeAdding() and add(), and should probably work with a stream (contents of JAR), so that it would help send messages back to the user, about failed uploads, etc. Validation should happen before adding the file to the filesystem.

If we're keeping the file system monitor, in whatever form, I think it should be something like this:

Monitor -------x
               |
               v
                --------> One way to add plugins, with validation
               ^
               |
UI ------------x

@arvindsv
Copy link
Member

@pamo, I think there is value in having the ability to upload a plugin (without restarting, for now). I haven't taken a look at the changes, since I last commented. If you want, I can take a look, give feedback and maybe accept it, if everything looks ok. Do you want me to?

@pwen
Copy link
Contributor Author

pwen commented Dec 15, 2014

@arvindsv Yes that would be great! Please review the changes and give some feedback! We'd like to see this go through :)

@pamo
Copy link
Contributor

pamo commented Dec 15, 2014

Yup, yup. @pwen and I are pulling your negotiation leg hint hint
"Let's write another story for that feature" 😁

.gitignore Outdated
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this could be problematic. If you look at the Gemfile, there are a couple of locally vendored gems, which will get lost, with this change. It's a little complicated, because Go is not purely a Rails project. The fact that it uses JRuby and is packaged as a WAR file makes it a little weird. So, bundler is not used directly at runtime, as with most Rails projects.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't brought up the server with this change, yet. I'll do it and see how this page looks. Was there a reason to remove this? [Not saying it shouldn't ... just wondering]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing it has something to do with the "INSTALLED_PLUGINS" below. I'll probably realize why as soon as I see the UI. :) I'll do that later tonight. I'm in the middle of something.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, let us know!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got around to seeing this. I'm no expert in UI/UX. But, I was wondering whether "Upload Plugins" needs to be given such a prominent spot on the page. It's at the top, and that would make sense if it's the most used user action. I don't know if it would be. This is what I mean:

uploadplugin_topofpage

Maybe you can consider doing something like this? I've uploaded the index.html.erb I used to make that happen.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was following the same styling conventions I saw on another page with form fields but I like your solution to reduce clutter on the page @arvindsv.

@arvindsv
Copy link
Member

Overall, I'm almost ready to merge this in (even with my thoughts about UI changes). The two things that are making me squirm a bit are:

  1. The Gemfile change.
  2. The DefaultPluginManager change.

If those are resolved, I can accept this change, while you continue further, on changing the structure of how plugins are loaded, if you want.

@arvindsv arvindsv added this to the Release 15.1 milestone Dec 17, 2014
pwen added 3 commits December 17, 2014 14:45
…he Manager, respectively; first step to create a wrapper class around FileUtils - it captures .copyFile method only, for now.
@pwen
Copy link
Contributor Author

pwen commented Dec 17, 2014

@arvindsv So I reverted the .gitignore file change and refactored DefaultPluginManager. I also found a bug where the website blows up when someone clicks "upload" when nothing is selected from the disk yet. How do things look now?

I agree with you that uploading a plugin is probably not the most common use case. I can take a look at your UI suggestions tonight. On a related note, where are we testing the javascript interactions on the rails side (e.g. toggle hide/show of the upload form when button is clicked).

@arvindsv
Copy link
Member

@pwen, It's looking good!

About testing Javascript, it's Jasmine tests. You can see them running in the build here. Not visually, but the fact that they're running. Username: view and password: password.

Usually, I leave only a small initialization step in the ERB and move the Javascript out into a different file, so that it can be used. I'll talk about this with an example. Here's the commit of a feature in progress. Confusingly enough, it is the UI for feature toggles, which will be used for nearly every feature, going forward, so that a release can be made at any time, without worrying too much about what has gone in. In fact, I think I will feature toggle the plugin upload feature as well, for a little while, so that we can iterate on it, without confusing anyone, if we make a release. We can get rid of the toggle soon.

Back to the commit:

  1. As I said, I usually add an initialization step in the ERB and verify it.
  2. Then, the Javascript is in a different file, and Jasmine specs are written for it.

I don't like the slowness of the feedback loop during running Jasmine specs, if I run them the way the build runs it. That's because it brings up the server, using JRuby, etc. I prefer to write my Jasmine tests outside, using just plain Jasmine and then, bring the code and specs over to the Go codebase. In the build, it is the right thing to do, because the specs run against the Javascript from the asset pipeline, that is the real Javascript used by Go.

Hope that makes sense. Let me know if it doesn't.

@arvindsv
Copy link
Member

Forgot to mention: There's always some old code which doesn't do this (and has inline Javascript, which is not tested well). I do this, to make sure that it is tested. I'd definitely recommend this.

@pwen
Copy link
Contributor Author

pwen commented Dec 19, 2014

@arvindsv makes sense, thanks for the explanation!

anything else we need to do for this to be merged?

@arvindsv
Copy link
Member

Nope, nothing else for this one, I think. I was running all the tests, to make sure it's ok. They're all passing. I'll accept this now. I worked on feature toggling this as well. So, I'll merge this and then apply that on top.

arvindsv added a commit that referenced this pull request Dec 19, 2014
form to upload a plugin jar in plugin tab
@arvindsv arvindsv merged commit 3481b96 into gocd:master Dec 19, 2014
arvindsv added a commit to arvindsv/gocd that referenced this pull request Dec 19, 2014
arvindsv added a commit that referenced this pull request Dec 19, 2014
#768 - Add feature toggle for plugin upload form.
@arvindsv
Copy link
Member

I've submitted the feature toggle as well, here. The build is running. Thank you, @pamo and @pwen! This is looking like the start of a lot of nice changes around this area or other areas! 👍

@pwen pwen deleted the plugin branch December 19, 2014 21:03
@pwen
Copy link
Contributor Author

pwen commented Jan 14, 2015

@arvindsv Hey! @pamo and I are having our second hack night, and are excited to contribute to this.

What do you think should be the next thing in this capability that we should work on? We were thinking about the restart mechanism. If that's the case, we'd like some guidance on this. What are your thoughts?

@arvindsv
Copy link
Member

Hi @pwen and @pamo. Very cool. Here are some thoughts:

I'd not look at the restart mechanism. I don't think the restart mechanism should be strictly necessary. It should be possible to upload a plugin and load it, without having to restart the server. As I might have told you before, it was done to make sure that the Java perm gen space is properly freed after an older version of a plugin is removed (Java's GC does not garbage collect types, at least the older ones didn't). So, I'd look at the ability to run verifications on a plugin, without placing it on the filesystem, and rejecting the upload. If that doesn't seem interesting enough :), I'd consider reloading plugins on the agent side. Right now, plugins get reloaded only on the server side.

If those two don't interest you, then definitely look at the restart mechanism (maybe you've already started looking at it). Let me know if you need any help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants