dctl_rb 0.3.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d0ae33aa0aa3f5d0dc263616ad547a5b41118e44fce672b40f411707e1534304
4
- data.tar.gz: aa01e608aa311a94dd21fd105dd181a9ef05b684ef8acb3616c152972ee1450e
3
+ metadata.gz: cd25c95274d81568271c730fb7162171ee0e8a432ee451c2c9a8ea500ef4aba5
4
+ data.tar.gz: fc162add3502d9741b89eca1e67920da9a7775adfac89ab4b520e2b3422ef7c4
5
5
  SHA512:
6
- metadata.gz: 0f2ba5b3e5f84856e83b1c6890218babb971b1d90e581af430ab7172d16c0f5360c94da7b8e20d2af46817ed9e0244b43ed0c530c58f35a50e84b958a74701d0
7
- data.tar.gz: d1e0225c072033d0fb7aef0586dd0e7803bd4dc8a19eb51e498c38c73afe388931f019e1ae6514f8dcbf6338bb7c51d62744d90ebba566d2faefdde8b364bdc0
6
+ metadata.gz: 199f823503954b1ad893f930c202e6091fb0f5801cde315812826da5607adf38b29403c13ea212243786f6b92b9c08ece7aa925749f746889cfa95f09dc157c6
7
+ data.tar.gz: 155973810386b77f1a5e7654ccaf0a2dcb69153ee946611a7c4702f521320022ee814c0ccc7bec43dba837305e8494e42639dde3bcc2abc5ecb09529191f2bb9
data/.editorconfig ADDED
@@ -0,0 +1,16 @@
1
+ # EditorConfig helps developers define and maintain consistent
2
+ # coding styles between different editors and IDEs
3
+ # editorconfig.org
4
+
5
+ root = true
6
+
7
+ [*]
8
+ end_of_line = lf
9
+ charset = utf-8
10
+ trim_trailing_whitespace = true
11
+ insert_final_newline = true
12
+ indent_style = space
13
+ indent_size = 2
14
+
15
+ [*.{diff,md}]
16
+ trim_trailing_whitespace = false
data/Gemfile.lock CHANGED
@@ -1,10 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- dctl_rb (0.3.4)
4
+ dctl_rb (0.4.0)
5
5
  config (>= 1, < 2)
6
6
  rainbow (>= 2.2, < 3)
7
- thor (>= 0.17.0)
7
+ thor (~> 0.17, >= 0.17.0)
8
8
 
9
9
  GEM
10
10
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -21,7 +21,10 @@ The default environment is `dev`, but you can override this with `--env prod` et
21
21
  * `dctl build`
22
22
  * `dctl push`
23
23
  * `dctl pull`
24
-
24
+ * `dctl create`
25
+ * `dctl rm`
26
+ * `dctl restart`
27
+ * `dctl ps`
25
28
 
26
29
  ### Targeting specific containers
27
30
 
