simplygenius-atmos 0.7.1 → 0.8.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/README.md +4 -4
- data/exe/atmos +2 -2
- data/lib/{atmos.rb → simplygenius/atmos.rb} +9 -7
- data/lib/simplygenius/atmos/cli.rb +116 -0
- data/lib/simplygenius/atmos/commands/account.rb +69 -0
- data/lib/simplygenius/atmos/commands/apply.rb +24 -0
- data/lib/simplygenius/atmos/commands/auth_exec.rb +34 -0
- data/lib/simplygenius/atmos/commands/base_command.rb +16 -0
- data/lib/simplygenius/atmos/commands/bootstrap.rb +76 -0
- data/lib/simplygenius/atmos/commands/container.rb +62 -0
- data/lib/simplygenius/atmos/commands/destroy.rb +22 -0
- data/lib/simplygenius/atmos/commands/generate.rb +187 -0
- data/lib/simplygenius/atmos/commands/init.rb +22 -0
- data/lib/simplygenius/atmos/commands/new.rb +22 -0
- data/lib/simplygenius/atmos/commands/otp.rb +58 -0
- data/lib/simplygenius/atmos/commands/plan.rb +24 -0
- data/lib/simplygenius/atmos/commands/secret.rb +91 -0
- data/lib/simplygenius/atmos/commands/terraform.rb +56 -0
- data/lib/simplygenius/atmos/commands/user.rb +78 -0
- data/lib/simplygenius/atmos/config.rb +279 -0
- data/lib/simplygenius/atmos/exceptions.rb +13 -0
- data/lib/simplygenius/atmos/generator.rb +232 -0
- data/lib/simplygenius/atmos/ipc.rb +136 -0
- data/lib/simplygenius/atmos/ipc_actions/notify.rb +31 -0
- data/lib/simplygenius/atmos/ipc_actions/ping.rb +23 -0
- data/lib/simplygenius/atmos/logging.rb +164 -0
- data/lib/simplygenius/atmos/otp.rb +62 -0
- data/lib/simplygenius/atmos/plugin.rb +27 -0
- data/lib/simplygenius/atmos/plugin_manager.rb +120 -0
- data/lib/simplygenius/atmos/plugins/output_filter.rb +29 -0
- data/lib/simplygenius/atmos/plugins/prompt_notify.rb +21 -0
- data/lib/simplygenius/atmos/provider_factory.rb +23 -0
- data/lib/simplygenius/atmos/providers/aws/account_manager.rb +83 -0
- data/lib/simplygenius/atmos/providers/aws/auth_manager.rb +220 -0
- data/lib/simplygenius/atmos/providers/aws/container_manager.rb +118 -0
- data/lib/simplygenius/atmos/providers/aws/provider.rb +53 -0
- data/lib/simplygenius/atmos/providers/aws/s3_secret_manager.rb +51 -0
- data/lib/simplygenius/atmos/providers/aws/user_manager.rb +213 -0
- data/lib/simplygenius/atmos/settings_hash.rb +93 -0
- data/lib/simplygenius/atmos/source_path.rb +186 -0
- data/lib/simplygenius/atmos/template.rb +117 -0
- data/lib/simplygenius/atmos/terraform_executor.rb +297 -0
- data/lib/simplygenius/atmos/ui.rb +173 -0
- data/lib/simplygenius/atmos/utils.rb +54 -0
- data/lib/simplygenius/atmos/version.rb +5 -0
- data/templates/new/config/atmos.yml +21 -13
- data/templates/new/config/atmos/recipes.yml +16 -0
- data/templates/new/config/atmos/runtime.yml +9 -0
- metadata +46 -40
- data/lib/atmos/cli.rb +0 -105
- data/lib/atmos/commands/account.rb +0 -65
- data/lib/atmos/commands/apply.rb +0 -20
- data/lib/atmos/commands/auth_exec.rb +0 -29
- data/lib/atmos/commands/base_command.rb +0 -12
- data/lib/atmos/commands/bootstrap.rb +0 -72
- data/lib/atmos/commands/container.rb +0 -58
- data/lib/atmos/commands/destroy.rb +0 -18
- data/lib/atmos/commands/generate.rb +0 -90
- data/lib/atmos/commands/init.rb +0 -18
- data/lib/atmos/commands/new.rb +0 -18
- data/lib/atmos/commands/otp.rb +0 -54
- data/lib/atmos/commands/plan.rb +0 -20
- data/lib/atmos/commands/secret.rb +0 -87
- data/lib/atmos/commands/terraform.rb +0 -52
- data/lib/atmos/commands/user.rb +0 -74
- data/lib/atmos/config.rb +0 -208
- data/lib/atmos/exceptions.rb +0 -9
- data/lib/atmos/generator.rb +0 -199
- data/lib/atmos/generator_factory.rb +0 -93
- data/lib/atmos/ipc.rb +0 -132
- data/lib/atmos/ipc_actions/notify.rb +0 -27
- data/lib/atmos/ipc_actions/ping.rb +0 -19
- data/lib/atmos/logging.rb +0 -160
- data/lib/atmos/otp.rb +0 -61
- data/lib/atmos/provider_factory.rb +0 -19
- data/lib/atmos/providers/aws/account_manager.rb +0 -82
- data/lib/atmos/providers/aws/auth_manager.rb +0 -208
- data/lib/atmos/providers/aws/container_manager.rb +0 -116
- data/lib/atmos/providers/aws/provider.rb +0 -51
- data/lib/atmos/providers/aws/s3_secret_manager.rb +0 -49
- data/lib/atmos/providers/aws/user_manager.rb +0 -211
- data/lib/atmos/settings_hash.rb +0 -90
- data/lib/atmos/terraform_executor.rb +0 -267
- data/lib/atmos/ui.rb +0 -159
- data/lib/atmos/utils.rb +0 -50
- data/lib/atmos/version.rb +0 -3
@@ -1,267 +0,0 @@
|
|
1
|
-
require_relative '../atmos'
|
2
|
-
require_relative '../atmos/ipc'
|
3
|
-
require_relative '../atmos/ui'
|
4
|
-
require 'open3'
|
5
|
-
require 'fileutils'
|
6
|
-
require 'find'
|
7
|
-
require 'climate_control'
|
8
|
-
|
9
|
-
module Atmos
|
10
|
-
|
11
|
-
class TerraformExecutor
|
12
|
-
include GemLogger::LoggerSupport
|
13
|
-
include FileUtils
|
14
|
-
include Atmos::UI
|
15
|
-
|
16
|
-
class ProcessFailed < RuntimeError; end
|
17
|
-
|
18
|
-
def initialize(process_env: ENV, working_group: 'default')
|
19
|
-
@process_env = process_env
|
20
|
-
@working_group = working_group
|
21
|
-
@working_dir = Atmos.config.tf_working_dir(@working_group)
|
22
|
-
@recipes = Atmos.config["recipes.#{@working_group}"]
|
23
|
-
end
|
24
|
-
|
25
|
-
def run(*terraform_args, skip_backend: false, skip_secrets: false, get_modules: false, output_io: nil)
|
26
|
-
setup_working_dir(skip_backend: skip_backend)
|
27
|
-
|
28
|
-
if get_modules
|
29
|
-
logger.debug("Getting modules")
|
30
|
-
get_modules_io = StringIO.new
|
31
|
-
begin
|
32
|
-
execute("get", output_io: get_modules_io)
|
33
|
-
rescue Atmos::TerraformExecutor::ProcessFailed => e
|
34
|
-
logger.info(get_modules_io.string)
|
35
|
-
raise
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
return execute(*terraform_args, skip_secrets: skip_secrets, output_io: output_io)
|
40
|
-
end
|
41
|
-
|
42
|
-
private
|
43
|
-
|
44
|
-
def tf_cmd(*args)
|
45
|
-
['terraform'] + args
|
46
|
-
end
|
47
|
-
|
48
|
-
def execute(*terraform_args, skip_secrets: false, output_io: nil)
|
49
|
-
cmd = tf_cmd(*terraform_args)
|
50
|
-
logger.debug("Running terraform: #{cmd.join(' ')}")
|
51
|
-
|
52
|
-
env = Hash[@process_env]
|
53
|
-
if ! skip_secrets
|
54
|
-
begin
|
55
|
-
env = env.merge(secrets_env)
|
56
|
-
rescue => e
|
57
|
-
logger.debug("Secrets not available: #{e}")
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
# lets tempfiles create by subprocesses be easily found by users
|
62
|
-
env['TMPDIR'] = Atmos.config.tmp_dir
|
63
|
-
|
64
|
-
# Lets terraform communicate back to atmos, e.g. for UI notifications
|
65
|
-
ipc = Atmos::Ipc.new(Atmos.config.tmp_dir)
|
66
|
-
|
67
|
-
IO.pipe do |stdout, stdout_writer|
|
68
|
-
IO.pipe do |stderr, stderr_writer|
|
69
|
-
|
70
|
-
stdout_writer.sync = stderr_writer.sync = true
|
71
|
-
# TODO: more filtering on terraform output?
|
72
|
-
stdout_thr = pipe_stream(stdout, output_io.nil? ? $stdout : output_io) do |data|
|
73
|
-
if data =~ /^[\e\[\dm\s]*Enter a value:[\e\[\dm\s]*$/
|
74
|
-
notify(message: "Terraform is waiting for user input")
|
75
|
-
end
|
76
|
-
data
|
77
|
-
end
|
78
|
-
stderr_thr = pipe_stream(stderr, output_io.nil? ? $stderr : output_io)
|
79
|
-
|
80
|
-
ipc.listen do |sock_path|
|
81
|
-
|
82
|
-
if Atmos.config['ipc.disable']
|
83
|
-
# Using : as the command makes execution of ipc from the
|
84
|
-
# terraform side a no-op in both cases of how we call it. This
|
85
|
-
# way, terraform execution continues to work when IPC is disabled
|
86
|
-
# command = "$ATMOS_IPC_CLIENT <json_string>"
|
87
|
-
# program = ["sh", "-c", "$ATMOS_IPC_CLIENT"]
|
88
|
-
env['ATMOS_IPC_CLIENT'] = ":"
|
89
|
-
else
|
90
|
-
env['ATMOS_IPC_SOCK'] = sock_path
|
91
|
-
env['ATMOS_IPC_CLIENT'] = ipc.generate_client_script
|
92
|
-
end
|
93
|
-
|
94
|
-
# Was unable to get piping to work with stdin for some reason. It
|
95
|
-
# worked in simple case, but started to fail when terraform config
|
96
|
-
# got more extensive. Thus, using spawn to redirect stdin from the
|
97
|
-
# terminal direct to terraform, with IO.pipe to copy the outher
|
98
|
-
# streams. Maybe in the future we can completely disconnect stdin
|
99
|
-
# and have atmos do the output parsing and stdin prompting
|
100
|
-
pid = spawn(env, *cmd,
|
101
|
-
chdir: tf_recipes_dir,
|
102
|
-
:out=>stdout_writer, :err=> stderr_writer, :in => :in)
|
103
|
-
|
104
|
-
logger.debug("Terraform started with pid #{pid}")
|
105
|
-
Process.wait(pid)
|
106
|
-
end
|
107
|
-
|
108
|
-
stdout_writer.close
|
109
|
-
stderr_writer.close
|
110
|
-
stdout_thr.join
|
111
|
-
stderr_thr.join
|
112
|
-
|
113
|
-
status = $?.exitstatus
|
114
|
-
logger.debug("Terraform exited: #{status}")
|
115
|
-
if status != 0
|
116
|
-
raise ProcessFailed.new "Terraform exited with non-zero exit code: #{status}"
|
117
|
-
end
|
118
|
-
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
end
|
123
|
-
|
124
|
-
def setup_working_dir(skip_backend: false)
|
125
|
-
clean_links
|
126
|
-
link_shared_plugin_dir
|
127
|
-
link_support_dirs
|
128
|
-
link_recipes
|
129
|
-
write_atmos_vars
|
130
|
-
setup_backend(skip_backend)
|
131
|
-
end
|
132
|
-
|
133
|
-
def setup_backend(skip_backend=false)
|
134
|
-
backend_file = File.join(tf_recipes_dir, 'atmos-backend.tf.json')
|
135
|
-
backend_config = (Atmos.config["backend"] || {}).clone
|
136
|
-
|
137
|
-
if backend_config.present? && ! skip_backend
|
138
|
-
logger.debug("Writing out terraform state backend config")
|
139
|
-
|
140
|
-
# Use a different state file per group
|
141
|
-
if @working_group
|
142
|
-
backend_config['key'] = "#{@working_group}-#{backend_config['key']}"
|
143
|
-
end
|
144
|
-
|
145
|
-
backend_type = backend_config.delete("type")
|
146
|
-
|
147
|
-
backend = {
|
148
|
-
"terraform" => {
|
149
|
-
"backend" => {
|
150
|
-
backend_type => backend_config
|
151
|
-
}
|
152
|
-
}
|
153
|
-
}
|
154
|
-
|
155
|
-
File.write(backend_file, JSON.pretty_generate(backend))
|
156
|
-
else
|
157
|
-
logger.debug("Clearing terraform state backend config")
|
158
|
-
File.delete(backend_file) if File.exist?(backend_file)
|
159
|
-
end
|
160
|
-
end
|
161
|
-
|
162
|
-
# terraform currently (v0.11.3) doesn't handle maps with nested maps or
|
163
|
-
# lists well, so flatten them - nested maps get expanded into the top level
|
164
|
-
# one, with their keys being appended with underscores, and lists get
|
165
|
-
# joined with "," so we end up with a single hash with homogenous types
|
166
|
-
def homogenize_for_terraform(h, root={}, prefix="")
|
167
|
-
h.each do |k, v|
|
168
|
-
if v.is_a? Hash
|
169
|
-
homogenize_for_terraform(v, root, "#{k}_")
|
170
|
-
else
|
171
|
-
v = v.join(",") if v.is_a? Array
|
172
|
-
root["#{prefix}#{k}"] = v
|
173
|
-
end
|
174
|
-
end
|
175
|
-
return root
|
176
|
-
end
|
177
|
-
|
178
|
-
def tf_recipes_dir
|
179
|
-
@tf_recipes_dir ||= begin
|
180
|
-
dir = File.join(@working_dir, 'recipes')
|
181
|
-
logger.debug("Tf recipes dir: #{dir}")
|
182
|
-
mkdir_p(dir)
|
183
|
-
dir
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
def write_atmos_vars
|
188
|
-
File.open(File.join(tf_recipes_dir, 'atmos.auto.tfvars.json'), 'w') do |f|
|
189
|
-
atmos_var_config = atmos_config = homogenize_for_terraform(Atmos.config.to_h)
|
190
|
-
|
191
|
-
var_prefix = Atmos.config['var_prefix']
|
192
|
-
if var_prefix
|
193
|
-
atmos_var_config = Hash[atmos_var_config.collect {|k, v| ["#{var_prefix}#{k}", v]}]
|
194
|
-
end
|
195
|
-
|
196
|
-
var_hash = {
|
197
|
-
atmos_env: Atmos.config.atmos_env,
|
198
|
-
all_env_names: Atmos.config.all_env_names,
|
199
|
-
account_ids: Atmos.config.account_hash,
|
200
|
-
atmos_config: atmos_config
|
201
|
-
}
|
202
|
-
var_hash = var_hash.merge(atmos_var_config)
|
203
|
-
f.puts(JSON.pretty_generate(var_hash))
|
204
|
-
end
|
205
|
-
end
|
206
|
-
|
207
|
-
def secrets_env
|
208
|
-
# NOTE use an auto-deleting temp file if passing secrets through env ends
|
209
|
-
# up being problematic
|
210
|
-
# TODO fix the need for CC - TE calls for secrets which needs auth in
|
211
|
-
# ENV, so kinda clunk to have to do both CC and pass the env in
|
212
|
-
ClimateControl.modify(@process_env) do
|
213
|
-
secrets = Atmos.config.provider.secret_manager.to_h
|
214
|
-
env_secrets = Hash[secrets.collect { |k, v| ["TF_VAR_#{k}", v] }]
|
215
|
-
return env_secrets
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
def clean_links
|
220
|
-
Find.find(@working_dir) do |f|
|
221
|
-
Find.prune if f =~ /\/.terraform\/modules\//
|
222
|
-
File.delete(f) if File.symlink?(f)
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
def link_support_dirs
|
227
|
-
['modules', 'templates'].each do |subdir|
|
228
|
-
ln_sf(File.join(Atmos.config.root_dir, subdir), @working_dir)
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
def link_shared_plugin_dir
|
233
|
-
if ! Atmos.config["terraform.disable_shared_plugins"]
|
234
|
-
shared_plugins_dir = File.join(Atmos.config.tmp_root, "terraform_plugins")
|
235
|
-
mkdir_p(shared_plugins_dir)
|
236
|
-
terraform_state_dir = File.join(tf_recipes_dir, '.terraform')
|
237
|
-
mkdir_p(terraform_state_dir)
|
238
|
-
terraform_plugins_dir = File.join(terraform_state_dir, 'plugins')
|
239
|
-
ln_sf(shared_plugins_dir, terraform_plugins_dir)
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
def link_recipes
|
244
|
-
@recipes.each do |recipe|
|
245
|
-
ln_sf(File.join(Atmos.config.root_dir, 'recipes', "#{recipe}.tf"), tf_recipes_dir)
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
def pipe_stream(src, dest)
|
250
|
-
Thread.new do
|
251
|
-
block_size = 1024
|
252
|
-
begin
|
253
|
-
while data = src.readpartial(block_size)
|
254
|
-
data = yield data if block_given?
|
255
|
-
dest.write(data)
|
256
|
-
end
|
257
|
-
rescue EOFError
|
258
|
-
nil
|
259
|
-
rescue Exception => e
|
260
|
-
logger.log_exception(e, "Stream failure")
|
261
|
-
end
|
262
|
-
end
|
263
|
-
end
|
264
|
-
|
265
|
-
end
|
266
|
-
|
267
|
-
end
|
data/lib/atmos/ui.rb
DELETED
@@ -1,159 +0,0 @@
|
|
1
|
-
require_relative '../atmos'
|
2
|
-
require 'highline'
|
3
|
-
require 'rainbow'
|
4
|
-
require 'yaml'
|
5
|
-
require 'open3'
|
6
|
-
require 'os'
|
7
|
-
require 'hashie'
|
8
|
-
|
9
|
-
module OSDockerDetection
|
10
|
-
refine OS.singleton_class do
|
11
|
-
def docker?
|
12
|
-
@docker ||= File.exist?('/.dockerenv')
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
module Atmos
|
18
|
-
module UI
|
19
|
-
extend ActiveSupport::Concern
|
20
|
-
include GemLogger::LoggerSupport
|
21
|
-
using OSDockerDetection
|
22
|
-
|
23
|
-
def self.color_enabled=(val)
|
24
|
-
Rainbow.enabled = val
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.color_enabled
|
28
|
-
Rainbow.enabled
|
29
|
-
end
|
30
|
-
|
31
|
-
class Markup
|
32
|
-
|
33
|
-
def initialize(color = nil)
|
34
|
-
@color = color
|
35
|
-
@atmos_ui = HighLine.new
|
36
|
-
end
|
37
|
-
|
38
|
-
def say(statement)
|
39
|
-
statement = @color ? Rainbow(statement).send(@color) : statement
|
40
|
-
@atmos_ui.say(statement)
|
41
|
-
end
|
42
|
-
|
43
|
-
def ask(question, answer_type=nil, &details)
|
44
|
-
s = @color ? Rainbow(question).send(@color) : question
|
45
|
-
@atmos_ui.ask(question, answer_type, &details)
|
46
|
-
end
|
47
|
-
|
48
|
-
def agree(question, character=nil, &details)
|
49
|
-
s = @color ? Rainbow(question).send(@color) : question
|
50
|
-
@atmos_ui.agree(question, character, &details)
|
51
|
-
end
|
52
|
-
|
53
|
-
end
|
54
|
-
|
55
|
-
def warn
|
56
|
-
return Markup.new(:yellow)
|
57
|
-
end
|
58
|
-
|
59
|
-
def error
|
60
|
-
return Markup.new(:red)
|
61
|
-
end
|
62
|
-
|
63
|
-
def say(statement)
|
64
|
-
return Markup.new().say(statement)
|
65
|
-
end
|
66
|
-
|
67
|
-
def ask(question, answer_type=nil, &details)
|
68
|
-
return Markup.new().ask(question, answer_type, &details)
|
69
|
-
end
|
70
|
-
|
71
|
-
def agree(question, character=nil, &details)
|
72
|
-
return Markup.new().agree(question, character, &details)
|
73
|
-
end
|
74
|
-
|
75
|
-
# Pretty display of hashes
|
76
|
-
def display(data)
|
77
|
-
data = Hashie.stringify_keys(data)
|
78
|
-
display = YAML.dump(data).sub(/\A---\n/, "").gsub(/^/, " ")
|
79
|
-
end
|
80
|
-
|
81
|
-
def notify(message:nil, title: nil, modal: false, **opts)
|
82
|
-
|
83
|
-
result = {
|
84
|
-
'stdout' => '',
|
85
|
-
'success' => ''
|
86
|
-
}
|
87
|
-
|
88
|
-
message = message.to_s
|
89
|
-
title = title.present? ? title.to_s : "Atmos Notification"
|
90
|
-
modal = ["true", "1"].include?(modal.to_s)
|
91
|
-
modal = false if Atmos.config["ui.notify.disable_modal"]
|
92
|
-
|
93
|
-
return result if Atmos.config["ui.notify.disable"].to_s == "true"
|
94
|
-
|
95
|
-
force_inline = Atmos.config["ui.notify.force_inline"].to_s == "true"
|
96
|
-
command = Atmos.config["ui.notify.command"]
|
97
|
-
|
98
|
-
if command.present? && ! force_inline
|
99
|
-
|
100
|
-
raise ArgumentError.new("notify command must be a list") if ! command.is_a?(Array)
|
101
|
-
|
102
|
-
command = command.collect do |c|
|
103
|
-
c = c.gsub("{{title}}", title)
|
104
|
-
c = c.gsub("{{message}}", message)
|
105
|
-
c = c.gsub("{{modal}}", modal.to_s)
|
106
|
-
end
|
107
|
-
result.merge! run_ui_process(*command)
|
108
|
-
|
109
|
-
elsif OS.mac? && ! force_inline
|
110
|
-
display_method = modal ? "displayDialog" : "displayNotification"
|
111
|
-
|
112
|
-
dialogScript = <<~EOF
|
113
|
-
var app = Application.currentApplication();
|
114
|
-
app.includeStandardAdditions = true;
|
115
|
-
app.#{display_method}(
|
116
|
-
#{JSON.generate(message)}, {
|
117
|
-
withTitle: #{JSON.generate(title)},
|
118
|
-
buttons: ['OK'],
|
119
|
-
defaultButton: 1
|
120
|
-
})
|
121
|
-
EOF
|
122
|
-
|
123
|
-
result.merge! run_ui_process("osascript", "-l", "JavaScript", "-e", dialogScript)
|
124
|
-
|
125
|
-
elsif OS.linux? && ! OS.docker? && ! force_inline
|
126
|
-
# TODO: add a modal option
|
127
|
-
result.merge! run_ui_process("notify-send", title, message)
|
128
|
-
|
129
|
-
# TODO windows notifications?
|
130
|
-
# elseif OS.windows? && ! force_inline
|
131
|
-
|
132
|
-
else
|
133
|
-
|
134
|
-
logger.debug("Notifications are unsupported on this OS")
|
135
|
-
logger.info(Rainbow("\n***** #{title} *****\n#{message}\n").orange)
|
136
|
-
if modal
|
137
|
-
logger.info(Rainbow("Hit enter to continue\n").orange)
|
138
|
-
$stdin.gets
|
139
|
-
end
|
140
|
-
|
141
|
-
end
|
142
|
-
|
143
|
-
return result
|
144
|
-
end
|
145
|
-
|
146
|
-
private
|
147
|
-
|
148
|
-
def run_ui_process(*args)
|
149
|
-
stdout, status = Open3.capture2e(*args)
|
150
|
-
result = {'stdout' => stdout, 'success' => status.success?.to_s}
|
151
|
-
if ! status.success?
|
152
|
-
result['error'] = "Notification process failed"
|
153
|
-
logger.debug("Failed to run notification utility: #{stdout}")
|
154
|
-
end
|
155
|
-
return result
|
156
|
-
end
|
157
|
-
|
158
|
-
end
|
159
|
-
end
|
data/lib/atmos/utils.rb
DELETED
@@ -1,50 +0,0 @@
|
|
1
|
-
require_relative '../atmos'
|
2
|
-
|
3
|
-
module Atmos
|
4
|
-
module Utils
|
5
|
-
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
include GemLogger::LoggerSupport
|
8
|
-
|
9
|
-
class SymbolizedMash < ::Hashie::Mash
|
10
|
-
include Hashie::Extensions::Mash::SymbolizeKeys
|
11
|
-
end
|
12
|
-
|
13
|
-
# remove leading whitespace using first non-empty line to determine how
|
14
|
-
# much space to remove from the rest. Skips empty lines
|
15
|
-
def clean_indent(str)
|
16
|
-
first = true
|
17
|
-
first_size = 0
|
18
|
-
str.lines.collect do |line|
|
19
|
-
if line =~ /^(\s*)\S/ # line has at least one non-whitespace character
|
20
|
-
if first
|
21
|
-
first_size = Regexp.last_match(0).size
|
22
|
-
first = false
|
23
|
-
end
|
24
|
-
line[(first_size - 1)..-1]
|
25
|
-
else
|
26
|
-
line
|
27
|
-
end
|
28
|
-
end.join()
|
29
|
-
end
|
30
|
-
|
31
|
-
# wraps to an 80 character limit by adding newlines
|
32
|
-
def wrap(str)
|
33
|
-
result = ""
|
34
|
-
count = 0
|
35
|
-
str.each do |c|
|
36
|
-
result << c
|
37
|
-
if count >= 78
|
38
|
-
result << "\n"
|
39
|
-
count = 0
|
40
|
-
else
|
41
|
-
count += 1
|
42
|
-
end
|
43
|
-
end
|
44
|
-
return result
|
45
|
-
end
|
46
|
-
|
47
|
-
extend self
|
48
|
-
|
49
|
-
end
|
50
|
-
end
|