knife-ec2 0.12.0 → 0.13.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.
@@ -1,49 +1,49 @@
1
- class Chef
2
- class Knife
3
- class S3Source
4
- attr_accessor :url
5
-
6
- def self.fetch(url)
7
- source = Chef::Knife::S3Source.new
8
- source.url = url
9
- source.body
10
- end
11
-
12
- def body
13
- bucket_obj.files.get(path).body
14
- end
15
-
16
- private
17
-
18
- def bucket_obj
19
- @bucket_obj ||= fog.directories.get(bucket)
20
- end
21
-
22
- def bucket
23
- uri = URI(@url)
24
- if uri.scheme == "s3"
25
- URI(@url).host
26
- else
27
- URI(@url).path.split("/")[1]
28
- end
29
- end
30
-
31
- def path
32
- uri = URI(@url)
33
- if uri.scheme == "s3"
34
- URI(@url).path.sub(/^\//, '')
35
- else
36
- URI(@url).path.split(bucket).last.sub(/^\//, '')
37
- end
38
- end
39
-
40
- def fog
41
- require 'fog' # lazy load the fog library to speed up the knife run
42
- @fog ||= Fog::Storage::AWS.new(
43
- aws_access_key_id: Chef::Config[:knife][:aws_access_key_id],
44
- aws_secret_access_key: Chef::Config[:knife][:aws_secret_access_key]
45
- )
46
- end
47
- end
48
- end
49
- end
1
+ class Chef
2
+ class Knife
3
+ class S3Source
4
+ attr_accessor :url
5
+
6
+ def self.fetch(url)
7
+ source = Chef::Knife::S3Source.new
8
+ source.url = url
9
+ source.body
10
+ end
11
+
12
+ def body
13
+ bucket_obj.files.get(path).body
14
+ end
15
+
16
+ private
17
+
18
+ def bucket_obj
19
+ @bucket_obj ||= fog.directories.get(bucket)
20
+ end
21
+
22
+ def bucket
23
+ uri = URI(@url)
24
+ if uri.scheme == "s3"
25
+ URI(@url).host
26
+ else
27
+ URI(@url).path.split("/")[1]
28
+ end
29
+ end
30
+
31
+ def path
32
+ uri = URI(@url)
33
+ if uri.scheme == "s3"
34
+ URI(@url).path.sub(/^\//, '')
35
+ else
36
+ URI(@url).path.split(bucket).last.sub(/^\//, '')
37
+ end
38
+ end
39
+
40
+ def fog
41
+ require 'fog/aws' # lazy load the fog library to speed up the knife run
42
+ @fog ||= Fog::Storage::AWS.new(
43
+ aws_access_key_id: Chef::Config[:knife][:aws_access_key_id],
44
+ aws_secret_access_key: Chef::Config[:knife][:aws_secret_access_key]
45
+ )
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,6 +1,6 @@
1
- module Knife
2
- module Ec2
3
- VERSION = "0.12.0"
4
- MAJOR, MINOR, TINY = VERSION.split('.')
5
- end
6
- end
1
+ module Knife
2
+ module Ec2
3
+ VERSION = "0.13.0"
4
+ MAJOR, MINOR, TINY = VERSION.split('.')
5
+ end
6
+ end
@@ -1,18 +1,18 @@
1
- $:.unshift File.expand_path('../../lib', __FILE__)
2
- require 'chef'
3
- require 'chef/knife/winrm_base'
4
- require 'chef/knife/ec2_server_create'
5
- require 'chef/knife/ec2_server_delete'
6
- require 'chef/knife/ec2_server_list'
7
-
8
- # Clear config between each example
9
- # to avoid dependencies between examples
10
- RSpec.configure do |c|
11
- c.raise_errors_for_deprecations!
12
- c.filter_run_excluding :exclude => true
13
- c.before(:each) do
14
- Chef::Config.reset
15
- Chef::Config[:knife] ={}
16
- end
17
- end
18
-
1
+ $:.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'chef'
3
+ require 'chef/knife/winrm_base'
4
+ require 'chef/knife/ec2_server_create'
5
+ require 'chef/knife/ec2_server_delete'
6
+ require 'chef/knife/ec2_server_list'
7
+
8
+ # Clear config between each example
9
+ # to avoid dependencies between examples
10
+ RSpec.configure do |c|
11
+ c.raise_errors_for_deprecations!
12
+ c.filter_run_excluding :exclude => true
13
+ c.before(:each) do
14
+ Chef::Config.reset
15
+ Chef::Config[:knife] ={}
16
+ end
17
+ end
18
+
@@ -20,7 +20,7 @@ require File.expand_path('../../spec_helper', __FILE__)
20
20
  require 'net/ssh/proxy/http'
21
21
  require 'net/ssh/proxy/command'
22
22
  require 'net/ssh/gateway'
23
- require 'fog'
23
+ require 'fog/aws'
24
24
  require 'chef/knife/bootstrap'
25
25
  require 'chef/knife/bootstrap_windows_winrm'
26
26
  require 'chef/knife/bootstrap_windows_ssh'
@@ -35,11 +35,15 @@ describe Chef::Knife::Ec2ServerCreate do
35
35
  :image => 'image',
36
36
  :ssh_key_name => 'ssh_key_name',
37
37
  :aws_access_key_id => 'aws_access_key_id',
38
- :aws_secret_access_key => 'aws_secret_access_key'
38
+ :aws_secret_access_key => 'aws_secret_access_key',
39
+ :network_interfaces => ['eni-12345678',
40
+ 'eni-87654321']
39
41
  }.each do |key, value|
40
42
  Chef::Config[:knife][key] = value
41
43
  end
42
44
 
45
+ @my_vpc = 'vpc-12345678'
46
+
43
47
  @ec2_connection = double(Fog::Compute::AWS)
44
48
  allow(@ec2_connection).to receive(:tags).and_return double('create', :create => true)
45
49
  allow(@ec2_connection).to receive_message_chain(:images, :get).and_return double('ami', :root_device_type => 'not_ebs', :platform => 'linux')
@@ -49,6 +53,11 @@ describe Chef::Knife::Ec2ServerCreate do
49
53
  :server_id => nil,
50
54
  :allocation_id => ''})]
51
55
 
56
+ allow(@ec2_connection).to receive(:subnets).and_return [@subnet_1, @subnet_2]
57
+ allow(@ec2_connection).to receive_message_chain(:network_interfaces, :all).and_return [
58
+ double('network_interfaces', network_interface_id: 'eni-12345678'),
59
+ double('network_interfaces', network_interface_id: 'eni-87654321')
60
+ ]
52
61
 
53
62
  @ec2_servers = double()
54
63
  @new_ec2_server = double()
@@ -98,6 +107,8 @@ describe Chef::Knife::Ec2ServerCreate do
98
107
  @validation_key_url = 's3://bucket/foo/bar'
99
108
  @validation_key_file = '/tmp/a_good_temp_file'
100
109
  @validation_key_body = "TEST VALIDATION KEY\n"
110
+ @vpc_id = "vpc-1a2b3c4d"
111
+ @vpc_security_group_ids = ["sg-1a2b3c4d"]
101
112
  end
102
113
 
103
114
  describe "Spot Instance creation" do
@@ -162,6 +173,66 @@ describe Chef::Knife::Ec2ServerCreate do
162
173
  expect(@new_ec2_server).to receive(:wait_for).and_return(true)
163
174
  @knife_ec2_create.run
164
175
  end