@@ -36,17 +39,21 @@ Most commands also allow you to specify a specific image to target (defaulting t
36
39
 
37
40
  There are also some non-compose commands to make your life easier
38
41
 
39
- * `dctl connect app`
40
- * Start a new shell in a running `app` container.
41
- * `dctl attach app`
42
- * Attach your current TTY to that of the running `app` container.
42
+ * `dctl connect [image]`
43
+ * Start a new shell in a running container.
44
+ * For instance, use `dctl connect app` to open a shell in your running `app` container.
45
+ * `dctl attach [image]`
46
+ * Attach your current TTY to that of a running container.
43
47
  * This is useful if you've put a debugger or something similar and need to talk directly to a running container's current shell (docker-compose eats stdin/stdout/stderr so normally this isn't possible)
44
- * `dctl bash app`
45
- * Spin up a new `app` image and drop you in a shell.
46
- * `dctl recreate app`
48
+ * `dctl bash [image]`
49
+ * Spin up a new container using the given image and drop you in a shell.
50
+ * While `connect` (above) creates a shell in a container which is already running, `bash` creates an entirely new container (and also does not require your stack to already be up).
51
+ * `dctl recreate [image]`
47
52
  * Stops, removes, builds, creates, and starts an image.
48
53
  * Useful if you've made a change to one container but don't want to restart your entire stack to have it reflected.
49
- * Specify `--build false` (or `-b false`) if you don't want the image to be rebuilt.
54
+ * Options:
55
+ * `--build` (`-b`) (default `true`)
56
+ * Whether or not the image in question should be rebuilt before bringing it back up.
50
57
  * `dctl cleanup`
51
58
  * Useful for policing the large numbers of built-but-unused containers which tend to accumulate when using docker.
52
59
  * Removes local images without tags and which are not referenced by other images.
data/dctl_rb.gemspec CHANGED
@@ -33,7 +33,7 @@ Gem::Specification.new do |spec|
33
33
  spec.add_development_dependency "rake", "~> 10.0"
34
34
  spec.add_development_dependency "rspec", "~> 3.0"
35
35
 
36
- spec.add_dependency "thor", ">= 0.17.0"
36
+ spec.add_dependency "thor", "~> 0.17", ">= 0.17.0"
37
37
  spec.add_dependency "config", ">= 1", "< 2"
38
38
  spec.add_dependency "rainbow", ">= 2.2", "< 3"
39
39
  end
data/exe/dctl CHANGED
@@ -12,18 +12,16 @@ module Dctl
12
12
 
13
13
  desc "build", "Build images. Pass image name to build a specific one; otherwise builds all"
14
14
  def build(*images)
15
- load_config!
16
- images = versions.keys if images.empty?
17
- images = Array(images)
15
+ dctl = Dctl::Main.new env: options[:env]
16
+ images = dctl.expand_images *images
18
17
  env = options[:env]
19
18
 
20
19
  puts "Generating build script for #{images.join(", ")}"
21
20
  commands = []
22
21
 
23
22
  images.each do |image|
24
- version = versions[image]
25
- tag = "#{Settings.org}/#{Settings.project}-#{env}-#{image}:#{version}"
26
- dockerfile = "docker/#{env}/#{image}/Dockerfile"
23
+ tag = dctl.image_tag(image)
24
+ dockerfile = dctl.image_dockerfile(image)
27
25
 
28
26
  commands << "#{sudo}docker #{docker_opts} build -f #{dockerfile} -t #{tag} ."
29
27
  end
@@ -33,20 +31,13 @@ module Dctl
33
31
 
34
32
  desc "push", "Upload locally built images to the remote store"
35
33
  def push(*images)
36
- load_config!
37
- images = versions.keys if images.empty?
38
- images = Array(images)
39
- env = options[:env]
40
-
34
+ dctl = Dctl::Main.new env: options[:env]
35
+ images = dctl.expand_images *images
41
36
  push_cmds = []
42
37
 
43
38
  images.each do |image|
44
- version = versions[image]
45
- tag_cmd = "#{sudo}docker tag #{Settings.org}/#{Settings.project}-#{env}-#{image}:#{version} #{Settings.org}/#{Settings.project}-#{env}-#{image}:latest"
46
- puts tag_cmd
47
- `#{tag_cmd}`
48
-
49
- push_cmds << "#{sudo}docker push #{Settings.org}/#{Settings.project}-#{env}-#{image}:#{version}"
39
+ tag = dctl.image_tag(image)
40
+ push_cmds << "#{sudo}docker push #{tag}"
50
41
  end
51
42
 
52
43
  push_cmd = push_cmds.join " && "
@@ -55,16 +46,13 @@ module Dctl
55
46
 
56
47
  desc "pull", "Pull the latest remote images to your local machine"
57
48
  def pull(*images)
58
- load_config!
59
- images = versions.keys if images.empty?
60
- images = Array(images)
61
- env = options[:env]
62
-
49
+ dctl = Dctl::Main.new env: options[:env]
50
+ images = dctl.expand_images *images
63
51
  pull_cmds = []
64
52
 
65
53
  images.each do |image|
66
- version = versions[image]
67
- pull_cmds << "#{sudo}docker pull #{Settings.org}/#{Settings.project}-#{env}-#{image}:#{version}"
54
+ tag = dctl.image_tag(image)
55
+ pull_cmds << "#{sudo}docker pull #{tag}"
68
56
  end
69
57
 
70
58
  pull_cmd = pull_cmds.join " && "
@@ -73,51 +61,51 @@ module Dctl
73
61
 
74
62
  desc "up", "Start your dockerized app server"
75
63
  def up
76
- load_config!
64
+ dctl = Dctl::Main.new env: options[:env]
77
65
 
78
66
  pidfile = "tmp/pids/server.pid"
79
67
  FileUtils.rm pidfile if File.exist? pidfile
80
68
 
81
69
  compose_opts = %w(--remove-orphans)
82
- stream_output "#{sudo}docker-compose -f #{compose_file_path} up #{compose_opts.join(" ")}", exec: true
70
+ stream_output "#{sudo}docker-compose -f #{dctl.compose_file_path} up #{compose_opts.join(" ")}", exec: true
83
71
  end
84
72
 
85
73
  desc "down", "Stop one or many containers"
86
- def down(*args)
87
- load_config!
88
- stream_output "#{sudo}docker-compose -f #{compose_file_path} down #{args.join(" ")}", exec: true
74
+ def down(*images)
75
+ dctl = Dctl::Main.new env: options[:env]
76
+ stream_output "#{sudo}docker-compose -f #{dctl.compose_file_path} down #{images.join(" ")}", exec: true
89
77
  end
90
78
 
91
79
  desc "rm", "Remove one or many containers"
92
80
  option :force, type: :boolean, default: false, aliases: %w(f)
93
- def rm(*args)
94
- load_config!
81
+ def rm(*images)
82
+ dctl = Dctl::Main.new env: options[:env]
95
83
  opts = " --force" if options[:force]
96
- stream_output "#{sudo}docker-compose -f #{compose_file_path} rm#{opts} #{args.join(" ")}", exec: true
84
+ stream_output "#{sudo}docker-compose -f #{dctl.compose_file_path} rm#{opts} #{images.join(" ")}", exec: true
97
85
  end
98
86
 
99
87
  desc "start", "Start one or many containers"
100
- def start(*args)
101
- load_config!
102
- stream_output "#{sudo}docker-compose -f #{compose_file_path} start #{args.join(" ")}", exec: true
88
+ def start(*images)
89
+ dctl = Dctl::Main.new env: options[:env]
90
+ stream_output "#{sudo}docker-compose -f #{dctl.compose_file_path} start #{images.join(" ")}", exec: true
103
91
  end
104
92
 
105
93
  desc "stop", "Stop one or many containers"
106
- def stop(*args)
107
- load_config!
108
- stream_output "#{sudo}docker-compose -f #{compose_file_path} stop #{args.join(" ")}", exec: true
94
+ def stop(*images)
95
+ dctl = Dctl::Main.new env: options[:env]
96
+ stream_output "#{sudo}docker-compose -f #{dctl.compose_file_path} stop #{images.join(" ")}", exec: true
109
97
  end
110
98
 
111
99
  desc "restart", "Restart one or many containers"
112
- def restart(*args)
113
- load_config!
114
- stream_output "#{sudo}docker-compose -f #{compose_file_path} restart #{args.join(" ")}", exec: true
100
+ def restart(*images)
101
+ dctl = Dctl::Main.new env: options[:env]
102
+ stream_output "#{sudo}docker-compose -f #{dctl.compose_file_path} restart #{images.join(" ")}", exec: true
115
103
  end
116
104
 
117
105
  desc "create", "Create one or many containers"
118
- def create(*args)
119
- load_config!
120
- stream_output "#{sudo}docker-compose -f #{compose_file_path} create #{args.join(" ")}", exec: true
106
+ def create(*images)
107
+ dctl = Dctl::Main.new env: options[:env]
108
+ stream_output "#{sudo}docker-compose -f #{dctl.compose_file_path} create #{images.join(" ")}", exec: true
121
109
  end
122
110
 
123
111
  desc "recreate", "Stop, remove, build, create, and start a container"
@@ -133,18 +121,18 @@ module Dctl
133
121
 
134
122
  desc "ps", "List running containers for this environment"
135
123
  def ps
136
- load_config!
137
- stream_output "#{sudo}docker-compose -f #{compose_file_path} ps", exec: true
124
+ dctl = Dctl::Main.new env: options[:env]
125
+ stream_output "#{sudo}docker-compose -f #{dctl.compose_file_path} ps", exec: true
138
126
  end
139
127
 
140
128
  desc "initdb", "Setup initial postgres database"
141
129
  def initdb
142
- load_config!
130
+ dctl = Dctl::Main.new env: options[:env]
143
131
  env = options[:env]
144
132
  local_data_dir = File.expand_path "../tmp/psql-#{env}", __FILE__
145
133
  `#{sudo}rm -r #{local_data_dir}` if File.exists? local_data_dir # todo prompt
146
134
 
147
- cmd = "#{sudo}docker-compose -f #{compose_file_path} run --rm psql /bin/bash -c /etc/initdb.sh"
135
+ cmd = "#{sudo}docker-compose -f #{dtcl.compose_file_path} run --rm psql /bin/bash -c /etc/initdb.sh"
148
136
 
149
137
  stream_output cmd, exec: true
150
138
  end
@@ -163,25 +151,23 @@ module Dctl
163
151
 
164
152
  desc "bash CONTAINER", "Create a new instance of the given image with a bash prompt"
165
153
  def bash(container = "app")
166
- load_config!
167
- cmd = "#{sudo}docker-compose -f #{compose_file_path} run --rm #{container} /bin/bash"
154
+ dctl = Dctl::Main.new env: options[:env]
155
+ cmd = "#{sudo}docker-compose -f #{dctl.compose_file_path} run --rm #{container} /bin/bash"
168
156
 
169
157
  stream_output cmd, exec: true
170
158
  end
171
159
 
172
160
  desc "connect CONTAINER", "Connect to a running container."
173
161
  def connect(image = "app")
174
- load_config!
175
- stream_output "#{sudo}docker-compose -f #{compose_file_path} exec #{image} /bin/bash", exec: true
162
+ dctl = Dctl::Main.new env: options[:env]
163
+ stream_output "#{sudo}docker-compose -f #{dctl.compose_file_path} exec #{image} /bin/bash", exec: true
176
164
  end
177
165
 
178
166
  desc "attach CONTAINER", "Connect to a running container."
179
167
  option :env, type: :string, default: "dev"
180
168
  def attach(image = "app")
181
- load_config!
182
- env = options[:env]
183
- version = versions[image]
184
- image = "#{Settings.org}/#{Settings.project}-#{env}-#{image}:#{version}"
169
+ dctl = Dctl::Main.new env: options[:env]
170
+ tag = dctl.image_tag(image)
185
171
 
186
172
  cmd = "#{sudo}docker ps --filter ancestor=#{image} -aq | head -n1"
187
173
  puts cmd
@@ -216,39 +202,6 @@ module Dctl
216
202
  `uname`.chomp == "Darwin" ? "" : "sudo " # use sudo on linux hosts
217
203
  end
218
204
 
219
- def config_path
220
- path = File.expand_path ".dctl.yaml", Dir.pwd
221
-
222
- unless File.exist? path
223
- error = "Could not find config file at #{path}"
224
- puts Rainbow(error).red
225
- exit 1
226
- end
227
-
228
- path
229
- end
230
-
231
- def check_settings!
232
- required_keys = %w(
233
- org
234
- project
235
- )
236
-
237
- required_keys.each do |key|
238
- unless Settings.send key
239
- error = "Config is missing required key '#{key}'. Please add it " \
240
- "to #{config_path} and try again."
241
- error += "\n\nFor more info, see https://github.com/jutonz/dctl#required-keys"
242
- puts Rainbow(error).red
243
- exit 1
244
- end
245
- end
246
- end
247
-
248
- def load_config!
249
- Config.load_and_set_settings(config_path)
250
- check_settings!
251
- end
252
205
 
253
206
  def docker_opts
254
207
  return "" unless ENV["JENKINS"]
@@ -260,33 +213,6 @@ module Dctl
260
213
 
261
214
  opts
262
215
  end
263
-
264
- def versions(env: options[:env])
265
- @versions ||= begin
266
- compose_file = compose_file_path env: env
267
- parsed = YAML.load_file compose_file
268
- images = parsed["services"].keys
269
- version_map = {}
270
-
271
- images.each do |image|
272
- version_map[image] = parsed["services"][image]["image"].split(":").last
273
- end
274
-
275
- version_map
276
- end
277
- end
278
-
279
- def compose_file_path(env: options[:env])
280
- path = File.expand_path "docker/#{env}/docker-compose.yml"
281
-
282
- unless File.exist? path
283
- err = "There is no docker compose file for env #{env} (I expected to find it at #{path})"
284
- puts Rainbow(err).red
285
- exit 1
286
- end
287
-
288
- path
289
- end
290
216
  end
291
217
  end
292
218
  end
data/lib/dctl/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Dctl
2
- VERSION = "0.3.4"
2
+ VERSION = "0.4.0"
3
3
  end
data/lib/dctl.rb CHANGED
@@ -1,5 +1,118 @@
1
+ require "rainbow"
1
2
  require "dctl/version"
3
+ require "config"
2
4
 
3
5
  module Dctl
4
- # Your code goes here...
6
+ class Main
7
+ attr_reader :env, :settings
8
+
9
+ def initialize(env: "dev")
10
+ @env = env
11
+ load_config!
12
+ end
13
+
14
+ ##
15
+ # Generate the full tag for the given image, concatenating the org,
16
+ # project, env, image name, and version.
17
+ #
18
+ # @example
19
+ # image_tag("app") # => jutonz/dctl-dev-app:1
20
+ def image_tag(image)
21
+ org = settings.org
22
+ project = settings.project
23
+ version = versions[image]
24
+
25
+ "#{org}/#{project}-#{env}-#{image}:#{version}"
26
+ end
27
+
28
+ ##
29
+ # Returns the path to the given image's data directory (which includes at
30
+ # minimum the Dockerfile, plus any other relevant files the user may have
31
+ # placed there).
32
+ def image_dir(image)
33
+ relative = File.join "docker", env, image
34
+ File.expand_path relative, Dir.pwd
35
+ end
36
+
37
+ def image_dockerfile(image)
38
+ File.expand_path "Dockerfile", image_dir(image)
39
+ end
40
+
41
+ def expand_images(*images)
42
+ images = versions.keys if images.empty?
43
+ images = Array(images)
44
+ end
45
+
46
+ ##
47
+ # Returns the path to the .dctl.yml file for the current project
48
+ def config_path
49
+ path = File.expand_path ".dctl.yml", Dir.pwd
50
+
51
+ unless File.exist? path
52
+ error = "Could not find config file at #{path}"
53
+ puts Rainbow(error).red
54
+ exit 1
55
+ end
56
+
57
+ path
58
+ end
59
+
60
+ def versions
61
+ @versions ||= begin
62
+ images = parsed_compose_file["services"].keys
63
+ version_map = {}
64
+
65
+ images.each do |image|
66
+ version_map[image] = parsed_compose_file["services"][image]["image"].split(":").last
67
+ end
68
+
69
+ version_map
70
+ end
71
+ end
72
+
73
+ def parsed_compose_file
74
+ @parsed_compose_file ||= YAML.load_file compose_file_path
75
+ end
76
+
77
+ ##
78
+ # Ensure the current project's .dctl.yml contains all the requisite keys.
79
+ def check_settings!
80
+ required_keys = %w(
81
+ org
82
+ project
83
+ )
84
+
85
+ required_keys.each do |key|
86
+ unless Settings.send key
87
+ error = "Config is missing required key '#{key}'. Please add it " \
88
+ "to #{config_path} and try again."
89
+ error += "\n\nFor more info, see https://github.com/jutonz/dctl_rb#required-keys"
90
+ puts Rainbow(error).red
91
+ exit 1
92
+ end
93
+ end
94
+ end
95
+
96
+ ##
97
+ # Load the current project's config file, complaining if it does not exist
98
+ # or is malformed.
99
+ def load_config!
100
+ Config.load_and_set_settings(config_path)
101
+ check_settings!
102
+
103
+ @settings = Settings
104
+ end
105
+
106
+ def compose_file_path
107
+ path = File.expand_path "docker/#{env}/docker-compose.yml"
108
+
109
+ unless File.exist? path
110
+ err = "There is no docker compose file for env #{env} (I expected to find it at #{path})"
111
+ puts Rainbow(err).red
112
+ exit 1
113
+ end
114
+
115
+ path
116
+ end
117
+ end
5
118
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dctl_rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.4
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Toniazzo
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-11-10 00:00:00.000000000 Z
11
+ date: 2017-11-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -56,6 +56,9 @@ dependencies:
56
56
  name: thor
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.17'
59
62
  - - ">="
60
63
  - !ruby/object:Gem::Version
61
64
  version: 0.17.0
@@ -63,6 +66,9 @@ dependencies:
63
66
  prerelease: false
64
67
  version_requirements: !ruby/object:Gem::Requirement
65
68
  requirements:
69
+ - - "~>"
70
+ - !ruby/object:Gem::Version
71
+ version: '0.17'
66
72
  - - ">="
67
73
  - !ruby/object:Gem::Version
68
74
  version: 0.17.0
@@ -114,6 +120,7 @@ executables:
114
120
  extensions: []
115
121
  extra_rdoc_files: []
116
122
  files:
123
+ - ".editorconfig"
117
124
  - ".gitignore"
118
125
  - ".rspec"
119
126
  - ".travis.yml"