ami_spec 1.1.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4504c60fd0ce24f40be03e192159fcc9c8509cddbc2642cb0c8c50e351a7c7fa
4
- data.tar.gz: 8fc38e659fb6436b8ad37467564445de49c92940991d3f8b820d1b2f6927355a
3
+ metadata.gz: 718f947b58e6bedd2093507f23b7bcc1c8deae4503dde3603c6768700729948a
4
+ data.tar.gz: b8c05a3702f5951932d372f6c3788a2ee71f9d0ead934a4bdfb52cae382bbe70
5
5
  SHA512:
6
- metadata.gz: 1a86bbfccdfbbe323eea7cea45bc9450d41626d3a40ed456a41b4228ef4eb1b211e23268a024dbecd81ebb768a06f00ac19e99f31387ce14e6b32635c99886cf
7
- data.tar.gz: 65effb5f2d0a7053c645c79b9ffa0c42ca93c4ee4183cdfbc7ab909263affb431d54ba0ea7f0dcb339bc5f3b81466ed765393d644886910b499e6a8df501c673
6
+ metadata.gz: a2ceb57cf5b2ea84f085a835e47e1533065338479c23bf3da88ff962d5c046c6109f2c0b93461ac4c1d5093a14bc7d522e4c154d1f34225ef3813ebd70f6ecda
7
+ data.tar.gz: ca6403909f96efb50c412ed722e6449b51ea147677f10d2e7729e31d02adc8ae82561eeaf2bbe054ab774bdf9086fe7b690254512f590c49d977920f99e2f371
data/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # AmiSpec
2
2
 