176
+
177
+ context 'spot-wait-mode option' do
178
+ context 'when spot-price is not given' do
179
+ context 'spot-wait-mode option is not given' do
180
+ before do
181
+ @knife_ec2_create.config.delete(:spot_price)
182
+ end
183
+
184
+ it 'does not raise error' do
185
+ expect(@knife_ec2_create.ui).to_not receive(:error).with(
186
+ 'spot-wait-mode option requires that a spot-price option is set.'
187
+ )
188
+ expect { @knife_ec2_create.validate! }.to_not raise_error
189
+ end
190
+ end
191
+
192
+ context 'spot-wait-mode option is given' do
193
+ before do
194
+ @knife_ec2_create.config.delete(:spot_price)
195
+ @knife_ec2_create.config[:spot_wait_mode] = 'wait'
196
+ end
197
+
198
+ it 'raises error' do
199
+ expect(@knife_ec2_create.ui).to receive(:error).with(
200
+ 'spot-wait-mode option requires that a spot-price option is set.'
201
+ )
202
+ expect { @knife_ec2_create.validate! }.to raise_error(SystemExit)
203
+ end
204
+ end
205
+ end
206
+
207
+ context 'when spot-price is given' do
208
+ context 'spot-wait-mode option is not given' do
209
+ before do
210
+ @knife_ec2_create.config[:spot_price] = 0.001
211
+ end
212
+
213
+ it 'does not raise error' do
214
+ expect(@knife_ec2_create.ui).to_not receive(:error).with(
215
+ 'spot-wait-mode option requires that a spot-price option is set.'
216
+ )
217
+ expect { @knife_ec2_create.validate! }.to_not raise_error
218
+ end
219
+ end
220
+
221
+ context 'spot-wait-mode option is given' do
222
+ before do
223
+ @knife_ec2_create.config[:spot_price] = 0.001
224
+ @knife_ec2_create.config[:spot_wait_mode] = 'exit'
225
+ end
226
+
227
+ it 'does not raise error' do
228
+ expect(@knife_ec2_create.ui).to_not receive(:error).with(
229
+ 'spot-wait-mode option requires that a spot-price option is set.'
230
+ )
231
+ expect { @knife_ec2_create.validate! }.to_not raise_error
232
+ end
233
+ end
234
+ end
235
+ end
165
236
  end
166
237
 
167
238
  describe "run" do
@@ -258,6 +329,17 @@ describe Chef::Knife::Ec2ServerCreate do
258
329
  expect(@knife_ec2_create.server).to_not be_nil
259
330
  end
260
331
 
332
+ it "creates an EC2 instance, enables ClassicLink and bootstraps it" do
333
+ @knife_ec2_create.config[:classic_link_vpc_id] = @vpc_id
334
+ @knife_ec2_create.config[:classic_link_vpc_security_group_ids] = @vpc_security_group_ids
335
+
336
+ expect(@ec2_connection).to receive(:attach_classic_link_vpc).with(@ec2_server_attribs[:id], @vpc_id, @vpc_security_group_ids)
337
+ expect(@new_ec2_server).to receive(:wait_for).and_return(true)
338
+
339
+ @knife_ec2_create.run
340
+ expect(@knife_ec2_create.server).to_not be_nil
341
+ end
342
+
261
343
  it "retries if it receives Fog::Compute::AWS::NotFound" do
262
344
  expect(@new_ec2_server).to receive(:wait_for).and_return(true)
263
345
  expect(@knife_ec2_create).to receive(:create_tags).and_raise(Fog::Compute::AWS::NotFound)
@@ -269,10 +351,8 @@ describe Chef::Knife::Ec2ServerCreate do
269
351
 
270
352
  it 'actually writes to the validation key tempfile' do
271
353
  expect(@new_ec2_server).to receive(:wait_for).and_return(true)
272
- Chef::Config[:knife][:validation_key_url] =
273
- @validation_key_url
274
- @knife_ec2_create.config[:validation_key_url] =
275
- @validation_key_url
354
+ Chef::Config[:knife][:validation_key_url] = @validation_key_url
355
+ @knife_ec2_create.config[:validation_key_url] = @validation_key_url
276
356
 
277
357
  allow(@knife_ec2_create).to receive_message_chain(:validation_key_tmpfile, :path).and_return(@validation_key_file)
278
358
  allow(Chef::Knife::S3Source).to receive(:fetch).with(@validation_key_url).and_return(@validation_key_body)
@@ -423,6 +503,10 @@ describe Chef::Knife::Ec2ServerCreate do
423
503
  expect(bootstrap.config[:secret]).to eql("sys-knife-secret")
424
504
  end
425
505
 
506
+ it "sets encrypted_data_bag_secret" do
507
+ expect(bootstrap.config[:encrypted_data_bag_secret]).to eql("sys-knife-secret")
508
+ end
509
+
426
510
  it "prefers using a provided value instead of the knife confiuration" do
427
511
  subject.config[:secret] = "cli-provided-secret"
428
512
  expect(bootstrap.config[:secret]).to eql("cli-provided-secret")
@@ -438,6 +522,10 @@ describe Chef::Knife::Ec2ServerCreate do
438
522
  expect(bootstrap.config[:secret_file]).to eql("sys-knife-secret-file")
439
523
  end
440
524
 
525
+ it "sets encrypted_data_bag_secret_file" do
526
+ expect(bootstrap.config[:encrypted_data_bag_secret_file]).to eql("sys-knife-secret-file")
527
+ end
528
+
441
529
  it "prefers using a provided value instead of the knife confiuration" do
442
530
  subject.config[:secret_file] = "cli-provided-secret-file"
443
531
  expect(bootstrap.config[:secret_file]).to eql("cli-provided-secret-file")
@@ -458,12 +546,41 @@ describe Chef::Knife::Ec2ServerCreate do
458
546
  end
459
547
  end
460
548
 
549
+ describe 'S3 secret test cases' do
550
+ before do
551
+ Chef::Config[:knife][:s3_secret] =
552
+ 's3://test.bucket/folder/encrypted_data_bag_secret'
553
+ @knife_ec2_create.config[:distro] = 'ubuntu-10.04-magic-sparkles'
554
+ @secret_content = "TEST DATA BAG SECRET\n"
555
+ allow(@knife_ec2_create).to receive(:s3_secret).and_return(@secret_content)
556
+ allow(Chef::Knife).to receive(:Bootstrap)
557
+ @bootstrap = @knife_ec2_create.bootstrap_for_linux_node(@new_ec2_server, @new_ec2_server.dns_name)
558
+ end
559
+
560
+ context 'when s3 secret option is passed' do
561
+ it 'sets the s3 secret value to cl_secret key' do
562
+ @knife_ec2_create.bootstrap_common_params(@bootstrap)
563
+ expect(Chef::Config[:knife][:cl_secret]).to eql(@secret_content)
564
+ end
565
+ end
566
+
567
+ context 'when s3 secret option is not passed' do
568
+ it 'sets the cl_secret value to nil' do
569
+ Chef::Config[:knife].delete(:s3_secret)
570
+ Chef::Config[:knife].delete(:cl_secret)
571
+ @knife_ec2_create.bootstrap_common_params(@bootstrap)
572
+ expect(Chef::Config[:knife][:cl_secret]).to eql(nil)
573
+ end
574
+ end
575
+ end
576
+
461
577
  context "when deprecated aws_ssh_key_id option is used in knife config and no ssh-key is supplied on the CLI" do
462
578
  before do
463
579
  Chef::Config[:knife][:aws_ssh_key_id] = "mykey"
464
580
  Chef::Config[:knife].delete(:ssh_key_name)
465
581
  @aws_key = Chef::Config[:knife][:aws_ssh_key_id]
466
582
  allow(@knife_ec2_create).to receive(:ami).and_return(false)
583
+ allow(@knife_ec2_create).to receive(:validate_nics!).and_return(true)
467
584
  end
468
585
 
469
586
  it "gives warning message and creates the attribute with the required name" do
@@ -478,6 +595,7 @@ describe Chef::Knife::Ec2ServerCreate do
478
595
  Chef::Config[:knife][:aws_ssh_key_id] = "mykey"
