Class: Opsicle::ManageableInstance

Inherits:
Object
  • Object
show all
Defined in:
lib/opsicle/manageable_instance.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(instance, layer, stack, opsworks, ec2, cli) ⇒ ManageableInstance

Returns a new instance of ManageableInstance.



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/opsicle/manageable_instance.rb', line 31

def initialize(instance, layer, stack, opsworks, ec2, cli)
  self.hostname = instance.hostname
  self.status = instance.status
  self.layer = layer
  self.stack = stack
  self.ami_id = instance.ami_id
  self.instance_type = instance.instance_type
  self.agent_version = instance.agent_version
  self.stack_id = instance.stack_id
  self.layer_ids = instance.layer_ids
  self.auto_scaling_type = instance.auto_scaling_type
  self.os = instance.os
  self.ssh_key_name = instance.ssh_key_name
  self.availability_zone = instance.availability_zone
  self.virtualization_type = instance.virtualization_type
  self.subnet_id = instance.subnet_id
  self.architecture = instance.architecture
  self.root_device_type = instance.root_device_type
  self.install_updates_on_boot = instance.install_updates_on_boot
  self.ebs_optimized = instance.ebs_optimized
  self.tenancy = instance.tenancy
  self.opsworks = opsworks
  self.ec2 = ec2
  self.cli = cli
  self.instance_id = instance.instance_id
  self.new_instance_id = nil
end

Instance Attribute Details

#agent_versionObject

Returns the value of attribute agent_version.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def agent_version
  @agent_version
end

#ami_idObject

Returns the value of attribute ami_id.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def ami_id
  @ami_id
end

#architectureObject

Returns the value of attribute architecture.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def architecture
  @architecture
end

#auto_scaling_typeObject

Returns the value of attribute auto_scaling_type.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def auto_scaling_type
  @auto_scaling_type
end

#availability_zoneObject

Returns the value of attribute availability_zone.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def availability_zone
  @availability_zone
end

#cliObject

Returns the value of attribute cli.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def cli
  @cli
end

#ebs_optimizedObject

Returns the value of attribute ebs_optimized.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def ebs_optimized
  @ebs_optimized
end

#ec2Object

Returns the value of attribute ec2.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def ec2
  @ec2
end

#hostnameObject

Returns the value of attribute hostname.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def hostname
  @hostname
end

#install_updates_on_bootObject

Returns the value of attribute install_updates_on_boot.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def install_updates_on_boot
  @install_updates_on_boot
end

#instance_idObject

Returns the value of attribute instance_id.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def instance_id
  @instance_id
end

#instance_typeObject

Returns the value of attribute instance_type.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def instance_type
  @instance_type
end

#layerObject

Returns the value of attribute layer.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def layer
  @layer
end

#layer_idsObject

Returns the value of attribute layer_ids.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def layer_ids
  @layer_ids
end

#new_instance_idObject

Returns the value of attribute new_instance_id.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def new_instance_id
  @new_instance_id
end

#opsworksObject

Returns the value of attribute opsworks.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def opsworks
  @opsworks
end

#osObject

Returns the value of attribute os.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def os
  @os
end

#root_device_typeObject

Returns the value of attribute root_device_type.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def root_device_type
  @root_device_type
end

#ssh_key_nameObject

Returns the value of attribute ssh_key_name.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def ssh_key_name
  @ssh_key_name
end

#stackObject

Returns the value of attribute stack.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def stack
  @stack
end

#stack_idObject

Returns the value of attribute stack_id.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def stack_id
  @stack_id
end

#statusObject

Returns the value of attribute status.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def status
  @status
end

#subnet_idObject

Returns the value of attribute subnet_id.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def subnet_id
  @subnet_id
end

#tenancyObject

Returns the value of attribute tenancy.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def tenancy
  @tenancy
end

#virtualization_typeObject

Returns the value of attribute virtualization_type.



3
4
5
# File 'lib/opsicle/manageable_instance.rb', line 3

def virtualization_type
  @virtualization_type
end

Instance Method Details

#add_tags(options = {}) ⇒ Object

Raises:

  • (ArgumentError)


262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/opsicle/manageable_instance.rb', line 262

def add_tags(options={})
  raise ArgumentError, 'The instance must be running to add tags' if options[:add_tags_mode] && @status != "online"

  if ask_to_add_tags
    tags = []

    tag_count.times do
      tags << define_tag
    end

    ec2_instance_id = @opsworks.describe_instances(instance_ids: [new_instance_id || instance_id]).instances.first.ec2_instance_id
    @ec2.create_tags(resources: [ ec2_instance_id ], tags: tags)
  end
end

#ask_for_new_option(description) ⇒ Object



216
217
218
# File 'lib/opsicle/manageable_instance.rb', line 216

