capistrano-asg 0.5.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.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +22 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +15 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +80 -0
  8. data/Rakefile +5 -0
  9. data/capistrano-asg.gemspec +31 -0
  10. data/lib/capistrano/asg/ami.rb +60 -0
  11. data/lib/capistrano/asg/aws/autoscaling.rb +36 -0
  12. data/lib/capistrano/asg/aws/credentials.rb +20 -0
  13. data/lib/capistrano/asg/aws/ec2.rb +28 -0
  14. data/lib/capistrano/asg/aws_resource.rb +43 -0
  15. data/lib/capistrano/asg/launch_configuration.rb +69 -0
  16. data/lib/capistrano/asg/logger.rb +9 -0
  17. data/lib/capistrano/asg/retryable.rb +18 -0
  18. data/lib/capistrano/asg/taggable.rb +12 -0
  19. data/lib/capistrano/asg/tasks/asg.rake +17 -0
  20. data/lib/capistrano/asg/version.rb +5 -0
  21. data/lib/capistrano/asg.rb +56 -0
  22. data/lib/capistrano-asg.rb +0 -0
  23. data/spec/ami_spec.rb +11 -0
  24. data/spec/asg_spec.rb +69 -0
  25. data/spec/spec_helper.rb +32 -0
  26. data/spec/support/stubs/CreateImage.200.xml +4 -0
  27. data/spec/support/stubs/CreateLaunchConfiguration.200.xml +5 -0
  28. data/spec/support/stubs/CreateTags.200.xml +4 -0
  29. data/spec/support/stubs/DeleteLaunchConfiguration.200.xml +5 -0
  30. data/spec/support/stubs/DeleteSnapshot.200.xml +4 -0
  31. data/spec/support/stubs/DeregisterImage.200.xml +4 -0
  32. data/spec/support/stubs/DescribeAutoScalingGroups.200.xml +21 -0
  33. data/spec/support/stubs/DescribeImages.200.xml +44 -0
  34. data/spec/support/stubs/DescribeInstances.200.xml +124 -0
  35. data/spec/support/stubs/DescribeLaunchConfigurations.200.xml +29 -0
  36. data/spec/support/stubs/DescribeSnapshots.200.xml +27 -0
  37. data/spec/support/stubs/DescribeTags.200.xml +17 -0
  38. data/spec/support/stubs/UpdateAutoScalingGroup.200.xml +5 -0
  39. data/spec/support/stubs/security-credentials.200.json +9 -0
  40. metadata +203 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 65590a9ec7bb5ea9e7989900db32e3186d113dc1
