ufo 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.rspec +3 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +128 -0
- data/Guardfile +12 -0
- data/LICENSE.txt +22 -0
- data/README.md +227 -0
- data/Rakefile +6 -0
- data/bin/ufo +10 -0
- data/lib/starter_project/.env.prod +3 -0
- data/lib/starter_project/Dockerfile +20 -0
- data/lib/starter_project/bin/deploy +12 -0
- data/lib/starter_project/ufo/settings.yml +7 -0
- data/lib/starter_project/ufo/task_definitions.rb +44 -0
- data/lib/starter_project/ufo/templates/main.json.erb +39 -0
- data/lib/ufo.rb +26 -0
- data/lib/ufo/aws_services.rb +21 -0
- data/lib/ufo/cli.rb +136 -0
- data/lib/ufo/cli/help.rb +164 -0
- data/lib/ufo/defaults.rb +46 -0
- data/lib/ufo/destroy.rb +60 -0
- data/lib/ufo/docker_builder.rb +120 -0
- data/lib/ufo/docker_cleaner.rb +52 -0
- data/lib/ufo/dockerfile_updater.rb +42 -0
- data/lib/ufo/dsl.rb +93 -0
- data/lib/ufo/dsl/helper.rb +47 -0
- data/lib/ufo/dsl/outputter.rb +40 -0
- data/lib/ufo/dsl/task_definition.rb +65 -0
- data/lib/ufo/ecr_auth.rb +35 -0
- data/lib/ufo/ecr_cleaner.rb +66 -0
- data/lib/ufo/execute.rb +19 -0
- data/lib/ufo/init.rb +83 -0
- data/lib/ufo/pretty_time.rb +14 -0
- data/lib/ufo/scale.rb +34 -0
- data/lib/ufo/settings.rb +33 -0
- data/lib/ufo/ship.rb +436 -0
- data/lib/ufo/tasks_builder.rb +30 -0
- data/lib/ufo/tasks_register.rb +51 -0
- data/lib/ufo/templates/default.json.erb +39 -0
- data/lib/ufo/version.rb +3 -0
- data/spec/fixtures/home_existing/.docker/config.json +10 -0
- data/spec/lib/cli_spec.rb +50 -0
- data/spec/lib/ecr_auth_spec.rb +39 -0
- data/spec/lib/ecr_cleaner_spec.rb +32 -0
- data/spec/lib/ship_spec.rb +77 -0
- data/spec/spec_helper.rb +28 -0
- data/ufo.gemspec +34 -0
- metadata +267 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3f4295c61395db86047326a8b5cca89b35735ac5
|
4
|
+
data.tar.gz: fa3eda92853d988e5f95f673eccb296f1f85526d
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2bd0122e097ef64e815caac9c1b4ad3a7f16e12fa60b15d47ba5033d7ea818b237bd80004e6c589e447a2866678ff734118060f49ff24abe9443fef7b548a7cc
|
7
|
+
data.tar.gz: ef44ccd22089e3e408f7453ce978c51102acc43edf968d6edfe3721c02729a926fd8d37ac08fd6961d726d3800cd27b8f8d01b7d066d327b520926d86d09f7b3
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# Change Log
|
2
|
+
|
3
|
+
All notable changes to this project will be documented in this file.
|
4
|
+
This project *tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
|
5
|
+
|
6
|
+
## [0.0.5]
|
7
|
+
|
8
|
+
- add docker base command
|
9
|
+
- add docker image cleaners
|
10
|
+
- service_cluster settings.yml
|
11
|
+
- Initial conceptual release
|
12
|
+
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
ufo (0.0.2)
|
5
|
+
aws-sdk
|
6
|
+
byebug
|
7
|
+
colorize
|
8
|
+
deep_merge
|
9
|
+
hashie
|
10
|
+
plissken
|
11
|
+
thor
|
12
|
+
|
13
|
+
GEM
|
14
|
+
remote: https://rubygems.org/
|
15
|
+
specs:
|
16
|
+
activemodel (4.0.13)
|
17
|
+
activesupport (= 4.0.13)
|
18
|
+
builder (~> 3.1.0)
|
19
|
+
activesupport (4.0.13)
|
20
|
+
i18n (~> 0.6, >= 0.6.9)
|
21
|
+
minitest (~> 4.2)
|
22
|
+
multi_json (~> 1.3)
|
23
|
+
thread_safe (~> 0.1)
|
24
|
+
tzinfo (~> 0.3.37)
|
25
|
+
aws-sdk (2.6.9)
|
26
|
+
aws-sdk-resources (= 2.6.9)
|
27
|
+
aws-sdk-core (2.6.9)
|
28
|
+
jmespath (~> 1.0)
|
29
|
+
aws-sdk-resources (2.6.9)
|
30
|
+
aws-sdk-core (= 2.6.9)
|
31
|
+
builder (3.1.4)
|
32
|
+
byebug (9.0.6)
|
33
|
+
codeclimate-test-reporter (0.6.0)
|
34
|
+
simplecov (>= 0.7.1, < 1.0.0)
|
35
|
+
coderay (1.1.1)
|
36
|
+
colorize (0.8.1)
|
37
|
+
deep_merge (1.1.1)
|
38
|
+
diff-lcs (1.2.5)
|
39
|
+
docile (1.1.5)
|
40
|
+
ffi (1.9.14)
|
41
|
+
formatador (0.2.5)
|
42
|
+
guard (2.14.0)
|
43
|
+
formatador (>= 0.2.4)
|
44
|
+
listen (>= 2.7, < 4.0)
|
45
|
+
lumberjack (~> 1.0)
|
46
|
+
nenv (~> 0.1)
|
47
|
+
notiffany (~> 0.0)
|
48
|
+
pry (>= 0.9.12)
|
49
|
+
shellany (~> 0.0)
|
50
|
+
thor (>= 0.18.1)
|
51
|
+
guard-bundler (2.1.0)
|
52
|
+
bundler (~> 1.0)
|
53
|
+
guard (~> 2.2)
|
54
|
+
guard-compat (~> 1.1)
|
55
|
+
guard-compat (1.2.1)
|
56
|
+
guard-rspec (4.7.3)
|
57
|
+
guard (~> 2.1)
|
58
|
+
guard-compat (~> 1.1)
|
59
|
+
rspec (>= 2.99.0, < 4.0)
|
60
|
+
hashie (3.4.6)
|
61
|
+
i18n (0.7.0)
|
62
|
+
jmespath (1.3.1)
|
63
|
+
json (2.0.2)
|
64
|
+
listen (3.1.5)
|
65
|
+
rb-fsevent (~> 0.9, >= 0.9.4)
|
66
|
+
rb-inotify (~> 0.9, >= 0.9.7)
|
67
|
+
ruby_dep (~> 1.2)
|
68
|
+
lumberjack (1.0.10)
|
69
|
+
method_source (0.8.2)
|
70
|
+
minitest (4.7.5)
|
71
|
+
multi_json (1.12.1)
|
72
|
+
nenv (0.3.0)
|
73
|
+
notiffany (0.1.1)
|
74
|
+
nenv (~> 0.1)
|
75
|
+
shellany (~> 0.0)
|
76
|
+
plissken (0.2.0)
|
77
|
+
symbolize (~> 4.2)
|
78
|
+
pry (0.10.4)
|
79
|
+
coderay (~> 1.1.0)
|
80
|
+
method_source (~> 0.8.1)
|
81
|
+
slop (~> 3.4)
|
82
|
+
rake (11.3.0)
|
83
|
+
rb-fsevent (0.9.7)
|
84
|
+
rb-inotify (0.9.7)
|
85
|
+
ffi (>= 0.5.0)
|
86
|
+
rspec (3.5.0)
|
87
|
+
rspec-core (~> 3.5.0)
|
88
|
+
rspec-expectations (~> 3.5.0)
|
89
|
+
rspec-mocks (~> 3.5.0)
|
90
|
+
rspec-core (3.5.3)
|
91
|
+
rspec-support (~> 3.5.0)
|
92
|
+
rspec-expectations (3.5.0)
|
93
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
94
|
+
rspec-support (~> 3.5.0)
|
95
|
+
rspec-mocks (3.5.0)
|
96
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
97
|
+
rspec-support (~> 3.5.0)
|
98
|
+
rspec-support (3.5.0)
|
99
|
+
ruby_dep (1.4.0)
|
100
|
+
shellany (0.0.1)
|
101
|
+
simplecov (0.12.0)
|
102
|
+
docile (~> 1.1.0)
|
103
|
+
json (>= 1.8, < 3)
|
104
|
+
simplecov-html (~> 0.10.0)
|
105
|
+
simplecov-html (0.10.0)
|
106
|
+
slop (3.6.0)
|
107
|
+
symbolize (4.5.2)
|
108
|
+
activemodel (>= 3.2, < 5)
|
109
|
+
activesupport (>= 3.2, < 5)
|
110
|
+
i18n
|
111
|
+
thor (0.19.1)
|
112
|
+
thread_safe (0.3.5)
|
113
|
+
tzinfo (0.3.51)
|
114
|
+
|
115
|
+
PLATFORMS
|
116
|
+
ruby
|
117
|
+
|
118
|
+
DEPENDENCIES
|
119
|
+
bundler (~> 1.3)
|
120
|
+
codeclimate-test-reporter
|
121
|
+
guard
|
122
|
+
guard-bundler
|
123
|
+
guard-rspec
|
124
|
+
rake
|
125
|
+
ufo!
|
126
|
+
|
127
|
+
BUNDLED WITH
|
128
|
+
1.13.2
|
data/Guardfile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
guard 'rspec' do
|
2
|
+
watch(%r{^spec/.+_spec\.rb$})
|
3
|
+
watch(%r{^lib/(.+)\.rb$}) { "spec/ufo_spec.rb" }
|
4
|
+
watch(%r{^lib/ufo/(.+)\.rb$}) { "spec/ufo_spec.rb" }
|
5
|
+
watch('spec/spec_helper.rb') { "spec/ufo_spec.rb" }
|
6
|
+
watch(%r{^lib/ufo/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
7
|
+
end
|
8
|
+
|
9
|
+
guard 'bundler' do
|
10
|
+
watch('Gemfile')
|
11
|
+
watch(/^.+\.gemspec/)
|
12
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 GitResolve
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,227 @@
|
|
1
|
+
# Ufo
|
2
|
+
|
3
|
+
This script handles a common application deployment pattern to AWS ECS. Most rails apps have web, worker, and clock processes. These processes use the same codebase (same docker image) but have slightly different run time settings. For example, the docker run command for a web process could be `puma` and the command for a worker process could be `sidekiq`. Environment variables are sometimes different also.
|
4
|
+
|
5
|
+
This script builds the same docker image to be used for all of these processes but allows you to different generated AWS ECS Task Definitions for each of the processes. The task defintions for each process is created via a template generator which you fully can control.
|
6
|
+
|
7
|
+
A summary of steps `ufo ship` takes:
|
8
|
+
|
9
|
+
1. builds a docker image - optional and can be skipped
|
10
|
+
2. generates the ecs template definition - optional and can be skipped
|
11
|
+
3. ships it to possible multiple services depending on the settings
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
$ gem install ufo
|
16
|
+
|
17
|
+
You will need a working version of docker installed if you want ufo to also build the docker image. If you do not want ufo to build the docker image, then you do not need docker installed.
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
If the cluster or the services do not exist then they get created. If you are relying on this tool to create the cluster, you still need to associate ECS Container Instances to the cluster yourself.
|
22
|
+
|
23
|
+
First initialize ufo files within your project. Let's say you have an `hi` app.
|
24
|
+
|
25
|
+
```
|
26
|
+
$ cd hi
|
27
|
+
$ ufo init --cluster default --image tongueroo/hi
|
28
|
+
Generated starter ufo structure:
|
29
|
+
hi/ufo/task_definitions.rb
|
30
|
+
hi/ufo/templates/web.json.erb
|
31
|
+
hi/ufo/settings.yml # default cluster is saved here
|
32
|
+
```
|
33
|
+
|
34
|
+
It is now a good time to take a look at the generated files at this point.
|
35
|
+
|
36
|
+
### ufo/settings.yml
|
37
|
+
|
38
|
+
`ufo/settings.yml` holds some default configuration settings so you don't have to type out these options every single time.
|
39
|
+
|
40
|
+
```yaml
|
41
|
+
service_cluster:
|
42
|
+
default: my-default-cluster
|
43
|
+
hi-web-prod: hi-cluster
|
44
|
+
image: tongueroo/hi
|
45
|
+
```
|
46
|
+
|
47
|
+
You should adjust the image name if it not already adjusted.
|
48
|
+
|
49
|
+
The `service_cluster` mapping provides a way to set default service to cluster mappings so that you do not have to specify the `--cluster` repeatedly. Example:
|
50
|
+
|
51
|
+
```
|
52
|
+
ufo ship hi-web-prod --cluster hi-cluster
|
53
|
+
ufo ship hi-web-prod # same as above because it is configured in ufo/settings.yml
|
54
|
+
ufo ship hi-web-prod --cluster special-cluster # overrides any setting default fallback.
|
55
|
+
```
|
56
|
+
|
57
|
+
### ufo/task_definitions.rb
|
58
|
+
|
59
|
+
`ufo/task_definitions.rb` holds the task definitions to be generated. They correspond to each service you want deployed. It is written in a DSL. We'll go over a simplifed example:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
task_definition "hi-web-prod" do
|
63
|
+
source "web" # this corresponds to the file in "ufo/templates/web.json.erb"
|
64
|
+
# if source is not set, it will use a default task definition template:
|
65
|
+
# https://github.com/tongueroo/ufo/tree/master/lib/ufo/templates/default.json.erb
|
66
|
+
variables(
|
67
|
+
family: "hi-web-prod",
|
68
|
+
name: "web",
|
69
|
+
container_port: helper.dockerfile_port,
|
70
|
+
command: ["bin/web"]
|
71
|
+
image:helper.full_image_name,
|
72
|
+
cpu: 2,
|
73
|
+
memory_reservation: 128,
|
74
|
+
container_port: helper.dockerfile_port,
|
75
|
+
command: helper.dockerfile_command,
|
76
|
+
environment: [
|
77
|
+
{name: "DATABASE_URL", value: "mysql2://user:pass@domani.com:3306/myapp"},
|
78
|
+
{name: "PORT", value: helper.dockerfile_port.to_s},
|
79
|
+
{name: "SECRET", value: "supersecret"},
|
80
|
+
]
|
81
|
+
)
|
82
|
+
end
|
83
|
+
|
84
|
+
```
|
85
|
+
|
86
|
+
You'll notice a `helper` variable being used. `helper` is a variable that holds some special variables that is available within the ufo DSL. They are optional to use. Here is a list of them:
|
87
|
+
|
88
|
+
* helper.full_image_name - Docker image name to be used when a the docker image is build. This is defined in ufo/settings.yml.
|
89
|
+
* helper.dockerfile_port - Expose port in the Dockerfile. Only supports one exposed port, the first one that is encountered.
|
90
|
+
|
91
|
+
The variables defined within the task_definition block of code are available as instance variables in the corresponding template. Here is the template with the use of the instance variables:
|
92
|
+
|
93
|
+
### ufo/templates/web.json.erb
|
94
|
+
|
95
|
+
```html
|
96
|
+
{
|
97
|
+
"family": "<%= @family %>",
|
98
|
+
"containerDefinitions": [
|
99
|
+
{
|
100
|
+
"name": "<%= @name %>",
|
101
|
+
"image": "<%= @image %>",
|
102
|
+
"cpu": <%= @cpu %>,
|
103
|
+
<% if @memory %>
|
104
|
+
"memory": <%= @memory %>,
|
105
|
+
<% end %>
|
106
|
+
<% if @memory_reservation %>
|
107
|
+
"memoryReservation": <%= @memory_reservation %>,
|
108
|
+
<% end %>
|
109
|
+
<% if @container_port %>
|
110
|
+
"portMappings": [
|
111
|
+
{
|
112
|
+
"containerPort": "<%= @container_port %>",
|
113
|
+
"protocol": "tcp"
|
114
|
+
}
|
115
|
+
],
|
116
|
+
<% end %>
|
117
|
+
"command": <%= @command.to_json %>,
|
118
|
+
<% if @environment %>
|
119
|
+
"environment": <%= @environment.to_json %>,
|
120
|
+
<% end %>
|
121
|
+
"essential": true
|
122
|
+
}
|
123
|
+
]
|
124
|
+
}
|
125
|
+
```
|
126
|
+
|
127
|
+
### Customizing Templates
|
128
|
+
|
129
|
+
If you want to change the template then you can follow the example in the generated ufo files. For example, if you want to create a template for the worker service.
|
130
|
+
|
131
|
+
1. Create a new template under ufo/templates/worker.json.erb.
|
132
|
+
2. Change the source in the `task_definition` using "worker" as the source.
|
133
|
+
3. Add variables.
|
134
|
+
|
135
|
+
### Ship
|
136
|
+
|
137
|
+
Ufo uses the aforementioned files to build task definitions and then ship to them to AWS ECS. To execute the ship process run:
|
138
|
+
|
139
|
+
```bash
|
140
|
+
ufo ship hi-web-prod
|
141
|
+
```
|
142
|
+
|
143
|
+
When you run `ufo ship hi-web-prod`:
|
144
|
+
|
145
|
+
1. It builds the docker image
|
146
|
+
2. Generates a task definition and registers it
|
147
|
+
3. Updates the ECS service to use it.
|
148
|
+
|
149
|
+
If the ECS service hi-web-prod does not yet exist, ufo will create the service for you.
|
150
|
+
|
151
|
+
If the service has a container name web, you'll get prompted to create an ELB and specify a target group arn. The ELB and target group must already exist.
|
152
|
+
|
153
|
+
You can bypass the prompt and specify the target group arn as part of the command. The elb target group can only be associated when the service gets created for the first time. If the service already exists then the `--target-group` parameter just gets ignored and the ECS task simply gets updated.
|
154
|
+
|
155
|
+
|
156
|
+
```bash
|
157
|
+
ufo ship hi-web-prod --target-group=arn:aws:elasticloadbalancing:us-east-1:12345689:targetgroup/hi-web-prod/jdisljflsdkjl
|
158
|
+
```
|
159
|
+
|
160
|
+
### Service and Task Names Convention
|
161
|
+
|
162
|
+
Ufo assumes a convention that service\_name and the task\_name are the same. If you would like to override this convention then you can specify the task name.
|
163
|
+
|
164
|
+
```
|
165
|
+
ufo ship hi-web-prod-1 --task hi-web-prod
|
166
|
+
```
|
167
|
+
|
168
|
+
This means that in the task_definitionintion.rb you will also defined it without the `-1`. For example:
|
169
|
+
|
170
|
+
```ruby
|
171
|
+
task_definition "hi-web-prod" do
|
172
|
+
source "web" # this corresponds to the file in "ufo/templates/web.json.erb"
|
173
|
+
variables(
|
174
|
+
family: "hi-web-prod",
|
175
|
+
....
|
176
|
+
)
|
177
|
+
end
|
178
|
+
|
179
|
+
```
|
180
|
+
|
181
|
+
### Running Tasks in Pieces
|
182
|
+
|
183
|
+
The `ufo ship` command goes few a few stages: building the docker image, registering the task defiintions and updating the ECS service. The CLI exposes each of the steps as separate commands. Here is now you would be able to run each of the steps in pieces.
|
184
|
+
|
185
|
+
Build the docker image first.
|
186
|
+
|
187
|
+
```bash
|
188
|
+
ufo docker build
|
189
|
+
ufo docker build --push # will also push to the docker registry
|
190
|
+
```
|
191
|
+
|
192
|
+
Build the task definitions.
|
193
|
+
|
194
|
+
```bash
|
195
|
+
ufo tasks build
|
196
|
+
ufo tasks register # will register all genreated task definitinos in the ufo/output folder
|
197
|
+
```
|
198
|
+
|
199
|
+
Skips all the build docker phases of a deploy sequence and only update the service with the task definitions.
|
200
|
+
|
201
|
+
```bash
|
202
|
+
ufo ship hi-web-prod --no-docker
|
203
|
+
```
|
204
|
+
Note you use the `--no-docker` option you should make sure you have push a docker image with the previous committed sha code to your docker register. Or else the task will not be able to spin up because the docker image does not exist. You can work around this but just running `--no-docker` with a dirty working tree.
|
205
|
+
|
206
|
+
|
207
|
+
## Automatically Creates the Service
|
208
|
+
|
209
|
+
When running `ufo ship` if the ECS service does not yet exist, it will automatically be created for you.
|
210
|
+
|
211
|
+
## Scale
|
212
|
+
|
213
|
+
There is a convenience wrapper that simple executes `aws ecs update-service --service [SERVICE] ----desired-count [COUNT]`
|
214
|
+
|
215
|
+
```
|
216
|
+
ufo scale hi-web-prod 1
|
217
|
+
```
|
218
|
+
|
219
|
+
### More Help
|
220
|
+
|
221
|
+
```
|
222
|
+
ufo help
|
223
|
+
```
|
224
|
+
## Contributing
|
225
|
+
|
226
|
+
Bug reports and pull requests are welcome on GitHub at [https://github.com/tongueroo/ufo/issues](https://github.com/tongueroo/ufo/issues).
|
227
|
+
|
data/Rakefile
ADDED