def ask_for_new_option(description)
  @cli.ask("Please write in the new #{description} and press ENTER:")
end

#ask_for_overriding_permission(description, overriding_all) ⇒ Object



220
221
222
223
224
225
226
227
# File 'lib/opsicle/manageable_instance.rb', line 220

def ask_for_overriding_permission(description, overriding_all)
  if overriding_all
    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)
  else
    ans = @cli.ask("Do you wish to override this #{description}?\n1) Yes\n2) No", Integer)
  end
  ans == 1
end

#ask_for_possible_options(arr, description) ⇒ Object



210
211
212
213
214
# File 'lib/opsicle/manageable_instance.rb', line 210

def ask_for_possible_options(arr, description)
  arr.each_with_index { |id, index| puts "#{index.to_i + 1}) #{id}"}
  id_index = @cli.ask("Which #{description}?\n", Integer) { |q| q.in = 1..arr.length.to_i } - 1
  arr[id_index]
end

#ask_to_add_tagsObject



287
288
289
290
# File 'lib/opsicle/manageable_instance.rb', line 287

def ask_to_add_tags
  ans = @cli.ask("\nDo you wish to add EC2 tags to this instance?\n1) Yes\n2) No", Integer)
  ans == 1
end

#ask_to_start_instanceObject



292
293
294
295
# File 'lib/opsicle/manageable_instance.rb', line 292

def ask_to_start_instance
  ans = @cli.ask("Do you wish to start this new instance?\n1) Yes\n2) No", Integer)
  ans == 1
end

#auto_generated_hostnameObject



89
90
91
92
93
94
95
# File 'lib/opsicle/manageable_instance.rb', line 89

def auto_generated_hostname
  if hostname =~ /\d\d\z/
    increment_hostname
  else
    hostname << "-clone"
  end
end

#clone(options) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/opsicle/manageable_instance.rb', line 59

def clone(options)
  puts "\nCloning an instance..."

  new_instance_hostname = make_new_hostname
  ami_id = verify_ami_id
  agent_version = verify_agent_version
  subnet_id = verify_subnet_id
  instance_type = verify_instance_type

  create_new_instance(new_instance_hostname, instance_type, ami_id, agent_version, subnet_id)
  start_new_instance
end

#clone_with_defaults(options) ⇒ Object



73
74
75
76
77
78
79
80
# File 'lib/opsicle/manageable_instance.rb', line 73

def clone_with_defaults(options)
  puts "\nCloning an instance..."
  new_hostname = auto_generated_hostname
  create_new_instance(new_hostname, instance_type, ami_id, agent_version, subnet_id)
  opsworks.start_instance(instance_id: new_instance_id)
  add_tags
  puts "\nNew instance is starting…"
end

#create_new_instance(new_instance_hostname, instance_type, ami_id, agent_version, subnet_id) ⇒ Object



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/opsicle/manageable_instance.rb', line 229

def create_new_instance(new_instance_hostname, instance_type, ami_id, agent_version, subnet_id)
  new_instance = @opsworks.create_instance({
    stack_id: self.stack_id, # required
    layer_ids: self.layer_ids, # required
    instance_type: instance_type, # required
    auto_scaling_type: self.auto_scaling_type, # accepts load, timer
    hostname: new_instance_hostname,
    os: self.os,
    ami_id: ami_id,
    ssh_key_name: self.ssh_key_name,
    # availability_zone: self.availability_zone,
    subnet_id: subnet_id,
    virtualization_type: self.virtualization_type,
    architecture: self.architecture, # accepts x86_64, i386
    root_device_type: self.root_device_type, # accepts ebs, instance-store
    install_updates_on_boot: self.install_updates_on_boot,
    #ebs_optimized: self.ebs_optimized,
    agent_version: agent_version,
    tenancy: self.tenancy,
  })
  self.new_instance_id = new_instance.instance_id
  self.layer.add_new_instance(new_instance_id)
  puts "\nNew instance #{new_instance_hostname} has been created: #{new_instance_id}"
end

#define_tagObject



277
278
279
280
281
# File 'lib/opsicle/manageable_instance.rb', line 277

def define_tag
  tag_key = ask_for_new_option('tag name')
  tag_value = ask_for_new_option('tag value')
  { key: tag_key, value: tag_value }
end

#find_subnet_name(subnet) ⇒ Object



117
118
119
120
121
122
# File 'lib/opsicle/manageable_instance.rb', line 117

def find_subnet_name(subnet)
  tags = subnet.tags
  tag = nil
  tags.each { |t| tag = t if t.key == 'Name' }
  tag.value if tag
end

#hostname_unique?(name) ⇒ Boolean

Returns:

  • (Boolean)


113
114
115
# File 'lib/opsicle/manageable_instance.rb', line 113

def hostname_unique?(name)
  !sibling_hostnames.include?(name)
