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
@@ -1,33 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yle_tf/helpers/hash'
|
4
|
+
|
1
5
|
class YleTf
|
2
6
|
class Config
|
3
7
|
module Defaults
|
4
8
|
DEFAULT_CONFIG = {
|
5
|
-
'hooks'
|
6
|
-
'pre'
|
9
|
+
'hooks' => {
|
10
|
+
'pre' => [],
|
7
11
|
'post' => []
|
8
12
|
},
|
9
|
-
'backend'
|
13
|
+
'backend' => {
|
10
14
|
'type' => 'file',
|
11
|
-
'
|
12
|
-
|
13
|
-
|
14
|
-
'
|
15
|
+
'file' => {
|
16
|
+
'path' => '<%= @module %>_<%= @env %>.tfstate'
|
17
|
+
},
|
18
|
+
's3' => {
|
19
|
+
'key' => '<%= @module %>_<%= @env %>.tfstate'
|
20
|
+
}
|
15
21
|
},
|
16
|
-
'tfvars'
|
22
|
+
'tfvars' => {
|
17
23
|
},
|
18
24
|
'terraform' => {
|
19
25
|
'version_requirement' => nil
|
26
|
+
},
|
27
|
+
'yle_tf' => {
|
28
|
+
'version_requirement' => nil
|
20
29
|
}
|
21
30
|
}.freeze
|
22
31
|
|
32
|
+
# Returns deep copy of the default config Hash.
|
23
33
|
def default_config
|
24
|
-
DEFAULT_CONFIG
|
34
|
+
Helpers::Hash.deep_copy(DEFAULT_CONFIG)
|
25
35
|
end
|
26
36
|
|
27
37
|
def default_config_context
|
28
38
|
{
|
29
|
-
env:
|
30
|
-
module:
|
39
|
+
env: tf_env,
|
40
|
+
module: module_dir.basename.to_s,
|
41
|
+
module_dir: module_dir.to_s,
|
31
42
|
}
|
32
43
|
end
|
33
44
|
end
|
data/lib/yle_tf/config/erb.rb
CHANGED
data/lib/yle_tf/config/file.rb
CHANGED
data/lib/yle_tf/config/loader.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'yle_tf/config/defaults'
|
2
4
|
require 'yle_tf/config/erb'
|
3
5
|
require 'yle_tf/config/file'
|
6
|
+
require 'yle_tf/config/migration'
|
7
|
+
require 'yle_tf/helpers/hash'
|
4
8
|
require 'yle_tf/logger'
|
5
9
|
require 'yle_tf/plugin'
|
6
10
|
|
7
|
-
require_relative '../../../vendor/hash_deep_merge'
|
8
|
-
|
9
11
|
class YleTf
|
10
12
|
class Config
|
11
13
|
class Loader
|
@@ -19,20 +21,88 @@ class YleTf
|
|
19
21
|
end
|
20
22
|
|
21
23
|
def load
|
22
|
-
|
23
|
-
|
24
|
-
|
24
|
+
load_sequence = %i[
|
25
|
+
load_default_config
|
26
|
+
load_plugin_configurations
|
27
|
+
load_config_files
|
28
|
+
evaluate_configuration_strings
|
29
|
+
]
|
30
|
+
load_sequence.inject({}) { |config, method| send(method, config) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def load_default_config(_config)
|
34
|
+
task('Loading default config') { default_config }
|
35
|
+
end
|
36
|
+
|
37
|
+
def load_plugin_configurations(config)
|
38
|
+
Logger.debug('Loading configuration from plugins')
|
39
|
+
|
40
|
+
plugins.inject(config) do |prev_config, plugin|
|
41
|
+
migrate_and_merge_configuration(prev_config, plugin.default_config,
|
42
|
+
type: 'plugin', name: plugin.to_s)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def load_config_files(config)
|
47
|
+
Logger.debug('Loading configuration from files')
|
48
|
+
|
49
|
+
config_files.inject(config) do |prev_config, file|
|
50
|
+
migrate_and_merge_configuration(prev_config, file.read,
|
51
|
+
type: 'file', name: file.name)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def evaluate_configuration_strings(config)
|
56
|
+
task('Evaluating the configuration strings') { eval_config(config) }
|
57
|
+
end
|
58
|
+
|
59
|
+
def eval_config(config)
|
60
|
+
case config
|
61
|
+
when Hash
|
62
|
+
config.each_with_object({}) { |(key, value), h| h[key] = eval_config(value) }
|
63
|
+
when Array
|
64
|
+
config.map { |item| eval_config(item) }
|
65
|
+
when String
|
66
|
+
Config::ERB.evaluate(config, config_context)
|
67
|
+
else
|
68
|
+
config
|
69
|
+
end
|
70
|
+
end
|
25
71
|
|
26
|
-
|
27
|
-
|
28
|
-
|
72
|
+
def plugins
|
73
|
+
Plugin.manager.registered
|
74
|
+
end
|
75
|
+
|
76
|
+
def config_files
|
77
|
+
module_dir.descend.lazy
|
78
|
+
.map { |dir| dir.join('tf.yaml') }
|
79
|
+
.select(&:exist?)
|
80
|
+
.map { |file| Config::File.new(file) }
|
81
|
+
end
|
29
82
|
|
30
|
-
|
31
|
-
|
32
|
-
|
83
|
+
def migrate_and_merge_configuration(prev_config, config, **opts)
|
84
|
+
task("- #{opts[:name]}") { config }
|
85
|
+
return prev_config if config.empty?
|
33
86
|
|
34
|
-
|
35
|
-
|
87
|
+
source = "#{opts[:type]}: '#{opts[:name]}'"
|
88
|
+
config = migrate_old_config(config, source: source)
|
89
|
+
deep_merge(prev_config, config, source: source)
|
90
|
+
end
|
91
|
+
|
92
|
+
def migrate_old_config(config, **opts)
|
93
|
+
task(' -> Migrating') do
|
94
|
+
Config::Migration.migrate_old_config(config, **opts)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def deep_merge(prev_config, config, **opts)
|
99
|
+
task(' -> Merging') do
|
100
|
+
Helpers::Hash.deep_merge(prev_config, config)
|
101
|
+
end
|
102
|
+
rescue StandardError => e
|
103
|
+
Logger.fatal("Failed to merge configuration from #{opts[:source]}:\n" \
|
104
|
+
"#{config.inspect}\ninto:\n#{prev_config.inspect}")
|
105
|
+
raise e
|
36
106
|
end
|
37
107
|
|
38
108
|
def config_context
|
@@ -54,53 +124,13 @@ class YleTf
|
|
54
124
|
end
|
55
125
|
end
|
56
126
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
error_msg:
|
62
|
-
"Failed to merge a plugin's default configuration:\n" \
|
63
|
-
"#{plugin_config.inspect}\ninto:\n#{config.inspect}"
|
64
|
-
)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def merge_config_files(config)
|
69
|
-
config_files do |file|
|
70
|
-
Logger.debug(" - #{file}")
|
71
|
-
deep_merge(
|
72
|
-
config, file.read,
|
73
|
-
error_msg:
|
74
|
-
"Failed to merge configuration from '#{file}' into:\n" \
|
75
|
-
"#{config.inspect}"
|
76
|
-
)
|
77
|
-
end
|
78
|
-
end
|
127
|
+
# Helper to print debug information about the task and configuration
|
128
|
+
# after it
|
129
|
+
def task(message = nil)
|
130
|
+
Logger.debug(message) if message
|
79
131
|
|
80
|
-
|
81
|
-
|
82
|
-
rescue StandardError => e
|
83
|
-
Logger.fatal(opts[:error_msg]) if opts[:error_msg]
|
84
|
-
raise e
|
85
|
-
end
|
86
|
-
|
87
|
-
def config_files
|
88
|
-
module_dir.descend do |dir|
|
89
|
-
file = dir.join('tf.yaml')
|
90
|
-
yield(Config::File.new(file)) if file.exist?
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def eval_config(config)
|
95
|
-
case config
|
96
|
-
when Hash
|
97
|
-
config.each_with_object({}) { |(key, value), h| h[key] = eval_config(value) }
|
98
|
-
when Array
|
99
|
-
config.map { |item| eval_config(item) }
|
100
|
-
when String
|
101
|
-
Config::ERB.evaluate(config, config_context)
|
102
|
-
else
|
103
|
-
config
|
132
|
+
yield.tap do |config|
|
133
|
+
Logger.debug(" #{config.inspect}")
|
104
134
|
end
|
105
135
|
end
|
106
136
|
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'yle_tf/helpers/hash'
|
5
|
+
require 'yle_tf/logger'
|
6
|
+
|
7
|
+
class YleTf
|
8
|
+
class Config
|
9
|
+
class Migration
|
10
|
+
BACKEND_MIGRATIONS = {
|
11
|
+
'file' => {
|
12
|
+
'file' => 'path'
|
13
|
+
},
|
14
|
+
's3' => {
|
15
|
+
'region' => 'region',
|
16
|
+
'bucket' => 'bucket',
|
17
|
+
'file' => 'key',
|
18
|
+
'encrypt' => 'encrypt'
|
19
|
+
},
|
20
|
+
'swift' => {
|
21
|
+
'region' => 'region_name',
|
22
|
+
'container' => 'container',
|
23
|
+
'archive_container' => 'archive_container'
|
24
|
+
}
|
25
|
+
}.freeze
|
26
|
+
|
27
|
+
include Helpers::Hash
|
28
|
+
|
29
|
+
def self.migrate_old_config(config, **opts)
|
30
|
+
new(config, **opts).migrated_config
|
31
|
+
end
|
32
|
+
|
33
|
+
attr_reader :config, :config_source
|
34
|
+
|
35
|
+
def initialize(config, **opts)
|
36
|
+
@config = config
|
37
|
+
@config_source = opts.fetch(:source)
|
38
|
+
end
|
39
|
+
|
40
|
+
def old_backend_config
|
41
|
+
config['backend']
|
42
|
+
end
|
43
|
+
|
44
|
+
def migrated_config
|
45
|
+
migrate_old_backend_config(&deprecation_warning)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Returns a `Proc` to print deprecation warnings unless denied by an env var
|
49
|
+
def deprecation_warning
|
50
|
+
return nil if ENV['TF_OLD_CONFIG_WARNINGS'] == 'false'
|
51
|
+
|
52
|
+
lambda do |new_config|
|
53
|
+
Logger.warn("Old configuration found in #{config_source}")
|
54
|
+
Logger.warn("Please migrate to relevant parts of:\n" \
|
55
|
+
"#{sanitize_config(new_config)}")
|
56
|
+
Logger.warn(
|
57
|
+
'See https://github.com/Yleisradio/yle_tf/wiki/Migrating-Configuration for more details'
|
58
|
+
)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# TODO: Remove support in v2.0
|
63
|
+
def migrate_old_backend_config
|
64
|
+
changed = false
|
65
|
+
|
66
|
+
new_config = BACKEND_MIGRATIONS.inject(config) do |prev_config, (type, keys)|
|
67
|
+
migrate_old_backend_config_keys(prev_config, type, keys) { changed = true }
|
68
|
+
end
|
69
|
+
|
70
|
+
yield(new_config) if changed && block_given?
|
71
|
+
|
72
|
+
new_config
|
73
|
+
end
|
74
|
+
|
75
|
+
def migrate_old_backend_config_keys(config, type, keys)
|
76
|
+
migrated_keys = find_old_backend_config_keys(keys)
|
77
|
+
return config if migrated_keys.empty?
|
78
|
+
|
79
|
+
defaults = {
|
80
|
+
'backend' => {
|
81
|
+
type => {}
|
82
|
+
}
|
83
|
+
}
|
84
|
+
copy_with_defaults(config, defaults).tap do |new_config|
|
85
|
+
migrated_keys.each do |old_key, new_key|
|
86
|
+
new_config['backend'][type][new_key] = old_backend_config[old_key]
|
87
|
+
end
|
88
|
+
|
89
|
+
yield new_config
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def find_old_backend_config_keys(keys)
|
94
|
+
return {} if !old_backend_config.is_a?(Hash)
|
95
|
+
|
96
|
+
keys.select do |old_key, _new_key|
|
97
|
+
old_backend_config.key?(old_key) &&
|
98
|
+
# Special case for 'file' as it is now used for option Hash for the
|
99
|
+
# 'file' backend
|
100
|
+
!(old_key == 'file' && old_backend_config['file'].is_a?(Hash))
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def copy_with_defaults(config, defaults)
|
105
|
+
deep_merge(deep_copy(config), defaults)
|
106
|
+
end
|
107
|
+
|
108
|
+
def sanitize_config(config)
|
109
|
+
backend_config = config['backend'].select do |key, value|
|
110
|
+
key == 'type' || value.is_a?(Hash)
|
111
|
+
end
|
112
|
+
|
113
|
+
YAML.dump('backend' => backend_config)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
data/lib/yle_tf/error.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../../vendor/hash_deep_merge'
|
4
|
+
|
5
|
+
class YleTf
|
6
|
+
module Helpers
|
7
|
+
module Hash
|
8
|
+
module_function
|
9
|
+
|
10
|
+
# Returns deep merged new Hash
|
11
|
+
def deep_merge(target, source)
|
12
|
+
target.deep_merge(source)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns deep copy of a Hash.
|
16
|
+
# `dup` and `clone` only return shallow copies.
|
17
|
+
def deep_copy(hash)
|
18
|
+
Marshal.load(Marshal.dump(hash))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/yle_tf/logger.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'forwardable'
|
2
4
|
require 'logger'
|
3
5
|
require 'rubygems'
|
@@ -21,7 +23,6 @@ class YleTf
|
|
21
23
|
|
22
24
|
def self.logger
|
23
25
|
@logger ||= ::Logger.new(DEVICE).tap do |logger|
|
24
|
-
patch_for_old_ruby(logger)
|
25
26
|
logger.level = log_level
|
26
27
|
logger.formatter = log_formatter
|
27
28
|
end
|
@@ -63,14 +64,5 @@ class YleTf
|
|
63
64
|
:brown
|
64
65
|
end
|
65
66
|
end
|
66
|
-
|
67
|
-
# Patches the `::Logger` in older Ruby versions to
|
68
|
-
# accept log level as a `String`
|
69
|
-
def self.patch_for_old_ruby(logger)
|
70
|
-
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.3')
|
71
|
-
require_relative '../../vendor/logger_level_patch'
|
72
|
-
logger.extend(LoggerLevelPatch)
|
73
|
-
end
|
74
|
-
end
|
75
67
|
end
|
76
68
|
end
|
data/lib/yle_tf/plugin.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class YleTf
|
2
4
|
class Plugin
|
3
5
|
autoload :ActionHook, 'yle_tf/plugin/action_hook'
|
4
6
|
autoload :Loader, 'yle_tf/plugin/loader'
|
5
7
|
autoload :Manager, 'yle_tf/plugin/manager'
|
6
8
|
|
9
|
+
DEFAULT_BACKEND = Object.new.freeze
|
7
10
|
DEFAULT_COMMAND = Object.new.freeze
|
8
11
|
|
9
12
|
def self.manager
|
@@ -30,7 +33,7 @@ class YleTf
|
|
30
33
|
name = name.to_s if name.is_a?(Symbol)
|
31
34
|
commands[name] = {
|
32
35
|
synopsis: synopsis,
|
33
|
-
proc:
|
36
|
+
proc: block
|
34
37
|
}
|
35
38
|
end
|
36
39
|
|
@@ -49,7 +52,8 @@ class YleTf
|
|
49
52
|
end
|
50
53
|
|
51
54
|
def self.backend(type, &block)
|
52
|
-
|
55
|
+
type = type.to_s if type.is_a?(Symbol)
|
56
|
+
backends[type] = block
|
53
57
|
end
|
54
58
|
end
|
55
59
|
end
|