dream-ops 0.5.0 → 0.6.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
  SHA1:
3
- metadata.gz: 9729a06fc81ca0a17b9897304d0de3562c28f05a
4
- data.tar.gz: 707bbb6ca751d6d55e5a6c2d0557d0f87c99329d
3
+ metadata.gz: 635291c5f60c092e9a6aadccbbb94b9c406f44aa
4
+ data.tar.gz: b53af42711e3c850419e528221e568bf14c136b7
5
5
  SHA512:
6
- metadata.gz: fd9d0dc3bc43af57f596e2d9e161481cf4b0bdc529c7c769c752d67df07f92258beb5f6fc2702949809a3a057e723f34d52da3e306a17e341c548c808ded35d5
7
- data.tar.gz: 7a9a2de51970785f8ce5a71bcffaf6f5f7cc523a0465350a1ef227a2cafaffded305f632007872b6246b61c2c05273e419731f3c22440a22522d3e3da4d79ef2
6
+ metadata.gz: dec24a3be06450e6b4aadd9907d65e5f3020681680337bf8c8e119e76ce1e39049fdfb22dc712195135d0a60b992aa365ad1652a9e99e1268efc44e1a681e1ad
7
+ data.tar.gz: 52451f10fd6658f6b443ad632c60285c24be4b28d3117fafa45bc617638e40eeaa8e603d3543b4a9a53c737c8a95ff9ff65d6607983f4b50aa5d3e8abdb4c69f
@@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.6.0]
10
+
11
+ ### Added
12
+ - Added global `aws_profile` option
13
+ - Added spinner to all deployments to avoid CI hangs
14
+
9
15
  ## [0.5.0]
10
16
 
11
17
  ### Changed
data/README.md CHANGED
@@ -33,11 +33,12 @@ Commands:
33
33
  dream version # Display version
34
34
 
35
35
  Options:
36
- -F, [--format=FORMAT] # Output format to use.
37
- # Default: human
38
- -q, [--quiet], [--no-quiet] # Silence all informational output.
39
- -d, [--debug], [--no-debug] # Output debug information
40
- -i, [--ssh-key=SSH_KEY] # Path to SSH key
36
+ -F, [--format=FORMAT] # Output format to use.
37
+ # Default: human
38
+ -q, [--quiet], [--no-quiet] # Silence all informational output.
39
+ -d, [--debug], [--no-debug] # Output debug information
40
+ -i, [--ssh-key=SSH_KEY] # Path to SSH key
41
+ -p, [--aws-profile=AWS_PROFILE] # AWS profile to use
41
42
 
