tfwrapper 0.4.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -59,6 +59,8 @@ describe TFWrapper::RakeTasks do
59
59
  expect(cls.instance_variable_get('@tf_dir')).to eq('/rake/dir/tfdir')
60
60
  expect(cls.instance_variable_get('@consul_env_vars_prefix')).to eq(nil)
61
61
  expect(cls.instance_variable_get('@tf_vars_from_env')).to eq({})
62
+ expect(cls.instance_variable_get('@allowed_empty_vars')).to eq([])
63
+ expect(cls.instance_variable_get('@tf_sensitive_vars')).to eq([])
62
64
  expect(cls.instance_variable_get('@tf_extra_vars')).to eq({})
63
65
  expect(cls.instance_variable_get('@backend_config')).to eq({})
64
66
  expect(cls.instance_variable_get('@consul_url')).to eq(nil)
@@ -66,6 +68,8 @@ describe TFWrapper::RakeTasks do
66
68
  .to eq(Gem::Version.new('0.0.0'))
67
69
  expect(cls.instance_variable_get('@before_proc')).to eq(nil)
68
70
  expect(cls.instance_variable_get('@after_proc')).to eq(nil)
71
+ expect(cls.instance_variable_get('@disable_landscape')).to eq(false)
72
+ expect(cls.instance_variable_get('@landscape_progress')).to eq(nil)
69
73
  end
70
74
  it 'sets options' do
71
75
  allow(ENV).to receive(:[])
@@ -85,10 +89,14 @@ describe TFWrapper::RakeTasks do
85
89
  'tf/dir',
86
90
  consul_env_vars_prefix: 'cvprefix',
87
91
  tf_vars_from_env: { 'foo' => 'bar' },
92
+ allowed_empty_vars: %w[bar blam],
93
+ tf_sensitive_vars: %w[secret],
88
94
  tf_extra_vars: { 'baz' => 'blam' },
89
95
  consul_url: 'foobar',
90
96
  before_proc: bproc,
91
- after_proc: aproc
97
+ after_proc: aproc,
98
+ disable_landscape: true,
99
+ landscape_progress: :dots
92
100
  )
93
101
  expect(cls.instance_variable_get('@tf_dir'))
94
102
  .to eq('/path/to/tf/dir')
@@ -96,12 +104,18 @@ describe TFWrapper::RakeTasks do
96
104
  .to eq('cvprefix')
97
105
  expect(cls.instance_variable_get('@tf_vars_from_env'))
98
106
  .to eq('foo' => 'bar')
107
+ expect(cls.instance_variable_get('@allowed_empty_vars'))
108
+ .to eq(%w[bar blam])
109
+ expect(cls.instance_variable_get('@tf_sensitive_vars'))
110
+ .to eq(%w[secret])
99
111
  expect(cls.instance_variable_get('@tf_extra_vars'))
100
112
  .to eq('baz' => 'blam')
101
113
  expect(cls.instance_variable_get('@backend_config')).to eq({})
102
114
  expect(cls.instance_variable_get('@consul_url')).to eq('foobar')
103
115
  expect(cls.instance_variable_get('@before_proc')).to eq(bproc)
104
116
  expect(cls.instance_variable_get('@after_proc')).to eq(aproc)
117
+ expect(cls.instance_variable_get('@disable_landscape')).to eq(true)
118
+ expect(cls.instance_variable_get('@landscape_progress')).to eq(:dots)
105
119
  end
106
120
  context 'when before_proc is not a proc or nil' do
107
121
  it 'raises an error' do
@@ -120,6 +134,23 @@ describe TFWrapper::RakeTasks do
120
134
  )
121
135
  end
122
136
  end
137
+ context 'when landscape_progress is an invalid value' do
138
+ it 'raises an error' do
139
+ allow(ENV).to receive(:[])
140
+ allow(ENV).to receive(:[]).with('CONSUL_HOST').and_return('chost')
141
+ allow(ENV).to receive(:[]).with('ENVIRONMENT').and_return('myenv')
142
+ allow(ENV).to receive(:[]).with('PROJECT').and_return('myproj')
143
+ allow(Rake.application).to receive(:rakefile)
144
+ .and_return('/rake/dir/Rakefile')
145
+ allow(File).to receive(:realpath) { |p| p.sub('../', '') }
146
+ allow(File).to receive(:file?).and_return(true)
147
+ expect { TFWrapper::RakeTasks.new('tfdir', landscape_progress: :foo) }
148
+ .to raise_error(
149
+ ArgumentError,
150
+ /landscape_progress option must be one of:/
151
+ )
152
+ end
153
+ end
123
154
  context 'when after_proc is not a proc or nil' do
