opsicle 0.12.0 → 0.13.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: 382eb43575e7839130f2b9aeb764eb073f00eb55
4
- data.tar.gz: d2daa070bd8e667242c07655c9c9fe2f615a1a6b
3
+ metadata.gz: c70b5f91d3917104411e5e0b6cc183406b1b8016
4
+ data.tar.gz: 61418c77bb81f7adccd36dfed093ea482e59077c
5
5
  SHA512:
6
- metadata.gz: 2e3f9d74f4a3e204639c113564faae10f2714f7347a348044de701da4573fb76a915097ea482cc0c81d7b6d9d71365705b0ad11a10e8d16a1f52b10d43a970b4
7
- data.tar.gz: eaf95944a7eaa244811546b382e5c1b05ed4cdd9522290e93f353173ad2adf97727dcf46db1c7a7c396e7da154189e39cec13387720c7e39eface42f2e0c57fb
6
+ metadata.gz: 39ceb8570c356e6a74411a4f5307771ee7cfc1bddb9ddb958d26209a3a8366225c8f5e8d695b075be0b2744a472acd35cb74eade46841f29bd5cd65b98d8a5b4
7
+ data.tar.gz: d1322f7a77cfb0c3e5e416fe9a7d3632a13908704f9a0e1d32adcdb8969705d4c50c04de01653f19c6aedb0bfcda659ec1c1b1be0db89f4034c545979996b869
data/bin/opsicle CHANGED
@@ -2,6 +2,8 @@
2
2
  require 'rubygems'
3
3
  require 'gli'
4
4
  require 'opsicle'
5
+ require 'json'
6
+ require 'yaml'
5
7
 
6
8
  include GLI::App
7
9
 
@@ -181,4 +183,29 @@ command :instances do |c|
181
183
  end
182
184
  end
183
185
 
186
+
187
+ desc "Update properties on a OpsWorks resource."
188
+ arg_name '<environment> <type>'
189
+ command 'update' do |c|
190
+ valid_types = %w[app elastic_ip instance layer my_user_profile rds_db_instance stack user_profile volume]
191
+ c.flag [:j, :json], :desc => 'JSON of values to update.', :type => String
192
+ c.flag [:y, :yaml_file], :desc => 'YAML file of values to update.', :type => String
193
+
194
+ c.action do |global_options, options, args|
195
+ raise ArgumentError, "Environment is required" unless args.first
196
+ raise ArgumentError, "Resource type is required" unless args[1]
197
+ raise ArgumentError, "Invalid type: #{args[1]}. Valid types: #{valid_types}" unless valid_types.include?(args[1])
198
+ if options[:json]
199
+ values = JSON.parse(options[:json])
200
+ elsif options[:yaml_file]
201
+ yaml_file = File.expand_path(options[:yaml_file])
202
+ values = YAML.load_file(yaml_file)
203
+ else
204
+ raise ArgumentError, "Values required in JSON or YAML flag."
205
+ end
206
+
207
+ Opsicle::Update.new(*args).execute(values, global_options.merge(options))
208
+ end
209
+ end
210
+
184
211
  exit run(ARGV)
@@ -5,6 +5,7 @@ require "opsicle/commands/chef_update"
5
5
  require "opsicle/commands/execute_recipes"
6
6
  require "opsicle/commands/list"
7
7
  require "opsicle/commands/list_instances"
8
+ require "opsicle/commands/update"
8
9
  require "opsicle/commands/ssh"
9
10
  require "opsicle/commands/ssh_key"
10
11
  require "opsicle/commands/ssh_clean_keys"
@@ -0,0 +1,57 @@
1
+ require 'hashdiff'
2
+ require 'opsicle/output'
3
+
4
+ module Opsicle
5
+ class Update
6
+ attr_reader :client, :type
7
+
8
+ def initialize(environment, type)
9
+ @client = Client.new(environment)
10
+ @type = type
11
+ end
12
+
13
+ def execute(values, options)
14
+ before = describe
15
+ update(values)
16
+ after = describe
17
+ print(before, after)
18
+ end
19
+
20
+ def describe
21
+ api_method = "describe_#{@type}s"
22
+ api_opts = {
23
+ :"#{@type}_ids" => [client.config.opsworks_config[:"#{@type}_id"]]
24
+ }
25
+ client.api_call(api_method, api_opts)[:"#{@type}s"][0]
26
+ end
27
+
28
+ def update(values)
29
+ api_method = "update_#{@type}"
30
+ api_opts = values.merge(:"#{@type}_id" => client.config.opsworks_config[:"#{@type}_id"])
31
+ client.api_call(api_method, api_opts)
32
+ end
33
+
34
+ def print(before, after)
35
+ diff = HashDiff.diff(before, after)
36
+ Output.say("Changes: #{diff.size}")
37
+ Output.terminal.say(Terminal::Table.new headings: %w[Change Key Before After], rows: format_diff(diff)) if diff.size > 0
38
+ end
39
+
40
+ def format_diff(diff)
41
+ diff.map { |change|
42
+ case change[0]
43
+ when '-'
44
+ change.insert(3, nil)
45
+ change.map! { |i| Output.format(i, :removal) }
46
+ when '+'
47
+ change.insert(2, nil)
48
+ change.map! { |i| Output.format(i, :addition) }
49
+ when '~'
50
+ change.map! { |i| Output.format(i, :modification) }
51
+ end
52
+ change
53
+ }
54
+ end
55
+
56
+ end
57
+ end
@@ -15,14 +15,21 @@ module Opsicle
15
15
  :verbose => [:bold, :magenta],
