dctl_rb 0.3.4 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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"