opsicle 2.9.6 → 2.10.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|