16
16
  :debug => [:bold, :cyan],
17
17
  :success => [:bold, :green],
18
+ :addition => [:bold, :green],
19
+ :removal => [:bold, :red],
20
+ :modification => [:bold, :yellow],
18
21
  )
19
22
  end
20
23
 
21
24
  def self.say(msg, log_style=:normal)
25
+ terminal.say format(msg, log_style)
26
+ end
27
+
28
+ def self.format(msg, log_style=:normal)
22
29
  if $color
23
- terminal.say "<%= color('#{msg}', '#{log_style}') %>"
30
+ terminal.color(msg.to_s, log_style)
24
31
  else
25
- terminal.say msg
32
+ msg
26
33
  end
27
34
  end
28
35
 
@@ -1,3 +1,3 @@
1
1
  module Opsicle
2
- VERSION = "0.12.0"
2
+ VERSION = "0.13.0"
3
3
  end
@@ -0,0 +1,71 @@
1
+ require "spec_helper"
2
+ require "opsicle"
3
+
4
+ module Opsicle
5
+ describe Update do
6
+ subject { Update.new("env", "type") }
7
+ let(:client) { double }
8
+ let(:env) { "env" }
9
+ let(:type) { "type" }
10
+ let(:values) { { :foo => "bar" } }
11
+
12
+ before do
13
+ allow(Client).to receive(:new).with('env') { client }
14
+ allow(client).to receive_message_chain("config.opsworks_config.[]") { 123 }
15
+ end
16
+
17
+ context "#execute" do
18
+ it "should update and print results" do
19
+ allow(subject).to receive(:describe) { "tacos" }
20
+ expect(subject).to receive(:print).with("tacos", "tacos")
21
+ api_opts = values.merge(:type_id => 123)
22
+ expect(client).to receive(:api_call).with("update_type", api_opts)
23
+ subject.execute(values, api_opts)
24
+ end
25
+ end
26
+
27
+ context "#describe" do
28
+ it "should return data for type" do
29
+ expect(client).to receive(:api_call).with("describe_types", :type_ids => [123]).and_return(:types => [])
30
+ subject.describe
31
+ end
32
+ end
33
+
34
+ context "#update" do
35
+ it "should update values for type" do
36
+ api_opts = values.merge(:type_id => 123)
37
+ expect(client).to receive(:api_call).with("update_type", api_opts)
38
+ subject.update(values)
39
+ end
40
+ end
41
+
42
+ context "#print" do
43
+ it "should print no changes without table" do
44
+ allow(HashDiff).to receive(:diff) { [] }
45
+ expect(Output).to receive(:say).with("Changes: 0") { nil }
46
+ expect(Output).to_not receive(:terminal)
47
+ subject.print(nil, nil)
48
+ end
49
+ it "should print changes with table" do
50
+ allow(HashDiff).to receive(:diff) { [%w[- nyan 1], %w[+ cat 2],%w[~ taco 3 4]] }
51
+ expect(Output).to receive(:say).with("Changes: 3") { nil }
52
+ expect(Output).to receive_message_chain("terminal.say")
53
+ subject.print(nil, nil)
54
+ end
55
+ end
56
+
57
+ context "#format_diff" do
58
+ let(:diff) { [%w[- nyan 1], %w[+ cat 2],%w[~ taco 3 4]] }
59
+ let(:formatted_diff) {
60
+ [%w[r- rnyan r1 r], %w[a+ acat a a2], %w[m~ mtaco m3 m4]]
61
+ }
62
+
63
+ it "should align columns and colorize" do
64
+ allow(Output).to receive(:format).with(anything, :removal) { |arg| "r#{arg}"}
65
+ allow(Output).to receive(:format).with(anything, :addition) { |arg| "a#{arg}"}
66
+ allow(Output).to receive(:format).with(anything, :modification) { |arg| "m#{arg}"}
67
+ expect(subject.format_diff(diff)).to eq(formatted_diff)
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,61 @@
1
+ require "spec_helper"
2
+ require "opsicle"
3
+
4
+ module Opsicle
5
+ describe Output do
6
+ subject { Output }
7
+ let(:terminal) { double(:say => nil, :color => nil) }
8
+ let(:msg) { "message" }
9
+ let(:colored_msg) { "COLOURmessageCOLOUR" }
10
+
11
+ before do
12
+ allow(subject).to receive(:terminal).and_return(terminal)
13
+ $color = true
14
+ $verbose = false
15
+ end
16
+
17
+ context "#say" do
18
+ it "should say a formatted message" do
19
+ allow(terminal).to receive(:color).and_return(colored_msg)
20
+ expect(terminal).to receive(:say).with(colored_msg)
21
+ subject.say(msg)
22
+ end
23
+ it "should say a message without color" do
24
+ $color = false
25
+ expect(terminal).to receive(:say).with(msg)
26
+ subject.say(msg)
27
+ end
28
+ end
29
+
30
+ context "#format" do
31
+ it "should color message" do
32
+ allow(terminal).to receive(:color).and_return(colored_msg)
33
+ expect(subject.format(msg)).to eq(colored_msg)
34
+ end
35
+ it "should not color message" do
36
+ $color = false
37
+ expect(subject.format(msg)).to eq(msg)
38
+ end
39
+ end
40
+
41
+ context "#say_verbose" do
42
+ it "should not say a verbose message" do
43
+ expect(terminal).to_not receive(:say)
44
+ subject.say_verbose(msg)
45
+ end
46
+ it "should say a verbose message" do
47
+ $verbose = true
48
+ expect(terminal).to receive(:say)
49
+ subject.say_verbose(msg)
50
+ end
51
+ end
52
+
53
+ context "#ask" do
54
+ it "should ask" do
55
+ expect(terminal).to receive(:ask)
56
+ subject.ask
57
+ end
58
+ end
59
+
60
+ end
61
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opsicle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.12.0
4
+ version: 0.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andy Fleener
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-03-26 00:00:00.000000000 Z
12
+ date: 2015-03-30 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: aws-sdk
@@ -95,6 +95,20 @@ dependencies:
95
95
  - - "~>"