124
155
  it 'raises an error' do
125
156
  allow(Rake.application).to receive(:original_dir)
@@ -294,6 +325,7 @@ describe TFWrapper::RakeTasks do
294
325
  .to eq(Gem::Version.new('0.0.0'))
295
326
  vars = { foo: 'bar', baz: 'blam' }
296
327
  subject.instance_variable_set('@tf_vars_from_env', vars)
328
+ subject.instance_variable_set('@allowed_empty_vars', ['bar'])
297
329
  allow(TFWrapper::Helpers).to receive(:check_env_vars)
298
330
  allow(ENV).to receive(:[])
299
331
  subject.instance_variable_set(
@@ -306,7 +338,7 @@ describe TFWrapper::RakeTasks do
306
338
  allow(subject).to receive(:check_tf_version)
307
339
  .and_return(Gem::Version.new('0.9.5'))
308
340
  expect(TFWrapper::Helpers)
309
- .to receive(:check_env_vars).once.ordered.with(vars.values)
341
+ .to receive(:check_env_vars).once.ordered.with(vars.values, ['bar'])
310
342
  expect(subject).to receive(:check_tf_version).once.ordered
311
343
  expect(subject).to receive(:terraform_runner).once.ordered
312
344
  .with('terraform init -input=false '\
@@ -328,7 +360,7 @@ describe TFWrapper::RakeTasks do
328
360
  allow(subject).to receive(:check_tf_version)
329
361
  .and_return(Gem::Version.new('0.10.2'))
330
362
  expect(TFWrapper::Helpers)
331
- .to receive(:check_env_vars).once.ordered.with(vars.values)
363
+ .to receive(:check_env_vars).once.ordered.with(vars.values, [])
332
364
  expect(subject).to receive(:check_tf_version).once.ordered
333
365
  expect(subject).to receive(:terraform_runner).once.ordered
334
366
  .with('terraform init -input=false')
@@ -377,6 +409,7 @@ describe TFWrapper::RakeTasks do
377
409
  before(:each) do
378
410
  Rake::Task.clear
379
411
  Rake.application = Rake::Application.new
412
+ allow(subject).to receive(:landscape_format)
380
413
  end
381
414
  after(:each) do
382
415
  Rake.application = rake_application
@@ -392,33 +425,107 @@ describe TFWrapper::RakeTasks do
392
425
  expect(Rake.application['tf:plan'].arg_names).to eq([:target])
393
426
  end
394
427
  it 'runs the plan command with no targets' do
428
+ stub_const('TFWrapper::RakeTasks::HAVE_LANDSCAPE', true)
395
429
  Rake.application['tf:plan'].clear_prerequisites
396
430
  allow(subject).to receive(:var_file_path).and_return('file.tfvars.json')
397
431
  allow(subject).to receive(:terraform_runner)
398
432
  expect(subject).to receive(:terraform_runner).once
399
- .with('terraform plan -var-file file.tfvars.json')
433
+ .with('terraform plan -var-file file.tfvars.json', progress: nil)
400
434
  Rake.application['tf:plan'].invoke
401
435
  end
402
436
  it 'runs the plan command with one target' do
437
+ stub_const('TFWrapper::RakeTasks::HAVE_LANDSCAPE', true)
403
438
  Rake.application['tf:plan'].clear_prerequisites
404
439
  allow(subject).to receive(:var_file_path).and_return('file.tfvars.json')
405
440
  allow(subject).to receive(:terraform_runner)
406
441
  expect(subject).to receive(:terraform_runner).once
407
442
  .with('terraform plan -var-file file.tfvars.json ' \
408
- '-target tar.get[1]')
443
+ '-target tar.get[1]', progress: nil)
409
444
  Rake.application['tf:plan'].invoke('tar.get[1]')
410
445
  end
411
446
  it 'runs the plan command with three targets' do
447
+ stub_const('TFWrapper::RakeTasks::HAVE_LANDSCAPE', true)
412
448
  Rake.application['tf:plan'].clear_prerequisites
413
449
  allow(subject).to receive(:var_file_path).and_return('file.tfvars.json')
414
450
  allow(subject).to receive(:terraform_runner)
415
451
  expect(subject).to receive(:terraform_runner).once
416
452
  .with('terraform plan -var-file file.tfvars.json ' \
417
- '-target tar.get[1] -target t.gt[2] -target my.target[3]')
453
+ '-target tar.get[1] -target t.gt[2] -target my.target[3]',
454
+ progress: nil)
418
455
  Rake.application['tf:plan'].invoke(
419
456
  'tar.get[1]', 't.gt[2]', 'my.target[3]'
420
457
  )
