opsworks-cli 0.6.0 → 0.7.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: 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