Class: OpsworksWrapper::Deployer

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

Instance Method Summary collapse

Constructor Details

#initialize(app_id) ⇒ Deployer

Returns a new instance of Deployer.



6
7
8
# File 'lib/opsworks_wrapper.rb', line 6

def initialize(app_id)
  @app_id = app_id
end

Instance Method Details

#_wait_until_deployed(deployment_id, timeout) ⇒ Object

Waits on the provided deployment for specified timeout (seconds)



206
207
208
209
210
211
212
213
214
# File 'lib/opsworks_wrapper.rb', line 206

def _wait_until_deployed(deployment_id, timeout)
  opsworks_client.wait_until(:deployment_successful, deployment_ids: [deployment_id]) do |w|
    w.before_attempt do |attempt|
      puts "Attempt #{attempt} to check deployment status".light_black
    end
    w.interval = 10
    w.max_attempts = timeout / w.interval
  end
end

#app_idObject



26
27
28
# File 'lib/opsworks_wrapper.rb', line 26

def app_id
  @app_id
end

#create_deployment(command, instances, timeout) ⇒ Boolean

Creates an OpsWorks deployment with specified command If @instances is not nil, the deployment will only be performed on specified instances

Parameters:

  • command (Object)
  • instances (Array[Object])
  • timeout (Number)

Returns:

  • (Boolean)


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
202
203
# File 'lib/opsworks_wrapper.rb', line 173

def create_deployment(command, instances, timeout)
  instance_ids = nil
  instance_description = "all instances"

  if !instances.nil?
    instance_ids = instances.map(&:instance_id)
    instance_description = instances.map(&:hostname).join(',')
  end

  deployment_config = {
      stack_id: opsworks_app[:stack_id],
      app_id: app_id,
      instance_ids: instance_ids,
      command: command,
      comment: "Git Sha: #{current_sha}"
  }

  deployment = opsworks_client.create_deployment(deployment_config)
  print "Running command ".light_blue
  print "#{command[:name]}".light_blue.bold
  puts " on #{instance_description}".light_blue

  begin
    _wait_until_deployed(deployment[:deployment_id], timeout)
    puts "Deployment successful".green
    true
  rescue Aws::Waiters::Errors::WaiterFailed => e
    puts  "Failed to deploy: #{e.message}".red
    false
  end
end

#create_deployment_exclude(command, layer_to_exclude, timeout) ⇒ Boolean

Creates an OpsWorks deployment with specified command on all layers excluding layer_to_exclude

Parameters:

  • command (Object)
    • Opsworks deployment command

  • layer_to_exclude (String)
  • timeout (Number)

Returns:

  • (Boolean)


159
160
161
162
163
164
165
# File 'lib/opsworks_wrapper.rb', line 159

def create_deployment_exclude(command, layer_to_exclude, timeout)
  all_instances = get_instances
  excluded_instances = get_instances(layer_to_exclude)
  included_instances = all_instances - excluded_instances

  create_deployment(command, included_instances, timeout)
end

#current_shaObject



10
11
12
# File 'lib/opsworks_wrapper.rb', line 10

def current_sha
  @current_sha ||= `git rev-parse HEAD`.chomp
end

#deploy(layer_name = nil, timeout = 600) ⇒ Boolean

Run deploy command on specified layer or all layers if @layer_name is not specified (non rolling)

Parameters:

  • layer_name (String) (defaults to: nil)
  • timeout (Number) (defaults to: 600)

Returns:

  • (Boolean)


96
97
98
99
100
101
102
103
104
105
106
# File 'lib/opsworks_wrapper.rb', line 96

def deploy(layer_name = nil, timeout = 600)
  if layer_name
    puts "Deploying on #{layer_name} layer".light_white.bold
    instances = get_instances(layer_name)
  else
    puts "Deploying on all layers".light_white.bold
    instances = nil
  end

  create_deployment({name: 'deploy'}, instances, timeout)
end

#deploy_exclude(layer_name, timeout = 600) ⇒ Boolean

Deploy to all layers except specified layer (non-rolling)

Parameters:

  • layer_name (String)
  • timeout (Number) (defaults to: 600)

Returns:

  • (Boolean)


149
150
151
152
# File 'lib/opsworks_wrapper.rb', line 149

def deploy_exclude(layer_name, timeout = 600)
  puts "Deploying to all layers except #{layer_name}".light_white.bold
  create_deployment_exclude({name: 'deploy'}, layer_name, timeout)
end

#deploy_instance_rolling(instance, elb, timeout = 600) ⇒ Boolean

Performs rolling deployment on an instance Will detach instance if elb is provided and re-attach after deployment succeeds