421
458
  end
459
+ context 'with terraform_landscape available and enabled' do
460
+ before(:each) do
461
+ stub_const('TFWrapper::RakeTasks::HAVE_LANDSCAPE', true)
462
+ allow(subject).to receive(:var_file_path).and_return('file.tfvars.json')
463
+ allow(subject).to receive(:terraform_runner).and_return('TFoutput')
464
+ end
465
+ it 'runs plan with default progress type' do
466
+ Rake.application['tf:plan'].clear_prerequisites
467
+ expect(subject).to receive(:terraform_runner).once
468
+ .with('terraform plan -var-file file.tfvars.json', progress: nil)
469
+ expect(subject).to receive(:landscape_format).once.with('TFoutput')
470
+ Rake.application['tf:plan'].invoke
471
+ end
472
+ it 'runs plan with dots progress type' do
473
+ Rake.application['tf:plan'].clear_prerequisites
474
+ subject.instance_variable_set('@landscape_progress', :dots)
475
+ expect(subject).to receive(:terraform_runner).once
476
+ .with('terraform plan -var-file file.tfvars.json', progress: :dots)
477
+ expect(subject).to receive(:landscape_format).once.with('TFoutput')
478
+ Rake.application['tf:plan'].invoke
479
+ end
480
+ it 'runs plan with lines progress type' do
481
+ Rake.application['tf:plan'].clear_prerequisites
482
+ subject.instance_variable_set('@landscape_progress', :lines)
483
+ expect(subject).to receive(:terraform_runner).once
484
+ .with('terraform plan -var-file file.tfvars.json', progress: :lines)
485
+ expect(subject).to receive(:landscape_format).once.with('TFoutput')
486
+ Rake.application['tf:plan'].invoke
487
+ end
488
+ it 'runs plan with stream progress type' do
489
+ Rake.application['tf:plan'].clear_prerequisites
490
+ subject.instance_variable_set('@landscape_progress', :stream)
491
+ expect(subject).to receive(:terraform_runner).once
492
+ .with('terraform plan -var-file file.tfvars.json',
493
+ progress: :stream)
494
+ expect(subject).to receive(:landscape_format).once.with('TFoutput')
495
+ Rake.application['tf:plan'].invoke
496
+ end
497
+ end
498
+ context 'with terraform_landscape unavailable' do
499
+ it 'runs plan with stream progress and does not run landscape' do
500
+ stub_const('TFWrapper::RakeTasks::HAVE_LANDSCAPE', false)
501
+ allow(subject).to receive(:var_file_path).and_return('file.tfvars.json')
502
+ allow(subject).to receive(:terraform_runner).and_return('TFoutput')
503
+
504
+ Rake.application['tf:plan'].clear_prerequisites
505
+ expect(subject).to receive(:terraform_runner).once
506
+ .with(
507
+ 'terraform plan -var-file file.tfvars.json', progress: :stream
508
+ )
509
+ expect(subject).to_not receive(:landscape_format)
510
+ Rake.application['tf:plan'].invoke
511
+ end
512
+ end
513
+ context 'with terraform_landscape available but disabled' do
514
+ it 'runs plan with stream progress and does not run landscape' do
515
+ stub_const('TFWrapper::RakeTasks::HAVE_LANDSCAPE', true)
516
+ allow(subject).to receive(:var_file_path).and_return('file.tfvars.json')
517
+ allow(subject).to receive(:terraform_runner).and_return('TFoutput')
518
+
519
+ subject.instance_variable_set('@disable_landscape', true)
520
+ Rake.application['tf:plan'].clear_prerequisites
521
+ expect(subject).to receive(:terraform_runner).once
522
+ .with(
523
+ 'terraform plan -var-file file.tfvars.json', progress: :stream
524
+ )
525
+ expect(subject).to_not receive(:landscape_format)
526
+ Rake.application['tf:plan'].invoke
527
+ end
528
+ end
422
529
  it 'calls before_proc if not nil' do
