rat_deployer 0.4.0 → 0.5.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
  SHA1:
3
- metadata.gz: 9434ec7c84475197340d979cd8cd297eeed41802
4
- data.tar.gz: 9168a21f79a69cb597c61b703b3ec1ede5d65026
3
+ metadata.gz: d8370c118d92b2f06d327225481cb3d592a11167
4
+ data.tar.gz: a03cf3b020a9d3e38d99c6f1fa3adf56aa078e0d
5
5
  SHA512:
6
- metadata.gz: 8f62a6495fe7e3fa55c7a958c1bcaf5b39c2355cb1278236abdf51ee0bcd71e4306b572b5f5ef1ad20f1714dbdf448ed2273e11b9673610f843eaac4c737cbb3
7
- data.tar.gz: 9b1870d24db2c922e4556d260f129363e3a5385a0f4ca8b7706a11b0b9cf18e14217d7a6f31ef0262f994347168141a342b2dfc032bf2c2b824499a017987d1f
6
+ metadata.gz: e6626360686e73f7d236290cd3e842748b6d4b64f41afba11f0d4c8fb0125d71b76a895be6156b42c52c8b04db37d3f3e147c1fe7ccdbad94cbe031f1df63963
7
+ data.tar.gz: 7a2f2e575bb63d46e7eb7a074fb14e43e4f13f909e2fb0015030d9329e56e10b99f06f7c776c39fdab1a1ead62e972916053a073f7f6dc3d07ba1f07da47ed08
@@ -1,68 +1,88 @@
1
1
  require 'thor'
2
2
  require 'fileutils'
3
+ require 'active_support/core_ext/string/strip'
3
4
 
4
5
  require 'rat_deployer/command'
5
6
  require 'rat_deployer/notifier'
6
7
 
7
8
  module RatDeployer
9
+ # The main Thor subclass
8
10
  class Cli < Thor
9
11
  include RatDeployer::Command
10
12
 
11
- desc "deploy", "deploys current environment"
13
+ desc 'deploy', 'deploys current environment'
12
14
  def deploy(*services)
13
15
  RatDeployer::Notifier.notify_deploy_start
14
-
15
- if services.any?
16
- services_str = services.join(' ')
17
- compose("pull #{services_str}")
18
- compose("up -d --no-deps --force-recreate #{services_str}")
19
- else
20
- compose('pull')
21
- compose('up -d')
22
- end
23
-
16
+ do_deploy(*services)
24
17
  RatDeployer::Notifier.notify_deploy_end
25
- rescue Exception => e
26
- RatDeployer::Notifier.notify <<-STR
27
- Failed deploy on #{ENV.fetch('RAT_ENV')}"
28
- Reason:
29
- #{e.message}
18
+ rescue StandardError => e
19
+ RatDeployer::Notifier.notify <<-STR.strip_heredoc
20
+ Failed deploy on #{RatDeployer::Config.env}
21
+ Reason:
22
+ #{e.message}
30
23
  STR
31
24
  raise e
32
25
  end
33
26
 
34
- desc "compose ARGS...", "runs docker-compose command with default flags"
27
+ desc 'compose ARGS...', 'runs docker-compose command with default flags'
35
28
  def compose(cmd, *cmd_flags, silent: false)
36
- env = RatDeployer::Config.env
37
- project_name = RatDeployer::Config.all.fetch('project_name')
29
+ run(
30
+ [
31
+ 'docker-compose',
32
+ compose_flags,
33
+ cmd,
34
+ cmd_flags
35
+ ].flatten.join(' '),
36
+ silent: silent
37
+ )
38
+ .fetch(:output)
39
+ end
38
40
 
39
- flags = [
40
- "-f config/default.yml",
41
- "-f config/#{env}.yml",
42
- "-p #{project_name}_#{env}"
43
- ]
41
+ desc 'docker ARGS...', 'runs docker command with default flags'
42
+ def docker(cmd, *cmd_flags)
43
+ flags = []
44
44
 
45
45
  if RatDeployer::Config.remote