3
+ [![License MIT](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://github.com/envato/ami-spec/blob/master/LICENSE.txt)
4
+ [![Gem Version](https://badge.fury.io/rb/ami_spec.svg)](https://badge.fury.io/rb/ami_spec)
5
+ [![Build Status](https://github.com/envato/ami-spec/workflows/tests/badge.svg?branch=master)](https://github.com/envato/ami-spec/actions?query=branch%3Amaster+workflow%3Atests)
6
+
3
7
  Acceptance testing your AMIs.
4
8
 
5
9
  AmiSpec is a RubyGem used to launch an Amazon Machine Image (AMI) and run ServerSpecs against it. It wraps around the AWS API and ServerSpec to spin up, test and tear down instances.
@@ -29,33 +33,39 @@ Run `bundle install`
29
33
  ```cli
30
34
  $ bundle exec ami_spec --help
31
35
  Options:
32
- -r, --role=<s> The role to test, this should map to a directory in the spec
33
- folder
34
- -a, --ami=<s> The ami ID to run tests against
35
- -o, --role-ami-file=<s> A file containing comma separated roles and amis. i.e.
36
- web_server,ami-id.
37
- -s, --specs=<s> The directory to find ServerSpecs
38
- -u, --subnet-id=<s> The subnet to start the instance in
39
- -k, --key-name=<s> The SSH key name to assign to instances
40
- -e, --key-file=<s> The SSH private key file associated to the key_name
41
- -h, --ssh-user=<s> The user to ssh to the instance as
42
- -w, --aws-region=<s> The AWS region, defaults to AWS_DEFAULT_REGION environment
43
- variable
44
- -i, --aws-instance-type=<s> The ec2 instance type, defaults to t2.micro (default:
45
- t2.micro)
46
- -c, --aws-security-groups=<s+> Security groups to associate to the launched instances. May be
47
- specified multiple times
48
- -p, --aws-public-ip Launch instances with a public IP
49
- -t, --ssh-retries=<i> The number of times we should try sshing to the ec2 instance
50
- before giving up. Defaults to 30 (default: 30)
51
- -g, --tags=<s> Additional tags to add to launched instances in the form of
52
- comma separated key=value pairs. i.e. Name=AmiSpec (default: )
53
- -d, --debug Don't terminate instances on exit
54
- -f, --wait-for-rc Wait for oldschool SystemV scripts to run before conducting
55
- tests. Currently only supports Ubuntu with upstart
56
- -l, --user-data-file=<s> File path for aws ec2 user data
57
- -m, --iam-instance-profile-arn=<s> IAM instance profile to use
58
- --help Show this message
36
+ -r, --role=<s> The role to test, this should map to a directory in the spec
37
+ folder
38
+ -a, --ami=<s> The ami ID to run tests against
39
+ -o, --role-ami-file=<s> A file containing comma separated roles and amis. i.e.
40
+ web_server,ami-id.
41
+ -s, --specs=<s> The directory to find ServerSpecs
42
+ -u, --subnet-id=<s> The subnet to start the instance in. If not provided a subnet
43
+ will be chosen from the default VPC
44
+ -k, --key-name=<s> The SSH key name to assign to instances. If not provided a
45
+ temporary key pair will be generated in AWS
46
+ -e, --key-file=<s> The SSH private key file associated to the key_name
47
+ -h, --ssh-user=<s> The user to ssh to the instance as
48
+ -w, --aws-region=<s> The AWS region, defaults to AWS_DEFAULT_REGION environment
49
+ variable
50
+ -i, --aws-instance-type=<s> The ec2 instance type, defaults to t2.micro (default:
51
+ t2.micro)
52
+ -c, --aws-security-groups=<s> Security groups IDs to associate to the launched instances. May be
53
+ specified multiple times. If not provided a temporary security
54
+ group will be generated in AWS
55
+ -n, --allow-any-temporary-security-group The temporary security group will allow SSH connections
56
+ from any IP address (0.0.0.0/0), otherwise allow the subnet's block
57
+ -p, --aws-public-ip Launch instances with a public IP
58
+ -t, --ssh-retries=<i> The number of times we should try sshing to the ec2 instance
59
+ before giving up. Defaults to 30 (default: 30)
60
+ -g, --tags=<s> Additional tags to add to launched instances in the form of
61
+ comma separated key=value pairs. i.e. Name=AmiSpec (default: )
62
+ -d, --debug Don't terminate instances on exit
63
+ -b, --buildkite Output section separators for buildkite
64
+ -f, --wait-for-rc Wait for oldschool SystemV scripts to run before conducting
65
+ tests. Currently only supports Ubuntu with upstart
66
+ -l, --user-data-file=<s> File path for aws ec2 user data
67
+ -m, --iam-instance-profile-arn=<s> IAM instance profile to use
68
+ --help Show this message
59
69
 
60
70
  ```
61
71
 
@@ -65,6 +75,41 @@ When the instances becomes reachable it will run all Specs inside the role spec
65
75
 
66
76
  Alternative to the `--ami` and `--role` variables, a file of comma separated roles and AMIs (`ROLE,AMI\n`) can be supplied to `--role-ami-file`.
67
77
 
78
+ ## ServerSpec test layout
79
+
80
+ AmiSpec expects the usual ServerSpec configuration layout as generated by "serverspec-init":
81
+
82
+ spec/
83
+ ├── webserver
84
+ │   └── webserver_spec.rb
85
+ └── spec_helper.rb
86
+
87
+ The \*\_spec.rb files under the role (e.g. webserver) contain the ServerSpec
88
+ tests that you want to run. The spec_helper.rb file can be very simple:
89
+
90
+ require 'serverspec'
91
+
92
+ set :backend, :ssh
93
+
94
+ Note that the backend *needs* to be :ssh or ami_spec might run the tests on
95
+ your local machine, not in EC2.
96
+
97
+ ## Example usage
98
+
99
+ To test a custom AMI using a pre-created security group that allows SSH from anywhere:
100
+
101
+ ```cli
102
+ ami_spec --role webserver\
103
+ --specs spec\
104
+ --aws-region us-east-1\
105
+ --ami ami-0123456789abcdef0\
106
+ --key-name default\
107
+ --key-file ~/.ssh/default.pem\
108
+ --ssh-user ubuntu\
109
+ --aws-public-ip\
110
+ --aws-security-groups sg-0123456789abcdef0
111
+ ```
112
+
68
113
  ## Known caveats
69
114
 
70
115
  ### RSpec conditions in examples
data/bin/ami_spec CHANGED
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require 'trollop'
4
3
  require 'ami_spec'
5
4
 
6
5
  AmiSpec.invoke
data/lib/ami_spec.rb CHANGED
@@ -1,10 +1,15 @@
1
1
  require 'ami_spec/aws_instance'
2
2
  require 'ami_spec/aws_instance_options'
3
+ require 'ami_spec/aws_default_vpc'
4
+ require 'ami_spec/aws_key_pair'
5
+ require 'ami_spec/aws_security_group'
3
6
  require 'ami_spec/server_spec'
4
7
  require 'ami_spec/server_spec_options'
5
8
  require 'ami_spec/wait_for_ssh'
6
9
  require 'ami_spec/wait_for_rc'
7
- require 'trollop'
10
+ require 'ami_spec/wait_for_cloud_init'
11
+ require 'optimist'
12
+ require 'logger'
8
13
 
9
14
  module AmiSpec
10
15
  class InstanceConnectionTimeout < StandardError; end
@@ -19,7 +24,7 @@ module AmiSpec
19
24
  # subnet_id::
20
25
  # The subnet_id to start instances in.
21
26
  # key_name::
22
- # The SSH key name to assign to instances. This key name must exist on the executing host for passwordless login.
27
+ # The SSH key name to assign to instances. If not provided a temporary key pair will be generated in AWS
23
28
  # key_file::
24
29
  # The SSH key file to use to connect to the host.
25
30
  # aws_region::
@@ -27,7 +32,9 @@ module AmiSpec
27
32
  # Defaults to AWS_DEFAULT_REGION
28
33
  # aws_security_group_ids::
29
34
  # AWS Security groups to assign to the instances
30
- # Defaults to the default security group for the VPC
35
+ # If not provided a temporary security group will be generated in AWS
36
+ # allow_any_temporary_security_group::
37
+ # The temporary security group will allow SSH connections from any IP address (0.0.0.0/0)
31
38
  # aws_instance_type::
32
39
  # AWS ec2 instance type
33
40
  # aws_public_ip::
@@ -45,6 +52,33 @@ module AmiSpec
45
52
  # == Returns:
46
53
  # Boolean - The result of all the server specs.
47
54
  def self.run(options)
55
+ logger = Logger.new(STDOUT, formatter: proc { |_sev, _time, _name, message| "#{message}\n" })
56
+
57
+ ec2 = Aws::EC2::Resource.new(options[:aws_region] ? {region: options[:aws_region]} : {})
58
+
59
+ if options[:subnet_id].nil?
60
+ default_vpc_subnet = AwsDefaultVpc.find_subnet(ec2: ec2)
61
+ raise 'No default VPC subnet found. Please specify a subnet id.' if default_vpc_subnet.nil?
62
+ options[:subnet_id] = default_vpc_subnet.id
63
+ logger.info("Using subnet #{options[:subnet_id]} from the default VPC")
64
+ end
65
+
66
+ unless options[:key_name]
67
+ key_pair = AwsKeyPair.create(ec2: ec2, logger: logger)
68
+ options[:key_name] = key_pair.key_name
69
+ options[:key_file] = key_pair.key_file
70
+ end
71
+
72
+ if options[:aws_security_groups].nil? || options[:aws_security_groups].empty?
73
+ temporary_security_group = AwsSecurityGroup.create(
74
+ ec2: ec2,
75
+ subnet_id: options[:subnet_id],
76
+ allow_any_ip: options[:allow_any_temporary_security_group],
77
+ logger: logger
78
+ )
79
+ options[:aws_security_groups] = [temporary_security_group.group_id]
80
+ end
81
+
48
82
  instances = []
49
83
  options[:amis].each_pair do |role, ami|
50
84
  aws_instance_options = AwsInstanceOptions.new(options.merge(role: role, ami: ami))
@@ -56,6 +90,7 @@ module AmiSpec
56
90
  ip_address = options[:aws_public_ip] ? instance.public_ip_address : instance.private_ip_address
57
91
  WaitForSSH.wait(ip_address, options[:ssh_user], options[:key_file], options[:ssh_retries])
58
92
  WaitForRC.wait(ip_address, options[:ssh_user], options[:key_file]) if options[:wait_for_rc]
93
+ WaitForCloudInit.wait(ip_address, options[:ssh_user], options[:key_file]) if options[:wait_for_cloud_init]
59
94
 
60
95
  server_spec_options = ServerSpecOptions.new(options.merge(instance: instance))
61
96
  results << ServerSpec.new(server_spec_options).run
@@ -64,10 +99,12 @@ module AmiSpec
64
99
  results.all?
65
100
  ensure
66
101
  stop_instances(instances, options[:debug])
102
+ key_pair.delete if key_pair
103
+ temporary_security_group.delete if temporary_security_group
67
104
  end
68
105
 
69
106
  def self.stop_instances(instances, debug)
70
- instances.each do |instance|
107
+ instances && instances.each do |instance|
71
108
  begin
72
109
  if debug
73
110
  puts "EC2 instance ##{instance.instance_id} has not been stopped due to debug mode."
@@ -83,29 +120,45 @@ module AmiSpec
83
120
  private_class_method :stop_instances
84
121
 
85
122
  def self.invoke
86
- options = Trollop::options do
87
- opt :role, "The role to test, this should map to a directory in the spec folder", type: :string
88
- opt :ami, "The ami ID to run tests against", type: :string
89
- opt :role_ami_file, "A file containing comma separated roles and amis. i.e.\nweb_server,ami-id.",
90
- type: :string
91
- opt :specs, "The directory to find ServerSpecs", type: :string, required: true
92
- opt :subnet_id, "The subnet to start the instance in", type: :string, required: true
93
- opt :key_name, "The SSH key name to assign to instances", type: :string, required: true
94
- opt :key_file, "The SSH private key file associated to the key_name", type: :string, required: true
95
- opt :ssh_user, "The user to ssh to the instance as", type: :string, required: true
96
- opt :aws_region, "The AWS region, defaults to AWS_DEFAULT_REGION environment variable", type: :string
97
- opt :aws_instance_type, "The ec2 instance type, defaults to t2.micro", type: :string, default: 't2.micro'
98
- opt :aws_security_groups, "Security groups to associate to the launched instances. May be specified multiple times",
99
- type: :strings, default: nil
100
- opt :aws_public_ip, "Launch instances with a public IP"
101
- opt :ssh_retries, "The number of times we should try sshing to the ec2 instance before giving up. Defaults to 30",
102
- type: :int, default: 30
103
- opt :tags, "Additional tags to add to launched instances in the form of comma separated key=value pairs. i.e. Name=AmiSpec", type: :string, default: ""
104
- opt :debug, "Don't terminate instances on exit"
105
- opt :buildkite, "Output section separators for buildkite"
106
- opt :wait_for_rc, "Wait for oldschool SystemV scripts to run before conducting tests. Currently only supports Ubuntu with upstart"
107
- opt :user_data_file, "File path for aws ec2 user data", type: :string, default: nil
108
- opt :iam_instance_profile_arn, "IAM instance profile to use", type: :string
123
+ options = Optimist::options do
124
+ opt :role,
125
+ 'The role to test, this should map to a directory in the spec folder',
126
+ type: :string, short: :r
127
+ opt :ami, 'The ami ID to run tests against', type: :string, short: :a
128
+ opt :role_ami_file,
129
+ 'A file containing comma separated roles and amis. i.e.
130
+ web_server,ami-id.',
131
+ type: :string, short: :o
132
+ opt :specs, 'The directory to find ServerSpecs',
133
+ type: :string, required: true, short: :s
134
+ opt :subnet_id,
135
+ 'The subnet to start the instance in. If not provided a subnet will be chosen from the default VPC',
136
+ type: :string, short: :u
137
+ opt :key_name, 'The SSH key name to assign to instances. If not provided a temporary key pair will be generated in AWS',
138
+ type: :string, short: :k
139
+ opt :key_file, 'The SSH private key file associated to the key_name', type: :string, short: :e
140
+ opt :ssh_user, 'The user to ssh to the instance as', type: :string, required: true, short: :h
141
+ opt :aws_region, 'The AWS region, defaults to AWS_DEFAULT_REGION environment variable',
142
+ type: :string, short: :w
143
+ opt :aws_instance_type, 'The ec2 instance type, defaults to t2.micro',
144
+ type: :string, default: 't2.micro', short: :i
145
+ opt :aws_security_groups,
146
+ 'Security groups to associate to the launched instances. May be specified multiple times. If not provided a temporary security group will be generated in AWS',
147
+ type: :string, default: nil, multi: true, short: :c
148
+ opt :allow_any_temporary_security_group, 'The temporary security group will allow SSH connections from any IP address (0.0.0.0/0)',
149
+ short: :n
150
+ opt :aws_public_ip, 'Launch instances with a public IP', short: :p
151
+ opt :ssh_retries, 'The number of times we should try sshing to the ec2 instance before giving up. Defaults to 30',
152
+ type: :int, default: 30, short: :t
153
+ opt :tags, 'Additional tags to add to launched instances in the form of comma separated key=value pairs. i.e. Name=AmiSpec',
154
+ type: :string, default: '', short: :g
155
+ opt :debug, "Don't terminate instances on exit", short: :d
156
+ opt :buildkite, 'Output section separators for buildkite', short: :b
157
+ opt :wait_for_rc, 'Wait for oldschool SystemV scripts to run before conducting tests. Currently only supports Ubuntu with upstart',
158
+ short: :f
159
+ opt :wait_for_cloud_init, 'Wait for Cloud Init to complete before running tests'
160
+ opt :user_data_file, 'File path for aws ec2 user data', type: :string, default: nil, short: :l
161
+ opt :iam_instance_profile_arn, 'IAM instance profile to use', type: :string, short: :m
109
162
  end
110
163
 
111
164
  if options[:role] && options[:ami]
@@ -121,9 +174,7 @@ module AmiSpec
121
174
  fail "You must specify either role and ami or role_ami_file"
122
175
  end
123
176
 
124
- unless File.exist? options[:key_file]
125
- fail "Key file #{options[:key_file]} not found"
126
- end
177
+ fail "Key file #{options[:key_file]} not found" if options[:key_name] && !File.exist?(options.fetch(:key_file))
127
178
 
128
179
  if options[:user_data_file] and !File.exist? options[:user_data_file]
129
180
  fail "User Data file #{options[:user_data_file]} not found"
@@ -131,6 +182,12 @@ module AmiSpec
131
182
 
132
183
  options[:tags] = parse_tags(options[:tags])
133
184
 
185
+ options[:amis].each_pair do |role, _|
186
+ unless Dir.exist?("#{options[:specs]}/#{role}")
187
+ fail "Role directory #{options[:specs]}/#{role} does not exist. If you'd like to skip the role '#{role}', create the directory but leave it empty (except for a .gitignore file)."
188
+ end
189
+ end
190
+
134
191
  exit run(options)
135
192
  end
136
193
 
@@ -0,0 +1,10 @@
1
+ require 'aws-sdk-ec2'
2
+
3
+ module AmiSpec
4
+ class AwsDefaultVpc
5
+ def self.find_subnet(ec2: Aws::EC2::Resource.new)
6
+ default_vpc = ec2.vpcs(filters: [{name: 'isDefault', values: ['true']}]).first
7
+ default_vpc && default_vpc.subnets.first
8
+ end
9
+ end
10
+ end
@@ -1,4 +1,4 @@
1
- require 'aws-sdk'
1
+ require 'aws-sdk-ec2'
2
2
  require 'forwardable'
3
3
  require 'base64'
4
4
 
@@ -26,7 +26,7 @@ module AmiSpec
26
26
  @iam_instance_profile_arn = options.fetch(:iam_instance_profile_arn, nil)
27
27
  end
28
28
 
29
- def_delegators :@instance, :instance_id, :tags, :terminate, :private_ip_address, :public_ip_address
29
+ def_delegators :@instance, :instance_id, :tags, :private_ip_address, :public_ip_address
30
30
 
31
31
  def start
32
32
  client = Aws::EC2::Client.new(client_options)
@@ -37,6 +37,11 @@ module AmiSpec
37
37
  tag_instance
38
38
  end
39
39
 
40
+ def terminate
41
+ @instance.terminate
42
+ @instance.wait_until_terminated
43
+ end
44
+
40
45
  private
41
46
 
42
47
  def client_options
@@ -0,0 +1,36 @@
1
+ require 'aws-sdk-ec2'
2
+ require 'logger'
3
+ require 'securerandom'
4
+ require 'tempfile'
5
+ require 'pathname'
6
+
7
+ module AmiSpec
8
+ class AwsKeyPair
9
+
10
+ def self.create(**args)
11
+ new(**args).tap(&:create)
12
+ end
13
+
14
+ def initialize(ec2: Aws::EC2::Resource.new, key_name_prefix: 'ami-spec-', logger: Logger.new(STDOUT))
15
+ @ec2 = ec2
16
+ @key_name = "#{key_name_prefix}#{SecureRandom.uuid}"
17
+ @logger = logger
18
+ end
19
+
20
+ attr_reader :key_name, :key_file
21
+
22
+ def create
23
+ @logger.info "Creating temporary AWS key pair: #{@key_name}"
24
+ @key_pair = @ec2.create_key_pair(key_name: @key_name)
25
+ @temp_file = Tempfile.new('key')
26
+ @temp_file.write(@key_pair.key_material)
27
+ @temp_file.close
28
+ @key_file = Pathname.new(@temp_file.path)
29
+ end
30
+
31
+ def delete
32
+ @logger.info "Deleting temporary AWS key pair: #{@key_name}"
33
+ @key_pair.delete
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,72 @@
1
+ require 'aws-sdk-ec2'
2
+ require 'forwardable'
3
+ require 'securerandom'
4
+
5
+ module AmiSpec
6
+ class AwsSecurityGroup
7
+ extend Forwardable
8
+
9
+ def self.create(**args)
10
+ new(**args).tap(&:create)
11
+ end
12
+
13
+ def initialize(ec2: Aws::EC2::Resource.new,
14
+ group_name_prefix: "ami-spec-",
15
+ connection_port: 22,
16
+ subnet_id:,
17
+ allow_any_ip: false,
18
+ logger: Logger.new(STDOUT))
19
+ @ec2 = ec2
20
+ @group_name = "#{group_name_prefix}#{SecureRandom.uuid}"
21
+ @connection_port = connection_port
22
+ @subnet_id = subnet_id
23
+ @allow_any_ip = allow_any_ip
24
+ @logger = logger
25
+ end
26
+
27
+ def_delegators :@security_group, :group_id
28
+ attr_reader :group_name
29
+
30
+ def create
31
+ @logger.info "Creating temporary AWS security group: #{@group_name}"
32
+ create_security_group
33
+ allow_ingress_via_connection_port
34
+ end
35
+
36
+ def delete
37
+ @logger.info "Deleting temporary AWS security group: #{@group_name}"
38
+ @security_group.delete
39
+ end
40
+
41
+ private
42
+
43
+ def create_security_group
44
+ @security_group = @ec2.create_security_group(
45
+ group_name: @group_name,
46
+ description: "A temporary security group for running AmiSpec",
47
+ vpc_id: subnet.vpc_id,
48
+ )
49
+ end
50
+
51
+ def allow_ingress_via_connection_port
52
+ @security_group.authorize_ingress(
53
+ ip_permissions: [
54
+ {
55
+ ip_protocol: "tcp",
56
+ from_port: @connection_port,
57
+ to_port: @connection_port,
58
+ ip_ranges: [{cidr_ip: cidr_block}],
59
+ },
60
+ ],
61
+ )
62
+ end
63
+
64
+ def cidr_block
65
+ @allow_any_ip ? "0.0.0.0/0" : subnet.cidr_block
66
+ end
67
+
68
+ def subnet
69
+ @subnet ||= @ec2.subnet(@subnet_id)
70
+ end
71
+ end
72
+ end
@@ -28,11 +28,15 @@ module AmiSpec
28
28
  end
29
29
 
30
30
  $LOAD_PATH.unshift(@spec) unless $LOAD_PATH.include?(@spec)
31
- require File.join(@spec, 'spec_helper')
31
+ begin
32
+ require File.join(@spec, 'spec_helper')
33
+ rescue LoadError
34
+ puts 'Spec Helper does not exist. Skipping!'
35
+ end
32
36
 
33
37
  set :backend, :ssh
34
38
  set :host, @ip
35
- set :ssh_options, :user => @user, :keys => [@key_file], :paranoid => false
39
+ set :ssh_options, :user => @user, :keys => [@key_file], :verify_host_key => :never
36
40
 
37
41
  RSpec.configuration.fail_fast = true if @debug
38
42
 
@@ -1,3 +1,3 @@
1
1
  module AmiSpec
2
- VERSION = '1.1.0'
2
+ VERSION = '1.7.0'
3
3
  end
@@ -0,0 +1,11 @@
1
+ require 'net/ssh'
2
+
3
+ module AmiSpec
4
+ class WaitForCloudInit
5
+ def self.wait(ip_address, user, key, port=22)
6
+ Net::SSH.start(ip_address, user, keys: [key], :verify_host_key => :never, port: port) do |ssh|
7
+ ssh.exec! '/usr/bin/cloud-init status --wait'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -3,7 +3,7 @@ require 'net/ssh'
3
3
  module AmiSpec
4
4
  class WaitForRC
5
5
  def self.wait(ip_address, user, key, port=22)
6
- Net::SSH.start(ip_address, user, keys: [key], paranoid: false, port: port) do |ssh|
6
+ Net::SSH.start(ip_address, user, keys: [key], :verify_host_key => :never, port: port) do |ssh|
7
7
  distrib_stdout = ""
8
8
  # Determine the OS family
9
9
  ssh.exec!("source /etc/*release && echo -n $DISTRIB_ID && echo -n $ID") do |channel, stream, data|
@@ -8,8 +8,8 @@ module AmiSpec
8
8
 
9
9
  while retries < max_retries
10
10
  begin
11
- Net::SSH.start(ip_address, user, keys: [key], paranoid: false) { |ssh| ssh.exec 'echo boo!' }
12
- rescue Errno::ETIMEDOUT, Errno::ECONNREFUSED, Timeout::Error => error
11
+ Net::SSH.start(ip_address, user, keys: [key], :verify_host_key => :never) { |ssh| ssh.exec 'echo boo!' }
12
+ rescue Errno::ETIMEDOUT, Errno::ECONNREFUSED, Timeout::Error, Net::SSH::Exception => error
13
13
  last_error = error
14
14
  sleep 1
15
15
  else
metadata CHANGED
@@ -1,30 +1,30 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ami_spec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Patrick Robinson
8
8
  - Martin Jagusch
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-08-03 00:00:00.000000000 Z
12
+ date: 2021-07-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: aws-sdk
15
+ name: aws-sdk-ec2
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
18
  - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: '2'
20
+ version: '1'
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
- version: '2'
27
+ version: '1'
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: rake
30
30
  requirement: !ruby/object:Gem::Requirement
@@ -32,7 +32,7 @@ dependencies:
32
32
  - - ">="
33
33
  - !ruby/object:Gem::Version
34
34
  version: '0'
35
- type: :runtime
35
+ type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
@@ -43,16 +43,16 @@ dependencies:
43
43
  name: serverspec
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - ">="
46
+ - - "~>"
47
47
  - !ruby/object:Gem::Version
48
- version: '0'
48
+ version: '2'
49
49
  type: :runtime
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - ">="
53
+ - - "~>"
54
54
  - !ruby/object:Gem::Version
55
- version: '0'
55
+ version: '2'
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: specinfra
58
58
  requirement: !ruby/object:Gem::Requirement
@@ -68,19 +68,19 @@ dependencies:
68
68
  - !ruby/object:Gem::Version
69
69
  version: '2.45'
70
70
  - !ruby/object:Gem::Dependency
71
- name: trollop
71
+ name: optimist
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - ">="
74
+ - - "~>"
75
75
  - !ruby/object:Gem::Version
76
- version: '0'
76
+ version: '3'
77
77
  type: :runtime
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
- - - ">="
81
+ - - "~>"
82
82
  - !ruby/object:Gem::Version
83
- version: '0'
83
+ version: '3'
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: hashie
86
86
  requirement: !ruby/object:Gem::Requirement
@@ -99,16 +99,16 @@ dependencies:
99
99
  name: net-ssh
100
100
  requirement: !ruby/object:Gem::Requirement
101
101
  requirements:
102
- - - "<"
102
+ - - "~>"
103
103
  - !ruby/object:Gem::Version
104
- version: '3.0'
104
+ version: '5'
105
105
  type: :runtime
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
- - - "<"
109
+ - - "~>"
110
110
  - !ruby/object:Gem::Version
111
- version: '3.0'
111
+ version: '5'
112
112
  description: Acceptance testing your AMIs
113
113
  email: []
114
114
  executables:
@@ -116,41 +116,25 @@ executables:
116
116
  extensions: []
117
117
  extra_rdoc_files: []
118
118
  files:
119
- - ".gitignore"
120
- - ".ruby-version"
121
- - ".travis.yml"
122
- - Gemfile
123
119
  - LICENSE.txt
124
120
  - README.md
125
- - Rakefile
126
- - ami_spec.gemspec
127
121
  - bin/ami_spec
128
122
  - lib/ami_spec.rb
123
+ - lib/ami_spec/aws_default_vpc.rb
129
124
  - lib/ami_spec/aws_instance.rb
130
125
  - lib/ami_spec/aws_instance_options.rb
126
+ - lib/ami_spec/aws_key_pair.rb
127
+ - lib/ami_spec/aws_security_group.rb
131
128
  - lib/ami_spec/server_spec.rb
132
129
  - lib/ami_spec/server_spec_options.rb
133
130
  - lib/ami_spec/version.rb
131
+ - lib/ami_spec/wait_for_cloud_init.rb
134
132
  - lib/ami_spec/wait_for_rc.rb
135
133
  - lib/ami_spec/wait_for_ssh.rb
136
- - spec/ami_spec_spec.rb
137
- - spec/aws_instance_spec.rb
138
- - spec/containers/Dockerfile.amazon_linux
139
- - spec/containers/Dockerfile.trusty
140
- - spec/containers/Dockerfile.xenial
141
- - spec/containers/README.md
142
- - spec/containers/ami-spec
143
- - spec/containers/ami-spec.pub
144
- - spec/containers/docker-compose.yml
145
- - spec/containers/rc.conf
146
- - spec/containers/sshd_config
147
- - spec/spec_helper.rb
148
- - spec/wait_for_rc_spec.rb
149
- - spec/wait_for_ssh_spec.rb
150
134
  homepage: https://github.com/envato/ami-spec
151
135
  licenses: []
152
136
  metadata: {}
153
- post_install_message:
137
+ post_install_message:
154
138
  rdoc_options: []
155
139
  require_paths:
156
140
  - lib
@@ -158,30 +142,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
158
142
  requirements:
159
143
  - - ">="
160
144
  - !ruby/object:Gem::Version
161
- version: '0'
145
+ version: 2.2.6
162
146
  required_rubygems_version: !ruby/object:Gem::Requirement
163
147
  requirements:
164
148
  - - ">="
165
149
  - !ruby/object:Gem::Version
166
150
  version: '0'
167
151
  requirements: []
168
- rubyforge_project:
169
- rubygems_version: 2.7.6
170
- signing_key:
152
+ rubygems_version: 3.0.4
153
+ signing_key:
171
154
  specification_version: 4
172
155
  summary: Acceptance testing your AMIs
173
- test_files:
174
- - spec/ami_spec_spec.rb
175
- - spec/aws_instance_spec.rb
176
- - spec/containers/Dockerfile.amazon_linux
177
- - spec/containers/Dockerfile.trusty
178
- - spec/containers/Dockerfile.xenial
179
- - spec/containers/README.md
180
- - spec/containers/ami-spec
181
- - spec/containers/ami-spec.pub
182
- - spec/containers/docker-compose.yml
183
- - spec/containers/rc.conf
184
- - spec/containers/sshd_config
185
- - spec/spec_helper.rb
186
- - spec/wait_for_rc_spec.rb
187
- - spec/wait_for_ssh_spec.rb
156
+ test_files: []
data/.gitignore DELETED
@@ -1,2 +0,0 @@
1
- Gemfile.lock
2
- *.gem
data/.ruby-version DELETED
@@ -1 +0,0 @@
1
- 1.9.3-p551
data/.travis.yml DELETED
@@ -1,6 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 1.9.3
4
- - 2.1.8
5
- - 2.2.4
6
- script: bundle exec rake spec
data/Gemfile DELETED
@@ -1,3 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec
data/Rakefile DELETED
@@ -1,8 +0,0 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
3
-
4
- RSpec::Core::RakeTask.new(:spec) do |t|
5
- t.rspec_opts = "--tag ~integration"
6
- end
7
-
8
- task :default => :spec
data/ami_spec.gemspec DELETED
@@ -1,27 +0,0 @@
1
- lib = File.expand_path('../lib', __FILE__)
2
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
-
4
- require 'ami_spec/version'
5
-
6
- Gem::Specification.new do |gem|
7
- gem.name = 'ami_spec'
8
- gem.version = AmiSpec::VERSION
9
- gem.authors = ['Patrick Robinson', 'Martin Jagusch']
10
- gem.email = []
11
- gem.description = 'Acceptance testing your AMIs'
12
- gem.summary = gem.description
13
- gem.homepage = 'https://github.com/envato/ami-spec'
14
-
15
- gem.files = `git ls-files`.split($/)
16
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
- gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
- gem.require_paths = ['lib']
19
-
20
- gem.add_dependency 'aws-sdk', '~> 2'
21
- gem.add_dependency 'rake'
22
- gem.add_dependency 'serverspec'
23
- gem.add_dependency 'specinfra', '>= 2.45'
24
- gem.add_dependency 'trollop'
25
- gem.add_dependency 'hashie'
26
- gem.add_dependency 'net-ssh', '< 3.0'
27
- end
@@ -1,74 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe AmiSpec do
4
- let(:amis) { {'web_server' => 'ami-1234abcd', 'db_server' => 'ami-1234abcd'} }
5
- let(:ec2_double) { instance_double(AmiSpec::AwsInstance) }
6
- let(:state) { double(name: 'running') }
7
- let(:test_result) { true }
8
- let(:server_spec_double) { double(run: test_result) }
9
- subject do
10
- described_class.run(
11
- amis: amis,
12
- specs: '/tmp/foobar',
13
- subnet_id: 'subnet-1234abcd',
14
- key_name: 'key',
15
- key_file: 'key.pem',
16
- aws_public_ip: false,
17
- aws_instance_type: 't2.micro',
18
- ssh_user: 'ubuntu',
19
- debug: false,
20
- ssh_retries: 30,
21
- )
22
- end
23
-
24
- describe '#invoke' do
25
- it 'raises a system exit with no arguments' do
26
- expect{ described_class.invoke }.to raise_error(SystemExit)
27
- end
28
- end
29
-
30
- describe '#run' do
31
- before do
32
- allow(AmiSpec::WaitForSSH).to receive(:wait).and_return(true)
33
- allow(AmiSpec::AwsInstance).to receive(:start).and_return(ec2_double)
34
- allow(AmiSpec::ServerSpec).to receive(:new).and_return(server_spec_double)
35
- allow(ec2_double).to receive(:terminate).and_return(true)
36
- allow(ec2_double).to receive(:private_ip_address).and_return('127.0.0.1')
37
- allow_any_instance_of(Object).to receive(:sleep)
38
- end
39
-
40
- context 'successful tests' do
41
- it 'calls aws instance for each ami' do
42
- expect(AmiSpec::AwsInstance).to receive(:start).with(hash_including(role: 'web_server'))
43
- expect(AmiSpec::AwsInstance).to receive(:start).with(hash_including(role: 'db_server'))
44
- subject
45
- end
46
-
47
- it 'returns true' do
48
- expect(subject).to be_truthy
49
- end
50
- end
51
-
52
- context 'failed tests' do
53
- let(:test_result) { false }
54
-
55
- it 'returns false' do
56
- expect(subject).to be_falsey
57
- end
58
- end
59
- end
60
-
61
- describe '#parse_tags' do
62
- it 'parses a single key/value pair' do
63
- expect(described_class.parse_tags("Name=AmiSpec")).to eq( { "Name"=>"AmiSpec" } )
64
- end
65
-
66
- it 'parses multiple key/value pairs' do
67
- expect(described_class.parse_tags("Name=AmiSpec,Owner=Me")).to eq( { "Name"=>"AmiSpec", "Owner"=>"Me" } )
68
- end
69
-
70
- it 'parses an empty string' do
71
- expect(described_class.parse_tags("")).to eq({})
72
- end
73
- end
74
- end
@@ -1,142 +0,0 @@
1
- require 'spec_helper'
2
- require 'base64'
3
- require 'tempfile'
4
-
5
- describe AmiSpec::AwsInstance do
6
- let(:role) { 'web_server' }
7
- let(:sec_group_id) { nil }
8
- let(:region) { nil }
9
- let(:client_double) { instance_double(Aws::EC2::Client) }
10
- let(:new_ec2_double) { instance_double(Aws::EC2::Types::Instance) }
11
- let(:ec2_double) { instance_double(Aws::EC2::Instance) }
12
- let(:tags) { {} }
13
- let(:iam_instance_profile_arn) { nil }
14
- let(:user_data_file) { nil }
15
-
16
- subject(:aws_instance) do
17
- described_class.new(
18
- role: role,
19
- ami: 'ami',
20
- subnet_id: 'subnet',
21
- key_name: 'key',
22
- aws_instance_type: 't2.micro',
23
- aws_public_ip: false,
24
- aws_security_groups: sec_group_id,
25
- aws_region: region,
26
- tags: tags,
27
- user_data_file: user_data_file,
28
- iam_instance_profile_arn: iam_instance_profile_arn
29
- )
30
- end
31
-
32
- before do
33
- allow(Aws::EC2::Client).to receive(:new).and_return(client_double)
34
- allow(client_double).to receive(:run_instances).and_return(double(instances: [new_ec2_double]))
35
- allow(ec2_double).to receive(:create_tags).and_return(double)
36
- allow(Aws::EC2::Instance).to receive(:new).and_return(ec2_double)
37
- allow(new_ec2_double).to receive(:instance_id)
38
- allow(ec2_double).to receive(:instance_id)
39
- allow(ec2_double).to receive(:wait_until_running)
40
- end
41
-
42
- describe '#start' do
43
- subject(:start) { aws_instance.start }
44
- context 'without optional values' do
45
- it 'does not include the security group' do
46
- expect(client_double).to receive(:run_instances).with(
47
- hash_excluding(:network_interfaces=>array_including(hash_including(:groups)))
48
- )
49
- start
50
- end
51
-
52
- it 'does include the region' do
53
- expect(Aws::EC2::Client).to receive(:new).with(
54
- hash_excluding(:region => region)
55
- )
56
- start
57
- end
58
- end
59
-
60
- context 'with security group' do
61
- let(:sec_group_id) { ['1234'] }
62
-
63
- it 'does include security groups' do
64
- expect(client_double).to receive(:run_instances).with(
65
- hash_including(:network_interfaces=>array_including(hash_including(:groups)))
66
- )
67
- start
68
- end
69
- end
70
-
71
- context 'with region' do
72
- let(:region) { 'us-east-1' }
73
-
74
- it 'does include the region in the intial connection' do
75
- expect(Aws::EC2::Client).to receive(:new).with(
76
- hash_including(:region => region)
77
- )
78
- start
79
- end
80
-
81
- it 'does include the region in the subsequent connection' do
82
- expect(Aws::EC2::Instance).to receive(:new).with(
83
- anything,
84
- hash_including(:region => region)
85
- )
86
- start
87
- end
88
- end
89
-
90
- context 'with tags' do
91
- let(:tags) { {"Name" => "AmiSpec"} }
92
-
93
- it 'tags the instance' do
94
- expect(ec2_double).to receive(:create_tags).with(
95
- {tags: [{ key: 'AmiSpec', value: role}, { key: "Name", value: "AmiSpec"}]}
96
- )
97
- start
98
- end
99
- end
100
-
101
- context 'with user_data' do
102
- let(:user_data_file) {
103
- file = Tempfile.new('user_data.txt')
104
- file.write("my file\ncontent")
105
- file.close
106
- file.path
107
- }
108
-
109
- it 'does include user_data' do
110
- expect(client_double).to receive(:run_instances).with(
111
- hash_including(:user_data => Base64.encode64("my file\ncontent"))
112
- )
113
- start
114
- end
115
- end
116
-
117
- context 'with iam_instance_profile_arn' do
118
- let(:iam_instance_profile_arn) { "my_arn" }
119
-
120
- it 'does include iam_instance_profile_arn' do
121
- expect(client_double).to receive(:run_instances).with(
122
- hash_including(:iam_instance_profile => { arn: 'my_arn'})
123
- )
124
- start
125
- end
126
- end
127
-
128
- it 'tags the instance with a role' do
129
- expect(ec2_double).to receive(:create_tags).with(
130
- hash_including(tags: [{ key: 'AmiSpec', value: role}])
131
- )
132
- start
133
- end
134
-
135
- it 'delegates some methods to the instance variable' do
136
- expect(ec2_double).to receive(:instance_id)
137
- start
138
- aws_instance.instance_id
139
- end
140
- end
141
-
142
- end
@@ -1,9 +0,0 @@
1
- FROM amazonlinux:1
2
-
3
- RUN yum install -y upstart openssh-server && yum clean all
4
- ADD rc.conf /etc/init/rc.conf
5
-
6
- COPY ami-spec.pub /root/.ssh/authorized_keys
7
- COPY sshd_config /etc/ssh/sshd_config
8
-
9
- CMD ["/bin/bash", "-c", "exec /sbin/init"]
@@ -1,8 +0,0 @@
1
- FROM ubuntu-upstart:trusty
2
-
3
- ENV DEBIAN_FRONTEND noninteractive
4
- RUN apt-get update && apt-get install -y openssh-server && apt-get clean
5
-
6
- COPY ami-spec.pub /root/.ssh/authorized_keys
7
-
8
- EXPOSE 22
@@ -1,22 +0,0 @@
1
- FROM ubuntu:xenial
2
-
3
- RUN cd /lib/systemd/system/sysinit.target.wants/; ls | grep -v systemd-tmpfiles-setup | xargs rm -f $1 \
4
- rm -f /lib/systemd/system/multi-user.target.wants/*;\
5
- rm -f /etc/systemd/system/*.wants/*;\
6
- rm -f /lib/systemd/system/local-fs.target.wants/*; \
7
- rm -f /lib/systemd/system/sockets.target.wants/*udev*; \
8
- rm -f /lib/systemd/system/sockets.target.wants/*initctl*; \
9
- rm -f /lib/systemd/system/basic.target.wants/*;\
10
- rm -f /lib/systemd/system/anaconda.target.wants/*; \
11
- rm -f /lib/systemd/system/plymouth*; \
12
- rm -f /lib/systemd/system/systemd-update-utmp*;
13
-
14
- RUN apt-get update && apt-get install -y openssh-server dbus && apt-get clean
15
-
16
- RUN systemctl set-default multi-user.target
17
-
18
- COPY ami-spec.pub /root/.ssh/authorized_keys
19
-
20
- EXPOSE 22
21
-
22
- CMD ["/bin/bash", "-c", "exec /sbin/init --log-target=journal 3>&1"]
@@ -1,5 +0,0 @@
1
- ## Integration test containers
2
-
3
- This directory is used to create containers that can be used to test the `WaitForRC` class. Because they require upstart/systemd to exist we have to install and start the init environment. We also setup SSH so that we can simple call the `wait` function and have it SSH to our container to execute.
4
-
5
- Refer to the [README](../../README.md#running-tests) for how to execute them.
@@ -1,27 +0,0 @@
1
- -----BEGIN RSA PRIVATE KEY-----
2
- MIIEowIBAAKCAQEAwWn2++lylp8RcHzy7H9QpYli3nxLDh769DDbnb9cw2UDd9OH
3
- 6JZKaT3xe3IbMr39SmkGlOygkBmeH43VxAkiVJv3awDPRU0UvDyUvCsbaYj1/cOS
4
- 8Vxr7ENExoiKkengcg6k3mFj65ooJ1pf8RoXuj+0+YU0fgejuR/M4x6V8GKFCJhU
5
- wFmRs3mcoCx0EiJtTx40IW87uOQUruDX5HcgTUInRhyRxltNrXJaap1weMGpIA/o
6
- Bo8foOx1Os9o3YKQlkPF4iqk2AVJ4FZGbMay0cIq3075Jeig6bdlIhRpYA+w+SAI
7
- y/yT/K3U1ciQqKtPgahGEyihrh7Ks2F2FSLhdwIDAQABAoIBABWt/QNLrY54kgnb
8
- 15buxmlntu9dW0Rf8J1ChLtv4cP9JKBf05IcloapbNH7flT3utaGYzh6NZ0xYeoD
9
- ifyJUZHOUbNqydDozPQ0ji9xXYc81OX28Beh1m8LM0BVucKVRpVCUvSiUgLsqqeO
10
- l8Z8uEAmN/DoH3QpAw8TI3Ip0YC6OHA2aRV9PXuDnR5OTdBPOBj33Fdtf0rUAk41
11
- UFe/BHFyACfTK05+bcQz9DvRV/H+SnBeOCqDie1eNDnEgza4NS2cnBUCogKsaCrY
12
- gV06pivS2aHsK5CuNB1lcZi1tVf3DnDwPvFWqLLG9PIHaevPDpDURECirCrpCWJT
13
- VSHm7KECgYEA4K5jSna4Jzo9FlHzF+yGEju5QwEJTjnhunNw1FpcgPAddFQ4hs3w
14
- 0EhyPlZyf3vwhfdH4vBhTLjRTrOF2SIvSSPwrkWlAhaluVvpVRFd/ncYW4kAVwhQ
15
- 15/ZBtvu8OQnKeeztsLlkEi4ik3cKjeXyeDQReb2Guvc6IM4fr6ZrlkCgYEA3F/S
16
- uJr04UgzX0cQuNLX7uXz6oeyJupwFkTuAhvLcHDsDHFkP1M9zfFzg5aEcQungz/l
17
- 5s/vFJmfLBrzhSoYY1T9PDdLwEL/JKaxhKNEV9lExF4exMui6QPWdTMA8ndvB7r5
18
- Ur85X8scH1qJo99fsEmNmG5O72PGXmltOB0sNE8CgYEApeuCPYIweh+C7xGzkE5F
19
- r/9Uz4tbYN5TuMn5X4gfWcR4K+jqGXrJxDZLz4ctZMGVHIlBF/DmGa8+On1OccvR
20
- 2ZRl73xU35bz6U9bn0uE+x7d6PLiQmNMt/8+WNdfu5rw5PxLdcK1nnhldxUKak7F
21
- k/qmM4jc44Kcj0QgG1EL0nkCgYAFbV61KSvKuIp7WDazNo4W1hbxubHLf46PHdd2
22
- udSCymUl0U0UuioVflLH9NcCKbVQaCxzSL+slDP1VByXNPgwyhEKgJoe/Adokaph
23
- h9vRBgrJgz/ivNkgP/XyIPVvAz36xMILJaZ2E3x30TT+kiu7HbSdAmpzPtPN027b
24
- KOzDxQKBgEv2OvEtpvpv9DgPHs9Mq4haTh2o8c8JW7kwHqbbZOZjZ/4daEh89FhH
25
- gjvJV5NjaNhFqBWTnNfjSr4o09WFDoQyVwEUrWNJXXZmsjOHqMDT/kwVoAsld1tO
26
- N+JW6/4M+EMYvF39yWzdQn/U3A1gZIfzAC6S3HUCi9BgKLBMKEN3
27
- -----END RSA PRIVATE KEY-----
@@ -1 +0,0 @@
1
- ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDBafb76XKWnxFwfPLsf1CliWLefEsOHvr0MNudv1zDZQN304folkppPfF7chsyvf1KaQaU7KCQGZ4fjdXECSJUm/drAM9FTRS8PJS8KxtpiPX9w5LxXGvsQ0TGiIqR6eByDqTeYWPrmignWl/xGhe6P7T5hTR+B6O5H8zjHpXwYoUImFTAWZGzeZygLHQSIm1PHjQhbzu45BSu4NfkdyBNQidGHJHGW02tclpqnXB4wakgD+gGjx+g7HU6z2jdgpCWQ8XiKqTYBUngVkZsxrLRwirfTvkl6KDpt2UiFGlgD7D5IAjL/JP8rdTVyJCoq0+BqEYTKKGuHsqzYXYVIuF3
@@ -1,28 +0,0 @@
1
- version: '3'
2
- services:
3
- xenial:
4
- build:
5
- context: .
6
- dockerfile: Dockerfile.xenial
7
- ports:
8
- - "1122:22"
9
- # --security-opt seccomp=unconfined --tmpfs /run --tmpfs /run/lock -v /sys/fs/cgroup:/sys/fs/cgroup:ro
10
- security_opt:
11
- - seccomp:unconfined
12
- tmpfs:
13
- - /run
14
- - /run/lock
15
- volumes:
16
- - /sys/fs/cgroup:/sys/fs/cgroup:ro
17
- trusty:
18
- build:
19
- context: .
20
- dockerfile: Dockerfile.trusty
21
- ports:
22
- - "1123:22"
23
- amazon_linux:
24
- build:
25
- context: .
26
- dockerfile: Dockerfile.amazon_linux
27
- ports:
28
- - "1124:22"
@@ -1,17 +0,0 @@
1
- # rc - System V runlevel compatibility
2
- #
3
- # This task runs the old sysv-rc runlevel scripts. It
4
- # is usually started by the telinit compatibility wrapper.
5
- #
6
- # Do not edit this file directly. If you want to change the behaviour,
7
- # please create a file rc.override and put your changes there.
8
-
9
- start on runlevel [0123456]
10
-
11
- stop on runlevel [!$RUNLEVEL]
12
-
13
- task
14
-
15
- export RUNLEVEL
16
- console output
17
- exec /etc/rc.d/rc $RUNLEVEL
@@ -1,17 +0,0 @@
1
- HostKey /etc/ssh/ssh_host_rsa_key
2
- HostKey /etc/ssh/ssh_host_ecdsa_key
3
- HostKey /etc/ssh/ssh_host_ed25519_key
4
- SyslogFacility AUTHPRIV
5
- AuthorizedKeysFile .ssh/authorized_keys
6
- PasswordAuthentication no
7
- ChallengeResponseAuthentication no
8
- UsePAM yes
9
- X11Forwarding yes
10
- PrintLastLog yes
11
- UsePrivilegeSeparation sandbox
12
- AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
13
- AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
14
- AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
15
- AcceptEnv XMODIFIERS
16
- Subsystem sftp /usr/libexec/openssh/sftp-server
17
- PermitRootLogin yes
data/spec/spec_helper.rb DELETED
@@ -1,2 +0,0 @@
1
- $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
- require 'ami_spec'
@@ -1,25 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe AmiSpec::WaitForRC, integration: true do
4
- let(:private_key_file) { File.expand_path(File.join('..', 'containers', 'ami-spec'), __FILE__) }
5
- context 'xenial server' do
6
- let(:ssh_port) { 1122 }
7
- it 'executes without printing any errors' do
8
- expect { described_class.wait("localhost", "root", private_key_file, ssh_port) }.to_not output.to_stdout
9
- end
10
- end
11
-
12
- context 'trusty server' do
13
- let(:ssh_port) { 1123 }
14
- it 'executes without printing any errors' do
15
- expect { described_class.wait("localhost", "root", private_key_file, ssh_port) }.to_not output.to_stdout
16
- end
17
- end
18
-
19
- context 'amazon linux server' do
20
- let(:ssh_port) { 1124 }
21
- it 'executes without printing any errors' do
22
- expect { described_class.wait("localhost", "root", private_key_file, ssh_port) }.to_not output.to_stdout
23
- end
24
- end
25
- end
@@ -1,39 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe AmiSpec::WaitForSSH do
4
- describe '#wait' do
5
- let(:retries) { 30 }
6
- subject { described_class.wait('127.0.0.1', 'ubuntu', 'key.pem', 30) }
7
-
8
- before do
9
- allow_any_instance_of(Object).to receive(:sleep)
10
- end
11
-
12
- it 'returns after one attempt if ssh connection succeeds' do
13
- expect(Net::SSH).to receive(:start)
14
-
15
- subject
16
- end
17
-
18
- context 'ssh fails' do
19
- before do
20
- allow(Net::SSH).to receive(:start).and_raise(Errno::ECONNREFUSED, 'ssh failed')
21
- end
22
-
23
- it 'raises an exception' do
24
- expect{subject}.to raise_error(AmiSpec::InstanceConnectionTimeout)
25
- end
26
-
27
- it 'returns the last error' do
28
- expect(Net::SSH).to receive(:start).and_raise(Errno::ECONNREFUSED, 'some other error')
29
- expect{subject}.to raise_error(AmiSpec::InstanceConnectionTimeout, /ssh failed/)
30
- end
31
-
32
- it 'tries the number of retries specified' do
33
- expect(Net::SSH).to receive(:start).exactly(retries).times
34
-
35
- expect{subject}.to raise_error(AmiSpec::InstanceConnectionTimeout)
36
- end
37
- end
38
- end
39
- end