ufo 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +5 -0
  3. data/.rspec +3 -0
  4. data/CHANGELOG.md +12 -0
  5. data/Gemfile +6 -0
  6. data/Gemfile.lock +128 -0
  7. data/Guardfile +12 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +227 -0
  10. data/Rakefile +6 -0
  11. data/bin/ufo +10 -0
  12. data/lib/starter_project/.env.prod +3 -0
  13. data/lib/starter_project/Dockerfile +20 -0
  14. data/lib/starter_project/bin/deploy +12 -0
  15. data/lib/starter_project/ufo/settings.yml +7 -0
  16. data/lib/starter_project/ufo/task_definitions.rb +44 -0
  17. data/lib/starter_project/ufo/templates/main.json.erb +39 -0
  18. data/lib/ufo.rb +26 -0
  19. data/lib/ufo/aws_services.rb +21 -0
  20. data/lib/ufo/cli.rb +136 -0
  21. data/lib/ufo/cli/help.rb +164 -0
  22. data/lib/ufo/defaults.rb +46 -0
  23. data/lib/ufo/destroy.rb +60 -0
  24. data/lib/ufo/docker_builder.rb +120 -0
  25. data/lib/ufo/docker_cleaner.rb +52 -0
  26. data/lib/ufo/dockerfile_updater.rb +42 -0
  27. data/lib/ufo/dsl.rb +93 -0
  28. data/lib/ufo/dsl/helper.rb +47 -0
  29. data/lib/ufo/dsl/outputter.rb +40 -0
  30. data/lib/ufo/dsl/task_definition.rb +65 -0
  31. data/lib/ufo/ecr_auth.rb +35 -0
  32. data/lib/ufo/ecr_cleaner.rb +66 -0
  33. data/lib/ufo/execute.rb +19 -0
  34. data/lib/ufo/init.rb +83 -0
  35. data/lib/ufo/pretty_time.rb +14 -0
  36. data/lib/ufo/scale.rb +34 -0
  37. data/lib/ufo/settings.rb +33 -0
  38. data/lib/ufo/ship.rb +436 -0
  39. data/lib/ufo/tasks_builder.rb +30 -0
  40. data/lib/ufo/tasks_register.rb +51 -0
  41. data/lib/ufo/templates/default.json.erb +39 -0
  42. data/lib/ufo/version.rb +3 -0
  43. data/spec/fixtures/home_existing/.docker/config.json +10 -0
  44. data/spec/lib/cli_spec.rb +50 -0
  45. data/spec/lib/ecr_auth_spec.rb +39 -0
  46. data/spec/lib/ecr_cleaner_spec.rb +32 -0
  47. data/spec/lib/ship_spec.rb +77 -0
  48. data/spec/spec_helper.rb +28 -0
  49. data/ufo.gemspec +34 -0
  50. 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
@@ -0,0 +1,5 @@
1
+ /ufo/output
2
+ /ufo/docker_full_image_name.txt
3
+ /spec/fixtures/hi
4
+ /spec/fixtures/home
5
+ /pkg
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require spec_helper
3
+ --format documentation
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
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ufo.gemspec
4
+ gemspec
5
+
6
+ gem "codeclimate-test-reporter", group: :test, require: nil
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
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ task :default => :spec
5
+
6
+ RSpec::Core::RakeTask.new
data/bin/ufo ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+
5
+ $:.unshift(File.expand_path('../../lib', __FILE__))
6
+ puts File.expand_path('../../lib', __FILE__)
7
+ require 'ufo'
8
+ require 'ufo/cli'
9
+
10
+ Ufo::CLI.start(ARGV)