4
+ data.tar.gz: 1de9dbe90e304d5bf31a46444fbd912d0445bbce
5
+ SHA512:
6
+ metadata.gz: e7318766a16a55a0a8668e55fe0efaee988ea7e1ba7a6635fdcaf5b6b5158b01458d7617aa0dd13afc8995d891c65cae2011cb62c70177a68a3a67fa2c077f8d
7
+ data.tar.gz: d656273906059100458d400dd04ec9f539b3f5d62f4dfa2afa9e2c6250bd3482b076b4d94639fad5fbc68fad9ad8a327885ff3ff38c5269633c777cc16002b9d
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ bin/
2
+ *.gem
3
+ *.rbc
4
+ /Gemfile.lock
5
+ .bundle
6
+ .config
7
+ .yardoc
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.travis.yml ADDED
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+ cache: bundler
3
+ rvm:
4
+ - 2.3.3
5
+ - 2.4.1
6
+ sudo: false
7
+ env:
8
+ - AWS_REGION: us-west-2
9
+ deploy:
10
+ provider: rubygems
11
+ gem:
12
+ master: capistrano-asg
13
+ on:
14
+ repo: sixfeetover/capistrano-asg
15
+ branch: master
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in capistrano-asg.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Logan Serman
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,80 @@
1
+ # capistrano-asg
2
+
3
+ This is a fork of [lserman/capistrano-elbas](https://github.com/lserman/capistrano-elbas), updated with new features and Capistrano 3 conventions.
4
+
5
+ capistrano-asg was written to ease the deployment of Rails applications to AWS AutoScale groups. capistrano-asg will:
6
+
7
+ - Deploy your code to each running instance connected to a given AutoScale group
8
+ - After deployment, create an AMI from one of the running instances
9
+ - Attach the AMI with the new code to a new AWS Launch Configuration
10
+ - Update your AutoScale group to use the new launch configuration
11
+ - Delete any old AMIs created by capistrano-asg
12
+ - Delete any old launch configurations created by capistrano-asg
13
+
14
+ This ensures that your current and future servers will be running the newly deployed code.
15
+
16
+ ## Installation
17
+
18
+ `gem 'capistrano-asg'`
19
+
20
+ Add this statement to your Capfile:
21
+
22
+ `require 'capistrano/asg'`
23
+
24
+ ## Configuration
25
+
26
+ Below are the Capistrano configuration options with their defaults:
27
+
28
+ ```ruby
29
+ set :aws_access_key_id, ENV['AWS_ACCESS_KEY_ID']
30
+ set :aws_secret_access_key, ENV['AWS_SECRET_ACCESS_KEY']
31
+ set :aws_region, ENV['AWS_REGION']
32
+
33
+ set :aws_no_reboot_on_create_ami, true
34
+ set :aws_autoscale_instance_size, 'm1.small'
35
+
36
+ set :aws_launch_configuration_detailed_instance_monitoring, true
37
+ set :aws_launch_configuration_associate_public_ip, true
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ Instead of using Capistrano's `server` method, use `autoscale` instead in `deploy/production.rb` (or
43
+ whichever environment you're deploying to). Provide the name of your AutoScale group instead of a
44
+ hostname:
45
+
46
+ ```ruby
47
+ autoscale 'production', user: 'apps', roles: [:app, :web, :db]
48
+ ```
49
+
50
+ If you have multiple autoscaling groups to deploy to, specify each of them:
51
+
52
+ ```ruby
53
+ autoscale 'asg-app', user: 'apps', roles: [:app, :web]
54
+ autoscale 'asg-db', user: 'apps', roles: [:db]
55
+ ```
56
+
57
+ Similarly, if you are deploying to multiple regions:
58
+
59
+ ```ruby
60
+ regions = %w(us-east-1 eu-west-1)
61
+
62
+ regions.each do |region|
63
+ set :aws_region, region
64
+ autoscale 'production', user: 'apps', roles: [:app, :web, :db]
65
+ end
66
+ ```
67
+
68
+ That's it! Run `cap production deploy`. The following log statements are printed
69
+ during deployment:
70
+
71
+ ```
72
+ Autoscaling: Adding server: ec2-XX-XX-XX-XXX.compute-1.amazonaws.com
73
+ Autoscaling: Creating EC2 AMI from i-123abcd
74
+ Autoscaling: Created AMI: ami-123456
75
+ Autoscaling: Creating an EC2 Launch Configuration for AMI: ami-123456
76
+ Autoscaling: Created Launch Configuration: cap-asg-lc-ENVIRONMENT-UNIX_TIMESTAMP
77
+ Autoscaling: Attaching Launch Configuration to AutoScale Group
78
+ Autoscaling: Deleting old launch configuration: cap-asg-lc-production-123456
79
+ Autoscaling: Deleting old image: ami-999999
80
+ ```
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+ task :default => :spec
5
+ RSpec::Core::RakeTask.new
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ # frozen_string_literal: true
3
+
4
+ lib = File.expand_path('../lib', __FILE__)
5
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
6
+ require 'capistrano/asg/version'
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = 'capistrano-asg'
10
+ spec.version = Capistrano::Asg::VERSION
11
+ spec.authors = ['Logan Serman', 'Jeff Fraser', 'Michael Martell']
12
+ spec.email = ['logan.serman@metova.com', 'jeff.fraser@veracross.com', 'michael.martell@veracross.com']
13
+ spec.summary = 'Capistrano plugin for deploying to AWS AutoScale Groups.'
14
+ spec.description = "#{spec.summary} Deploys to all instances in a group, creates a fresh AMI post-deploy, and attaches the AMI to your AutoScale Group."
15
+ spec.homepage = 'http://github.com/sixfeetover/capistrano-asg'
16
+ spec.license = 'MIT'
17
+
18
+ spec.files = `git ls-files -z`.split("\x0")
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_development_dependency 'bundler', '~> 1.6'
24
+ spec.add_development_dependency 'rake'
25
+ spec.add_development_dependency 'rspec'
26
+ spec.add_development_dependency 'webmock'
27
+
28
+ spec.add_dependency 'aws-sdk', '~> 2'
29
+ spec.add_dependency 'capistrano', '> 3.0.0'
30
+ spec.add_dependency 'activesupport', '>= 4.0.0'
31
+ end
@@ -0,0 +1,60 @@
1
+ module Capistrano
2
+ module Asg
3
+ # Extend AWS Resource class to include AMI methods
4
+ class AMI < AWSResource
5
+ include Taggable
6
+
7
+ def self.create(&_block)
8
+ ami = new
9
+ ami.cleanup do
10
+ ami.save
11
+ ami.tag 'deployed-with' => 'cap-asg'
12
+ ami.tag 'cap-asg-deploy-group' => ami.autoscaling_group_name
13
+ yield ami
14
+ end
15
+ end
16
+
17
+ def save
18
+ info "Creating EC2 AMI from EC2 Instance: #{base_ec2_instance.id}"
19
+ ec2_instance = ec2_resource.instance(base_ec2_instance.id)
20
+ @aws_counterpart = ec2_instance.create_image(
21
+ name: name,
22
+ no_reboot: fetch(:aws_no_reboot_on_create_ami, true)
23
+ )
24
+ end
25
+
26
+ def destroy(images = [])
27
+ images.each do |i|
28
+ info "Deleting old AMI: #{i.id}"
29
+ snapshots = snapshots_attached_to i
30
+ i.deregister
31
+ delete_snapshots snapshots
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def name
38
+ timestamp "latest-#{environment}-AMI"
39
+ end
40
+
41
+ def trash
42
+ ec2_resource.images(owners: ['self']).to_a.select do |ami|
43
+ deployed_with_asg? ami
44
+ end
45
+ end
46
+
47
+ def snapshots_attached_to(image)
48
+ ids = image.block_device_mappings.map(&:ebs).compact.map(&:snapshot_id)
49
+ ec2_resource.snapshots(snapshot_ids: ids)
50
+ end
51
+
52
+ def delete_snapshots(snapshots)
53
+ snapshots.each do |snapshot|
54
+ info "Deleting snapshot: #{snapshot.id}"
55
+ snapshot.delete unless snapshot.nil?
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Capistrano
4
+ module Asg
5
+ module Aws
6
+ # Provide AutoScaling client, resource, and group information
7
+ module AutoScaling
8
+ extend ActiveSupport::Concern
9
+ include Credentials
10
+ include Capistrano::DSL
11
+
12
+ def autoscaling_client
13
+ @_autoscaling_client ||= ::Aws::AutoScaling::Client.new(credentials)
14
+ end
15
+
16
+ def autoscaling_resource
17
+ @_autoscaling_resource ||= ::Aws::AutoScaling::Resource.new(client: autoscaling_client)
18
+ end
19
+
20
+ def autoscaling_group
21
+ @_autoscaling_group ||= autoscaling_resource.group(autoscaling_group_name)
22
+ end
23
+
24
+ def autoscaling_group_name
25
+ fetch(:aws_autoscale_group)
26
+ end
27
+
28
+ def reset_autoscaling_objects
29
+ @_autoscaling_client = nil
30
+ @_autoscaling_resource = nil
31
+ @_autoscaling_group = nil
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Capistrano
4
+ module Asg
5
+ module Aws
6
+ module Credentials
7
+ extend ActiveSupport::Concern
8
+ include Capistrano::DSL
9
+
10
+ def credentials
11
+ {
12
+ access_key_id: fetch(:aws_access_key_id, ENV['AWS_ACCESS_KEY_ID']),
13
+ secret_access_key: fetch(:aws_secret_access_key, ENV['AWS_SECRET_ACCESS_KEY']),
14
+ region: fetch(:aws_region, ENV['AWS_REGION'])
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Capistrano
4
+ module Asg
5
+ module Aws
6
+ # Provide EC2 client and resource information
7
+ module EC2
8
+ extend ActiveSupport::Concern
9
+ include Credentials
10
+ include Capistrano::DSL
11
+
12
+ def ec2_resource
13
+ @_ec2_resource ||= ::Aws::EC2::Resource.new(client: ec2_client)
14
+ end
15
+
16
+ def reset_ec2_objects
17
+ @_ec2_resource = nil
18
+ end
19
+
20
+ private
21
+
22
+ def ec2_client
23
+ ::Aws::EC2::Client.new(credentials)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Capistrano
4
+ module Asg
5
+ # Provides basic AWS resource methods
6
+ class AWSResource
7
+ include Capistrano::DSL
8
+ include Capistrano::Asg::Aws::AutoScaling
9
+ include Capistrano::Asg::Aws::EC2
10
+ include Capistrano::Asg::Retryable
11
+ include Logger
12
+
13
+ attr_reader :aws_counterpart
14
+
15
+ def cleanup(&_block)
16
+ items = trash || []
17
+ yield
18
+ destroy items
19
+ self
20
+ end
21
+
22
+ private
23
+
24
+ def base_ec2_instance
25
+ autoscaling_group.instances[0]
26
+ end
27
+
28
+ def environment
29
+ fetch(:rails_env, 'production')
30
+ end
31
+
32
+ def timestamp(str)
33
+ "#{str}-#{Time.now.to_i}"
34
+ end
35
+
36
+ def deployed_with_asg?(resource)
37
+ return false if resource.tags.empty?
38
+ resource.tags.any? { |k| k.key == 'deployed-with' && k.value == 'cap-asg' } &&
39
+ resource.tags.any? { |k| k.key == 'cap-asg-deploy-group' && k.value == autoscaling_group_name }
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,69 @@
1
+ module Capistrano
2
+ module Asg
3
+ # Create launch configuration
4
+ class LaunchConfiguration < AWSResource
5
+ def self.create(ami, &_block)
6
+ lc = new
7
+ lc.cleanup do
8
+ lc.save(ami)
9
+ yield lc
10
+ end
11
+ end
12
+
13
+ def save(ami)
14
+ info "Creating an EC2 Launch Configuration for AMI: \
15
+ #{ami.aws_counterpart.id}"
16
+ ec2_instance = ec2_resource.instance(base_ec2_instance.id)
17
+ with_retry do
18
+ @aws_counterpart = autoscaling_resource.create_launch_configuration(
19
+ launch_configuration_name: name,
20
+ image_id: ami.aws_counterpart.id,
21
+ instance_type: instance_size,
22
+ security_groups: ec2_instance.security_groups.map(&:group_id),
23
+ associate_public_ip_address:
24
+ fetch(:aws_launch_configuration_associate_public_ip, true),
25
+ instance_monitoring: {
26
+ enabled: fetch(:aws_launch_configuration_detailed_instance_monitoring, true)
27
+ },
28
+ user_data: fetch(:aws_launch_configuration_user_data, nil)
29
+ )
30
+ end
31
+ end
32
+
33
+ def attach_to_autoscale_group!
34
+ info "Attaching Launch Configuration #{aws_counterpart.name} \
35
+ to AutoScaling Group #{autoscaling_group.name}"
36
+ autoscaling_group.update(
37
+ launch_configuration_name: aws_counterpart.name
38
+ )
39
+ end
40
+
41
+ def destroy(launch_configurations = [])
42
+ launch_configurations.each do |lc|
43
+ info "Deleting old Launch Configuration: #{lc.name}"
44
+ lc.delete
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def name
51
+ timestamp "cap-asg-#{environment}-#{autoscaling_group_name}-lc"
52
+ end
53
+
54
+ def instance_size
55
+ fetch(:aws_autoscale_instance_size, 'm1.small')
56
+ end
57
+
58
+ def deployed_with_asg?(lc)
59
+ lc.name.include? "cap-asg-#{environment}-#{autoscaling_group_name}-lc"
60
+ end
61
+
62
+ def trash
63
+ autoscaling_resource.launch_configurations.to_a.select do |lc|
64
+ deployed_with_asg? lc
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,9 @@
1
+ module Capistrano
2
+ module Asg
3
+ module Logger
4
+ def info(message)
5
+ puts "Autoscaling: #{message}"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,18 @@
1
+ module Capistrano
2
+ module Asg
3
+ module Retryable
4
+ def with_retry(max: fetch(:asg_retry_max, 3), delay: fetch(:asg_retry_delay, 5))
5
+ tries ||= 0
6
+ tries += 1
7
+ yield
8
+ rescue => e
9
+ puts "Rescued #{e.message}"
10
+ if tries < max
11
+ puts "Retrying in #{delay} seconds..."
12
+ sleep delay
13
+ retry
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ module Capistrano
2
+ module Asg
3
+ # Adds tags to AWS resources
4
+ module Taggable
5
+ def tag(tags = {})
6
+ with_retry do
7
+ tags.each { |k, v| aws_counterpart.create_tags(tags: [{key: k, value: v}]) }
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,17 @@
1
+ require 'capistrano/asg'
2
+
3
+ namespace :asg do
4
+ task :scale do
5
+ set :aws_access_key_id, fetch(:aws_access_key_id, ENV['AWS_ACCESS_KEY_ID'])
6
+ set :aws_secret_access_key, fetch(:aws_secret_access_key, ENV['AWS_SECRET_ACCESS_KEY'])
7
+ set :aws_region, fetch(:aws_region, ENV['AWS_REGION'])
8
+
9
+ Capistrano::Asg::AMI.create do |ami|
10
+ puts "Autoscaling: Created AMI: #{ami.aws_counterpart.id}"
11
+ Capistrano::Asg::LaunchConfiguration.create(ami) do |lc|
12
+ puts "Autoscaling: Created Launch Configuration: #{lc.aws_counterpart.name}"
13
+ lc.attach_to_autoscale_group!
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ module Capistrano
2
+ module Asg
3
+ VERSION = '0.5.0'.freeze
4
+ end
5
+ end
@@ -0,0 +1,56 @@
1
+ require 'aws-sdk'
2
+ require 'capistrano/all'
3
+ require 'active_support/concern'
4
+
5
+ require 'capistrano/asg/version'
6
+ require 'capistrano/asg/retryable'
7
+ require 'capistrano/asg/taggable'
8
+ require 'capistrano/asg/logger'
9
+ require 'capistrano/asg/aws/credentials'
10
+ require 'capistrano/asg/aws/autoscaling'
11
+ require 'capistrano/asg/aws/ec2'
12
+ require 'capistrano/asg/aws_resource'
13
+ require 'capistrano/asg/ami'
14
+ require 'capistrano/asg/launch_configuration'
15
+
16
+ module Capistrano
17
+ module Asg
18
+ end
19
+ end
20
+
21
+ require 'aws-sdk'
22
+ require 'capistrano/dsl'
23
+
24
+ load File.expand_path('../asg/tasks/asg.rake', __FILE__)
25
+
26
+ def autoscale(groupname, *args)
27
+ include Capistrano::DSL
28
+ include Capistrano::Asg::Aws::AutoScaling
29
+ include Capistrano::Asg::Aws::EC2
30
+
31
+ autoscaling_group = autoscaling_resource.group(groupname)
32
+ asg_instances = autoscaling_group.instances
33
+
34
+ set :aws_autoscale_group, groupname
35
+
36
+ asg_instances.each do |asg_instance|
37
+ if asg_instance.health_status != 'Healthy'
38
+ puts "Autoscaling: Skipping unhealthy instance #{instance.id}"
39
+ else
40
+ ec2_instance = ec2_resource.instance(asg_instance.id)
41
+ hostname = ec2_instance.private_ip_address
42
+ puts "Autoscaling: Adding server #{hostname}"
43
+ server(hostname, *args)
44
+ end
45
+ end
46
+
47
+ if asg_instances.count > 0
48
+ after('deploy', 'asg:scale')
49
+ else
50
+ puts 'Autoscaling: AMI could not be created because no running instances were found.\
51
+ Is your autoscale group name correct?'
52
+ end
53
+
54
+ reset_autoscaling_objects
55
+ reset_ec2_objects
56
+ end
File without changes
data/spec/ami_spec.rb ADDED
@@ -0,0 +1,11 @@
1
+ describe Capistrano::Asg::AMI do
2
+ describe '#tag' do
3
+ subject { Capistrano::Asg::AMI.new }
4
+
5
+ it 'retries the tag 3 times' do
6
+ skip
7
+ expect(subject).to receive(:aws_counterpart).exactly(3).times { raise RuntimeError }
8
+ subject.tag 'Test' => true
9
+ end
10
+ end
11
+ end
data/spec/asg_spec.rb ADDED
@@ -0,0 +1,69 @@
1
+ describe 'Capistrano::Asg' do
2
+ before do
3
+ allow_any_instance_of(Capistrano::Asg::AWSResource).to receive(:autoscaling_group_name) { 'production' }
4
+ webmock :get, /security-credentials/ => 'security-credentials.200.json'
5
+ webmock(:post, %r{autoscaling.(.*).amazonaws.com\/\z} => 'DescribeAutoScalingGroups.200.xml') { Hash[body: /Action=DescribeAutoScalingGroups/] }
6
+ webmock(:post, %r{ec2.(.*).amazonaws.com\/\z} => 'DescribeImages.200.xml') { Hash[body: /Action=DescribeImages/] }
7
+ webmock(:post, %r{ec2.(.*).amazonaws.com\/\z} => 'DescribeTags.200.xml') { Hash[body: /Action=DescribeTags/] }
8
+ webmock(:post, %r{ec2.(.*).amazonaws.com\/\z} => 'DescribeInstances.200.xml') { Hash[body: /Action=DescribeInstances/] }
9
+ webmock(:post, %r{ec2.(.*).amazonaws.com\/\z} => 'CreateImage.200.xml') { Hash[body: /Action=CreateImage/] }
10
+ webmock(:post, %r{ec2.(.*).amazonaws.com\/\z} => 'DeregisterImage.200.xml') { Hash[body: /Action=DeregisterImage/] }
11
+ webmock(:post, %r{ec2.(.*).amazonaws.com\/\z} => 'CreateTags.200.xml') { Hash[body: /Action=CreateTags/] }
12
+ webmock(:post, %r{ec2.(.*).amazonaws.com\/\z} => 'DescribeSnapshots.200.xml') { Hash[body: /Action=DescribeSnapshots/] }
13
+ webmock(:post, %r{ec2.(.*).amazonaws.com\/\z} => 'DeleteSnapshot.200.xml') { Hash[body: /Action=DeleteSnapshot/] }
14
+ webmock(:post, %r{autoscaling.(.*).amazonaws.com\/\z} => 'DescribeLaunchConfigurations.200.xml') { Hash[body: /Action=DescribeLaunchConfigurations/] }
15
+ webmock(:post, %r{autoscaling.(.*).amazonaws.com\/\z} => 'CreateLaunchConfiguration.200.xml') { Hash[body: /Action=CreateLaunchConfiguration/] }
16
+ webmock(:post, %r{autoscaling.(.*).amazonaws.com\/\z} => 'DeleteLaunchConfiguration.200.xml') { Hash[body: /Action=DeleteLaunchConfiguration/] }
17
+ webmock(:post, %r{autoscaling.(.*).amazonaws.com\/\z} => 'UpdateAutoScalingGroup.200.xml') { Hash[body: /Action=UpdateAutoScalingGroup/] }
18
+ end
19
+
20
+ let!(:ami) do
21
+ _ami = nil
22
+ Capistrano::Asg::AMI.create { |ami| _ami = ami }
23
+ _ami
24
+ end
25
+
26
+ describe 'AMI creation & cleanup' do
27
+ it 'creates a new AMI on Amazon' do
28
+ expect(ami.aws_counterpart.id).to eq 'ami-4fa54026'
29
+ end
30
+
31
+ it 'deletes any AMIs tagged with deployed-with=cap-asg' do
32
+ expect(WebMock).to have_requested(:post, /ec2.(.*).amazonaws.com\/\z/).with(body: /Action=DeregisterImage&ImageId=ami-1a2b3c4d/)
33
+ end
34
+
35
+ it 'deletes snapshots that are associated with the AMI' do
36
+ expect(WebMock).to have_requested(:post, /ec2.(.*).amazonaws.com\/\z/).with(body: /Action=DeleteSnapshot&SnapshotId=snap-1a2b3c4d/)
37
+ end
38
+
39
+ it 'tags the new AMI with deployed-with=cap-asg' do
40
+ expect(WebMock).to have_requested(:post, /ec2.(.*).amazonaws.com\/\z/).with(body: /Action=CreateTags&ResourceId.1=ami-4fa54026&Tag.1.Key=deployed-with&Tag.1.Value=cap-asg/)
41
+ end
42
+
43
+ it 'tags the new AMI with cap-asg-Deploy-group=<autoscale group name>' do
44
+ expect(WebMock).to have_requested(:post, /ec2.(.*).amazonaws.com\/\z/).with(body: /Action=CreateTags&ResourceId.1=ami-4fa54026&Tag.1.Key=cap-asg-deploy-group&Tag.1.Value=production/)
45
+ end
46
+ end
47
+
48
+ describe 'Launch configuration creation & cleanup' do
49
+ let!(:launch_configuration) do
50
+ _lc = nil
51
+ Capistrano::Asg::LaunchConfiguration.create(ami) { |lc| _lc = lc }
52
+ _lc
53
+ end
54
+
55
+ it 'creates a new Launch Configuration on AWS' do
56
+ expect(WebMock).to have_requested(:post, /autoscaling.(.*).amazonaws.com\/\z/).
57
+ with(body: /Action=CreateLaunchConfiguration&AssociatePublicIpAddress=true&ImageId=ami-4fa54026&InstanceMonitoring.Enabled=true&InstanceType=m1.small&LaunchConfigurationName=cap-asg-production/)
58
+ end
59
+
60
+ it 'deletes any LCs with name =~ cap-asg-production' do
61
+ expect(WebMock).to have_requested(:post, /autoscaling.(.*).amazonaws.com\/\z/).with(body: /Action=DeleteLaunchConfiguration&LaunchConfigurationName=cap-asg-production-production-lc-1234567890/)
62
+ end
63
+
64
+ it 'attaches the LC to the autoscale group' do
65
+ launch_configuration.attach_to_autoscale_group!
66
+ expect(WebMock).to have_requested(:post, /autoscaling.(.*).amazonaws.com\/\z/).with(body: /Action=UpdateAutoScalingGroup&AutoScalingGroupName=production&LaunchConfigurationName=cap-asg-production-production-lc-\d{10,}/)
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,32 @@
1
+ require 'webmock'
2
+ require 'capistrano/all'
3
+ require 'capistrano/asg'
4
+ require 'webmock/rspec'
5
+
6
+ WebMock.disable_net_connect!
7
+
8
+ Dir[File.join(File.expand_path('../..', __FILE__), 'spec', 'support', '**', '*.rb')].each { |f| require f }
9
+
10
+ module WebMock
11
+ module RSpec
12
+ module Helper
13
+
14
+ def webmock(method, mocks = {})
15
+ mocks.each do |regex, filename|
16
+ status = filename[/\.(\d+)\./, 1] || 200
17
+ body = File.read File.join(File.expand_path('../..', __FILE__), 'spec', 'support', 'stubs', filename)
18
+ if block_given? && with_options = yield
19
+ WebMock.stub_request(method, regex).with(with_options).to_return status: status.to_i, body: body
20
+ else
21
+ WebMock.stub_request(method, regex).to_return status: status.to_i, body: body
22
+ end
23
+ end
24
+ end
25
+
26
+ end
27
+ end
28
+ end
29
+
30
+ RSpec.configure do |config|
31
+ config.include WebMock::RSpec::Helper
32
+ end
@@ -0,0 +1,4 @@
1
+ <CreateImageResponse xmlns="http://ec2.amazonaws.com/doc/2014-10-01/">
2
+ <requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
3
+ <imageId>ami-4fa54026</imageId>
4
+ </CreateImageResponse>
@@ -0,0 +1,5 @@
1
+ <CreateLaunchConfigurationResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
2
+ <ResponseMetadata>
3
+ <RequestId>7c6e177f-f082-11e1-ac58-3714bEXAMPLE</RequestId>
4
+ </ResponseMetadata>
5
+ </CreateLaunchConfigurationResponse>
@@ -0,0 +1,4 @@
1
+ <CreateTagsResponse xmlns="http://ec2.amazonaws.com/doc/2014-10-01/">
2
+ <requestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</requestId>
3
+ <return>true</return>
4
+ </CreateTagsResponse>
@@ -0,0 +1,5 @@
1
+ <DeleteLaunchConfigurationResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
2
+ <ResponseMetadata>
3
+ <RequestId>7347261f-97df-11e2-8756-35eEXAMPLE</RequestId>
4
+ </ResponseMetadata>
5
+ </DeleteLaunchConfigurationResponse>
@@ -0,0 +1,4 @@
1
+ <DeleteSnapshotResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
2
+ <requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
3
+ <return>true</return>
4
+ </DeleteSnapshotResponse>
@@ -0,0 +1,4 @@
1
+ <DeregisterImageResponse xmlns="http://ec2.amazonaws.com/doc/2014-10-01/">
2
+ <requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
3
+ <return>true</return>
4
+ </DeregisterImageResponse>
@@ -0,0 +1,21 @@
1
+ <DescribeAutoScalingGroupsResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
2
+ <ResponseMetadata>
3
+ <RequestId>7c6e177f-f082-11e1-ac58-3714bEXAMPLE</RequestId>
4
+ </ResponseMetadata>
5
+ <DescribeAutoScalingGroupsResult>
6
+ <AutoScalingGroups>
7
+ <member>
8
+ <AutoScalingGroupName>production</AutoScalingGroupName>
9
+ <Instances>
10
+ <member>
11
+ <LaunchConfigurationName>cap-asg-production-production-lc-1234567890</LaunchConfigurationName>
12
+ <LifecycleState>InService</LifecycleState>
13
+ <InstanceId>i-1a2b3c4d</InstanceId>
14
+ <ProtectedFromScaleIn>false</ProtectedFromScaleIn>
15
+ <AvailabilityZone>us-west-2a</AvailabilityZone>
16
+ </member>
17
+ </Instances>
18
+ </member>
19
+ </AutoScalingGroups>
20
+ </DescribeAutoScalingGroupsResult>
21
+ </DescribeAutoScalingGroupsResponse>
@@ -0,0 +1,44 @@
1
+ <DescribeImagesResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
2
+ <requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
3
+ <imagesSet>
4
+ <item>
5
+ <imageId>ami-1a2b3c4d</imageId>
6
+ <imageLocation>amazon/getting-started</imageLocation>
7
+ <imageState>available</imageState>
8
+ <imageOwnerId>123456789012</imageOwnerId>
9
+ <isPublic>true</isPublic>
10
+ <architecture>i386</architecture>
11
+ <imageType>machine</imageType>
12
+ <kernelId>aki-1a2b3c4d</kernelId>
13
+ <ramdiskId>ari-1a2b3c4d</ramdiskId>
14
+ <imageOwnerAlias>self</imageOwnerAlias>
15
+ <name>getting-started</name>
16
+ <description>Image Description</description>
17
+ <rootDeviceType>ebs</rootDeviceType>
18
+ <rootDeviceName>/dev/sda</rootDeviceName>
19
+ <blockDeviceMapping>
20
+ <item>
21
+ <deviceName>/dev/sda1</deviceName>
22
+ <ebs>
23
+ <snapshotId>snap-1a2b3c4d</snapshotId>
24
+ <volumeSize>15</volumeSize>
25
+ <deleteOnTermination>false</deleteOnTermination>
26
+ <volumeType>standard</volumeType>
27
+ </ebs>
28
+ </item>
29
+ </blockDeviceMapping>
30
+ <virtualizationType>paravirtual</virtualizationType>
31
+ <tagSet>
32
+ <item>
33
+ <key>deployed-with</key>
34
+ <value>cap-asg</value>
35
+ </item>
36
+ <item>
37
+ <key>cap-asg-deploy-group</key>
38
+ <value>production</value>
39
+ </item>
40
+ </tagSet>
41
+ <hypervisor>xen</hypervisor>
42
+ </item>
43
+ </imagesSet>
44
+ </DescribeImagesResponse>
@@ -0,0 +1,124 @@
1
+ <DescribeInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2014-10-01/">
2
+ <requestId>fdcdcab1-ae5c-489e-9c33-4637c5dda355</requestId>
3
+ <reservationSet>
4
+ <item>
5
+ <reservationId>r-1a2b3c4d</reservationId>
6
+ <ownerId>123456789012</ownerId>
7
+ <groupSet>
8
+ <item>
9
+ <groupId>sg-1a2b3c4d</groupId>
10
+ <groupName>my-security-group</groupName>
11
+ </item>
12
+ </groupSet>
13
+ <instancesSet>
14
+ <item>
15
+ <instanceId>i-1a2b3c4d</instanceId>
16
+ <imageId>ami-1a2b3c4d</imageId>
17
+ <instanceState>
18
+ <code>16</code>
19
+ <name>running</name>
20
+ </instanceState>
21
+ <privateDnsName/>
22
+ <dnsName/>
23
+ <reason/>
24
+ <keyName>my-key-pair</keyName>
25
+ <amiLaunchIndex>0</amiLaunchIndex>
26
+ <productCodes/>
27
+ <instanceType>c1.medium</instanceType>
28
+ <launchTime>Y2035-02-09T23:17:13Z+0000</launchTime>
29
+ <placement>
30
+ <availabilityZone>us-west-2a</availabilityZone>
31
+ <groupName/>
32
+ <tenancy>default</tenancy>
33
+ </placement>
34
+ <platform>windows</platform>
35
+ <monitoring>
36
+ <state>disabled</state>
37
+ </monitoring>
38
+ <subnetId>subnet-1a2b3c4d</subnetId>
39
+ <vpcId>vpc-1a2b3c4d</vpcId>
40
+ <privateIpAddress>10.0.0.12</privateIpAddress>
41
+ <ipAddress>46.51.219.63</ipAddress>
42
+ <sourceDestCheck>true</sourceDestCheck>
43
+ <groupSet>
44
+ <item>
45
+ <groupId>sg-1a2b3c4d</groupId>
46
+ <groupName>my-security-group</groupName>
47
+ </item>
48
+ </groupSet>
49
+ <architecture>x86_64</architecture>
50
+ <rootDeviceType>ebs</rootDeviceType>
51
+ <rootDeviceName>/dev/sda1</rootDeviceName>
52
+ <blockDeviceMapping>
53
+ <item>
54
+ <deviceName>/dev/sda1</deviceName>
55
+ <ebs>
56
+ <volumeId>vol-1a2b3c4d</volumeId>
57
+ <status>attached</status>
58
+ <attachTime>2035-02-09T23:17:13Z</attachTime>
59
+ <deleteOnTermination>true</deleteOnTermination>
60
+ </ebs>
61
+ </item>
62
+ </blockDeviceMapping>
63
+ <virtualizationType>hvm</virtualizationType>
64
+ <clientToken>ABCDE1234567890123</clientToken>
65
+ <tagSet>
66
+ <item>
67
+ <key>Name</key>
68
+ <value>Windows Instance</value>
69
+ </item>
70
+ </tagSet>
71
+ <hypervisor>xen</hypervisor>
72
+ <networkInterfaceSet>
73
+ <item>
74
+ <networkInterfaceId>eni-1a2b3c4d</networkInterfaceId>
75
+ <subnetId>subnet-1a2b3c4d</subnetId>
76
+ <vpcId>vpc-1a2b3c4d</vpcId>
77
+ <description>Primary network interface</description>
78
+ <ownerId>123456789012</ownerId>
79
+ <status>in-use</status>
80
+ <macAddress>1b:2b:3c:4d:5e:6f</macAddress>
81
+ <privateIpAddress>10.0.0.12</privateIpAddress>
82
+ <sourceDestCheck>true</sourceDestCheck>
83
+ <groupSet>
84
+ <item>
85
+ <groupId>sg-1a2b3c4d</groupId>
86
+ <groupName>my-security-group</groupName>
87
+ </item>
88
+ </groupSet>
89
+ <attachment>
90
+ <attachmentId>eni-attach-1a2b3c4d</attachmentId>
91
+ <deviceIndex>0</deviceIndex>
92
+ <status>attached</status>
93
+ <attachTime>2035-02-09T23:17:13Z</attachTime>
94
+ <deleteOnTermination>true</deleteOnTermination>
95
+ </attachment>
96
+ <association>
97
+ <publicIp>198.51.100.63</publicIp>
98
+ <ipOwnerId>123456789012</ipOwnerId>
99
+ </association>
100
+ <privateIpAddressesSet>
101
+ <item>
102
+ <privateIpAddress>10.0.0.12</privateIpAddress>
103
+ <primary>true</primary>
104
+ <association>
105
+ <publicIp>198.51.100.63</publicIp>
106
+ <ipOwnerId>123456789012</ipOwnerId>
107
+ </association>
108
+ </item>
109
+ <item>
110
+ <privateIpAddress>10.0.0.14</privateIpAddress>
111
+ <primary>false</primary>
112
+ <association>
113
+ <publicIp>198.51.100.177</publicIp>
114
+ <ipOwnerId>123456789012</ipOwnerId>
115
+ </association>
116
+ </item>
117
+ </privateIpAddressesSet>
118
+ </item>
119
+ </networkInterfaceSet>
120
+ </item>
121
+ </instancesSet>
122
+ </item>
123
+ </reservationSet>
124
+ </DescribeInstancesResponse>
@@ -0,0 +1,29 @@
1
+ <DescribeLaunchConfigurationsResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
2
+ <DescribeLaunchConfigurationsResult>
3
+ <LaunchConfigurations>
4
+ <member>
5
+ <AssociatePublicIpAddress>true</AssociatePublicIpAddress>
6
+ <SecurityGroups/>
7
+ <PlacementTenancy>dedicated</PlacementTenancy>
8
+ <CreatedTime>2013-01-21T23:04:42.200Z</CreatedTime>
9
+ <KernelId/>
10
+ <LaunchConfigurationName>cap-asg-production-production-lc-1234567890</LaunchConfigurationName>
11
+ <UserData/>
12
+ <InstanceType>m1.small</InstanceType>
13
+ <LaunchConfigurationARN>arn:aws:autoscaling:us-east-1:803981987763:launchConfiguration:
14
+ 9dbbbf87-6141-428a-a409-0752edbe6cad:launchConfigurationName/my-test-lc</LaunchConfigurationARN>
15
+ <BlockDeviceMappings/>
16
+ <ImageId>ami-514ac838</ImageId>
17
+ <KeyName/>
18
+ <RamdiskId/>
19
+ <InstanceMonitoring>
20
+ <Enabled>true</Enabled>
21
+ </InstanceMonitoring>
22
+ <EbsOptimized>false</EbsOptimized>
23
+ </member>
24
+ </LaunchConfigurations>
25
+ </DescribeLaunchConfigurationsResult>
26
+ <ResponseMetadata>
27
+ <RequestId>d05a22f8-b690-11e2-bf8e-2113fEXAMPLE</RequestId>
28
+ </ResponseMetadata>
29
+ </DescribeLaunchConfigurationsResponse>
@@ -0,0 +1,27 @@
1
+ <DescribeSnapshotsResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
2
+ <requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
3
+ <snapshotSet>
4
+ <item>
5
+ <snapshotId>snap-1a2b3c4d</snapshotId>
6
+ <volumeId>vol-1234567890abcdef0</volumeId>
7
+ <status>pending</status>
8
+ <startTime>2013-01-21T23:04:42.200Z</startTime>
9
+ <progress>80%</progress>
10
+ <ownerId>111122223333</ownerId>
11
+ <volumeSize>15</volumeSize>
12
+ <description>Daily Backup</description>
13
+ <encrypted>true</encrypted>
14
+ <kmsKeyId>arn:aws:kms:us-east-1:123456789012:key/6876fb1b-example</kmsKeyId>
15
+ <tagSet>
16
+ <item>
17
+ <key>deployed-with</key>
18
+ <value>cap-asg</value>
19
+ </item>
20
+ <item>
21
+ <key>cap-asg-deploy-group</key>
22
+ <value>production</value>
23
+ </item>
24
+ </tagSet>
25
+ </item>
26
+ </snapshotSet>
27
+ </DescribeSnapshotsResponse>
@@ -0,0 +1,17 @@
1
+ <DescribeTagsResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
2
+ <requestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</requestId>
3
+ <tagSet>
4
+ <item>
5
+ <resourceId>ami-1a2b3c4d</resourceId>
6
+ <resourceType>image</resourceType>
7
+ <key>deployed-with</key>
8
+ <value>cap-asg</value>
9
+ </item>
10
+ <item>
11
+ <resourceId>ami-1a2b3c4d</resourceId>
12
+ <resourceType>image</resourceType>
13
+ <key>cap-asg-deploy-group</key>
14
+ <value>production</value>
15
+ </item>
16
+ </tagSet>
17
+ </DescribeTagsResponse>
@@ -0,0 +1,5 @@
1
+ <UpdateAutoScalingGroupResponse xmlns="http://autoscaling.amazonaws.com/doc/2011-01-01/">
2
+ <ResponseMetadata>
3
+ <RequestId>adafead0-ab8a-11e2-ba13-ab0ccEXAMPLE</RequestId>
4
+ </ResponseMetadata>
5
+ </UpdateAutoScalingGroupResponse>
@@ -0,0 +1,9 @@
1
+ {
2
+ "Code" : "Success",
3
+ "LastUpdated" : "2013-11-22T20:03:48Z",
4
+ "Type" : "AWS-HMAC",
5
+ "AccessKeyId" : "akid",
6
+ "SecretAccessKey" : "secret",
7
+ "Token" : "token",
8
+ "Expiration" : "2035-02-09T21:53:57Z"
9
+ }
metadata ADDED
@@ -0,0 +1,203 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: capistrano-asg
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
5
+ platform: ruby
6
+ authors:
7
+ - Logan Serman
8
+ - Jeff Fraser
9
+ - Michael Martell
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2017-08-01 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: bundler
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - "~>"
20
+ - !ruby/object:Gem::Version
21
+ version: '1.6'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - "~>"
27
+ - !ruby/object:Gem::Version
28
+ version: '1.6'
29
+ - !ruby/object:Gem::Dependency
30
+ name: rake
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: '0'
36
+ type: :development
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ - !ruby/object:Gem::Dependency
44
+ name: rspec
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: webmock
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ - !ruby/object:Gem::Dependency
72
+ name: aws-sdk
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: '2'
78
+ type: :runtime
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - "~>"
83
+ - !ruby/object:Gem::Version
84
+ version: '2'
85
+ - !ruby/object:Gem::Dependency
86
+ name: capistrano
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">"
90
+ - !ruby/object:Gem::Version
91
+ version: 3.0.0
92
+ type: :runtime
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">"
97
+ - !ruby/object:Gem::Version
98
+ version: 3.0.0
99
+ - !ruby/object:Gem::Dependency
100
+ name: activesupport
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: 4.0.0
106
+ type: :runtime
107
+ prerelease: false
108
+ version_requirements: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: 4.0.0
113
+ description: Capistrano plugin for deploying to AWS AutoScale Groups. Deploys to all
114
+ instances in a group, creates a fresh AMI post-deploy, and attaches the AMI to your
115
+ AutoScale Group.
116
+ email:
117
+ - logan.serman@metova.com
118
+ - jeff.fraser@veracross.com
119
+ - michael.martell@veracross.com
120
+ executables: []
121
+ extensions: []
122
+ extra_rdoc_files: []
123
+ files:
124
+ - ".gitignore"
125
+ - ".rspec"
126
+ - ".travis.yml"
127
+ - Gemfile
128
+ - LICENSE.txt
129
+ - README.md
130
+ - Rakefile
131
+ - capistrano-asg.gemspec
132
+ - lib/capistrano-asg.rb
133
+ - lib/capistrano/asg.rb
134
+ - lib/capistrano/asg/ami.rb
135
+ - lib/capistrano/asg/aws/autoscaling.rb
136
+ - lib/capistrano/asg/aws/credentials.rb
137
+ - lib/capistrano/asg/aws/ec2.rb
138
+ - lib/capistrano/asg/aws_resource.rb
139
+ - lib/capistrano/asg/launch_configuration.rb
140
+ - lib/capistrano/asg/logger.rb
141
+ - lib/capistrano/asg/retryable.rb
142
+ - lib/capistrano/asg/taggable.rb
143
+ - lib/capistrano/asg/tasks/asg.rake
144
+ - lib/capistrano/asg/version.rb
145
+ - spec/ami_spec.rb
146
+ - spec/asg_spec.rb
147
+ - spec/spec_helper.rb
148
+ - spec/support/stubs/CreateImage.200.xml
149
+ - spec/support/stubs/CreateLaunchConfiguration.200.xml
150
+ - spec/support/stubs/CreateTags.200.xml
151
+ - spec/support/stubs/DeleteLaunchConfiguration.200.xml
152
+ - spec/support/stubs/DeleteSnapshot.200.xml
153
+ - spec/support/stubs/DeregisterImage.200.xml
154
+ - spec/support/stubs/DescribeAutoScalingGroups.200.xml
155
+ - spec/support/stubs/DescribeImages.200.xml
156
+ - spec/support/stubs/DescribeInstances.200.xml
157
+ - spec/support/stubs/DescribeLaunchConfigurations.200.xml
158
+ - spec/support/stubs/DescribeSnapshots.200.xml
159
+ - spec/support/stubs/DescribeTags.200.xml
160
+ - spec/support/stubs/UpdateAutoScalingGroup.200.xml
161
+ - spec/support/stubs/security-credentials.200.json
162
+ homepage: http://github.com/sixfeetover/capistrano-asg
163
+ licenses:
164
+ - MIT
165
+ metadata: {}
166
+ post_install_message:
167
+ rdoc_options: []
168
+ require_paths:
169
+ - lib
170
+ required_ruby_version: !ruby/object:Gem::Requirement
171
+ requirements:
172
+ - - ">="
173
+ - !ruby/object:Gem::Version
174
+ version: '0'
175
+ required_rubygems_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: '0'
180
+ requirements: []
181
+ rubyforge_project:
182
+ rubygems_version: 2.6.11
183
+ signing_key:
184
+ specification_version: 4
185
+ summary: Capistrano plugin for deploying to AWS AutoScale Groups.
186
+ test_files:
187
+ - spec/ami_spec.rb
188
+ - spec/asg_spec.rb
189
+ - spec/spec_helper.rb
190
+ - spec/support/stubs/CreateImage.200.xml
191
+ - spec/support/stubs/CreateLaunchConfiguration.200.xml
192
+ - spec/support/stubs/CreateTags.200.xml
193
+ - spec/support/stubs/DeleteLaunchConfiguration.200.xml
194
+ - spec/support/stubs/DeleteSnapshot.200.xml
195
+ - spec/support/stubs/DeregisterImage.200.xml
196
+ - spec/support/stubs/DescribeAutoScalingGroups.200.xml
197
+ - spec/support/stubs/DescribeImages.200.xml
198
+ - spec/support/stubs/DescribeInstances.200.xml
199
+ - spec/support/stubs/DescribeLaunchConfigurations.200.xml
200
+ - spec/support/stubs/DescribeSnapshots.200.xml
201
+ - spec/support/stubs/DescribeTags.200.xml
202
+ - spec/support/stubs/UpdateAutoScalingGroup.200.xml
203
+ - spec/support/stubs/security-credentials.200.json