{"action":"created","issue":{"url":"https://api.github.com/repos/habitat-sh/habitat/issues/2902","repository_url":"https://api.github.com/repos/habitat-sh/habitat","labels_url":"https://api.github.com/repos/habitat-sh/habitat/issues/2902/labels{/name}","comments_url":"https://api.github.com/repos/habitat-sh/habitat/issues/2902/comments","events_url":"https://api.github.com/repos/habitat-sh/habitat/issues/2902/events","html_url":"https://github.com/habitat-sh/habitat/issues/2902","id":249202041,"number":2902,"title":"Composite Plan/Package/Service","user":{"login":"reset","id":54036,"avatar_url":"https://avatars1.githubusercontent.com/u/54036?v=4","gravatar_id":"","url":"https://api.github.com/users/reset","html_url":"https://github.com/reset","followers_url":"https://api.github.com/users/reset/followers","following_url":"https://api.github.com/users/reset/following{/other_user}","gists_url":"https://api.github.com/users/reset/gists{/gist_id}","starred_url":"https://api.github.com/users/reset/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/reset/subscriptions","organizations_url":"https://api.github.com/users/reset/orgs","repos_url":"https://api.github.com/users/reset/repos","events_url":"https://api.github.com/users/reset/events{/privacy}","received_events_url":"https://api.github.com/users/reset/received_events","type":"User","site_admin":false},"labels":[{"id":621115488,"url":"https://api.github.com/repos/habitat-sh/habitat/labels/A-plan-build","name":"A-plan-build","color":"87B09A","default":false},{"id":621112519,"url":"https://api.github.com/repos/habitat-sh/habitat/labels/A-supervisor","name":"A-supervisor","color":"87B09A","default":false},{"id":621115721,"url":"https://api.github.com/repos/habitat-sh/habitat/labels/C-feature","name":"C-feature","color":"ff9012","default":false},{"id":621119785,"url":"https://api.github.com/repos/habitat-sh/habitat/labels/L-rust","name":"L-rust","color":"5c6670","default":false}],"state":"open","locked":false,"assignee":{"login":"christophermaier","id":207178,"avatar_url":"https://avatars2.githubusercontent.com/u/207178?v=4","gravatar_id":"","url":"https://api.github.com/users/christophermaier","html_url":"https://github.com/christophermaier","followers_url":"https://api.github.com/users/christophermaier/followers","following_url":"https://api.github.com/users/christophermaier/following{/other_user}","gists_url":"https://api.github.com/users/christophermaier/gists{/gist_id}","starred_url":"https://api.github.com/users/christophermaier/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/christophermaier/subscriptions","organizations_url":"https://api.github.com/users/christophermaier/orgs","repos_url":"https://api.github.com/users/christophermaier/repos","events_url":"https://api.github.com/users/christophermaier/events{/privacy}","received_events_url":"https://api.github.com/users/christophermaier/received_events","type":"User","site_admin":false},"assignees":[{"login":"christophermaier","id":207178,"avatar_url":"https://avatars2.githubusercontent.com/u/207178?v=4","gravatar_id":"","url":"https://api.github.com/users/christophermaier","html_url":"https://github.com/christophermaier","followers_url":"https://api.github.com/users/christophermaier/followers","following_url":"https://api.github.com/users/christophermaier/following{/other_user}","gists_url":"https://api.github.com/users/christophermaier/gists{/gist_id}","starred_url":"https://api.github.com/users/christophermaier/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/christophermaier/subscriptions","organizations_url":"https://api.github.com/users/christophermaier/orgs","repos_url":"https://api.github.com/users/christophermaier/repos","events_url":"https://api.github.com/users/christophermaier/events{/privacy}","received_events_url":"https://api.github.com/users/christophermaier/received_events","type":"User","site_admin":false}],"milestone":null,"comments":15,"created_at":"2017-08-10T00:47:47Z","updated_at":"2017-08-14T16:42:26Z","closed_at":null,"body":"## User Story\r\n\r\nAs a plan author, I need a way to represent a service which is made up of one or more processes, so I can interact with a collection of services in the same Supervisor as one\r\n\r\n## Background\r\n\r\nWe currently have one kind of plan which is represented by a `plan.sh` or a `plan.ps1`. A plan outputs a package which, when installed, can be started by a Supervisor to start a service. It can be said that a plan/package is a 1:1 mapping to a service.\r\n\r\nSome services require another to run and we need a way to represent this \"sidecar\" pattern. An example of this is an API server and an API proxy.\r\n\r\n## Changes to Plan-Build\r\n\r\nWe need a way to represent that the plan is a composite plan. We could do this in a few different ways such as:\r\n\r\n* Add a new key/value setting which plan-build reads such as `pkg_composite = true`\r\n* Use a different filename than `plan.sh` such as `composite-plan.sh`\r\n\r\nWe also do not need to allow any additional artifacts aside from the `plan.sh` in a composite plan. There's no need for the additional artifacts - read on for details.\r\n\r\n### Promise Mapping\r\n\r\nOnce we've indicated that we're building a composite plan we also need a way to configure some mappings for any promises that the package exposes (aka, `exports`/`binds`). We also need a way to note that an export of a service of the composite plan satisfies a bind of another. For example, `builder-api` needs to satisfy the bind for `builder-api-proxy`.\r\n\r\nWe need to verify that there are no collisions in the key space of exports or binds. If one package in the composite exports `hello` and a second also does, we will need to fail the build (and should fail before any work is done)\r\n\r\nWe will want to record this in a new METADATA file indicating:\r\n\r\n* That this is a composite package\r\n* What the promise mappings are\r\n* Which promise mappings self satisfy service members\r\n\r\n## Changes to Hab CLI\r\n\r\nAll operations with the CLI should be atomic across all service members of the composite package/service. For example: installing a composite package should install all packages it points to. Another way to think about a composite package is as a \"pointer package\" (sometimes referred to in other systems as a virtual package).\r\n\r\nWe may want to consider representing a composite service in the status output of running services as something like:\r\n\r\n```\r\n$ hab svc status\r\ncore/builder-api/4567/20170727171959, state:up, time:PT1.870780743S, pid:9199, group:builder-api.acceptance, style:persistent\r\n  - core/builder-api-srv/4567/20170727171959\r\n  - core/builder-api-proxy/4355/20170706225642\r\n```\r\n\r\nAll `hab pkg` and `hab svc` commands should be refreshed to support these changes\r\n\r\n### Config Apply\r\n\r\nSince we want a composite service to be addressable as a service group itself, we will also need  to make some alterations to `hab config apply`.\r\n\r\nCurrently we run `hab config apply <SERVICE_GROUP> <VERSION_NUMER> [file]` which takes a toml file representing a single service's configuration. We should allow the toml file to be split into multiple sections, one for each service in the composite service:\r\n\r\n```toml\r\n[builder-api-srv]\r\n  [http]\r\n  listen = \"0.0.0.0\"\r\n  port = 9636\r\n[builder-api-proxy]\r\n  worker_rlimit_nofile = 8192\r\n  worker_processes = \"auto\"\r\n\r\n  [events]\r\n  worker_connections = 8000\r\n```\r\n\r\n## Changes to Butterfly / Supervisor\r\n\r\nWith all of the above changes we may also need to add a new rumor type, `CompositeServiceRumor`, which contains the metadata for promise mappings.\r\n\r\nThe config apply changes described above may also result in the need for us to generate a new type of rumor for `CompositeServiceConfigRumor`. This would contain the combined configuration. If we decide to go this route, we will need to make sure that we reject config changes to the individual service groups which make up the composite service group - contains a combined \r\n\r\nLastly, we should not generate a service directory at `/hab/svc/{name}` for a composite service."},"comment":{"url":"https://api.github.com/repos/habitat-sh/habitat/issues/comments/322242217","html_url":"https://github.com/habitat-sh/habitat/issues/2902#issuecomment-322242217","issue_url":"https://api.github.com/repos/habitat-sh/habitat/issues/2902","id":322242217,"user":{"login":"eeyun","id":12615148,"avatar_url":"https://avatars1.githubusercontent.com/u/12615148?v=4","gravatar_id":"","url":"https://api.github.com/users/eeyun","html_url":"https://github.com/eeyun","followers_url":"https://api.github.com/users/eeyun/followers","following_url":"https://api.github.com/users/eeyun/following{/other_user}","gists_url":"https://api.github.com/users/eeyun/gists{/gist_id}","starred_url":"https://api.github.com/users/eeyun/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eeyun/subscriptions","organizations_url":"https://api.github.com/users/eeyun/orgs","repos_url":"https://api.github.com/users/eeyun/repos","events_url":"https://api.github.com/users/eeyun/events{/privacy}","received_events_url":"https://api.github.com/users/eeyun/received_events","type":"User","site_admin":false},"created_at":"2017-08-14T16:42:25Z","updated_at":"2017-08-14T16:42:25Z","body":"Thats what I figured @reset. I guess from my perspective just the DB example is a little misleading if only because lots of times having a DB connection is trivial to orchestrate and they aren't usually to hard to manage with the current habitat behaviors. Those paired services with web-server+static content, or service + supporting service are harder to compose currently."}}
{"actor":{"display_login":"eeyun"}}