simplygenius-atmos 0.11.4 → 0.11.5
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/CHANGELOG.md +10 -0
- data/lib/simplygenius/atmos/cli.rb +28 -2
- data/lib/simplygenius/atmos/commands/tfutil.rb +129 -0
- data/lib/simplygenius/atmos/config.rb +5 -5
- data/lib/simplygenius/atmos/terraform_executor.rb +12 -8
- data/lib/simplygenius/atmos/version.rb +1 -1
- data/templates/new/config/atmos/runtime.yml +3 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: afa120dcd3c2081998e5a215a4590553a2545f699ad9cbd17e585b6f51784045
|
4
|
+
data.tar.gz: eeb60c1ed55ea88b7b34970cf752289b8a6eb7f64b67221e063a5f27ce1949f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 964094b4a7e12e23dadb011872cb5cddde9353e472d0cf17f1c168ae3a66ff4fddceca55a1a20c4d0bd8886e87937de717e84ffe60c08b89bd4513867ad8a2c8
|
7
|
+
data.tar.gz: 381ed5d125cd3dc1fca56d30e6d1e13c2356f4e5c61320e02d808d5180d7f7f00d86a36e72c630ce2842955183d4a49952bd92ee18fa82a0aaac3e2c7de804cb
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
0.11.5 (12/12/2019)
|
2
|
+
-------------------
|
3
|
+
|
4
|
+
* fix usage to include exe name and add -v for checking version [64a6183](https://github.com/simplygenius/atmos/commit/64a6183)
|
5
|
+
* allow setting atmos root/config_file from env, and pass it down to subprocesses so that tfutil can act the same from the terraform working dir [c417d4c](https://github.com/simplygenius/atmos/commit/c417d4c)
|
6
|
+
* add tfutil.jsonify to make it easier to call out from terraform data.external [c9bfdf5](https://github.com/simplygenius/atmos/commit/c9bfdf5)
|
7
|
+
* add ability to dump config as json [9e6176f](https://github.com/simplygenius/atmos/commit/9e6176f)
|
8
|
+
* allow customization of what gets linked into terraform working dir [115e460](https://github.com/simplygenius/atmos/commit/115e460)
|
9
|
+
|
10
|
+
|
1
11
|
0.11.4 (11/27/2019)
|
2
12
|
-------------------
|
3
13
|
|
@@ -51,6 +51,9 @@ module SimplyGenius
|
|
51
51
|
"PATH", "adds additional paths to ruby load path",
|
52
52
|
multivalued: true
|
53
53
|
|
54
|
+
option ["-v", "--version"],
|
55
|
+
:flag, "Shows the atmos version"
|
56
|
+
|
54
57
|
def default_color?
|
55
58
|
$stdout.tty?
|
56
59
|
end
|
@@ -88,6 +91,8 @@ module SimplyGenius
|
|
88
91
|
Commands::AuthExec
|
89
92
|
subcommand "container", "Container tools",
|
90
93
|
Commands::Container
|
94
|
+
subcommand "tfutil", "Terraform tools",
|
95
|
+
Commands::TfUtil
|
91
96
|
|
92
97
|
subcommand "version", "Display version" do
|
93
98
|
def execute
|
@@ -96,8 +101,17 @@ module SimplyGenius
|
|
96
101
|
end
|
97
102
|
|
98
103
|
subcommand "config", "Display expanded config for atmos_env" do
|
104
|
+
|
105
|
+
option ["-j", "--json"],
|
106
|
+
:flag, "Dump config as json instead of yaml"
|
107
|
+
|
99
108
|
def execute
|
100
|
-
|
109
|
+
if json?
|
110
|
+
output = JSON.pretty_generate(Atmos.config.to_h)
|
111
|
+
else
|
112
|
+
output = YAML.dump(Atmos.config.to_h)
|
113
|
+
end
|
114
|
+
logger.info output
|
101
115
|
end
|
102
116
|
end
|
103
117
|
|
@@ -118,14 +132,26 @@ module SimplyGenius
|
|
118
132
|
|
119
133
|
Atmos.config.add_user_load_path(*load_path_list)
|
120
134
|
Atmos.config.plugin_manager.load_plugins
|
135
|
+
|
136
|
+
# So we can show just the version with the -v flag
|
137
|
+
if version?
|
138
|
+
logger.info "Atmos Version #{VERSION}"
|
139
|
+
exit(0)
|
140
|
+
end
|
121
141
|
end
|
122
142
|
end
|
123
143
|
|
124
144
|
# Hook into clamp lifecycle to globally handle errors
|
125
145
|
class << self
|
126
|
-
def run(
|
146
|
+
def run(invocation_path = File.basename($PROGRAM_NAME), arguments = ARGV, context = {})
|
127
147
|
begin
|
128
148
|
super
|
149
|
+
rescue SystemExit => e
|
150
|
+
if ! e.success?
|
151
|
+
logger.log_exception(e, "Failure exit", level: :debug)
|
152
|
+
logger.error(e.message)
|
153
|
+
raise
|
154
|
+
end
|
129
155
|
rescue Exception => e
|
130
156
|
logger.log_exception(e, "Unhandled exception", level: :debug)
|
131
157
|
logger.error(e.message)
|
@@ -0,0 +1,129 @@
|
|
1
|
+
require_relative 'base_command'
|
2
|
+
require 'json'
|
3
|
+
require 'open3'
|
4
|
+
require 'clipboard'
|
5
|
+
|
6
|
+
module SimplyGenius
|
7
|
+
module Atmos
|
8
|
+
module Commands
|
9
|
+
|
10
|
+
class TfUtil < BaseCommand
|
11
|
+
|
12
|
+
def self.description
|
13
|
+
"Useful utilities when calling out from terraform with data.external"
|
14
|
+
end
|
15
|
+
|
16
|
+
subcommand "jsonify", "Manages json on stdin/out to conform\nto use in terraform data.external" do
|
17
|
+
|
18
|
+
banner "Ensures json output only contains a single level Hash with string values (e.g. when execing curl returns a deep json hash of mixed values)"
|
19
|
+
|
20
|
+
option ["-a", "--atmos_config"],
|
21
|
+
:flag, "Includes the atmos config in the\nhash from parsing json on stdin"
|
22
|
+
|
23
|
+
option ["-c", "--clipboard"],
|
24
|
+
:flag, "Copies the actual command used\nto the clipboard to allow external debugging"
|
25
|
+
|
26
|
+
option ["-j", "--json"],
|
27
|
+
:flag, "The command output is parsed as json"
|
28
|
+
|
29
|
+
option ["-x", "--[no-]exit"],
|
30
|
+
:flag, "Exit with the command's exit code\non failure (or not)", default: true
|
31
|
+
|
32
|
+
parameter "COMMAND ...",
|
33
|
+
"The command to call", :attribute_name => :command
|
34
|
+
|
35
|
+
# Recursively converts all values to strings as required by terraform data.external
|
36
|
+
def stringify(obj)
|
37
|
+
case obj
|
38
|
+
when Hash
|
39
|
+
Hash[obj.collect {|k, v| [k, stringify(v)] }]
|
40
|
+
when Array
|
41
|
+
obj.collect {|v| stringify(v) }
|
42
|
+
else
|
43
|
+
obj.to_s
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Makes a hash have only a single level as required by terraform data.external
|
48
|
+
def flatten(obj)
|
49
|
+
result = {}
|
50
|
+
|
51
|
+
if obj.is_a? Hash
|
52
|
+
obj.each do |k, v|
|
53
|
+
ev = case v
|
54
|
+
when String
|
55
|
+
v
|
56
|
+
when Hash, Array
|
57
|
+
JSON.generate(v)
|
58
|
+
else
|
59
|
+
v.to_s
|
60
|
+
end
|
61
|
+
result[k] = ev
|
62
|
+
end
|
63
|
+
else
|
64
|
+
result["data"] = JSON.generate(result)
|
65
|
+
end
|
66
|
+
|
67
|
+
return result
|
68
|
+
end
|
69
|
+
|
70
|
+
def maybe_read_stdin
|
71
|
+
data = nil
|
72
|
+
begin
|
73
|
+
chunk = $stdin.read_nonblock(1)
|
74
|
+
data = chunk + $stdin.read
|
75
|
+
logger.debug("Received stdin: " + data)
|
76
|
+
rescue Errno::EAGAIN
|
77
|
+
data = nil
|
78
|
+
logger.debug("No stdin")
|
79
|
+
end
|
80
|
+
return data
|
81
|
+
end
|
82
|
+
|
83
|
+
def execute
|
84
|
+
params = JSON.parse(maybe_read_stdin || '{}')
|
85
|
+
params = SettingsHash.new(params)
|
86
|
+
params.enable_expansion = true
|
87
|
+
if atmos_config?
|
88
|
+
params = Atmos.config.config_merge(SettingsHash.new(Atmos.config.to_h), params)
|
89
|
+
end
|
90
|
+
expanded_command = command.collect {|c| params.expand_string(c) }
|
91
|
+
|
92
|
+
begin
|
93
|
+
formatted_command = expanded_command.collect {|a| "'#{a}'" }.join(" ")
|
94
|
+
logger.debug("Running command: #{formatted_command}")
|
95
|
+
Clipboard.copy(formatted_command) if clipboard?
|
96
|
+
|
97
|
+
cmd_opts = {}
|
98
|
+
cmd_opts[:stdin_data] = params[:stdin] if params.key?(:stdin)
|
99
|
+
stdout, stderr, status = Open3.capture3(*expanded_command, **cmd_opts)
|
100
|
+
result = {stdout: stdout, stderr: stderr, exitcode: status.exitstatus.to_s}
|
101
|
+
logger.debug("Command result: #{result.inspect}")
|
102
|
+
|
103
|
+
if exit? && status.exitstatus != 0
|
104
|
+
$stderr.puts stdout
|
105
|
+
$stderr.puts stderr
|
106
|
+
exit status.exitstatus
|
107
|
+
end
|
108
|
+
|
109
|
+
if json?
|
110
|
+
result = result.merge(flatten(stringify(JSON.parse(stdout))))
|
111
|
+
end
|
112
|
+
|
113
|
+
logger.debug("Json output: #{result.inspect}")
|
114
|
+
$stdout.puts JSON.generate(result)
|
115
|
+
|
116
|
+
rescue => e
|
117
|
+
$stderr.puts("#{e.class}: #{e.message}")
|
118
|
+
exit 1
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -19,11 +19,11 @@ module SimplyGenius
|
|
19
19
|
:user_config_file,
|
20
20
|
:tmp_root
|
21
21
|
|
22
|
-
def initialize(atmos_env, working_group = 'default')
|
22
|
+
def initialize(atmos_env, working_group = 'default', root: ENV['ATMOS_ROOT'], config: ENV['ATMOS_CONFIG'])
|
23
23
|
@atmos_env = atmos_env
|
24
24
|
@working_group = working_group
|
25
|
-
@root_dir = File.expand_path(Dir.pwd)
|
26
|
-
@config_file = File.join(root_dir, "config", "atmos.yml")
|
25
|
+
@root_dir = File.expand_path(root || Dir.pwd)
|
26
|
+
@config_file = config ? File.expand_path(config, root_dir) : File.join(root_dir, "config", "atmos.yml")
|
27
27
|
@user_config_file = "~/.atmos.yml"
|
28
28
|
@tmp_root = File.join(root_dir, "tmp")
|
29
29
|
@included_configs = []
|
@@ -119,8 +119,6 @@ module SimplyGenius
|
|
119
119
|
File.chmod(0600, user_config_file)
|
120
120
|
end
|
121
121
|
|
122
|
-
private
|
123
|
-
|
124
122
|
def config_merge(lhs, rhs, debug_state=[])
|
125
123
|
result = nil
|
126
124
|
|
@@ -168,6 +166,8 @@ module SimplyGenius
|
|
168
166
|
return result
|
169
167
|
end
|
170
168
|
|
169
|
+
private
|
170
|
+
|
171
171
|
def load_config_sources(relative_root, config, *patterns)
|
172
172
|
patterns.each do |pattern|
|
173
173
|
logger.debug("Loading atmos config files using pattern: #{pattern}")
|
@@ -54,6 +54,8 @@ module SimplyGenius
|
|
54
54
|
logger.debug("Running terraform: #{cmd.join(' ')}")
|
55
55
|
|
56
56
|
env = Hash[@process_env]
|
57
|
+
env['ATMOS_ROOT'] = Atmos.config.root_dir
|
58
|
+
env['ATMOS_CONFIG'] = Atmos.config.config_file
|
57
59
|
if ! skip_secrets
|
58
60
|
begin
|
59
61
|
env = env.merge(secrets_env)
|
@@ -84,7 +86,7 @@ module SimplyGenius
|
|
84
86
|
|
85
87
|
stdout_thr = pipe_stream(stdout, output_io.nil? ? $stdout : output_io, &stdout_filters.filter_block)
|
86
88
|
stderr_thr = pipe_stream(stderr, output_io.nil? ? $stderr : output_io, &stderr_filters.filter_block)
|
87
|
-
|
89
|
+
status = nil
|
88
90
|
ipc.listen do |sock_path|
|
89
91
|
|
90
92
|
if Atmos.config['atmos.ipc.disable']
|
@@ -111,12 +113,12 @@ module SimplyGenius
|
|
111
113
|
|
112
114
|
logger.debug("Terraform started with pid #{pid}")
|
113
115
|
begin
|
114
|
-
Process.
|
116
|
+
_, status = Process.wait2(pid)
|
115
117
|
rescue Interrupt
|
116
118
|
logger.warn "Got SIGINT, sending to terraform pid=#{pid}"
|
117
119
|
|
118
120
|
Process.kill("INT", pid)
|
119
|
-
Process.
|
121
|
+
_, status = Process.wait2(pid)
|
120
122
|
|
121
123
|
logger.debug "Completed signal cleanup"
|
122
124
|
exit!(1)
|
@@ -131,10 +133,10 @@ module SimplyGenius
|
|
131
133
|
stdout_filters.close
|
132
134
|
stderr_filters.close
|
133
135
|
|
134
|
-
|
135
|
-
logger.debug("Terraform exited: #{
|
136
|
-
if
|
137
|
-
raise ProcessFailed.new "Terraform exited with non-zero exit code: #{
|
136
|
+
exitcode = status.exitstatus
|
137
|
+
logger.debug("Terraform exited: #{exitcode}")
|
138
|
+
if exitcode != 0
|
139
|
+
raise ProcessFailed.new "Terraform exited with non-zero exit code: #{exitcode}"
|
138
140
|
end
|
139
141
|
|
140
142
|
end
|
@@ -301,7 +303,9 @@ module SimplyGenius
|
|
301
303
|
end
|
302
304
|
|
303
305
|
def link_support_dirs
|
304
|
-
|
306
|
+
working_dir_links = Atmos.config['atmos.terraform.working_dir_links']
|
307
|
+
working_dir_links ||= ['modules', 'templates']
|
308
|
+
working_dir_links.each do |subdir|
|
305
309
|
source = File.join(Atmos.config.root_dir, subdir)
|
306
310
|
ln_sf(source, Atmos.config.tf_working_dir) if File.exist?(source)
|
307
311
|
end
|
@@ -120,5 +120,8 @@ atmos:
|
|
120
120
|
# env/group combination will be independent and download all plugins for
|
121
121
|
# itself only
|
122
122
|
disable_shared_plugins: false
|
123
|
+
# Customize what gets linked into the working directory that terraform gets
|
124
|
+
# executed in
|
125
|
+
working_dir_links: ['modules', 'templates', 'bin', '.terraform-version']
|
123
126
|
# Set true if running terraform version < 0.11.x
|
124
127
|
compat11: false
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: simplygenius-atmos
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.11.
|
4
|
+
version: 0.11.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matt Conway
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-12-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -531,6 +531,7 @@ files:
|
|
531
531
|
- lib/simplygenius/atmos/commands/plan.rb
|
532
532
|
- lib/simplygenius/atmos/commands/secret.rb
|
533
533
|
- lib/simplygenius/atmos/commands/terraform.rb
|
534
|
+
- lib/simplygenius/atmos/commands/tfutil.rb
|
534
535
|
- lib/simplygenius/atmos/commands/user.rb
|
535
536
|
- lib/simplygenius/atmos/config.rb
|
536
537
|
- lib/simplygenius/atmos/exceptions.rb
|