479
596
  @aws_key = Chef::Config[:knife][:aws_ssh_key_id]
480
597
  allow(@knife_ec2_create).to receive(:ami).and_return(false)
598
+ allow(@knife_ec2_create).to receive(:validate_nics!).and_return(true)
481
599
  end
482
600
 
483
601
  it "gives warning message and gives preference to CLI value over knife config's value" do
@@ -491,6 +609,7 @@ describe Chef::Knife::Ec2ServerCreate do
491
609
  before do
492
610
  Chef::Config[:knife][:ssh_key_name] = "mykey"
493
611
  allow(@knife_ec2_create).to receive(:ami).and_return(false)
612
+ allow(@knife_ec2_create).to receive(:validate_nics!).and_return(true)
494
613
  end
495
614
 
496
615
  it "does nothing" do
@@ -521,7 +640,9 @@ describe Chef::Knife::Ec2ServerCreate do
521
640
  @knife_ec2_create.config[:template_file] = '~/.chef/templates/my-bootstrap.sh.erb'
522
641
  @knife_ec2_create.config[:distro] = 'ubuntu-10.04-magic-sparkles'
523
642
  @knife_ec2_create.config[:run_list] = ['role[base]']
524
- @knife_ec2_create.config[:json_attributes] = "{'my_attributes':{'foo':'bar'}"
643
+ @knife_ec2_create.config[:first_boot_attributes] = "{'my_attributes':{'foo':'bar'}"
644
+ @knife_ec2_create.config[:first_boot_attributes_from_file] = "{'my_attributes':{'foo':'bar'}"
645
+
525
646
 
526
647
  @bootstrap = @knife_ec2_create.bootstrap_for_linux_node(@new_ec2_server, @new_ec2_server.dns_name)
527
648
  end
@@ -539,6 +660,10 @@ describe Chef::Knife::Ec2ServerCreate do
539
660
  expect(@bootstrap.config[:first_boot_attributes]).to eq("{'my_attributes':{'foo':'bar'}")
540
661
  end
541
662
 
663
+ it "should set the bootstrap 'first_boot_attributes_from_file' correctly" do
664
+ expect(@bootstrap.config[:first_boot_attributes_from_file]).to eq("{'my_attributes':{'foo':'bar'}")
665
+ end
666
+
542
667
  it "configures sets the bootstrap's run_list" do
543
668
  expect(@bootstrap.config[:run_list]).to eq(['role[base]'])
544
669
  end
@@ -613,7 +738,7 @@ describe Chef::Knife::Ec2ServerCreate do
613
738
  expect(@bootstrap.config[:forward_agent]).to eq(true)
614
739
  end
615
740
  end
616
-
741
+
617
742
  describe "when configuring the winrm bootstrap process for windows" do
618
743
  before do
619
744
  allow(@knife_ec2_create).to receive(:fetch_server_fqdn).and_return("SERVERNAME")
@@ -628,8 +753,8 @@ describe Chef::Knife::Ec2ServerCreate do
628
753
  @knife_ec2_create.config[:template_file] = '~/.chef/templates/my-bootstrap.sh.erb'
629
754
  @knife_ec2_create.config[:distro] = 'ubuntu-10.04-magic-sparkles'
630
755
  @knife_ec2_create.config[:run_list] = ['role[base]']
631
- @knife_ec2_create.config[:json_attributes] = "{'my_attributes':{'foo':'bar'}"
632
- @knife_ec2_create.config[:winrm_ssl_verify_mode] = 'basic'
756
+ @knife_ec2_create.config[:first_boot_attributes] = "{'my_attributes':{'foo':'bar'}"
757
+ @knife_ec2_create.config[:winrm_ssl_verify_mode] = 'verify_peer'
633
758
  @knife_ec2_create.config[:msi_url] = 'https://opscode-omnibus-packages.s3.amazonaws.com/windows/2008r2/x86_64/chef-client-12.3.0-1.msi'
634
759
  @knife_ec2_create.config[:install_as_service] = true
635
760
  @knife_ec2_create.config[:session_timeout] = "90"
@@ -679,7 +804,7 @@ describe Chef::Knife::Ec2ServerCreate do
679
804
  end
680
805
 
681
806
  it "should set the bootstrap 'winrm_ssl_verify_mode' correctly" do
682
- expect(@bootstrap.config[:winrm_ssl_verify_mode]).to eq("basic")
807
+ expect(@bootstrap.config[:winrm_ssl_verify_mode]).to eq("verify_peer")
683
808
  end
684
809
 
685
810
  it "should set the bootstrap 'msi_url' correctly" do
@@ -764,7 +889,75 @@ describe Chef::Knife::Ec2ServerCreate do
764
889
  @knife_ec2_create.validate!
765
890
  expect(Chef::Config[:knife][:aws_access_key_id]).to eq(@access_key_id)
766
891
  expect(Chef::Config[:knife][:aws_secret_access_key]).to eq(@secret_key)
767
- end
892
+ end
893
+
894
+ context "when invalid --aws-profile is given" do
895
+ it "raises exception" do
896
+ Chef::Config[:knife][:aws_profile] = 'xyz'
897
+ allow(File).to receive(:read).and_return("[default]\naws_access_key_id=TESTKEY\r\naws_secret_access_key=TESTSECRET")
898
+ expect{ @knife_ec2_create.validate! }.to raise_error("The provided --aws-profile 'xyz' is invalid.")
899
+ end
900
+ end
901
+ end
902
+
903
+
904
+ describe "when reading aws_config_file" do
905
+ before do
906
+ Chef::Config[:knife][:aws_config_file] = '/apple/pear'
907
+ @region = 'region'
908
+ end
909
+
910
+ it "reads UNIX Line endings" do
911
+ allow(File).to receive(:read).
912
+ and_return("[default]\r\nregion=#{@region}")
913
+ @knife_ec2_create.validate!
914
+ expect(Chef::Config[:knife][:region]).to eq(@region)
915
+ end
916
+
917
+ it "reads DOS Line endings" do
918
+ allow(File).to receive(:read).
919
+ and_return("[default]\r\nregion=#{@region}")
920
+ @knife_ec2_create.validate!
921
+ expect(Chef::Config[:knife][:region]).to eq(@region)
922
+ end
923
+ it "reads UNIX Line endings for new format" do
924
+ allow(File).to receive(:read).
925
+ and_return("[default]\nregion=#{@region}")
926
+ @knife_ec2_create.validate!
927
+ expect(Chef::Config[:knife][:region]).to eq(@region)
928
+ end
929
+
930
+ it "reads DOS Line endings for new format" do
931
+ allow(File).to receive(:read).
932
+ and_return("[default]\nregion=#{@region}")
933
+ @knife_ec2_create.validate!
934
+ expect(Chef::Config[:knife][:region]).to eq(@region)
935
+ end
936
+
937
+ it "loads the correct profile" do
938
+ Chef::Config[:knife][:aws_profile] = 'other'
939
+ allow(File).to receive(:read).
940
+ and_return("[default]\nregion=TESTREGION\n\n[profile other]\nregion=#{@region}")
941
+ @knife_ec2_create.validate!
942
+ expect(Chef::Config[:knife][:region]).to eq(@region)
943
+ end
944
+
945
+ context "when invalid --aws-profile is given" do
946
+ it "raises exception" do
947
+ Chef::Config[:knife][:aws_profile] = 'xyz'
948
+ allow(File).to receive(:read).and_return("[default]\nregion=TESTREGION")
949
+ expect{ @knife_ec2_create.validate! }.to raise_error("The provided --aws-profile 'profile xyz' is invalid.")
950
+ end
951
+ end
952
+
953
+ context "when aws_profile is passed a 'default' from CLI or knife.rb file" do
954
+ it 'loads the default profile successfully' do
955
+ Chef::Config[:knife][:aws_profile] = 'default'
956
+ allow(File).to receive(:read).and_return("[default]\nregion=#{@region}\n\n[profile other]\nregion=TESTREGION")
957
+ @knife_ec2_create.validate!
958
+ expect(Chef::Config[:knife][:region]).to eq(@region)
959
+ end
960
+ end
768
961
  end
