stemcell 0.11.11 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -54,16 +54,33 @@ encrypted_data_bag_secret_path='<%= opts['chef_data_bag_secret_path'].to_s %>'
54
54
  ##
55
55
 
56
56
  update() {
57
- echo updating apt repo
58
- apt-get update 1>&2
57
+ echo updating repository metadata
58
+
59
+ case $OS_PACKAGE_MANAGER in
60
+ apt)
61
+ apt-get update 1>&2
62
+ ;;
63
+ yum)
64
+ # yum install will check if metadata needs to be updated
65
+ # so it's just for consistency with apt-based distros
66
+ yum check-update 1>&2 || true
67
+ ;;
68
+ esac
59
69
  }
60
70
 
61
71
  install() {
62
- if ! (dpkg -l | awk '{print $2}' | grep -q ^$1$ ) ; then
63
- echo installing $1...
64
- export DEBIAN_FRONTEND=noninteractive
65
- apt-get install -y $1 1>&2
66
- fi
72
+ case $OS_PACKAGE_MANAGER in
73
+ apt)
74
+ if ! (dpkg -l | awk '{print $2}' | grep -q ^$1$ ) ; then
75
+ echo installing $1...
76
+ export DEBIAN_FRONTEND=noninteractive
77
+ apt-get install -y $1 1>&2
78
+ fi
79
+ ;;
80
+ yum)
81
+ rpm -q $1 2>&1 >/dev/null || yum install -y $1
82
+ ;;
83
+ esac
67
84
  }
68
85
 
69
86
  set_hostname() {
@@ -86,22 +103,34 @@ set_hostname() {
86
103
  echo "$local_ip $fqdn $hostname" >> /etc/hosts
87
104
  }
88
105
 
106
+ download_chef_package() {
107
+ echo "Downloading chef from $1"
108
+ wget "$1" -O "$2" --progress=dot:mega --tries=15 --retry-connrefused --timeout=5 --wait=10 --random-wait --continue --no-dns-cache
109
+ }
110
+
89
111
  install_chef() {
112
+ package_local="/tmp/chef_${chef_version}.${OS_PACKAGE_EXT}"
113
+ package_url="$(render_chef_url)"
114
+
90
115
  # check to see if chef is already installed
91
116
  if ! which chef-solo > /dev/null ; then
92
- platform=`lsb_release -s -i | tr '[:upper:]' '[:lower:]'`
93
- platform_version=`lsb_release -s -r`
94
- arch=`uname -m`
95
- package_local="/tmp/chef_${chef_version}.deb"
96
- package_url="<%= opts['chef_package_source'] %>"
97
- echo "Downloading chef from $package_url"
98
- wget $package_url -O $package_local --progress=dot:mega
99
- echo "Installing chef $chef_version"
100
- dpkg -i $package_local
101
- rm $package_local
117
+ case $OS_PACKAGE_MANAGER in
118
+ apt)
119
+ download_chef_package "$package_url" "$package_local"
120
+ echo "Installing chef $chef_version"
121
+ dpkg -i $package_local
122
+ ;;
123
+ yum)
124
+ download_chef_package "$package_url" "$package_local"
125
+ echo "Installing chef $chef_version"
126
+ rpm -ivh "$package_local"
127
+ ;;
128
+ esac
102
129
  else
103
130
  echo chef is already installed
104
131
  fi
132
+
133
+ rm -f $package_local
105
134
  }
106
135
 
