ufo 0.0.6 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +10 -8
- data/README.md +127 -83
- data/lib/starter_project/{.env.prod → .env} +0 -0
- data/lib/starter_project/bin/deploy +1 -1
- data/lib/starter_project/ufo/task_definitions.rb +1 -1
- data/lib/ufo/dsl.rb +1 -1
- data/lib/ufo/tasks_builder.rb +1 -1
- data/lib/ufo/version.rb +1 -1
- data/ufo.gemspec +2 -2
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7789e9644d6d70e458722decdc1212590dcc2941
|
4
|
+
data.tar.gz: 686742062dc6728297aecad1a4fb89583ba24b2a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4580b708e976c77128454ff540cdf4751bb9634dbcd9813b31fccdd1e757805aef1592fd2b8804827c0e540de70f0e9715fb1bed6870db7f3ad4e4c156529d9f
|
7
|
+
data.tar.gz: 3137da3783c02fcfeb770dc95bc2000f0bc4b947aa96c9c0f115c684d7b56a050d4479c67129ba834a8eb350beceec1089f715bf9f4a04eefa111c1243f70b22
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ufo (0.0
|
4
|
+
ufo (0.1.0)
|
5
5
|
aws-sdk
|
6
6
|
byebug
|
7
7
|
colorize
|
@@ -22,12 +22,14 @@ GEM
|
|
22
22
|
multi_json (~> 1.3)
|
23
23
|
thread_safe (~> 0.1)
|
24
24
|
tzinfo (~> 0.3.37)
|
25
|
-
aws-sdk (2.6.
|
26
|
-
aws-sdk-resources (= 2.6.
|
27
|
-
aws-sdk-core (2.6.
|
25
|
+
aws-sdk (2.6.29)
|
26
|
+
aws-sdk-resources (= 2.6.29)
|
27
|
+
aws-sdk-core (2.6.29)
|
28
|
+
aws-sigv4 (~> 1.0)
|
28
29
|
jmespath (~> 1.0)
|
29
|
-
aws-sdk-resources (2.6.
|
30
|
-
aws-sdk-core (= 2.6.
|
30
|
+
aws-sdk-resources (2.6.29)
|
31
|
+
aws-sdk-core (= 2.6.29)
|
32
|
+
aws-sigv4 (1.0.0)
|
31
33
|
builder (3.1.4)
|
32
34
|
byebug (9.0.6)
|
33
35
|
codeclimate-test-reporter (0.6.0)
|
@@ -110,7 +112,7 @@ GEM
|
|
110
112
|
i18n
|
111
113
|
thor (0.19.1)
|
112
114
|
thread_safe (0.3.5)
|
113
|
-
tzinfo (0.3.
|
115
|
+
tzinfo (0.3.52)
|
114
116
|
|
115
117
|
PLATFORMS
|
116
118
|
ruby
|
@@ -125,4 +127,4 @@ DEPENDENCIES
|
|
125
127
|
ufo!
|
126
128
|
|
127
129
|
BUNDLED WITH
|
128
|
-
1.13.
|
130
|
+
1.13.6
|
data/README.md
CHANGED
@@ -1,98 +1,71 @@
|
|
1
|
-
# Ufo
|
1
|
+
# Ufo - Build Docker Containers and Ship Them to AWS ECS
|
2
2
|
|
3
|
-
|
3
|
+
## Quick Introduction
|
4
4
|
|
5
|
-
|
5
|
+
Ufo is a simple tool that makes building and shipping Docker containers to [AWS ECS](https://aws.amazon.com/ecs/) super easy.
|
6
6
|
|
7
7
|
A summary of steps `ufo ship` takes:
|
8
8
|
|
9
|
-
1. builds a docker image
|
10
|
-
2. generates the
|
11
|
-
3.
|
9
|
+
1. builds a docker image.
|
10
|
+
2. generates and registers the ECS template definition.
|
11
|
+
3. deploys the ECS template definition to the specified service.
|
12
|
+
|
13
|
+
Ufo deploys a task definition that is created via a template generator which is fully controllable.
|
14
|
+
|
12
15
|
|
13
16
|
## Installation
|
14
17
|
|
15
18
|
$ gem install ufo
|
16
19
|
|
17
|
-
You will need a working version of docker installed
|
20
|
+
You will need a working version of docker installed as ufo calls the docker command.
|
18
21
|
|
19
22
|
## Usage
|
20
23
|
|
21
|
-
|
24
|
+
When using ufo if the ECS service does not yet exist, it will automatically be created for you. If you are relying on this tool to create the cluster, you still need to associate ECS Container Instances to the cluster yourself.
|
22
25
|
|
23
26
|
First initialize ufo files within your project. Let's say you have an `hi` app.
|
24
27
|
|
25
28
|
```
|
29
|
+
$ git clone https://github.com/tongueroo/hi
|
26
30
|
$ cd hi
|
27
|
-
$ ufo init --cluster
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
31
|
+
$ ufo init --app hi --cluster stag --image tongueroo/hi
|
32
|
+
Setting up ufo project...
|
33
|
+
created: ./bin/deploy
|
34
|
+
exists: ./Dockerfile
|
35
|
+
created: ./ufo/settings.yml
|
36
|
+
created: ./ufo/task_definitions.rb
|
37
|
+
created: ./ufo/templates/main.json.erb
|
38
|
+
created: ./.env
|
39
|
+
Starter ufo files created.
|
40
|
+
$
|
32
41
|
```
|
33
42
|
|
34
|
-
|
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.
|
43
|
+
Take a look at the `ufo/settings.yml` file to see that it holds some default configuration settings so you don't have to type out these options every single time.
|
39
44
|
|
40
45
|
```yaml
|
41
|
-
service_cluster:
|
42
|
-
default: my-default-cluster
|
43
|
-
hi-web-prod: hi-cluster
|
44
46
|
image: tongueroo/hi
|
47
|
+
service_cluster:
|
48
|
+
default: stag # default cluster
|
49
|
+
hi-web: stag
|
50
|
+
hi-clock: stag
|
51
|
+
hi-worker: stag
|
45
52
|
```
|
46
53
|
|
47
|
-
|
54
|
+
The `image` value is the name that ufo will use for the Docker image name.
|
48
55
|
|
49
56
|
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
57
|
|
51
58
|
```
|
52
|
-
ufo ship hi-web
|
53
|
-
ufo ship hi-web
|
54
|
-
ufo ship hi-web
|
59
|
+
ufo ship hi-web --cluster hi-cluster
|
60
|
+
ufo ship hi-web # same as above because it is configured in ufo/settings.yml
|
61
|
+
ufo ship hi-web --cluster special-cluster # overrides any setting default fallback.
|
55
62
|
```
|
56
63
|
|
57
|
-
|
64
|
+
## Task Definition ERB Template and DSL Generator
|
58
65
|
|
59
|
-
|
66
|
+
Ufo task definitions are is written in a template generator DSL to provide full control of the task definition that gets uploaded for each service. We'll go over a simple example. Here is the ERB template for `ufo/templates/main.json.erb`:
|
60
67
|
|
61
|
-
```
|
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
|
68
|
+
```json
|
96
69
|
{
|
97
70
|
"family": "<%= @family %>",
|
98
71
|
"containerDefinitions": [
|
@@ -118,12 +91,48 @@ The variables defined within the task_definition block of code are available as
|
|
118
91
|
<% if @environment %>
|
119
92
|
"environment": <%= @environment.to_json %>,
|
120
93
|
<% end %>
|
94
|
+
<% if @awslogs_group %>
|
95
|
+
"logConfiguration": {
|
96
|
+
"logDriver": "awslogs",
|
97
|
+
"options": {
|
98
|
+
"awslogs-group": "<%= @awslogs_group %>",
|
99
|
+
"awslogs-region": "<%= @awslogs_region || 'us-east-1' %>",
|
100
|
+
"awslogs-stream-prefix": "<%= @awslogs_stream_prefix %>"
|
101
|
+
}
|
102
|
+
},
|
103
|
+
<% end %>
|
121
104
|
"essential": true
|
122
105
|
}
|
123
106
|
]
|
124
107
|
}
|
125
108
|
```
|
126
109
|
|
110
|
+
The instance variable values are specified in `ufo/task_definitions.rb`. Here's the
|
111
|
+
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
task_definition "hi-web" do
|
115
|
+
source "main" # will use ufo/templates/main.json.erb
|
116
|
+
variables(
|
117
|
+
family: task_definition_name,
|
118
|
+
# image: tongueroo/hi:ufo-[timestamp]=[sha]
|
119
|
+
image: helper.full_image_name,
|
120
|
+
environment: env_file('.env.prod')
|
121
|
+
name: "web",
|
122
|
+
container_port: helper.dockerfile_port,
|
123
|
+
command: ["bin/web"]
|
124
|
+
)
|
125
|
+
end
|
126
|
+
```
|
127
|
+
|
128
|
+
As you can see above, the task\_definitions.rb file has some special variables and helper methods available. These helper methods provide useful contextual information about the project. For example, one of the variable provides the exposed port in the Dockerfile of the project. Here is a list of the important ones:
|
129
|
+
|
130
|
+
* **helper.full\_image\_name** — The full docker image name that ufo builds. The “base” portion of the docker image name is defined in ufo/settings.yml. For example, the base portion is "tongueroo/hi" and the full image name is tongueroo/hi:ufo-[timestamp]-[sha]. So the base does not include the Docker tag and the full image name does include the tag.
|
131
|
+
* **helper.dockerfile\_port** — Exposed port extracted from the Dockerfile of the project.
|
132
|
+
* **env_file** — This method takes an .env file which contains a simple key value list of environment variables and converts the list to the proper task definition json format.
|
133
|
+
|
134
|
+
The 2 classes which provide these special helper methods are in [ufo/dsl.rb](https://github.com/tongueroo/ufo/blob/master/lib/ufo/dsl.rb) and [ufo/dsl/helper.rb](https://github.com/tongueroo/ufo/blob/master/lib/ufo/dsl/helper.rb). Refer to these classes for the full list of the special variables and methods.
|
135
|
+
|
127
136
|
### Customizing Templates
|
128
137
|
|
129
138
|
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.
|
@@ -132,46 +141,68 @@ If you want to change the template then you can follow the example in the genera
|
|
132
141
|
2. Change the source in the `task_definition` using "worker" as the source.
|
133
142
|
3. Add variables.
|
134
143
|
|
135
|
-
###
|
144
|
+
### ufo ship
|
136
145
|
|
137
146
|
Ufo uses the aforementioned files to build task definitions and then ship to them to AWS ECS. To execute the ship process run:
|
138
147
|
|
139
148
|
```bash
|
140
|
-
ufo ship hi-web
|
149
|
+
ufo ship hi-web --cluster stag
|
141
150
|
```
|
142
151
|
|
143
|
-
|
152
|
+
Note, if you have configured `ufo/settings.yml` to map hi-web to the stag cluster using the service_cluster option the command becomes simply:
|
144
153
|
|
145
|
-
|
146
|
-
|
154
|
+
```bash
|
155
|
+
ufo ship hi-web
|
156
|
+
```
|
157
|
+
|
158
|
+
When you run `ufo ship hi-web`:
|
159
|
+
|
160
|
+
1. It builds the docker image.
|
161
|
+
2. Generates a task definition and registers it.
|
147
162
|
3. Updates the ECS service to use it.
|
148
163
|
|
149
|
-
If the ECS service hi-web
|
164
|
+
If the ECS service hi-web does not yet exist, ufo will create the service for you.
|
150
165
|
|
151
166
|
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
167
|
|
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.
|
168
|
+
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. Example:
|
169
|
+
|
170
|
+
|
171
|
+
```bash
|
172
|
+
ufo ship hi-web --target-group=arn:aws:elasticloadbalancing:us-east-1:12345689:targetgroup/hi-web/jdisljflsdkjl
|
173
|
+
```
|
174
|
+
|
175
|
+
### Shipping Multiple Services with bin/deploy
|
154
176
|
|
177
|
+
A common pattern is to have 3 processes: web, worker, and clock. This is very common in rails applcations. The web process handles web traffic, the worker process handles background job processing that would be too slow and potentially block web requests, and a clock process is typically used to schedule recurring jobs. These processes use the same codebase, or same docker image, but have slightly different run time settings. For example, the docker run command for a web process could be [puma](http://puma.io/) and the command for a worker process could be [sidekiq](http://sidekiq.org/). Environment variables are sometimes different also. The important key is that the same docker image is used for all 3 services but the task definition for each service is different.
|
178
|
+
|
179
|
+
This is easily accomplished with the `bin/deploy` wrapper script that the `ufo init` command initially generates. The starter script example shows you how you can use ufo to generate one docker image and use the same image to deploy to all 3 services. Here is an example `bin/deploy` script:
|
155
180
|
|
156
181
|
```bash
|
157
|
-
|
182
|
+
#!/bin/bash -xe
|
183
|
+
|
184
|
+
ufo ship hi-worker --cluster stag --no-wait
|
185
|
+
ufo ship hi-clock --cluster stag --no-wait --no-docker
|
186
|
+
ufo ship hi-web --cluster stag --no-docker
|
158
187
|
```
|
159
188
|
|
189
|
+
The first `ufo ship hi-worker` command build and ships docker image to ECS, but the following two `ufo ship` commands use the `--no-docker` flag to skip the `docker build` step. `ufo ship` will use the last built docker image as the image to be shipped. For those curious, this is stored in `ufo/docker_image_name_ufo.txt`.
|
190
|
+
|
160
191
|
### Service and Task Names Convention
|
161
192
|
|
162
193
|
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
194
|
|
164
195
|
```
|
165
|
-
ufo ship hi-web
|
196
|
+
ufo ship hi-web --task my-task
|
166
197
|
```
|
167
198
|
|
168
|
-
This means that in the
|
199
|
+
This means that in the task_definition.rb you will also defined it with `my-task`. For example:
|
169
200
|
|
170
201
|
```ruby
|
171
|
-
task_definition "
|
202
|
+
task_definition "my-task" do
|
172
203
|
source "web" # this corresponds to the file in "ufo/templates/web.json.erb"
|
173
204
|
variables(
|
174
|
-
family: "
|
205
|
+
family: "my-task",
|
175
206
|
....
|
176
207
|
)
|
177
208
|
end
|
@@ -180,7 +211,7 @@ end
|
|
180
211
|
|
181
212
|
### Running Tasks in Pieces
|
182
213
|
|
183
|
-
The `ufo ship` command goes
|
214
|
+
The `ufo ship` command goes through 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
215
|
|
185
216
|
Build the docker image first.
|
186
217
|
|
@@ -199,21 +230,35 @@ ufo tasks register # will register all genreated task definitinos in the ufo/out
|
|
199
230
|
Skips all the build docker phases of a deploy sequence and only update the service with the task definitions.
|
200
231
|
|
201
232
|
```bash
|
202
|
-
ufo ship hi-web
|
233
|
+
ufo ship hi-web --no-docker
|
203
234
|
```
|
204
|
-
Note you use the `--no-docker` option you should
|
235
|
+
Note if you use the `--no-docker` option you should ensure that you have already push a docker image to your docker register. Or else the task will not be able to spin up because the docker image does not exist. I recommend that you normally use `ufo ship` most of the time.
|
236
|
+
|
205
237
|
|
238
|
+
## Automated Docker Images Clean Up
|
206
239
|
|
207
|
-
|
240
|
+
Ufo can be configured to automatically clean old images from the ECR registry after the deploy completes. I normally set `~/.ufo/settings.yml` like so:
|
208
241
|
|
209
|
-
|
242
|
+
```yaml
|
243
|
+
ecr_keep: 3
|
244
|
+
```
|
245
|
+
|
246
|
+
Automated Docker images clean up only works if you are using ECR registry.
|
210
247
|
|
211
248
|
## Scale
|
212
249
|
|
213
|
-
There is a convenience wrapper that simple executes `aws ecs update-service --service [SERVICE]
|
250
|
+
There is a convenience wrapper that simple executes `aws ecs update-service --service [SERVICE] --desired-count [COUNT]`
|
214
251
|
|
215
252
|
```
|
216
|
-
ufo scale hi-web
|
253
|
+
ufo scale hi-web 1
|
254
|
+
```
|
255
|
+
|
256
|
+
## Destroy
|
257
|
+
|
258
|
+
To scale down the service and destroy it:
|
259
|
+
|
260
|
+
```
|
261
|
+
ufo destroy hi-web
|
217
262
|
```
|
218
263
|
|
219
264
|
### More Help
|
@@ -223,5 +268,4 @@ ufo help
|
|
223
268
|
```
|
224
269
|
## Contributing
|
225
270
|
|
226
|
-
Bug reports and pull requests are welcome on GitHub at [https://github.com/tongueroo/ufo/issues](https://github.com/tongueroo/ufo/issues).
|
227
|
-
|
271
|
+
Bug reports and pull requests are welcome on GitHub at [https://github.com/tongueroo/ufo/issues](https://github.com/tongueroo/ufo/issues).
|
File without changes
|
@@ -9,4 +9,4 @@ ufo ship <%= @app %>-clock --cluster <%= @cluster %> --no-wait
|
|
9
9
|
ufo ship <%= @app %>-worker --cluster <%= @cluster %> --no-wait --no-docker
|
10
10
|
# The final service will wait for the deploy to finish. Please specify an
|
11
11
|
# Application Load Balancer if creating the service for the first time.
|
12
|
-
ufo ship <%= @app %>-web --cluster <%= @cluster %> --no-docker
|
12
|
+
ufo ship <%= @app %>-web --cluster <%= @cluster %> --no-docker
|
data/lib/ufo/dsl.rb
CHANGED
data/lib/ufo/tasks_builder.rb
CHANGED
@@ -10,7 +10,7 @@ module Ufo
|
|
10
10
|
def build
|
11
11
|
puts "Building Task Definitions...".green unless @options[:mute]
|
12
12
|
check_templates_definitions_path
|
13
|
-
dsl = DSL.new(template_definitions_path, @options.merge(quiet:
|
13
|
+
dsl = DSL.new(template_definitions_path, @options.merge(quiet: false, mute: true))
|
14
14
|
dsl.run
|
15
15
|
puts "Task Definitions built in ufo/output." unless @options[:mute]
|
16
16
|
end
|
data/lib/ufo/version.rb
CHANGED
data/ufo.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Ufo::VERSION
|
9
9
|
spec.authors = ["Tung Nguyen"]
|
10
10
|
spec.email = ["tongueroo@gmail.com"]
|
11
|
-
spec.description = %q{Build
|
12
|
-
spec.summary = %q{Build
|
11
|
+
spec.description = %q{Build Docker Containers and Ship Them to AWS ECS}
|
12
|
+
spec.summary = %q{Build Docker Containers and Ship Them to AWS ECS}
|
13
13
|
spec.homepage = "https://github.com/tongueroo/ufo"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ufo
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tung Nguyen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-12-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -178,7 +178,7 @@ dependencies:
|
|
178
178
|
- - ">="
|
179
179
|
- !ruby/object:Gem::Version
|
180
180
|
version: '0'
|
181
|
-
description: Build
|
181
|
+
description: Build Docker Containers and Ship Them to AWS ECS
|
182
182
|
email:
|
183
183
|
- tongueroo@gmail.com
|
184
184
|
executables:
|
@@ -196,7 +196,7 @@ files:
|
|
196
196
|
- README.md
|
197
197
|
- Rakefile
|
198
198
|
- bin/ufo
|
199
|
-
- lib/starter_project/.env
|
199
|
+
- lib/starter_project/.env
|
200
200
|
- lib/starter_project/Dockerfile
|
201
201
|
- lib/starter_project/bin/deploy
|
202
202
|
- lib/starter_project/ufo/settings.yml
|
@@ -257,7 +257,7 @@ rubyforge_project:
|
|
257
257
|
rubygems_version: 2.5.2
|
258
258
|
signing_key:
|
259
259
|
specification_version: 4
|
260
|
-
summary: Build
|
260
|
+
summary: Build Docker Containers and Ship Them to AWS ECS
|
261
261
|
test_files:
|
262
262
|
- spec/fixtures/home_existing/.docker/config.json
|
263
263
|
- spec/lib/cli_spec.rb
|