simplygenius-atmos 0.7.1 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (87) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -4
  3. data/exe/atmos +2 -2
  4. data/lib/{atmos.rb → simplygenius/atmos.rb} +9 -7
  5. data/lib/simplygenius/atmos/cli.rb +116 -0
  6. data/lib/simplygenius/atmos/commands/account.rb +69 -0
  7. data/lib/simplygenius/atmos/commands/apply.rb +24 -0
  8. data/lib/simplygenius/atmos/commands/auth_exec.rb +34 -0
  9. data/lib/simplygenius/atmos/commands/base_command.rb +16 -0
  10. data/lib/simplygenius/atmos/commands/bootstrap.rb +76 -0
  11. data/lib/simplygenius/atmos/commands/container.rb +62 -0
  12. data/lib/simplygenius/atmos/commands/destroy.rb +22 -0
  13. data/lib/simplygenius/atmos/commands/generate.rb +187 -0
  14. data/lib/simplygenius/atmos/commands/init.rb +22 -0
  15. data/lib/simplygenius/atmos/commands/new.rb +22 -0
  16. data/lib/simplygenius/atmos/commands/otp.rb +58 -0
  17. data/lib/simplygenius/atmos/commands/plan.rb +24 -0
  18. data/lib/simplygenius/atmos/commands/secret.rb +91 -0
  19. data/lib/simplygenius/atmos/commands/terraform.rb +56 -0
  20. data/lib/simplygenius/atmos/commands/user.rb +78 -0
  21. data/lib/simplygenius/atmos/config.rb +279 -0
  22. data/lib/simplygenius/atmos/exceptions.rb +13 -0
  23. data/lib/simplygenius/atmos/generator.rb +232 -0
  24. data/lib/simplygenius/atmos/ipc.rb +136 -0
  25. data/lib/simplygenius/atmos/ipc_actions/notify.rb +31 -0
  26. data/lib/simplygenius/atmos/ipc_actions/ping.rb +23 -0
  27. data/lib/simplygenius/atmos/logging.rb +164 -0
  28. data/lib/simplygenius/atmos/otp.rb +62 -0
  29. data/lib/simplygenius/atmos/plugin.rb +27 -0
  30. data/lib/simplygenius/atmos/plugin_manager.rb +120 -0
  31. data/lib/simplygenius/atmos/plugins/output_filter.rb +29 -0
  32. data/lib/simplygenius/atmos/plugins/prompt_notify.rb +21 -0
  33. data/lib/simplygenius/atmos/provider_factory.rb +23 -0
  34. data/lib/simplygenius/atmos/providers/aws/account_manager.rb +83 -0
  35. data/lib/simplygenius/atmos/providers/aws/auth_manager.rb +220 -0
  36. data/lib/simplygenius/atmos/providers/aws/container_manager.rb +118 -0
  37. data/lib/simplygenius/atmos/providers/aws/provider.rb +53 -0
  38. data/lib/simplygenius/atmos/providers/aws/s3_secret_manager.rb +51 -0
  39. data/lib/simplygenius/atmos/providers/aws/user_manager.rb +213 -0
  40. data/lib/simplygenius/atmos/settings_hash.rb +93 -0
  41. data/lib/simplygenius/atmos/source_path.rb +186 -0
  42. data/lib/simplygenius/atmos/template.rb +117 -0
  43. data/lib/simplygenius/atmos/terraform_executor.rb +297 -0
  44. data/lib/simplygenius/atmos/ui.rb +173 -0
  45. data/lib/simplygenius/atmos/utils.rb +54 -0
  46. data/lib/simplygenius/atmos/version.rb +5 -0
  47. data/templates/new/config/atmos.yml +21 -13
  48. data/templates/new/config/atmos/recipes.yml +16 -0
  49. data/templates/new/config/atmos/runtime.yml +9 -0
  50. metadata +46 -40
  51. data/lib/atmos/cli.rb +0 -105
  52. data/lib/atmos/commands/account.rb +0 -65
  53. data/lib/atmos/commands/apply.rb +0 -20
  54. data/lib/atmos/commands/auth_exec.rb +0 -29
  55. data/lib/atmos/commands/base_command.rb +0 -12
  56. data/lib/atmos/commands/bootstrap.rb +0 -72
  57. data/lib/atmos/commands/container.rb +0 -58
  58. data/lib/atmos/commands/destroy.rb +0 -18
  59. data/lib/atmos/commands/generate.rb +0 -90
  60. data/lib/atmos/commands/init.rb +0 -18
  61. data/lib/atmos/commands/new.rb +0 -18
  62. data/lib/atmos/commands/otp.rb +0 -54
  63. data/lib/atmos/commands/plan.rb +0 -20
  64. data/lib/atmos/commands/secret.rb +0 -87
  65. data/lib/atmos/commands/terraform.rb +0 -52
  66. data/lib/atmos/commands/user.rb +0 -74
  67. data/lib/atmos/config.rb +0 -208
  68. data/lib/atmos/exceptions.rb +0 -9
  69. data/lib/atmos/generator.rb +0 -199
  70. data/lib/atmos/generator_factory.rb +0 -93
  71. data/lib/atmos/ipc.rb +0 -132
  72. data/lib/atmos/ipc_actions/notify.rb +0 -27
  73. data/lib/atmos/ipc_actions/ping.rb +0 -19
  74. data/lib/atmos/logging.rb +0 -160
  75. data/lib/atmos/otp.rb +0 -61
  76. data/lib/atmos/provider_factory.rb +0 -19
  77. data/lib/atmos/providers/aws/account_manager.rb +0 -82
  78. data/lib/atmos/providers/aws/auth_manager.rb +0 -208
  79. data/lib/atmos/providers/aws/container_manager.rb +0 -116
  80. data/lib/atmos/providers/aws/provider.rb +0 -51
  81. data/lib/atmos/providers/aws/s3_secret_manager.rb +0 -49
  82. data/lib/atmos/providers/aws/user_manager.rb +0 -211
  83. data/lib/atmos/settings_hash.rb +0 -90
  84. data/lib/atmos/terraform_executor.rb +0 -267
  85. data/lib/atmos/ui.rb +0 -159
  86. data/lib/atmos/utils.rb +0 -50
  87. data/lib/atmos/version.rb +0 -3
