simplygenius-atmos 0.11.4 → 0.11.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|