terraform-wrapper 0.0.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.gitlab-ci.yml +2 -0
  3. data/Gemfile +0 -4
  4. data/lib/terraform-wrapper.rb +36 -16
  5. data/lib/terraform-wrapper/common.rb +12 -23
  6. data/lib/terraform-wrapper/shared.rb +7 -1
  7. data/lib/terraform-wrapper/shared/auths.rb +9 -0
  8. data/lib/terraform-wrapper/shared/auths/azure.rb +179 -0
  9. data/lib/terraform-wrapper/shared/auths/common.rb +95 -0
  10. data/lib/terraform-wrapper/shared/backends/aws.rb +71 -33
  11. data/lib/terraform-wrapper/shared/backends/azure.rb +38 -39
  12. data/lib/terraform-wrapper/shared/backends/common.rb +18 -14
  13. data/lib/terraform-wrapper/shared/backends/local.rb +20 -18
  14. data/lib/terraform-wrapper/shared/binary.rb +16 -5
  15. data/lib/terraform-wrapper/shared/code.rb +15 -4
  16. data/lib/terraform-wrapper/shared/config.rb +61 -31
  17. data/lib/terraform-wrapper/shared/latest.rb +11 -7
  18. data/lib/terraform-wrapper/shared/logger.rb +80 -0
  19. data/lib/terraform-wrapper/shared/logging.rb +77 -0
  20. data/lib/terraform-wrapper/shared/runner.rb +79 -21
  21. data/lib/terraform-wrapper/shared/variables.rb +66 -0
  22. data/lib/terraform-wrapper/tasks.rb +6 -0
  23. data/lib/terraform-wrapper/tasks/apply.rb +16 -18
  24. data/lib/terraform-wrapper/tasks/binary.rb +26 -23
  25. data/lib/terraform-wrapper/tasks/clean.rb +15 -15
  26. data/lib/terraform-wrapper/tasks/destroy.rb +16 -18
  27. data/lib/terraform-wrapper/tasks/import.rb +66 -0
  28. data/lib/terraform-wrapper/tasks/init.rb +16 -18
  29. data/lib/terraform-wrapper/tasks/plan.rb +16 -18
  30. data/lib/terraform-wrapper/tasks/plandestroy.rb +16 -18
  31. data/lib/terraform-wrapper/tasks/upgrade.rb +58 -0
  32. data/lib/terraform-wrapper/tasks/validate.rb +7 -7
  33. data/lib/terraform-wrapper/version.rb +1 -1
  34. data/terraform-wrapper.gemspec +3 -0
  35. metadata +39 -4
  36. data/lib/terraform-wrapper/shared/identifiers.rb +0 -70
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ada2b6b6e65d6daedfc646d9f983894ada4061b649902252468bccaae76b4fee
4
- data.tar.gz: 4698b8bc21d9ab1ab2866a263645a2aa07955aeb03b2f10d15aed732da1d4553
3
+ metadata.gz: f7338d84681486fc0e4e0f7135bdbf48327ed5d074c545b16f4c934ed1601698
4
+ data.tar.gz: 48a5e381f0dfa34084b65025a6cf2de67e017c1a52bf9fe7f29302a4a50b213a
5
5
  SHA512:
6
- metadata.gz: '095bd5f00cda0d8fa2e6e636bfaf4bf31e6dea0a03cbc49b3149c85b15c75e4928e5754dd56b9a71d9d0b33f5b8a7e033739e45e7746fe2fd97d28bb0139f62e'
7
- data.tar.gz: 36f56ccf800f33dba662e41f377688e753c409076417269a2b638a6a28b60980aea437736236ca1083602f2a1cf8d935c0cc7aaaa35b297ba11bde06e935efd2
6
+ metadata.gz: 590c7262c9d433a058c300d5f5f11e5cdbf2f4722f7aa9ea5cb341923c14666cb8ad8dcbee92df81b5d3cd6d3868c4cf635a67ffbcbe8103fbe90e928bb28928
7
+ data.tar.gz: 9f335a63961bed6a0a807d9ef504b2f44a76748ff7e4459d687d1f40c74085ad0e6dd1767fcd5b68c5bebef8bd7824415a6f17fac83b78075ef0792ee006d355
data/.gitlab-ci.yml CHANGED
@@ -31,5 +31,7 @@ deploy:
31
31
  - hash gem