423
530
  Rake.application['tf:plan'].clear_prerequisites
424
531
  allow(subject).to receive(:var_file_path).and_return('file.tfvars.json')
@@ -729,6 +836,7 @@ describe TFWrapper::RakeTasks do
729
836
  Rake.application = rake_application
730
837
  end
731
838
  before do
839
+ subject.instance_variable_set('@tf_sensitive_vars', ['secret'])
732
840
  subject.install_write_tf_vars
733
841
  end
734
842
 
@@ -741,7 +849,8 @@ describe TFWrapper::RakeTasks do
741
849
  vars = {
742
850
  'foo' => 'bar',
743
851
  'baz' => 'blam',
744
- 'aws_access_key' => 'ak'
852
+ 'aws_access_key' => 'ak',
853
+ 'secret' => 'abc'
745
854
  }
746
855
  allow(subject).to receive(:terraform_vars).and_return(vars)
747
856
  allow(subject).to receive(:var_file_path).and_return('file.tfvars.json')
@@ -753,6 +862,8 @@ describe TFWrapper::RakeTasks do
753
862
  expect(STDOUT).to receive(:puts).once.with('Terraform vars:')
754
863
  expect(STDOUT).to receive(:puts)
755
864
  .once.with('aws_access_key => (redacted)')
865
+ expect(STDOUT).to receive(:puts)
866
+ .once.with('secret => (redacted)')
756
867
  expect(STDOUT).to receive(:puts).once.with('baz => blam')
757
868
  expect(STDOUT).to receive(:puts).once.with('foo => bar')
758
869
  expect(File).to receive(:open).once.with('file.tfvars.json', 'w')
@@ -814,6 +925,7 @@ describe TFWrapper::RakeTasks do
814
925
  Rake.application = rake_application
815
926
  end
816
927
  before do
928
+ subject.instance_variable_set('@tf_sensitive_vars', ['secret'])
817
929
  subject.instance_variable_set('@ns_prefix', 'foo')
818
930
  subject.install_write_tf_vars
819
931
  end
@@ -827,7 +939,8 @@ describe TFWrapper::RakeTasks do
827
939
  vars = {
828
940
  'foo' => 'bar',
829
941
  'baz' => 'blam',
830
- 'aws_access_key' => 'ak'
942
+ 'aws_access_key' => 'ak',
943
+ 'secret' => 'abc'
831
944
  }
832
945
  allow(subject).to receive(:terraform_vars).and_return(vars)
833
946
  allow(subject).to receive(:var_file_path)
@@ -840,6 +953,8 @@ describe TFWrapper::RakeTasks do
840
953
  expect(STDOUT).to receive(:puts).once.with('Terraform vars:')
841
954
  expect(STDOUT).to receive(:puts)
842
955
  .once.with('aws_access_key => (redacted)')
956
+ expect(STDOUT).to receive(:puts)
957
+ .once.with('secret => (redacted)')
843
958
  expect(STDOUT).to receive(:puts).once.with('baz => blam')
844
959
  expect(STDOUT).to receive(:puts).once.with('foo => bar')
845
960
  expect(File).to receive(:open).once.with('foo_file.tfvars.json', 'w')
@@ -1003,20 +1118,102 @@ describe TFWrapper::RakeTasks do
1003
1118
  )
1004
1119
  end
1005
1120
  end
