opsworks-cli 0.6.0 → 0.7.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: 7245edfcd7b7b42bb13b880e8e6e420eed060679712b2f1e6e4d54052387fa99
4
- data.tar.gz: 3c8699d3f0b438b1f5a55779dd0f233cd596be5980a35cee36aeeba6ec708bd0
3
+ metadata.gz: 4559d0b2cb6a2d928f5ada92931a25d2dc6a1701549cace6f847989edd93e66c
4
+ data.tar.gz: b59bf1e379e042ebae144fef653da7e45678b5c9b47e4f9e1ae12c2903d435df
5
5
  SHA512:
6
- metadata.gz: aa0ae55d4ea9198bd44e329e933de21b2a3bf62758537c7816b70730f66a14ac770bdf8f31206c010326599c1998268869328b9382273afa9b19d1ca078e9003
7
- data.tar.gz: a5fa63b9259cb2c9aa8f91dd44d2c0a5379f42d4b1d7794f8f93244c48428715cd69e4f456783b3656011ee1599ddae6e82f857134c0c3e58767568547ad9902
6
+ metadata.gz: ad0296093d9d19cd0fb49fb83c5b6b3a0d1477024dafc3402af1ebb508b49c39fa78e0c4eab236a44b343f1065483c53ee18dfbd2e0eff0aa329a31ed0c3d36c
7
+ data.tar.gz: 5598f4b72427313587c8b6e53de8945776e969c46cb07cf0d8be03366ff28db7f27bb0532e3bc452580d499d700935e7dc33037611a5d2626a05d36c1dc2880a
@@ -0,0 +1 @@
1
+ * @almathew
data/README.md CHANGED
@@ -56,6 +56,4 @@ Commands:
56
56
 
57
57
  MIT License, see [LICENSE](LICENSE.md) for details.
58
58
 
