opsicle 0.7.1 → 0.8.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.
data/bin/opsicle CHANGED
@@ -147,10 +147,12 @@ arg_name '<environment>'
147
147
  arg_name '<recipe>'
148
148
  command 'execute-recipes' do |c|
149
149
  c.switch [:m, :monitor], :desc => "Run the Stack Monitor on deploy", :default_value => true
150
+ c.switch [:e, :eip], :desc => "Executes recipes on a single instance with an elastic IP", :default_value => false
150
151
  c.switch [:t, :track], :desc => "Tracks to deploy and exits when completed. Exits with non-zero if the deploy fails."
151
152
  c.flag [:r, :recipes], :desc => 'The recipes to execute', :type => Array, :required => true
152
153
  c.flag [:i, :instance_ids], :desc => 'The specific instances to execute recipes on', :type => Array
153
154
  c.flag [:l, :layers], :desc => 'The specific layers to execute recipes on', :type => Array
155
+ c.flag [:a, :ip_addresses], :desc => 'The specific ip addresses of instance to execute recipes on', :type => Array
154
156
  c.action do |global_options, options, args|
155
157
  raise ArgumentError, "Environment is required" unless args.first
156
158
 
@@ -18,7 +18,8 @@ module Opsicle
18
18
  command_args = {}
19
19
  command_args["recipes"] = options[:recipes]
20
20
  command_opts = {}
21
- command_opts["instance_ids"] = determine_instance_ids(options) if options[:instance_ids] || options[:layers]
21
+ command_opts["instance_ids"] = determine_instance_ids(options)
22
+ command_opts.reject! {|key,value| value.nil?}
22
23
 
23
24
  response = client.run_command('execute_recipes', command_args, command_opts)
24
25
  launch_stack_monitor(response, options)
@@ -28,9 +29,39 @@ module Opsicle
28
29
  if options[:instance_ids]
29
30
  options[:instance_ids]
30
31
  elsif options[:layers]
31
- Opsicle::Layer.instance_ids(client, options[:layers])
32
+ determine_from_layers(options[:layers])
33
+ elsif options[:ip_addresses]
34
+ determine_from_ips(options[:ip_addresses])
35
+ elsif options[:eip]
36
+ determine_from_eip
32
37
  end
33
38
  end
34
39
 
40
+ def determine_from_ips(ips)
41
+ if instances = Opsicle::Instances.find_by_ip(client, ips)
42
+ instances.map { |instance| instance[:instance_id] }
43
+ else
44
+ raise NoInstanceError, "Unable to find instances with given IP"
45
+ end
46
+ end
47
+
48
+ def determine_from_eip
49
+ if instance = Opsicle::Instances.find_by_eip(client).first
50
+ Array(instance[:instance_id])
51
+ else
52
+ raise NoInstanceError, "Unable to find instances with elastic IPs"
53
+ end
54
+ end
55
+
56
+ def determine_from_layers(layers)
57
+ if instances = Opsicle::Layer.instance_ids(client, layers)
58
+ instances
59
+ else
60
+ raise NoInstanceError, "Unable to find instances in specified layers"
61
+ end
62
+ end
63
+
64
+ NoInstanceError = Class.new(StandardError)
65
+
35
66
  end
36
67
  end
@@ -15,8 +15,8 @@ module Opsicle
15
15
 
16
16
  def aws_config
17
17
  return @aws_config if @aws_config
18
- fog_confg = load_config(File.expand_path(FOG_CONFIG_PATH))
19
- @aws_config = { access_key_id: fog_confg[:aws_access_key_id], secret_access_key: fog_confg[:aws_secret_access_key] }
18
+ fog_config = load_config(File.expand_path(FOG_CONFIG_PATH))
19
+ @aws_config = { access_key_id: fog_config[:aws_access_key_id], secret_access_key: fog_config[:aws_secret_access_key] }
20
20
  end
21
21
 
22
22
  def opsworks_config