1121
+ describe '#landscape_format', if: HAVE_LANDSCAPE do
1122
+ before(:each) do
1123
+ allow(STDERR).to receive(:puts)
1124
+ allow(STDOUT).to receive(:puts)
1125
+ end
1126
+ context 'when no exception is raised' do
1127
+ it 'processes the string through TerraformLandscape' do
1128
+ dbl_printer = double
1129
+ dbl_output = double
1130
+ allow(TerraformLandscape::Printer)
1131
+ .to receive(:new).and_return(dbl_printer)
1132
+ allow(TerraformLandscape::Output)
1133
+ .to receive(:new).and_return(dbl_output)
1134
+ allow(dbl_printer).to receive(:process_string)
1135
+
1136
+ expect(TerraformLandscape::Output)
1137
+ .to receive(:new).once.with(STDOUT)
1138
+ expect(TerraformLandscape::Printer)
1139
+ .to receive(:new).once.with(dbl_output)
1140
+ expect(dbl_printer).to receive(:process_string).once.with('PlanOutput')
1141
+ expect(STDERR).to_not receive(:puts)
1142
+ expect(STDOUT).to_not receive(:puts)
1143
+ subject.landscape_format('PlanOutput')
1144
+ end
1145
+ end
1146
+ context 'when an exception is raised' do
1147
+ context 'and landscape_progress is :stream' do
1148
+ it 'prints an error message' do
1149
+ dbl_printer = double
1150
+ dbl_output = double
1151
+ allow(TerraformLandscape::Printer)
1152
+ .to receive(:new).and_return(dbl_printer)
1153
+ allow(TerraformLandscape::Output)
1154
+ .to receive(:new).and_return(dbl_output)
1155
+ allow(dbl_printer).to receive(:process_string)
1156
+ .and_raise(RuntimeError, 'FooError')
1157
+
1158
+ expect(TerraformLandscape::Output)
1159
+ .to receive(:new).once.with(STDOUT)
1160
+ expect(TerraformLandscape::Printer)
1161
+ .to receive(:new).once.with(dbl_output)
1162
+ expect(dbl_printer)
1163
+ .to receive(:process_string).once.with('PlanOutput')
1164
+ expect(STDERR).to receive(:puts).once
1165
+ .with(
1166
+ 'Exception calling terraform_landscape to reformat output: ' \
1167
+ 'RuntimeError: FooError'
1168
+ )
1169
+ expect(STDOUT).to_not receive(:puts)
1170
+ subject.instance_variable_set('@landscape_progress', :stream)
1171
+ subject.landscape_format('PlanOutput')
1172
+ end
1173
+ end
1174
+ context 'and landscape_progress is not :stream' do
1175
+ it 'prints an error message and then the output' do
1176
+ dbl_printer = double
1177
+ dbl_output = double
1178
+ allow(TerraformLandscape::Printer)
1179
+ .to receive(:new).and_return(dbl_printer)
1180
+ allow(TerraformLandscape::Output)
1181
+ .to receive(:new).and_return(dbl_output)
1182
+ allow(dbl_printer).to receive(:process_string)
1183
+ .and_raise(RuntimeError, 'FooError')
1184
+
1185
+ expect(TerraformLandscape::Output)
1186
+ .to receive(:new).once.with(STDOUT)
1187
+ expect(TerraformLandscape::Printer)
1188
+ .to receive(:new).once.with(dbl_output)
1189
+ expect(dbl_printer)
1190
+ .to receive(:process_string).once.with('PlanOutput')
1191
+ expect(STDERR).to receive(:puts).once
1192
+ .with(
1193
+ 'Exception calling terraform_landscape to reformat output: ' \
1194
+ 'RuntimeError: FooError'
1195
+ )
1196
+ expect(STDOUT).to receive(:puts).once.with('PlanOutput')
1197
+ subject.instance_variable_set('@landscape_progress', nil)
1198
+ subject.landscape_format('PlanOutput')
1199
+ end
1200
+ end
1201
+ end
1202
+ end
1006
1203
  describe '#terraform_runner' do
1007
1204
  before do
1008
1205
  Retries.sleep_enabled = false
1009
1206
  end
1010
1207
  it 'outputs nothing and succeeds when command succeeds' do
1011
1208
  allow(TFWrapper::Helpers).to receive(:run_cmd_stream_output)
1012
- .with(any_args).and_return(['', 0])
1209
+ .with(any_args).and_return(['MyOutput', 0])
1013
1210
  expect(TFWrapper::Helpers).to receive(:run_cmd_stream_output)
1014
- .once.with('foo', 'tfdir')
1211
+ .once.with('foo', 'tfdir', progress: :stream)
1015
1212
  expect(STDERR).to receive(:puts).once
1016
1213
  .with("terraform_runner command: 'foo' (in tfdir)")
1017
1214
  expect(STDERR).to receive(:puts).once
1018
1215
  .with("terraform_runner command 'foo' finished and exited 0")
1019
- subject.terraform_runner('foo')
1216
+ expect(subject.terraform_runner('foo')).to eq('MyOutput')
1020
1217
  end
1021
1218
  it 'retries if needed' do
1022
1219
  @times_called = 0
