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
data/lib/atmos/commands/plan.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
require_relative 'terraform'
|
2
|
-
|
3
|
-
module Atmos::Commands
|
4
|
-
|
5
|
-
class Plan < Atmos::Commands::Terraform
|
6
|
-
|
7
|
-
def self.description
|
8
|
-
"Runs terraform plan"
|
9
|
-
end
|
10
|
-
|
11
|
-
def execute
|
12
|
-
args = ["plan"]
|
13
|
-
args << "--get-modules" unless Atmos.config["disable_auto_modules"].to_s == "true"
|
14
|
-
@terraform_arguments.insert(0, *args)
|
15
|
-
super
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
@@ -1,87 +0,0 @@
|
|
1
|
-
require_relative 'base_command'
|
2
|
-
require 'climate_control'
|
3
|
-
|
4
|
-
module Atmos::Commands
|
5
|
-
|
6
|
-
class Secret < BaseCommand
|
7
|
-
|
8
|
-
def self.description
|
9
|
-
"Manages application secrets"
|
10
|
-
end
|
11
|
-
|
12
|
-
subcommand "get", "Gets the secret value" do
|
13
|
-
|
14
|
-
parameter "KEY",
|
15
|
-
"The secret key"
|
16
|
-
|
17
|
-
def execute
|
18
|
-
|
19
|
-
Atmos.config.provider.auth_manager.authenticate(ENV) do |auth_env|
|
20
|
-
ClimateControl.modify(auth_env) do
|
21
|
-
value = Atmos.config.provider.secret_manager.get(key)
|
22
|
-
logger.info "Secret value for #{key}: #{value}"
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
subcommand "set", "Sets the secret value" do
|
31
|
-
|
32
|
-
parameter "KEY",
|
33
|
-
"The secret key"
|
34
|
-
|
35
|
-
parameter "VALUE",
|
36
|
-
"The secret value"
|
37
|
-
|
38
|
-
def execute
|
39
|
-
|
40
|
-
Atmos.config.provider.auth_manager.authenticate(ENV) do |auth_env|
|
41
|
-
ClimateControl.modify(auth_env) do
|
42
|
-
Atmos.config.provider.secret_manager.set(key, value)
|
43
|
-
logger.info "Secret set for #{key}"
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
|
49
|
-
end
|
50
|
-
|
51
|
-
subcommand "list", "Lists all secret keys" do
|
52
|
-
|
53
|
-
def execute
|
54
|
-
|
55
|
-
Atmos.config.provider.auth_manager.authenticate(ENV) do |auth_env|
|
56
|
-
ClimateControl.modify(auth_env) do
|
57
|
-
logger.info "Secret keys are:"
|
58
|
-
Atmos.config.provider.secret_manager.to_h.keys.each {|k| logger.info k}
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
end
|
65
|
-
|
66
|
-
subcommand "delete", "Deletes the secret key/value" do
|
67
|
-
|
68
|
-
parameter "KEY",
|
69
|
-
"The secret key"
|
70
|
-
|
71
|
-
def execute
|
72
|
-
|
73
|
-
Atmos.config.provider.auth_manager.authenticate(ENV) do |auth_env|
|
74
|
-
ClimateControl.modify(auth_env) do
|
75
|
-
value = Atmos.config.provider.secret_manager.get(key)
|
76
|
-
Atmos.config.provider.secret_manager.delete(key)
|
77
|
-
logger.info "Deleted secret: #{key}=#{value}"
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
end
|
82
|
-
|
83
|
-
end
|
84
|
-
|
85
|
-
end
|
86
|
-
|
87
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
require_relative 'base_command'
|
2
|
-
require_relative '../../atmos/terraform_executor'
|
3
|
-
|
4
|
-
module Atmos::Commands
|
5
|
-
|
6
|
-
class Terraform < BaseCommand
|
7
|
-
|
8
|
-
def self.description
|
9
|
-
"Runs terraform"
|
10
|
-
end
|
11
|
-
|
12
|
-
# override so we can pass all options/flags/parameters directly to
|
13
|
-
# terraform instead of having clamp parse them
|
14
|
-
def parse(arguments)
|
15
|
-
@terraform_arguments = arguments
|
16
|
-
end
|
17
|
-
|
18
|
-
def execute
|
19
|
-
|
20
|
-
unless Atmos.config.is_atmos_repo?
|
21
|
-
signal_usage_error <<~EOF
|
22
|
-
Atmos can only run terraform from a location configured for atmos.
|
23
|
-
Have you run atmos init?"
|
24
|
-
EOF
|
25
|
-
end
|
26
|
-
|
27
|
-
Atmos.config.provider.auth_manager.authenticate(ENV) do |auth_env|
|
28
|
-
begin
|
29
|
-
|
30
|
-
# TODO: hack to allow apply/etc for bootstrap group
|
31
|
-
# Fix this once we allow more extensive recipe grouping
|
32
|
-
working_group = 'default'
|
33
|
-
@terraform_arguments.each_with_index do |a, i|
|
34
|
-
if a == "--group"
|
35
|
-
@terraform_arguments.delete_at(i)
|
36
|
-
working_group = @terraform_arguments.delete_at(i)
|
37
|
-
break
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
exe = Atmos::TerraformExecutor.new(process_env: auth_env, working_group: working_group)
|
42
|
-
get_modules = @terraform_arguments.delete("--get-modules")
|
43
|
-
exe.run(*@terraform_arguments, get_modules: get_modules.present?)
|
44
|
-
rescue Atmos::TerraformExecutor::ProcessFailed => e
|
45
|
-
logger.error(e.message)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
51
|
-
|
52
|
-
end
|
data/lib/atmos/commands/user.rb
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
require_relative 'base_command'
|
2
|
-
require 'climate_control'
|
3
|
-
|
4
|
-
module Atmos::Commands
|
5
|
-
|
6
|
-
class User < BaseCommand
|
7
|
-
|
8
|
-
def self.description
|
9
|
-
"Manages users in the cloud provider"
|
10
|
-
end
|
11
|
-
|
12
|
-
subcommand "create", "Create a new user" do
|
13
|
-
|
14
|
-
option ["-f", "--force"],
|
15
|
-
:flag, "forces deletion/updates for pre-existing resources\n",
|
16
|
-
default: false
|
17
|
-
|
18
|
-
option ["-l", "--login"],
|
19
|
-
:flag, "generate a login password\n",
|
20
|
-
default: false
|
21
|
-
|
22
|
-
option ["-m", "--mfa"],
|
23
|
-
:flag, "setup a mfa device\n",
|
24
|
-
default: false
|
25
|
-
|
26
|
-
option ["-k", "--key"],
|
27
|
-
:flag, "create access keys\n",
|
28
|
-
default: false
|
29
|
-
|
30
|
-
option ["-p", "--public-key"],
|
31
|
-
"PUBLIC_KEY", "add ssh public key\n"
|
32
|
-
|
33
|
-
option ["-g", "--group"],
|
34
|
-
"GROUP",
|
35
|
-
"associate the given groups to new user\n",
|
36
|
-
multivalued: true
|
37
|
-
|
38
|
-
parameter "USERNAME",
|
39
|
-
"The username of the user to add\nShould be an email address" do |u|
|
40
|
-
raise ArgumentError.new("Not an email") if u !~ URI::MailTo::EMAIL_REGEXP
|
41
|
-
u
|
42
|
-
end
|
43
|
-
|
44
|
-
def execute
|
45
|
-
|
46
|
-
Atmos.config.provider.auth_manager.authenticate(ENV) do |auth_env|
|
47
|
-
ClimateControl.modify(auth_env) do
|
48
|
-
manager = Atmos.config.provider.user_manager
|
49
|
-
user = manager.create_user(username)
|
50
|
-
user.merge!(manager.set_groups(username, group_list, force: force?)) if group_list.present?
|
51
|
-
user.merge!(manager.enable_login(username, force: force?)) if login?
|
52
|
-
user.merge!(manager.enable_mfa(username, force: force?)) if mfa?
|
53
|
-
user.merge!(manager.enable_access_keys(username, force: force?)) if key?
|
54
|
-
user.merge!(manager.set_public_key(username, public_key, force: force?)) if public_key.present?
|
55
|
-
|
56
|
-
logger.info "\nUser created:\n#{display user}\n"
|
57
|
-
|
58
|
-
if mfa? && user[:mfa_secret]
|
59
|
-
save_mfa = agree("Save the MFA secret for runtime integration with auth? ") {|q|
|
60
|
-
q.default = 'y'
|
61
|
-
}
|
62
|
-
Atmos::Otp.instance.save if save_mfa
|
63
|
-
end
|
64
|
-
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
69
|
-
|
70
|
-
end
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
|
-
end
|
data/lib/atmos/config.rb
DELETED
@@ -1,208 +0,0 @@
|
|
1
|
-
require_relative '../atmos'
|
2
|
-
require_relative '../atmos/settings_hash'
|
3
|
-
require_relative '../atmos/provider_factory'
|
4
|
-
require 'yaml'
|
5
|
-
require 'fileutils'
|
6
|
-
require 'find'
|
7
|
-
|
8
|
-
module Atmos
|
9
|
-
class Config
|
10
|
-
include GemLogger::LoggerSupport
|
11
|
-
include FileUtils
|
12
|
-
|
13
|
-
attr_accessor :atmos_env, :root_dir,
|
14
|
-
:config_file, :configs_dir,
|
15
|
-
:tmp_root
|
16
|
-
|
17
|
-
def initialize(atmos_env)
|
18
|
-
@atmos_env = atmos_env
|
19
|
-
@root_dir = File.expand_path(Dir.pwd)
|
20
|
-
@config_file = File.join(root_dir, "config", "atmos.yml")
|
21
|
-
@configs_dir = File.join(root_dir, "config", "atmos")
|
22
|
-
@tmp_root = File.join(root_dir, "tmp")
|
23
|
-
end
|
24
|
-
|
25
|
-
def is_atmos_repo?
|
26
|
-
File.exist?(config_file)
|
27
|
-
end
|
28
|
-
|
29
|
-
def [](key)
|
30
|
-
load
|
31
|
-
result = @config.notation_get(key)
|
32
|
-
return result
|
33
|
-
end
|
34
|
-
|
35
|
-
def to_h
|
36
|
-
load
|
37
|
-
@config.to_hash
|
38
|
-
end
|
39
|
-
|
40
|
-
def provider
|
41
|
-
@provider ||= Atmos::ProviderFactory.get(self[:provider])
|
42
|
-
end
|
43
|
-
|
44
|
-
def all_env_names
|
45
|
-
load
|
46
|
-
@full_config[:environments].keys
|
47
|
-
end
|
48
|
-
|
49
|
-
def account_hash
|
50
|
-
load
|
51
|
-
environments = @full_config[:environments] || {}
|
52
|
-
environments.inject(Hash.new) do |accum, entry|
|
53
|
-
accum[entry.first] = entry.last[:account_id]
|
54
|
-
accum
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
def tmp_dir
|
59
|
-
@tmp_dir ||= begin
|
60
|
-
dir = File.join(tmp_root, atmos_env)
|
61
|
-
logger.debug("Tmp dir: #{dir}")
|
62
|
-
mkdir_p(dir)
|
63
|
-
dir
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
def auth_cache_dir
|
68
|
-
@auth_cache_dir ||= begin
|
69
|
-
dir = File.join(tmp_dir, 'auth')
|
70
|
-
logger.debug("Auth cache dir: #{dir}")
|
71
|
-
mkdir_p(dir)
|
72
|
-
dir
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
def tf_working_dir(group='default')
|
77
|
-
@tf_working_dir ||= {}
|
78
|
-
@tf_working_dir[group] ||= begin
|
79
|
-
dir = File.join(tmp_dir, 'tf', group)
|
80
|
-
logger.debug("Terraform working dir: #{dir}")
|
81
|
-
mkdir_p(dir)
|
82
|
-
dir
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
private
|
87
|
-
|
88
|
-
INTERP_PATTERN = /(\#\{([^\}]+)\})/
|
89
|
-
|
90
|
-
def load
|
91
|
-
@config ||= begin
|
92
|
-
|
93
|
-
logger.debug("Atmos env: #{atmos_env}")
|
94
|
-
|
95
|
-
if ! File.exist?(config_file)
|
96
|
-
logger.warn "Could not find an atmos config file at: #{config_file}"
|
97
|
-
# raise RuntimeError.new("Could not find an atmos config file at: #{config_file}")
|
98
|
-
end
|
99
|
-
|
100
|
-
logger.debug("Loading atmos config file #{config_file}")
|
101
|
-
@full_config = SettingsHash.new((YAML.load_file(config_file) rescue Hash.new))
|
102
|
-
|
103
|
-
if Dir.exist?(configs_dir)
|
104
|
-
logger.debug("Loading atmos config files from #{configs_dir}")
|
105
|
-
Find.find(configs_dir) do |f|
|
106
|
-
if f =~ /\.ya?ml/i
|
107
|
-
logger.debug("Loading atmos config file: #{f}")
|
108
|
-
h = SettingsHash.new(YAML.load_file(f))
|
109
|
-
@full_config = @full_config.merge(h)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
else
|
113
|
-
logger.debug("Atmos config dir doesn't exist: #{configs_dir}")
|
114
|
-
end
|
115
|
-
|
116
|
-
@full_config['provider'] = provider_name = @full_config['provider'] || 'aws'
|
117
|
-
global = SettingsHash.new(@full_config.reject {|k, v| ['environments', 'providers'].include?(k) })
|
118
|
-
begin
|
119
|
-
prov = @full_config.deep_fetch(:providers, provider_name)
|
120
|
-
rescue
|
121
|
-
logger.debug("No provider config found for '#{provider_name}'")
|
122
|
-
prov = {}
|
123
|
-
end
|
124
|
-
|
125
|
-
begin
|
126
|
-
env = @full_config.deep_fetch(:environments, atmos_env)
|
127
|
-
rescue
|
128
|
-
logger.debug("No environment config found for '#{atmos_env}'")
|
129
|
-
env = {}
|
130
|
-
end
|
131
|
-
|
132
|
-
conf = global.deep_merge(prov).
|
133
|
-
deep_merge(env).
|
134
|
-
deep_merge(
|
135
|
-
atmos_env: atmos_env,
|
136
|
-
atmos_version: Atmos::VERSION
|
137
|
-
)
|
138
|
-
expand(conf, conf)
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def expand(config, obj)
|
143
|
-
case obj
|
144
|
-
when Hash
|
145
|
-
SettingsHash.new(Hash[obj.collect {|k, v| [k, expand(config, v)] }])
|
146
|
-
when Array
|
147
|
-
obj.collect {|i| expand(config, i) }
|
148
|
-
when String
|
149
|
-
result = obj
|
150
|
-
result.scan(INTERP_PATTERN).each do |substr, statement|
|
151
|
-
# TODO: check for cycles
|
152
|
-
if statement =~ /^[\w\.\[\]]$/
|
153
|
-
val = config.notation_get(statement)
|
154
|
-
else
|
155
|
-
# TODO: be consistent with dot notation between eval and
|
156
|
-
# notation_get. eval ends up calling Hashie method_missing,
|
157
|
-
# which returns nil if a key doesn't exist, causing a nil
|
158
|
-
# exception for next item in chain, while notation_get returns
|
159
|
-
# nil gracefully for the entire chain (preferred)
|
160
|
-
begin
|
161
|
-
val = eval(statement, config.instance_eval("binding"))
|
162
|
-
rescue => e
|
163
|
-
file, line = find_config_error(substr)
|
164
|
-
file_msg = file.nil? ? "" : " in #{File.basename(file)}:#{line}"
|
165
|
-
raise RuntimeError.new("Failing config statement '#{substr}'#{file_msg} => #{e.class} #{e.message}")
|
166
|
-
end
|
167
|
-
end
|
168
|
-
result = result.sub(substr, expand(config, val).to_s)
|
169
|
-
end
|
170
|
-
result = true if result == 'true'
|
171
|
-
result = false if result == 'false'
|
172
|
-
result
|
173
|
-
else
|
174
|
-
obj
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
def find_config_error(statement)
|
179
|
-
filename = nil
|
180
|
-
line = 0
|
181
|
-
|
182
|
-
configs = []
|
183
|
-
configs << config_file if File.exist?(config_file)
|
184
|
-
if Dir.exist?(configs_dir)
|
185
|
-
Find.find(configs_dir) do |f|
|
186
|
-
if f =~ /\.ya?ml/i
|
187
|
-
configs << f
|
188
|
-
end
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
configs.each do |c|
|
193
|
-
current_line = 0
|
194
|
-
File.foreach(c) do |f|
|
195
|
-
current_line += 1
|
196
|
-
if f.include?(statement)
|
197
|
-
filename = c
|
198
|
-
line = current_line
|
199
|
-
break
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
return filename, line
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
end
|