107
136
  create_ohai_hint() {
@@ -147,16 +176,17 @@ configure_chef() {
147
176
 
148
177
  echo "configuring chef solo..."
149
178
  cat<<EOF > ${chef_dir}/solo.rb
179
+ # chef config (https://docs.chef.io/config_rb_client.html)
150
180
  repo_dir = "${repo_dir}"
151
181
 
152
182
  cookbook_path ["#{repo_dir}/site-cookbooks", "#{repo_dir}/cookbooks"]
153
183
  role_path "#{repo_dir}/roles"
154
184
  data_bag_path "#{repo_dir}/data_bags"
185
+ ohai.plugin_path << "#{repo_dir}/ohai_plugins"
155
186
  ssl_verify_mode :verify_peer
156
187
  log_level :info
157
188
  log_location STDOUT
158
189
 
159
- Ohai::Config[:plugin_path] << "#{repo_dir}/ohai_plugins"
160
190
  EOF
161
191
 
162
192
  if [ -n "$encrypted_data_bag_secret_path" ]; then
@@ -197,7 +227,7 @@ git reset --hard origin/\${branch}
197
227
  git clean -fdx
198
228
 
199
229
  json="{\"role\": \"\${role}\", \"env\": \"\${env}\", \"branch\": \"\${branch}\"}"
200
- json_file=\`tempfile\`
230
+ json_file=\`mktemp\`
201
231
  echo \$json > \$json_file
202
232
  trap "{ rm -f '\$json_file' ; }" EXIT
203
233
 
@@ -235,12 +265,55 @@ run_chef() {
235
265
  set -e
236
266
  }
237
267
 
268
+ render_chef_url() {
269
+ base_url="<%= opts['chef_package_source'] %>"
270
+ echo $base_url | sed \
271
+ -e "s/%{platform}/$OS_PLATFORM/g" \
272
+ -e "s/%{platform_version}/$OS_PLATFORM_VERSION/g" \
273
+ -e "s/%{chef_version}/$chef_version/g" \
274
+ -e "s/%{package_manager}/$OS_PACKAGE_MANAGER/g" \
275
+ -e "s/%{package_arch}/$OS_PACKAGE_ARCH/g" \
276
+ -e "s/%{package_ext}/$OS_PACKAGE_EXT/g"
277
+ }
278
+
279
+ check_os_version() {
280
+ NAME=unsupported
281
+
282
+ if [ -f /etc/os-release ]; then
283
+ . /etc/os-release
284
+ fi
285
+
286
+ case "$NAME" in
287
+ "Ubuntu")
288
+ OS_VERSION="$NAME $VERSION_ID"
289
+ OS_PLATFORM=ubuntu
290
+ OS_PLATFORM_VERSION=$VERSION_ID
291
+ OS_PACKAGE_MANAGER=apt
292
+ OS_PACKAGE_ARCH=$(dpkg --print-architecture)
293
+ OS_PACKAGE_EXT=deb
294
+ ;;
295
+ "Amazon Linux")
296
+ OS_VERSION="$NAME $VERSION_ID"
297
+ OS_PLATFORM=amazon
298
+ OS_PLATFORM_VERSION=$VERSION_ID
299
+ OS_PACKAGE_MANAGER=yum
300
+ OS_PACKAGE_ARCH=$(uname -m)
301
+ OS_PACKAGE_EXT=rpm
302
+ ;;
303
+ *)
304
+ echo "Unsupported operating system"
305
+ exit 1
306
+ ;;
307
+ esac
308
+ }
238
309
 
239
310
  ##
240
311
  ## main
241
312
  ##
242
313
 
243
- echo "starting chef bootstrapping..."
314
+ check_os_version
315
+
316
+ echo "starting chef bootstrapping on ${OS_VERSION}..."
244
317
  update
245
318
  install curl
246
319
  install git
@@ -1,3 +1,3 @@
1
1
  module Stemcell
2
- VERSION = "0.11.11"
2
+ VERSION = "0.13.0"
3
3
  end
@@ -4,7 +4,9 @@
4
4
  },
5
5
  "backing_store": {
6
6
  "instance_store": {
7
- "image_id": "ami-d9d6a6b0"
7
+ "us-east-1": {
8
+ "image_id": "ami-d9d6a6b0"
9
+ }
8
10
  }
9
11
  }
10
12
  }
@@ -0,0 +1,13 @@
1
+ {
2
+ "defaults": {
3
+ "instance_type": "m1.small"
4
+ },
5
+ "backing_store": {
6
+ "instance_store": {
7
+ "image_id": "ami-d9d6a6b0"
8
+ }
9
+ },
10
+ "availability_zones": {
11
+ "us-east-1": ["us-east-1a"]
12
+ }
13
+ }
@@ -5,7 +5,9 @@
5
5
  },
6
6
  "backing_store": {
7
7
  "instance_store": {
8
- "image_id": "ami-d9d6a6b0"
8
+ "us-east-1": {
9
+ "image_id": "ami-d9d6a6b0"
10
+ }
9
11
  }
10
12
  },
11
13
  "availability_zones": {
@@ -1,7 +1,9 @@
1
1
  {
2
2
  "backing_store": {
3
3
  "instance_store": {
4
- "baz": "woo"
4
+ "us-east-1": {
5
+ "baz": "woo"
6
+ }
5
7
  }
6
8
  },
7
9
  "availability_zones": {
@@ -16,10 +16,14 @@
16
16
 
17
17
  "backing_store": {
18
18
  "hvm1": {
19
- "image_id": "ami-1"
19
+ "us-east-1": {
20
+ "image_id": "ami-1"
21
+ }
20
22
  },
21
23
  "pv1": {
22
- "image_id": "ami-2"
24
+ "us-east-1": {
25
+ "image_id": "ami-2"
26
+ }
23
27
  }
24
28
  },
25
29
 
@@ -4,7 +4,9 @@
4
4
  },
5
5
  "backing_store": {
6
6
  "instance_store": {
7
- "image_id": "ami-d9d6a6b0"
7
+ "us-east-1": {
8
+ "image_id": "ami-d9d6a6b0"
9
+ }
8
10
  }
9
11
  },
10
12
  "availability_zones": {
@@ -1,45 +1,56 @@
1
1
  require 'spec_helper'
2
+ require 'base64'
2
3
 
3
- class MockInstance
4
- def initialize(id)
5
- @id = id
6
- end
7
-
8
- def id
9
- @id
10
- end
11
-
12
- def status
13
- :running
14
- end
15
- end
16
-
17
- class MockSecurityGroup
18
- attr_reader :group_id, :name, :vpc_id
19
- def initialize(id, name, vpc_id)
20
- @group_id = id
21
- @name = name
22
- @vpc_id = vpc_id
4
+ describe Stemcell::Launcher do
5
+ before do
6
+ Aws.config[:stub_responses] = true
23
7
  end
24
- end
25
-
26
- class MockException < StandardError
27
- end
28
8
 
29
- describe Stemcell::Launcher do
30
9
  let(:launcher) {
31
10
  opts = {'region' => 'region'}
32
11
  launcher = Stemcell::Launcher.new(opts)
33
12
  launcher
34
13
  }
35
14
  let(:operation) { 'op' }
36
- let(:instances) { (1..4).map { |id| MockInstance.new(id) } }
15
+ let(:instances) do
16
+ ('1'..'4').map do |id|
17
+ Aws::EC2::Types::Instance.new(
18
+ instance_id: id,
19
+ private_ip_address: "10.10.10.#{id}",
20
+ state: Aws::EC2::Types::InstanceState.new(name: 'pending')
21
+ )
22
+ end
23
+ end
37
24
  let(:instance_ids) { instances.map(&:id) }
38
25
 
39
26
  describe '#launch' do
40
- let(:ec2) { instance_double(AWS::EC2) }
41
- let(:client) { double(AWS::EC2::Client) }
42
- let(:response) { instance_double(AWS::Core::Response) }
27
+ let(:ec2) do
28
+ ec2 = Aws::EC2::Client.new
29
+ ec2.stub_responses(
30
+ :describe_security_groups,
31
+ security_groups: [
32
+ {group_id: 'sg-1', group_name: 'sg_name1', vpc_id:'vpc-1'},
33
+ {group_id: 'sg-2', group_name: 'sg_name2', vpc_id:'vpc-1'},
34
+ ],
35
+ )
36
+ ec2.stub_responses(
37
+ :describe_instances,
38
+ reservations: [{
39
+ instances: ('1'..'4').map do |id|
40
+ {
41
+ instance_id: id,
42
+ private_ip_address: "10.10.10.#{id}",
43
+ public_ip_address: "24.10.10.#{id}",
44
+ state: {
45
+ name: 'running'
46
+ }
47
+ }
48
+ end
49
+ }]
50
+ )
51
+ ec2
52
+ end
53
+ let(:response) { instance_double(Seahorse::Client::Response) }
43
54
  let(:launcher) {
44
55
  opts = {'region' => 'region', 'vpc_id' => 'vpc-1'}
45
56
  launcher = Stemcell::Launcher.new(opts)
@@ -59,7 +70,8 @@ describe Stemcell::Launcher do
59
70
  'availability_zone' => 'us-east-1a',
60
71
  'count' => 2,
61
72
  'security_groups' => ['sg_name1', 'sg_name2'],
62
- 'wait' => false
73
+ 'user' => 'some_user',
74
+ 'wait' => true
63
75
  }
64
76
  }
65
77
 
@@ -67,132 +79,105 @@ describe Stemcell::Launcher do
67
79
  allow(launcher).to receive(:try_file).and_return('secret')
68
80
  allow(launcher).to receive(:render_template).and_return('template')
69
81
  allow(launcher).to receive(:ec2).and_return(ec2)
70
- allow(ec2).to receive(:client).and_return(client)
71
82
  allow(response).to receive(:error).and_return(nil)
72
83
  end
73
84
 
74
85
  it 'launches all of the instances' do
75
86
  expect(launcher).to receive(:get_vpc_security_group_ids).
76
87
  with('vpc-1', ['sg_name1', 'sg_name2']).and_call_original
77
- expect_any_instance_of(AWS::EC2::VPC).to receive(:security_groups).
78
- and_return([1,2].map { |i| MockSecurityGroup.new("sg-#{i}", "sg_name#{i}", 'vpc-1')})
88
+ expect(ec2).to receive(:describe_security_groups).and_call_original
79
89
  expect(launcher).to receive(:do_launch).with(a_hash_including(
80
90
  :image_id => 'ami-d9d6a6b0',
81
91
  :instance_type => 'c1.xlarge',
82
92
  :key_name => 'key',
83
- :count => 2,
84
- :security_group_ids => ['sg-1', 'sg-2'],
85
- :availability_zone => 'us-east-1a',
86
- :user_data => 'template'
93
+ :min_count => 2,
94
+ :max_count => 2,
95
+ :placement => { :availability_zone => 'us-east-1a' },
96
+ :network_interfaces => [{
97
+ :device_index => 0,
98
+ :groups => ['sg-1', 'sg-2' ]
99
+ }],
100
+ :tag_specifications => [
101
+ {
102
+ :resource_type => 'instance',
103
+ :tags => [
104
+ { :key => "Name", :value => "role-environment" },
105
+ { :key => "Group", :value => "role-environment" },
106
+ { :key => "created_by", :value => "some_user" },
107
+ { :key => "stemcell", :value => Stemcell::VERSION },
108
+ ]},
109
+ ],
110
+ :user_data => Base64.encode64('template')
87
111
  )).and_return(instances)
88
- expect(launcher).to receive(:set_tags).with(kind_of(Array), kind_of(Hash)).and_return(nil)
89
- # set_classic_link should not be set on vpc hosts.
90
- expect(launcher).not_to receive(:set_classic_link)
91
-
92
- launcher.send(:launch, launch_options)
93
- end
94
-
95
- it 'calls set_classic_link for non vpc instances' do
96
- launcher = Stemcell::Launcher.new({'region' => 'region', 'vpc_id' => false})
97
- expect(launcher).to receive(:set_classic_link)
98
- expect(launcher).to receive(:set_tags).with(kind_of(Array), kind_of(Hash)).and_return(nil)
99
- expect(launcher).to receive(:do_launch).and_return(instances)
100
- launcher.send(:launch, launch_options)
112
+ launched_instances = launcher.send(:launch, launch_options)
113
+ expect(launched_instances.map(&:public_ip_address)).to all(be_truthy)
101
114
  end
102
115
  end
103
116
 
104
- describe '#set_classic_link' do
105
- let(:ec2) { instance_double(AWS::EC2) }
106
- let(:client) { double(AWS::EC2::Client) }
107
- let(:response) { instance_double(AWS::Core::Response) }
108
- before do
109
- allow(launcher).to receive(:ec2).and_return(ec2)
110
- allow(ec2).to receive(:client).and_return(client)
111
- allow(response).to receive(:error).and_return(nil)
117
+ describe '#kill' do
118
+ let(:ec2) do
119
+ ec2 = Aws::EC2::Client.new
120
+ ec2.stub_responses(
121
+ :terminate_instances, -> (context) {
122
+ instance_ids = context.params[:instance_ids]
123
+ if instance_ids.include? 'i-3'
124
+ Aws::EC2::Errors::InvalidInstanceIDNotFound.new(nil, "The instance ID 'i-3' do not exist")
125
+ else
126
+ {} # success
127
+ end
128
+ })
129
+ ec2
112
130
  end
113
131
 
114
- let(:classic_link) {
115
- {
116
- 'vpc_id' => 'vpc-1',
117
- 'security_group_ids' => ['sg-1', 'sg-2'],
118
- 'security_groups' => ['sg_name']
119
- }
120
- }
121
-
122
- it 'invokes classic link on all of the instances' do
123
- expect(launcher).to receive(:get_vpc_security_group_ids).with('vpc-1', ['sg_name']).
124
- and_call_original
125
- expect_any_instance_of(AWS::EC2::VPC).to receive(:security_groups).
126
- and_return([MockSecurityGroup.new('sg-3', 'sg_name', 'vpc-1')])
127
- instances.each do |instance|
128
- expect(client).to receive(:attach_classic_link_vpc).ordered.with(a_hash_including(
129
- :instance_id => instance.id,
130
- :vpc_id => classic_link['vpc_id'],
131
- :groups => ['sg-1', 'sg-2', 'sg-3'],
132
- )).and_return(response)
133
- end
132
+ let(:instance_ids) { ('i-1'..'i-4').to_a }
134
133
 
135
- launcher.send(:set_classic_link, instances, classic_link)
136
- end
137
- end
138
-
139
- describe '#run_batch_operation' do
140
- it "raises no exception when no internal error occur" do
141
- errors = launcher.send(:run_batch_operation, instances) {}
142
- expect(errors.all?(&:nil?)).to be true
134
+ before do
135
+ allow(launcher).to receive(:ec2).and_return(ec2)
143
136
  end
144
137
 
145
- it "runs full batch even when there are two error" do
146
- errors = launcher.send(:run_batch_operation,
147
- instances) do |instance, error|
148
- raise "error-#{instance.id}" if instance.id % 2 == 0
138
+ context 'when ignore_not_found is true' do
139
+ it 'terminates valid instances even if an invalid instance id is provided' do
140
+ launcher.kill(instance_ids, ignore_not_found: true)
149
141
  end
150
- expect(errors.count(&:nil?)).to be_eql(2)
151
- expect(errors.reject(&:nil?).map { |e| e.message }).to \
152
- be_eql([2, 4].map { |id| "error-#{id}" })
153
- end
154
142
 
155
- it "retries after an intermittent error" do
156
- count = 0
157
- errors = launcher.send(:run_batch_operation,
158
- instances) do |instance|
159
- if instance.id == 3
160
- count += 1
161
- count < 3 ?
162
- AWS::EC2::Errors::InvalidInstanceID::NotFound.new("error-#{instance.id}"):
163
- nil
164
- end
143
+ it 'finishes without error even if no instance ids are valid' do
144
+ launcher.kill(['i-3'], ignore_not_found: true)
165
145
  end
166
- expect(errors.all?(&:nil?)).to be true
167
146
  end
168
147
 
169
- it "retries up to max_attempts option per instance" do
170
- max_attempts = 6
171
- opts = {'region' => 'region', 'max_attempts' => max_attempts}
172
- launcher = Stemcell::Launcher.new(opts)
173
- allow(launcher).to receive(:sleep).and_return(0)
174
- tags = double("Tags")
175
- instances = (1..2).map do |id|
176
- inst = MockInstance.new(id)
177
- allow(inst).to receive(:tags).and_return(tags)
178
- inst
148
+ context 'when ignore_not_found is false' do
149
+ it 'raises an error' do
150
+ expect { launcher.kill(instance_ids) }.to raise_error(Aws::EC2::Errors::InvalidInstanceIDNotFound)
179
151
  end
180
- expect(tags).to receive(:set).with({'a' => 'b'}).exactly(12).times.
181
- and_raise(AWS::EC2::Errors::InvalidInstanceID::NotFound.new("error"))
182
- expect do
183
- launcher.send(:set_tags, instances, {'a' => 'b'})
184
- end.to raise_error(Stemcell::IncompleteOperation)
185
152
  end
186
153
  end
187
154
 
188
155
  describe '#configure_aws_creds_and_region' do
189
- it 'AWS region is configured after launcher is instanciated' do
190
- expect(AWS.config.region).to be_eql('region')
156
+ it 'AWS region is configured after launcher is instantiated' do
157
+ expect(Aws.config[:region]).to be_eql('region')
191
158
  end
192
159
 
193
160
  it 'AWS region configuration changed' do
194
161
  mock_launcher = Stemcell::Launcher.new('region' => 'ap-northeast-1')
195
- expect(AWS.config.region).to be_eql('ap-northeast-1')
162
+ expect(Aws.config[:region]).to be_eql('ap-northeast-1')
163
+ end
164
+ end
165
+
166
+ describe '#ec2' do
167
+
168
+ it 'can return a client with regional endpoint' do
169
+ launcher = Stemcell::Launcher.new({'region' => 'us-east-1', 'ec2_endpoint' => nil})
170
+ client = launcher.send(:ec2)
171
+ expect(client.config[:endpoint].to_s).to be_eql('https://ec2.us-east-1.amazonaws.com')
172
+ end
173
+
174
+ it 'can return a client with custom endpoint' do
175
+ launcher = Stemcell::Launcher.new({
176
+ 'region' => 'region1',
177
+ 'ec2_endpoint' => 'https://endpoint1',
178
+ })
179
+ client = launcher.send(:ec2)
180
+ expect(client.config[:endpoint].to_s).to be_eql('https://endpoint1')
196
181
  end
197
182
  end
198
183
  end
@@ -32,7 +32,9 @@ describe Stemcell::MetadataSource::Configuration do
32
32
  it "sets backing_store_options" do
33
33
  expect(config.backing_store_options).to eql({
34
34
  'instance_store' => {
35
- 'image_id' => 'ami-d9d6a6b0'
35
+ 'us-east-1' => {
36
+ 'image_id' => 'ami-d9d6a6b0'
37
+ }
36
38
  }
37
39
  })
38
40
  end
@@ -86,10 +88,11 @@ describe Stemcell::MetadataSource::Configuration do
86
88
 
87
89
  describe '#options_for_backing_store' do
88
90
  let(:backing_store) { 'instance_store' }
91
+ let(:region) { 'us-east-1' }
89
92
 
90
93
  context "when the backing store definition exists" do
91
94
  it "returns the options" do
92
- expect(config.options_for_backing_store(backing_store)).to eql({
95
+ expect(config.options_for_backing_store(backing_store, region)).to eql({
93
96
  'image_id' => 'ami-d9d6a6b0'
94
97
  })
95
98
  end
@@ -97,13 +100,23 @@ describe Stemcell::MetadataSource::Configuration do
97
100
 
98
101
  context "when the backing store isn't defined" do
99
102
  let(:backing_store) { 'nyanstore' }
103
+ let(:region) { 'us-east-1' }
100
104
  it "raises" do
101
- expect { config.options_for_backing_store(backing_store) }.to raise_error(
105
+ expect { config.options_for_backing_store(backing_store, region) }.to raise_error(
102
106
  Stemcell::UnknownBackingStoreError
103
107
  )
104
108
  end
105
109
  end
106
110
 
111
+ context "when the legacy backing store definition exists" do
112
+ let(:config_filename) { 'stemcell-backing-store-legacy.json' }
113
+ it "returns the options" do
114
+ expect(config.options_for_backing_store(backing_store, region)).to eql({
115
+ 'image_id' => 'ami-d9d6a6b0'
116
+ })
117
+ end
118
+ end
119
+
107
120
  end
108
121
 
109
122
  describe '#random_az_in_region' do
@@ -161,7 +161,8 @@ describe Stemcell::MetadataSource do
161
161
  it "calls the config object to retrieve the backing store options" do
162
162
  backing_options.merge!('image_id' => 'ami-nyancat')
163
163
  override_options.merge!('backing_store' => 'ebs')
164
- expect(config).to receive(:options_for_backing_store).with('ebs') { backing_options }
164
+ override_options.merge!('region' => 'us-east-1')
165
+ expect(config).to receive(:options_for_backing_store).with('ebs', 'us-east-1') { backing_options }
165
166
  expect(expansion['image_id']).to eql 'ami-nyancat'
166
167
  end
167
168
 
data/stemcell.gemspec CHANGED
@@ -17,8 +17,11 @@ Gem::Specification.new do |s|
17
17
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
18
18
  s.require_paths = ["lib"]
19
19
 
20
- s.add_runtime_dependency 'aws-sdk-v1', '~> 1.63'
21
- s.add_runtime_dependency 'net-ssh', '~> 2.9'
20
+ # pins several aws sdk transitive dependencies to maintain compatibility with Ruby < 2.3
21
+ s.add_runtime_dependency 'aws-eventstream', '~> 1.1.1'
22
+ s.add_runtime_dependency 'aws-sdk-ec2', '~> 1'
23
+ s.add_runtime_dependency 'aws-sigv4', '~> 1.2.4'
24
+ s.add_runtime_dependency 'net-ssh', '~> 2.9'
22
25
  if RUBY_VERSION >= '2.0'
23
26
  s.add_runtime_dependency 'chef', '>= 11.4.0'
24
27
  else
@@ -29,7 +32,7 @@ Gem::Specification.new do |s|
29
32
  # version dependency. lets explicitly include it here. if this becomes
30
33
  # no-longer a dependency of chef via chef-zero, then remove it
31
34
  s.add_runtime_dependency 'rack', '< 2.0.0'
32
- s.add_runtime_dependency 'nokogiri', '< 1.7.0'
35
+ s.add_runtime_dependency 'nokogiri', '~> 1.8.2'
33
36
  s.add_runtime_dependency 'ffi-yajl', '< 2.3.1'
34
37
 
35
38
  s.add_runtime_dependency 'trollop', '~> 2.1'