tfwrapper 0.4.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.rubocop.yml +5 -5
- data/.travis.yml +62 -0
- data/ChangeLog.md +31 -0
- data/Gemfile +4 -0
- data/README.md +48 -5
- data/lib/tfwrapper/helpers.rb +25 -3
- data/lib/tfwrapper/raketasks.rb +91 -10
- data/lib/tfwrapper/version.rb +1 -1
- data/spec/acceptance/acceptance_helpers.rb +16 -3
- data/spec/acceptance/acceptance_spec.rb +229 -0
- data/spec/fixtures/landscapeTest/Rakefile +38 -0
- data/spec/fixtures/landscapeTest/failingTerraform/main.tf +28 -0
- data/spec/fixtures/landscapeTest/main.tf +32 -0
- data/spec/fixtures/landscapeTest/state.json +43 -0
- data/spec/fixtures/landscapeTest/with_landscape_default.out +45 -0
- data/spec/fixtures/landscapeTest/with_landscape_dots.out +45 -0
- data/spec/fixtures/landscapeTest/with_landscape_lines.out +70 -0
- data/spec/fixtures/landscapeTest/with_landscape_stream.out +71 -0
- data/spec/fixtures/landscapeTest/without_landscape.out +62 -0
- data/spec/fixtures/testOne.tf +1 -0
- data/spec/fixtures/testThree/bar/testThreeBar.tf +1 -0
- data/spec/fixtures/testThree/baz/testThreeBaz.tf +1 -0
- data/spec/fixtures/testThree/foo/testThreeFoo.tf +1 -0
- data/spec/fixtures/testTwo/foo/bar/testTwo.tf +1 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/unit/helpers_spec.rb +131 -3
- data/spec/unit/raketasks_spec.rb +250 -26
- data/tfwrapper.gemspec +1 -0
- metadata +36 -4
- data/circle.yml +0 -28
data/lib/tfwrapper/version.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'ffi'
|
4
4
|
require 'faraday'
|
5
5
|
require 'json'
|
6
|
+
require 'retries'
|
6
7
|
|
7
8
|
def fixture_dir
|
8
9
|
File.absolute_path(
|
@@ -24,12 +25,24 @@ def desired_tf_version
|
|
24
25
|
return ENV['TF_VERSION']
|
25
26
|
end
|
26
27
|
# else get the latest release from GitHub
|
27
|
-
|
28
|
-
|
29
|
-
|
28
|
+
latest_tf_version
|
29
|
+
end
|
30
|
+
|
31
|
+
def latest_tf_version
|
32
|
+
resp = Faraday.get('https://checkpoint-api.hashicorp.com/v1/check/terraform')
|
33
|
+
rel = JSON.parse(resp.body)['current_version']
|
34
|
+
puts "Found latest terraform release as: #{rel}"
|
30
35
|
rel
|
31
36
|
end
|
32
37
|
|
38
|
+
# Given the example terraform plan output with placeholders for the
|
39
|
+
# latest terraform version and fixtures path, return the interpolated string.
|
40
|
+
def clean_tf_plan_output(raw_out, latest_ver, fixture_path)
|
41
|
+
raw_out
|
42
|
+
.gsub('%%TF_LATEST_VER%%', latest_ver)
|
43
|
+
.gsub('%%FIXTUREPATH%%', fixture_path)
|
44
|
+
end
|
45
|
+
|
33
46
|
class HashicorpFetcher
|
34
47
|
def initialize(program, version)
|
35
48
|
@program = program
|
@@ -18,6 +18,10 @@ else
|
|
18
18
|
APPLY_CMD = 'terraform apply'
|
19
19
|
end
|
20
20
|
|
21
|
+
without_landscape = !HAVE_LANDSCAPE && TF_VERSION == '0.11.2'
|
22
|
+
with_landscape = HAVE_LANDSCAPE && TF_VERSION == '0.11.2'
|
23
|
+
latest_tf_ver = latest_tf_version
|
24
|
+
|
21
25
|
Diplomat.configure do |config|
|
22
26
|
config.url = 'http://127.0.0.1:8500'
|
23
27
|
end
|
@@ -734,4 +738,229 @@ describe 'tfwrapper' do
|
|
734
738
|
end
|
735
739
|
end
|
736
740
|
end
|
741
|
+
context 'landscapeTest', order: :defined do
|
742
|
+
before(:all) do
|
743
|
+
@fixturepath = File.absolute_path(
|
744
|
+
File.join(File.dirname(__FILE__), '..', 'fixtures', 'landscapeTest')
|
745
|
+
)
|
746
|
+
end
|
747
|
+
before(:each) do
|
748
|
+
Diplomat::Kv.put(
|
749
|
+
'landscapeTest/foo', '{"bar":"barval","baz":"bazval","foo":"fooval"}'
|
750
|
+
)
|
751
|
+
Diplomat::Kv.put(
|
752
|
+
'terraform/landscapeTest',
|
753
|
+
File.read(File.join(@fixturepath, 'state.json'))
|
754
|
+
)
|
755
|
+
end
|
756
|
+
context 'without landscape installed', if: without_landscape do
|
757
|
+
describe 'default_tf:plan' do
|
758
|
+
before(:all) do
|
759
|
+
@out_err, @ecode = Open3.capture2e(
|
760
|
+
'timeout -k 60 45 bundle exec rake default_tf:plan',
|
761
|
+
chdir: @fixturepath
|
762
|
+
)
|
763
|
+
@varpath = File.join(@fixturepath, 'default_build.tfvars.json')
|
764
|
+
end
|
765
|
+
after(:all) do
|
766
|
+
File.delete(@varpath) if File.file?(@varpath)
|
767
|
+
end
|
768
|
+
it 'does not time out' do
|
769
|
+
expect(@ecode.exitstatus).to_not eq(124)
|
770
|
+
expect(@ecode.exitstatus).to_not eq(137)
|
771
|
+
end
|
772
|
+
it 'exits zero' do
|
773
|
+
expect(@ecode.exitstatus).to eq(0)
|
774
|
+
end
|
775
|
+
it 'returns unmodified terraform output' do
|
776
|
+
expected = clean_tf_plan_output(
|
777
|
+
File.read(File.join(@fixturepath, 'without_landscape.out')),
|
778
|
+
latest_tf_ver, @fixturepath
|
779
|
+
)
|
780
|
+
expect(@out_err.strip).to eq(expected.strip)
|
781
|
+
end
|
782
|
+
end
|
783
|
+
end
|
784
|
+
context 'with landscape installed', if: with_landscape do
|
785
|
+
context 'and disabled' do
|
786
|
+
describe 'disabled_tf:plan' do
|
787
|
+
before(:all) do
|
788
|
+
@out_err, @ecode = Open3.capture2e(
|
789
|
+
'timeout -k 60 45 bundle exec rake disabled_tf:plan',
|
790
|
+
chdir: @fixturepath
|
791
|
+
)
|
792
|
+
@varpath = File.join(@fixturepath, 'disabled_build.tfvars.json')
|
793
|
+
end
|
794
|
+
after(:all) do
|
795
|
+
File.delete(@varpath) if File.file?(@varpath)
|
796
|
+
end
|
797
|
+
it 'does not time out' do
|
798
|
+
expect(@ecode.exitstatus).to_not eq(124)
|
799
|
+
expect(@ecode.exitstatus).to_not eq(137)
|
800
|
+
end
|
801
|
+
it 'exits zero' do
|
802
|
+
expect(@ecode.exitstatus).to eq(0)
|
803
|
+
end
|
804
|
+
it 'returns unmodified terraform output' do
|
805
|
+
expected = clean_tf_plan_output(
|
806
|
+
File.read(File.join(@fixturepath, 'without_landscape.out')),
|
807
|
+
latest_tf_ver, @fixturepath
|
808
|
+
).gsub('default_build.tfvars.json', 'disabled_build.tfvars.json')
|
809
|
+
expect(@out_err.strip).to eq(expected.strip)
|
810
|
+
end
|
811
|
+
end
|
812
|
+
end
|
813
|
+
context 'and default progress' do
|
814
|
+
describe 'default_tf:plan' do
|
815
|
+
before(:all) do
|
816
|
+
@out_err, @ecode = Open3.capture2e(
|
817
|
+
'timeout -k 60 45 bundle exec rake default_tf:plan',
|
818
|
+
chdir: @fixturepath
|
819
|
+
)
|
820
|
+
@varpath = File.join(@fixturepath, 'default_build.tfvars.json')
|
821
|
+
end
|
822
|
+
after(:all) do
|
823
|
+
File.delete(@varpath) if File.file?(@varpath)
|
824
|
+
end
|
825
|
+
it 'does not time out' do
|
826
|
+
expect(@ecode.exitstatus).to_not eq(124)
|
827
|
+
expect(@ecode.exitstatus).to_not eq(137)
|
828
|
+
end
|
829
|
+
it 'exits zero' do
|
830
|
+
expect(@ecode.exitstatus).to eq(0)
|
831
|
+
end
|
832
|
+
it 'returns landscape output and no plan output' do
|
833
|
+
expected = clean_tf_plan_output(
|
834
|
+
File.read(File.join(@fixturepath, 'with_landscape_default.out')),
|
835
|
+
latest_tf_ver, @fixturepath
|
836
|
+
)
|
837
|
+
expect(@out_err.strip).to eq(expected.strip)
|
838
|
+
end
|
839
|
+
end
|
840
|
+
end
|
841
|
+
context 'and dots progress' do
|
842
|
+
describe 'dots_tf:plan' do
|
843
|
+
before(:all) do
|
844
|
+
@out_err, @ecode = Open3.capture2e(
|
845
|
+
'timeout -k 60 45 bundle exec rake dots_tf:plan',
|
846
|
+
chdir: @fixturepath
|
847
|
+
)
|
848
|
+
@varpath = File.join(@fixturepath, 'dots_build.tfvars.json')
|
849
|
+
end
|
850
|
+
after(:all) do
|
851
|
+
File.delete(@varpath) if File.file?(@varpath)
|
852
|
+
end
|
853
|
+
it 'does not time out' do
|
854
|
+
expect(@ecode.exitstatus).to_not eq(124)
|
855
|
+
expect(@ecode.exitstatus).to_not eq(137)
|
856
|
+
end
|
857
|
+
it 'exits zero' do
|
858
|
+
expect(@ecode.exitstatus).to eq(0)
|
859
|
+
end
|
860
|
+
it 'returns progress dots for plan output and landscape output' do
|
861
|
+
expected = clean_tf_plan_output(
|
862
|
+
File.read(File.join(@fixturepath, 'with_landscape_dots.out')),
|
863
|
+
latest_tf_ver, @fixturepath
|
864
|
+
)
|
865
|
+
expect(@out_err.strip).to eq(expected.strip)
|
866
|
+
end
|
867
|
+
end
|
868
|
+
end
|
869
|
+
context 'and lines progress' do
|
870
|
+
describe 'lines_tf:plan' do
|
871
|
+
before(:all) do
|
872
|
+
@out_err, @ecode = Open3.capture2e(
|
873
|
+
'timeout -k 60 45 bundle exec rake lines_tf:plan',
|
874
|
+
chdir: @fixturepath
|
875
|
+
)
|
876
|
+
@varpath = File.join(@fixturepath, 'lines_build.tfvars.json')
|
877
|
+
end
|
878
|
+
after(:all) do
|
879
|
+
File.delete(@varpath) if File.file?(@varpath)
|
880
|
+
end
|
881
|
+
it 'does not time out' do
|
882
|
+
expect(@ecode.exitstatus).to_not eq(124)
|
883
|
+
expect(@ecode.exitstatus).to_not eq(137)
|
884
|
+
end
|
885
|
+
it 'exits zero' do
|
886
|
+
expect(@ecode.exitstatus).to eq(0)
|
887
|
+
end
|
888
|
+
it 'returns progress lines for plan output and landscape output' do
|
889
|
+
expected = clean_tf_plan_output(
|
890
|
+
File.read(File.join(@fixturepath, 'with_landscape_lines.out')),
|
891
|
+
latest_tf_ver, @fixturepath
|
892
|
+
)
|
893
|
+
expect(@out_err.strip).to eq(expected.strip)
|
894
|
+
end
|
895
|
+
end
|
896
|
+
end
|
897
|
+
context 'and stream progress' do
|
898
|
+
describe 'stream_tf:plan' do
|
899
|
+
before(:all) do
|
900
|
+
@out_err, @ecode = Open3.capture2e(
|
901
|
+
'timeout -k 60 45 bundle exec rake stream_tf:plan',
|
902
|
+
chdir: @fixturepath
|
903
|
+
)
|
904
|
+
@varpath = File.join(@fixturepath, 'stream_build.tfvars.json')
|
905
|
+
end
|
906
|
+
after(:all) do
|
907
|
+
File.delete(@varpath) if File.file?(@varpath)
|
908
|
+
end
|
909
|
+
it 'does not time out' do
|
910
|
+
expect(@ecode.exitstatus).to_not eq(124)
|
911
|
+
expect(@ecode.exitstatus).to_not eq(137)
|
912
|
+
end
|
913
|
+
it 'exits zero' do
|
914
|
+
expect(@ecode.exitstatus).to eq(0)
|
915
|
+
end
|
916
|
+
it 'returns streaming plan output and landscape output' do
|
917
|
+
expected = clean_tf_plan_output(
|
918
|
+
File.read(File.join(@fixturepath, 'with_landscape_stream.out')),
|
919
|
+
latest_tf_ver, @fixturepath
|
920
|
+
)
|
921
|
+
expect(@out_err.strip).to eq(expected.strip)
|
922
|
+
end
|
923
|
+
end
|
924
|
+
end
|
925
|
+
context 'when terraform fails' do
|
926
|
+
describe 'failing_tf:plan' do
|
927
|
+
before(:all) do
|
928
|
+
@out_err, @ecode = Open3.capture2e(
|
929
|
+
'timeout -k 60 45 bundle exec rake failing_tf:plan',
|
930
|
+
chdir: @fixturepath
|
931
|
+
)
|
932
|
+
@varpath = File.join(@fixturepath, 'failing_build.tfvars.json')
|
933
|
+
end
|
934
|
+
after(:all) do
|
935
|
+
File.delete(@varpath) if File.file?(@varpath)
|
936
|
+
end
|
937
|
+
it 'does not time out' do
|
938
|
+
expect(@ecode.exitstatus).to_not eq(124)
|
939
|
+
expect(@ecode.exitstatus).to_not eq(137)
|
940
|
+
end
|
941
|
+
it 'exits 1' do
|
942
|
+
expect(@ecode.exitstatus).to eq(1)
|
943
|
+
end
|
944
|
+
it 'returns the terraform output' do
|
945
|
+
expect(@out_err).to match(
|
946
|
+
/Terraform\sv0\.11\.2.*
|
947
|
+
terraform_runner\scommand:\s'terraform\sinit\s-input=false'.*
|
948
|
+
Running\swith:\sTerraform\sv0\.11\.2.*
|
949
|
+
Initializing\sthe\sbackend\.\.\..*
|
950
|
+
Successfully\sconfigured\sthe\sbackend\s"consul".*
|
951
|
+
Terraform\shas\sbeen\ssuccessfully\sinitialized.*
|
952
|
+
terraform_runner\scommand\s'terraform\sinit\s-input=false'\s
|
953
|
+
finished\sand\sexited\s0.*
|
954
|
+
consul_key_prefix\.landscapeTest:\s"path_prefix":\srequired\s
|
955
|
+
field\sis\snot\sset.*
|
956
|
+
rake\saborted.*
|
957
|
+
StandardError:\sErrors\shave\soccurred\sexecuting:\s
|
958
|
+
'terraform\splan\s-var-file.*
|
959
|
+
Tasks:\sTOP\s=>\sfailing_tf:plan.*/xm
|
960
|
+
)
|
961
|
+
end
|
962
|
+
end
|
963
|
+
end
|
964
|
+
end
|
965
|
+
end
|
737
966
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'tfwrapper/raketasks'
|
4
|
+
|
5
|
+
TFWrapper::RakeTasks.install_tasks(
|
6
|
+
'.',
|
7
|
+
namespace_prefix: 'default'
|
8
|
+
)
|
9
|
+
|
10
|
+
TFWrapper::RakeTasks.install_tasks(
|
11
|
+
'.',
|
12
|
+
namespace_prefix: 'disabled',
|
13
|
+
disable_landscape: true
|
14
|
+
)
|
15
|
+
|
16
|
+
TFWrapper::RakeTasks.install_tasks(
|
17
|
+
'.',
|
18
|
+
namespace_prefix: 'stream',
|
19
|
+
landscape_progress: :stream
|
20
|
+
)
|
21
|
+
|
22
|
+
TFWrapper::RakeTasks.install_tasks(
|
23
|
+
'.',
|
24
|
+
namespace_prefix: 'dots',
|
25
|
+
landscape_progress: :dots
|
26
|
+
)
|
27
|
+
|
28
|
+
TFWrapper::RakeTasks.install_tasks(
|
29
|
+
'.',
|
30
|
+
namespace_prefix: 'lines',
|
31
|
+
landscape_progress: :lines
|
32
|
+
)
|
33
|
+
|
34
|
+
TFWrapper::RakeTasks.install_tasks(
|
35
|
+
'failingTerraform/',
|
36
|
+
namespace_prefix: 'failing',
|
37
|
+
landscape_progress: :dots
|
38
|
+
)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
terraform {
|
2
|
+
required_version = "> 0.9.0"
|
3
|
+
backend "consul" {
|
4
|
+
address = "127.0.0.1:8500"
|
5
|
+
path = "terraform/landscapeTestFailure"
|
6
|
+
}
|
7
|
+
}
|
8
|
+
|
9
|
+
provider "consul" {
|
10
|
+
address = "127.0.0.1:8500"
|
11
|
+
version = "1.0.0"
|
12
|
+
}
|
13
|
+
|
14
|
+
locals {
|
15
|
+
keys = {
|
16
|
+
foo = "foo2val"
|
17
|
+
bar = "bar2val"
|
18
|
+
baz = "baz2val"
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
variable "foo" { default = "bar" }
|
23
|
+
|
24
|
+
resource "consul_key_prefix" "landscapeTest" {
|
25
|
+
invalid_param = "whoCares"
|
26
|
+
}
|
27
|
+
|
28
|
+
output "foo_variable" { value = "${var.foo}" }
|
@@ -0,0 +1,32 @@
|
|
1
|
+
terraform {
|
2
|
+
required_version = "> 0.9.0"
|
3
|
+
backend "consul" {
|
4
|
+
address = "127.0.0.1:8500"
|
5
|
+
path = "terraform/landscapeTest"
|
6
|
+
}
|
7
|
+
}
|
8
|
+
|
9
|
+
provider "consul" {
|
10
|
+
address = "127.0.0.1:8500"
|
11
|
+
version = "1.0.0"
|
12
|
+
}
|
13
|
+
|
14
|
+
locals {
|
15
|
+
keys = {
|
16
|
+
foo = "foo2val"
|
17
|
+
bar = "bar2val"
|
18
|
+
baz = "baz2val"
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
variable "foo" { default = "bar" }
|
23
|
+
|
24
|
+
resource "consul_key_prefix" "landscapeTest" {
|
25
|
+
path_prefix = "landscapeTest/"
|
26
|
+
|
27
|
+
subkeys = {
|
28
|
+
foo = "${jsonencode(local.keys)}"
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
output "foo_variable" { value = "${var.foo}" }
|
@@ -0,0 +1,43 @@
|
|
1
|
+
{
|
2
|
+
"version": 3,
|
3
|
+
"terraform_version": "0.11.2",
|
4
|
+
"serial": 1,
|
5
|
+
"lineage": "2bab32f5-67fc-4210-8a74-af61d21a5420",
|
6
|
+
"modules": [
|
7
|
+
{
|
8
|
+
"path": [
|
9
|
+
"root"
|
10
|
+
],
|
11
|
+
"outputs": {
|
12
|
+
"foo_variable": {
|
13
|
+
"sensitive": false,
|
14
|
+
"type": "string",
|
15
|
+
"value": "bar"
|
16
|
+
}
|
17
|
+
},
|
18
|
+
"resources": {
|
19
|
+
"consul_key_prefix.landscapeTest": {
|
20
|
+
"type": "consul_key_prefix",
|
21
|
+
"depends_on": [
|
22
|
+
"local.keys"
|
23
|
+
],
|
24
|
+
"primary": {
|
25
|
+
"id": "landscapeTest/",
|
26
|
+
"attributes": {
|
27
|
+
"datacenter": "dc1",
|
28
|
+
"id": "landscapeTest/",
|
29
|
+
"path_prefix": "landscapeTest/",
|
30
|
+
"subkeys.%": "1",
|
31
|
+
"subkeys.foo": "{\"bar\":\"bar2val\",\"baz\":\"baz2val\",\"foo\":\"foo2val\"}"
|
32
|
+
},
|
33
|
+
"meta": {},
|
34
|
+
"tainted": false
|
35
|
+
},
|
36
|
+
"deposed": [],
|
37
|
+
"provider": "provider.consul"
|
38
|
+
}
|
39
|
+
},
|
40
|
+
"depends_on": []
|
41
|
+
}
|
42
|
+
]
|
43
|
+
}
|
@@ -0,0 +1,45 @@
|
|
1
|
+
Terraform v0.11.2
|
2
|
+
|
3
|
+
Your version of Terraform is out of date! The latest version
|
4
|
+
is %%TF_LATEST_VER%%. You can update by downloading from www.terraform.io/downloads.html
|
5
|
+
terraform_runner command: 'terraform init -input=false' (in %%FIXTUREPATH%%)
|
6
|
+
Running with: Terraform v0.11.2
|
7
|
+
|
8
|
+
Your version of Terraform is out of date! The latest version
|
9
|
+
is %%TF_LATEST_VER%%. You can update by downloading from www.terraform.io/downloads.html
|
10
|
+
|
11
|
+
[0m[1mInitializing the backend...[0m
|
12
|
+
[0m[32m
|
13
|
+
Successfully configured the backend "consul"! Terraform will automatically
|
14
|
+
use this backend unless the backend configuration changes.[0m
|
15
|
+
|
16
|
+
[0m[1mInitializing provider plugins...[0m
|
17
|
+
- Checking for available provider plugins on https://releases.hashicorp.com...
|
18
|
+
- Downloading plugin for provider "consul" (1.0.0)...
|
19
|
+
|
20
|
+
[0m[1m[32mTerraform has been successfully initialized![0m[32m[0m
|
21
|
+
[0m[32m
|
22
|
+
You may now begin working with Terraform. Try running "terraform plan" to see
|
23
|
+
any changes that are required for your infrastructure. All Terraform commands
|
24
|
+
should now work.
|
25
|
+
|
26
|
+
If you ever set or change modules or backend configuration for Terraform,
|
27
|
+
rerun this command to reinitialize your working directory. If you forget, other
|
28
|
+
commands will detect it and remind you to do so if necessary.[0m
|
29
|
+
terraform_runner command 'terraform init -input=false' finished and exited 0
|
30
|
+
Terraform vars written to: %%FIXTUREPATH%%/default_build.tfvars.json
|
31
|
+
terraform_runner command: 'terraform plan -var-file %%FIXTUREPATH%%/default_build.tfvars.json' (in %%FIXTUREPATH%%)
|
32
|
+
Terraform vars:
|
33
|
+
terraform_runner command 'terraform plan -var-file %%FIXTUREPATH%%/default_build.tfvars.json' finished and exited 0
|
34
|
+
[0;33;49m~ consul_key_prefix.landscapeTest[0m
|
35
|
+
[0;33;49m subkeys.foo: [0m{
|
36
|
+
[31m- "bar": "barval",[0m
|
37
|
+
[31m- "baz": "bazval",[0m
|
38
|
+
[31m- "foo": "fooval"[0m
|
39
|
+
[32m+ "bar": "bar2val",[0m
|
40
|
+
[32m+ "baz": "baz2val",[0m
|
41
|
+
[32m+ "foo": "foo2val"[0m
|
42
|
+
}
|
43
|
+
|
44
|
+
Plan: 0 to add, 1 to change, 0 to destroy.
|
45
|
+
|