@@ -1,6 +1,11 @@
1
1
  module Opsicle
2
2
  class Instances
3
3
 
4
+ attr_accessor :client
5
+ class <<self
6
+ attr_accessor :client
7
+ end
8
+
4
9
  def initialize(client)
5
10
  @client = client
6
11
  end
@@ -9,11 +14,28 @@ module Opsicle
9
14
  instances(reload: true)
10
15
  end
11
16
 
17
+ def self.find_by_ip(client, ips)
18
+ instances = new(client).data.reject { |instance| instances_matching_ips(instance, ips) }
19
+ instances.empty? ? nil : instances
20
+ end
21
+
22
+ def self.instances_matching_ips(instance, ip_addresses)
23
+ instance_ips = [instance[:public_ip], instance[:elastic_ip], instance[:private_ip]].compact
24
+ (ip_addresses & instance_ips).empty?
25
+ end
26
+
27
+ private_class_method :instances_matching_ips
28
+
29
+ def self.find_by_eip(client)
30
+ instances = new(client).data.reject { |instance| instance[:elastic_ip] == nil }
31
+ instances.empty? ? nil : instances
32
+ end
33
+
12
34
  def instances(options={})
13
35
  # Only call the API again if you need to
14
36
  @instances = nil if options[:reload]
15
- @instances ||= @client.api_call('describe_instances',
16
- :stack_id => @client.config.opsworks_config[:stack_id]
37
+ @instances ||= client.api_call('describe_instances',
38
+ :stack_id => client.config.opsworks_config[:stack_id]
17
39
  )[:instances]
18
40
  end
19
41
  private :instances
@@ -1,3 +1,3 @@
1
1
  module Opsicle
2
- VERSION = "0.7.1"
2
+ VERSION = "0.8.0"
3
3
  end
@@ -87,8 +87,55 @@ module Opsicle
87
87
 
88
88
  it "returns the instance_ids when a layer is passed in" do
89
89
  options = {:layers => ["main-util"]}
90
+ expect(subject).to receive(:determine_from_layers)
91
+ subject.determine_instance_ids(options)
92
+ end
93
+
94
+ it "returns an instance_id when eip is set to true" do
95
+ options = {:eip => true}
96
+ expect(subject).to receive(:determine_from_eip)
97
+ subject.determine_instance_ids(options)
98
+ end
99
+
100
+ it "returns an instance_id when an ip is passed in" do
101
+ options = {:ip_addresses => true}
102
+ expect(subject).to receive(:determine_from_ips)
103
+ subject.determine_instance_ids(options)
104
+ end
105
+ end
106
+
107
+ context "#determine_from_layer" do
108
+ let(:layers) {["main-util"]}
109
+ before do
110
+ allow(Client).to receive(:new).with('derp').and_return(client)
111
+ end
112
+
113
+ it "returns the instance_ids when a layer is passed in" do
90
114
  allow(Opsicle::Layer).to receive(:instance_ids).and_return(["a1b2c3"])
91
- expect(subject.determine_instance_ids(options)).to eq(["a1b2c3"])
115
+ expect(subject.determine_from_layers(layers)).to eq(["a1b2c3"])
116
+ end
117
+ end
118
+
119
+ context "#determine_from_ips" do
120
+ let(:ips) {['1.2.3.4','5.6.7.8']}
121
+ before do
122
+ allow(Client).to receive(:new).with('derp').and_return(client)
123
+ end
124
+
125
+ it "returns an instance_id when an ip is passed in" do
126
+ allow(Opsicle::Instances).to receive(:find_by_ip).and_return([{instance_id: "a1b2c3"}, {instance_id: "1234567"}])
127
+ expect(subject.determine_from_ips(ips)).to eq(["a1b2c3","1234567"])
128
+ end
129
+ end
130
+
131
+ context "#determine_from_eip" do
132
+ before do
133
+ allow(Client).to receive(:new).with('derp').and_return(client)
134
+ end
135
+ it "returns an instance_id when eip is set to true" do
136
+ eip = true
137
+ allow(Opsicle::Instances).to receive(:find_by_eip).and_return([{instance_id: "a1b2c3"}, {instance_id: "1234567"}])
138
+ expect(subject.determine_from_eip).to eq(["a1b2c3"])
92
139
  end
93
140
  end
94
141
 
@@ -0,0 +1,77 @@
1
+ require "spec_helper"
2
+ require "opsicle"
3
+
4
+ module Opsicle
5
+ describe Instances do
6
+ let(:client) { double }
7
+ let(:config) { double }
8
+
9
+ let(:instance1) { {private_ip: "10.0.0.1", elastic_ip: "100.0.0.1", public_ip: "200.0.0.1"} }
10
+ let(:instance2) { {private_ip: "10.0.0.2", elastic_ip: "100.0.0.2", public_ip: "200.0.0.2"} }
11
+
12
+ subject {Opsicle::Instances}
13
+ before do
14
+ allow_any_instance_of(subject).to receive(:data).and_return([instance1,instance2])
15
+ end
16
+
17
+ context ".instances_matching_ips" do
18
+ it "returns false if no instances have a given ip" do
19
+ expect(subject.send(:instances_matching_ips, instance1, ["10.0.0.4","100.0.0.4"])).to eq(true)
20
+ end
21
+
22
+ it "returns true if an instance hasa given ip" do
23
+ expect(subject.send(:instances_matching_ips, instance1, ["10.0.0.1","100.0.0.4"])).to eq(false)
24
+ end
25
+ end
26
+
27
+ context ".find_by_ip" do
28
+ before do
29
+ allow(subject).to receive(:instances_matching_ips)
30
+ end
31
+
32
+ it "returns nil if no instances have a given ip" do
33
+ allow(subject).to receive(:instances_matching_ips).and_return(true)
34
+ expect(subject.find_by_ip(client,["10.0.0.4","100.0.0.4"])).to eq(nil)
35
+ end
36
+
37
+ it "returns an instance if an instance has a given private_ip" do
38
+ allow(subject).to receive(:instances_matching_ips).and_return(false,true)
39
+ expect(subject.find_by_ip(client,["10.0.0.1","100.0.0.4"])).to eq([instance1])
40
+ end
41
+
42
+ it "returns an instance if an instance has a given public_ip" do
43
+ allow(subject).to receive(:instances_matching_ips).and_return(true,false)
44
+ expect(subject.find_by_ip(client,["100.0.0.2","100.0.0.4"])).to eq([instance2])
45
+ end
46
+
47
+ it "returns multiple instances with a given set of ips" do
48
+ allow(subject).to receive(:instances_matching_ips).and_return(false)
49
+ expect(subject.find_by_ip(client,["100.0.0.2","200.0.0.1"])).to eq([instance1,instance2])
50
+ end
51
+ end
52
+
53
+ context ".find_by_eip" do
54
+ it "returns instances with an elastic_ip" do
55
+ expect(subject.find_by_eip(client)).to eq([instance1,instance2])
56
+ end
57
+
58
+ context "one instance has an elastic_ip" do
59
+ let(:instance2) { {private_ip: "10.0.0.2", public_ip: "200.0.0.2"} }
60
+ it "returns instances with an elastic_ip" do
61
+ expect(subject.find_by_eip(client)).to eq([instance1])
62
+ end
63
+ end
64
+
65
+ context "no instances have an elastic_ip" do
66
+ let(:instance1) { {private_ip: "10.0.0.1", public_ip: "200.0.0.1"} }
67
+ let(:instance2) { {private_ip: "10.0.0.2", public_ip: "200.0.0.2"} }
68
+
69
+ it "returns nil if no instances have a given ip" do
70
+ expect(subject.find_by_eip(client)).to eq(nil)
71
+ end
72
+
73
+ end
74
+ end
75
+
76
+ end
77
+ end
metadata CHANGED
@@ -1,7 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opsicle
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.1
4
+ version: 0.8.0
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Andy Fleener
@@ -9,11 +10,12 @@ authors:
9
10
  autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2014-11-06 00:00:00.000000000 Z
13
+ date: 2014-11-11 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
16
  name: aws-sdk
16
17
  requirement: !ruby/object:Gem::Requirement
18
+ none: false
17
19
  requirements:
18
20
  - - ~>
19
21
  - !ruby/object:Gem::Version
@@ -21,6 +23,7 @@ dependencies:
21
23
  type: :runtime
22
24
  prerelease: false
23
25
  version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
24
27
  requirements:
25
28
  - - ~>
26
29
  - !ruby/object:Gem::Version
@@ -28,6 +31,7 @@ dependencies:
28
31
  - !ruby/object:Gem::Dependency
29
32
  name: gli
30
33
  requirement: !ruby/object:Gem::Requirement
34
+ none: false
31
35
  requirements:
32
36
  - - ~>
33
37
  - !ruby/object:Gem::Version
@@ -35,6 +39,7 @@ dependencies:
35
39
  type: :runtime
36
40
  prerelease: false
37
41
  version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
38
43
  requirements:
39
44
  - - ~>
40
45
  - !ruby/object:Gem::Version
@@ -42,6 +47,7 @@ dependencies:
42
47
  - !ruby/object:Gem::Dependency
43
48
  name: highline
44
49
  requirement: !ruby/object:Gem::Requirement
50
+ none: false
45
51
  requirements:
46
52
  - - ~>
47
53
  - !ruby/object:Gem::Version
@@ -49,6 +55,7 @@ dependencies:
49
55
  type: :runtime
50
56
  prerelease: false
51
57
  version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
52
59
  requirements:
53
60
  - - ~>
54
61
  - !ruby/object:Gem::Version
@@ -56,6 +63,7 @@ dependencies:
56
63
  - !ruby/object:Gem::Dependency
57
64
  name: terminal-table
58
65
  requirement: !ruby/object:Gem::Requirement
66
+ none: false
59
67
  requirements:
60
68
  - - ~>
61
69
  - !ruby/object:Gem::Version
@@ -63,6 +71,7 @@ dependencies:
63
71
  type: :runtime
64
72
  prerelease: false
65
73
  version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
66
75
  requirements:
67
76
  - - ~>
68
77
  - !ruby/object:Gem::Version
@@ -70,6 +79,7 @@ dependencies:
70
79
  - !ruby/object:Gem::Dependency
71
80
  name: minitar
72
81
  requirement: !ruby/object:Gem::Requirement
82
+ none: false
73
83
  requirements:
74
84
  - - ~>
75
85
  - !ruby/object:Gem::Version
@@ -77,6 +87,7 @@ dependencies:
77
87
  type: :runtime
78
88
  prerelease: false
79
89
  version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
80
91
  requirements:
81
92
  - - ~>
82
93
  - !ruby/object:Gem::Version
@@ -84,6 +95,7 @@ dependencies:
84
95
  - !ruby/object:Gem::Dependency
85
96
  name: bundler
86
97
  requirement: !ruby/object:Gem::Requirement
98
+ none: false
87
99
  requirements:
88
100
  - - ~>
89
101
  - !ruby/object:Gem::Version
@@ -91,6 +103,7 @@ dependencies:
91
103
  type: :development
92
104
  prerelease: false
93
105
  version_requirements: !ruby/object:Gem::Requirement
106
+ none: false
94
107
  requirements:
95
108
  - - ~>
96
109
  - !ruby/object:Gem::Version
@@ -98,6 +111,7 @@ dependencies:
98
111
  - !ruby/object:Gem::Dependency
99
112
  name: rake
100
113
  requirement: !ruby/object:Gem::Requirement
114
+ none: false
101
115
  requirements:
102
116
  - - ~>
103
117
  - !ruby/object:Gem::Version
@@ -105,6 +119,7 @@ dependencies:
105
119
  type: :development
106
120
  prerelease: false
107
121
  version_requirements: !ruby/object:Gem::Requirement
122
+ none: false
108
123
  requirements:
109
124
  - - ~>
110
125
  - !ruby/object:Gem::Version
@@ -112,6 +127,7 @@ dependencies:
112
127
  - !ruby/object:Gem::Dependency
113
128
  name: rspec
114
129
  requirement: !ruby/object:Gem::Requirement
130
+ none: false
115
131
  requirements:
116
132
  - - ~>
117
133
  - !ruby/object:Gem::Version
@@ -119,6 +135,7 @@ dependencies:
119
135
  type: :development
120
136
  prerelease: false
121
137
  version_requirements: !ruby/object:Gem::Requirement
138
+ none: false
122
139
  requirements:
123
140
  - - ~>
124
141
  - !ruby/object:Gem::Version
@@ -126,6 +143,7 @@ dependencies:
126
143
  - !ruby/object:Gem::Dependency
127
144
  name: guard
128
145
  requirement: !ruby/object:Gem::Requirement
146
+ none: false
129
147
  requirements:
130
148
  - - ~>
131
149
  - !ruby/object:Gem::Version
@@ -133,6 +151,7 @@ dependencies:
133
151
  type: :development
134
152
  prerelease: false
135
153
  version_requirements: !ruby/object:Gem::Requirement
154
+ none: false
136
155
  requirements:
137
156
  - - ~>
138
157
  - !ruby/object:Gem::Version
@@ -140,6 +159,7 @@ dependencies:
140
159
  - !ruby/object:Gem::Dependency
141
160
  name: guard-rspec
142
161
  requirement: !ruby/object:Gem::Requirement
162
+ none: false
143
163
  requirements:
144
164
  - - ~>
145
165
  - !ruby/object:Gem::Version
@@ -147,6 +167,7 @@ dependencies:
147
167
  type: :development
148
168
  prerelease: false
149
169
  version_requirements: !ruby/object:Gem::Requirement
170
+ none: false
150
171
  requirements:
151
172
  - - ~>
152
173
  - !ruby/object:Gem::Version
@@ -159,11 +180,7 @@ executables:
159
180
  extensions: []
160
181
  extra_rdoc_files: []
161
182
  files:
162
- - LICENSE
163
- - bin/opsicle
164
- - lib/opsicle.rb
165
183
  - lib/opsicle/client.rb
166
- - lib/opsicle/commands.rb
167
184
  - lib/opsicle/commands/chef_update.rb
168
185
  - lib/opsicle/commands/deploy.rb
169
186
  - lib/opsicle/commands/execute_recipes.rb
@@ -171,6 +188,7 @@ files:
171
188
  - lib/opsicle/commands/list_instances.rb
172
189
  - lib/opsicle/commands/ssh.rb
173
190
  - lib/opsicle/commands/ssh_key.rb
191
+ - lib/opsicle/commands.rb
174
192
  - lib/opsicle/config.rb
175
193
  - lib/opsicle/deploy_helper.rb
176
194
  - lib/opsicle/deployment.rb
@@ -178,7 +196,6 @@ files:
178
196
  - lib/opsicle/errors.rb
179
197
  - lib/opsicle/instances.rb
180
198
  - lib/opsicle/layer.rb
181
- - lib/opsicle/monitor.rb
182
199
  - lib/opsicle/monitor/app.rb
183
200
  - lib/opsicle/monitor/panel.rb
184
201
  - lib/opsicle/monitor/panels/deployments.rb
@@ -191,10 +208,14 @@ files:
191
208
  - lib/opsicle/monitor/spy/instances.rb
192
209
  - lib/opsicle/monitor/subpanel.rb
193
210
  - lib/opsicle/monitor/translatable.rb
211
+ - lib/opsicle/monitor.rb
194
212
  - lib/opsicle/output.rb
195
213
  - lib/opsicle/s3_bucket.rb
196
214
  - lib/opsicle/stack.rb
197
215
  - lib/opsicle/version.rb
216
+ - lib/opsicle.rb
217
+ - bin/opsicle
218
+ - LICENSE
198
219
  - spec/opsicle/client_spec.rb
199
220
  - spec/opsicle/commands/chef_update_spec.rb
200
221
  - spec/opsicle/commands/deploy_spec.rb
@@ -205,6 +226,7 @@ files:
205
226
  - spec/opsicle/commands/ssh_spec.rb
206
227
  - spec/opsicle/config_spec.rb
207
228
  - spec/opsicle/errors_spec.rb
229
+ - spec/opsicle/instances_spec.rb
208
230
  - spec/opsicle/layer_spec.rb
209
231
  - spec/opsicle/monitor/app_spec.rb
210
232
  - spec/opsicle/monitor/panel_spec.rb
@@ -216,26 +238,27 @@ files:
216
238
  homepage: https://github.com/sportngin/opsicle
217
239
  licenses:
218
240
  - MIT
219
- metadata: {}
220
241
  post_install_message:
221
242
  rdoc_options: []
222
243
  require_paths:
223
244
  - lib
224
245
  required_ruby_version: !ruby/object:Gem::Requirement
246
+ none: false
225
247
  requirements:
226
248
  - - ! '>='
227
249
  - !ruby/object:Gem::Version
228
250
  version: '0'
229
251
  required_rubygems_version: !ruby/object:Gem::Requirement
252
+ none: false
230
253
  requirements:
231
254
  - - ! '>='
232
255
  - !ruby/object:Gem::Version
233
256
  version: '0'
234
257
  requirements: []
235
258
  rubyforge_project:
236
- rubygems_version: 2.2.2
259
+ rubygems_version: 1.8.25
237
260
  signing_key:
238
- specification_version: 4
261
+ specification_version: 3
239
262
  summary: An opsworks specific abstraction on top of the aws sdk
240
263
  test_files:
241
264
  - spec/opsicle/client_spec.rb
@@ -248,6 +271,7 @@ test_files:
248
271
  - spec/opsicle/commands/ssh_spec.rb
249
272
  - spec/opsicle/config_spec.rb
250
273
  - spec/opsicle/errors_spec.rb
274
+ - spec/opsicle/instances_spec.rb
251
275
  - spec/opsicle/layer_spec.rb
252
276
  - spec/opsicle/monitor/app_spec.rb
253
277
  - spec/opsicle/monitor/panel_spec.rb
checksums.yaml DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- YzdlMWE1YmRhMzZmNWJkYWM0MmI0OWRhN2VmODZjMmYxYjA5NDM3NQ==
5
- data.tar.gz: !binary |-
6
- NGYzZGVhY2RkZjM3NzRiNzdmZWRjZmQ0NTNiNTZjNzNlZDRmMDA3OQ==
7
- SHA512:
8
- metadata.gz: !binary |-
9
- Y2QwZjVkN2FiMjA4YWZiZGFjZjkxNmY3ZjU1MWY1ZDdhZDBhMWM2MDYxNmVm
10
- NjExMTFiMDJjZDliMDVlNjc5YTYyZDQ1NjU2ZDU1OWJiMmIwNmIyNTk5MGIx
11
- YzRkYzE0YTg5NmFkN2U2OTcwNzEwMGZjMjc1ZWJmNGQ4ZTQ4YTI=
12
- data.tar.gz: !binary |-
13
- OTRjMGNjZTJmODI5YWMyMjY5ZWI3MzMyZWJiNjg1OWE5NjdmZWYyYzQ2NGU5
14
- M2NkMzYxZmZjMWY1ZjE0NmVmZDhkYjk0OTk3ODBlMzI2NGJjNzI4ZTVlNTRl
15
- Y2ViNzAzNjAyNzM1MTU1ZjgyNzFmYTQ0NjhlYzZiZDc1ZTc4MjQ=