opsicle 2.9.6 → 2.10.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 +4 -4
- data/bin/opsicle +45 -1
- data/lib/opsicle/commands.rb +10 -5
- data/lib/opsicle/commands/add_tags.rb +59 -0
- data/lib/opsicle/commands/clone_instance.rb +6 -6
- data/lib/opsicle/commands/create_instance.rb +46 -0
- data/lib/opsicle/commands/delete_instance.rb +55 -0
- data/lib/opsicle/commands/move_eip.rb +24 -0
- data/lib/opsicle/commands/stop_instance.rb +54 -0
- data/lib/opsicle/commands/update.rb +1 -1
- data/lib/opsicle/config.rb +7 -4
- data/lib/opsicle/creatable_instance.rb +200 -0
- data/lib/opsicle/{cloneable_instance.rb → manageable_instance.rb} +35 -3
- data/lib/opsicle/{cloneable_layer.rb → manageable_layer.rb} +3 -3
- data/lib/opsicle/manageable_stack.rb +83 -0
- data/lib/opsicle/version.rb +1 -1
- data/spec/opsicle/commands/clone_instance_spec.rb +1 -0
- data/spec/opsicle/commands/delete_instance_spec.rb +81 -0
- data/spec/opsicle/{cloneable_instance_spec.rb → manageable_instance_spec.rb} +17 -17
- data/spec/opsicle/{cloneable_layer_spec.rb → manageable_layer_spec.rb} +8 -8
- data/spec/opsicle/{cloneable_stack_spec.rb → manageable_stack_spec.rb} +2 -2
- metadata +20 -12
- data/lib/opsicle/cloneable_stack.rb +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f351c978f6ecef8f39e1bcaedf071d57766f8fca
|
4
|
+
data.tar.gz: fb2f615938ab86f7fc8cd431670511ffe0f78f01
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d9d7ff9546d924d2bcd8f29786c7d6e8368485f8173a77f013a11dd142dc2f96f1df8337d000f0b5cd300b0a781fa7d36e13f70d805f505ab1070e2d5e4157f
|
7
|
+
data.tar.gz: 264695840f0389211f6f3bbc6252d16c2cd1078d3f5bb3e9d1dd5ddce19d6d39ff3484f4f8b2be8e0f6d5a34f897959527584e2dde3c183be3de0e4948e31fb3
|
data/bin/opsicle
CHANGED
@@ -203,6 +203,51 @@ command 'clone-instance' do |c|
|
|
203
203
|
end
|
204
204
|
end
|
205
205
|
|
206
|
+
desc "Create an instance in the given environment stack"
|
207
|
+
arg_name '<environment>'
|
208
|
+
command 'create-instance' do |c|
|
209
|
+
c.action do |global_options, options, args|
|
210
|
+
raise ArgumentError, "Environment is required" unless args.first
|
211
|
+
Opsicle::CreateInstance.new(args.first).execute global_options.merge options
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
desc "Delete stopped instances in the given environment stack"
|
216
|
+
arg_name '<environment>'
|
217
|
+
command 'delete-instance' do |c|
|
218
|
+
c.action do |global_options, options, args|
|
219
|
+
raise ArgumentError, "Environment is required" unless args.first
|
220
|
+
Opsicle::DeleteInstance.new(args.first).execute global_options.merge options
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
desc "Stop instances in the given environment stack(only instances without EIPs)"
|
225
|
+
arg_name '<environment>'
|
226
|
+
command 'stop-instance' do |c|
|
227
|
+
c.action do |global_options, options, args|
|
228
|
+
raise ArgumentError, "Environment is required" unless args.first
|
229
|
+
Opsicle::StopInstance.new(args.first).execute global_options.merge options
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
desc "Move EIPs between instances"
|
234
|
+
arg_name '<environment>'
|
235
|
+
command 'move-eip' do |c|
|
236
|
+
c.action do |global_options, options, args|
|
237
|
+
raise ArgumentError, "Environment is required" unless args.first
|
238
|
+
Opsicle::MoveEip.new(args.first).execute global_options.merge options
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
desc "Add tags to existing instances in the given environment stack"
|
243
|
+
arg_name '<environment>'
|
244
|
+
command 'add-tags' do |c|
|
245
|
+
c.action do |global_options, options, args|
|
246
|
+
raise ArgumentError, "Environment is required" unless args.first
|
247
|
+
Opsicle::AddTags.new(args.first).execute global_options.merge options
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
206
251
|
desc "List all instances in the given environment stack"
|
207
252
|
arg_name '<environment>'
|
208
253
|
command :instances do |c|
|
@@ -212,7 +257,6 @@ command :instances do |c|
|
|
212
257
|
end
|
213
258
|
end
|
214
259
|
|
215
|
-
|
216
260
|
desc "Update properties on a OpsWorks resource."
|
217
261
|
arg_name '<environment> <type>'
|
218
262
|
command 'update' do |c|
|
data/lib/opsicle/commands.rb
CHANGED
@@ -1,15 +1,20 @@
|
|
1
1
|
require 'opsicle/client'
|
2
2
|
|
3
|
-
require "opsicle/commands/
|
3
|
+
require "opsicle/commands/add_tags"
|
4
4
|
require "opsicle/commands/chef_update"
|
5
5
|
require "opsicle/commands/clone_instance"
|
6
|
+
require "opsicle/commands/create_instance"
|
7
|
+
require "opsicle/commands/delete_instance"
|
8
|
+
require "opsicle/commands/deploy"
|
6
9
|
require "opsicle/commands/execute_recipes"
|
10
|
+
require "opsicle/commands/failure_log"
|
11
|
+
require "opsicle/commands/legacy_credential_converter"
|
7
12
|
require "opsicle/commands/list"
|
8
13
|
require "opsicle/commands/list_instances"
|
9
|
-
require "opsicle/commands/
|
14
|
+
require "opsicle/commands/move_eip"
|
10
15
|
require "opsicle/commands/ssh"
|
11
|
-
require "opsicle/commands/ssh_key"
|
12
16
|
require "opsicle/commands/ssh_clean_keys"
|
17
|
+
require "opsicle/commands/ssh_key"
|
18
|
+
require "opsicle/commands/stop_instance"
|
19
|
+
require "opsicle/commands/update"
|
13
20
|
require "opsicle/commands/user_profile_info"
|
14
|
-
require "opsicle/commands/legacy_credential_converter"
|
15
|
-
require "opsicle/commands/failure_log"
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'gli'
|
2
|
+
require "opsicle/user_profile"
|
3
|
+
require "opsicle/manageable_layer"
|
4
|
+
require "opsicle/manageable_instance"
|
5
|
+
require "opsicle/manageable_stack"
|
6
|
+
|
7
|
+
module Opsicle
|
8
|
+
class AddTags
|
9
|
+
|
10
|
+
def initialize(environment)
|
11
|
+
@client = Client.new(environment)
|
12
|
+
@opsworks = @client.opsworks
|
13
|
+
@ec2 = @client.ec2
|
14
|
+
stack_id = @client.config.opsworks_config[:stack_id]
|
15
|
+
@stack = ManageableStack.new(@client.config.opsworks_config[:stack_id], @opsworks)
|
16
|
+
@cli = HighLine.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def execute(options={})
|
20
|
+
puts "Stack ID = #{@stack.id}"
|
21
|
+
layer = select_layer
|
22
|
+
all_instances = layer.get_cloneable_instances
|
23
|
+
instances_to_add_tags = select_instances(all_instances)
|
24
|
+
add_tags_to_instances(instances_to_add_tags)
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_tags_to_instances(instances)
|
28
|
+
instances.each { |instance| instance.add_tags({add_tags_mode: true}) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def select_layer
|
32
|
+
puts "\nLayers:\n"
|
33
|
+
ops_layers = @opsworks.describe_layers({ :stack_id => @stack.id }).layers
|
34
|
+
|
35
|
+
layers = []
|
36
|
+
ops_layers.each do |layer|
|
37
|
+
layers << ManageableLayer.new(layer.name, layer.layer_id, @stack, @opsworks, @ec2, @cli)
|
38
|
+
end
|
39
|
+
|
40
|
+
layers.each_with_index { |layer, index| puts "#{index.to_i + 1}) #{layer.name}" }
|
41
|
+
layer_index = @cli.ask("Layer?\n", Integer) { |q| q.in = 1..layers.length.to_i } - 1
|
42
|
+
layers[layer_index]
|
43
|
+
end
|
44
|
+
|
45
|
+
def select_instances(instances)
|
46
|
+
puts "\nInstances:\n"
|
47
|
+
instances.each_with_index { |instance, index| puts "#{index.to_i + 1}) #{instance.status} - #{instance.hostname}" }
|
48
|
+
instance_indices_string = @cli.ask("Instances? (enter as a comma separated list)\n", String)
|
49
|
+
instance_indices_list = instance_indices_string.split(/,\s*/)
|
50
|
+
instance_indices_list.map! { |instance_index| instance_index.to_i - 1 }
|
51
|
+
|
52
|
+
return_array = []
|
53
|
+
instance_indices_list.each do |index|
|
54
|
+
return_array << instances[index]
|
55
|
+
end
|
56
|
+
return_array
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
require 'gli'
|
2
2
|
require "opsicle/user_profile"
|
3
|
-
require "opsicle/
|
4
|
-
require "opsicle/
|
5
|
-
require "opsicle/
|
3
|
+
require "opsicle/manageable_layer"
|
4
|
+
require "opsicle/manageable_instance"
|
5
|
+
require "opsicle/manageable_stack"
|
6
6
|
|
7
7
|
module Opsicle
|
8
8
|
class CloneInstance
|
@@ -12,7 +12,7 @@ module Opsicle
|
|
12
12
|
@opsworks = @client.opsworks
|
13
13
|
@ec2 = @client.ec2
|
14
14
|
stack_id = @client.config.opsworks_config[:stack_id]
|
15
|
-
@stack =
|
15
|
+
@stack = ManageableStack.new(@client.config.opsworks_config[:stack_id], @opsworks)
|
16
16
|
@cli = HighLine.new
|
17
17
|
end
|
18
18
|
|
@@ -40,10 +40,10 @@ module Opsicle
|
|
40
40
|
|
41
41
|
layers = []
|
42
42
|
ops_layers.each do |layer|
|
43
|
-
layers <<
|
43
|
+
layers << ManageableLayer.new(layer.name, layer.layer_id, @stack, @opsworks, @ec2, @cli)
|
44
44
|
end
|
45
45
|
|
46
|
-
layers.each_with_index { |layer, index| puts "#{index.to_i + 1}) #{layer.name}"}
|
46
|
+
layers.each_with_index { |layer, index| puts "#{index.to_i + 1}) #{layer.name}" }
|
47
47
|
layer_index = @cli.ask("Layer?\n", Integer) { |q| q.in = 1..layers.length.to_i } - 1
|
48
48
|
layers[layer_index]
|
49
49
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'gli'
|
2
|
+
require "opsicle/user_profile"
|
3
|
+
require "opsicle/manageable_layer"
|
4
|
+
require "opsicle/manageable_instance"
|
5
|
+
require "opsicle/manageable_stack"
|
6
|
+
|
7
|
+
module Opsicle
|
8
|
+
class CreateInstance
|
9
|
+
|
10
|
+
def initialize(environment)
|
11
|
+
@client = Client.new(environment)
|
12
|
+
@opsworks = @client.opsworks
|
13
|
+
@ec2 = @client.ec2
|
14
|
+
stack_id = @client.config.opsworks_config[:stack_id]
|
15
|
+
@stack = ManageableStack.new(@client.config.opsworks_config[:stack_id], @opsworks)
|
16
|
+
@cli = HighLine.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def execute(options={})
|
20
|
+
puts "Stack ID = #{@stack.id}"
|
21
|
+
layer = select_layer
|
22
|
+
layer.get_cloneable_instances
|
23
|
+
create_instance(layer, options)
|
24
|
+
layer.ami_id = nil
|
25
|
+
layer.agent_version = nil
|
26
|
+
end
|
27
|
+
|
28
|
+
def create_instance(layer, options)
|
29
|
+
CreatableInstance.new(layer, @stack, @opsworks, @ec2, @cli).create(options)
|
30
|
+
end
|
31
|
+
|
32
|
+
def select_layer
|
33
|
+
puts "\nLayers:\n"
|
34
|
+
ops_layers = @opsworks.describe_layers({ :stack_id => @stack.id }).layers
|
35
|
+
|
36
|
+
layers = []
|
37
|
+
ops_layers.each do |layer|
|
38
|
+
layers << ManageableLayer.new(layer.name, layer.layer_id, @stack, @opsworks, @ec2, @cli)
|
39
|
+
end
|
40
|
+
|
41
|
+
layers.each_with_index { |layer, index| puts "#{index.to_i + 1}) #{layer.name}" }
|
42
|
+
layer_index = @cli.ask("Layer?\n", Integer) { |q| q.in = 1..layers.length.to_i } - 1
|
43
|
+
layers[layer_index]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'gli'
|
2
|
+
require "opsicle/user_profile"
|
3
|
+
require "opsicle/manageable_layer"
|
4
|
+
require "opsicle/manageable_instance"
|
5
|
+
require "opsicle/manageable_stack"
|
6
|
+
|
7
|
+
module Opsicle
|
8
|
+
class DeleteInstance
|
9
|
+
|
10
|
+
def initialize(environment)
|
11
|
+
@client = Client.new(environment)
|
12
|
+
@opsworks = @client.opsworks
|
13
|
+
@ec2 = @client.ec2
|
14
|
+
stack_id = @client.config.opsworks_config[:stack_id]
|
15
|
+
@stack = ManageableStack.new(@client.config.opsworks_config[:stack_id], @opsworks)
|
16
|
+
@cli = HighLine.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def execute(options={})
|
20
|
+
puts "Stack ID = #{@stack.id}"
|
21
|
+
instances_to_delete = select_instances
|
22
|
+
instances_to_delete.each do |instance|
|
23
|
+
begin
|
24
|
+
@opsworks.delete_instance(instance_id: instance.instance_id)
|
25
|
+
puts "Successfully deleted #{instance.hostname}"
|
26
|
+
rescue
|
27
|
+
puts "Failed to delete #{instance.hostname}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def deleteable_instances
|
33
|
+
@stack.deleteable_instances
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
def select_instances
|
38
|
+
instances = deleteable_instances
|
39
|
+
return_array = []
|
40
|
+
if instances.empty?
|
41
|
+
puts "There are no deletable instances"
|
42
|
+
else
|
43
|
+
puts "\nDeleteable Instances:\n"
|
44
|
+
instances.each_with_index { |instance, index| puts "#{index.to_i + 1}) #{instance.status} - #{instance.hostname}" }
|
45
|
+
instance_indices_string = @cli.ask("Which instances would you like to delete? (enter as a comma separated list)\n", String)
|
46
|
+
instance_indices_list = instance_indices_string.split(/,\s*/)
|
47
|
+
instance_indices_list.map! { |instance_index| instance_index.to_i - 1 }
|
48
|
+
instance_indices_list.each do |index|
|
49
|
+
return_array << instances[index]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
return_array
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'gli'
|
2
|
+
require "opsicle/user_profile"
|
3
|
+
require "opsicle/manageable_layer"
|
4
|
+
require "opsicle/manageable_instance"
|
5
|
+
require "opsicle/manageable_stack"
|
6
|
+
|
7
|
+
module Opsicle
|
8
|
+
class MoveEip
|
9
|
+
|
10
|
+
def initialize(environment)
|
11
|
+
@client = Client.new(environment)
|
12
|
+
@opsworks = @client.opsworks
|
13
|
+
@ec2 = @client.ec2
|
14
|
+
stack_id = @client.config.opsworks_config[:stack_id]
|
15
|
+
@cli = HighLine.new
|
16
|
+
@stack = ManageableStack.new(@client.config.opsworks_config[:stack_id], @opsworks, @cli)
|
17
|
+
end
|
18
|
+
|
19
|
+
def execute(options={})
|
20
|
+
puts "Stack ID = #{@stack.id}"
|
21
|
+
@stack.move_eip
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'gli'
|
2
|
+
require "opsicle/user_profile"
|
3
|
+
require "opsicle/manageable_layer"
|
4
|
+
require "opsicle/manageable_instance"
|
5
|
+
require "opsicle/manageable_stack"
|
6
|
+
|
7
|
+
module Opsicle
|
8
|
+
class StopInstance
|
9
|
+
|
10
|
+
def initialize(environment)
|
11
|
+
@client = Client.new(environment)
|
12
|
+
@opsworks = @client.opsworks
|
13
|
+
@ec2 = @client.ec2
|
14
|
+
stack_id = @client.config.opsworks_config[:stack_id]
|
15
|
+
@stack = ManageableStack.new(@client.config.opsworks_config[:stack_id], @opsworks)
|
16
|
+
@cli = HighLine.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def execute(options={})
|
20
|
+
puts "Stack ID = #{@stack.id}"
|
21
|
+
instances_to_stop = select_instances
|
22
|
+
instances_to_stop.each do |instance|
|
23
|
+
begin
|
24
|
+
@opsworks.stop_instance(instance_id: instance.instance_id)
|
25
|
+
puts "Stopping instance #{instance.hostname}..."
|
26
|
+
rescue
|
27
|
+
puts "Failed to stop #{instance.hostname}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def stoppable_instances
|
33
|
+
@stack.stoppable_instances
|
34
|
+
end
|
35
|
+
|
36
|
+
def select_instances
|
37
|
+
instances = stoppable_instances
|
38
|
+
return_array = []
|
39
|
+
if instances.empty?
|
40
|
+
puts "There are no stoppable instances"
|
41
|
+
else
|
42
|
+
puts "\nStoppable Instances:\n"
|
43
|
+
instances.each_with_index { |instance, index| puts "#{index.to_i + 1}) #{instance.status} - #{instance.hostname}" }
|
44
|
+
instance_indices_string = @cli.ask("Which instances would you like to stop? (enter as a comma separated list)\n", String)
|
45
|
+
instance_indices_list = instance_indices_string.split(/,\s*/)
|
46
|
+
instance_indices_list.map! { |instance_index| instance_index.to_i - 1 }
|
47
|
+
instance_indices_list.each do |index|
|
48
|
+
return_array << instances[index]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
return_array
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/opsicle/config.rb
CHANGED
@@ -36,6 +36,10 @@ module Opsicle
|
|
36
36
|
env_config
|
37
37
|
end
|
38
38
|
|
39
|
+
def mfa_required
|
40
|
+
return opsworks_config[:mfa_required] || $use_mfa
|
41
|
+
end
|
42
|
+
|
39
43
|
def get_mfa_token
|
40
44
|
return @token if @token
|
41
45
|
@token = Output.ask("Enter MFA token: "){ |q| q.validate = /^\d{6}$/ }
|
@@ -81,9 +85,9 @@ module Opsicle
|
|
81
85
|
|
82
86
|
iam = Aws::IAM::Client.new
|
83
87
|
|
84
|
-
|
85
|
-
|
86
|
-
if
|
88
|
+
# this will be an array of 0 or 1 because iam.list_mfa_devices.mfa_devices will only return 0 or 1 device per user;
|
89
|
+
# if user doesn't have MFA enabled, then this loop won't even execute
|
90
|
+
if mfa_required
|
87
91
|
iam.list_mfa_devices.mfa_devices.each do |mfadevice|
|
88
92
|
mfa_serial_number = mfadevice.serial_number
|
89
93
|
get_mfa_token
|
@@ -112,6 +116,5 @@ module Opsicle
|
|
112
116
|
|
113
117
|
MissingConfig = Class.new(StandardError)
|
114
118
|
MissingEnvironment = Class.new(StandardError)
|
115
|
-
|
116
119
|
end
|
117
120
|
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
module Opsicle
|
2
|
+
class CreatableInstance
|
3
|
+
attr_accessor :layer, :stack, :new_instance_id, :opsworks, :ec2, :cli
|
4
|
+
|
5
|
+
def initialize(layer, stack, opsworks, ec2, cli)
|
6
|
+
self.layer = layer
|
7
|
+
self.stack = stack
|
8
|
+
self.opsworks = opsworks
|
9
|
+
self.ec2 = ec2
|
10
|
+
self.cli = cli
|
11
|
+
self.new_instance_id = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def create(options)
|
15
|
+
puts "\nCreating an instance..."
|
16
|
+
|
17
|
+
new_instance_hostname = make_new_hostname
|
18
|
+
puts ""
|
19
|
+
ami_id = select_ami_id
|
20
|
+
puts ""
|
21
|
+
agent_version = select_agent_version
|
22
|
+
puts ""
|
23
|
+
subnet_id = select_subnet_id
|
24
|
+
puts ""
|
25
|
+
instance_type = ask_for_new_option('instance type')
|
26
|
+
puts ""
|
27
|
+
|
28
|
+
create_new_instance(new_instance_hostname, instance_type, ami_id, agent_version, subnet_id)
|
29
|
+
start_new_instance
|
30
|
+
end
|
31
|
+
|
32
|
+
def make_new_hostname
|
33
|
+
new_instance_hostname = auto_generated_hostname
|
34
|
+
puts "\nAutomatically generated hostname: #{new_instance_hostname}\n"
|
35
|
+
new_instance_hostname = ask_for_new_option("instance's hostname") if ask_for_overriding_permission("hostname", false)
|
36
|
+
new_instance_hostname
|
37
|
+
end
|
38
|
+
|
39
|
+
def hostname
|
40
|
+
self.layer.instances.first.hostname
|
41
|
+
end
|
42
|
+
|
43
|
+
def auto_generated_hostname
|
44
|
+
if hostname =~ /\d\d\z/
|
45
|
+
increment_hostname
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def sibling_hostnames
|
50
|
+
self.layer.instances.collect { |instance| instance.hostname }
|
51
|
+
end
|
52
|
+
|
53
|
+
def increment_hostname
|
54
|
+
name = hostname
|
55
|
+
until hostname_unique?(name) do
|
56
|
+
name = name.gsub(/(\d\d\z)/) { "#{($1.to_i + 1).to_s.rjust(2, '0')}" }
|
57
|
+
end
|
58
|
+
name
|
59
|
+
end
|
60
|
+
|
61
|
+
def sibling_hostnames
|
62
|
+
self.layer.instances.map(&:hostname)
|
63
|
+
end
|
64
|
+
|
65
|
+
def hostname_unique?(name)
|
66
|
+
!sibling_hostnames.include?(name)
|
67
|
+
end
|
68
|
+
|
69
|
+
def find_subnet_name(subnet)
|
70
|
+
tags = subnet.tags
|
71
|
+
tag = nil
|
72
|
+
tags.each { |t| tag = t if t.key == 'Name' }
|
73
|
+
tag.value if tag
|
74
|
+
end
|
75
|
+
|
76
|
+
def select_ami_id
|
77
|
+
instances = @opsworks.describe_instances(stack_id: @stack.id).instances
|
78
|
+
ami_ids = instances.collect { |i| i.ami_id }.uniq
|
79
|
+
ami_ids << "Provide a different AMI ID."
|
80
|
+
ami_id = ask_for_possible_options(ami_ids, "AMI ID")
|
81
|
+
|
82
|
+
if ami_id == "Provide a different AMI ID."
|
83
|
+
ami_id = ask_for_new_option('AMI ID')
|
84
|
+
end
|
85
|
+
|
86
|
+
self.layer.ami_id = ami_id
|
87
|
+
|
88
|
+
ami_id
|
89
|
+
end
|
90
|
+
|
91
|
+
def select_agent_version
|
92
|
+
agents = @opsworks.describe_agent_versions(stack_id: @stack.id).agent_versions
|
93
|
+
version_ids = agents.collect { |i| i.version }.uniq
|
94
|
+
agent_version = ask_for_possible_options(version_ids, "agent version")
|
95
|
+
self.layer.agent_version = agent_version
|
96
|
+
agent_version
|
97
|
+
end
|
98
|
+
|
99
|
+
def select_subnet_id
|
100
|
+
ec2_subnets = ec2.describe_subnets.subnets
|
101
|
+
subnets = []
|
102
|
+
|
103
|
+
ec2_subnets.each do |subnet|
|
104
|
+
if subnet.vpc_id == stack.vpc_id
|
105
|
+
subnet_name = find_subnet_name(subnet)
|
106
|
+
zone_name = subnet.availability_zone
|
107
|
+
subnet_id = subnet.subnet_id
|
108
|
+
subnets << "\"#{subnet_name}\" #{zone_name} (#{subnet_id})"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
subnets = subnets.sort
|
113
|
+
subnet_id = ask_for_possible_options(subnets, "subnet ID")
|
114
|
+
subnet_id = subnet_id.scan(/(subnet-[a-z0-9]*)/).first.first if subnet_id
|
115
|
+
|
116
|
+
self.layer.subnet_id = subnet_id
|
117
|
+
subnet_id
|
118
|
+
end
|
119
|
+
|
120
|
+
def os
|
121
|
+
self.layer.instances.first.os
|
122
|
+
end
|
123
|
+
|
124
|
+
def ask_for_possible_options(arr, description)
|
125
|
+
arr.each_with_index { |id, index| puts "#{index.to_i + 1}) #{id}"}
|
126
|
+
id_index = @cli.ask("Which #{description}?\n", Integer) { |q| q.in = 1..arr.length.to_i } - 1
|
127
|
+
arr[id_index]
|
128
|
+
end
|
129
|
+
|
130
|
+
def ask_for_new_option(description)
|
131
|
+
@cli.ask("Please write in the new #{description} and press ENTER:")
|
132
|
+
end
|
133
|
+
|
134
|
+
def ask_for_overriding_permission(description, overriding_all)
|
135
|
+
if overriding_all
|
136
|
+
ans = @cli.ask("Do you wish to override this #{description}? By overriding, you are choosing to override the current #{description} for all of the following instances you're cloning.\n1) Yes\n2) No", Integer)
|
137
|
+
else
|
138
|
+
ans = @cli.ask("Do you wish to override this #{description}?\n1) Yes\n2) No", Integer)
|
139
|
+
end
|
140
|
+
ans == 1
|
141
|
+
end
|
142
|
+
|
143
|
+
def create_new_instance(new_instance_hostname, instance_type, ami_id, agent_version, subnet_id)
|
144
|
+
new_instance = @opsworks.create_instance({
|
145
|
+
stack_id: self.stack.id, # required
|
146
|
+
layer_ids: [self.layer.layer_id], # required
|
147
|
+
instance_type: instance_type, # required
|
148
|
+
hostname: new_instance_hostname,
|
149
|
+
ami_id: ami_id,
|
150
|
+
subnet_id: subnet_id,
|
151
|
+
agent_version: agent_version,
|
152
|
+
os: os
|
153
|
+
})
|
154
|
+
self.new_instance_id = new_instance.instance_id
|
155
|
+
self.layer.add_new_instance(new_instance_id)
|
156
|
+
puts "New instance #{new_instance_hostname} has been created: #{new_instance_id}"
|
157
|
+
end
|
158
|
+
|
159
|
+
def start_new_instance
|
160
|
+
if ask_to_start_instance
|
161
|
+
@opsworks.start_instance(instance_id: self.new_instance_id)
|
162
|
+
puts "\nNew instance is starting…"
|
163
|
+
add_tags
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def add_tags
|
168
|
+
if ask_to_add_tags
|
169
|
+
tags = []
|
170
|
+
|
171
|
+
tag_count.times do
|
172
|
+
tags << define_tag
|
173
|
+
end
|
174
|
+
|
175
|
+
ec2_instance_id = @opsworks.describe_instances(instance_ids: [new_instance_id]).instances.first.ec2_instance_id
|
176
|
+
@ec2.create_tags(resources: [ ec2_instance_id ], tags: tags)
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def define_tag
|
181
|
+
tag_key = ask_for_new_option('tag name')
|
182
|
+
tag_value = ask_for_new_option('tag value')
|
183
|
+
{ key: tag_key, value: tag_value }
|
184
|
+
end
|
185
|
+
|
186
|
+
def tag_count
|
187
|
+
@cli.ask("How many tags do you wish to add? Please write in the number as an integer and press ENTER:").to_i
|
188
|
+
end
|
189
|
+
|
190
|
+
def ask_to_add_tags
|
191
|
+
ans = @cli.ask("Do you wish to add EC2 tags to this instance?\n1) Yes\n2) No", Integer)
|
192
|
+
ans == 1
|
193
|
+
end
|
194
|
+
|
195
|
+
def ask_to_start_instance
|
196
|
+
ans = @cli.ask("Do you wish to start this new instance?\n1) Yes\n2) No", Integer)
|
197
|
+
ans == 1
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Opsicle
|
2
|
-
class
|
2
|
+
class ManageableInstance
|
3
3
|
attr_accessor(
|
4
4
|
:hostname,
|
5
5
|
:status,
|
@@ -75,6 +75,7 @@ module Opsicle
|
|
75
75
|
new_hostname = auto_generated_hostname
|
76
76
|
create_new_instance(new_hostname, instance_type, ami_id, agent_version, subnet_id)
|
77
77
|
opsworks.start_instance(instance_id: new_instance_id)
|
78
|
+
add_tags
|
78
79
|
puts "\nNew instance is starting…"
|
79
80
|
end
|
80
81
|
|
@@ -155,7 +156,7 @@ module Opsicle
|
|
155
156
|
agents = @opsworks.describe_agent_versions(stack_id: self.stack_id).agent_versions
|
156
157
|
version_ids = agents.collect { |i| i.version }.uniq
|
157
158
|
agent_version = ask_for_possible_options(version_ids, "agent version")
|
158
|
-
|
159
|
+
|
159
160
|
self.layer.agent_version = agent_version # only set agent version for whole layer if they override
|
160
161
|
else
|
161
162
|
agent_version = self.agent_version
|
@@ -189,7 +190,7 @@ module Opsicle
|
|
189
190
|
subnets = subnets.sort
|
190
191
|
subnet_id = ask_for_possible_options(subnets, "subnet ID")
|
191
192
|
subnet_id = subnet_id.scan(/(subnet-[a-z0-9]*)/).first.first if subnet_id
|
192
|
-
|
193
|
+
|
193
194
|
self.layer.subnet_id = subnet_id # only set the subnet ID for whole layer if they override it
|
194
195
|
else
|
195
196
|
subnet_id = self.subnet_id
|
@@ -254,9 +255,40 @@ module Opsicle
|
|
254
255
|
if ask_to_start_instance
|
255
256
|
@opsworks.start_instance(instance_id: self.new_instance_id)
|
256
257
|
puts "\nNew instance is starting…"
|
258
|
+
add_tags
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def add_tags(options={})
|
263
|
+
raise ArgumentError, 'The instance must be running to add tags' if options[:add_tags_mode] && @status != "online"
|
264
|
+
|
265
|
+
if ask_to_add_tags
|
266
|
+
tags = []
|
267
|
+
|
268
|
+
tag_count.times do
|
269
|
+
tags << define_tag
|
270
|
+
end
|
271
|
+
|
272
|
+
ec2_instance_id = @opsworks.describe_instances(instance_ids: [new_instance_id || instance_id]).instances.first.ec2_instance_id
|
273
|
+
@ec2.create_tags(resources: [ ec2_instance_id ], tags: tags)
|
257
274
|
end
|
258
275
|
end
|
259
276
|
|
277
|
+
def define_tag
|
278
|
+
tag_key = ask_for_new_option('tag name')
|
279
|
+
tag_value = ask_for_new_option('tag value')
|
280
|
+
{ key: tag_key, value: tag_value }
|
281
|
+
end
|
282
|
+
|
283
|
+
def tag_count
|
284
|
+
@cli.ask("How many tags do you wish to add? Please write in the number as an integer and press ENTER:").to_i
|
285
|
+
end
|
286
|
+
|
287
|
+
def ask_to_add_tags
|
288
|
+
ans = @cli.ask("\nDo you wish to add EC2 tags to this instance?\n1) Yes\n2) No", Integer)
|
289
|
+
ans == 1
|
290
|
+
end
|
291
|
+
|
260
292
|
def ask_to_start_instance
|
261
293
|
ans = @cli.ask("Do you wish to start this new instance?\n1) Yes\n2) No", Integer)
|
262
294
|
ans == 1
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Opsicle
|
2
|
-
class
|
2
|
+
class ManageableLayer
|
3
3
|
attr_accessor :name, :layer_id, :stack, :instances, :opsworks, :ec2, :cli, :agent_version, :ami_id, :subnet_id
|
4
4
|
|
5
5
|
def initialize(name, layer_id, stack, opsworks, ec2, cli)
|
@@ -15,14 +15,14 @@ module Opsicle
|
|
15
15
|
def get_cloneable_instances
|
16
16
|
ops_instances = @opsworks.describe_instances({ :layer_id => layer_id }).instances
|
17
17
|
ops_instances.each do |instance|
|
18
|
-
self.instances <<
|
18
|
+
self.instances << ManageableInstance.new(instance, self, stack, @opsworks, @ec2, @cli)
|
19
19
|
end
|
20
20
|
self.instances
|
21
21
|
end
|
22
22
|
|
23
23
|
def add_new_instance(instance_id)
|
24
24
|
instance = @opsworks.describe_instances({ :instance_ids => [instance_id] }).instances.first
|
25
|
-
self.instances <<
|
25
|
+
self.instances << ManageableInstance.new(instance, self, stack, @opsworks, @ec2, @cli)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Opsicle
|
2
|
+
class ManageableStack
|
3
|
+
attr_accessor :id, :opsworks, :stack, :vpc_id, :eips, :cli
|
4
|
+
|
5
|
+
def initialize(stack_id, opsworks, cli=nil)
|
6
|
+
self.id = stack_id
|
7
|
+
self.opsworks = opsworks
|
8
|
+
self.cli = cli
|
9
|
+
self.stack = get_stack
|
10
|
+
self.vpc_id = self.stack.vpc_id
|
11
|
+
self.eips = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_stack
|
15
|
+
@opsworks.describe_stacks({ :stack_ids => [self.id.to_s] }).stacks.first
|
16
|
+
end
|
17
|
+
|
18
|
+
def get_eips
|
19
|
+
self.eips = @opsworks.describe_elastic_ips(stack_id: self.id.to_s).elastic_ips
|
20
|
+
end
|
21
|
+
|
22
|
+
def gather_eip_information
|
23
|
+
eip_information = []
|
24
|
+
|
25
|
+
@eips.each do |eip|
|
26
|
+
instance_id = eip.instance_id
|
27
|
+
instance = @opsworks.describe_instances(instance_ids: [instance_id]).instances.first
|
28
|
+
instance_name = instance.hostname
|
29
|
+
layer_id = instance.layer_ids.first
|
30
|
+
layer = @opsworks.describe_layers(layer_ids: [layer_id]).layers.first
|
31
|
+
layer_name = layer.name
|
32
|
+
eip_information << { eip: eip, ip_address: eip.ip, instance_name: instance_name, layer_id: layer_id }
|
33
|
+
end
|
34
|
+
|
35
|
+
eip_information
|
36
|
+
end
|
37
|
+
|
38
|
+
def ask_which_eip_to_move(eip_information)
|
39
|
+
puts "\nHere are all of the EIPs for this stack:"
|
40
|
+
eip_information.each_with_index { |h, index| puts "#{index.to_i + 1}) #{h[:ip_address]} connected to #{h[:instance_name]}" }
|
41
|
+
eip_index = @cli.ask("Which EIP would you like to move?\n", Integer) { |q| q.in = 1..eip_information.length.to_i } - 1
|
42
|
+
eip_information[eip_index]
|
43
|
+
end
|
44
|
+
|
45
|
+
def ask_which_target_instance(moveable_eip)
|
46
|
+
puts "\nHere are all of the instances in the current instance's layer:"
|
47
|
+
instances = @opsworks.describe_instances(layer_id: moveable_eip[:layer_id]).instances
|
48
|
+
instances = instances.select { |instance| instance.elastic_ip.nil? && instance.auto_scaling_type.nil? }
|
49
|
+
instances.each_with_index { |instance, index| puts "#{index.to_i + 1}) #{instance.status} - #{instance.hostname}" }
|
50
|
+
instance_index = @cli.ask("What is your target instance?\n", Integer) { |q| q.in = 1..instances.length.to_i } - 1
|
51
|
+
instances[instance_index].instance_id
|
52
|
+
end
|
53
|
+
|
54
|
+
def transfer_eip(moveable_eip, target_instance_id)
|
55
|
+
@opsworks.associate_elastic_ip({ elastic_ip: moveable_eip[:ip_address], instance_id: target_instance_id })
|
56
|
+
puts "\nEIP #{moveable_eip[:ip_address]} was moved to instance #{target_instance_id}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def move_eip
|
60
|
+
get_eips
|
61
|
+
eip_information = gather_eip_information
|
62
|
+
moveable_eip = ask_which_eip_to_move(eip_information)
|
63
|
+
target_instance_id = ask_which_target_instance(moveable_eip)
|
64
|
+
transfer_eip(moveable_eip, target_instance_id)
|
65
|
+
end
|
66
|
+
|
67
|
+
def instances
|
68
|
+
@opsworks.describe_instances(stack_id: self.id).instances
|
69
|
+
end
|
70
|
+
|
71
|
+
def deleteable_instances
|
72
|
+
instances.select{ |instance| instance.auto_scaling_type.nil? && instance.status == "stopped" }
|
73
|
+
end
|
74
|
+
|
75
|
+
def stoppable_states
|
76
|
+
%w(start_failed stop_failed online running_setup setup_failed booting rebooting)
|
77
|
+
end
|
78
|
+
|
79
|
+
def stoppable_instances
|
80
|
+
instances.select{ |instance| instance.elastic_ip.nil? && stoppable_states.include?(instance.status) }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/opsicle/version.rb
CHANGED
@@ -61,6 +61,7 @@ module Opsicle
|
|
61
61
|
allow_any_instance_of(HighLine).to receive(:ask).with("Do you wish to override this subnet ID? By overriding, you are choosing to override the current subnet ID for all of the following instances you're cloning.\n1) Yes\n2) No", Integer).and_return(2)
|
62
62
|
allow_any_instance_of(HighLine).to receive(:ask).with("Which subnet ID?\n", Integer).and_return(1)
|
63
63
|
allow_any_instance_of(HighLine).to receive(:ask).with("Do you wish to start this new instance?\n1) Yes\n2) No", Integer).and_return(1)
|
64
|
+
allow_any_instance_of(HighLine).to receive(:ask).with("\nDo you wish to add EC2 tags to this instance?\n1) Yes\n2) No", Integer).and_return(2)
|
64
65
|
end
|
65
66
|
|
66
67
|
context "#execute" do
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "opsicle"
|
3
|
+
require 'gli'
|
4
|
+
require "opsicle/user_profile"
|
5
|
+
|
6
|
+
module Opsicle
|
7
|
+
describe DeleteInstance do
|
8
|
+
before do
|
9
|
+
@instance1 = double('instance1', :hostname => 'example-hostname-01', :status => 'active',
|
10
|
+
:ami_id => 'ami_id', :instance_type => 'instance_type',
|
11
|
+
:agent_version => 'agent_version', :stack_id => 1234567890,
|
12
|
+
:layer_ids => [12345, 67890], :auto_scaling_type => 'auto_scaling_type',
|
13
|
+
:os => 'os', :ssh_key_name => 'ssh_key_name',
|
14
|
+
:availability_zone => 'availability_zone', :virtualization_type => 'virtualization_type',
|
15
|
+
:subnet_id => 'subnet_id', :architecture => 'architecture',
|
16
|
+
:root_device_type => 'root_device_type', :install_updates_on_boot => 'install_updates_on_boot',
|
17
|
+
:ebs_optimized => 'ebs_optimized', :tenancy => 'tenancy', :instance_id => 'some-id')
|
18
|
+
@instance2 = double('instance2', :hostname => 'example-hostname-02', :status => 'active',
|
19
|
+
:ami_id => 'ami_id', :instance_type => 'instance_type',
|
20
|
+
:agent_version => 'agent_version', :stack_id => 1234567890,
|
21
|
+
:layer_ids => [12345, 67890], :auto_scaling_type => 'auto_scaling_type',
|
22
|
+
:os => 'os', :ssh_key_name => 'ssh_key_name',
|
23
|
+
:availability_zone => 'availability_zone', :virtualization_type => 'virtualization_type',
|
24
|
+
:subnet_id => 'subnet_id', :architecture => 'architecture',
|
25
|
+
:root_device_type => 'root_device_type', :install_updates_on_boot => 'install_updates_on_boot',
|
26
|
+
:ebs_optimized => 'ebs_optimized', :tenancy => 'tenancy', :instance_id => 'some-id')
|
27
|
+
@instances = double('instances', :instances => [@instance1, @instance2])
|
28
|
+
@layer1 = double('layer1', :name => 'layer-1', :layer_id => 12345, :instances => [@instance1, @instance2])
|
29
|
+
@layer2 = double('layer2', :name => 'layer-2', :layer_id => 67890, :instances => [@instance1, @instance2])
|
30
|
+
@layers = double('layers', :layers => [@layer1, @layer2])
|
31
|
+
@new_instance = double('new_instance', :instance_id => 1029384756)
|
32
|
+
@stack = double('stack', :vpc_id => "vpc-123456")
|
33
|
+
@stacks = double('stacks', :stacks => [@stack])
|
34
|
+
@opsworks = double('opsworks', :describe_instances => @instances, :describe_layers => @layers,
|
35
|
+
:create_instance => @new_instance, :describe_stacks => @stacks,
|
36
|
+
:start_instance => @new_instance)
|
37
|
+
@ec2 = double('ec2')
|
38
|
+
@config = double('config', :opsworks_config => {:stack_id => 1234567890})
|
39
|
+
@client = double('client', :config => @config, :opsworks => @opsworks, :ec2 => @ec2)
|
40
|
+
allow(@instances).to receive(:each_with_index)
|
41
|
+
@agent_version_1 = double('agent_version', :version => '3434-20160316181345')
|
42
|
+
@agent_version_2 = double('agent_version', :version => '3435-20160406115841')
|
43
|
+
@agent_version_3 = double('agent_version', :version => '3436-20160418214624')
|
44
|
+
@agent_versions = double('agent_versions', :agent_versions => [@agent_version_1, @agent_version_2, @agent_version_3])
|
45
|
+
allow(@opsworks).to receive(:describe_agent_versions).and_return(@agent_versions)
|
46
|
+
tag1 = double('tag', :value => 'Subnet', :key => 'Name')
|
47
|
+
@tags = [tag1]
|
48
|
+
@current_subnet = double('subnet', :tags => @tags, :availability_zone => 'us-east-1b')
|
49
|
+
allow(Aws::EC2::Subnet).to receive(:new).and_return(@current_subnet)
|
50
|
+
allow_any_instance_of(HighLine).to receive(:ask).with("Layer?\n", Integer).and_return(2)
|
51
|
+
allow_any_instance_of(HighLine).to receive(:ask).with("Instances? (enter as a comma separated list)\n", String).and_return('2')
|
52
|
+
allow_any_instance_of(HighLine).to receive(:ask).with("Do you wish to override this hostname?\n1) Yes\n2) No", Integer).and_return(2)
|
53
|
+
allow_any_instance_of(HighLine).to receive(:ask).with("Please write in the new instance's hostname and press ENTER:").and_return('example-hostname')
|
54
|
+
allow_any_instance_of(HighLine).to receive(:ask).with("Do you wish to override this AMI ID? By overriding, you are choosing to override the current AMI ID for all of the following instances you're cloning.\n1) Yes\n2) No", Integer).and_return(2)
|
55
|
+
allow_any_instance_of(HighLine).to receive(:ask).with("Which AMI ID?\n", Integer).and_return(1)
|
56
|
+
allow_any_instance_of(HighLine).to receive(:ask).with("Do you wish to override this agent version? By overriding, you are choosing to override the current agent version for all of the following instances you're cloning.\n1) Yes\n2) No", Integer).and_return(2)
|
57
|
+
allow_any_instance_of(HighLine).to receive(:ask).with("Which agent version?\n", Integer).and_return(1)
|
58
|
+
allow_any_instance_of(HighLine).to receive(:ask).with("Do you wish to override this instance type?\n1) Yes\n2) No", Integer).and_return(2)
|
59
|
+
allow_any_instance_of(HighLine).to receive(:ask).with("Please write in the new instance type press ENTER:").and_return('t2.micro')
|
60
|
+
allow_any_instance_of(HighLine).to receive(:ask).with("Do you wish to override this subnet ID? By overriding, you are choosing to override the current subnet ID for all of the following instances you're cloning.\n1) Yes\n2) No", Integer).and_return(2)
|
61
|
+
allow_any_instance_of(HighLine).to receive(:ask).with("Which subnet ID?\n", Integer).and_return(1)
|
62
|
+
allow_any_instance_of(HighLine).to receive(:ask).with("Do you wish to start this new instance?\n1) Yes\n2) No", Integer).and_return(1)
|
63
|
+
end
|
64
|
+
|
65
|
+
subject{DeleteInstance.new("staging")}
|
66
|
+
|
67
|
+
# context "#execute" do
|
68
|
+
# it "lists deleteable instances" do
|
69
|
+
# allow(subject).to receive("staging"){[@instance1]}
|
70
|
+
# expect(@stack).to receive(:deleteable_instances)
|
71
|
+
# subject.execute
|
72
|
+
# end
|
73
|
+
#
|
74
|
+
# it "deletes the selected instance" do
|
75
|
+
# allow(subject).to receive("staging"){[@instance1]}
|
76
|
+
# expect(@opsworks).to receive(:delete_instance)
|
77
|
+
# subject.execute
|
78
|
+
# end
|
79
|
+
# end
|
80
|
+
end
|
81
|
+
end
|
@@ -4,7 +4,7 @@ require 'gli'
|
|
4
4
|
require "opsicle/user_profile"
|
5
5
|
|
6
6
|
module Opsicle
|
7
|
-
describe
|
7
|
+
describe ManageableInstance do
|
8
8
|
before do
|
9
9
|
@instance = double('instance1', :hostname => 'example-hostname-01', :status => 'active',
|
10
10
|
:ami_id => 'ami_id', :instance_type => 'instance_type',
|
@@ -49,7 +49,7 @@ module Opsicle
|
|
49
49
|
|
50
50
|
context "#make_new_hostname" do
|
51
51
|
it "should make a unique incremented hostname" do
|
52
|
-
instance =
|
52
|
+
instance = ManageableInstance.new(@instance, @layer, @stack, @opsworks, @ec2, @cli)
|
53
53
|
instance1 = double('instance', :hostname => 'example-hostname-01')
|
54
54
|
instance2 = double('instance', :hostname => 'example-hostname-02')
|
55
55
|
allow(@layer).to receive(:instances).and_return([instance1, instance2])
|
@@ -57,7 +57,7 @@ module Opsicle
|
|
57
57
|
end
|
58
58
|
|
59
59
|
it "should make a unique incremented hostname" do
|
60
|
-
instance =
|
60
|
+
instance = ManageableInstance.new(@instance, @layer, @stack, @opsworks, @ec2, @cli)
|
61
61
|
instance1 = double('instance', :hostname => 'example-hostname-01')
|
62
62
|
instance2 = double('instance', :hostname => 'example-hostname-02')
|
63
63
|
instance3 = double('instance', :hostname => 'example-hostname-03')
|
@@ -69,7 +69,7 @@ module Opsicle
|
|
69
69
|
|
70
70
|
context "#increment_hostname" do
|
71
71
|
it "should increment the hostname" do
|
72
|
-
instance =
|
72
|
+
instance = ManageableInstance.new(@instance, @layer, @stack, @opsworks, @ec2, @cli)
|
73
73
|
expect(instance).to receive(:hostname_unique?).and_return('example-hostname-03')
|
74
74
|
allow(@opsworks).to receive(:describe_agent_version).with({})
|
75
75
|
expect(instance.increment_hostname).to eq('example-hostname-01')
|
@@ -78,13 +78,13 @@ module Opsicle
|
|
78
78
|
|
79
79
|
context "#clone" do
|
80
80
|
it "should grab instances and make new hostname" do
|
81
|
-
instance =
|
81
|
+
instance = ManageableInstance.new(@instance, @layer, @stack, @opsworks, @ec2, @cli)
|
82
82
|
expect(instance).to receive(:make_new_hostname).and_return('example-hostname-03')
|
83
83
|
instance.clone({})
|
84
84
|
end
|
85
85
|
|
86
86
|
it "should get information from old instance" do
|
87
|
-
instance =
|
87
|
+
instance = ManageableInstance.new(@instance, @layer, @stack, @opsworks, @ec2, @cli)
|
88
88
|
expect(instance).to receive(:verify_ami_id)
|
89
89
|
expect(instance).to receive(:verify_agent_version)
|
90
90
|
expect(instance).to receive(:verify_instance_type)
|
@@ -93,13 +93,13 @@ module Opsicle
|
|
93
93
|
end
|
94
94
|
|
95
95
|
it "should create new instance" do
|
96
|
-
instance =
|
96
|
+
instance = ManageableInstance.new(@instance, @layer, @stack, @opsworks, @ec2, @cli)
|
97
97
|
expect(instance).to receive(:create_new_instance)
|
98
98
|
instance.clone({})
|
99
99
|
end
|
100
100
|
|
101
101
|
it "should start new instance" do
|
102
|
-
instance =
|
102
|
+
instance = ManageableInstance.new(@instance, @layer, @stack, @opsworks, @ec2, @cli)
|
103
103
|
allow(instance).to receive(:ask_to_start_instance).and_return(true)
|
104
104
|
expect(instance).to receive(:start_new_instance)
|
105
105
|
instance.clone({})
|
@@ -109,7 +109,7 @@ module Opsicle
|
|
109
109
|
context '#verify_agent_version' do
|
110
110
|
it "should check the agent version and ask if the user wants a new agent version" do
|
111
111
|
@cli = double('cli', :ask => 1)
|
112
|
-
instance =
|
112
|
+
instance = ManageableInstance.new(@instance, @layer, @stack, @opsworks, @ec2, @cli)
|
113
113
|
allow(@layer).to receive(:agent_version).and_return(nil)
|
114
114
|
allow_any_instance_of(HighLine).to receive(:ask).with("Do you wish to override this version? By overriding, you are choosing to override the current agent version for all instances you are cloning.\n1) Yes\n2) No", Integer).and_return(1)
|
115
115
|
expect(instance).to receive(:ask_for_possible_options)
|
@@ -117,7 +117,7 @@ module Opsicle
|
|
117
117
|
end
|
118
118
|
|
119
119
|
it "should see if the layer already has overwritten the agent version" do
|
120
|
-
instance =
|
120
|
+
instance = ManageableInstance.new(@instance, @layer, @stack, @opsworks, @ec2, @cli)
|
121
121
|
expect(@layer).to receive(:agent_version)
|
122
122
|
instance.verify_agent_version
|
123
123
|
end
|
@@ -126,7 +126,7 @@ module Opsicle
|
|
126
126
|
context '#verify_subnet_id' do
|
127
127
|
it "should check the subnet id and ask if the user wants a new subnet id" do
|
128
128
|
@cli = double('cli', :ask => 1)
|
129
|
-
instance =
|
129
|
+
instance = ManageableInstance.new(@instance, @layer, @stack, @opsworks, @ec2, @cli)
|
130
130
|
allow(@layer).to receive(:subnet_id).and_return(nil)
|
131
131
|
allow_any_instance_of(HighLine).to receive(:ask).with("Do you wish to override this id? By overriding, you are choosing to override the current agent version for all instances you are cloning.\n1) Yes\n2) No", Integer).and_return(1)
|
132
132
|
expect(instance).to receive(:ask_for_possible_options)
|
@@ -134,7 +134,7 @@ module Opsicle
|
|
134
134
|
end
|
135
135
|
|
136
136
|
it "should see if the layer already has overwritten the subnet id" do
|
137
|
-
instance =
|
137
|
+
instance = ManageableInstance.new(@instance, @layer, @stack, @opsworks, @ec2, @cli)
|
138
138
|
expect(@layer).to receive(:subnet_id)
|
139
139
|
instance.verify_subnet_id
|
140
140
|
end
|
@@ -143,7 +143,7 @@ module Opsicle
|
|
143
143
|
context '#verify_ami_id' do
|
144
144
|
it "should check the ami id and ask if the user wants a new ami" do
|
145
145
|
@cli = double('cli', :ask => 1)
|
146
|
-
instance =
|
146
|
+
instance = ManageableInstance.new(@instance, @layer, @stack, @opsworks, @ec2, @cli)
|
147
147
|
allow(@layer).to receive(:ami_id).and_return(nil)
|
148
148
|
allow_any_instance_of(HighLine).to receive(:ask).with("Do you wish to override this AMI? By overriding, you are choosing to override the current AMI for all instances you are cloning.\n1) Yes\n2) No", Integer).and_return(1)
|
149
149
|
expect(@cli).to receive(:ask)
|
@@ -152,7 +152,7 @@ module Opsicle
|
|
152
152
|
end
|
153
153
|
|
154
154
|
it "should see if the layer already has overwritten the ami id" do
|
155
|
-
instance =
|
155
|
+
instance = ManageableInstance.new(@instance, @layer, @stack, @opsworks, @ec2, @cli)
|
156
156
|
expect(@layer).to receive(:ami_id)
|
157
157
|
instance.verify_ami_id
|
158
158
|
end
|
@@ -161,7 +161,7 @@ module Opsicle
|
|
161
161
|
context '#verify_instance_type' do
|
162
162
|
it "should check the agent version and ask if the user wants a new agent version" do
|
163
163
|
@cli = double('cli', :ask => 1)
|
164
|
-
instance =
|
164
|
+
instance = ManageableInstance.new(@instance, @layer, @stack, @opsworks, @ec2, @cli)
|
165
165
|
allow(@layer).to receive(:ami_id).and_return(nil)
|
166
166
|
allow_any_instance_of(HighLine).to receive(:ask).with("Do you wish to override this instance type?\n1) Yes\n2) No", Integer).and_return(1)
|
167
167
|
expect(@cli).to receive(:ask).twice
|
@@ -171,13 +171,13 @@ module Opsicle
|
|
171
171
|
|
172
172
|
context "#create_new_instance" do
|
173
173
|
it "should create an instance" do
|
174
|
-
instance =
|
174
|
+
instance = ManageableInstance.new(@instance, @layer, @stack, @opsworks, @ec2, @cli)
|
175
175
|
expect(@opsworks).to receive(:create_instance)
|
176
176
|
instance.create_new_instance('hostname', 'type', 'ami', 'agent_version', 'subnet_id')
|
177
177
|
end
|
178
178
|
|
179
179
|
it "should take information from old instance" do
|
180
|
-
instance =
|
180
|
+
instance = ManageableInstance.new(@instance, @layer, @stack, @opsworks, @ec2, @cli)
|
181
181
|
expect(instance).to receive(:stack_id)
|
182
182
|
expect(instance).to receive(:layer_ids)
|
183
183
|
expect(instance).to receive(:auto_scaling_type)
|
@@ -4,7 +4,7 @@ require 'gli'
|
|
4
4
|
require "opsicle/user_profile"
|
5
5
|
|
6
6
|
module Opsicle
|
7
|
-
describe
|
7
|
+
describe ManageableLayer do
|
8
8
|
before do
|
9
9
|
@instance1 = double('instance1', :hostname => 'example-hostname-01', :status => 'active',
|
10
10
|
:ami_id => 'ami_id', :instance_type => 'instance_type',
|
@@ -42,31 +42,31 @@ module Opsicle
|
|
42
42
|
|
43
43
|
context "#get_cloneable_instances" do
|
44
44
|
it "should gather opsworks instances for that layer" do
|
45
|
-
layer =
|
45
|
+
layer = ManageableLayer.new('layer-name', 12345, @stack, @opsworks, @ec2, @cli)
|
46
46
|
expect(@opsworks).to receive(:describe_instances).and_return(@instances)
|
47
47
|
expect(@instances).to receive(:instances)
|
48
48
|
layer.get_cloneable_instances
|
49
49
|
end
|
50
50
|
|
51
|
-
it "should make a new
|
52
|
-
layer =
|
53
|
-
expect(
|
51
|
+
it "should make a new ManageableInstance for each instance" do
|
52
|
+
layer = ManageableLayer.new('layer-name', 12345, @stack, @opsworks, @ec2, @cli)
|
53
|
+
expect(ManageableInstance).to receive(:new).twice
|
54
54
|
layer.get_cloneable_instances
|
55
55
|
end
|
56
56
|
end
|
57
57
|
|
58
58
|
context "#add_new_instance" do
|
59
59
|
it "should accurately find a new instance via instance_id" do
|
60
|
-
layer =
|
60
|
+
layer = ManageableLayer.new('layer-name', 12345, @stack, @opsworks, @ec2, @cli)
|
61
61
|
expect(@opsworks).to receive(:describe_instances).and_return(@new_instance)
|
62
62
|
expect(@new_instance).to receive(:instances)
|
63
63
|
layer.add_new_instance('456-789')
|
64
64
|
end
|
65
65
|
|
66
66
|
it "should add the new instance to the instances array" do
|
67
|
-
layer =
|
67
|
+
layer = ManageableLayer.new('layer-name', 12345, @stack, @opsworks, @ec2, @cli)
|
68
68
|
expect(@opsworks).to receive(:describe_instances).and_return(@new_instance)
|
69
|
-
expect(
|
69
|
+
expect(ManageableInstance).to receive(:new).once
|
70
70
|
layer.add_new_instance('456-789')
|
71
71
|
end
|
72
72
|
end
|
@@ -4,7 +4,7 @@ require 'gli'
|
|
4
4
|
require "opsicle/user_profile"
|
5
5
|
|
6
6
|
module Opsicle
|
7
|
-
describe
|
7
|
+
describe ManageableStack do
|
8
8
|
before do
|
9
9
|
@stack = double('stack', :vpc_id => 'vpc-123456')
|
10
10
|
@stacks = double('stacks', :stacks => [@stack])
|
@@ -13,7 +13,7 @@ module Opsicle
|
|
13
13
|
|
14
14
|
context "#get_stack" do
|
15
15
|
it "should gather opsworks instances for that layer" do
|
16
|
-
stack =
|
16
|
+
stack = ManageableStack.new(12345, @opsworks)
|
17
17
|
expect(@opsworks).to receive(:describe_stacks).and_return(@stacks)
|
18
18
|
expect(@stacks).to receive(:stacks)
|
19
19
|
stack.get_stack
|
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: 2.
|
4
|
+
version: 2.10.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:
|
12
|
+
date: 2018-01-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: aws-sdk
|
@@ -191,24 +191,27 @@ files:
|
|
191
191
|
- bin/opsicle
|
192
192
|
- lib/opsicle.rb
|
193
193
|
- lib/opsicle/client.rb
|
194
|
-
- lib/opsicle/cloneable_instance.rb
|
195
|
-
- lib/opsicle/cloneable_layer.rb
|
196
|
-
- lib/opsicle/cloneable_stack.rb
|
197
194
|
- lib/opsicle/commands.rb
|
195
|
+
- lib/opsicle/commands/add_tags.rb
|
198
196
|
- lib/opsicle/commands/chef_update.rb
|
199
197
|
- lib/opsicle/commands/clone_instance.rb
|
198
|
+
- lib/opsicle/commands/create_instance.rb
|
199
|
+
- lib/opsicle/commands/delete_instance.rb
|
200
200
|
- lib/opsicle/commands/deploy.rb
|
201
201
|
- lib/opsicle/commands/execute_recipes.rb
|
202
202
|
- lib/opsicle/commands/failure_log.rb
|
203
203
|
- lib/opsicle/commands/legacy_credential_converter.rb
|
204
204
|
- lib/opsicle/commands/list.rb
|
205
205
|
- lib/opsicle/commands/list_instances.rb
|
206
|
+
- lib/opsicle/commands/move_eip.rb
|
206
207
|
- lib/opsicle/commands/ssh.rb
|
207
208
|
- lib/opsicle/commands/ssh_clean_keys.rb
|
208
209
|
- lib/opsicle/commands/ssh_key.rb
|
210
|
+
- lib/opsicle/commands/stop_instance.rb
|
209
211
|
- lib/opsicle/commands/update.rb
|
210
212
|
- lib/opsicle/commands/user_profile_info.rb
|
211
213
|
- lib/opsicle/config.rb
|
214
|
+
- lib/opsicle/creatable_instance.rb
|
212
215
|
- lib/opsicle/credential_converter_helper.rb
|
213
216
|
- lib/opsicle/deploy_helper.rb
|
214
217
|
- lib/opsicle/deployment.rb
|
@@ -216,6 +219,9 @@ files:
|
|
216
219
|
- lib/opsicle/errors.rb
|
217
220
|
- lib/opsicle/instances.rb
|
218
221
|
- lib/opsicle/layer.rb
|
222
|
+
- lib/opsicle/manageable_instance.rb
|
223
|
+
- lib/opsicle/manageable_layer.rb
|
224
|
+
- lib/opsicle/manageable_stack.rb
|
219
225
|
- lib/opsicle/monitor.rb
|
220
226
|
- lib/opsicle/monitor/app.rb
|
221
227
|
- lib/opsicle/monitor/panel.rb
|
@@ -235,11 +241,9 @@ files:
|
|
235
241
|
- lib/opsicle/user_profile.rb
|
236
242
|
- lib/opsicle/version.rb
|
237
243
|
- spec/opsicle/client_spec.rb
|
238
|
-
- spec/opsicle/cloneable_instance_spec.rb
|
239
|
-
- spec/opsicle/cloneable_layer_spec.rb
|
240
|
-
- spec/opsicle/cloneable_stack_spec.rb
|
241
244
|
- spec/opsicle/commands/chef_update_spec.rb
|
242
245
|
- spec/opsicle/commands/clone_instance_spec.rb
|
246
|
+
- spec/opsicle/commands/delete_instance_spec.rb
|
243
247
|
- spec/opsicle/commands/deploy_spec.rb
|
244
248
|
- spec/opsicle/commands/execute_recipes_spec.rb
|
245
249
|
- spec/opsicle/commands/failure_log_spec.rb
|
@@ -253,6 +257,9 @@ files:
|
|
253
257
|
- spec/opsicle/errors_spec.rb
|
254
258
|
- spec/opsicle/instances_spec.rb
|
255
259
|
- spec/opsicle/layer_spec.rb
|
260
|
+
- spec/opsicle/manageable_instance_spec.rb
|
261
|
+
- spec/opsicle/manageable_layer_spec.rb
|
262
|
+
- spec/opsicle/manageable_stack_spec.rb
|
256
263
|
- spec/opsicle/monitor/app_spec.rb
|
257
264
|
- spec/opsicle/monitor/panel_spec.rb
|
258
265
|
- spec/opsicle/monitor/screen_spec.rb
|
@@ -282,17 +289,15 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
282
289
|
version: '0'
|
283
290
|
requirements: []
|
284
291
|
rubyforge_project:
|
285
|
-
rubygems_version: 2.6.
|
292
|
+
rubygems_version: 2.6.13
|
286
293
|
signing_key:
|
287
294
|
specification_version: 4
|
288
295
|
summary: An opsworks specific abstraction on top of the aws sdk
|
289
296
|
test_files:
|
290
297
|
- spec/opsicle/client_spec.rb
|
291
|
-
- spec/opsicle/cloneable_instance_spec.rb
|
292
|
-
- spec/opsicle/cloneable_layer_spec.rb
|
293
|
-
- spec/opsicle/cloneable_stack_spec.rb
|
294
298
|
- spec/opsicle/commands/chef_update_spec.rb
|
295
299
|
- spec/opsicle/commands/clone_instance_spec.rb
|
300
|
+
- spec/opsicle/commands/delete_instance_spec.rb
|
296
301
|
- spec/opsicle/commands/deploy_spec.rb
|
297
302
|
- spec/opsicle/commands/execute_recipes_spec.rb
|
298
303
|
- spec/opsicle/commands/failure_log_spec.rb
|
@@ -306,6 +311,9 @@ test_files:
|
|
306
311
|
- spec/opsicle/errors_spec.rb
|
307
312
|
- spec/opsicle/instances_spec.rb
|
308
313
|
- spec/opsicle/layer_spec.rb
|
314
|
+
- spec/opsicle/manageable_instance_spec.rb
|
315
|
+
- spec/opsicle/manageable_layer_spec.rb
|
316
|
+
- spec/opsicle/manageable_stack_spec.rb
|
309
317
|
- spec/opsicle/monitor/app_spec.rb
|
310
318
|
- spec/opsicle/monitor/panel_spec.rb
|
311
319
|
- spec/opsicle/monitor/screen_spec.rb
|
@@ -1,16 +0,0 @@
|
|
1
|
-
module Opsicle
|
2
|
-
class CloneableStack
|
3
|
-
attr_accessor :id, :opsworks, :stack, :vpc_id
|
4
|
-
|
5
|
-
def initialize(stack_id, opsworks)
|
6
|
-
self.id = stack_id
|
7
|
-
self.opsworks = opsworks
|
8
|
-
self.stack = get_stack
|
9
|
-
self.vpc_id = self.stack.vpc_id
|
10
|
-
end
|
11
|
-
|
12
|
-
def get_stack
|
13
|
-
@opsworks.describe_stacks({ :stack_ids => [self.id.to_s] }).stacks.first
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|