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.
- checksums.yaml +4 -4
- data/.gitlab-ci.yml +2 -0
- data/Gemfile +0 -4
- data/lib/terraform-wrapper.rb +36 -16
- data/lib/terraform-wrapper/common.rb +12 -23
- data/lib/terraform-wrapper/shared.rb +7 -1
- data/lib/terraform-wrapper/shared/auths.rb +9 -0
- data/lib/terraform-wrapper/shared/auths/azure.rb +179 -0
- data/lib/terraform-wrapper/shared/auths/common.rb +95 -0
- data/lib/terraform-wrapper/shared/backends/aws.rb +71 -33
- data/lib/terraform-wrapper/shared/backends/azure.rb +38 -39
- data/lib/terraform-wrapper/shared/backends/common.rb +18 -14
- data/lib/terraform-wrapper/shared/backends/local.rb +20 -18
- data/lib/terraform-wrapper/shared/binary.rb +16 -5
- data/lib/terraform-wrapper/shared/code.rb +15 -4
- data/lib/terraform-wrapper/shared/config.rb +61 -31
- data/lib/terraform-wrapper/shared/latest.rb +11 -7
- data/lib/terraform-wrapper/shared/logger.rb +80 -0
- data/lib/terraform-wrapper/shared/logging.rb +77 -0
- data/lib/terraform-wrapper/shared/runner.rb +79 -21
- data/lib/terraform-wrapper/shared/variables.rb +66 -0
- data/lib/terraform-wrapper/tasks.rb +6 -0
- data/lib/terraform-wrapper/tasks/apply.rb +16 -18
- data/lib/terraform-wrapper/tasks/binary.rb +26 -23
- data/lib/terraform-wrapper/tasks/clean.rb +15 -15
- data/lib/terraform-wrapper/tasks/destroy.rb +16 -18
- data/lib/terraform-wrapper/tasks/import.rb +66 -0
- data/lib/terraform-wrapper/tasks/init.rb +16 -18
- data/lib/terraform-wrapper/tasks/plan.rb +16 -18
- data/lib/terraform-wrapper/tasks/plandestroy.rb +16 -18
- data/lib/terraform-wrapper/tasks/upgrade.rb +58 -0
- data/lib/terraform-wrapper/tasks/validate.rb +7 -7
- data/lib/terraform-wrapper/version.rb +1 -1
- data/terraform-wrapper.gemspec +3 -0
- metadata +39 -4
- data/lib/terraform-wrapper/shared/identifiers.rb +0 -70
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f7338d84681486fc0e4e0f7135bdbf48327ed5d074c545b16f4c934ed1601698
|
4
|
+
data.tar.gz: 48a5e381f0dfa34084b65025a6cf2de67e017c1a52bf9fe7f29302a4a50b213a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 590c7262c9d433a058c300d5f5f11e5cdbf2f4722f7aa9ea5cb341923c14666cb8ad8dcbee92df81b5d3cd6d3868c4cf635a67ffbcbe8103fbe90e928bb28928
|
7
|
+
data.tar.gz: 9f335a63961bed6a0a807d9ef504b2f44a76748ff7e4459d687d1f40c74085ad0e6dd1767fcd5b68c5bebef8bd7824415a6f17fac83b78075ef0792ee006d355
|
data/.gitlab-ci.yml
CHANGED
data/Gemfile
CHANGED
data/lib/terraform-wrapper.rb
CHANGED
@@ -14,28 +14,48 @@ module TerraformWrapper
|
|
14
14
|
|
15
15
|
###############################################################################
|
16
16
|
|
17
|
-
|
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
|
-
|
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(
|
29
|
-
code = TerraformWrapper::Shared::Code.new(
|
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(
|
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(
|
36
|
-
tasks << TerraformWrapper::Tasks::
|
37
|
-
tasks << TerraformWrapper::Tasks::
|
38
|
-
tasks << TerraformWrapper::Tasks::
|
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
|
-
|
3
|
+
module TerraformWrapper
|
4
4
|
|
5
5
|
###############################################################################
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
progname: "TerraformWrapper")
|
7
|
+
def self.create_directory(directory:, purpose: nil, exists: true)
|
8
|
+
return exists if File.directory?(directory)
|
10
9
|
|
11
|
-
|
12
|
-
sevId = severity.chars.first.upcase
|
13
|
-
"#{progname} [#{sevId}] #{msg}\n"
|
14
|
-
end
|
15
|
-
|
16
|
-
###############################################################################
|
10
|
+
result = false
|
17
11
|
|
18
|
-
|
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
|
-
|
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
|
-
|
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
|
+
###############################################################################
|