这是indexloc提供的服务,不要输入任何密码
Skip to content

Conversation

@stuartpb
Copy link

This is my proposed implementation for moving Dokku's commands into plugins as described in #457.

While I moved most of the commands from the root dokku script and 00_dokku-standard out to their own plugins (and added individual documentation for each one), I moved the "version" command from 00_dokku-standard into the root script, as it seems wise to make that as plugin-independent as the "help" command (which I also left in the root script).

With this new layout, plugins can be placed in front of (almost) any command in Dokku, and individual commands can be overridden, replaced, or disabled entirely. Some things this enables:

  • A plugin that requires "administrator access" before running certain commands, which can be enforced by moving the corresponding plugins into a directory within the access-control plugin.
  • Similarly, a plugin that enforces ownership of an app by denying users who did not create the app from pushing / performing commands on it.
  • By replacing the core "deploy" command with one that pushes the built container to a test / production cluster, Dokku could be used as the basis for a build / integration / deployment server.

Since execution order never really matters for any of the core plugins relative to each other, I'm ambivalent about the "XX_" prefixes. I mostly kept them to follow the precedent set by "00_dokku-standard" and other projects that use similar conventions like GRUB.

Hooks aren't really any less stable than anything else in Dokku,
which is covered by the README
core-install is the install/uninstall scripts;
core-admin is the admin commands.
Since core-plugin-system provides the commands that run the install hooks in
00_core-install, it makes sense to put it closer to the top: however,
there needs to be priority room for plugins before any core plugins with
commands (so higher-priority plugins can wrap/deny access to them), which
is why this is at 05 and not 00 itself.
I misinterpreted the purpose of these hooks: they belong with the
plugin that defines the "delete" command.
This way, individual components of Dokku can be disabled or overridden
without affecting the other commands.
@progrium
Copy link
Contributor

Very interesting. Feedback?

@asm89
Copy link
Contributor

asm89 commented Feb 19, 2014

I'm unsure about moving the receive, build, release and deploy commands out of the base dokku file. This is the minimal core you need to run dokku, all the other stuff we moved to plugins. Maybe we envision different things for the project, but I see it as a great starter to play around with docker and git push based deployments. Right now if you're new to the project, you open up the dokku file and you can get a fair idea of what's going on. Maybe this is just a documentation issue though. ;)

@stuartpb
Copy link
Author

I'm not sure why the Travis build failed there - looks like pluginhook failed to allocate heap in the middle of a test for some reason. These changes don't do anything that should be causing drastically more memory usage. Maybe rerun the test?

@progrium
Copy link
Contributor

Yeah, there's some good stuff in here but I agree with @asm89's comments

On Wed, Feb 19, 2014 at 4:35 PM, Stuart P. Bentley <notifications@github.com

wrote:

I'm not sure why the Travis build failed there - looks like pluginhook
failed to allocate heap in the middle of a test for some reason. These
changes don't do anything that should be causing drastically more memory
usage. Maybe rerun the test?

Reply to this email directly or view it on GitHubhttps://github.com//pull/458#issuecomment-35551837
.

Jeff Lindsay
http://progrium.com

@ghost
Copy link

ghost commented Feb 19, 2014

A 'how dokku works' flowchart/explanation could take care of that

@ghost
Copy link

ghost commented Feb 19, 2014

After rerunning tests a few time we have a passing mark

@lonnen
Copy link

lonnen commented Mar 8, 2014

I was midway through writing this change myself when I thought to look into the pull requests. I like this because you still get a dokku out of the box but it's easier to experiment with replacing core bits. I am building a toy CI, for example.

@stuartpb
Copy link
Author

stuartpb commented Mar 9, 2014

@asm89, I agree that it's an important point to make it easy for people new to Dokku to be able to easily tell what's going on. To that point, moving every core command into a plugin makes it easier to dive into the Dokku code.

Rather than sifting through which components are (rather arbitrarily) part of the base script, the "standard" plugin, or another plugin that comes with Dokku out-of-the-box, you can simply determine what each component does, and where it's implemented, by looking at ls plugins, knowing that all its associated implementation is going to be in a plugin directory containing only code for that functionality.

Indeed, when I was hacking together the rethinkdb datastore plugin, I found that I was reading from this branch, rather than upstream/master, to determine the functionality of each component of Dokku, for exactly this reason of increased discoverability. The README I've added for each component helps here as well.