@@ -0,0 +1,22 @@
1
+ require_relative 'terraform'
2
+
3
+ module SimplyGenius
4
+ module Atmos
5
+ module Commands
6
+
7
+ class Destroy < Terraform
8
+
9
+ def self.description
10
+ "Runs terraform destroy"
11
+ end
12
+
13
+ def execute
14
+ @terraform_arguments.insert(0, "destroy")
15
+ super
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,187 @@
1
+ require_relative 'base_command'
2
+ require_relative '../../atmos/source_path'
3
+ require_relative '../../atmos/generator'
4
+ require_relative '../../atmos/utils'
5
+
6
+ module SimplyGenius
7
+ module Atmos
8
+ module Commands
9
+
10
+ # From https://github.com/rubber/rubber/blob/master/lib/rubber/commands/vulcanize.rb
11
+ class Generate < BaseCommand
12
+
13
+ def self.description
14
+ <<~EOF
15
+ Installs configuration templates used by atmos to create infrastructure
16
+ resources e.g.
17
+
18
+ atmos generate aws/vpc
19
+
20
+ use --list to get a list of the template names for a given sourceroot
21
+ EOF
22
+ end
23
+
24
+ option ["-f", "--force"],
25
+ :flag, "Overwrite files that already exist"
26
+ option ["-n", "--dryrun"],
27
+ :flag, "Run but do not make any changes"
28
+ option ["-q", "--quiet"],
29
+ :flag, "Supress status output"
30
+ option ["-s", "--skip"],
31
+ :flag, "Skip files that already exist"
32
+ option ["-d", "--[no-]dependencies"],
33
+ :flag, "Walk dependencies, or not", default: true
34
+ option ["-l", "--list"],
35
+ :flag, "list available templates"
36
+ option ["-u", "--update"],
37
+ :flag, "update all installed templates\n"
38
+ option ["-p", "--sourcepath"],
39
+ "PATH", "search for templates using given sourcepath",
40
+ multivalued: true
41
+ option ["-r", "--[no-]sourcepaths"],
42
+ :flag, "clear sourcepaths from template search\n", default: true
43
+ option ["-c", "--context"],
44
+ "CONTEXT", "provide context variables (dot notation)",
45
+ multivalued: true
46
+
47
+ parameter "TEMPLATE ...", "atmos template(s)", required: false
48
+
49
+ def execute
50
+ signal_usage_error "template name is required" if template_list.blank? && ! list? && !update?
51
+
52
+ sourcepath_list.each do |sp|
53
+ SourcePath.register(File.basename(sp), sp)
54
+ end
55
+
56
+ if sourcepaths?
57
+
58
+ # don't want to fail for new repo
59
+ if Atmos.config && Atmos.config.is_atmos_repo?
60
+ Atmos.config['template_sources'].try(:each) do |item|
61
+ SourcePath.register(item.name, item.location)
62
+ end
63
+ end
64
+
65
+ # Always search for templates against the bundled templates directory
66
+ SourcePath.register('bundled', File.expand_path('../../../../../templates', __FILE__))
67
+
68
+ end
69
+
70
+ if list?
71
+ logger.info "Valid templates are:"
72
+ SourcePath.registry.each do |spname, sp|
73
+ logger.info("\tSourcepath #{sp}")
74
+ filtered_names = sp.template_names.select do |name|
75
+ template_list.blank? || template_list.any? {|f| name =~ /#{f}/ }
76
+ end
77
+ filtered_names.each {|n| logger.info ("\t\t#{n}")}
78
+ end
79
+ else
80
+ g = Generator.new(force: force?,
81
+ pretend: dryrun?,
82
+ quiet: quiet?,
83
+ skip: skip?,
84
+ dependencies: dependencies?)
85
+
86
+ begin
87
+
88
+ context = SettingsHash.new
89
+ context_list.each do |c|
90
+ key, value = c.split('=', 2)
91
+ context.notation_put(key, value)
92
+ end
93
+
94
+ if update?
95
+ # this isn't 100% foolproof, but is a convenience that should help for most cases
96
+
97
+ filtered_templates = state[:visited_templates].select do |vt|
98
+ template_list.blank? || template_list.any? {|n| vt[:name] =~ /#{n}/ }
99
+ end
100
+
101
+ sps = filtered_templates.collect(&:source).uniq
102
+ sps.each do |src|
103
+ spname = src[:name]
104
+ sploc = src[:location]
105
+
106
+ existing_sp = SourcePath.registry[spname]
107
+ if existing_sp
108
+ if existing_sp.location != sploc
109
+ logger.warn("Saved sourcepath location differs from that in configuration")
110
+ logger.warn(" #{spname} -> saved=#{sploc} configured=#{existing_sp.location}")
111
+ logger.warn(" consider running with --no-sourcepaths")
112
+ end
113
+ else
114
+ sp = SourcePath.register(spname, sploc)
115
+ logger.warn("Saved state contains a source path missing from configuration: #{sp}")
116
+ end
117
+ end
118
+
119
+ filtered_templates.each do |vt|
120
+ name = vt[:name]
121
+ ctx = vt[:context]
122
+ spname = vt[:source][:name]
123
+ sp = SourcePath.registry[spname]
124
+ tmpl = sp.template(name)
125
+ tmpl.scoped_context.merge!(ctx) if ctx
126
+ tmpl.context.merge!(context)
127
+ g.apply_template(tmpl)
128
+ end
129
+ else
130
+ g.generate(*template_list, context: context)
131
+ end
132
+
133
+ save_state(g.visited_templates, template_list)
134
+
135
+ rescue ArgumentError => e
136
+ logger.error(e.message)
137
+ exit 1
138
+ end
139
+ end
140
+
141
+ end
142
+
143
+ def state_file
144
+ @state_file ||= Atmos.config["generate.state_file"]
145
+ end
146
+
147
+ def state
148
+ @state ||= begin
149
+ if state_file.present?
150
+ path = File.expand_path(state_file)
151
+ yml_hash = {}
152
+ if File.exist?(path)
153
+ yml_hash = YAML.load_file(path)
154
+ end
155
+ SettingsHash.new(yml_hash)
156
+ else
157
+ SettingsHash.new
158
+ end
159
+ end
160
+ end
161
+
162
+ def save_state(visited_templates, entrypoint_template_names)
163
+ if state_file.present?
164
+ visited_state = []
165
+ visited_templates.each do |tmpl|
166
+ visited_tmpl = tmpl.to_h
167
+ visited_tmpl[:context] = tmpl.scoped_context.to_h
168
+ visited_state << visited_tmpl
169
+ end
170
+
171
+ state[:visited_templates] ||= []
172
+ state[:visited_templates].concat(visited_state)
173
+ state[:visited_templates].sort! {|h1, h2| h1[:name] <=> h2[:name] }.uniq!
174
+
175
+ state[:entrypoint_templates] ||= []
176
+ state[:entrypoint_templates].concat(entrypoint_template_names)
177
+ state[:entrypoint_templates].sort!.uniq!
178
+
179
+ File.write(state_file, YAML.dump(state.to_hash))
180
+ end
181
+ end
182
+
183
+ end
184
+
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,22 @@
1
+ require_relative 'terraform'
2
+
3
+ module SimplyGenius
4
+ module Atmos
5
+ module Commands
6
+
7
+ class Init < Terraform
8
+
9
+ def self.description
10
+ "Runs terraform init"
11
+ end
12
+
13
+ def execute
14
+ @terraform_arguments.insert(0, "init")
15
+ super
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ require_relative 'generate'
2
+
3
+ module SimplyGenius
4
+ module Atmos
5
+ module Commands
6
+
7
+ class New < Generate
8
+
9
+ def self.description
10
+ "Sets up a new atmos project in the current directory"
11
+ end
12
+
13
+ def execute
14
+ template_list << "new"
15
+ super
16
+ end
17
+
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,58 @@
1
+ require_relative 'base_command'
2
+ require_relative '../../atmos/otp'
3
+ require 'clipboard'
4
+
5
+ module SimplyGenius
6
+ module Atmos
7
+ module Commands
8
+
9
+ class Otp < BaseCommand
10
+
11
+ def self.description
12
+ "Generates an otp token for the given user"
13
+ end
14
+
15
+ option ["-s", "--secret"],
16
+ 'SECRET', "The otp secret\nWill save for future use"
17
+
18
+ option ["-c", "--clipboard"],
19
+ :flag,
20
+ <<~EOF
21
+ Automatically copy the token to the system
22
+ clipboard. For dependencies see:
23
+ https://github.com/janlelis/clipboard
24
+ EOF
25
+
26
+ parameter "NAME",
27
+ "The otp name (IAM username)"
28
+
29
+ def execute
30
+ code = nil
31
+ if secret
32
+ Atmos::Otp.instance.add(name, secret)
33
+ code = Atmos::Otp.instance.generate(name)
34
+ Atmos::Otp.instance.save
35
+ else
36
+ code = Atmos::Otp.instance.generate(name)
37
+ end
38
+
39
+ if code.nil?
40
+ signal_usage_error <<~EOF
41
+ No otp secret has been setup for #{name}
42
+ Use the -m flag to 'atmos user create' to create/activate one
43
+ or associate an existing secret with 'atmos otp -s <secret> <name>'
44
+ EOF
45
+ else
46
+ puts code
47
+ end
48
+
49
+ if clipboard?
50
+ Clipboard.copy(code)
51
+ end
52
+ end
53
+
54
+ end
55
+
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,24 @@
1
+ require_relative 'terraform'
2
+
3
+ module SimplyGenius
4
+ module Atmos
5
+ module Commands
6
+
7
+ class Plan < Terraform
8
+
9
+ def self.description
10
+ "Runs terraform plan"
11
+ end
12
+
13
+ def execute
14
+ args = ["plan"]
15
+ args << "--get-modules" unless Atmos.config["disable_auto_modules"].to_s == "true"
16
+ @terraform_arguments.insert(0, *args)
17
+ super
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,91 @@
1
+ require_relative 'base_command'
2
+ require 'climate_control'
3
+
4
+ module SimplyGenius
5
+ module Atmos
6
+ module Commands
7
+
8
+ class Secret < BaseCommand
9
+
10
+ def self.description
11
+ "Manages application secrets"
12
+ end
13
+
14
+ subcommand "get", "Gets the secret value" do
15
+
16
+ parameter "KEY",
17
+ "The secret key"
18
+
19
+ def execute
20
+
21
+ Atmos.config.provider.auth_manager.authenticate(ENV) do |auth_env|
22
+ ClimateControl.modify(auth_env) do
23
+ value = Atmos.config.provider.secret_manager.get(key)
24
+ logger.info "Secret value for #{key}: #{value}"
25
+ end
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+
32
+ subcommand "set", "Sets the secret value" do
33
+
34
+ parameter "KEY",
35
+ "The secret key"
36
+
37
+ parameter "VALUE",
38
+ "The secret value"
39
+
40
+ def execute
41
+
42
+ Atmos.config.provider.auth_manager.authenticate(ENV) do |auth_env|
43
+ ClimateControl.modify(auth_env) do
44
+ Atmos.config.provider.secret_manager.set(key, value)
45
+ logger.info "Secret set for #{key}"
46
+ end
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+
53
+ subcommand "list", "Lists all secret keys" do
54
+
55
+ def execute
56
+
57
+ Atmos.config.provider.auth_manager.authenticate(ENV) do |auth_env|
58
+ ClimateControl.modify(auth_env) do
59
+ logger.info "Secret keys are:"
60
+ Atmos.config.provider.secret_manager.to_h.keys.each {|k| logger.info k}
61
+ end
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+
68
+ subcommand "delete", "Deletes the secret key/value" do
69
+
70
+ parameter "KEY",
71
+ "The secret key"
72
+
73
+ def execute
74
+
75
+ Atmos.config.provider.auth_manager.authenticate(ENV) do |auth_env|
76
+ ClimateControl.modify(auth_env) do
77
+ value = Atmos.config.provider.secret_manager.get(key)
78
+ Atmos.config.provider.secret_manager.delete(key)
79
+ logger.info "Deleted secret: #{key}=#{value}"
80
+ end
81
+ end
82
+
83
+ end
84
+
85
+ end
86
+
87
+ end
88
+
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,56 @@
1
+ require_relative 'base_command'
2
+ require_relative '../../atmos/terraform_executor'
3
+
4
+ module SimplyGenius
5
+ module Atmos
6
+ module Commands
7
+
8
+ class Terraform < BaseCommand
9
+
10
+ def self.description
11
+ "Runs terraform"
12
+ end
13
+
14
+ # override so we can pass all options/flags/parameters directly to
15
+ # terraform instead of having clamp parse them
16
+ def parse(arguments)
17
+ @terraform_arguments = arguments
18
+ end
19
+
20
+ def execute
21
+
22
+ unless Atmos.config.is_atmos_repo?
23
+ signal_usage_error <<~EOF
24
+ Atmos can only run terraform from a location configured for atmos.
25
+ Have you run atmos init?"
26
+ EOF
27
+ end
28
+
29
+ Atmos.config.provider.auth_manager.authenticate(ENV) do |auth_env|
30
+ begin
31
+
32
+ # TODO: hack to allow apply/etc for bootstrap group
33
+ # Fix this once we allow more extensive recipe grouping
34
+ working_group = 'default'
35
+ @terraform_arguments.each_with_index do |a, i|
36
+ if a == "--group"
37
+ @terraform_arguments.delete_at(i)
38
+ working_group = @terraform_arguments.delete_at(i)
39
+ break
40
+ end
41
+ end
42
+
43
+ exe = TerraformExecutor.new(process_env: auth_env, working_group: working_group)
44
+ get_modules = @terraform_arguments.delete("--get-modules")
45
+ exe.run(*@terraform_arguments, get_modules: get_modules.present?)
46
+ rescue TerraformExecutor::ProcessFailed => e
47
+ logger.error(e.message)
48
+ end
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+ end
56
+ end