769
962
 
770
963
  it 'understands that file:// validation key URIs are just paths' do
@@ -782,10 +975,33 @@ describe Chef::Knife::Ec2ServerCreate do
782
975
  end
783
976
 
784
977
  it "disallows security group names when using a VPC" do
785
- @knife_ec2_create.config[:subnet_id] = 'subnet-1a2b3c4d'
978
+ @knife_ec2_create.config[:subnet_id] = @subnet_1_id
979
+ @knife_ec2_create.config[:security_group_ids] = 'sg-aabbccdd'
980
+ @knife_ec2_create.config[:security_groups] = 'groupname'
981
+
982
+ allow(@ec2_connection).to receive_message_chain(:subnets, :get).with(@subnet_1_id).and_return(@subnet_1)
983
+
984
+ expect { @knife_ec2_create.validate! }.to raise_error(SystemExit)
985
+ end
986
+
987
+ it 'disallows invalid network interface ids' do
988
+ @knife_ec2_create.config[:network_interfaces] = ['INVALID_ID']
989
+
990
+ expect { @knife_ec2_create.validate! }.to raise_error(SystemExit)
991
+ end
992
+
993
+ it 'disallows network interfaces not in the right VPC' do
994
+ @knife_ec2_create.config[:subnet_id] = @subnet_1_id
786
995
  @knife_ec2_create.config[:security_group_ids] = 'sg-aabbccdd'
787
996
  @knife_ec2_create.config[:security_groups] = 'groupname'
788
997
 
998
+ allow(@ec2_connection).to receive_message_chain(:subnets, :get).with(@subnet_1_id).and_return(@subnet_1)
999
+
1000
+ allow(@ec2_connection).to receive_message_chain(:network_interfaces, :all).and_return [
1001
+ double('network_interfaces', network_interface_id: 'eni-12345678', vpc_id: 'another_vpc'),
1002
+ double('network_interfaces', network_interface_id: 'eni-87654321', vpc_id: @my_vpc)
1003
+ ]
1004
+
789
1005
  expect { @knife_ec2_create.validate! }.to raise_error SystemExit
790
1006
  end
791
1007
 
@@ -809,6 +1025,23 @@ describe Chef::Knife::Ec2ServerCreate do
809
1025
  expect { @knife_ec2_create.validate! }.to raise_error SystemExit
810
1026
  end
811
1027
 
1028
+ it "disallows setting only one of the two ClassicLink options" do
1029
+ @knife_ec2_create.config[:classic_link_vpc_id] = @vpc_id
1030
+ @knife_ec2_create.config[:classic_link_vpc_security_group_ids] = nil
1031
+
1032
+ expect { @knife_ec2_create.validate! }.to raise_error SystemExit
1033
+ end
1034
+
1035
+ it "disallows ClassicLink with VPC" do
1036
+ @knife_ec2_create.config[:subnet_id] = 'subnet-1a2b3c4d'
1037
+ @knife_ec2_create.config[:classic_link_vpc_id] = @vpc_id
1038
+ @knife_ec2_create.config[:classic_link_vpc_security_group_ids] = @vpc_security_group_ids
1039
+
1040
+ allow(@knife_ec2_create).to receive(:validate_nics!).and_return(true)
1041
+
1042
+ expect { @knife_ec2_create.validate! }.to raise_error SystemExit
1043
+ end
1044
+
812
1045
  it "disallows ebs provisioned iops option when not using ebs volume type" do
813
1046
  @knife_ec2_create.config[:ebs_provisioned_iops] = "123"
814
1047
  @knife_ec2_create.config[:ebs_volume_type] = nil
@@ -1151,8 +1384,8 @@ describe Chef::Knife::Ec2ServerCreate do
1151
1384
  describe "ssh_connect_host" do
1152
1385
  before(:each) do
1153
1386
  allow(@new_ec2_server).to receive_messages(
1154
- :dns_name => 'public_name',
1155
- :private_ip_address => 'private_ip',
1387
+ :dns_name => 'public.example.org',
1388
+ :private_ip_address => '192.168.1.100',
1156
1389
  :custom => 'custom',
1157
1390
  :public_ip_address => '111.111.111.111'
1158
1391
  )
@@ -1161,7 +1394,7 @@ describe Chef::Knife::Ec2ServerCreate do
1161
1394
 
1162
1395
  describe "by default" do
1163
1396
  it 'should use public dns name' do
1164
- expect(@knife_ec2_create.ssh_connect_host).to eq('public_name')
1397
+ expect(@knife_ec2_create.ssh_connect_host).to eq('public.example.org')
1165
1398
  end
1166
1399
  end
1167
1400
 
@@ -1172,10 +1405,29 @@ describe Chef::Knife::Ec2ServerCreate do
1172
1405
  end
1173
1406
  end
1174
1407
 
1175
- describe "with vpc_mode?" do
1176
- it 'should use private ip' do
1408
+ context "when vpc_mode? is true" do
1409
+ before do
1177
1410
  allow(@knife_ec2_create).to receive_messages(:vpc_mode? => true)
1178
- expect(@knife_ec2_create.ssh_connect_host).to eq('private_ip')
1411
+ end
1412
+
1413
+ context "--associate-public-ip is specified" do
1414
+ it "uses the dns_name or public_ip_address" do
1415
+ @knife_ec2_create.config[:associate_public_ip] = true
1416
+ expect(@knife_ec2_create.ssh_connect_host).to eq('public.example.org')
1417
+ end
1418
+ end
1419
+
1420
+ context "--associate-eip is specified" do
1421
+ it "uses the dns_name or public_ip_address" do
1422
+ @knife_ec2_create.config[:associate_eip] = '111.111.111.111'
1423
+ expect(@knife_ec2_create.ssh_connect_host).to eq('public.example.org')
1424
+ end
1425
+ end
1426
+
1427
+ context "with no other ip flags" do
1428
+ it 'uses private_ip_address' do
1429
+ expect(@knife_ec2_create.ssh_connect_host).to eq('192.168.1.100')
1430
+ end
1179
1431
  end
1180
1432
  end
1181
1433
 
@@ -1278,4 +1530,663 @@ describe Chef::Knife::Ec2ServerCreate do
1278
1530
  expect(@knife_ec2_create.tcp_test_ssh("blackhole.ninja", 22)).to be_falsey
1279
1531
  end
1280
1532
  end