Parameters:

  • instance (Object)
    • opsworks instance

  • elb (Object)
    • elb instance

  • timeout (Number) (defaults to: 600)

Returns:

  • (Boolean)


130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/opsworks_wrapper.rb', line 130

def deploy_instance_rolling(instance, elb, timeout = 600)
  if !elb.nil?
    elb.remove_instance(instance)
  end

  success = create_deployment({name: 'deploy'}, [instance], timeout)

  # only add instance back to elb if deployment succeeded
  if !elb.nil? && success
    success = elb.add_instance(instance)
  end

  success
end

#deploy_layer_rolling(layer_name, timeout = 600) ⇒ Boolean

Performs a rolling deploy on each instance in the layer If an elb is attached to the layer, de-registration and registration will be performed for the instance

Parameters:

  • layer_name (String)
  • timeout (Number) (defaults to: 600)

Returns:

  • (Boolean)


113
114
115
116
117
118
119
120
121
122
# File 'lib/opsworks_wrapper.rb', line 113

def deploy_layer_rolling(layer_name, timeout = 600)
  instances = get_instances(layer_name)
  elb = get_elb(layer_name)
  success = true
  instances.each do |instance|
    success = deploy_instance_rolling(instance, elb, timeout)
    break if !success
  end
  success
end

#get_elb(layer_name) ⇒ Object?

Returns ELB instance for layer if one is attached

Parameters:

  • layer_name (String)

Returns:

  • (Object?)
    • ELB instance



73
74
75
76
77
78
79
80
81
82
# File 'lib/opsworks_wrapper.rb', line 73

def get_elb(layer_name)
  layer_id = layers[layer_name].layer_id
  elbs = opsworks_client.describe_elastic_load_balancers(layer_ids:[layer_id])
  if elbs.elastic_load_balancers.size > 0
    name = elbs.elastic_load_balancers.first.elastic_load_balancer_name
    ELB.new(name)
  else
    nil
  end
end

#get_instances(layer_name = nil) ⇒ List[Object]

Returns a list of OpsWorks instances for a specific layer or all layers if @layer_name is not provided

Parameters:

  • layer_name (String) (defaults to: nil)

Returns:

  • (List[Object])
    • List of OpsWorks instances



59
60
61
62
63
64
65
66
67
68
# File 'lib/opsworks_wrapper.rb', line 59

def get_instances(layer_name = nil)
  if layer_name == nil
    data = opsworks_client.describe_instances(stack_id: opsworks_app[:stack_id])
  else
    layer_id = layers[layer_name].layer_id
    data = opsworks_client.describe_instances(layer_id: layer_id)
  end

  data.instances
end

#get_opsworks_appObject

Returns OpsWorks app details

Returns:

  • (Object)


47
48
49
50
51
52
53
# File 'lib/opsworks_wrapper.rb', line 47

def get_opsworks_app
  data = opsworks_client.describe_apps(app_ids: [app_id])
  if !(data[:apps] && data[:apps].count == 1)
    raise Error, "App #{app_id} not found.", error.backtrace
  end
  data[:apps].first
end

#get_opsworks_layersDictionary

Returns a dictionary for all OpsWorks layers keyed by layer name

Returns:

  • (Dictionary)


36
37
38
39
40
41
42
43
# File 'lib/opsworks_wrapper.rb', line 36

def get_opsworks_layers
  data = opsworks_client.describe_layers(stack_id: opsworks_app[:stack_id])
  layers = {}
  data.layers.each do |layer|
    layers[layer.name] = layer
  end
  layers
end

#layersObject



30
31
32
# File 'lib/opsworks_wrapper.rb', line 30

def layers
  @layers ||= get_opsworks_layers
end

#load_balancer_clientObject



22
23
24
# File 'lib/opsworks_wrapper.rb', line 22

def load_balancer_client
  @client ||= Aws::ElasticLoadBalancing::Client.new
end

#opsworks_appObject



14
15
16
# File 'lib/opsworks_wrapper.rb', line 14

def opsworks_app
  @opsworks_app ||= get_opsworks_app
end

#opsworks_clientObject



18
19
20
# File 'lib/opsworks_wrapper.rb', line 18

def opsworks_client
  @opsworks_client ||= Aws::OpsWorks::Client.new
end

#update_cookbooks(timeout = 150) ⇒ Boolean

Run update cookbooks on all layers

Parameters:

  • timeout (Number) (defaults to: 150)

Returns:

  • (Boolean)


87
88
89
90
# File 'lib/opsworks_wrapper.rb', line 87

def update_cookbooks(timeout = 150)
  puts 'Updating cookbooks'.light_white.bold
  create_deployment({name: 'update_custom_cookbooks'}, nil, timeout)
end