docker-archive / deploykit

A toolkit for creating and managing declarative, self-healing infrastructure.
Apache License 2.0
2.25k stars 262 forks source link

Improve UX with frontend for managing multiple groups and other resource types #230

Open chungers opened 8 years ago

chungers commented 8 years ago

Currently the CLI is very developer-facing and a free-for-all in that it reflects all the http endpoint for all the plugin types. It's handy for developers to develop and test the building blocks but confusing to end users / ops.

The Issue here tracks the design and development of a separate frontend (and likely a separate CLI) that will provide a unified UX that will be much better suited for end-users of this toolkit and not just for developers.

Features

This "frontend" will likely to provide means to simplify the start up for plugins -- by examining the local filesystem holding the configs and determine the plugins that need to be run. Ability to do this will be environment specific (e.g. running the plugins as unix daemons or as docker containers or whatever), so a base implementation and mechanisms for naming/ typing of plugins will have to be worked out as part of this.

wfarner commented 8 years ago

Can you elaborate on the UX? Doing so before breaking ground on code will be extremely helpful for others to collaborate during development, and have a shared vision of where this takes the project.

chungers commented 7 years ago

Motivation

Design

The proposal here is that we use directory hierarchy / filesystem to manage a large collection of configuration files (in JSON). There will be a well-defined hierarchy of files and directories and the "frontend" (aka demux) will traverse and invoke the plugins as watch or update. The reason for using a directory hierarchy:

There are also other nice properties such filesystem events / file hashes that provide enough signal to simplify interaction with plugins such as Group, which has distinct verbs like watch and update. These verbs can be deduced from the filesystem events and hashes or commit triggers.

Initially we will only support groups. So under a top level directory, we will have something like this, for managers, workders-db, workers-large, and workers-small groups.

infrakit/
└── groups
    ├── .trash
    ├── managers
    │   └── config.json
    ├── workers-db
    │   ├── config.json
    │   └── terraform_files
    │       ├── main.tf
    │       └── variables.tf
    ├── workers-large
    │   └── config.json
    ├── workers-small
    │   └── config.json
    └── zookeeper
        └── config.json

8 directories, 7 files

/tmp$ cat infrakit/groups/zookeeper/config.json 
{
    "ID": "zk",
    "Properties": {
        "Instance" : {
            "Plugin": "instance-vagrant",
            "Properties": {
                "Box": "bento/ubuntu-16.04"
            }
        },
        "Flavor" : {
            "Plugin": "flavor-zookeeper",
            "Properties": {
                "type": "member",
                "IPs": ["192.168.1.200", "192.168.1.201", "192.168.1.202"]
            }
        }
    }
}
/tmp$ 

Under the top level directory infrakit, a groups directory indicates that all members of this folder are configurations for plugins that conform to spi.Group. In each subdirectory under groups such as managers, there is a file config.json, which is the group config JSON as they are currently defined. Note it's possible to nest folders that are appropriate for the plugin -- e.g. the terraform_files directory for config files used by the Terraform plugin.

At the moment, we assume there are no dependencies. Each group / folder is independent on one of another.

Removing (unwatch) a group (see Group plugin api) is as simple as moving a directory into the .trash folder under groups. For example, unwatching the workers-small group looks like

/tmp$ mv infrakit/groups/workers-small infrakit/groups/.trash/
/tmp$ tree -a infrakit/
infrakit/
└── groups
    ├── .trash
    │   └── workers-small
    │       └── config.json
    ├── managers
    │   └── config.json
    ├── workers-db
    │   ├── config.json
    │   └── terraform_files
    │       ├── main.tf
    │       └── variables.tf
    ├── workers-large
    │   └── config.json
    └── zookeeper
        └── config.json

8 directories, 7 files

Alternatively, when integrated with backends that have full revision history, such as git, the removal of a group can be determined from change log.

UX

Given the directory structure above, the UX / workflow is as follows:

  1. Create or edit a JSON config, add new folders as necessary. Or move folders to .trash for unwatch.
  2. At the command line, do
$infrakit commit ./infrakit   # assumes infrakit is the name of the top level directory.

This command invocation will tell the frontend to start traversing the directories and depending on the state of the config files (new or edits), call the group plugins watch or update endpoints accordingly. The commit can also be tied to a commit trigger for a VCS (e.g. git).

Plugin Activation

As part of processing this hierarchy of files, the frontend will activate the plugin if it's not already running. This will relieve the user from having to start the plugins manually.

We may implement pruning (deactivating) plugins if they are no longer referenced / needed in the configs. That's for a later phase.

Other Concerns

wfarner commented 7 years ago

The proposal above leaves me unclear on the UX problem being addressed. I was anticipating that this effort would focus on relieving the user of managing startup of plugins for their configs. If i'm reading correctly, this seems to be more of a configuration management effort.

I find the config approach described above more cumbersome than the single JSON document we use today. The single document stands on its own, is atomically shareable, and it is easy to see in one place how the pieces fit together. I'm not seeing benefits of splitting it up that outweigh the added complexity of interacting with the system.

chungers commented 7 years ago

Addressed the point on automating plugin activation. It's implicit but was not called out explicitly in the doc.

I don't think this is any more cumbersome than a single JSON document. A single JSON document is not significantly more shareable than a tarball of the entire directory.

Are there specific examples of 'added complexities' you are referring to?

chungers commented 7 years ago

Updated the doc to make clear that a config.json is the whole config, as seen in the documentation of the plugins. I am not proposing to split up fields or chunks within a logical, atomic config into separate files.

wfarner commented 7 years ago

Are there specific examples of 'added complexities' you are referring to?

I gave myself the impression that config files were splitting apart each plugin configuration into separate files. The fact that configs are 1:1 with Groups alleviates a bunch of my concern.

Other than that, I find the implicit side-effects of changing files to be surprising and difficult to work with (e.g. move to .trash directory has side-effects, sounds like you may have more similar side-effects in mind).

The biggest benefit i can see is storing auxiliary files next to the relevant configuration, but my hunch is that is not big enough of a problem to be engineered away.

chungers commented 7 years ago

A PR #283 is a start to address this. The manager should be the entity that handles this, in terms of roles and responsibility.

chungers commented 7 years ago

PR #283 is merged -- this is the start of a single frontend. Note its data model at manager/spec.go has the notions of multiple groups.