1533
+
1534
+ describe 'ssl_config_user_data' do
1535
+ before do
1536
+ @knife_ec2_create.config[:winrm_password] = "ec2@123"
1537
+ end
1538
+
1539
+ context 'For domain user' do
1540
+ before do
1541
+ @knife_ec2_create.config[:winrm_user] = "domain\\ec2"
1542
+ @ssl_config_data = <<-EOH
1543
+
1544
+ If (-Not (Get-Service WinRM | Where-Object {$_.status -eq "Running"})) {
1545
+ winrm quickconfig -q
1546
+ }
1547
+ If (winrm e winrm/config/listener | Select-String -Pattern " Transport = HTTP\\b" -Quiet) {
1548
+ winrm delete winrm/config/listener?Address=*+Transport=HTTP
1549
+ }
1550
+ $vm_name = invoke-restmethod -uri http://169.254.169.254/latest/meta-data/public-ipv4
1551
+ New-SelfSignedCertificate -certstorelocation cert:\\localmachine\\my -dnsname $vm_name
1552
+ $thumbprint = (Get-ChildItem -Path cert:\\localmachine\\my | Where-Object {$_.Subject -match "$vm_name"}).Thumbprint;
1553
+ $create_listener_cmd = "winrm create winrm/config/Listener?Address=*+Transport=HTTPS '@{Hostname=`"$vm_name`";CertificateThumbprint=`"$thumbprint`"}'"
1554
+ iex $create_listener_cmd
1555
+
1556
+ netsh advfirewall firewall add rule name="WinRM HTTPS" protocol=TCP dir=in Localport=5986 remoteport=any action=allow localip=any remoteip=any profile=any enable=yes
1557
+
1558
+ EOH
1559
+ end
1560
+
1561
+ it 'gets ssl config user data' do
1562
+ expect(@knife_ec2_create.ssl_config_user_data).to be == @ssl_config_data
1563
+ end
1564
+ end
1565
+
1566
+ context 'For local user' do
1567
+ before do
1568
+ @knife_ec2_create.config[:winrm_user] = ".\\ec2"
1569
+ @ssl_config_data = <<-EOH
1570
+ net user /add ec2 ec2@123;
1571
+ net localgroup Administrators /add ec2;
1572
+
1573
+ If (-Not (Get-Service WinRM | Where-Object {$_.status -eq "Running"})) {
1574
+ winrm quickconfig -q
1575
+ }
1576
+ If (winrm e winrm/config/listener | Select-String -Pattern " Transport = HTTP\\b" -Quiet) {
1577
+ winrm delete winrm/config/listener?Address=*+Transport=HTTP
1578
+ }
1579
+ $vm_name = invoke-restmethod -uri http://169.254.169.254/latest/meta-data/public-ipv4
1580
+ New-SelfSignedCertificate -certstorelocation cert:\\localmachine\\my -dnsname $vm_name
1581
+ $thumbprint = (Get-ChildItem -Path cert:\\localmachine\\my | Where-Object {$_.Subject -match "$vm_name"}).Thumbprint;
1582
+ $create_listener_cmd = "winrm create winrm/config/Listener?Address=*+Transport=HTTPS '@{Hostname=`"$vm_name`";CertificateThumbprint=`"$thumbprint`"}'"
1583
+ iex $create_listener_cmd
1584
+
1585
+ netsh advfirewall firewall add rule name="WinRM HTTPS" protocol=TCP dir=in Localport=5986 remoteport=any action=allow localip=any remoteip=any profile=any enable=yes
1586
+
1587
+ EOH
1588
+
1589
+ end
1590
+
1591
+ it 'gets ssl config user data' do
1592
+ expect(@knife_ec2_create.ssl_config_user_data).to be == @ssl_config_data
1593
+ end
1594
+ end
1595
+ end
1596
+
1597
+ describe 'ssl_config_data_already_exist?' do
1598
+
1599
+ before(:each) do
1600
+ @user_user_data = 'user_user_data.ps1'
1601
+ @knife_ec2_create.config[:winrm_user] = "domain\\ec2"
1602
+ @knife_ec2_create.config[:winrm_password] = "ec2@123"
1603
+ @knife_ec2_create.config[:aws_user_data] = @user_user_data
1604
+ end
1605
+
1606
+ context 'ssl config data does not exist in user supplied user_data' do
1607
+ before do
1608
+ File.open(@user_user_data,"w+") do |f|
1609
+ f.write <<-EOH
1610
+ user_command_1\\\\user_command_2\\\\user_command_3
1611
+ user_command_4
1612
+ EOH
1613
+ end
1614
+ end
1615
+
1616
+ it 'returns false' do
1617
+ expect(@knife_ec2_create.ssl_config_data_already_exist?).to eq(false)
1618
+ end
1619
+ end
1620
+
1621
+ context 'ssl config data already exist in user supplied user_data' do
1622
+ before do
1623
+ File.open(@user_user_data,"w+") do |f|
1624
+ f.write <<-EOH
1625
+ user_command_1
1626
+ user_command_2
1627
+
1628
+ <powershell>
1629
+
1630
+ If (-Not (Get-Service WinRM | Where-Object {$_.status -eq "Running"})) {
1631
+ winrm quickconfig -q
1632
+ }
1633
+ If (winrm e winrm/config/listener | Select-String -Pattern " Transport = HTTP\\b" -Quiet) {
1634
+ winrm delete winrm/config/listener?Address=*+Transport=HTTP
1635
+ }
1636
+ $vm_name = invoke-restmethod -uri http://169.254.169.254/latest/meta-data/public-ipv4
1637
+ New-SelfSignedCertificate -certstorelocation cert:\\localmachine\\my -dnsname $vm_name
1638
+ $thumbprint = (Get-ChildItem -Path cert:\\localmachine\\my | Where-Object {$_.Subject -match "$vm_name"}).Thumbprint;
1639
+ $create_listener_cmd = "winrm create winrm/config/Listener?Address=*+Transport=HTTPS '@{Hostname=`"$vm_name`";CertificateThumbprint=`"$thumbprint`"}'"
1640
+ iex $create_listener_cmd
1641
+
1642
+ netsh advfirewall firewall add rule name="WinRM HTTPS" protocol=TCP dir=in Localport=5986 remoteport=any action=allow localip=any remoteip=any profile=any enable=yes
1643
+
1644
+ </powershell>
1645
+
1646
+ EOH
1647
+ end
1648
+ end
1649
+
1650
+ it 'returns false' do
1651
+ expect(@knife_ec2_create.ssl_config_data_already_exist?).to eq(true)
1652
+ end
1653
+ end
1654
+
1655
+ after(:each) do
1656
+ @knife_ec2_create.config.delete(:aws_user_data)
1657
+ FileUtils.rm_rf @user_user_data
1658
+ end
1659
+ end
1660
+
1661
+ describe 'attach ssl config into user data when transport is ssl' do
1662
+ before(:each) do
1663
+ allow(Fog::Compute::AWS).to receive(:new).and_return(@ec2_connection)
1664
+ Chef::Config[:knife][:ssh_key_name] = "mykey"
1665
+ @knife_ec2_create.config[:ssh_key_name] = "ssh_key_name"
1666
+ @knife_ec2_create.config[:winrm_transport] = "ssl"
1667
+ @knife_ec2_create.config[:create_ssl_listener] = true
1668
+ @knife_ec2_create.config[:winrm_user] = "domain\\ec2"
1669
+ @knife_ec2_create.config[:winrm_password] = "ec2@123"
1670
+ end
1671
+
1672
+ context 'when user_data script provided by user contains only <script> section' do
1673
+ before do
1674
+ @user_user_data = 'user_user_data.ps1'
1675
+ File.open(@user_user_data,"w+") do |f|
1676
+ f.write <<-EOH
1677
+ <script>
1678
+
1679
+ ipconfig > c:\\ipconfig_data.txt
1680
+
1681
+ </script>
1682
+ EOH
1683
+ end
1684
+ @server_def_user_data = <<-EOH
1685
+ <script>
1686
+
1687
+ ipconfig > c:\\ipconfig_data.txt
1688
+
1689
+ </script>
1690
+
1691
+
1692
+ <powershell>
1693
+
1694
+ If (-Not (Get-Service WinRM | Where-Object {$_.status -eq "Running"})) {
1695
+ winrm quickconfig -q
1696
+ }
1697
+ If (winrm e winrm/config/listener | Select-String -Pattern " Transport = HTTP\\b" -Quiet) {
1698
+ winrm delete winrm/config/listener?Address=*+Transport=HTTP
1699
+ }
1700
+ $vm_name = invoke-restmethod -uri http://169.254.169.254/latest/meta-data/public-ipv4
1701
+ New-SelfSignedCertificate -certstorelocation cert:\\localmachine\\my -dnsname $vm_name
1702
+ $thumbprint = (Get-ChildItem -Path cert:\\localmachine\\my | Where-Object {$_.Subject -match "$vm_name"}).Thumbprint;
1703
+ $create_listener_cmd = "winrm create winrm/config/Listener?Address=*+Transport=HTTPS '@{Hostname=`"$vm_name`";CertificateThumbprint=`"$thumbprint`"}'"
1704
+ iex $create_listener_cmd
1705
+
1706
+ netsh advfirewall firewall add rule name="WinRM HTTPS" protocol=TCP dir=in Localport=5986 remoteport=any action=allow localip=any remoteip=any profile=any enable=yes
1707
+
1708
+ </powershell>
1709
+ EOH
1710
+ @knife_ec2_create.config[:aws_user_data] = @user_user_data
1711
+ end
1712
+
1713
+ it "appends ssl config to user supplied user_data after <script> tag section" do
1714
+ server_def = @knife_ec2_create.create_server_def
1715
+
1716
+ expect(server_def[:user_data]).to eq(@server_def_user_data)
1717
+ end
1718
+
1719
+ after do
1720
+ @knife_ec2_create.config.delete(:aws_user_data)
1721
+ FileUtils.rm_rf @user_user_data
1722
+ end
1723
+ end
1724
+
1725
+ context 'when user_data script provided by user contains <powershell> section' do
1726
+ before do
1727
+ @user_user_data = 'user_user_data.ps1'
1728
+ File.open(@user_user_data,"w+") do |f|
1729
+ f.write <<-EOH
1730
+ <powershell>
1731
+
1732
+ Get-DscLocalConfigurationManager > c:\\dsc_data.txt
1733
+ </powershell>
1734
+ EOH
1735
+ end
1736
+ @server_def_user_data = <<-EOH
1737
+ <powershell>
1738
+
1739
+ Get-DscLocalConfigurationManager > c:\\dsc_data.txt
1740
+
1741
+ If (-Not (Get-Service WinRM | Where-Object {$_.status -eq "Running"})) {
1742
+ winrm quickconfig -q
1743
+ }
1744
+ If (winrm e winrm/config/listener | Select-String -Pattern " Transport = HTTP\\b" -Quiet) {
1745
+ winrm delete winrm/config/listener?Address=*+Transport=HTTP
1746
+ }
1747
+ $vm_name = invoke-restmethod -uri http://169.254.169.254/latest/meta-data/public-ipv4
1748
+ New-SelfSignedCertificate -certstorelocation cert:\\localmachine\\my -dnsname $vm_name
1749
+ $thumbprint = (Get-ChildItem -Path cert:\\localmachine\\my | Where-Object {$_.Subject -match "$vm_name"}).Thumbprint;
1750
+ $create_listener_cmd = "winrm create winrm/config/Listener?Address=*+Transport=HTTPS '@{Hostname=`"$vm_name`";CertificateThumbprint=`"$thumbprint`"}'"
1751
+ iex $create_listener_cmd
1752
+
1753
+ netsh advfirewall firewall add rule name="WinRM HTTPS" protocol=TCP dir=in Localport=5986 remoteport=any action=allow localip=any remoteip=any profile=any enable=yes
1754
+
1755
+ </powershell>
1756
+ EOH
1757
+ @knife_ec2_create.config[:aws_user_data] = @user_user_data
1758
+ end
1759
+
1760
+ it "appends ssl config to user supplied user_data at the end of <powershell> tag section" do
1761
+ server_def = @knife_ec2_create.create_server_def
1762
+
1763
+ expect(server_def[:user_data]).to eq(@server_def_user_data)
1764
+ end
1765
+
1766
+ after do
1767
+ @knife_ec2_create.config.delete(:aws_user_data)
1768
+ FileUtils.rm_rf @user_user_data
1769
+ end
1770
+ end
1771
+
1772
+ context 'when user_data script provided by user already contains ssl config code' do
1773
+ before do
1774
+ @user_user_data = 'user_user_data.ps1'
1775
+ File.open(@user_user_data,"w+") do |f|
1776
+ f.write <<-EOH
1777
+ <powershell>
1778
+
1779
+ Get-DscLocalConfigurationManager > c:\\dsc_data.txt
1780
+
1781
+ If (-Not (Get-Service WinRM | Where-Object {$_.status -eq "Running"})) {
1782
+ winrm quickconfig -q
1783
+ }
1784
+ If (winrm e winrm/config/listener | Select-String -Pattern " Transport = HTTP\\b" -Quiet) {
1785
+ winrm delete winrm/config/listener?Address=*+Transport=HTTP
1786
+ }
1787
+ $vm_name = invoke-restmethod -uri http://169.254.169.254/latest/meta-data/public-ipv4
1788
+ New-SelfSignedCertificate -certstorelocation cert:\\localmachine\\my -dnsname $vm_name
1789
+ $thumbprint = (Get-ChildItem -Path cert:\\localmachine\\my | Where-Object {$_.Subject -match "$vm_name"}).Thumbprint;
1790
+ $create_listener_cmd = "winrm create winrm/config/Listener?Address=*+Transport=HTTPS '@{Hostname=`"$vm_name`";CertificateThumbprint=`"$thumbprint`"}'"
1791
+ iex $create_listener_cmd
1792
+
1793
+ netsh advfirewall firewall add rule name="WinRM HTTPS" protocol=TCP dir=in Localport=5986 remoteport=any action=allow localip=any remoteip=any profile=any enable=yes
1794
+
1795
+ </powershell>
1796
+ EOH
1797
+ end
1798
+ @server_def_user_data = <<-EOH
1799
+ <powershell>
1800
+
1801
+ Get-DscLocalConfigurationManager > c:\\dsc_data.txt
1802
+
1803
+ If (-Not (Get-Service WinRM | Where-Object {$_.status -eq "Running"})) {
1804
+ winrm quickconfig -q
1805
+ }
1806
+ If (winrm e winrm/config/listener | Select-String -Pattern " Transport = HTTP\\b" -Quiet) {
1807
+ winrm delete winrm/config/listener?Address=*+Transport=HTTP
1808
+ }
1809
+ $vm_name = invoke-restmethod -uri http://169.254.169.254/latest/meta-data/public-ipv4
1810
+ New-SelfSignedCertificate -certstorelocation cert:\\localmachine\\my -dnsname $vm_name
1811
+ $thumbprint = (Get-ChildItem -Path cert:\\localmachine\\my | Where-Object {$_.Subject -match "$vm_name"}).Thumbprint;
1812
+ $create_listener_cmd = "winrm create winrm/config/Listener?Address=*+Transport=HTTPS '@{Hostname=`"$vm_name`";CertificateThumbprint=`"$thumbprint`"}'"
1813
+ iex $create_listener_cmd
1814
+
1815
+ netsh advfirewall firewall add rule name="WinRM HTTPS" protocol=TCP dir=in Localport=5986 remoteport=any action=allow localip=any remoteip=any profile=any enable=yes
1816
+
1817
+ </powershell>
1818
+ EOH
1819
+ @knife_ec2_create.config[:aws_user_data] = @user_user_data
1820
+ end
1821
+
1822
+ it "does no modifications and passes user_data as it is to server_def" do
1823
+ server_def = @knife_ec2_create.create_server_def
1824
+
1825
+ expect(server_def[:user_data]).to eq(@server_def_user_data)
1826
+ end
1827
+
1828
+ after do
1829
+ @knife_ec2_create.config.delete(:aws_user_data)
1830
+ FileUtils.rm_rf @user_user_data
1831
+ end
1832
+ end
1833
+
1834
+ context 'when user_data script provided by user has invalid syntax' do
1835
+ before do
1836
+ @user_user_data = 'user_user_data.ps1'
1837
+ File.open(@user_user_data,"w+") do |f|
1838
+ f.write <<-EOH
1839
+ <powershell>
1840
+
1841
+ Get-DscLocalConfigurationManager > c:\\dsc_data.txt
1842
+
1843
+ <script>
1844
+
1845
+ ipconfig > c:\\ipconfig_data.txt
1846
+
1847
+ </script>
1848
+ EOH
1849
+ end
1850
+ @knife_ec2_create.config[:aws_user_data] = @user_user_data
1851
+ end
1852
+
1853
+ it "gives error and exits" do
1854
+ expect(@knife_ec2_create.ui).to receive(:error).with("Provided user_data file is invalid.")
1855
+ expect { @knife_ec2_create.create_server_def }.to raise_error SystemExit
1856
+ end
1857
+
1858
+ after do
1859
+ @knife_ec2_create.config.delete(:aws_user_data)
1860
+ FileUtils.rm_rf @user_user_data
1861
+ end
1862
+ end
1863
+
1864
+ context 'when user_data script provided by user has <powershell> and <script> tag sections' do
1865
+ before do
1866
+ @user_user_data = 'user_user_data.ps1'
1867
+ File.open(@user_user_data,"w+") do |f|
1868
+ f.write <<-EOH
1869
+ <powershell>
1870
+
1871
+ Get-DscLocalConfigurationManager > c:\\dsc_data.txt
1872
+
1873
+ </powershell>
1874
+ <script>
1875
+
1876
+ ipconfig > c:\\ipconfig_data.txt
1877
+
1878
+ </script>
1879
+ EOH
1880
+ end
1881
+ @server_def_user_data = <<-EOH
1882
+ <powershell>
1883
+
1884
+ Get-DscLocalConfigurationManager > c:\\dsc_data.txt
1885
+
1886
+
1887
+ If (-Not (Get-Service WinRM | Where-Object {$_.status -eq "Running"})) {
1888
+ winrm quickconfig -q
1889
+ }
1890
+ If (winrm e winrm/config/listener | Select-String -Pattern " Transport = HTTP\\b" -Quiet) {
1891
+ winrm delete winrm/config/listener?Address=*+Transport=HTTP
1892
+ }
1893
+ $vm_name = invoke-restmethod -uri http://169.254.169.254/latest/meta-data/public-ipv4
1894
+ New-SelfSignedCertificate -certstorelocation cert:\\localmachine\\my -dnsname $vm_name
1895
+ $thumbprint = (Get-ChildItem -Path cert:\\localmachine\\my | Where-Object {$_.Subject -match "$vm_name"}).Thumbprint;
1896
+ $create_listener_cmd = "winrm create winrm/config/Listener?Address=*+Transport=HTTPS '@{Hostname=`"$vm_name`";CertificateThumbprint=`"$thumbprint`"}'"
1897
+ iex $create_listener_cmd
1898
+
1899
+ netsh advfirewall firewall add rule name="WinRM HTTPS" protocol=TCP dir=in Localport=5986 remoteport=any action=allow localip=any remoteip=any profile=any enable=yes
1900
+
1901
+ </powershell>
1902
+ <script>
1903
+
1904
+ ipconfig > c:\\ipconfig_data.txt
1905
+
1906
+ </script>
1907
+ EOH
1908
+ @knife_ec2_create.config[:aws_user_data] = @user_user_data
1909
+ end
1910
+
1911
+ it "appends ssl config to user supplied user_data at the end of <powershell> tag section" do
1912
+ server_def = @knife_ec2_create.create_server_def
1913
+
1914
+ expect(server_def[:user_data]).to eq(@server_def_user_data)
1915
+ end
1916
+
1917
+ after do
1918
+ @knife_ec2_create.config.delete(:aws_user_data)
1919
+ FileUtils.rm_rf @user_user_data
1920
+ end
1921
+ end
1922
+
1923
+ context "when user_data is not supplied by user on cli" do
1924
+ before do
1925
+ @server_def_user_data = <<-EOH
1926
+ <powershell>
1927
+
1928
+ If (-Not (Get-Service WinRM | Where-Object {$_.status -eq "Running"})) {
1929
+ winrm quickconfig -q
1930
+ }
1931
+ If (winrm e winrm/config/listener | Select-String -Pattern " Transport = HTTP\\b" -Quiet) {
1932
+ winrm delete winrm/config/listener?Address=*+Transport=HTTP
1933
+ }
1934
+ $vm_name = invoke-restmethod -uri http://169.254.169.254/latest/meta-data/public-ipv4
1935
+ New-SelfSignedCertificate -certstorelocation cert:\\localmachine\\my -dnsname $vm_name
1936
+ $thumbprint = (Get-ChildItem -Path cert:\\localmachine\\my | Where-Object {$_.Subject -match "$vm_name"}).Thumbprint;
1937
+ $create_listener_cmd = "winrm create winrm/config/Listener?Address=*+Transport=HTTPS '@{Hostname=`"$vm_name`";CertificateThumbprint=`"$thumbprint`"}'"
1938
+ iex $create_listener_cmd
1939
+
1940
+ netsh advfirewall firewall add rule name="WinRM HTTPS" protocol=TCP dir=in Localport=5986 remoteport=any action=allow localip=any remoteip=any profile=any enable=yes
1941
+
1942
+ </powershell>
1943
+ EOH
1944
+ end
1945
+
1946
+ it "creates user_data only with default ssl configuration" do
1947
+ server_def = @knife_ec2_create.create_server_def
1948
+
1949
+ expect(server_def[:user_data]).to eq(@server_def_user_data)
1950
+ end
1951
+ end
1952
+
1953
+ context "when user has specified --no-create-ssl-listener along with his/her own user_data on cli" do
1954
+ before do
1955
+ @knife_ec2_create.config[:create_ssl_listener] = false
1956
+ @user_user_data = 'user_user_data.ps1'
1957
+ File.open(@user_user_data,"w+") do |f|
1958
+ f.write <<-EOH
1959
+ <powershell>
1960
+
1961
+ Get-DscLocalConfigurationManager > c:\\dsc_data.txt
1962
+
1963
+ </powershell>
1964
+ <script>
1965
+
1966
+ ipconfig > c:\\ipconfig_data.txt
1967
+
1968
+ </script>
1969
+ EOH
1970
+ end
1971
+ @server_def_user_data = <<-EOH
1972
+ <powershell>
1973
+
1974
+ Get-DscLocalConfigurationManager > c:\\dsc_data.txt
1975
+
1976
+ </powershell>
1977
+ <script>
1978
+
1979
+ ipconfig > c:\\ipconfig_data.txt
1980
+
1981
+ </script>
1982
+ EOH
1983
+ @knife_ec2_create.config[:aws_user_data] = @user_user_data
1984
+ end
1985
+
1986
+ it "does not attach ssl config into the user_data supplied by user on cli" do
1987
+ server_def = @knife_ec2_create.create_server_def
1988
+
1989
+ expect(server_def[:user_data]).to eq(@server_def_user_data)
1990
+ end
1991
+
1992
+ after do
1993
+ @knife_ec2_create.config.delete(:aws_user_data)
1994
+ FileUtils.rm_rf @user_user_data
1995
+ end
1996
+ end
1997
+
1998
+ context "when user has specified --no-create-ssl-listener with no user_data on cli" do
1999
+ before do
2000
+ @knife_ec2_create.config[:create_ssl_listener] = false
2001
+ @server_def_user_data = nil
2002
+ end
2003
+
2004
+ it "creates nil or empty user_data" do
2005
+ server_def = @knife_ec2_create.create_server_def
2006
+
2007
+ expect(server_def[:user_data]).to eq(@server_def_user_data)
2008
+ end
2009
+ end
2010
+
2011
+ after(:each) do
2012
+ @knife_ec2_create.config.delete(:ssh_key_name)
2013
+ Chef::Config[:knife].delete(:ssh_key_name)
2014
+ @knife_ec2_create.config.delete(:winrm_transport)
2015
+ @knife_ec2_create.config.delete(:create_ssl_listener)
2016
+ end
2017
+ end
2018
+
2019
+ describe "do not attach ssl config into user data when transport is plaintext" do
2020
+ before(:each) do
2021
+ allow(Fog::Compute::AWS).to receive(:new).and_return(@ec2_connection)
2022
+ Chef::Config[:knife][:ssh_key_name] = "mykey"
2023
+ @knife_ec2_create.config[:ssh_key_name] = "ssh_key_name"
2024
+ @knife_ec2_create.config[:winrm_transport] = "plaintext"
2025
+ end
2026
+
2027
+ context "when user_data is supplied on cli" do
2028
+ before do
2029
+ @user_user_data = 'user_user_data.ps1'
2030
+ File.open(@user_user_data,"w+") do |f|
2031
+ f.write <<-EOH
2032
+ <script>
2033
+
2034
+ ipconfig > c:\\ipconfig_data.txt
2035
+ netstat > c:\\netstat_data.txt
2036
+
2037
+ </script>
2038
+ EOH
2039
+ end
2040
+ @knife_ec2_create.config[:aws_user_data] = @user_user_data
2041
+ @server_def_user_data = <<-EOH
2042
+ <script>
2043
+
2044
+ ipconfig > c:\\ipconfig_data.txt
2045
+ netstat > c:\\netstat_data.txt
2046
+
2047
+ </script>
2048
+ EOH
2049
+ end
2050
+
2051
+ it "user_data is created only with user's user_data" do
2052
+ server_def = @knife_ec2_create.create_server_def
2053
+
2054
+ expect(server_def[:user_data]).to eq(@server_def_user_data)
2055
+ end
2056
+
2057
+ after do
2058
+ @knife_ec2_create.config.delete(:aws_user_data)
2059
+ FileUtils.rm_rf @user_user_data
2060
+ end
2061
+ end
2062
+
2063
+ context "when user_data is not supplied on cli" do
2064
+ before do
2065
+ @server_def_user_data = nil
2066
+ end
2067
+
2068
+ it "creates nil or empty user_data" do
2069
+ server_def = @knife_ec2_create.create_server_def
2070
+
2071
+ expect(server_def[:user_data]).to eq(@server_def_user_data)
2072
+ end
2073
+ end
2074
+
2075
+ after(:each) do
2076
+ @knife_ec2_create.config.delete(:ssh_key_name)
2077
+ Chef::Config[:knife].delete(:ssh_key_name)
2078
+ @knife_ec2_create.config.delete(:winrm_transport)
2079
+ end
2080
+ end
2081
+
2082
+ describe 'disable_api_termination option' do
2083
+ context 'spot instance' do
2084
+ context 'disable_api_termination is not passed on CLI or in knife config' do
2085
+ before do
2086
+ allow(Fog::Compute::AWS).to receive(:new).and_return(@ec2_connection)
2087
+ @knife_ec2_create.config[:spot_price] = 0.001
2088
+ end
2089
+
2090
+ it "does not set disable_api_termination option in server_def" do
2091
+ server_def = @knife_ec2_create.create_server_def
2092
+ expect(server_def[:disable_api_termination]).to be == nil
2093
+ end
2094
+
2095
+ it "does not raise error" do
2096
+ expect(@knife_ec2_create.ui).to_not receive(:error).with(
2097
+ "spot-price and disable-api-termination options cannot be passed together as 'Termination Protection' cannot be enabled for spot instances."
2098
+ )
2099
+ expect { @knife_ec2_create.validate! }.to_not raise_error
2100
+ end
2101
+ end
2102
+
2103
+ context 'disable_api_termination is passed on CLI' do
2104
+ before do
2105
+ allow(Fog::Compute::AWS).to receive(:new).and_return(@ec2_connection)
2106
+ @knife_ec2_create.config[:spot_price] = 0.001
2107
+ @knife_ec2_create.config[:disable_api_termination] = true
2108
+ end
2109
+
2110
+ it "raises error" do
2111
+ expect(@knife_ec2_create.ui).to receive(:error).with(
2112
+ "spot-price and disable-api-termination options cannot be passed together as 'Termination Protection' cannot be enabled for spot instances."
2113
+ )
2114
+ expect { @knife_ec2_create.validate! }.to raise_error(SystemExit)
2115
+ end
2116
+ end
2117
+
2118
+ context 'disable_api_termination is passed in knife config' do
2119
+ before do
2120
+ allow(Fog::Compute::AWS).to receive(:new).and_return(@ec2_connection)
2121
+ @knife_ec2_create.config[:spot_price] = 0.001
2122
+ Chef::Config[:knife][:disable_api_termination] = true
2123
+ end
2124
+
2125
+ it "raises error" do
2126
+ expect(@knife_ec2_create.ui).to receive(:error).with(
2127
+ "spot-price and disable-api-termination options cannot be passed together as 'Termination Protection' cannot be enabled for spot instances."
2128
+ )
2129
+ expect { @knife_ec2_create.validate! }.to raise_error(SystemExit)
2130
+ end
2131
+ end
2132
+ end
2133
+
2134
+ context 'non-spot instance' do
2135
+ context 'when disable_api_termination option is not passed on the CLI or in the knife config' do
2136
+ before do
2137
+ allow(Fog::Compute::AWS).to receive(:new).and_return(@ec2_connection)
2138
+ end
2139
+
2140
+ it "sets disable_api_termination option in server_def with value as false" do
2141
+ server_def = @knife_ec2_create.create_server_def
2142
+ expect(server_def[:disable_api_termination]).to be == false
2143
+ end
2144
+
2145
+ it "does not raise error" do
2146
+ expect(@knife_ec2_create.ui).to_not receive(:error).with(
2147
+ "spot-price and disable-api-termination options cannot be passed together as 'Termination Protection' cannot be enabled for spot instances."
2148
+ )
2149
+ expect { @knife_ec2_create.validate! }.to_not raise_error
2150
+ end
2151
+ end
2152
+
2153
+ context "when disable_api_termination option is passed on the CLI" do
2154
+ before do
2155
+ allow(Fog::Compute::AWS).to receive(:new).and_return(@ec2_connection)
2156
+ @knife_ec2_create.config[:disable_api_termination] = true
2157
+ end
2158
+
2159
+ it "sets disable_api_termination option in server_def with value as true" do
2160
+ server_def = @knife_ec2_create.create_server_def
2161
+ expect(server_def[:disable_api_termination]).to be == true
2162
+ end
2163
+
2164
+ it "does not raise error" do
2165
+ expect(@knife_ec2_create.ui).to_not receive(:error).with(
2166
+ "spot-price and disable-api-termination options cannot be passed together as 'Termination Protection' cannot be enabled for spot instances."
2167
+ )
2168
+ expect { @knife_ec2_create.validate! }.to_not raise_error
2169
+ end
2170
+ end
2171
+
2172
+ context "when disable_api_termination option is passed in the knife config" do
2173
+ before do
2174
+ allow(Fog::Compute::AWS).to receive(:new).and_return(@ec2_connection)
2175
+ Chef::Config[:knife][:disable_api_termination] = true
2176
+ end
2177
+
2178
+ it "sets disable_api_termination option in server_def with value as true" do
2179
+ server_def = @knife_ec2_create.create_server_def
2180
+ expect(server_def[:disable_api_termination]).to be == true
2181
+ end
2182
+
2183
+ it "does not raise error" do
2184
+ expect(@knife_ec2_create.ui).to_not receive(:error).with(
2185
+ "spot-price and disable-api-termination options cannot be passed together as 'Termination Protection' cannot be enabled for spot instances."
2186
+ )
2187
+ expect { @knife_ec2_create.validate! }.to_not raise_error
2188
+ end
2189
+ end
2190
+ end
2191
+ end
1281
2192
  end