32
32
  - echo "-- Publishing Gem --"
33
33
  - rake release
34
+ - echo "-- Listing Sums --"
35
+ - sha256sum "pkg"/*.gem
34
36
 
35
37
  ###############################################################################
data/Gemfile CHANGED
@@ -11,7 +11,3 @@ source "https://rubygems.org"
11
11
  gemspec
12
12
 
13
13
  ###############################################################################
14
-
15
- gem "rake", "~> 13.0"
16
-
17
- ###############################################################################
@@ -14,28 +14,48 @@ module TerraformWrapper
14
14
 
15
15
  ###############################################################################
16
16
 
17
- def self.define_tasks(backend: "local",
18
- binaries: File.join(Dir.pwd, "vendor", "terraform"),
19
- component:,
20
- configs: File.join(Dir.pwd, "config"),
21
- overrides: Hash.new,
22
- service:,
23
- terraform: File.join(Dir.pwd, "terraform"),
24
- version: TerraformWrapper::Shared::Latest.instance.version)
17
+ @logger = TerraformWrapper::Shared::Logging.logger_for("TerraformWrapper")
25
18
 
26
- $logger.info("Building tasks for service: #{service}, component: #{component}...")
19
+ ###############################################################################
20
+
21
+ @logger.info("Terraform Wrapper for Ruby - version: #{TerraformWrapper::VERSION}")
22
+
23
+ ###############################################################################
24
+
25
+ def self.define_tasks(component:, options: Hash.new, service:)
26
+ @logger.info("Building tasks for service: #{service}, component: #{component}...")
27
+
28
+ @logger.fatal("Options must be specified as a hash!") unless options.kind_of?(Hash)
29
+
30
+ binary_options = Hash.new
31
+ binary_options["base"] = options.key?("binary-base") ? options["binary-base"] : File.join(Dir.pwd, "vendor", "terraform")
32
+ binary_options["version"] = options.key?("binary-version") ? options["binary-version"] : Shared::Latest.instance.version
33
+
34
+ code_options = Hash.new
35
+ code_options["base"] = options.key?("code-base") ? options["code-base"] : File.join(Dir.pwd, "terraform")
36
+ code_options["name"] = component
37
+
38
+ config_options = Hash.new
39
+ config_options["auth-azure"] = options.key?("config-auth-azure") ? options["config-auth-azure"] : false
40
+ config_options["auth-azure-options"] = options.key?("config-auth-azure-options") ? options["config-auth-azure-options"] : Hash.new
41
+ config_options["base"] = options.key?("config-base") ? options["config-base"] : File.join(Dir.pwd, "config")
42
+ config_options["backend"] = options.key?("config-backend") ? options["config-backend"] : "local"
43
+ config_options["backend-options"] = options.key?("config-backend-options") ? options["config-backend-options"] : Hash.new
44
+ config_options["service"] = service
27
45
 
28
- binary = TerraformWrapper::Shared::Binary.new(base: binaries, version: version)
29
- code = TerraformWrapper::Shared::Code.new(base: terraform, name: component)
46
+ binary = TerraformWrapper::Shared::Binary.new(options: binary_options)
47
+ code = TerraformWrapper::Shared::Code.new(options: code_options)
30
48
 
31
49
  tasks = Array.new
32
- tasks << TerraformWrapper::Tasks::Apply.new(backend: backend, binary: binary, code: code, configs: configs, overrides: overrides, service: service)
50
+ tasks << TerraformWrapper::Tasks::Apply.new(binary: binary, code: code, options: config_options)
33
51
  tasks << TerraformWrapper::Tasks::Binary.new(binary: binary)
34
52
  tasks << TerraformWrapper::Tasks::Clean.new(code: code)
35
- tasks << TerraformWrapper::Tasks::Destroy.new(backend: backend, binary: binary, code: code, configs: configs, overrides: overrides, service: service)
36
- tasks << TerraformWrapper::Tasks::Init.new(backend: backend, binary: binary, code: code, configs: configs, overrides: overrides, service: service)
37
- tasks << TerraformWrapper::Tasks::Plan.new(backend: backend, binary: binary, code: code, configs: configs, overrides: overrides, service: service)
38
- tasks << TerraformWrapper::Tasks::PlanDestroy.new(backend: backend, binary: binary, code: code, configs: configs, overrides: overrides, service: service)
53
+ tasks << TerraformWrapper::Tasks::Destroy.new(binary: binary, code: code, options: config_options)
54
+ tasks << TerraformWrapper::Tasks::Import.new(binary: binary, code: code, options: config_options)
55
+ tasks << TerraformWrapper::Tasks::Init.new(binary: binary, code: code, options: config_options)
56
+ tasks << TerraformWrapper::Tasks::Plan.new(binary: binary, code: code, options: config_options)
57
+ tasks << TerraformWrapper::Tasks::PlanDestroy.new(binary: binary, code: code, options: config_options)
58
+ tasks << TerraformWrapper::Tasks::Upgrade.new(binary: binary, code: code)
39
59
  tasks << TerraformWrapper::Tasks::Validate.new(binary: binary, code: code)
40
60
  return tasks
41
61
  end
@@ -1,38 +1,27 @@
1
1
  ###############################################################################
2
2
 
3
- require 'logger'
3
+ module TerraformWrapper
4
4
 
5
5
  ###############################################################################
6
6
 
7
- $logger = Logger.new(STDOUT,
8
- level: "INFO",
9
- progname: "TerraformWrapper")
7
+ def self.create_directory(directory:, purpose: nil, exists: true)
8
+ return exists if File.directory?(directory)
10
9
 
11
- $logger.formatter = proc do |severity, datetime, progname, msg|
12
- sevId = severity.chars.first.upcase
13
- "#{progname} [#{sevId}] #{msg}\n"
14
- end
15
-
16
- ###############################################################################
10
+ result = false
17
11
 
18
- $logger.info("Terraform Wrapper for Ruby - version: #{TerraformWrapper::VERSION}")
12
+ if not purpose.nil? and purpose.kind_of?(String) and not purpose.strip.empty? then
13
+ @logger.info("Creating directory for: #{purpose}, path: #{directory}")
14
+ else
15
+ @logger.info("Creating directory: #{directory}")
16
+ end
19
17
 
20
- ###############################################################################
18
+ FileUtils.mkdir_p(directory)
21
19
 
22
- def create_directory(directory:, purpose: nil, exists: true)
23
- return exists if File.directory?(directory)
24
-
25
- result = false
26
-
27
- if not purpose.nil? and purpose.kind_of?(String) and not purpose.strip.empty? then
28
- $logger.info("Creating directory for: #{purpose}, path: #{directory}")
29
- else
30
- $logger.info("Creating directory: #{directory}")
20
+ result = File.directory?(directory)
31
21
  end
32
22
 
33
- FileUtils.mkdir_p(directory)
23
+ ###############################################################################
34
24
 
35
- result = File.directory?(directory)
36
25
  end
37
26
 
38
27
  ###############################################################################
@@ -1,11 +1,17 @@
1
1
  ###############################################################################
2
2
 
3
+ require_relative 'shared/logger'
4
+ require_relative 'shared/logging'
5
+
6
+ ###############################################################################
7
+
8
+ require_relative 'shared/auths'
3
9
  require_relative 'shared/backends'
4
10
  require_relative 'shared/binary'
5
11
  require_relative 'shared/code'
6
12
  require_relative 'shared/config'
7
- require_relative 'shared/identifiers'
8
13
  require_relative 'shared/latest'
9
14
  require_relative 'shared/runner'
15
+ require_relative 'shared/variables'
10
16
 
11
17
  ###############################################################################
@@ -0,0 +1,9 @@
1
+ ###############################################################################
2
+
3
+ require_relative 'auths/common'
4
+
5
+ ###############################################################################
6
+
7
+ require_relative 'auths/azure'
8
+
9
+ ###############################################################################
@@ -0,0 +1,179 @@
1
+ ###############################################################################
2
+
3
+ module TerraformWrapper
4
+
5
+ ###############################################################################
6
+
7
+ module Shared
8
+
9
+ ###############################################################################
10
+
11
+ module Auths
12
+
13
+ ###############################################################################
14
+
15
+ class Azure < Common
16
+
17
+ ###############################################################################
18
+
19
+ include TerraformWrapper::Shared::Logging
20
+
21
+ ###############################################################################
22
+
23
+ @@az = "az"
24
+ @@type = "azure"
25
+
26
+ ###############################################################################
27
+
28
+ @password = nil
29
+
30
+ ###############################################################################
31
+
32
+ attr_reader :subscription
33
+ attr_reader :tenant
34
+ attr_reader :username
35
+
36
+ ###############################################################################
37
+
38
+ def initialize(code:, config:, options:, service:, variables:)
39
+ construct(code: code, config: config, options: options, service: service, variables: variables)
40
+ end
41
+
42
+ ###############################################################################
43
+
44
+ def auth()
45
+ ENV["ARM_SUBSCRIPTION_ID"] = @subscription
46
+ ENV["ARM_TENANT_ID"] = @tenant
47
+ ENV["ARM_CLIENT_ID"] = @username unless @username.nil?
48
+ ENV["ARM_CLIENT_SECRET"] = @password unless @password.nil?
49
+ logger.success("Azure authenticator environment variables set!")
50
+ end
51
+
52
+ ###############################################################################
53
+
54
+ def clear()
55
+ ENV.delete("ARM_SUBSCRIPTION_ID")
56
+ ENV.delete("ARM_TENANT_ID")
57
+ logger.info("Azure authenticator environment variables cleared!")
58
+ end
59
+
60
+ ###############################################################################
61
+
62
+ private
63
+
64
+ ###############################################################################
65
+
66
+ def cli()
67
+ output = logger.colour ? "jsonc" : "json"
68
+ cmdline = "\"#{@@az}\" version --output \"#{output}\""
69
+ return(system(cmdline) || false)
70
+ end
71
+
72
+ ###############################################################################
73
+
74
+ def secret(vault:, name:)
75
+ logger.info("Getting secret: #{name}, from key vault: #{vault}...")
76
+
77
+ cmdline = "\"#{@@az}\" keyvault secret show --vault-name \"#{vault}\" --name \"#{name}\" --query \"value\" --output \"tsv\""
78
+ stdout = `#{cmdline}`
79
+ code = $?.exitstatus
80
+
81
+ logger.fatal("Failed to get secret: #{name} from key vault: #{vault}!") if (code != 0 and stdout.strip.empty?)
82
+
83
+ return(stdout.strip)
84
+ end
85
+
86
+ ###############################################################################
87
+
88
+ def subscription_details(subscription:)
89
+ logger.info("Looking up details for subscription: #{subscription}...")
90
+
91
+ cmdline = "\"#{@@az}\" account show --subscription \"#{subscription}\" --query \"{id:id,tenant:tenantId}\" --output \"yaml\""
92
+ stdout = `#{cmdline}`
93
+ code = $?.exitstatus
94
+
95
+ logger.fatal("Failed to get details for subscription: #{subscription}!") if code != 0
96
+
97
+ details = YAML.load(stdout.strip)
98
+
99
+ logger.fatal("Returned details did not include the subscription ID!") unless details.key?("id")
100
+ logger.fatal("Returned subscription ID is not a String!") unless details["id"].kind_of?(String)
101
+ logger.fatal("Returned subscription ID is empty!") if details["id"].strip.empty?
102
+
103
+ logger.fatal("Returned details did not include the tenant ID!") unless details.key?("tenant")
104
+ logger.fatal("Returned tenant ID is not a String!") unless details["tenant"].kind_of?(String)
105
+ logger.fatal("Returned tenant ID is empty!") if details["tenant"].strip.empty?
106
+
107
+ details.transform_values! { |value| value.strip }
108
+
109
+ logger.debug("Returned subscription ID: #{details["id"]}")
110
+ logger.debug("Returned tenant ID: #{details["tenant"]}")
111
+
112
+ return(details)
113
+ end
114
+
115
+ ###############################################################################
116
+
117
+ def specific()
118
+ keyvault = nil
119
+
120
+ logger.fatal("Azure CLI must be installed and accessible to use the Azure authenticator.") unless cli
121
+
122
+ logger.fatal("Azure authenticator mandatory option 'subscription' has not been set!") unless @options.key?("subscription")
123
+
124
+ subscription = @options["subscription"]
125
+
126
+ logger.fatal("Azure authenticator subscription must be a String!") unless subscription.kind_of?(String)
127
+ logger.fatal("Azure authenticator subscription must not be blank!") if subscription.strip.empty?
128
+
129
+ if @options.key?("keyvault") then
130
+ keyvault = @options["keyvault"]
131
+
132
+ logger.fatal("Azure authenticator keyvault name must be a String if specified!") unless keyvault.kind_of?(String)
133
+ logger.fatal("Azure authenticator keyvault name must not be blank if specified!") if keyvault.strip.empty?
134
+
135
+ username = @options.key?("username-secret") ? @options["username-secret"] : "terraform-username"
136
+
137
+ logger.fatal("Azure authenticator keyvault secret for username must be a String if keyvault name is specified!") unless username.kind_of?(String)
138
+ logger.fatal("Azure authenticator keyvault secret for username must not be blank if keyvault name is specified!") if username.strip.empty?
139
+
140
+ password = @options.key?("username-password") ? @options["username-password"] : "terraform-password"
141
+
142
+ logger.fatal("Azure authenticator keyvault secret for password must be a String if keyvault name is specified!") unless password.kind_of?(String)
143
+ logger.fatal("Azure authenticator keyvault secret for password must not be blank if keyvault name is specified!") if password.strip.empty?
144
+ end
145
+
146
+ begin
147
+ subscription = subscription % @variables
148
+ keyvault = keyvault % @variables unless keyvault.nil?
149
+ username = username % @variables unless keyvault.nil?
150
+ password = password % @variables unless keyvault.nil?
151
+ rescue
152
+ logger.fatal("Azure authenticator options contain variables that are not included in the configuration file!")
153
+ end
154
+
155
+ details = subscription_details(subscription: subscription)
156
+
157
+ @subscription = details["id"]
158
+ @tenant = details["tenant"]
159
+ @username = keyvault.nil? ? nil : secret(vault: keyvault, name: username)
160
+ @password = keyvault.nil? ? nil : secret(vault: keyvault, name: password)
161
+ end
162
+
163
+ ###############################################################################
164
+
165
+ end
166
+
167
+ ###############################################################################
168
+
169
+ end
170
+
171
+ ###############################################################################
172
+
173
+ end
174
+
175
+ ###############################################################################
176
+
177
+ end
178
+
179
+ ###############################################################################
@@ -0,0 +1,95 @@
1
+ ###############################################################################
2
+
3
+ module TerraformWrapper
4
+
5
+ ###############################################################################
6
+
7
+ module Shared
8
+
9
+ ###############################################################################
10
+
11
+ module Auths
12
+
13
+ ###############################################################################
14
+
15
+ class Common
16
+
17
+ ###############################################################################
18
+
19
+ include TerraformWrapper::Shared::Logging
20
+
21
+ ###############################################################################
22
+
23
+ @@type
24
+
25
+ ###############################################################################
26
+
27
+ @options
28
+ @variables
29
+
30
+ ###############################################################################
31
+
32
+ def initialize(code:, config:, options:, service:, variables:)
33
+ logger.fatal("This class should not be used directly! Please create an authenticator-specific class instead!")
34
+ end
35
+
36
+ ###############################################################################
37
+
38
+ def auth()
39
+ logger.fatal("The authenticator specific class should override the 'auth' method to complete the authentication process!")
40
+ end
41
+
42
+ ###############################################################################
43
+
44
+ def clear()
45
+ logger.fatal("The authenticator specific class should override the 'auth' method to clear any authentication details!")
46
+ end
47
+
48
+ ###############################################################################
49
+
50
+ def type()
51
+ logger.fatal("The authenticator specific class should set the 'type' class variable to a string!") unless @@type.kind_of?(String)
52
+
53
+ return @@type
54
+ end
55
+
56
+ ###############################################################################
57
+
58
+ private
59
+
60
+ ###############################################################################
61
+
62
+ def construct(code:, config:, options:, service:, variables:)
63
+ @options = options
64
+ @variables = variables.values.merge({
65
+ component: code.name,
66
+ config: config,
67
+ service: service
68
+ })
69
+
70
+ specific
71
+ end
72
+
73
+ ###############################################################################
74
+
75
+ def specific()
76
+ logger.fatal("The authenticator specific class should override the 'specific' method to include authenticator specific validation and setup, or simply return 'true' if it is not required.")
77
+ end
78
+
79
+ ###############################################################################
80
+
81
+ end
82
+
83
+ ###############################################################################
84
+
85
+ end
86
+
87
+ ###############################################################################
88
+
89
+ end
90
+
91
+ ###############################################################################
92
+
93
+ end
94
+
95
+ ###############################################################################