96
96
  - !ruby/object:Gem::Version
97
97
  version: '0.5'
98
+ - !ruby/object:Gem::Dependency
99
+ name: hashdiff
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: '0.2'
105
+ type: :runtime
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: '0.2'
98
112
  - !ruby/object:Gem::Dependency
99
113
  name: bundler
100
114
  requirement: !ruby/object:Gem::Requirement
@@ -186,6 +200,7 @@ files:
186
200
  - lib/opsicle/commands/ssh.rb
187
201
  - lib/opsicle/commands/ssh_clean_keys.rb
188
202
  - lib/opsicle/commands/ssh_key.rb
203
+ - lib/opsicle/commands/update.rb
189
204
  - lib/opsicle/config.rb
190
205
  - lib/opsicle/deploy_helper.rb
191
206
  - lib/opsicle/deployment.rb
@@ -218,6 +233,7 @@ files:
218
233
  - spec/opsicle/commands/list_spec.rb
219
234
  - spec/opsicle/commands/ssh_key_spec.rb
220
235
  - spec/opsicle/commands/ssh_spec.rb
236
+ - spec/opsicle/commands/update_spec.rb
221
237
  - spec/opsicle/config_spec.rb
222
238
  - spec/opsicle/errors_spec.rb
223
239
  - spec/opsicle/instances_spec.rb
@@ -227,6 +243,7 @@ files:
227
243
  - spec/opsicle/monitor/screen_spec.rb
228
244
  - spec/opsicle/monitor/spy/deployments_spec.rb
229
245
  - spec/opsicle/monitor/subpanel_spec.rb
246
+ - spec/opsicle/output_spec.rb
230
247
  - spec/opsicle/s3_bucket_spec.rb
231
248
  - spec/spec_helper.rb
232
249
  homepage: https://github.com/sportngin/opsicle
@@ -262,6 +279,7 @@ test_files:
262
279
  - spec/opsicle/commands/list_spec.rb
263
280
  - spec/opsicle/commands/ssh_key_spec.rb
264
281
  - spec/opsicle/commands/ssh_spec.rb
282
+ - spec/opsicle/commands/update_spec.rb
265
283
  - spec/opsicle/config_spec.rb
266
284
  - spec/opsicle/errors_spec.rb
267
285
  - spec/opsicle/instances_spec.rb
@@ -271,5 +289,6 @@ test_files:
271
289
  - spec/opsicle/monitor/screen_spec.rb
272
290
  - spec/opsicle/monitor/spy/deployments_spec.rb
273
291
  - spec/opsicle/monitor/subpanel_spec.rb
292
+ - spec/opsicle/output_spec.rb
274
293
  - spec/opsicle/s3_bucket_spec.rb
275
294
  - spec/spec_helper.rb