simplygenius-atmos 0.9.2 → 0.9.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e52d0f9fe95219722359232e6a8895b0cdbf23f99fbeda7ad8a48fdfe8a21397
4
- data.tar.gz: bb3c2e1d01fd2071ecc41e10b7622cb320e10dcd65ee90d254cc68465ee923db
3
+ metadata.gz: 02b47aaaf544e268b0d3a9a9d6a69d8165f165ef9e9e500753ec8c87787228b4
4
+ data.tar.gz: 673992076c584283ee340d683a5a0c5aa8d9c9b0c4203cac7c96250480a012a1
5
5
  SHA512:
6
- metadata.gz: 0da4f8dc5d90d23b6f5f7bbc348c4b5c1a431924e7763d369a5bbfd3528bae260a7e627294ad9aebc2e67e88cc3f7a5843a5b269b3c90fba88d7af37cf981bf5
7
- data.tar.gz: c8e92569daec346d3c9e2a963374fcefd9e04c23a3a6d298fc9b3474871e8edc2f899c0903a5bc19a032993ec53588d4683e2c08ad3c8471d1f8b45a64eed1fc
6
+ metadata.gz: a4a7fc7d2c74988b22482c4252023fb4ecd1f0216bb8f28b0e802b5ee7a4532a4fa6f995cca60f11e7015545d20566463d577f3cb656240563436490a4c70237
7
+ data.tar.gz: 2396303b7e6ce14afc455597477be362f3ea77a3540d6187ec743efe2a2f48dcc8ab5f2fc7a2175da3ad2e5addeeb72f6b1dabaeb2ebc9d2a85262ad8a70cdd8
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ 0.9.3 (02/12/2019)
2
+ ------------------
3
+
4
+ * add the ability to use a prefix for scoping secrets [470556a](https://github.com/simplygenius/atmos/commit/470556a)
5
+ * add comment [b0592d5](https://github.com/simplygenius/atmos/commit/b0592d5)
6
+ * fix pro recipe source url [9ddb8a8](https://github.com/simplygenius/atmos/commit/9ddb8a8)
7
+ * handle flushing of data in plugin output handlers when streaming completes [e1e4707](https://github.com/simplygenius/atmos/commit/e1e4707)
8
+ * refactor secrets config into a more general user config file in users home directory [06875b7](https://github.com/simplygenius/atmos/commit/06875b7)
9
+ * expand warnings for missing aws auth [3ad6ec0](https://github.com/simplygenius/atmos/commit/3ad6ec0)
10
+
1
11
  0.9.2 (12/01/2018)
2
12
  ------------------
3
13
 
@@ -16,6 +16,7 @@ module SimplyGenius
16
16
  attr_accessor :atmos_env, :working_group,
17
17
  :root_dir,
18
18
  :config_file,
19
+ :user_config_file,
19
20
  :tmp_root
20
21
 
21
22
  def initialize(atmos_env, working_group = 'default')
@@ -23,6 +24,7 @@ module SimplyGenius
23
24
  @working_group = working_group
24
25
  @root_dir = File.expand_path(Dir.pwd)
25
26
  @config_file = File.join(root_dir, "config", "atmos.yml")
27
+ @user_config_file = "~/.atmos.yml"
26
28
  @tmp_root = File.join(root_dir, "tmp")
27
29
  @included_configs = []
28
30
  end
@@ -37,6 +39,12 @@ module SimplyGenius
37
39
  return result
38
40
  end
39
41
 
42
+ def []=(key, value)
43
+ load
44
+ result = @config.notation_put(key, value)
45
+ return result
46
+ end
47
+
40
48
  def to_h
41
49
  load
42
50
  @config.to_hash
@@ -100,6 +108,17 @@ module SimplyGenius
100
108
  end
101
109
  end
102
110
 
111
+ def save_user_config_file(data, merge_to_existing: true)
112
+ logger.debug("Saving to user config file (merging=#{merge_to_existing}): #{user_config_file}")
113
+
114
+ if merge_to_existing
115
+ existing = load_file(user_config_file, SettingsHash.new)
116
+ data = config_merge(existing, data, ["saving #{user_config_file}"])
117
+ end
118
+ File.write(user_config_file, YAML.dump(data.to_hash))
119
+ File.chmod(0600, user_config_file)
120
+ end
121
+
103
122
  private
104
123
 
105
124
  INTERP_PATTERN = /(\#\{([^\}]+)\})/
@@ -164,15 +183,7 @@ module SimplyGenius
164
183
  logger.debug("Expanded pattern: #{pattern}")
165
184
 
166
185
  Dir[pattern].each do |f|
167
- logger.debug("Loading atmos config file: #{f}")
168
- data = YAML.load_file(f)
169
- if ! data.is_a?(Hash)
170
- logger.debug("Skipping non-hash config file: #{f}")
171
- else
172
- h = SettingsHash.new(data)
173
- config = config_merge(config, h, [f])
174
- @included_configs << f
175
- end
186
+ config = load_file(f, config)
176
187
  end
177
188
  end
178
189
 
@@ -182,16 +193,8 @@ module SimplyGenius
182
193
  def load_submap(relative_root, group, name, config)
183
194
  submap_dir = File.join(relative_root, 'atmos', group)
184
195
  submap_file = File.join(submap_dir, "#{name}.yml")
185
- if File.exist?(submap_file)
186
- logger.debug("Loading atmos #{group} config file: #{submap_file}")
187
- data = YAML.load_file(submap_file)
188
- if ! data.is_a?(Hash)
189
- logger.debug("Skipping non-hash config file: #{submap_file}")
190
- else
191
- h = SettingsHash.new({group => {name => data}})
192
- config = config_merge(config, h, [submap_file])
193
- @included_configs << submap_file
194
- end
196
+ config = load_file(submap_file, config) do |d|
197
+ SettingsHash.new({group => {name => d}})
195
198
  end
196
199
 
197
200
  begin
@@ -209,15 +212,12 @@ module SimplyGenius
209
212
 
210
213
  logger.debug("Atmos env: #{atmos_env}")
211
214
 
215
+
212
216
  if ! File.exist?(config_file)
213
217
  logger.warn "Could not find an atmos config file at: #{config_file}"
214
218
  @full_config = SettingsHash.new
215
219
  else
216
- logger.debug("Loading atmos config file #{config_file}")
217
- data = YAML.load_file(config_file)
218
- raise ArgumentError.new("Invalid main config file (not hash-like): #{config_file}") if ! data.is_a?(Hash)
219
- @full_config = SettingsHash.new(data)
220
- @included_configs << config_file
220
+ @full_config = load_file(config_file, SettingsHash.new)
221
221
  end
222
222
 
223
223
  @full_config = load_config_sources(File.dirname(config_file), @full_config, *Array(@full_config.notation_get("atmos.config_sources")))
@@ -227,6 +227,10 @@ module SimplyGenius
227
227
  @full_config = load_submap(File.dirname(config_file), 'providers', provider_name, @full_config)
228
228
  @full_config = load_submap(File.dirname(config_file), 'environments', atmos_env, @full_config)
229
229
 
230
+ @user_config_file = @full_config.notation_get("atmos.user_config") || @user_config_file
231
+ @user_config_file = File.expand_path(@user_config_file)
232
+ @full_config = load_file(user_config_file, @full_config)
233
+
230
234
  global = SettingsHash.new(@full_config.reject {|k, v| ['providers', 'environments'].include?(k) })
231
235
  conf = config_merge(global, {
232
236
  atmos_env: atmos_env,
@@ -237,6 +241,25 @@ module SimplyGenius
237
241
  end
238
242
  end
239
243
 
244
+ def load_file(file, config=SettingsHash.new, &block)
245
+ if File.exist?(file)
246
+ logger.debug("Loading atmos config file #{file}")
247
+ data = YAML.load_file(file)
248
+ if ! data.is_a?(Hash)
249
+ logger.debug("Skipping invalid atmos config file (not hash-like): #{file}")
250
+ else
251
+ data = SettingsHash.new(data)
252
+ data = block.call(data) if block
253
+ config = config_merge(config, data, [file])
254
+ @included_configs << file
255
+ end
256
+ else
257
+ logger.debug "Could not find an atmos config file at: #{file}"
258
+ end
259
+
260
+ config
261
+ end
262
+
240
263
  def expand(config, obj)
241
264
  case obj
242
265
  when Hash
@@ -51,6 +51,9 @@ module SimplyGenius
51
51
 
52
52
  end
53
53
 
54
+ # TODO: return all context so the calling template can see answers to
55
+ # template questions to use in customizing its output (e.g. service
56
+ # needs cluster name and ec2 backed state)
54
57
  return visited_templates
55
58
  end
56
59
 
@@ -10,13 +10,9 @@ module SimplyGenius
10
10
  include GemLogger::LoggerSupport
11
11
 
12
12
  def initialize
13
- @secret_file = Atmos.config["atmos.otp.secret_file"] || "~/.atmos.yml"
14
- @secret_file = File.expand_path(@secret_file)
15
- yml_hash = YAML.load_file(@secret_file) rescue Hash.new
16
- @secret_store = SettingsHash.new(yml_hash)
17
- @secret_store[Atmos.config[:org]] ||= {}
18
- @secret_store[Atmos.config[:org]][:otp] ||= {}
19
- @scoped_secret_store = @secret_store[Atmos.config[:org]][:otp]
13
+ @scoped_path = "atmos.otp.#{Atmos.config[:org]}"
14
+ Atmos.config[@scoped_path] ||= {}
15
+ @scoped_secret_store = Atmos.config[@scoped_path]
20
16
  end
21
17
 
22
18
  def add(name, secret)
@@ -32,8 +28,9 @@ module SimplyGenius
32
28
  end
33
29
 
34
30
  def save
35
- File.write(@secret_file, YAML.dump(@secret_store.to_hash))
36
- File.chmod(0600, @secret_file)
31
+ data = SettingsHash.new
32
+ data.notation_put(@scoped_path, @scoped_secret_store)
33
+ Atmos.config.save_user_config_file(data)
37
34
  end
38
35
 
39
36
  def generate(name)
@@ -91,10 +91,10 @@ module SimplyGenius
91
91
  end
92
92
 
93
93
  def filter_block
94
- return Proc.new do |data|
94
+ return Proc.new do |data, flushing: false|
95
95
  @filters.inject(data) do |memo, obj|
96
96
  begin
97
- obj.filter(memo)
97
+ obj.filter(memo, flushing: flushing)
98
98
  rescue StandardError => e
99
99
  logger.log_exception e, "Output filter failed during filter: #{obj.class}"
100
100
  memo
@@ -15,7 +15,7 @@ module SimplyGenius
15
15
  @context = context
16
16
  end
17
17
 
18
- def filter(data)
18
+ def filter(data, flushing: false)
19
19
  raise "not implemented"
20
20
  end
21
21
 
@@ -7,7 +7,7 @@ module SimplyGenius
7
7
 
8
8
  class PromptNotify < OutputFilter
9
9
 
10
- def filter(data)
10
+ def filter(data, flushing: false)
11
11
  if data =~ /^[\e\[\dm\s]*Enter a value:[\e\[\dm\s]*$/
12
12
  notify(message: "Terraform is waiting for user input")
13
13
  end
@@ -25,8 +25,20 @@ module SimplyGenius
25
25
  profile = system_env['AWS_PROFILE']
26
26
  key = system_env['AWS_ACCESS_KEY_ID']
27
27
  secret = system_env['AWS_SECRET_ACCESS_KEY']
28
- if profile.blank? && (key.blank? || secret.blank?)
29
- logger.warn("An aws profile or key/secret should be supplied via the environment")
28
+ # dont warn if default profile
29
+ no_creds = ::Aws::SharedCredentials.new.credentials.nil? rescue true
30
+
31
+ if profile.blank? && (key.blank? || secret.blank?) && no_creds
32
+ logger.warn("No AWS credentials are active in the environment nor shared credential store")
33
+ logger.warn("Run 'aws configure' to add some to the shared credential store")
34
+ end
35
+ if profile.present? && key.present?
36
+ logger.warn("Ignoring AWS_PROFILE because AWS_ACCESS_KEY_ID is set in the environment")
37
+ end
38
+
39
+ if Atmos.config["auth.bypass"]
40
+ logger.warn("Bypassing atmos aws authentication")
41
+ return block.call(Hash[system_env])
30
42
  end
31
43
 
32
44
  # Handle bootstrapping a new env account. Newly created organization
@@ -13,26 +13,31 @@ module SimplyGenius
13
13
  @provider = provider
14
14
  logger.debug("Secrets config is: #{Atmos.config[:secret]}")
15
15
  @bucket_name = Atmos.config[:secret][:bucket]
16
+ @bucket_prefix = "#{Atmos.config[:secret][:prefix]}"
16
17
  @encrypt = Atmos.config[:secret][:encrypt]
17
18
  end
18
19
 
19
20
  def set(key, value)
20
21
  opts = {}
21
22
  opts[:server_side_encryption] = "AES256" if @encrypt
22
- bucket.object(key).put(body: value, **opts)
23
+ bucket.object(@bucket_prefix + key).put(body: value, **opts)
23
24
  end
24
25
 
25
26
  def get(key)
26
- bucket.object(key).get.body.read
27
+ bucket.object(@bucket_prefix + key).get.body.read
27
28
  end
28
29
 
29
30
  def delete(key)
30
- bucket.object(key).delete
31
+ bucket.object(@bucket_prefix + key).delete
31
32
  end
32
33
 
33
34
  def to_h
34
- Hash[bucket.objects.collect {|o|
35
- [o.key, o.get.body.read]
35
+ Hash[bucket.objects(prefix: @bucket_prefix).collect {|o|
36
+ key = o.key
37
+ if @bucket_prefix.present?
38
+ key = o.key.gsub(/^#{@bucket_prefix}/, '')
39
+ end
40
+ [key, o.get.body.read]
36
41
  }]
37
42
  end
38
43
 
@@ -259,18 +259,30 @@ module SimplyGenius
259
259
  end
260
260
  end
261
261
 
262
- def pipe_stream(src, dest)
262
+ def pipe_stream(src, dest, &block)
263
263
  Thread.new do
264
264
  block_size = 1024
265
265
  begin
266
266
  while data = src.readpartial(block_size)
267
- data = yield data if block_given?
267
+ data = block.call(data, flushing: false) if block
268
268
  dest.write(data)
269
269
  end
270
270
  rescue IOError, EOFError => e
271
271
  logger.log_exception(e, "Stream failure", level: :debug)
272
272
  rescue Exception => e
273
273
  logger.log_exception(e, "Stream failure")
274
+ ensure
275
+ begin
276
+ if block
277
+ data = block.call('', flushing: true)
278
+ dest.write(data)
279
+ end
280
+ dest.flush
281
+ rescue IOError, EOFError => e
282
+ logger.log_exception(e, "Stream failure while flushing", level: :debug)
283
+ rescue Exception => e
284
+ logger.log_exception(e, "Stream failure while flushing")
285
+ end
274
286
  end
275
287
  end
276
288
  end
@@ -1,5 +1,5 @@
1
1
  module SimplyGenius
2
2
  module Atmos
3
- VERSION = "0.9.2"
3
+ VERSION = "0.9.3"
4
4
  end
5
5
  end
@@ -1,6 +1,11 @@
1
1
  # Configuration for controlling the behavior of the atmos runtime
2
2
  atmos:
3
3
 
4
+ # Configure the location of a user config file. This is where secrets are
5
+ # stored, e.g. OTP secrets and atmos pro auth token
6
+ #
7
+ user_config_file: ~/.atmos.yml
8
+
4
9
  # Sources for atmos templates
5
10
  # To circumvent the version lock and get the latest git master recipes, use the git
6
11
  # location, e.g.:
@@ -9,11 +14,13 @@ atmos:
9
14
  template_sources:
10
15
  - name: atmos-recipes
11
16
  location: https://github.com/simplygenius/atmos-recipes/archive/v#{atmos_version}.zip#atmos-recipes-#{atmos_version}
17
+ # To access the Atmos Pro recipes, add your atmos pro auth token to
18
+ # ~/.atmos.yml and uncomment below
12
19
  #- name: atmos-pro-recipes
13
- # location: https://YOUR_API_KEY@releases.simplygenius.com/recipes/v#{atmos_version}#atmos-pro-recipes-#{atmos_version}
20
+ # location: https://#{atmos.pro_auth_token}@releases.simplygenius.com/recipes/v#{atmos_version}.zip#atmos-pro-recipes-#{atmos_version}
14
21
 
15
22
  # To get the atmos-pro gem, add the gem source like:
16
- # gem sources -a https://YOUR_API_KEY@releases.simplygenius.com/gems/
23
+ # gem sources -a https://ATMOS_PRO_AUTH_TOKEN@releases.simplygenius.com/gems/
17
24
  # then install the gem:
18
25
  # gem install simplygenius-atmos-pro
19
26
  # then add simplygenius-atmos-pro to the plugins key below
@@ -36,11 +43,6 @@ atmos:
36
43
  # Disable notify callbacks
37
44
  disable: false
38
45
 
39
- # Configure the integrated otp mechanism
40
- otp:
41
- # The file where otp secrets are stored
42
- secret_file: ~/.atmos.yml
43
-
44
46
  # Configure the template generator
45
47
  generate:
46
48
  # The file storing the record of each generated template
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.9.2
4
+ version: 0.9.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Conway
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-12-01 00:00:00.000000000 Z
11
+ date: 2019-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -526,8 +526,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
526
526
  - !ruby/object:Gem::Version
527
527
  version: '0'
528
528
  requirements: []
529
- rubyforge_project:
530
- rubygems_version: 2.7.6
529
+ rubygems_version: 3.0.1
531
530
  signing_key:
532
531
  specification_version: 4
533
532
  summary: Atmos provides a terraform scaffold for creating cloud system architectures