{"action":"created","issue":{"url":"https://api.github.com/repos/joyent/containerpilot/issues/128","repository_url":"https://api.github.com/repos/joyent/containerpilot","labels_url":"https://api.github.com/repos/joyent/containerpilot/issues/128/labels{/name}","comments_url":"https://api.github.com/repos/joyent/containerpilot/issues/128/comments","events_url":"https://api.github.com/repos/joyent/containerpilot/issues/128/events","html_url":"https://github.com/joyent/containerpilot/issues/128","id":147777077,"number":128,"title":"Split application state from config struct","user":{"login":"tgross","id":1409219,"avatar_url":"https://avatars.githubusercontent.com/u/1409219?v=3","gravatar_id":"","url":"https://api.github.com/users/tgross","html_url":"https://github.com/tgross","followers_url":"https://api.github.com/users/tgross/followers","following_url":"https://api.github.com/users/tgross/following{/other_user}","gists_url":"https://api.github.com/users/tgross/gists{/gist_id}","starred_url":"https://api.github.com/users/tgross/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tgross/subscriptions","organizations_url":"https://api.github.com/users/tgross/orgs","repos_url":"https://api.github.com/users/tgross/repos","events_url":"https://api.github.com/users/tgross/events{/privacy}","received_events_url":"https://api.github.com/users/tgross/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/joyent/containerpilot/labels/awaiting%20release","name":"awaiting release","color":"447394"},{"url":"https://api.github.com/repos/joyent/containerpilot/labels/enhancement","name":"enhancement","color":"71b8c7"}],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2016-04-12T14:53:05Z","updated_at":"2016-05-09T12:53:01Z","closed_at":"2016-05-09T12:53:01Z","body":"@justenwalker proposed the following in #123 and I want to make sure we come back to it as a future refactoring.\r\n\r\n---\r\n\r\nI can see how this would be painful.  I still think we are complicating the idea of external configuration (ie from a file) with our application state (internal configuration) - I believe the fact that the structures are very similar is incidental.\r\n\r\nPerhaps this isn't the time to undertake such a refactor, but does the idea of separating these concepts from each other seem like a good goal? Maybe we can create another issue for that. \r\n\r\n\r\nHere are some of my thoughts:\r\n\r\ninstead of\r\n\r\n```go\r\n// Config is the top-level Containerbuddy Configuration\r\ntype Config struct {\r\n\tConsul       string                    `json:\"consul,omitempty\"`\r\n\tEtcd         json.RawMessage           `json:\"etcd,omitempty\"`\r\n\tLogConfig    *LogConfig                `json:\"logging,omitempty\"`\r\n\tOnStart      json.RawMessage           `json:\"onStart,omitempty\"`\r\n\tPreStart     json.RawMessage           `json:\"preStart,omitempty\"`\r\n\tPreStop      json.RawMessage           `json:\"preStop,omitempty\"`\r\n\tPostStop     json.RawMessage           `json:\"postStop,omitempty\"`\r\n\tStopTimeout  int                       `json:\"stopTimeout\"`\r\n\tServices     []*services.ServiceConfig `json:\"services\"`\r\n\tBackends     []*backends.BackendConfig `json:\"backends\"`\r\n\tPreStartCmd  *exec.Cmd\r\n\tPreStopCmd   *exec.Cmd\r\n\tPostStopCmd  *exec.Cmd\r\n\tCommand      *exec.Cmd\r\n\tQuitChannels []chan bool\r\n\tConfigFlag   string\r\n}\r\n```\r\n\r\nsomething like\r\n\r\n```go\r\ntype ApplicationState struct {\r\n\tPreStartCmd  *exec.Cmd\r\n\tPreStopCmd   *exec.Cmd\r\n\tPostStopCmd  *exec.Cmd\r\n\tCommand      *exec.Cmd\r\n\tQuitChannels []chan bool\r\n\tBackends []backends.Backend\r\n\tService  []services.Service\r\n\tConfigFlag   string\r\n}\r\n```\r\n\r\nInside `loadConfig` some logic happens to parse the map[string]interface{} into several config structs\r\nwhich will be passed as arguments to the `NewX` functions in packages which are responsible for converting them to the appropriate interfaces ([github.com/mitchellh/mapstructure](https://github.com/mitchellh/mapstructure) might help). Those config structs live in the package itself.  \r\n\r\nFor instance, after loading up the `var backendConfig backends.BackendConfig` we get `backend := backends.NewBackend(backendConfig)` which is put into the `ApplicationState` struct\r\n\r\nMore concrete steps:\r\n\r\n- `loadConfig(config map[string]interface{})` will be a pure function which takes a raw config and produces a `ApplicationState` \r\n- We store it as the `currentState` \r\n- Then it is `Run()`\r\n- Later, the application might want to `reloadConfig()` which:\r\n  - `config := loadConfigMap()`\r\n  - `newState := loadConfig(config)`\r\n  - `currentState.Stop()` \r\n  - `currentState := newState`\r\n   - `currentState.Run()`\r\n\r\n\r\n-- \r\n\r\nIn retrospect I realize I oversimplified, this does not account for the fact that we don't re-run the shimmed application and preStart commands but it is part of the ApplicationState."},"comment":{"url":"https://api.github.com/repos/joyent/containerpilot/issues/comments/217855799","html_url":"https://github.com/joyent/containerpilot/issues/128#issuecomment-217855799","issue_url":"https://api.github.com/repos/joyent/containerpilot/issues/128","id":217855799,"user":{"login":"tgross","id":1409219,"avatar_url":"https://avatars.githubusercontent.com/u/1409219?v=3","gravatar_id":"","url":"https://api.github.com/users/tgross","html_url":"https://github.com/tgross","followers_url":"https://api.github.com/users/tgross/followers","following_url":"https://api.github.com/users/tgross/following{/other_user}","gists_url":"https://api.github.com/users/tgross/gists{/gist_id}","starred_url":"https://api.github.com/users/tgross/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/tgross/subscriptions","organizations_url":"https://api.github.com/users/tgross/orgs","repos_url":"https://api.github.com/users/tgross/repos","events_url":"https://api.github.com/users/tgross/events{/privacy}","received_events_url":"https://api.github.com/users/tgross/received_events","type":"User","site_admin":false},"created_at":"2016-05-09T12:53:01Z","updated_at":"2016-05-09T12:53:01Z","body":"Released in https://github.com/joyent/containerpilot/releases/tag/2.1.1"}}