59
- Copyright (c) 2014 [Aptible](https://www.aptible.com) and contributors.
60
-
61
- [<img src="https://s.gravatar.com/avatar/f7790b867ae619ae0496460aa28c5861?s=60" style="border-radius: 50%;" alt="@fancyremarker" />](https://github.com/fancyremarker)
59
+ Copyright (c) 2019 [Aptible](https://www.aptible.com) and contributors.
@@ -11,11 +11,16 @@ module OpsWorks
11
11
  stacks = parse_stacks(options)
12
12
  stacks.each do |stack|
13
13
  stack.instances.each do |instance|
14
- say [
14
+ arr = [
15
15
  stack.name,
16
16
  instance.hostname,
17
17
  instance.status
18
- ].join("\t")
18
+ ]
19
+ # TODO: Why does a EOL tab break say?
20
+ if (errors = instance.service_errors).any?
21
+ arr << errors.join(', ')
22
+ end
23
+ say arr.join("\t")
19
24
  end
20
25
  end
21
26
  end
@@ -7,11 +7,12 @@ module OpsWorks
7
7
  desc 'recipes:run RECIPE [--stack STACK]', 'Execute a Chef recipe'
8
8
  option :stack, type: :array
9
9
  option :timeout, type: :numeric, default: 300
10
+ option :layer, type: :string
10
11
  define_method 'recipes:run' do |recipe|
11
12
  stacks = parse_stacks(options.merge(active: true))
12
13
  deployments = stacks.map do |stack|
13
14
  say "Executing recipe on #{stack.name}..."
14
- stack.execute_recipe(recipe)
15
+ stack.execute_recipe(recipe, layer: options[:layer])
15
16
  end
16
17
  OpsWorks::Deployment.wait(deployments, options[:timeout])
17
18
  unless deployments.all?(&:success?)
@@ -1,5 +1,5 @@
1
1
  module OpsWorks
2
2
  module CLI
3
- VERSION = '0.6.0'.freeze
3
+ VERSION = '0.7.0'.freeze
4
4
  end
5
5
  end
@@ -1,6 +1,7 @@
1
1
  module OpsWorks
2
2
  class Instance < Resource
3
- attr_accessor :id, :hostname, :ec2_instance_id, :instance_type, :status
3
+ attr_accessor :id, :hostname, :ec2_instance_id, :instance_type, :status,
4
+ :service_errors
4
5
 
5
6
  FATAL_STATUSES = %w(
6
7
  connection_lost setup_failed start_failed stop_failed
@@ -12,13 +13,24 @@ module OpsWorks
12
13
 
13
14
  def self.from_collection_response(client, response)
14
15
  response.data[:instances].map do |hash|
16
+ # If instance is in start_failed status, grab the service errors to
17
+ # help explain why
18
+ if hash[:status] == 'start_failed'
19
+ instance_id = hash[:instance_id]
20
+ raw = client.describe_service_errors(instance_id: instance_id)
21
+ service_errors = raw[:service_errors].map { |e| e[:message] }
22
+ else
23
+ service_errors = []
24
+ end
25
+
15
26
  new(
16
27
  client,
17
28
  id: hash[:instance_id],
18
29
  hostname: hash[:hostname],
19
30
  ec2_instance_id: hash[:ec2_instance_id],
20
31
  instance_type: hash[:instance_type],
21
- status: hash[:status]
32
+ status: hash[:status],
33
+ service_errors: service_errors
22
34
  )
23
35
  end
24
36
  end
@@ -103,13 +103,17 @@ module OpsWorks
103
103
  create_deployment(command: { name: 'update_custom_cookbooks' })
104
104
  end
105
105
 
106
- def execute_recipe(recipe)
107
- create_deployment(
106
+ def execute_recipe(recipe, layer: nil)
107
+ deploy_args = {
108
108
  command: {
109
109
  name: 'execute_recipes',
110
110
  args: { 'recipes' => [recipe] }
111
111
  }
112
- )
112
+ }
113
+
114
+ deploy_args[:layer_ids] = [layer_id_from_name(layer)] if layer
115
+
116
+ create_deployment(**deploy_args)
113
117
  end
114
118
 
115
119
  def deploy_app(app, layer: nil, args: {})
@@ -123,11 +127,7 @@ module OpsWorks
123
127
  }
124
128
  }
125
129
 
126
- if layer
127
- layer = layers.find { |l| l.shortname == layer }
128
- raise "Layer #{layer} not found" unless layer
129
- deploy_args[:layer_ids] = [layer.id]
130
- end
130
+ deploy_args[:layer_ids] = [layer_id_from_name(layer)] if layer
131
131
 
132
132
  create_deployment(**deploy_args)
133
133
  end
@@ -193,6 +193,12 @@ module OpsWorks
193
193
  end
194
194
  # rubocop:enable Eval
195
195
 
196
+ def layer_id_from_name(shortname)
197
+ layer = layers.find { |l| l.shortname == shortname }
198
+ raise "Layer #{layer} not found" unless layer
199
+ layer.id
200
+ end
201
+
196
202
  def initialize_apps
197
203
  return [] unless id
198
204
  response = client.describe_apps(stack_id: id)
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.require_paths = ['lib']
22
22
 
23
23
  spec.add_dependency 'thor'
24
- spec.add_dependency 'aws-sdk', '~> 2.9.6'
24
+ spec.add_dependency 'aws-sdk', '~> 2.11.192'
25
25
  spec.add_dependency 'jsonpath'
26
26
  spec.add_dependency 'activesupport'
27
27
 
@@ -3,4 +3,5 @@ Fabricator(:instance, from: OpsWorks::Instance) do
3
3
  id { SecureRandom.uuid }
4
4
  hostname { Fabricate.sequence { |i| "test-instance#{i}" } }
5
5
  status { 'online' }
6
+ service_errors { [] }
6
7
  end
@@ -13,23 +13,33 @@ describe OpsWorks::CLI::Agent do
13
13
  describe 'recipes:run' do
14
14
  let(:success) { Fabricate(:deployment, status: 'successful') }
15
15
  let(:failure) { Fabricate(:deployment, status: 'failed') }
16
+ let(:args) { [recipe, { layer: nil }] }
16
17
 
17
18
  it 'should update custom cookbooks on all stacks' do
18
- expect(stacks[0]).to receive(:execute_recipe).with(recipe) { success }
19
- expect(stacks[1]).to receive(:execute_recipe).with(recipe) { success }
19
+ expect(stacks[0]).to receive(:execute_recipe).with(*args) { success }
20
+ expect(stacks[1]).to receive(:execute_recipe).with(*args) { success }
20
21
  subject.send('recipes:run', recipe)
21
22
  end
22
23
 
23
24
  it 'should optionally run on a subset of stacks' do
24
- expect(stacks[0]).to receive(:execute_recipe).with(recipe) { success }
25
+ expect(stacks[0]).to receive(:execute_recipe).with(*args) { success }
25
26
  expect(stacks[1]).not_to receive(:execute_recipe)
26
27
 
27
28
  allow(subject).to receive(:options) { { stack: [stacks[0].name] } }
28
29
  subject.send('recipes:run', recipe)
29
30
  end
30
31
 
32
+ it 'should optionally run on a single layer' do
33
+ args = [recipe, { layer: 'git' }]
34
+ expect(stacks[0]).to receive(:execute_recipe).with(*args) { success }
35
+ expect(stacks[1]).to receive(:execute_recipe).with(*args) { success }
36
+
37
+ allow(subject).to receive(:options) { { layer: 'git' } }
38
+ subject.send('recipes:run', recipe)
39
+ end
40
+
31
41
  it 'should fail if any update fails' do
32
- expect(stacks[0]).to receive(:execute_recipe).with(recipe) { failure }
42
+ expect(stacks[0]).to receive(:execute_recipe).with(*args) { failure }
33
43
 
34
44
  allow(subject).to receive(:options) { { stack: [stacks[0].name] } }
35
45
  expect { subject.send('recipes:run', recipe) }.to raise_error
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opsworks-cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Frank Macreery
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-23 00:00:00.000000000 Z
11
+ date: 2020-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 2.9.6
33
+ version: 2.11.192
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 2.9.6
40
+ version: 2.11.192
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: jsonpath
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -172,6 +172,7 @@ executables:
172
172
  extensions: []
173
173
  extra_rdoc_files: []
174
174
  files:
175
+ - ".github/CODEOWNERS"
175
176
  - ".gitignore"
176
177
  - ".rspec"
177
178
  - ".travis.yml"
@@ -236,8 +237,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
236
237
  - !ruby/object:Gem::Version
237
238
  version: '0'
238
239
  requirements: []
239
- rubyforge_project:
240
- rubygems_version: 2.7.6
240
+ rubygems_version: 3.0.3
241
241
  signing_key:
242
242
  specification_version: 4
243
243
  summary: Alternative CLI for Amazon OpsWorks