tfwrapper 0.4.1 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,5 +4,5 @@ module TFWrapper
4
4
  # version of the Gem/module; used in the gemspec and in messages.
5
5
  # NOTE: When updating this, also update the version in the "Installation"
6
6
  # section of README.md
7
- VERSION = '0.4.1'
7
+ VERSION = '0.6.2'
8
8
  end
@@ -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
- resp = Faraday.get('https://api.github.com/repos/hashicorp/terraform/releases/latest')
28
- rel = JSON.parse(resp.body)['tag_name'].sub(/^v/, '')
29
- puts "Found latest terraform release on GitHub: #{rel}"
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
+ Initializing the backend...
12
+ 
13
+ Successfully configured the backend "consul"! Terraform will automatically
14
+ use this backend unless the backend configuration changes.
15
+
16
+ Initializing provider plugins...
17
+ - Checking for available provider plugins on https://releases.hashicorp.com...
18
+ - Downloading plugin for provider "consul" (1.0.0)...
19
+
20
+ Terraform has been successfully initialized!
21
+ 
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.
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
+ ~ consul_key_prefix.landscapeTest
35
+  subkeys.foo: {
36
+ - "bar": "barval",
37
+ - "baz": "bazval",
38
+ - "foo": "fooval"
39
+ + "bar": "bar2val",
40
+ + "baz": "baz2val",
41
+ + "foo": "foo2val"
42
+ }
43
+
44
+ Plan: 0 to add, 1 to change, 0 to destroy.
45
+