knife-ec2 0.12.0 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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