yle_tf 0.4.0 → 1.3.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 +2 -1
- 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 +31 -33
- 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 +4 -2
- data/lib/yle_tf/backend.rb +42 -0
- data/lib/yle_tf/cli.rb +3 -1
- data/lib/yle_tf/config.rb +25 -9
- data/lib/yle_tf/config/defaults.rb +22 -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 +9 -2
- 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/{command.rb → backend.rb} +12 -13
- 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 +2 -0
- 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 -20
- data/lib/yle_tf/backend_config.rb +0 -41
- data/lib/yle_tf_plugins/backends/file/config.rb +0 -17
- data/lib/yle_tf_plugins/backends/s3/command.rb +0 -19
- 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: 7811f980206094727502839932ba9a800a4e37694ae26bc71d9c4935de38d3c3
|
4
|
+
data.tar.gz: 95e2c481a30b3caffb65c08407f9e222210fe01514f59ff88ca38a00915ea31b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 84010f77dfa1d2786f0c9b4a3783073ad15bbf6146bac16f4a49401b8b378e28f0747f82a6880eb01dda175fccbd1465f3e25391586e10c11d424e304fe8e74b
|
7
|
+
data.tar.gz: 95c19822da06edb58e250215fb0c5e2154da99e8881a2b8a8ce4fb9fe7c124772e81d7a2774595fdedb97cec3166e0b34e7c098ac20d8133ad97bfcb1196534e
|
data/bin/tf
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
# Catch Ctrl+C to avoid stack traces
|
4
5
|
Signal.trap('INT') { abort }
|
5
6
|
|
6
|
-
require 'bundler/setup' if File.exist?(File.expand_path('
|
7
|
+
require 'bundler/setup' if File.exist?(File.expand_path('../Gemfile', __dir__))
|
7
8
|
require 'yle_tf/cli'
|
8
9
|
|
9
10
|
cli = YleTf::CLI.new(ARGV)
|
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,10 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'pathname'
|
4
|
+
|
2
5
|
require 'yle_tf/logger'
|
3
6
|
require 'yle_tf/plugin'
|
4
7
|
require 'yle_tf/system'
|
5
|
-
require 'yle_tf/version_requirement'
|
6
8
|
|
7
9
|
class YleTf
|
8
10
|
module Action
|
@@ -10,62 +12,58 @@ class YleTf
|
|
10
12
|
TF_CMD_ARGS = %w[-input=false -no-color].freeze
|
11
13
|
|
12
14
|
TF_CMD_OPTS = {
|
13
|
-
env:
|
14
|
-
stdout: :debug
|
15
|
+
env: { 'TF_IN_AUTOMATION' => 'true' }, # Reduces some output
|
16
|
+
stdout: :debug # Hide the output to the debug level
|
15
17
|
}.freeze
|
16
18
|
|
19
|
+
attr_reader :config
|
20
|
+
|
17
21
|
def initialize(app)
|
18
22
|
@app = app
|
19
23
|
end
|
20
24
|
|
21
25
|
def call(env)
|
22
|
-
config = env[:config]
|
23
|
-
backend = backend_config(config)
|
26
|
+
@config = env[:config]
|
24
27
|
|
25
28
|
Logger.info('Initializing Terraform')
|
26
29
|
Logger.debug("Backend configuration: #{backend}")
|
27
30
|
|
28
|
-
|
29
|
-
init_pre_0_9(backend)
|
30
|
-
else
|
31
|
-
init(backend)
|
32
|
-
end
|
31
|
+
init(backend)
|
33
32
|
|
34
33
|
@app.call(env)
|
35
34
|
end
|
36
35
|
|
37
|
-
def
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
36
|
+
def init(backend)
|
37
|
+
Logger.debug('Configuring the backend')
|
38
|
+
backend.configure
|
39
|
+
|
40
|
+
Logger.debug('Symlinking errored.tfstate')
|
41
|
+
symlink_errored_tfstate
|
42
42
|
|
43
|
-
Logger.debug('
|
44
|
-
YleTf::System.cmd('terraform', '
|
43
|
+
Logger.debug('Initializing Terraform')
|
44
|
+
YleTf::System.cmd('terraform', 'init', *TF_CMD_ARGS, **TF_CMD_OPTS)
|
45
45
|
end
|
46
46
|
|
47
|
-
def
|
48
|
-
|
49
|
-
backend.generate_config do
|
50
|
-
Logger.debug('Initializing Terraform')
|
51
|
-
YleTf::System.cmd('terraform', 'init', *TF_CMD_ARGS, TF_CMD_OPTS)
|
52
|
-
end
|
47
|
+
def backend
|
48
|
+
@backend ||= find_backend
|
53
49
|
end
|
54
50
|
|
55
|
-
def
|
51
|
+
def find_backend
|
56
52
|
backend_type = config.fetch('backend', 'type').downcase
|
57
|
-
backend_proc =
|
53
|
+
backend_proc = Plugin.manager.backends[backend_type]
|
58
54
|
|
59
55
|
klass = backend_proc.call
|
60
|
-
klass.new
|
56
|
+
klass.new(config)
|
61
57
|
end
|
62
58
|
|
63
|
-
def
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
59
|
+
def symlink_errored_tfstate
|
60
|
+
local_path = Pathname.pwd.join('errored.tfstate')
|
61
|
+
remote_path = config.module_dir.join('errored.tfstate')
|
62
|
+
|
63
|
+
# Remove the possibly copied old file
|
64
|
+
local_path.unlink if local_path.exist?
|
65
|
+
|
66
|
+
local_path.make_symlink(remote_path)
|
69
67
|
end
|
70
68
|
end
|
71
69
|
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,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'fileutils'
|
2
4
|
require 'yle_tf/logger'
|
3
5
|
|
@@ -5,10 +7,10 @@ class YleTf
|
|
5
7
|
module Action
|
6
8
|
class WriteTerraformrcDefaults
|
7
9
|
# Path of the Terraform CLI configuration file
|
8
|
-
RC_PATH = '~/.terraformrc'
|
10
|
+
RC_PATH = '~/.terraformrc'
|
9
11
|
|
10
12
|
# Path of the plugin cache directory
|
11
|
-
DEFAULT_PLUGIN_CACHE_PATH = '
|
13
|
+
DEFAULT_PLUGIN_CACHE_PATH = '$HOME/.terraform.d/plugin-cache'
|
12
14
|
|
13
15
|
def initialize(app)
|
14
16
|
@app = app
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
class YleTf
|
6
|
+
class Backend
|
7
|
+
BACKEND_CONFIG_FILE = '_backend.tf.json'
|
8
|
+
|
9
|
+
attr_reader :config
|
10
|
+
|
11
|
+
def initialize(config)
|
12
|
+
@config = config
|
13
|
+
end
|
14
|
+
|
15
|
+
def type
|
16
|
+
@type ||= config.fetch('backend', 'type')
|
17
|
+
end
|
18
|
+
|
19
|
+
def backend_specific_config
|
20
|
+
config.fetch('backend', type)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Generate backend configuration file for Terraform
|
24
|
+
def configure
|
25
|
+
data = {
|
26
|
+
terraform: [{
|
27
|
+
backend: [to_h]
|
28
|
+
}]
|
29
|
+
}
|
30
|
+
File.write(BACKEND_CONFIG_FILE, JSON.pretty_generate(data))
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns the backend configuration as a `Hash` for Terraform
|
34
|
+
def to_h
|
35
|
+
{ type => backend_specific_config }
|
36
|
+
end
|
37
|
+
|
38
|
+
def to_s
|
39
|
+
to_h.to_s
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/yle_tf/cli.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'yle_tf'
|
2
4
|
|
3
5
|
class YleTf
|
@@ -48,7 +50,7 @@ class YleTf
|
|
48
50
|
if TF_OPTIONS.include?(arg)
|
49
51
|
@tf_options[key(arg)] = true
|
50
52
|
else
|
51
|
-
|
53
|
+
warn "Unknown option '#{arg}'"
|
52
54
|
@tf_command = 'help'
|
53
55
|
@tf_env = 'error'
|
54
56
|
break
|
data/lib/yle_tf/config.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'pathname'
|
2
4
|
require 'yaml'
|
3
5
|
|
@@ -10,16 +12,23 @@ class YleTf
|
|
10
12
|
class Config
|
11
13
|
NotFoundError = Class.new(Error)
|
12
14
|
|
13
|
-
|
15
|
+
# Loads the configuration based on the environment
|
16
|
+
def self.load(tf_env)
|
17
|
+
opts = {
|
18
|
+
tf_env: tf_env,
|
19
|
+
module_dir: Pathname.pwd
|
20
|
+
}
|
14
21
|
|
15
|
-
|
16
|
-
|
22
|
+
config = Loader.new(opts).load
|
23
|
+
new(config, **opts)
|
24
|
+
end
|
17
25
|
|
18
|
-
|
19
|
-
@module_dir = Pathname.pwd
|
20
|
-
@config = Loader.new(tf_env: tf_env, module_dir: module_dir).load
|
26
|
+
attr_reader :config, :tf_env, :module_dir
|
21
27
|
|
22
|
-
|
28
|
+
def initialize(config, **opts)
|
29
|
+
@config = config
|
30
|
+
@tf_env = opts[:tf_env]
|
31
|
+
@module_dir = opts[:module_dir]
|
23
32
|
end
|
24
33
|
|
25
34
|
def to_s
|
@@ -33,8 +42,15 @@ class YleTf
|
|
33
42
|
block ||= DEFAULT_NOT_FOUND_BLOCK
|
34
43
|
|
35
44
|
keys.inject(config) do |conf, key|
|
36
|
-
|
37
|
-
|
45
|
+
next conf[key] if conf.is_a?(Hash) && conf.key?(key)
|
46
|
+
|
47
|
+
if !conf.nil? && !conf.is_a?(Hash)
|
48
|
+
Logger.warn(
|
49
|
+
"Configuration [#{keys.join(' > ')}] includes non-hash element #{conf.inspect}"
|
50
|
+
)
|
51
|
+
end
|
52
|
+
|
53
|
+
break block.call(keys)
|
38
54
|
end
|
39
55
|
end
|
40
56
|
|