46
46
  flags.unshift(RatDeployer::Config.remote_machine_flags)
47
47
  end
48
48
 
49
- cmd = run "docker-compose #{flags.join(' ')} #{cmd} #{cmd_flags.join(" ")}", silent: silent
49
+ cmd = run "docker #{flags.join(' ')} #{cmd} #{cmd_flags.join(' ')}"
50
50
  cmd.fetch(:output)
51
51
  end
52
52
 
53
- desc "docker ARGS...", "runs docker command with default flags"
54
- def docker(cmd, *cmd_flags)
53
+ private
54
+
55
+ def do_deploy(*services)
56
+ if services.any?
57
+ services_str = services.join(' ')
58
+ compose("pull #{services_str}")
59
+ compose("up -d --no-deps --force-recreate #{services_str}")
60
+ else
61
+ compose('pull')
62
+ compose('up -d')
63
+ end
64
+ end
65
+
66
+ def compose_flags
55
67
  env = RatDeployer::Config.env
56
68
  project_name = RatDeployer::Config.all.fetch('project_name')
57
69
 
58
- flags = []
70
+ config_files =
71
+ RatDeployer::Config.for_env['config_files'] || %W[
72
+ config/default.yml
73
+ config/#{env}.yml
74
+ ]
75
+
76
+ flags = [
77
+ config_files.map { |cf| "-f #{cf}" },
78
+ "-p #{project_name}_#{env}"
79
+ ]
59
80
 
60
81
  if RatDeployer::Config.remote
61
82
  flags.unshift(RatDeployer::Config.remote_machine_flags)
62
83
  end
63
84
 
64
- cmd = run "docker #{flags.join(' ')} #{cmd} #{cmd_flags.join(" ")}"
65
- cmd.fetch(:output)
85
+ flags
66
86
  end
67
87
  end
68
88
  end
@@ -1,13 +1,16 @@
1
- require "colorize"
1
+ require 'colorize'
2
2
  require 'highline/import'
3
3
  require 'rat_deployer/config'
4
+ require 'English'
4
5
 
5
6
  module RatDeployer
7
+ # Rat::Deployer encapsulates all code related to running a shell command
8
+ # and displaying it's output.
6
9
  module Command
7
10
  def run(cmd, silent: false)
8
11
  if !silent && RatDeployer::Config.prompt_enabled?
9
- msg = "||=> Running command ".colorize(:blue) + "`#{cmd.colorize(:white)}`"
10
- puts msg
12
+ puts '||=> Running command '.colorize(:blue) +
13
+ "`#{cmd.colorize(:white)}`"
11
14
  end
12
15
 
13
16
  command = do_run(cmd, silent: silent)
@@ -16,18 +19,19 @@ module RatDeployer
16
19
  end
17
20
 
18
21
  def do_run(cmd, silent: false)
19
- output, status = '', 1
22
+ output = ''
23
+ status = 1
20
24
 
21
- IO.popen(cmd) do |io|
22
- while line = io.gets do
25
+ IO.popen(ENV, cmd) do |io|
26
+ while line = io.gets # rubocop:disable Lint/AssignmentInCondition
23
27
  puts line unless silent
24
28
  output << line
25
29
  end
26
30
  io.close
27
- status = $?.to_i
31
+ status = $CHILD_STATUS.to_i
28
32
  end
29
33
 
30
- {output: output, status: status}
34
+ { output: output, status: status }
31
35
  end
32
36
 
33
37
  def put_heading(str)
@@ -45,22 +49,6 @@ module RatDeployer
45
49
  puts colorize_warning(str)
46
50
  end
47
51
 
48
- def ask_for_confirmation
49
- return unless RatDeployer::Config.prompt_enabled?
50
- prompt = "Are you sure you want to continue?"
51
-
52
- a = ''
53
- s = '[y/n]'
54
- d = 'y'
55
-
56
- until %w[y n].include? a
57
- a = ask(colorize_warning("#{prompt} #{s} ")) { |q| q.limit = 1; q.case = :downcase }
58
- a = d if a.length == 0
59
- end
60
-
61
- exit 1 unless a == 'y'
62
- end
63
-
64
52
  def colorize_warning(str)
