yle_tf 1.0.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/bin/tf +1 -0
- data/lib/yle_tf.rb +4 -0
- data/lib/yle_tf/action.rb +4 -0
- data/lib/yle_tf/action/builder.rb +2 -0
- data/lib/yle_tf/action/command.rb +4 -2
- data/lib/yle_tf/action/copy_root_module.rb +2 -0
- data/lib/yle_tf/action/generate_vars_file.rb +2 -0
- data/lib/yle_tf/action/load_config.rb +9 -1
- data/lib/yle_tf/action/terraform_init.rb +63 -32
- data/lib/yle_tf/action/tf_hooks.rb +9 -5
- data/lib/yle_tf/action/tmpdir.rb +3 -1
- data/lib/yle_tf/action/verify_terraform_version.rb +19 -6
- data/lib/yle_tf/action/verify_tf_env.rb +2 -0
- data/lib/yle_tf/action/verify_yle_tf_version.rb +36 -0
- data/lib/yle_tf/action/write_terraformrc_defaults.rb +34 -17
- data/lib/yle_tf/backend.rb +47 -0
- data/lib/yle_tf/cli.rb +3 -1
- data/lib/yle_tf/config.rb +25 -9
- data/lib/yle_tf/config/defaults.rb +25 -11
- data/lib/yle_tf/config/erb.rb +2 -0
- data/lib/yle_tf/config/file.rb +2 -0
- data/lib/yle_tf/config/loader.rb +89 -59
- data/lib/yle_tf/config/migration.rb +117 -0
- data/lib/yle_tf/error.rb +2 -0
- data/lib/yle_tf/helpers/hash.rb +22 -0
- data/lib/yle_tf/logger.rb +2 -10
- data/lib/yle_tf/logger/colorize.rb +2 -0
- data/lib/yle_tf/plugin.rb +6 -2
- data/lib/yle_tf/plugin/action_hook.rb +2 -0
- data/lib/yle_tf/plugin/loader.rb +8 -1
- data/lib/yle_tf/plugin/manager.rb +3 -0
- data/lib/yle_tf/system.rb +5 -2
- data/lib/yle_tf/system/io_handlers.rb +5 -1
- data/lib/yle_tf/system/output_logger.rb +2 -0
- data/lib/yle_tf/system/tf_hook_output_logger.rb +2 -0
- data/lib/yle_tf/tf_hook.rb +11 -9
- data/lib/yle_tf/tf_hook/runner.rb +2 -0
- data/lib/yle_tf/vars_file.rb +16 -3
- data/lib/yle_tf/version.rb +3 -1
- data/lib/yle_tf/version_requirement.rb +2 -5
- data/lib/yle_tf_plugins/backends/{s3 → __default}/plugin.rb +6 -4
- data/lib/yle_tf_plugins/backends/file/backend.rb +89 -0
- data/lib/yle_tf_plugins/backends/file/plugin.rb +4 -2
- data/lib/yle_tf_plugins/commands/__default/command.rb +2 -0
- data/lib/yle_tf_plugins/commands/__default/plugin.rb +2 -0
- data/lib/yle_tf_plugins/commands/_config/command.rb +2 -0
- data/lib/yle_tf_plugins/commands/_config/plugin.rb +2 -0
- data/lib/yle_tf_plugins/commands/_shell/command.rb +2 -0
- data/lib/yle_tf_plugins/commands/_shell/plugin.rb +2 -0
- data/lib/yle_tf_plugins/commands/help/command.rb +9 -20
- data/lib/yle_tf_plugins/commands/help/plugin.rb +2 -0
- data/lib/yle_tf_plugins/commands/version/command.rb +2 -0
- data/lib/yle_tf_plugins/commands/version/plugin.rb +2 -0
- metadata +61 -22
- data/lib/yle_tf/backend_config.rb +0 -41
- data/lib/yle_tf_plugins/backends/file/command.rb +0 -31
- data/lib/yle_tf_plugins/backends/file/config.rb +0 -17
- data/lib/yle_tf_plugins/backends/s3/command.rb +0 -19
- data/lib/yle_tf_plugins/backends/swift/command.rb +0 -18
- data/lib/yle_tf_plugins/backends/swift/plugin.rb +0 -16
- data/vendor/logger_level_patch.rb +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e8df78c6d65e3180770988e0fdc1655bfa0af42d57d8f1b5dd19f26de1281a39
|
4
|
+
data.tar.gz: 10f59a1cdd3757d19dbeebfaaeb1328e41c367be464d87486b9bb8b93d6ef845
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc31eb920ce29b2aeb8616739b89e370a0c36a8ff395e3a41b3a1176d4ac592a2da913b6ff11eb0a0c015c33f5819cf5e888b9056b324e7ef81c156f75fa4fc6
|
7
|
+
data.tar.gz: 2fbcf63e27d8a817b654087d676a9252db1acde67629ad66a07e4d12ac20e44396c707718c42c3ee594593bcad74fb5d1be108026b5a17c615dc4663eca42a97
|
data/bin/tf
CHANGED
data/lib/yle_tf.rb
CHANGED
data/lib/yle_tf/action.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class YleTf
|
2
4
|
module Action
|
3
5
|
autoload :Builder, 'yle_tf/action/builder'
|
@@ -10,11 +12,13 @@ class YleTf
|
|
10
12
|
autoload :TmpDir, 'yle_tf/action/tmpdir'
|
11
13
|
autoload :VerifyTerraformVersion, 'yle_tf/action/verify_terraform_version'
|
12
14
|
autoload :VerifyTfEnv, 'yle_tf/action/verify_tf_env'
|
15
|
+
autoload :VerifyYleTfVersion, 'yle_tf/action/verify_yle_tf_version'
|
13
16
|
autoload :WriteTerraformrcDefaults, 'yle_tf/action/write_terraformrc_defaults'
|
14
17
|
|
15
18
|
def self.default_action_stack(command_class = nil)
|
16
19
|
Builder.new do
|
17
20
|
use LoadConfig
|
21
|
+
use VerifyYleTfVersion
|
18
22
|
use VerifyTfEnv
|
19
23
|
use TmpDir
|
20
24
|
use WriteTerraformrcDefaults
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'yle_tf/logger'
|
2
4
|
|
3
5
|
class YleTf
|
@@ -12,9 +14,9 @@ class YleTf
|
|
12
14
|
|
13
15
|
def call(env)
|
14
16
|
if env[:tf_options][:only_hooks]
|
15
|
-
Logger.debug "Skipping command #{command
|
17
|
+
Logger.debug "Skipping command #{command} due to `--only-hooks`"
|
16
18
|
else
|
17
|
-
Logger.debug "Executing command #{command
|
19
|
+
Logger.debug "Executing command #{command} with env: #{env.inspect}"
|
18
20
|
command.new.execute(env)
|
19
21
|
end
|
20
22
|
|
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'yle_tf/config'
|
4
|
+
require 'yle_tf/logger'
|
2
5
|
|
3
6
|
class YleTf
|
4
7
|
module Action
|
@@ -8,10 +11,15 @@ class YleTf
|
|
8
11
|
end
|
9
12
|
|
10
13
|
def call(env)
|
11
|
-
env[:config] ||=
|
14
|
+
env[:config] ||= load_config(env[:tf_env])
|
12
15
|
|
13
16
|
@app.call(env)
|
14
17
|
end
|
18
|
+
|
19
|
+
def load_config(tf_env)
|
20
|
+
Logger.debug("Initializing configuration for the #{tf_env.inspect} environment")
|
21
|
+
Config.load(tf_env).tap { |config| Logger.debug(config.inspect) }
|
22
|
+
end
|
15
23
|
end
|
16
24
|
end
|
17
25
|
end
|
@@ -1,8 +1,12 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
require 'pathname'
|
5
|
+
require 'shellwords'
|
6
|
+
|
2
7
|
require 'yle_tf/logger'
|
3
8
|
require 'yle_tf/plugin'
|
4
9
|
require 'yle_tf/system'
|
5
|
-
require 'yle_tf/version_requirement'
|
6
10
|
|
7
11
|
class YleTf
|
8
12
|
module Action
|
@@ -10,62 +14,89 @@ class YleTf
|
|
10
14
|
TF_CMD_ARGS = %w[-input=false -no-color].freeze
|
11
15
|
|
12
16
|
TF_CMD_OPTS = {
|
13
|
-
env:
|
14
|
-
stdout: :debug
|
17
|
+
env: { 'TF_IN_AUTOMATION' => 'true' }, # Reduces some output
|
18
|
+
stdout: :debug # Hide the output to the debug level
|
15
19
|
}.freeze
|
16
20
|
|
21
|
+
attr_reader :config
|
22
|
+
|
17
23
|
def initialize(app)
|
18
24
|
@app = app
|
19
25
|
end
|
20
26
|
|
21
27
|
def call(env)
|
22
|
-
config = env[:config]
|
23
|
-
backend = backend_config(config)
|
28
|
+
@config = env[:config]
|
24
29
|
|
25
30
|
Logger.info('Initializing Terraform')
|
26
31
|
Logger.debug("Backend configuration: #{backend}")
|
27
32
|
|
28
|
-
|
29
|
-
|
33
|
+
init_dir
|
34
|
+
|
35
|
+
if env[:tf_command] == 'init'
|
36
|
+
# Skip initializing Terraform here, as it will be done by the
|
37
|
+
# actuall command later in the middleware stack.
|
38
|
+
@app.call(env)
|
39
|
+
store_terraform_lock
|
30
40
|
else
|
31
|
-
|
41
|
+
init_terraform
|
42
|
+
store_terraform_lock
|
43
|
+
@app.call(env)
|
32
44
|
end
|
33
45
|
|
34
|
-
|
46
|
+
tear_down
|
35
47
|
end
|
36
48
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
40
|
-
YleTf::System.cmd('terraform', 'remote', 'config', *TF_CMD_ARGS, *cli_args, TF_CMD_OPTS)
|
41
|
-
end
|
49
|
+
def init_dir
|
50
|
+
Logger.debug('Configuring the backend')
|
51
|
+
backend.configure
|
42
52
|
|
43
|
-
Logger.debug('
|
44
|
-
|
53
|
+
Logger.debug('Symlinking errored.tfstate')
|
54
|
+
symlink_to_module_dir('errored.tfstate')
|
45
55
|
end
|
46
56
|
|
47
|
-
def
|
48
|
-
Logger.debug('
|
49
|
-
backend.
|
50
|
-
|
51
|
-
|
52
|
-
|
57
|
+
def tear_down
|
58
|
+
Logger.debug('Tearing down backend')
|
59
|
+
backend.tear_down
|
60
|
+
end
|
61
|
+
|
62
|
+
def init_terraform
|
63
|
+
Logger.debug('Initializing Terraform')
|
64
|
+
YleTf::System.cmd('terraform', 'init', *tf_init_args, **TF_CMD_OPTS)
|
65
|
+
end
|
66
|
+
|
67
|
+
def store_terraform_lock
|
68
|
+
Logger.debug('Storing .terraform.lock.hcl')
|
69
|
+
copy_to_module_dir('.terraform.lock.hcl')
|
53
70
|
end
|
54
71
|
|
55
|
-
def
|
72
|
+
def backend
|
73
|
+
@backend ||= find_backend
|
74
|
+
end
|
75
|
+
|
76
|
+
def tf_init_args
|
77
|
+
TF_CMD_ARGS + Shellwords.split(ENV.fetch('TF_INIT_ARGS', ''))
|
78
|
+
end
|
79
|
+
|
80
|
+
def find_backend
|
56
81
|
backend_type = config.fetch('backend', 'type').downcase
|
57
|
-
backend_proc =
|
82
|
+
backend_proc = Plugin.manager.backends[backend_type]
|
58
83
|
|
59
84
|
klass = backend_proc.call
|
60
|
-
klass.new
|
85
|
+
klass.new(config)
|
61
86
|
end
|
62
87
|
|
63
|
-
def
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
88
|
+
def symlink_to_module_dir(file)
|
89
|
+
local_path = Pathname.pwd.join(file)
|
90
|
+
remote_path = config.module_dir.join(file)
|
91
|
+
|
92
|
+
# Remove the possibly copied old file
|
93
|
+
local_path.unlink if local_path.exist?
|
94
|
+
|
95
|
+
local_path.make_symlink(remote_path)
|
96
|
+
end
|
97
|
+
|
98
|
+
def copy_to_module_dir(file)
|
99
|
+
FileUtils.cp(file, config.module_dir.to_s) if File.exist?(file)
|
69
100
|
end
|
70
101
|
end
|
71
102
|
end
|
@@ -1,5 +1,4 @@
|
|
1
|
-
|
2
|
-
require 'yle_tf/tf_hook/runner'
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
3
|
require 'yle_tf/logger'
|
5
4
|
require 'yle_tf/tf_hook/runner'
|
@@ -21,7 +20,7 @@ class YleTf
|
|
21
20
|
|
22
21
|
def hook_runner
|
23
22
|
if run_hooks?
|
24
|
-
TfHook::Runner.new(
|
23
|
+
TfHook::Runner.new(config, hook_env)
|
25
24
|
else
|
26
25
|
NoRunner
|
27
26
|
end
|
@@ -29,11 +28,16 @@ class YleTf
|
|
29
28
|
|
30
29
|
def hook_env
|
31
30
|
{
|
32
|
-
'TF_COMMAND'
|
33
|
-
'TF_ENV'
|
31
|
+
'TF_COMMAND' => @env[:tf_command],
|
32
|
+
'TF_ENV' => @env[:tf_env],
|
33
|
+
'TF_MODULE_DIR' => config.module_dir.to_s,
|
34
34
|
}
|
35
35
|
end
|
36
36
|
|
37
|
+
def config
|
38
|
+
@env[:config]
|
39
|
+
end
|
40
|
+
|
37
41
|
def run_hooks?
|
38
42
|
!@env[:tf_options][:no_hooks]
|
39
43
|
end
|
data/lib/yle_tf/action/tmpdir.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'fileutils'
|
2
4
|
require 'tmpdir'
|
3
5
|
|
@@ -20,7 +22,7 @@ class YleTf
|
|
20
22
|
@app.call(env)
|
21
23
|
end
|
22
24
|
ensure
|
23
|
-
FileUtils.
|
25
|
+
FileUtils.rm_rf(tmpdir, secure: true) if tmpdir && Dir.exist?(tmpdir)
|
24
26
|
end
|
25
27
|
|
26
28
|
def tmpdir_prefix(config)
|
@@ -1,3 +1,6 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yle_tf'
|
1
4
|
require 'yle_tf/error'
|
2
5
|
require 'yle_tf/logger'
|
3
6
|
require 'yle_tf/system'
|
@@ -17,22 +20,32 @@ class YleTf
|
|
17
20
|
raise(Error, 'Terraform not found') if !version
|
18
21
|
|
19
22
|
Logger.debug("Terraform version: #{version}")
|
20
|
-
|
23
|
+
|
24
|
+
verify_version(version, requirement_by_yletf, required_by: 'YleTf')
|
25
|
+
verify_version(version, requirement_by_config(env), required_by: 'config')
|
21
26
|
|
22
27
|
@app.call(env)
|
23
28
|
end
|
24
29
|
|
25
30
|
def terraform_version
|
26
31
|
v = YleTf::System.read_cmd('terraform', 'version', error_handler: proc {})
|
27
|
-
|
32
|
+
m = /^Terraform v(?<version>[^\s]+)/.match(v)
|
33
|
+
m && m[:version]
|
28
34
|
end
|
29
35
|
|
30
|
-
def
|
31
|
-
version = env[:terraform_version]
|
36
|
+
def requirement_by_config(env)
|
32
37
|
requirement = env[:config].fetch('terraform', 'version_requirement') { nil }
|
38
|
+
VersionRequirement.new(requirement)
|
39
|
+
end
|
40
|
+
|
41
|
+
def requirement_by_yletf
|
42
|
+
VersionRequirement.new(YleTf::TERRAFORM_VERSION_REQUIREMENT)
|
43
|
+
end
|
33
44
|
|
34
|
-
|
35
|
-
|
45
|
+
def verify_version(version, requirement, **opts)
|
46
|
+
if !requirement.satisfied_by?(version)
|
47
|
+
raise Error, "Terraform version '#{requirement}' required by #{opts[:required_by]}, " \
|
48
|
+
"'#{version}' found"
|
36
49
|
end
|
37
50
|
end
|
38
51
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yle_tf/error'
|
4
|
+
require 'yle_tf/logger'
|
5
|
+
require 'yle_tf/version'
|
6
|
+
require 'yle_tf/version_requirement'
|
7
|
+
|
8
|
+
class YleTf
|
9
|
+
module Action
|
10
|
+
class VerifyYleTfVersion
|
11
|
+
def initialize(app)
|
12
|
+
@app = app
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
Logger.debug('Verifying YleTf version')
|
17
|
+
|
18
|
+
requirement = requirement(env[:config])
|
19
|
+
verify_version(requirement)
|
20
|
+
|
21
|
+
@app.call(env)
|
22
|
+
end
|
23
|
+
|
24
|
+
def requirement(config)
|
25
|
+
requirement = config.fetch('yle_tf', 'version_requirement') { nil }
|
26
|
+
VersionRequirement.new(requirement)
|
27
|
+
end
|
28
|
+
|
29
|
+
def verify_version(requirement)
|
30
|
+
return if requirement.satisfied_by?(YleTf::VERSION)
|
31
|
+
|
32
|
+
raise Error, "YleTf version '#{YleTf::VERSION}', '#{requirement}' required by config"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,52 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'fileutils'
|
4
|
+
require 'pathname'
|
5
|
+
|
2
6
|
require 'yle_tf/logger'
|
3
7
|
|
4
8
|
class YleTf
|
5
9
|
module Action
|
6
10
|
class WriteTerraformrcDefaults
|
7
11
|
# Path of the Terraform CLI configuration file
|
8
|
-
RC_PATH = '~/.terraformrc'
|
12
|
+
RC_PATH = '~/.terraformrc'
|
9
13
|
|
10
14
|
# Path of the plugin cache directory
|
11
|
-
DEFAULT_PLUGIN_CACHE_PATH = '~/.terraform.d/plugin-cache'
|
15
|
+
DEFAULT_PLUGIN_CACHE_PATH = '~/.terraform.d/plugin-cache'
|
12
16
|
|
13
17
|
def initialize(app)
|
14
18
|
@app = app
|
15
19
|
end
|
16
20
|
|
17
21
|
def call(env)
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
if rc_file.exist?
|
23
|
+
Logger.debug("Terraform configuration file '#{RC_PATH}' already exists")
|
24
|
+
if !existing_keys.include?('plugin_cache_dir')
|
25
|
+
Logger.warn("'plugin_cache_dir' not configured in '#{RC_PATH}'")
|
26
|
+
end
|
27
|
+
else
|
28
|
+
Logger.debug("Writing default configuration to '#{RC_PATH}'")
|
29
|
+
write_default_config
|
24
30
|
end
|
25
31
|
|
26
32
|
@app.call(env)
|
27
33
|
end
|
28
34
|
|
29
|
-
def
|
30
|
-
|
35
|
+
def rc_file
|
36
|
+
@rc_file ||= Pathname.new(RC_PATH).expand_path
|
31
37
|
end
|
32
38
|
|
33
|
-
def existing_keys
|
34
|
-
[].tap do |keys|
|
35
|
-
rc_file.
|
39
|
+
def existing_keys
|
40
|
+
@existing_keys ||= [].tap do |keys|
|
41
|
+
rc_file.readlines.each do |line|
|
42
|
+
# The matcher is a bit naive, but enough for out use
|
36
43
|
keys << Regexp.last_match(1) if line =~ /^(.+?)[ \t]*=/
|
37
44
|
end
|
38
45
|
end
|
39
46
|
end
|
40
47
|
|
41
|
-
def
|
48
|
+
def write_default_config
|
49
|
+
rc_file.open('w') do |rc_file|
|
50
|
+
configure_checkpoint(rc_file)
|
51
|
+
configure_plugin_cache_dir(rc_file)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def configure_checkpoint(file)
|
42
56
|
Logger.info("Disabling Terraform upgrade and security bulletin checks by '#{RC_PATH}'")
|
43
57
|
|
44
|
-
|
58
|
+
file.puts('disable_checkpoint = true')
|
45
59
|
end
|
46
60
|
|
47
|
-
def configure_plugin_cache_dir(
|
61
|
+
def configure_plugin_cache_dir(file)
|
48
62
|
Logger.info("Configuring global Terraform plugin cache by '#{RC_PATH}'")
|
49
|
-
|
63
|
+
# Replace `~` with `$HOME` as it is not expanded correctly in all architectures.
|
64
|
+
# Can't use `$HOME` in the constant though, as it won't be expanded by
|
65
|
+
# `expand_path` below. Can't win this game.
|
66
|
+
file.puts("plugin_cache_dir = \"#{DEFAULT_PLUGIN_CACHE_PATH.sub(/^~/, '$HOME')}\"")
|
50
67
|
|
51
68
|
dir = File.expand_path(DEFAULT_PLUGIN_CACHE_PATH)
|
52
69
|
return if File.directory?(dir)
|