@@ -1027,7 +1224,7 @@ describe TFWrapper::RakeTasks do
1027
1224
  end
1028
1225
 
1029
1226
  expect(TFWrapper::Helpers).to receive(:run_cmd_stream_output)
1030
- .exactly(2).times.with('foo', 'tfdir')
1227
+ .exactly(2).times.with('foo', 'tfdir', progress: :stream)
1031
1228
  expect(STDERR).to receive(:puts).once
1032
1229
  .with("terraform_runner command: 'foo' (in tfdir)")
1033
1230
  expect(STDERR).to receive(:puts).once
@@ -1044,23 +1241,25 @@ describe TFWrapper::RakeTasks do
1044
1241
  if @times_called < 3
1045
1242
  ['foo Throttling bar', 2]
1046
1243
  else
1047
- ['', 0]
1244
+ ['out', 0]
1048
1245
  end
1049
1246
  end
1050
1247
 
1051
1248
  expect(TFWrapper::Helpers).to receive(:run_cmd_stream_output)
1052
- .exactly(3).times.with('foo', 'tfdir')
1249
+ .exactly(3).times.with('foo', 'tfdir', progress: :stream)
1053
1250
  expect(STDERR).to receive(:puts).once
1054
1251
  .with("terraform_runner command: 'foo' (in tfdir)")
1055
1252
  expect(STDERR).to receive(:puts).once