65
53
  "\\\\ #{str}".colorize(:yellow)
66
54
  end
@@ -2,36 +2,50 @@ require 'yaml'
2
2
  require 'deep_merge'
3
3
 
4
4
  module RatDeployer
5
+ # This module handles config fetching from env and config files
5
6
  module Config
6
7
  def self.all
7
8
  @all ||= YAML.load_file(File.expand_path('./rat_config.yml')) || {}
8
9
  end
10
+
9
11
  def self.for_env(e = env)
10
12
  environmental = all.fetch('environments', {})
11
13
  default_conf = environmental.fetch('default', {})
12
- env_conf = environmental.fetch(e)
14
+ env_conf = environmental.fetch(e, {})
13
15
 
14
16
  default_conf.deep_merge(env_conf)
15
17
  end
16
18
 
17
- def self.prompt_enabled?() ENV['RAT_PROMPT'] != "false" end
18
- def self.machine() for_env.fetch("machine") end
19
- def self.remote() ENV['RAT_REMOTE'] =~ /true|1|yes/ end
20
- def self.env() ENV.fetch('RAT_ENV') end
21
- def self.images() all.fetch('images', {}) end
19
+ def self.prompt_enabled?
20
+ ENV['RAT_PROMPT'] != 'false'
21
+ end
22
+
23
+ def self.remote
24
+ ENV['RAT_REMOTE'] =~ /true|1|yes/
25
+ end
26
+
27
+ def self.env
28
+ ENV['RAT_ENV'] || 'default'
29
+ end
30
+
31
+ def self.images
32
+ all.fetch('images', {})
33
+ end
22
34
 
23
35
  def self.remote_machine_flags
36
+ machine = for_env.fetch('machine')
37
+
24
38
  case machine
25
- when Symbol, String
26
- `docker-machine config #{machine}`.gsub(/\n/, ' ')
27
39
  when Hash
28
40
  [
29
- "--tlsverify",
41
+ '--tlsverify',
30
42
  "-H='#{machine.fetch('host')}'",
31
43
  "--tlscacert='#{machine.fetch('ca_cert')}'",
32
44
  "--tlscert='#{machine.fetch('cert')}'",
33
- "--tlskey='#{machine.fetch('key')}'",
45
+ "--tlskey='#{machine.fetch('key')}'"
34
46
  ].join(' ')
47
+ else
48
+ raise 'Bad configuration value for `machine`'
35
49
  end
36
50
  end
37
51
  end
@@ -3,39 +3,38 @@ require 'active_support/core_ext/string'
3
3
  require 'slack-notifier'
4
4
 
5
5
  module RatDeployer
6
+ # RatDeployer::Notifier handles notifications to slack
6
7
  module Notifier
7
8
  def self.notify_deploy_start
8
9
  return unless webhook_url
9
- notify_deploy "Starting deploy on #{ENV.fetch('RAT_ENV')}"
10
+ notify_deploy "Starting deploy on #{RatDeployer::Config.env}"
10
11
  end
11
12
 
12
13
  def self.notify_deploy_end
13
14
  return unless webhook_url
14
- notify_deploy "Ended deploy on #{ENV.fetch('RAT_ENV')}"
15
+ notify_deploy "Ended deploy on #{RatDeployer::Config.env}"
15
16
  end
16
17
 
17
18
  def self.notify(msg)
18
19
  return unless webhook_url
19
20
  return unless webhook_url
20
- self.slack_notifier.ping msg
21
+ slack_notifier.ping msg
21
22
  end
22
23
 
23
- private
24
-
25
24
  def self.notify_deploy(title)
26
25
  return unless webhook_url
27
- props = get_deploy_properties
26
+ props = deploy_properties
28
27
 