end

#increment_hostnameObject



101
102
103
104
105
106
107
# File 'lib/opsicle/manageable_instance.rb', line 101

def increment_hostname
  name = hostname
  until hostname_unique?(name) do
    name = name.gsub(/(\d\d\z)/) { "#{($1.to_i + 1).to_s.rjust(2, '0')}" }
  end
  name
end

#make_new_hostnameObject



82
83
84
85
86
87
# File 'lib/opsicle/manageable_instance.rb', line 82

def make_new_hostname
  new_instance_hostname = auto_generated_hostname
  puts "\nAutomatically generated hostname: #{new_instance_hostname}\n"
  new_instance_hostname = ask_for_new_option("instance's hostname") if ask_for_overriding_permission("hostname", false)
  new_instance_hostname
end

#sibling_hostnamesObject



97
98
99
# File 'lib/opsicle/manageable_instance.rb', line 97

def sibling_hostnames
  self.layer.instances.collect { |instance| instance.hostname }
end

#start_new_instanceObject



254
255
256
257
258
259
260
# File 'lib/opsicle/manageable_instance.rb', line 254

def start_new_instance
  if ask_to_start_instance
    @opsworks.start_instance(instance_id: self.new_instance_id)
    puts "\nNew instance is starting…"
    add_tags
  end
end

#tag_countObject



283
284
285
# File 'lib/opsicle/manageable_instance.rb', line 283

def tag_count
  @cli.ask("How many tags do you wish to add? Please write in the number as an integer and press ENTER:").to_i
end

#verify_agent_versionObject



149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
# File 'lib/opsicle/manageable_instance.rb', line 149

def verify_agent_version
  if self.layer.agent_version
    agent_version = self.layer.agent_version
  else
    puts "\nCurrent agent version is #{self.agent_version}"

    if ask_for_overriding_permission("agent version", true)
      agents = @opsworks.describe_agent_versions(stack_id: self.stack_id).agent_versions
      version_ids = agents.collect { |i| i.version }.uniq
      agent_version = ask_for_possible_options(version_ids, "agent version")

      self.layer.agent_version = agent_version   # only set agent version for whole layer if they override
    else
      agent_version = self.agent_version
    end
  end

  agent_version
end

#verify_ami_idObject



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/opsicle/manageable_instance.rb', line 124

def verify_ami_id
  if self.layer.ami_id
    ami_id = self.layer.ami_id
  else
    puts "\nCurrent AMI id is #{self.ami_id}"

    if ask_for_overriding_permission("AMI ID", true)
      instances = @opsworks.describe_instances(stack_id: self.stack_id).instances
      ami_ids = instances.collect { |i| i.ami_id }.uniq
      ami_ids << "Provide a different AMI ID."
      ami_id = ask_for_possible_options(ami_ids, "AMI ID")

      if ami_id == "Provide a different AMI ID."
        ami_id = ask_for_new_option('AMI ID')
      end

      self.layer.ami_id = ami_id   # only set AMI ID for whole layer if they override it
    else
      ami_id = self.ami_id
    end
  end

  ami_id
end

#verify_instance_typeObject



203
204
205
206
207
208
# File 'lib/opsicle/manageable_instance.rb', line 203

def verify_instance_type
  puts "\nCurrent instance type is #{self.instance_type}"
  rewriting = ask_for_overriding_permission("instance type", false)
  instance_type = rewriting ? ask_for_new_option('instance type') : self.instance_type
  instance_type
end

#verify_subnet_idObject



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/opsicle/manageable_instance.rb', line 169

def verify_subnet_id
  if self.layer.subnet_id
    subnet_id = self.layer.subnet_id
  else
    current_subnet = Aws::EC2::Subnet.new(id: self.subnet_id)
    subnet_name = find_subnet_name(current_subnet)
    puts "\nCurrent subnet ID is \"#{subnet_name}\" #{current_subnet.availability_zone} (#{self.subnet_id})"

    if ask_for_overriding_permission("subnet ID", true)
      ec2_subnets = ec2.describe_subnets.subnets
      subnets = []

      ec2_subnets.each do |subnet|
        if subnet.vpc_id == stack.vpc_id
          subnet_name = find_subnet_name(subnet)
          zone_name = subnet.availability_zone
          subnet_id = subnet.subnet_id
          subnets << "\"#{subnet_name}\" #{zone_name} (#{subnet_id})"
        end
      end

      subnets = subnets.sort
      subnet_id = ask_for_possible_options(subnets, "subnet ID")
      subnet_id = subnet_id.scan(/(subnet-[a-z0-9]*)/).first.first if subnet_id

      self.layer.subnet_id = subnet_id   # only set the subnet ID for whole layer if they override it
    else
      subnet_id = self.subnet_id
    end
  end

  subnet_id
end