1056
- .with(/terraform_runner\sfailed\swith\sTerraform\shit\sAWS\sAPI\srate\s
1253
+ .with(/terraform_runner\sfailed\swith\sfoo\sThrottling\sbar\s+
1254
+ Terraform\shit\sAWS\sAPI\srate\s
1057
1255
  limiting;\sretry\sattempt\s1;\s.+\sseconds\shave\spassed\./x)
1058
1256
  expect(STDERR).to receive(:puts).once
1059
- .with(/terraform_runner\sfailed\swith\sTerraform\shit\sAWS\sAPI\srate\s
1257
+ .with(/terraform_runner\sfailed\swith\sfoo\sThrottling\sbar\s+
1258
+ Terraform\shit\sAWS\sAPI\srate\s
1060
1259
  limiting;\sretry\sattempt\s2;\s.+\sseconds\shave\spassed\./x)
1061
1260
  expect(STDERR).to receive(:puts).once
1062
1261
  .with("terraform_runner command 'foo' finished and exited 0")
1063
- subject.terraform_runner('foo')
1262
+ expect(subject.terraform_runner('foo')).to eq('out')
1064
1263
  end
1065
1264
  it 'retries if status code 403' do
1066
1265
  @times_called = 0
@@ -1074,20 +1273,22 @@ describe TFWrapper::RakeTasks do
1074
1273
  end
1075
1274
 
1076
1275
  expect(TFWrapper::Helpers).to receive(:run_cmd_stream_output)
1077
- .exactly(3).times.with('foo', 'tfdir')
1276
+ .exactly(3).times.with('foo', 'tfdir', progress: :dots)
1078
1277
  expect(STDERR).to receive(:puts).once
1079
1278
  .with("terraform_runner command: 'foo' (in tfdir)")
1080
1279
  expect(STDERR).to receive(:puts).once
1081
- .with(/terraform_runner\sfailed\swith\sTerraform\scommand\sgot\s403\s
1280
+ .with(/terraform_runner\sfailed\swith\sfoo\sstatus\scode:\s403\sbar\s+
1281
+ Terraform\scommand\sgot\s403\s
1082
1282
  error\s-\saccess\sdenied\sor\scredentials\snot\spropagated;\sretry\s
1083
1283
  attempt\s1;\s.+\sseconds\shave\spassed\./x)
1084
1284
  expect(STDERR).to receive(:puts).once
1085
- .with(/terraform_runner\sfailed\swith\sTerraform\scommand\sgot\s403\s
1285
+ .with(/terraform_runner\sfailed\swith\sfoo\sstatus\scode:\s403\sbar\s+
1286
+ Terraform\scommand\sgot\s403\s
1086
1287
  error\s-\saccess\sdenied\sor\scredentials\snot\spropagated;\sretry\s
1087
1288
  attempt\s2;\s.+\sseconds\shave\spassed\./x)
1088
1289
  expect(STDERR).to receive(:puts).once
1089
1290
  .with("terraform_runner command 'foo' finished and exited 0")
1090
- subject.terraform_runner('foo')
1291
+ subject.terraform_runner('foo', progress: :dots)
1091
1292
  end
1092
1293
  it 'retries if status code 401' do
1093
1294
  @times_called = 0
@@ -1101,31 +1302,54 @@ describe TFWrapper::RakeTasks do
1101
1302
  end
1102
1303
 
1103
1304
  expect(TFWrapper::Helpers).to receive(:run_cmd_stream_output)
1104
- .exactly(3).times.with('foo', 'tfdir')
1305
+ .exactly(3).times.with('foo', 'tfdir', progress: nil)
1105
1306
  expect(STDERR).to receive(:puts).once
1106
1307
  .with("terraform_runner command: 'foo' (in tfdir)")
1107
1308
  expect(STDERR).to receive(:puts).once
1108
- .with(/terraform_runner\sfailed\swith\sTerraform\scommand\sgot\s401\s
1309
+ .with(/terraform_runner\sfailed\swith\sfoo\sstatus\scode:\s401\sbar\s+
1310
+ Terraform\scommand\sgot\s401\s
1109
1311
  error\s-\saccess\sdenied\sor\scredentials\snot\spropagated;\sretry\s
1110
1312
  attempt\s1;\s.+\sseconds\shave\spassed\./x)
1111
1313
  expect(STDERR).to receive(:puts).once
1112
- .with(/terraform_runner\sfailed\swith\sTerraform\scommand\sgot\s401\s
1314
+ .with(/terraform_runner\sfailed\swith\sfoo\sstatus\scode:\s401\sbar\s+
1315
+ Terraform\scommand\sgot\s401\s
1113
1316
  error\s-\saccess\sdenied\sor\scredentials\snot\spropagated;\sretry\s
1114
1317
  attempt\s2;\s.+\sseconds\shave\spassed\./x)
1115
1318
  expect(STDERR).to receive(:puts).once
1116
1319
  .with("terraform_runner command 'foo' finished and exited 0")
1117
- subject.terraform_runner('foo')
1320
+ subject.terraform_runner('foo', progress: nil)
1118
1321
  end
1119
1322
  it 'raises an error if the command exits non-zero' do
1120
1323
  allow(TFWrapper::Helpers).to receive(:run_cmd_stream_output)
1121
1324
  .and_return(['', 1])
1122
1325
  expect(TFWrapper::Helpers).to receive(:run_cmd_stream_output).once
1123
- .with('foo', 'tfdir')
1326
+ .with('foo', 'tfdir', progress: :stream)
1124
1327
  expect(STDERR).to receive(:puts).once
1125
1328
  .with('terraform_runner command: \'foo\' (in tfdir)')
1126
1329
  expect { subject.terraform_runner('foo') }
1127
1330
  .to raise_error('Errors have occurred executing: \'foo\' (exited 1)')
1128
1331
  end
1332
+ it 'prints output to STDERR if plan exits non-zero and not :stream' do
1333
+ allow(TFWrapper::Helpers).to receive(:run_cmd_stream_output)
1334
+ .and_return(['myoutput', 1])
1335
+ expect(TFWrapper::Helpers).to receive(:run_cmd_stream_output).once
1336
+ .with('foo', 'tfdir', progress: :dots)
1337
+ expect(STDERR).to receive(:puts).once
1338
+ .with('terraform_runner command: \'foo\' (in tfdir)')
1339
+ expect(STDERR).to receive(:puts).once
1340
+ .with('myoutput')
1341
+ expect { subject.terraform_runner('foo', progress: :dots) }
1342
+ .to raise_error('Errors have occurred executing: \'foo\' (exited 1)')
1343
+ end
1344
+ it 'raises an error if the progress option is invalid' do
1345
+ allow(TFWrapper::Helpers).to receive(:run_cmd_stream_output)
1346
+ .and_return(['', 1])
1347
+ expect(TFWrapper::Helpers).to_not receive(:run_cmd_stream_output)
1348
+ expect { subject.terraform_runner('foo', progress: :foo) }
1349
+ .to raise_error(
1350
+ 'progress option must be one of: [:dots, :lines, :stream, nil]'
1351
+ )
1352
+ end
1129
1353
  end
1130
1354
  describe '#check_tf_version' do
1131
1355
  it 'fails if the command exits non-zero' do