29
28
  slack_notifier.post(
30
29
  text: title,
31
30
  attachments: [{
32
31
  title: 'Deploy details',
33
- fields: get_deploy_properties.map do |k,v|
32
+ fields: props.map do |k, v|
34
33
  {
35
34
  title: k.to_s.titleize,
36
35
  value: k == :images ? v.join(' · ') : v,
37
36
  short: k != :images
38
- }
37
+ }
39
38
  end
40
39
  }]
41
40
  )
@@ -55,17 +54,18 @@ module RatDeployer
55
54
  end
56
55
 
57
56
  def self.webhook_url
58
- @webhook_url ||= RatDeployer::Config.all["slack_webhook_url"]
57
+ @webhook_url ||= RatDeployer::Config.all['slack_webhook_url']
59
58
  end
60
59
 
61
- def self.get_deploy_properties
60
+ def self.deploy_properties
62
61
  require 'socket'
63
62
 
64
- docker_config = YAML.load(RatDeployer::Cli.new.compose('config', silent: true))
65
- images = docker_config['services'].map { |s,c| c['image'] }.uniq.sort
63
+ compose_config = RatDeployer::Cli.new.compose('config', silent: true)
64
+ docker_config = YAML.safe_load(compose_config)
65
+ images = docker_config['services'].map { |_s, c| c['image'] }.uniq.sort
66
66
 
67
67
  {
68
- env: ENV.fetch('RAT_ENV'),
68
+ env: RatDeployer::Config.env,
69
69
  user: ENV.fetch('USER'),
70
70
  hostname: Socket.gethostname,
71
71
  started_at: Time.now.to_s,
@@ -1,3 +1,3 @@
1
1
  module RatDeployer
2
- VERSION = "0.4.0"
2
+ VERSION = '0.5.0'.freeze
3
3
  end
data/lib/rat_deployer.rb CHANGED
@@ -1,6 +1,14 @@
1
1
  require 'rat_deployer/version'
2
2
  require 'rat_deployer/config'
3
3
 
4
+ # Rat is a deploy tool for docker users.
5
+ # It implements a facade around 2 docker CLIs:
6
+ # - docker
7
+ # - docler-compose
8
+ #
9
+ # It is not very flexible and it is lightly tested.
10
+ # I named it rat because it is a rather little and
11
+ # ugly ball of code, but it does the job for now.
4
12
  module RatDeployer
5
13
  def self.print_rat
6
14
  return unless RatDeployer::Config.prompt_enabled?
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rat_deployer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nicolas Oga
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-17 00:00:00.000000000 Z
11
+ date: 2017-08-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -122,6 +122,76 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: '10.0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: 3.6.0
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: 3.6.0
139
+ - !ruby/object:Gem::Dependency
140
+ name: activesupport
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - "~>"
144
+ - !ruby/object:Gem::Version
145
+ version: 5.1.3
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - "~>"
151
+ - !ruby/object:Gem::Version
152
+ version: 5.1.3
153
+ - !ruby/object:Gem::Dependency
154
+ name: pry
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - "~>"
158
+ - !ruby/object:Gem::Version
159
+ version: 0.10.4
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - "~>"
165
+ - !ruby/object:Gem::Version
166
+ version: 0.10.4
167
+ - !ruby/object:Gem::Dependency
168
+ name: simplecov
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: 0.15.0
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: 0.15.0
181
+ - !ruby/object:Gem::Dependency
182
+ name: rubocop
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - "~>"
186
+ - !ruby/object:Gem::Version
187
+ version: 0.49.1
188
+ type: :development
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - "~>"
193
+ - !ruby/object:Gem::Version
194
+ version: 0.49.1
125
195
  description: A micro-framework to deploy dockerized apps
126
196
  email:
127
197
  - 2112.oga@gmail.com
@@ -158,7 +228,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
158
228
  version: '0'
159
229
  requirements: []
160
230
  rubyforge_project:
161
- rubygems_version: 2.5.1
231
+ rubygems_version: 2.6.12
162
232
  signing_key:
163
233
  specification_version: 4
164
234
  summary: A micro-framework to deploy dockerized apps