It also makes Dokku significantly more hackable as a base for building other, similar tools (such as a CI / build server as described above). You can treat Dokku more as a framework for sshcommand-and-pluginhook-based services, that by default comes with a set of plugins to receive Git packages, build a Docker container for them according to Heroku buildpacks, and then virtual-host them through an nginx proxy. (Indeed, this is how we're drafting our MVP infrastructure to work using Dokku @hutpass.)

@ghost
Copy link

ghost commented Mar 9, 2014

I'm on board but I'll call in @plietar as well to provide his opinion

@plietar
Copy link
Contributor

plietar commented Mar 9, 2014

Sorry I've been away lately.
First of all I think this is a good idea, thanks @stuartpb.
A few points however :

I don't like the XX_core- naming scheme. It makes the file names long and annoying, and most (all ?) hooks don't care about ordering.
I was thinking of improving pluginhook to support patterns like pluginname/XX_hookname. I think it makes more sense to have single hooks have higher priority than others rather than whole plugins. I can work on it tommorow.

While were at it, concering commands organization, ideas from #312 could be included (one script per command, commands are prefixed with the plugin name, use of aliases, automatic help messages which btw could be used to generate the man page, ...).
This avoids the use of one plugin per command as you've done it. You can then use aliases to select the prefered implementation of a command. We can then group (build, release, deploy, clean) as one plugin, and all small utility commands from 00_dokku_standard as another.

This is a major compatibility break, so we would have to think about both schemes.

Also the names can be simplified (again, I'm not a big fan of 20 char long plugin names)

  • deploy-start => deploy
  • receive-cycle=> receive
  • release-env => release

etc ....

@stuartpb
Copy link
Author

stuartpb commented Mar 9, 2014

I agree about ditching the "XX_core-" name components since none of the hooks really care about ordering.

I do think that the slightly more verbose names (deploy-start, release-env) are called for, however, so that they can be distinguished from alternatives to the core version of the plugin (for instance, deploy-start could be replaced with a deploy-saveload plugin that deploys containers to a remote server via docker save and docker load). Maybe core-deploy would be enough for that, but I prefer the more descriptive names that tell you what the core version of that command does.

EDIT: Just checked out #312. I'm going to tackle incorporating that idea into this system now.

@stuartpb
Copy link
Author

stuartpb commented Mar 9, 2014

Okay, so I've thrown up an initial implementation of a version of the plugin system that supports scripts for individual commands a la #312. It's a little clunky right now:

  • Command/subcommand scripts get their command name as $1 (because I didn't have time to rewrite the functionality for every command's script to adjust the number of parameters expected).
    • I'm thinking I'm actually going to keep this behavior: it allows things like easily getting the name of the plugin you're in, and implementing multiple commands by symlinking to a single script that switches on $1 (rather than reassembling it by pulling apart $0).
  • Similarly, the config command is still implemented as a "commands" hook script because I didn't have time to split its dependencies.
  • core violates the expected behavior from any other plugin/command, and there's virtually no rhyme or reason to what's a "core subcommand" versus its own plugin
    • Each command is implemented as a separate plugin as of ae97607
  • The help command is still implemented via listening for the root help command in the commands hook for each plugin and cating a heredoc. The help command should be re-implemented as a plugin that reads some kind of file for each plugin's documentation, and formats the output appropriately (with flush spacing for every command!). Interested in hearing thoughts on approaches to this (including how similar projects have handled command documentation, etc).
  • Command scripts are called via exec (this is probably fine).

@stuartpb
Copy link
Author

Okay, here's what I'm thinking for handling help files:

  • Help content is stored in help.txt. (The extension distinguishes it from the plethora of executable hook scripts in the plugin's directory.)
  • Each line is interpreted to describe the usage, and human explanation, for a command. Usage and explanation are separated by the first instance of 2 or more spaces.
  • Lines starting with ":" will have the ":" replaced with the name of the plugin, followed by a colon if there is a subcommand name immediately following the colon.

For example, this help.txt for the config plugin:

: <app>  display the config vars for an app
:get <app> KEY  display a config value for an app
:set <app> KEY1=VALUE1 [KEY2=VALUE2 ...]  set one or more config vars
:unset <app> KEY1 [KEY2 ...]  unset one or more config vars

would be formatted as this when output by the help command:

    config <app>                                    display the config vars for an app
    config:get <app> KEY                            display a config value for an app
    config:set <app> KEY1=VALUE1 [KEY2=VALUE2 ...]  set one or more config vars
    config:unset <app> KEY1 [KEY2 ...]              unset one or more config vars

This allows help files to be less redundant, and to permit renaming of the plugin. (Meanwhile, if a plugin, for some reason, implements commands at a fixed name outside its namespace, it can define those commands in help.txt by simply including them, and they won't be namespaced as their lines won't begin with ":".)

The `commands` hook still does the base parameter validation and
initialization, which is a little gauche, but not a major affront
for right now.
@stuartpb
Copy link
Author

By the way, is there a reason dokku runs commands in a loop rather than using pluginhook?

@josegonzalez
Copy link
Member

I'm interested in having this be merged in some sense, so I'm re-opening to encourage some discussion :)

@josegonzalez
Copy link
Member

Succeeded by #592

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.

6 participants