42
43
  ```
43
44
 
@@ -36,6 +36,7 @@ Gem::Specification.new do |spec|
36
36
 
37
37
  spec.add_dependency "rubyzip", "~> 1.2"
38
38
  spec.add_dependency "aws-sdk", "~> 2"
39
+ spec.add_dependency "inifile", "~> 3.0"
39
40
  spec.add_dependency "berkshelf", "~> 7.0"
40
41
  spec.add_dependency "thor", "~> 0.20"
41
42
  spec.add_dependency "chef", "~> 13.6"
@@ -10,6 +10,8 @@ end
10
10
 
11
11
  require "berkshelf"
12
12
  require "thor"
13
+ require "aws-sdk"
14
+ require "inifile"
13
15
 
14
16
  module DreamOps
15
17
 
@@ -76,6 +78,29 @@ module DreamOps
76
78
  @ssh_key = key
77
79
  end
78
80
 
81
+ # Specify AWS profile to use
82
+ def use_aws_profile(profile)
83
+ begin
84
+ shared_creds = Aws::SharedCredentials.new(profile_name: profile)
85
+ Aws.config.update(credentials: shared_creds)
86
+ rescue Aws::Errors::NoSuchProfileError => error
87
+ DreamOps.ui.error error
88
+ exit(1)
89
+ end
90
+
91
+ # Unfortunately, Aws::OpsWorks::Client only loads the default profile's
92
+ # region. This parses the INI files and honors the profile region if set.
93
+ ini = IniFile.load("#{ENV['HOME']}/.aws/config")
94
+ if ini.nil? || !ini.has_section(profile)
95
+ ini = IniFile.load("#{ENV['HOME']}/.aws/credentials")
96
+ end
97
+
98
+ region = ini.to_h[profile]['region']
99
+ if !region.nil? && !region.empty?
100
+ Aws.config.update(region: region)
101
+ end
102
+ end
103
+
79
104
  # Get whether to always run setup
80
105
  #
81
106
  # @return [~boolean]
@@ -65,10 +65,14 @@ module DreamOps
65
65
 
66
66
  DreamOps.set_format @options[:format]
67
67
 
68
- if @options[:ssh_key]
68
+ if !@options[:ssh_key].empty?
69
69
  DreamOps.set_ssh_key @options[:ssh_key]
70
70
  end
71
71
 
72
+ if !@options[:aws_profile].empty?
73
+ DreamOps.use_aws_profile @options[:aws_profile]
74
+ end
75
+
72
76
  @options = options.dup # unfreeze frozen options Hash from Thor
73
77
  end
74
78
 
@@ -100,6 +104,11 @@ module DreamOps
100
104
  desc: "Path to SSH key",
101
105
  aliases: "-i",
102
106
  default: ""
107
+ class_option :aws_profile,
108
+ type: :string,
109
+ desc: "AWS profile to use",
110
+ aliases: "-p",
111
+ default: ""
103
112
 
104
113
  desc "version", "Display version"
105
114
  def version
@@ -3,6 +3,15 @@ require 'fileutils'
3
3
 
4
4
  module DreamOps
5
5
  class BaseDeployer
6
+ @@spinner = Enumerator.new do |e|
7
+ loop do
8
+ e.yield '|'
9
+ e.yield '/'
10
+ e.yield '-'
11
+ e.yield '\\'
12
+ end
13
+ end
14
+
6
15
  class << self
7
16
  #
8
17
  # @macro deployer_method
@@ -96,6 +105,11 @@ module DreamOps
96
105
  end
97
106
 
98
107
  def deploy(*args)
108
+ # Ensure git is installed
109
+ if (!system("which git > /dev/null 2>&1"))
110
+ __bail_with_fatal_error(GitNotInstalledError.new)
111
+ end
112
+
99
113
  # Find unique cookbooks and deploy targets
100
114
  result = analyze(args)
101
115
 
@@ -240,8 +240,12 @@ module DreamOps
240
240
  status = "failed"
241
241
  while true
242
242
  status = get_deployment_status(deployment_id)
243
- break if ["successful", "failed"].include? status
243
+ if ["successful", "failed"].include? status
244
+ print "\b"
245
+ break
246
+ end
244
247
  sleep(2)
248
+ print "\r#{@@spinner.next}"
245
249
  end
246
250
  return status
247
251
  end
@@ -1,4 +1,5 @@
1
1
  require 'securerandom'
2
+ require 'timeout'
2
3
 
3
4
  module DreamOps
4
5
  class SoloDeployer < BaseDeployer
@@ -10,6 +11,20 @@ module DreamOps
10
11
  return cookbooks.any? {|c| c[:targets].include? target }
11
12
  end
12
13
 
14
+ def __wait_for_pid(pid)
15
+ while true do
16
+ begin
17
+ Timeout.timeout(5) do
18
+ Process.wait pid
19
+ end
20
+ print "\b"
21
+ return $?.exitstatus == 0
22
+ rescue Timeout::Error
23
+ print "\r#{@@spinner.next}"
24
+ end
25
+ end
26
+ end
27
+
13
28
  # Analyze the SSH hosts for deployment
14
29
  #
15
30
  # @return [Hash]
@@ -146,11 +161,18 @@ module DreamOps
146
161
 
147
162
  uuid = SecureRandom.uuid
148
163
 
149
- if ! system(
150
- "ssh #{@ssh_opts} #{target[:host]} \"" +
151
- "set -o pipefail && " +
152
- "sudo chef-solo -j /var/chef/chef.json -o \"role[#{role}]\" 2>&1 | sudo tee /var/log/chef/#{uuid}.log #{@q_all}\""
153
- )
164
+ pid = fork do
165
+ if ! system(
166
+ "ssh #{@ssh_opts} #{target[:host]} \"" +
167
+ "set -o pipefail && " +
168
+ "sudo chef-solo -j /var/chef/chef.json -o \"role[#{role}]\" 2>&1 | sudo tee /var/log/chef/#{uuid}.log #{@q_all}\""
169
+ )
170
+ exit 1
171
+ end
172
+ exit 0
173
+ end
174
+
175
+ if !__wait_for_pid(pid)
154
176
  __bail_with_fatal_error(ChefSoloFailedError.new(target[:host], "/var/log/chef/#{uuid}.log"))
155
177
  end
156
178
  end
@@ -148,4 +148,12 @@ module DreamOps
148
148
  ].join("\n")
149
149
  end
150
150
  end
151
+
152
+ class GitNotInstalledError < DreamOpsError
153
+ set_status_code(19)
154
+
155
+ def to_s
156
+ "Unabled to find git in your PATH."
157
+ end
158
+ end
151
159
  end
@@ -1,3 +1,3 @@
1
1
  module DreamOps
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dream-ops
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Allen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-02-14 00:00:00.000000000 Z
11
+ date: 2020-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,6 +66,20 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '2'
69
+ - !ruby/object:Gem::Dependency
70
+ name: inifile
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: berkshelf
71
85
  requirement: !ruby/object:Gem::Requirement