{"id":13398884,"url":"https://github.com/stitchfix/flotilla-os","last_synced_at":"2025-03-17T15:13:05.883Z","repository":{"id":22476033,"uuid":"96358156","full_name":"stitchfix/flotilla-os","owner":"stitchfix","description":"Open source Flotilla","archived":false,"fork":false,"pushed_at":"2024-07-17T18:25:58.000Z","size":2671,"stargazers_count":192,"open_issues_count":27,"forks_count":10,"subscribers_count":78,"default_branch":"master","last_synced_at":"2024-07-31T19:17:16.784Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stitchfix.png","metadata":{"files":{"readme":"README.html","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-07-05T20:22:42.000Z","updated_at":"2024-07-17T18:26:03.000Z","dependencies_parsed_at":"2023-09-21T21:57:32.768Z","dependency_job_id":"2cd31606-d64d-44e3-a153-bde339d5e8c8","html_url":"https://github.com/stitchfix/flotilla-os","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stitchfix%2Fflotilla-os","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stitchfix%2Fflotilla-os/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stitchfix%2Fflotilla-os/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stitchfix%2Fflotilla-os/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stitchfix","download_url":"https://codeload.github.com/stitchfix/flotilla-os/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244056425,"owners_count":20390719,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T19:00:32.447Z","updated_at":"2025-03-17T15:13:05.862Z","avatar_url":"https://github.com/stitchfix.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"\u003c!DOCTYPE html\u003e\u003chtml\u003e\u003chead\u003e\u003cmeta charset=\"utf-8\"\u003e\u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\"\u003e\u003cstyle\u003ebody {\n  max-width: 980px;\n  border: 1px solid #ddd;\n  outline: 1300px solid #fff;\n  margin: 16px auto;\n}\n\nbody .markdown-body\n{\n  padding: 45px;\n}\n\n@font-face {\n  font-family: fontawesome-mini;\n  src: url(data:font/woff;charset=utf-8;base64,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) format('woff');\n}\n\n.markdown-body {\n  font-family: sans-serif;\n  -ms-text-size-adjust: 100%;\n  -webkit-text-size-adjust: 100%;\n  color: #333333;\n  overflow: hidden;\n  font-family: \"Helvetica Neue\", Helvetica, \"Segoe UI\", Arial, freesans, sans-serif;\n  font-size: 16px;\n  line-height: 1.6;\n  word-wrap: break-word;\n}\n\n.markdown-body a {\n  background: transparent;\n}\n\n.markdown-body a:active,\n.markdown-body a:hover {\n  outline: 0;\n}\n\n.markdown-body b,\n.markdown-body strong {\n  font-weight: bold;\n}\n\n.markdown-body mark {\n  background: #ff0;\n  color: #000;\n  font-style: italic;\n  font-weight: bold;\n}\n\n.markdown-body sub,\n.markdown-body sup {\n  font-size: 75%;\n  line-height: 0;\n  position: relative;\n  vertical-align: baseline;\n}\n.markdown-body sup {\n  top: -0.5em;\n}\n.markdown-body sub {\n  bottom: -0.25em;\n}\n\n.markdown-body h1 {\n  font-size: 2em;\n  margin: 0.67em 0;\n}\n\n.markdown-body img {\n  border: 0;\n}\n\n.markdown-body hr {\n  -moz-box-sizing: content-box;\n  box-sizing: content-box;\n  height: 0;\n}\n\n.markdown-body pre {\n  overflow: auto;\n}\n\n.markdown-body code,\n.markdown-body kbd,\n.markdown-body pre,\n.markdown-body samp {\n  font-family: monospace, monospace;\n  font-size: 1em;\n}\n\n.markdown-body input {\n  color: inherit;\n  font: inherit;\n  margin: 0;\n}\n\n.markdown-body html input[disabled] {\n  cursor: default;\n}\n\n.markdown-body input {\n  line-height: normal;\n}\n\n.markdown-body input[type=\"checkbox\"] {\n  box-sizing: border-box;\n  padding: 0;\n}\n\n.markdown-body table {\n  border-collapse: collapse;\n  border-spacing: 0;\n}\n\n.markdown-body td,\n.markdown-body th {\n  padding: 0;\n}\n\n.markdown-body .codehilitetable {\n  border: 0;\n  border-spacing: 0;\n}\n\n.markdown-body .codehilitetable tr {\n  border: 0;\n}\n\n.markdown-body .codehilitetable pre,\n.markdown-body .codehilitetable div.codehilite {\n  margin: 0;\n}\n\n.markdown-body .linenos,\n.markdown-body .code,\n.markdown-body .codehilitetable td {\n  border: 0;\n  padding: 0;\n}\n\n.markdown-body td:not(.linenos) .linenodiv {\n  padding: 0 !important;\n}\n\n.markdown-body .code {\n  width: 100%;\n}\n\n.markdown-body .linenos div pre,\n.markdown-body .linenodiv pre,\n.markdown-body .linenodiv {\n  border: 0;\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n  -webkit-border-top-left-radius: 3px;\n  -webkit-border-bottom-left-radius: 3px;\n  -moz-border-radius-topleft: 3px;\n  -moz-border-radius-bottomleft: 3px;\n  border-top-left-radius: 3px;\n  border-bottom-left-radius: 3px;\n}\n\n.markdown-body .code div pre,\n.markdown-body .code div {\n  border: 0;\n  -webkit-border-radius: 0;\n  -moz-border-radius: 0;\n  border-radius: 0;\n  -webkit-border-top-right-radius: 3px;\n  -webkit-border-bottom-right-radius: 3px;\n  -moz-border-radius-topright: 3px;\n  -moz-border-radius-bottomright: 3px;\n  border-top-right-radius: 3px;\n  border-bottom-right-radius: 3px;\n}\n\n.markdown-body * {\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n\n.markdown-body input {\n  font: 13px Helvetica, arial, freesans, clean, sans-serif, \"Segoe UI Emoji\", \"Segoe UI Symbol\";\n  line-height: 1.4;\n}\n\n.markdown-body a {\n  color: #4183c4;\n  text-decoration: none;\n}\n\n.markdown-body a:hover,\n.markdown-body a:focus,\n.markdown-body a:active {\n  text-decoration: underline;\n}\n\n.markdown-body hr {\n  height: 0;\n  margin: 15px 0;\n  overflow: hidden;\n  background: transparent;\n  border: 0;\n  border-bottom: 1px solid #ddd;\n}\n\n.markdown-body hr:before,\n.markdown-body hr:after {\n  display: table;\n  content: \" \";\n}\n\n.markdown-body hr:after {\n  clear: both;\n}\n\n.markdown-body h1,\n.markdown-body h2,\n.markdown-body h3,\n.markdown-body h4,\n.markdown-body h5,\n.markdown-body h6 {\n  margin-top: 15px;\n  margin-bottom: 15px;\n  line-height: 1.1;\n}\n\n.markdown-body h1 {\n  font-size: 30px;\n}\n\n.markdown-body h2 {\n  font-size: 21px;\n}\n\n.markdown-body h3 {\n  font-size: 16px;\n}\n\n.markdown-body h4 {\n  font-size: 14px;\n}\n\n.markdown-body h5 {\n  font-size: 12px;\n}\n\n.markdown-body h6 {\n  font-size: 11px;\n}\n\n.markdown-body blockquote {\n  margin: 0;\n}\n\n.markdown-body ul,\n.markdown-body ol {\n  padding: 0;\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\n.markdown-body ol ol,\n.markdown-body ul ol {\n  list-style-type: lower-roman;\n}\n\n.markdown-body ul ul ol,\n.markdown-body ul ol ol,\n.markdown-body ol ul ol,\n.markdown-body ol ol ol {\n  list-style-type: lower-alpha;\n}\n\n.markdown-body dd {\n  margin-left: 0;\n}\n\n.markdown-body code,\n.markdown-body pre,\n.markdown-body samp {\n  font-family: Consolas, \"Liberation Mono\", Menlo, Courier, monospace;\n  font-size: 12px;\n}\n\n.markdown-body pre {\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\n.markdown-body kbd {\n  background-color: #e7e7e7;\n  background-image: -moz-linear-gradient(#fefefe, #e7e7e7);\n  background-image: -webkit-linear-gradient(#fefefe, #e7e7e7);\n  background-image: linear-gradient(#fefefe, #e7e7e7);\n  background-repeat: repeat-x;\n  border-radius: 2px;\n  border: 1px solid #cfcfcf;\n  color: #000;\n  padding: 3px 5px;\n  line-height: 10px;\n  font: 11px Consolas, \"Liberation Mono\", Menlo, Courier, monospace;\n  display: inline-block;\n}\n\n.markdown-body\u003e*:first-child {\n  margin-top: 0 !important;\n}\n\n.markdown-body\u003e*:last-child {\n  margin-bottom: 0 !important;\n}\n\n.markdown-body .headerlink {\n  font: normal 400 16px fontawesome-mini;\n  vertical-align: middle;\n  margin-left: -16px;\n  float: left;\n  display: inline-block;\n  text-decoration: none;\n  opacity: 0;\n  color: #333;\n}\n\n.markdown-body .headerlink:focus {\n  outline: none;\n}\n\n.markdown-body h1 .headerlink {\n  margin-top: 0.8rem;\n}\n\n.markdown-body h2 .headerlink,\n.markdown-body h3 .headerlink {\n  margin-top: 0.6rem;\n}\n\n.markdown-body h4 .headerlink {\n  margin-top: 0.2rem;\n}\n\n.markdown-body h5 .headerlink,\n.markdown-body h6 .headerlink {\n  margin-top: 0;\n}\n\n.markdown-body .headerlink:hover,\n.markdown-body h1:hover .headerlink,\n.markdown-body h2:hover .headerlink,\n.markdown-body h3:hover .headerlink,\n.markdown-body h4:hover .headerlink,\n.markdown-body h5:hover .headerlink,\n.markdown-body h6:hover .headerlink {\n  opacity: 1;\n  text-decoration: none;\n}\n\n.markdown-body h1 {\n  padding-bottom: 0.3em;\n  font-size: 2.25em;\n  line-height: 1.2;\n  border-bottom: 1px solid #eee;\n}\n\n.markdown-body h2 {\n  padding-bottom: 0.3em;\n  font-size: 1.75em;\n  line-height: 1.225;\n  border-bottom: 1px solid #eee;\n}\n\n.markdown-body h3 {\n  font-size: 1.5em;\n  line-height: 1.43;\n}\n\n.markdown-body h4 {\n  font-size: 1.25em;\n}\n\n.markdown-body h5 {\n  font-size: 1em;\n}\n\n.markdown-body h6 {\n  font-size: 1em;\n  color: #777;\n}\n\n.markdown-body p,\n.markdown-body blockquote,\n.markdown-body ul,\n.markdown-body ol,\n.markdown-body dl,\n.markdown-body table,\n.markdown-body pre,\n.markdown-body .admonition {\n  margin-top: 0;\n  margin-bottom: 16px;\n}\n\n.markdown-body hr {\n  height: 4px;\n  padding: 0;\n  margin: 16px 0;\n  background-color: #e7e7e7;\n  border: 0 none;\n}\n\n.markdown-body ul,\n.markdown-body ol {\n  padding-left: 2em;\n}\n\n.markdown-body ul ul,\n.markdown-body ul ol,\n.markdown-body ol ol,\n.markdown-body ol ul {\n  margin-top: 0;\n  margin-bottom: 0;\n}\n\n.markdown-body li\u003ep {\n  margin-top: 16px;\n}\n\n.markdown-body dl {\n  padding: 0;\n}\n\n.markdown-body dl dt {\n  padding: 0;\n  margin-top: 16px;\n  font-size: 1em;\n  font-style: italic;\n  font-weight: bold;\n}\n\n.markdown-body dl dd {\n  padding: 0 16px;\n  margin-bottom: 16px;\n}\n\n.markdown-body blockquote {\n  padding: 0 15px;\n  color: #777;\n  border-left: 4px solid #ddd;\n}\n\n.markdown-body blockquote\u003e:first-child {\n  margin-top: 0;\n}\n\n.markdown-body blockquote\u003e:last-child {\n  margin-bottom: 0;\n}\n\n.markdown-body table {\n  display: block;\n  width: 100%;\n  overflow: auto;\n  word-break: normal;\n  word-break: keep-all;\n}\n\n.markdown-body table th {\n  font-weight: bold;\n}\n\n.markdown-body table th,\n.markdown-body table td {\n  padding: 6px 13px;\n  border: 1px solid #ddd;\n}\n\n.markdown-body table tr {\n  background-color: #fff;\n  border-top: 1px solid #ccc;\n}\n\n.markdown-body table tr:nth-child(2n) {\n  background-color: #f8f8f8;\n}\n\n.markdown-body img {\n  max-width: 100%;\n  -moz-box-sizing: border-box;\n  box-sizing: border-box;\n}\n\n.markdown-body code,\n.markdown-body samp {\n  padding: 0;\n  padding-top: 0.2em;\n  padding-bottom: 0.2em;\n  margin: 0;\n  font-size: 85%;\n  background-color: rgba(0,0,0,0.04);\n  border-radius: 3px;\n}\n\n.markdown-body code:before,\n.markdown-body code:after {\n  letter-spacing: -0.2em;\n  content: \"\\00a0\";\n}\n\n.markdown-body pre\u003ecode {\n  padding: 0;\n  margin: 0;\n  font-size: 100%;\n  word-break: normal;\n  white-space: pre;\n  background: transparent;\n  border: 0;\n}\n\n.markdown-body .codehilite {\n  margin-bottom: 16px;\n}\n\n.markdown-body .codehilite pre,\n.markdown-body pre {\n  padding: 16px;\n  overflow: auto;\n  font-size: 85%;\n  line-height: 1.45;\n  background-color: #f7f7f7;\n  border-radius: 3px;\n}\n\n.markdown-body .codehilite pre {\n  margin-bottom: 0;\n  word-break: normal;\n}\n\n.markdown-body pre {\n  word-wrap: normal;\n}\n\n.markdown-body pre code {\n  display: inline;\n  max-width: initial;\n  padding: 0;\n  margin: 0;\n  overflow: initial;\n  line-height: inherit;\n  word-wrap: normal;\n  background-color: transparent;\n  border: 0;\n}\n\n.markdown-body pre code:before,\n.markdown-body pre code:after {\n  content: normal;\n}\n\n/* Admonition */\n.markdown-body .admonition {\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  position: relative;\n  border-radius: 3px;\n  border: 1px solid #e0e0e0;\n  border-left: 6px solid #333;\n  padding: 10px 10px 10px 30px;\n}\n\n.markdown-body .admonition table {\n  color: #333;\n}\n\n.markdown-body .admonition p {\n  padding: 0;\n}\n\n.markdown-body .admonition-title {\n  font-weight: bold;\n  margin: 0;\n}\n\n.markdown-body .admonition\u003e.admonition-title {\n  color: #333;\n}\n\n.markdown-body .attention\u003e.admonition-title {\n  color: #a6d796;\n}\n\n.markdown-body .caution\u003e.admonition-title {\n  color: #d7a796;\n}\n\n.markdown-body .hint\u003e.admonition-title {\n  color: #96c6d7;\n}\n\n.markdown-body .danger\u003e.admonition-title {\n  color: #c25f77;\n}\n\n.markdown-body .question\u003e.admonition-title {\n  color: #96a6d7;\n}\n\n.markdown-body .note\u003e.admonition-title {\n  color: #d7c896;\n}\n\n.markdown-body .admonition:before,\n.markdown-body .attention:before,\n.markdown-body .caution:before,\n.markdown-body .hint:before,\n.markdown-body .danger:before,\n.markdown-body .question:before,\n.markdown-body .note:before {\n  font: normal normal 16px fontawesome-mini;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n  line-height: 1.5;\n  color: #333;\n  position: absolute;\n  left: 0;\n  top: 0;\n  padding-top: 10px;\n  padding-left: 10px;\n}\n\n.markdown-body .admonition:before {\n  content: \"\\f056\\00a0\";\n  color: 333;\n}\n\n.markdown-body .attention:before {\n  content: \"\\f058\\00a0\";\n  color: #a6d796;\n}\n\n.markdown-body .caution:before {\n  content: \"\\f06a\\00a0\";\n  color: #d7a796;\n}\n\n.markdown-body .hint:before {\n  content: \"\\f05a\\00a0\";\n  color: #96c6d7;\n}\n\n.markdown-body .danger:before {\n  content: \"\\f057\\00a0\";\n  color: #c25f77;\n}\n\n.markdown-body .question:before {\n  content: \"\\f059\\00a0\";\n  color: #96a6d7;\n}\n\n.markdown-body .note:before {\n  content: \"\\f040\\00a0\";\n  color: #d7c896;\n}\n\n.markdown-body .admonition::after {\n  content: normal;\n}\n\n.markdown-body .attention {\n  border-left: 6px solid #a6d796;\n}\n\n.markdown-body .caution {\n  border-left: 6px solid #d7a796;\n}\n\n.markdown-body .hint {\n  border-left: 6px solid #96c6d7;\n}\n\n.markdown-body .danger {\n  border-left: 6px solid #c25f77;\n}\n\n.markdown-body .question {\n  border-left: 6px solid #96a6d7;\n}\n\n.markdown-body .note {\n  border-left: 6px solid #d7c896;\n}\n\n.markdown-body .admonition\u003e*:first-child {\n  margin-top: 0 !important;\n}\n\n.markdown-body .admonition\u003e*:last-child {\n  margin-bottom: 0 !important;\n}\n\n/* progress bar*/\n.markdown-body .progress {\n  display: block;\n  width: 300px;\n  margin: 10px 0;\n  height: 24px;\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  border-radius: 3px;\n  background-color: #ededed;\n  position: relative;\n  box-shadow: inset -1px 1px 3px rgba(0, 0, 0, .1);\n}\n\n.markdown-body .progress-label {\n  position: absolute;\n  text-align: center;\n  font-weight: bold;\n  width: 100%; margin: 0;\n  line-height: 24px;\n  color: #333;\n  text-shadow: 1px 1px 0 #fefefe, -1px -1px 0 #fefefe, -1px 1px 0 #fefefe, 1px -1px 0 #fefefe, 0 1px 0 #fefefe, 0 -1px 0 #fefefe, 1px 0 0 #fefefe, -1px 0 0 #fefefe, 1px 1px 2px #000;\n  -webkit-font-smoothing: antialiased !important;\n  white-space: nowrap;\n  overflow: hidden;\n}\n\n.markdown-body .progress-bar {\n  height: 24px;\n  float: left;\n  -webkit-border-radius: 3px;\n  -moz-border-radius: 3px;\n  border-radius: 3px;\n  background-color: #96c6d7;\n  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .5), inset 0 -1px 0 rgba(0, 0, 0, .1);\n  background-size: 30px 30px;\n  background-image: -webkit-linear-gradient(\n    135deg, rgba(255, 255, 255, .4) 27%,\n    transparent 27%,\n    transparent 52%, rgba(255, 255, 255, .4) 52%,\n    rgba(255, 255, 255, .4) 77%,\n    transparent 77%, transparent\n  );\n  background-image: -moz-linear-gradient(\n    135deg,\n    rgba(255, 255, 255, .4) 27%, transparent 27%,\n    transparent 52%, rgba(255, 255, 255, .4) 52%,\n    rgba(255, 255, 255, .4) 77%, transparent 77%,\n    transparent\n  );\n  background-image: -ms-linear-gradient(\n    135deg,\n    rgba(255, 255, 255, .4) 27%, transparent 27%,\n    transparent 52%, rgba(255, 255, 255, .4) 52%,\n    rgba(255, 255, 255, .4) 77%, transparent 77%,\n    transparent\n  );\n  background-image: -o-linear-gradient(\n    135deg,\n    rgba(255, 255, 255, .4) 27%, transparent 27%,\n    transparent 52%, rgba(255, 255, 255, .4) 52%,\n    rgba(255, 255, 255, .4) 77%, transparent 77%,\n    transparent\n  );\n  background-image: linear-gradient(\n    135deg,\n    rgba(255, 255, 255, .4) 27%, transparent 27%,\n    transparent 52%, rgba(255, 255, 255, .4) 52%,\n    rgba(255, 255, 255, .4) 77%, transparent 77%,\n    transparent\n  );\n}\n\n.markdown-body .progress-100plus .progress-bar {\n  background-color: #a6d796;\n}\n\n.markdown-body .progress-80plus .progress-bar {\n  background-color: #c6d796;\n}\n\n.markdown-body .progress-60plus .progress-bar {\n  background-color: #d7c896;\n}\n\n.markdown-body .progress-40plus .progress-bar {\n  background-color: #d7a796;\n}\n\n.markdown-body .progress-20plus .progress-bar {\n  background-color: #d796a6;\n}\n\n.markdown-body .progress-0plus .progress-bar {\n  background-color: #c25f77;\n}\n\n.markdown-body .candystripe-animate .progress-bar{\n  -webkit-animation: animate-stripes 3s linear infinite;\n  -moz-animation: animate-stripes 3s linear infinite;\n  animation: animate-stripes 3s linear infinite;\n}\n\n@-webkit-keyframes animate-stripes {\n  0% {\n    background-position: 0 0;\n  }\n\n  100% {\n    background-position: 60px 0;\n  }\n}\n\n@-moz-keyframes animate-stripes {\n  0% {\n    background-position: 0 0;\n  }\n\n  100% {\n    background-position: 60px 0;\n  }\n}\n\n@keyframes animate-stripes {\n  0% {\n    background-position: 0 0;\n  }\n\n  100% {\n    background-position: 60px 0;\n  }\n}\n\n.markdown-body .gloss .progress-bar {\n  box-shadow:\n    inset 0 4px 12px rgba(255, 255, 255, .7),\n    inset 0 -12px 0 rgba(0, 0, 0, .05);\n}\n\n/* MultiMarkdown Critic Blocks */\n.markdown-body .critic_mark {\n  background: #ff0;\n}\n\n.markdown-body .critic_delete {\n  color: #c82829;\n  text-decoration: line-through;\n}\n\n.markdown-body .critic_insert {\n  color: #718c00 ;\n  text-decoration: underline;\n}\n\n.markdown-body .critic_comment {\n  color: #8e908c;\n  font-style: italic;\n}\n\n.markdown-body .headeranchor {\n  font: normal normal 16px fontawesome-mini;\n  line-height: 1;\n  display: inline-block;\n  text-decoration: none;\n  -webkit-font-smoothing: antialiased;\n  -moz-osx-font-smoothing: grayscale;\n  -webkit-user-select: none;\n  -moz-user-select: none;\n  -ms-user-select: none;\n  user-select: none;\n}\n\n.headeranchor:before {\n  content: '\\e157';\n}\n\n.markdown-body .task-list-item {\n  list-style-type: none;\n}\n\n.markdown-body .task-list-item+.task-list-item {\n  margin-top: 3px;\n}\n\n.markdown-body .task-list-item input {\n  margin: 0 4px 0.25em -20px;\n  vertical-align: middle;\n}\n\n/* Media */\n@media only screen and (min-width: 480px) {\n  .markdown-body {\n    font-size:14px;\n  }\n}\n\n@media only screen and (min-width: 768px) {\n  .markdown-body {\n    font-size:16px;\n  }\n}\n\n@media print {\n  .markdown-body * {\n    background: transparent !important;\n    color: black !important;\n    filter:none !important;\n    -ms-filter: none !important;\n  }\n\n  .markdown-body {\n    font-size:12pt;\n    max-width:100%;\n    outline:none;\n    border: 0;\n  }\n\n  .markdown-body a,\n  .markdown-body a:visited {\n    text-decoration: underline;\n  }\n\n  .markdown-body .headeranchor-link {\n    display: none;\n  }\n\n  .markdown-body a[href]:after {\n    content: \" (\" attr(href) \")\";\n  }\n\n  .markdown-body abbr[title]:after {\n    content: \" (\" attr(title) \")\";\n  }\n\n  .markdown-body .ir a:after,\n  .markdown-body a[href^=\"javascript:\"]:after,\n  .markdown-body a[href^=\"#\"]:after {\n    content: \"\";\n  }\n\n  .markdown-body pre {\n    white-space: pre;\n    white-space: pre-wrap;\n    word-wrap: break-word;\n  }\n\n  .markdown-body pre,\n  .markdown-body blockquote {\n    border: 1px solid #999;\n    padding-right: 1em;\n    page-break-inside: avoid;\n  }\n\n  .markdown-body .progress,\n  .markdown-body .progress-bar {\n    -moz-box-shadow: none;\n    -webkit-box-shadow: none;\n    box-shadow: none;\n  }\n\n  .markdown-body .progress {\n    border: 1px solid #ddd;\n  }\n\n  .markdown-body .progress-bar {\n    height: 22px;\n    border-right: 1px solid #ddd;\n  }\n\n  .markdown-body tr,\n  .markdown-body img {\n    page-break-inside: avoid;\n  }\n\n  .markdown-body img {\n    max-width: 100% !important;\n  }\n\n  .markdown-body p,\n  .markdown-body h2,\n  .markdown-body h3 {\n    orphans: 3;\n    widows: 3;\n  }\n\n  .markdown-body h2,\n  .markdown-body h3 {\n    page-break-after: avoid;\n  }\n}\n\u003c/style\u003e\u003cstyle\u003e/*GitHub*/\n.codehilite {background-color:#fff;color:#333333;}\n.codehilite .hll {background-color:#ffffcc;}\n.codehilite .c{color:#999988;font-style:italic}\n.codehilite .err{color:#a61717;background-color:#e3d2d2}\n.codehilite .k{font-weight:bold}\n.codehilite .o{font-weight:bold}\n.codehilite .cm{color:#999988;font-style:italic}\n.codehilite .cp{color:#999999;font-weight:bold}\n.codehilite .c1{color:#999988;font-style:italic}\n.codehilite .cs{color:#999999;font-weight:bold;font-style:italic}\n.codehilite .gd{color:#000000;background-color:#ffdddd}\n.codehilite .ge{font-style:italic}\n.codehilite .gr{color:#aa0000}\n.codehilite .gh{color:#999999}\n.codehilite .gi{color:#000000;background-color:#ddffdd}\n.codehilite .go{color:#888888}\n.codehilite .gp{color:#555555}\n.codehilite .gs{font-weight:bold}\n.codehilite .gu{color:#800080;font-weight:bold}\n.codehilite .gt{color:#aa0000}\n.codehilite .kc{font-weight:bold}\n.codehilite .kd{font-weight:bold}\n.codehilite .kn{font-weight:bold}\n.codehilite .kp{font-weight:bold}\n.codehilite .kr{font-weight:bold}\n.codehilite .kt{color:#445588;font-weight:bold}\n.codehilite .m{color:#009999}\n.codehilite .s{color:#dd1144}\n.codehilite .n{color:#333333}\n.codehilite .na{color:teal}\n.codehilite .nb{color:#0086b3}\n.codehilite .nc{color:#445588;font-weight:bold}\n.codehilite .no{color:teal}\n.codehilite .ni{color:purple}\n.codehilite .ne{color:#990000;font-weight:bold}\n.codehilite .nf{color:#990000;font-weight:bold}\n.codehilite .nn{color:#555555}\n.codehilite .nt{color:navy}\n.codehilite .nv{color:teal}\n.codehilite .ow{font-weight:bold}\n.codehilite .w{color:#bbbbbb}\n.codehilite .mf{color:#009999}\n.codehilite .mh{color:#009999}\n.codehilite .mi{color:#009999}\n.codehilite .mo{color:#009999}\n.codehilite .sb{color:#dd1144}\n.codehilite .sc{color:#dd1144}\n.codehilite .sd{color:#dd1144}\n.codehilite .s2{color:#dd1144}\n.codehilite .se{color:#dd1144}\n.codehilite .sh{color:#dd1144}\n.codehilite .si{color:#dd1144}\n.codehilite .sx{color:#dd1144}\n.codehilite .sr{color:#009926}\n.codehilite .s1{color:#dd1144}\n.codehilite .ss{color:#990073}\n.codehilite .bp{color:#999999}\n.codehilite .vc{color:teal}\n.codehilite .vg{color:teal}\n.codehilite .vi{color:teal}\n.codehilite .il{color:#009999}\n.codehilite .gc{color:#999;background-color:#EAF2F5}\n\u003c/style\u003e\u003ctitle\u003eREADME\u003c/title\u003e\u003c/head\u003e\u003cbody\u003e\u003carticle class=\"markdown-body\"\u003e\u003cp\u003e\u003cimg src=\"https://user-images.githubusercontent.com/10807627/36499489-47bf1b6e-16f6-11e8-9a22-6e356c603a37.png\" height=\"64\"\u003e\u003c/p\u003e\n\u003ch1 id=\"flotilla-os\"\u003eflotilla-os\u003ca class=\"headerlink\" href=\"#flotilla-os\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h1\u003e\n\u003cp\u003e\u003ca href=\"https://circleci.com/gh/stitchfix/flotilla-os\"\u003e\u003cimg alt=\"Circle CI\" src=\"https://circleci.com/gh/stitchfix/flotilla-os.svg?style=shield\" /\u003e\u003c/a\u003e\n\u003ca href=\"https://goreportcard.com/report/github.com/stitchfix/flotilla-os\"\u003e\u003cimg alt=\"Go Report Card\" src=\"https://goreportcard.com/badge/github.com/stitchfix/flotilla-os\" /\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"introduction\"\u003eIntroduction\u003ca class=\"headerlink\" href=\"#introduction\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003eFlotilla is a self-service framework that dramatically simplifies the process of defining and executing containerized jobs. This means you get to focus on the work you\u0026rsquo;re doing rather than \u003cem\u003ehow\u003c/em\u003e to do it.\u003c/p\u003e\n\u003cp\u003eOnce deployed, Flotilla allows you to:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eDefine containerized jobs by allowing you to specify exactly what command to run, what image to run that command in, and what resources that command needs to run\u003c/li\u003e\n\u003cli\u003eRun any previously defined job and access its logs, status, and exit code\u003c/li\u003e\n\u003cli\u003eView and edit job definitions with a flexible UI\u003c/li\u003e\n\u003cli\u003eRun jobs and view execution history and logs within the UI\u003c/li\u003e\n\u003cli\u003eUse the complete REST API for definitions, jobs, and logs to build your own custom workflows\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"philosophy\"\u003ePhilosophy\u003ca class=\"headerlink\" href=\"#philosophy\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003eFlotilla is strongly opinionated about self-service for data science.\u003c/p\u003e\n\u003cp\u003eThe core assumption is that you understand your work the best. Therefore, it is \u003cem\u003eyou\u003c/em\u003e who should own your work from end-to-end. In other words, you shouldn\u0026rsquo;t need to be a \u0026ldquo;production engineer\u0026rdquo; to run your jobs or to access logs in case of problems. Do this with Flotilla.\u003c/p\u003e\n\u003ch2 id=\"quick-start\"\u003eQuick Start\u003ca class=\"headerlink\" href=\"#quick-start\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h2\u003e\n\u003ch3 id=\"minimal-assumptions\"\u003eMinimal Assumptions\u003ca class=\"headerlink\" href=\"#minimal-assumptions\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h3\u003e\n\u003cp\u003eBefore we can do \u003cem\u003eanything\u003c/em\u003e there\u0026rsquo;s some \u003cem\u003eprerequistes\u003c/em\u003e that must be met.\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eFlotilla by default uses AWS. You must have an AWS account and AWS keys available. This quick-start guide uses AWS keys exported into the environment variables: \u003ccode\u003eAWS_ACCESS_KEY_ID\u003c/code\u003e and \u003ccode\u003eAWS_SECRET_ACCESS_KEY\u003c/code\u003e. If you\u0026rsquo;ve got credentials configured on your machine you can set these easily by running:\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"codehilite\"\u003e\u003cpre\u003eexport AWS_ACCESS_KEY_ID=$(aws --profile default configure get aws_access_key_id)\nexport AWS_SECRET_ACCESS_KEY=$(aws --profile default configure get aws_secret_access_key)\n\u003c/pre\u003e\u003c/div\u003e\n\n\u003cblockquote\u003e\n\u003cp\u003eNote: When running on AWS EC2 instances or ECS it\u0026rsquo;s better practice to use an IAM profile for AWS credentials\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003col start=\"2\"\u003e\n\u003cli\u003eThe AWS credentials must be authorized. The permissions required are described in the following policy document for AWS (you can attach it to a user or a role depending on how you manage users in AWS).\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"codehilite\"\u003e\u003cpre\u003e{\n    \u0026quot;Version\u0026quot;: \u0026quot;2012-10-17\u0026quot;,\n    \u0026quot;Statement\u0026quot;: [\n        {\n            \u0026quot;Sid\u0026quot;: \u0026quot;flotilla-policy\u0026quot;,\n            \u0026quot;Effect\u0026quot;: \u0026quot;Allow\u0026quot;,\n            \u0026quot;Action\u0026quot;: [\n                \u0026quot;sqs:DeleteMessage\u0026quot;,\n                \u0026quot;sqs:ListQueues\u0026quot;,\n                \u0026quot;sqs:GetQueueUrl\u0026quot;,\n                \u0026quot;logs:DescribeLogGroups\u0026quot;,\n                \u0026quot;sqs:ReceiveMessage\u0026quot;,\n                \u0026quot;events:PutRule\u0026quot;,\n                \u0026quot;sqs:SendMessage\u0026quot;,\n                \u0026quot;sqs:GetQueueAttributes\u0026quot;,\n                \u0026quot;ecs:DescribeClusters\u0026quot;,\n                \u0026quot;ecs:DeregisterTaskDefinition\u0026quot;,\n                \u0026quot;events:ListRuleNamesByTarget\u0026quot;,\n                \u0026quot;ecs:RunTask\u0026quot;,\n                \u0026quot;ecs:RegisterTaskDefinition\u0026quot;,\n                \u0026quot;sqs:CreateQueue\u0026quot;,\n                \u0026quot;ecs:ListContainerInstances\u0026quot;,\n                \u0026quot;ecs:DescribeContainerInstances\u0026quot;,\n                \u0026quot;ecs:ListClusters\u0026quot;,\n                \u0026quot;ecs:StopTask\u0026quot;,\n                \u0026quot;logs:CreateLogGroup\u0026quot;,\n                \u0026quot;logs:PutRetentionPolicy\u0026quot;,\n                \u0026quot;logs:GetLogEvents\u0026quot;,\n                \u0026quot;events:PutTargets\u0026quot;,\n                \u0026quot;sqs:SetQueueAttributes\u0026quot;\n            ],\n            \u0026quot;Resource\u0026quot;: \u0026quot;*\u0026quot;\n        }\n    ]\n}\n\u003c/pre\u003e\u003c/div\u003e\n\n\u003col start=\"3\"\u003e\n\u003cli\u003eFlotilla uses AWS\u0026rsquo;s Elastic Container Service (ECS) and Elastic Kubernetes Service (EKS) as the execution backend. However, Flotilla does not manage ECS/EKS clusters. There must be at least one cluster defined in AWS\u0026rsquo;s ECS/EKS service available to you and it must have at least one task node. Most typically this is the \u003ccode\u003edefault\u003c/code\u003e cluster and examples will assume this going forward. You can easily set up a cluster by following the instructions here: \u003ca href=\"https://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_container_instance.html\"\u003ehttps://docs.aws.amazon.com/AmazonECS/latest/developerguide/launch_container_instance.html\u003c/a\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003ca href=\"https://docs.aws.amazon.com/eks/latest/userguide/what-is-eks.html\"\u003ehttps://docs.aws.amazon.com/eks/latest/userguide/what-is-eks.html\u003c/a\u003e\u003c/p\u003e\n\u003ch3 id=\"starting-the-service-locally\"\u003eStarting the service locally\u003ca class=\"headerlink\" href=\"#starting-the-service-locally\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h3\u003e\n\u003cp\u003eYou can run the service locally (which will still leverage AWS resources) using the \u003ca href=\"https://docs.docker.com/compose/\"\u003edocker-compose\u003c/a\u003e tool. From inside the repo run:\u003c/p\u003e\n\u003cdiv class=\"codehilite\"\u003e\u003cpre\u003edocker-compose up -d\n\u003c/pre\u003e\u003c/div\u003e\n\n\u003cp\u003eYou\u0026rsquo;ll notice it builds the code in the repo and starts the flotilla service as well as the default postgres backend.\u003c/p\u003e\n\u003cp\u003eVerify the service is running by making a \u003ccode\u003eGET\u003c/code\u003e request with cURL (or navigating to in a web browser) the url \u003ccode\u003ehttp://localhost:5000/api/v6/task\u003c/code\u003e. A 200OK response means things are good!\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eNote: The default configuration under \u003ccode\u003econf\u003c/code\u003e and in the \u003ccode\u003edocker-compose.yml\u003c/code\u003e assume port 3000. You\u0026rsquo;ll have to change it in both places if you don\u0026rsquo;t want to use port 3000 locally.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch3 id=\"using-the-ui\"\u003eUsing the UI\u003ca class=\"headerlink\" href=\"#using-the-ui\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h3\u003e\n\u003cp\u003eFlotilla has a simple, easy to use UI. Here\u0026rsquo;s some example images for basic usage.\u003c/p\u003e\n\u003ch4 id=\"define-a-task-with-the-ui\"\u003eDefine a task with the UI\u003ca class=\"headerlink\" href=\"#define-a-task-with-the-ui\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h4\u003e\n\u003cp\u003eThe UI allows you to quickly create new tasks.\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Define Task\" src=\"https://user-images.githubusercontent.com/10807627/36499487-47a0b82c-16f6-11e8-886b-ca6d38276889.png\" title=\"Create New Task\" /\u003e\u003c/p\u003e\n\u003ch4 id=\"launch-a-task-with-ui\"\u003eLaunch a task with UI\u003ca class=\"headerlink\" href=\"#launch-a-task-with-ui\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h4\u003e\n\u003cp\u003eYou can run tasks you\u0026rsquo;ve created with the UI as well. Once you\u0026rsquo;ve ran a task the run will transition from \u003ccode\u003eQueued\u003c/code\u003e to \u003ccode\u003ePending\u003c/code\u003e to \u003ccode\u003eRunning\u003c/code\u003e before it finishes and shows \u003ccode\u003eSuccess\u003c/code\u003e or \u003ccode\u003eFailed\u003c/code\u003e (see \u003ca href=\"#definitions-and-task-life-cycle\"\u003eTask Life Cycle\u003c/a\u003e). Once a task is in the \u003ccode\u003eRunning\u003c/code\u003e state the logs should be visible.\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eLaunch\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cimg alt=\"Run Task\" src=\"https://user-images.githubusercontent.com/10807627/36499492-481da436-16f6-11e8-9f14-5bbe8c297434.png\" title=\"Run Task\" /\u003e\u003c/p\u003e\n\u003col start=\"2\"\u003e\n\u003cli\u003eQueued \u0026ndash;\u0026gt; Pending\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cimg alt=\"Queued Task\" src=\"https://user-images.githubusercontent.com/10807627/36499491-4801515a-16f6-11e8-9525-db85bb999887.png\" title=\"Queued Task\" /\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Pending Task\" src=\"https://user-images.githubusercontent.com/10807627/36499490-47e27e88-16f6-11e8-8041-355de885be44.png\" title=\"Pending Task\" /\u003e\n3. View logs\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Running Task\" src=\"https://user-images.githubusercontent.com/10807627/36499493-4842176c-16f6-11e8-9467-a345987bd407.png\" title=\"Running Task\" /\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"Finished Task\" src=\"https://user-images.githubusercontent.com/10807627/36499494-48609cfa-16f6-11e8-8656-5504063cb6e7.png\" title=\"Finished Task\" /\u003e\u003c/p\u003e\n\u003ch3 id=\"basic-api-usage\"\u003eBasic API Usage\u003ca class=\"headerlink\" href=\"#basic-api-usage\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h3\u003e\n\u003ch4 id=\"defining-your-first-task\"\u003eDefining your first task\u003ca class=\"headerlink\" href=\"#defining-your-first-task\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h4\u003e\n\u003cp\u003eBefore you can run a task you first need to define it. We\u0026rsquo;ll use the example hello world task definition. Here\u0026rsquo;s what that looks like:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003ehello-world.json\u003c/p\u003e\n\u003cdiv class=\"codehilite\"\u003e\u003cpre\u003e{\n  \u0026quot;alias\u0026quot;: \u0026quot;hello-flotilla\u0026quot;,\n  \u0026quot;group_name\u0026quot;: \u0026quot;examples\u0026quot;,\n  \u0026quot;image\u0026quot;: \u0026quot;ubuntu:latest\u0026quot;,\n  \u0026quot;memory\u0026quot;: 512,\n  \u0026quot;env\u0026quot;: [\n    {\n      \u0026quot;name\u0026quot;: \u0026quot;USERNAME\u0026quot;,\n      \u0026quot;value\u0026quot;: \u0026quot;_fill_me_in_\u0026quot;\n    }\n  ],\n  \u0026quot;command\u0026quot;: \u0026quot;echo \\\u0026quot;hello ${USERNAME}\\\u0026quot;\u0026quot;\n}\n\u003c/pre\u003e\u003c/div\u003e\n\n\u003c/blockquote\u003e\n\u003cp\u003eIt\u0026rsquo;s a simple task that runs in the default ubuntu image, prints your username to the logs, and exits.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eNote: While you can use non-public images and images in your own registries with flotilla, credentials for accessing those images must exist on the ECS hosts. This is outside the scope of this doc. See the AWS \u003ca href=\"https://docs.aws.amazon.com/AmazonECS/latest/developerguide/private-auth.html\"\u003edocumentation\u003c/a\u003e.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eLet\u0026rsquo;s define it:\u003c/p\u003e\n\u003cdiv class=\"codehilite\"\u003e\u003cpre\u003ecurl -XPOST localhost:5000/api/v6/task --data @examples/hello-world.json\n\u003c/pre\u003e\u003c/div\u003e\n\n\u003cp\u003eYou\u0026rsquo;ll notice that if you visit the initial url again \u003ccode\u003ehttp://localhost:5000/api/v6/task\u003c/code\u003e the newly defined definition will be in the list.\u003c/p\u003e\n\u003ch4 id=\"running-your-first-task\"\u003eRunning your first task\u003ca class=\"headerlink\" href=\"#running-your-first-task\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h4\u003e\n\u003cp\u003eThis is the fun part. You\u0026rsquo;ll make a \u003ccode\u003ePUT\u003c/code\u003e request to the execution endpoint for the task you just defined and specify any environment variables.\u003c/p\u003e\n\u003cdiv class=\"codehilite\"\u003e\u003cpre\u003ecurl -XPUT localhost:5000/api/v6/task/alias/hello-flotilla/execute -d \u0026#39;{\n  \u0026quot;cluster\u0026quot;:\u0026quot;default\u0026quot;,\n  \u0026quot;env\u0026quot;:[\n    {\u0026quot;name\u0026quot;:\u0026quot;USERNAME\u0026quot;,\u0026quot;value\u0026quot;:\u0026quot;yourusername\u0026quot;}\n  ],\n  \u0026quot;run_tags\u0026quot;:{\u0026quot;owner_id\u0026quot;:\u0026quot;youruser\u0026quot;}\n}\u0026#39;\n\u003c/pre\u003e\u003c/div\u003e\n\n\u003cblockquote\u003e\n\u003cp\u003eNote: \u003ccode\u003erun_tags\u003c/code\u003e is defined as a way for all runs to have a ownership injected for visibility and is \u003cem\u003erequired\u003c/em\u003e.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eYou\u0026rsquo;ll get a response that contains a \u003ccode\u003erun_id\u003c/code\u003e field. You can check the status of your task at \u003ccode\u003ehttp://localhost:5000/api/v6/history/\u0026lt;run_id\u0026gt;\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"codehilite\"\u003e\u003cpre\u003ecurl -XGET localhost:5000/api/v6/history/\u0026lt;run_id\u0026gt;\n\n{\n  \u0026quot;instance\u0026quot;: {\n    \u0026quot;dns_name\u0026quot;: \u0026quot;\u0026lt;dns-host-of-task-node\u0026gt;\u0026quot;,\n    \u0026quot;instance_id\u0026quot;: \u0026quot;\u0026lt;instance-id-of-task-node\u0026gt;\u0026quot;\n  },\n  \u0026quot;run_id\u0026quot;: \u0026quot;\u0026lt;run_id\u0026gt;\u0026quot;,\n  \u0026quot;definition_id\u0026quot;: \u0026quot;\u0026lt;definition_id\u0026gt;\u0026quot;,\n  \u0026quot;alias\u0026quot;: \u0026quot;hello-flotilla\u0026quot;,\n  \u0026quot;image\u0026quot;: \u0026quot;ubuntu:latest\u0026quot;,\n  \u0026quot;cluster\u0026quot;: \u0026quot;default\u0026quot;,\n  \u0026quot;status\u0026quot;: \u0026quot;PENDING\u0026quot;,\n  \u0026quot;env\u0026quot;: [\n    {\n      \u0026quot;name\u0026quot;: \u0026quot;FLOTILLA_RUN_OWNER_ID\u0026quot;,\n      \u0026quot;value\u0026quot;: \u0026quot;youruser\u0026quot;\n    },\n    {\n      \u0026quot;name\u0026quot;: \u0026quot;FLOTILLA_SERVER_MODE\u0026quot;,\n      \u0026quot;value\u0026quot;: \u0026quot;dev\u0026quot;\n    },\n    {\n      \u0026quot;name\u0026quot;: \u0026quot;FLOTILLA_RUN_ID\u0026quot;,\n      \u0026quot;value\u0026quot;: \u0026quot;\u0026lt;run_id\u0026gt;\u0026quot;\n    },\n    {\n      \u0026quot;name\u0026quot;: \u0026quot;USERNAME\u0026quot;,\n      \u0026quot;value\u0026quot;: \u0026quot;yourusername\u0026quot;\n    }\n  ]\n}\n\u003c/pre\u003e\u003c/div\u003e\n\n\u003cp\u003eand you can get the logs for your task at \u003ccode\u003ehttp://localhost:5000/api/v6/\u0026lt;run_id\u0026gt;/logs\u003c/code\u003e. You will not see any logs until your task is at least in the \u003ccode\u003eRUNNING\u003c/code\u003e state.\u003c/p\u003e\n\u003cdiv class=\"codehilite\"\u003e\u003cpre\u003ecurl -XGET localhost:5000/api/v6/\u0026lt;run_id\u0026gt;/logs\n\n{\n  \u0026quot;last_seen\u0026quot;:\u0026quot;\u0026lt;last_seen_token_used_for_paging\u0026gt;\u0026quot;,\n  \u0026quot;log\u0026quot;:\u0026quot;+ set -e\\n+ echo \u0026#39;hello yourusername\u0026#39;\\nhello yourusername\u0026quot;\n}\n\u003c/pre\u003e\u003c/div\u003e\n\n\u003ch2 id=\"definitions-and-task-life-cycle\"\u003eDefinitions and Task Life Cycle\u003ca class=\"headerlink\" href=\"#definitions-and-task-life-cycle\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h2\u003e\n\u003ch3 id=\"definitions\"\u003eDefinitions\u003ca class=\"headerlink\" href=\"#definitions\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h3\u003e\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003eName\u003c/th\u003e\n\u003cth\u003eDefinition\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003etask\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eA definition of a task that can be executed to create a \u003ccode\u003erun\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003erun\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eAn instance of a task\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch3 id=\"task-life-cycle\"\u003eTask Life Cycle\u003ca class=\"headerlink\" href=\"#task-life-cycle\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h3\u003e\n\u003cp\u003eWhen executed, a task\u0026rsquo;s run goes through several transitions\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003ccode\u003eQUEUED\u003c/code\u003e - this is the first phase of a run and means the run is currently queued and waiting to be allocated to a cluster\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ePENDING\u003c/code\u003e - every \u003ccode\u003eworker.submit_interval\u003c/code\u003e (defined in the config) the submit worker pulls from the queues and submits them for execution. At this point, if the cluster associated with the run has resources, the run gets allocated to the cluster and transitions to the \u003ccode\u003ePENDING\u003c/code\u003e status. For the default execution engine this stage encapsulates the process of pulling the docker image and starting the container. It can take several minutes depending on whether the image is cached and how large the image is.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eRUNNING\u003c/code\u003e - Once the run starts on a particular execution host it transitions to this stage. At this point logs should become available.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eSTOPPED\u003c/code\u003e - A run enters this stage when it finishes execution. This can mean it either succeeded or failed depending on the existence of an \u003ccode\u003eexit_code\u003c/code\u003e and the value of that exit code.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eNEEDS_RETRY\u003c/code\u003e - on occassion, due to host level characteristics (full disk, too many open files, timeouts pulling image, etc) the run exits with a null exit code without ever being executed. In this case the reason is analyzed to determine if the run is retriable. If it is, the task transitions to this status and is allocated to the appropriate execution queue again, and will repeat the lifecycle.\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch4 id=\"normal-lifecycle\"\u003eNormal Lifecycle\u003ca class=\"headerlink\" href=\"#normal-lifecycle\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h4\u003e\n\u003cp\u003e\u003ccode\u003eQUEUED\u003c/code\u003e \u0026ndash;\u0026gt; \u003ccode\u003ePENDING\u003c/code\u003e \u0026ndash;\u0026gt; \u003ccode\u003eRUNNING\u003c/code\u003e \u0026ndash;\u0026gt; \u003ccode\u003eSTOPPED\u003c/code\u003e\u003c/p\u003e\n\u003ch4 id=\"retry-lifecycle\"\u003eRetry Lifecycle\u003ca class=\"headerlink\" href=\"#retry-lifecycle\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h4\u003e\n\u003cp\u003e\u0026hellip; \u0026ndash;\u0026gt; \u003ccode\u003ePENDING\u003c/code\u003e \u0026ndash;\u0026gt; \u003ccode\u003eSTOPPED\u003c/code\u003e \u0026ndash;\u0026gt; \u003ccode\u003eNEEDS_RETRY\u003c/code\u003e \u0026ndash;\u0026gt; \u003ccode\u003eQUEUED\u003c/code\u003e \u0026ndash;\u0026gt; \u0026hellip;\u003c/p\u003e\n\u003ch2 id=\"deploying\"\u003eDeploying\u003ca class=\"headerlink\" href=\"#deploying\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h2\u003e\n\u003cp\u003eIn a production deployment you\u0026rsquo;ll want multiple instances of the flotilla service running and postgres running elsewhere (eg. Amazon RDS). In this case the most salient detail configuration detail is the \u003ccode\u003eDATABASE_URL\u003c/code\u003e.\u003c/p\u003e\n\u003ch3 id=\"docker-based-deploy\"\u003eDocker based deploy\u003ca class=\"headerlink\" href=\"#docker-based-deploy\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h3\u003e\n\u003cp\u003eThe simplest way to deploy for very light usage is to avoid a reverse proxy and deploy directly with docker.\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003eBuild and tag an image for flotilla using the \u003ccode\u003eDockerfile\u003c/code\u003e provided in this repo:\u003c/p\u003e\n\u003cp\u003e\u003cdiv class=\"codehilite\"\u003e\u003cpre\u003edocker build -t \u0026lt;your repo name\u0026gt;/flotilla:\u0026lt;version tag\u0026gt;\n\u003c/pre\u003e\u003c/div\u003e\n2. Run this image wherever you deploy your services:\u003c/p\u003e\n\u003cdiv class=\"codehilite\"\u003e\u003cpre\u003edocker run -e DATABASE_URL=\u0026lt;your db url\u0026gt; -e FLOTILLA_MODE=prod -p 3000:3000 ...\u0026lt;other standard docker run args\u0026gt;\n\u003c/pre\u003e\u003c/div\u003e\n\n\u003cblockquote\u003e\n\u003ch2 id=\"notes\"\u003eNotes:\u003ca class=\"headerlink\" href=\"#notes\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eFlotilla uses \u003ca href=\"https://github.com/spf13/viper\"\u003eviper\u003c/a\u003e for configuration so you can override any of the default configuration under \u003ccode\u003econf/\u003c/code\u003e using run time environment variables passed to \u003ccode\u003edocker run\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eIn most realistic deploys you\u0026rsquo;ll likely want to configure a reverse proxy to sit in front of the flotilla container. See the docs \u003ca href=\"https://hub.docker.com/_/nginx/\"\u003ehere\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eSee \u003ca href=\"https://docs.docker.com/engine/reference/run/\"\u003edocker run\u003c/a\u003e for more details\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch3 id=\"configuration-in-detail\"\u003eConfiguration In Detail\u003ca class=\"headerlink\" href=\"#configuration-in-detail\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h3\u003e\n\u003cp\u003eThe variables in \u003ccode\u003econf/config.yml\u003c/code\u003e are sensible defaults. Most should be left alone unless you\u0026rsquo;re developing flotilla itself. However, there are a few you may want to change in a production environment.\u003c/p\u003e\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003eVariable Name\u003c/th\u003e\n\u003cth\u003eDescription\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eworker.retry_interval\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eRun frequency of the retry worker\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eworker.submit_interval\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003ePoll frequency of the submit worker\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eworker.status_interval\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003ePoll frequency of the status update worker\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ehttp.server.read_timeout_seconds\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eSets read timeout in seconds for the http server\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ehttp.server.write_timeout_seconds\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eSets the write timeout in seconds for the http server\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003ehttp.server.listen_address\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eThe port for the http server to listen on\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eowner_id_var\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eWhich environment variable containing ownership information to inject into the runtime of jobs\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eenabled_workers\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eThis variable is a list of the workers that run. Use this to control what workers run when using a multi-container deployment strategy. Valid list items include (\u003ccode\u003eretry\u003c/code\u003e, \u003ccode\u003esubmit\u003c/code\u003e, and \u003ccode\u003estatus\u003c/code\u003e)\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003elog.namespace\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eFor the default ECS execution engine setup this is the \u003ccode\u003elog-group\u003c/code\u003e to use\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003elog.retention_days\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eFor the default ECS execution engine this is the number of days to retain logs\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003elog.driver.options.*\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eFor the default ECS execution engine these map to the \u003ccode\u003eawslogs\u003c/code\u003e driver options \u003ca href=\"https://docs.aws.amazon.com/AmazonECS/latest/developerguide/using_awslogs.html\"\u003ehere\u003c/a\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003equeue.namespace\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eFor the default ECS execution engine this is the prefix used for SQS to determine which queues to pull job launch messages from\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003equeue.retention_seconds\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eFor the default ECS execution engine this configures how long a message will stay in an SQS queue without being consumed\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003equeue.process_time\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eFor the default ECS execution engine configures the length of time allowed to process a job launch message\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003equeue.status\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eFor the default ECS execution engine this configures which SQS queue to route ECS cluster status updates to\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003equeue.status_rule\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eFor the default ECS execution engine this configures the name of the rule for routing ECS cluster status updates\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003emetrics.dogstatsd.address\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eStatds metrics host in Datadog format\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003emetrics.dogstatsd.namespace\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eNamespace for the metrics - for example \u003ccode\u003eflotilla.\u003c/code\u003e\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eredis_address\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eRedis host for caching and locks\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003ccode\u003eredis_db\u003c/code\u003e\u003c/td\u003e\n\u003ctd\u003eRedis db to be used - numeric\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch2 id=\"development\"\u003eDevelopment\u003ca class=\"headerlink\" href=\"#development\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h2\u003e\n\u003ch3 id=\"api-documentation\"\u003eAPI Documentation\u003ca class=\"headerlink\" href=\"#api-documentation\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h3\u003e\n\u003cp\u003eSee \u003ca href=\"https://stitchfix.github.io/flotilla-os/api.html\"\u003eAPI\u003c/a\u003e\u003c/p\u003e\n\u003ch3 id=\"building\"\u003eBuilding\u003ca class=\"headerlink\" href=\"#building\" title=\"Permanent link\"\u003e\u003c/a\u003e\u003c/h3\u003e\n\u003cp\u003eCurrently Flotilla is built using \u003ccode\u003ego\u003c/code\u003e 1.9.3 and uses the \u003ca href=\"https://github.com/kardianos/govendor\"\u003e\u003ccode\u003egovendor\u003c/code\u003e\u003c/a\u003e to manage dependencies.\u003c/p\u003e\n\u003cdiv class=\"codehilite\"\u003e\u003cpre\u003egovendor sync \u0026amp;\u0026amp; go build\n\u003c/pre\u003e\u003c/div\u003e\u003c/article\u003e\u003c/body\u003e\u003c/html\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstitchfix%2Fflotilla-os","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstitchfix%2Fflotilla-os","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstitchfix%2Fflotilla-os/lists"}