chambermaid 0.1.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 96de691a190b68ff6d24e2410f1191ac0f3ef29c534de37ae73b7e7a7f4d8530
4
- data.tar.gz: 16b2fb406a93c823bba30938594294fdcad94a1588718327c57b1d10fddf7f0a
3
+ metadata.gz: 7205cca8ffd4e9f7b2e20eb02239fd42be4f9dcdbd7c85eafb2e74c000d39be6
4
+ data.tar.gz: a1b394c7dd79578e738defb6657276aa6988185d432153f900dab3b2bfeda97d
5
5
  SHA512:
6
- metadata.gz: 4d73421e3cdac6a8e835b745df14a2fe012f4785183e4cc28c4222358553a8ac29a12f5e7cd256af7d7bf2bfcbf5bf8cf2783d089dbb09e435d07f717a359269
7
- data.tar.gz: 7d7a11dbb825742c23bd9a1d8b2ac10cabb44c92b66d6fea40ae828c01862611d97b5422efafd3f57f9c5826e39648240eb389f69d9d98acf0635118908c266a
6
+ metadata.gz: 4ef58ed041bd944a89d06a72c4b4f71dfe7695ef86aa4c2a28edf6d32d6a8b46122c1bfe7b1f6461cf9199dfbe73cfcf9fadd7ee101b54f0e86be5d36cd76c9d
7
+ data.tar.gz: 9cb1b2f1781b2903a9af7121e7720a8c2f875a28472f8d0ded8b455560262917f2fec5e0cb8584886257de8141fabc90ca7d244d86435004b9c1377a121d4ee2
data/Gemfile CHANGED
@@ -2,6 +2,3 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in chambermaid.gemspec
4
4
  gemspec
5
-
6
- gem "rake", "~> 12.0"
7
- gem "rspec", "~> 3.0"
@@ -1,14 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- chambermaid (0.1.0)
4
+ chambermaid (0.4.0)
5
5
  aws-sdk-ssm (~> 1.85)
6
6
 
7
7
  GEM
8
8
  remote: https://rubygems.org/
9
9
  specs:
10
10
  aws-eventstream (1.1.0)
11
- aws-partitions (1.348.0)
11
+ aws-partitions (1.349.0)
12
12
  aws-sdk-core (3.104.3)
13
13
  aws-eventstream (~> 1, >= 1.0.2)
14
14
  aws-partitions (~> 1, >= 1.239.0)
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Chambermaid
1
+ # Chambermaid [![Gem Version](https://badge.fury.io/rb/chambermaid.svg)](https://badge.fury.io/rb/chambermaid) [![Build Status](https://travis-ci.com/mileszim/chambermaid.svg?branch=master)](https://travis-ci.com/mileszim/chambermaid)
2
2
 
3
3
  Companion RubyGem for [chamber](https://github.com/segmentio/chamber).
4
4
 
@@ -26,6 +26,7 @@ Or install it yourself as:
26
26
 
27
27
  ```ruby
28
28
  Chambermaid.add_namespace("/my/param/namespace")
29
+ Chambermaid.add_service("my-chamber-service")
29
30
  ```
30
31
 
31
32
  **Configuration Block**
@@ -34,14 +35,50 @@ Chambermaid.add_namespace("/my/param/namespace")
34
35
  # config/initializers/chambermaid.rb
35
36
 
36
37
  Chambermaid.configure do |config|
38
+ # Load all values from SSM Namespace path
37
39
  config.add_namespace("/my/param/namespace")
38
40
 
39
- # Set `overwrite_duplicates: true` to choose these params over existing
41
+ # Load values from chamber-cli service
42
+ config.add_service("my-chamber-service")
43
+
44
+ # Set `overload: true` to choose these params over existing
40
45
  # ones in ENV when they are merged together
41
- config.add_namespace("/my/important/namespace", overwrite_duplicates: true)
46
+ config.add_namespace("/my/important/namespace", overload: true)
42
47
  end
48
+
49
+ # Load after configuration
50
+ Chambermaid.load!
51
+ ```
52
+
53
+ **Reload SSM into ENV**
54
+ ```ruby
55
+ Chambermaid.reload!
43
56
  ```
44
57
 
58
+ **Restore ENV to original state**
59
+ ```ruby
60
+ Chambermaid.restore!
61
+ Chambermaid.reset! # alias of .restore!
62
+ ```
63
+
64
+ **Configure Logging**
65
+ ```ruby
66
+ Chambermaid.configure do |config|
67
+ # ... other config ...
68
+
69
+ # Change log level
70
+ config.log_level = :debug
71
+
72
+ # Set custom logger instance
73
+ config.logger = MyCoolLogger.new
74
+ end
75
+
76
+ # Outside of config block
77
+ Chambermaid.log_level = :warn
78
+ ```
79
+
80
+ _Note: Chambermaid.logger is set to Rails.logger automatically if including inside a rails app_
81
+
45
82
  ## Development
46
83
 
47
84
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -28,4 +28,6 @@ Gem::Specification.new do |spec|
28
28
 
29
29
  # Gems
30
30
  spec.add_dependency("aws-sdk-ssm", "~> 1.85")
31
+ spec.add_development_dependency("rspec", "~> 3.0")
32
+ spec.add_development_dependency("rake", "~> 12.0")
31
33
  end
@@ -1,5 +1,6 @@
1
1
  require "chambermaid/base"
2
2
  require "chambermaid/version"
3
+ require "chambermaid/railtie" if defined?(Rails)
3
4
 
4
5
  module Chambermaid
5
6
  class Error < StandardError; end
@@ -1,7 +1,16 @@
1
+ require "logger"
2
+
3
+ require "chambermaid/environment"
4
+ require "chambermaid/namespace"
1
5
  require "chambermaid/parameter_store"
2
6
 
3
7
  module Chambermaid
4
8
  module Base
9
+ def self.extended(base)
10
+ # Make a copy of ENV before we mess it all up
11
+ @@_original_env = ENV.to_h.dup.freeze
12
+ end
13
+
5
14
  extend self
6
15
 
7
16
  def configure
@@ -13,43 +22,126 @@ module Chambermaid
13
22
  raise "Namespaces must be defined" unless @namespaces
14
23
  end
15
24
 
25
+ # Load SSM into ENV
26
+ def load!
27
+ @namespaces.each(&:load!)
28
+ end
29
+
16
30
  # @todo
17
31
  def reload!
32
+ @namespaces.each(&:reload!)
18
33
  end
19
34
 
35
+ def unload!
36
+ @namespaces.each(&:unload!)
37
+ end
38
+
39
+ # Restore ENV to its original state
40
+ def restore!
41
+ ENV.replace(@@_original_env)
42
+ end
43
+ alias :reset! :restore!
44
+
20
45
  # Add an AWS SSM parameter namespace to ENV
21
46
  #
22
47
  # @param [String] path
23
- # @param [Boolean] overwrite_duplicates
48
+ # @param [Boolean] overload
24
49
  # true - replace any duplicate ENV keys with new params
25
50
  # false - keep any existing duplicate ENV key values
26
51
  #
27
- # @raise
28
- def add_namespace(path, overwrite_duplicates: false)
29
- @namespaces ||= {}
30
- raise "namespace already included in ENV" unless @namespaces[path].nil?
52
+ # @raise [ArgumentError]
53
+ # when `path` is not a string
54
+ #
55
+ # @example
56
+ # Chambermaid.add_namespace("/my/param/namespace")
57
+ #
58
+ # @example overload duplicate ENV vars
59
+ # Chambermaid.add_namespace("/my/param/namespace", overload: true)
60
+ def add_namespace(path, overload: false)
61
+ raise ArgumentError.new("`path` must be a string") unless path.is_a?(String)
62
+ raise ArgumentError.new("`overload` must be a boolean") unless [true, false].include?(overload)
31
63
 
32
- @namespaces[path] = ParameterStore.load!(path: path)
33
- update_env!(
34
- params: @namespaces[path].params,
35
- overwrite_duplicates: overwrite_duplicates
36
- )
64
+ namespaces << Namespace.new(path: path, overload: overload)
37
65
  end
38
66
 
39
- # Inject into ENV
67
+ # Immediately load an AWS SSM parameter namespace to ENV
40
68
  #
41
- # @param [Hash] params
42
- # @param [Boolean] overwrite_duplicates
69
+ # @param [String] path
70
+ # @param [Boolean] overload
43
71
  # true - replace any duplicate ENV keys with new params
44
72
  # false - keep any existing duplicate ENV key values
45
- def update_env!(params:, overwrite_duplicates:)
46
- if overwrite_duplicates
47
- ENV.update(params)
48
- else
49
- current_env = ENV.to_h.dup
50
- new_env = params.merge(current_env)
51
- ENV.replace(new_env)
52
- end
73
+ #
74
+ # @raise [ArgumentError]
75
+ # when `path` is not a string
76
+ #
77
+ # @example
78
+ # Chambermaid.add_namespace!("/my/param/namespace")
79
+ #
80
+ # @example overload duplicate ENV vars
81
+ # Chambermaid.add_namespace("/my/param/namespace", overload: true)
82
+ def add_namespace!(path, overload: false)
83
+ raise ArgumentError.new("`path` must be a string") unless path.is_a?(String)
84
+ raise ArgumentError.new("`overload` must be a boolean") unless [true, false].include?(overload)
85
+
86
+ namespaces << Namespace.load!(path: path, overload: overload)
87
+ end
88
+
89
+ # Add all secrets from Chamber service to ENV
90
+ #
91
+ # @param [String] service
92
+ # @param [Boolean] overload
93
+ # true - replace any duplicate ENV keys with new params
94
+ # false - keep any existing duplicate ENV key values
95
+ #
96
+ # @example
97
+ # Chambermaid.add_service("my-chamber-service")
98
+ #
99
+ # @example overload duplicate ENV vars
100
+ # Chambermaid.add_service("my-chamber-service", overload: true)
101
+ #
102
+ # @see {Chambermaid::Base.add_namespace}
103
+ def add_service(service, overload: false)
104
+ service = "/#{service}" unless service[0] == "/"
105
+ add_namespace(service)
106
+ end
107
+
108
+ # !@attribute [r] logger
109
+ # @return [Logger]
110
+ def logger
111
+ @logger ||= Logger.new(STDOUT,
112
+ level: log_level,
113
+ progname: "Chambermaid"
114
+ )
115
+ end
116
+
117
+ # !@attribute [w] logger
118
+ # @return [Logger]
119
+ def logger=(val)
120
+ @logger = val
121
+ @logger.progname = "Chambermaid"
122
+ logger
123
+ end
124
+
125
+ # !@attribute [r] log_level
126
+ # @return [Symbol] (default = :info) current logger level
127
+ def log_level
128
+ return logger.level unless @logger.nil?
129
+ return @log_level unless @log_level.nil?
130
+ return :info
131
+ end
132
+
133
+ # !@attribute [w] log_level
134
+ # @return [Symbol] (default = :info) current logger level
135
+ def log_level=(val = :info)
136
+ @logger.level = val unless @logger.nil?
137
+ @log_level = val
138
+ val
139
+ end
140
+
141
+ private
142
+
143
+ def namespaces
144
+ @namespaces ||= []
53
145
  end
54
146
  end
55
147
  end
@@ -0,0 +1,68 @@
1
+ module Chambermaid
2
+ class Environment < Hash
3
+ attr_reader :params
4
+
5
+ # Create new Chambermaid::Environment
6
+ #
7
+ # @param [Hash] params
8
+ #
9
+ # @raise [ArgumentError]
10
+ # if params is not type Hash
11
+ #
12
+ # @return [Chambermaid::Environment]
13
+ def initialize(params)
14
+ validate_params!(params)
15
+ stash_current_env!
16
+ update(format_env(params))
17
+ end
18
+
19
+ # Generate a dotenv (.env) compatible string
20
+ #
21
+ # @return [String] dotenv compatible string
22
+ def to_dotenv
23
+ to_h.inject("") do |env_str, param|
24
+ env_str + "#{param[0]}=#{param[1]}\n"
25
+ end
26
+ end
27
+
28
+ # Write a .env file
29
+ #
30
+ # @param [String] file_path
31
+ def to_file!(file_path)
32
+ File.open(file_path, "wb") do |f|
33
+ f.write(to_dotenv)
34
+ end
35
+ end
36
+
37
+ # Inject into ENV without overwriting duplicates
38
+ def load!
39
+ each { |k, v| ENV[k] ||= v }
40
+ end
41
+
42
+ # Inject into ENV and overwrite duplicates
43
+ def overload!
44
+ each { |k, v| ENV[k] = v }
45
+ end
46
+
47
+ # Restore to original ENV
48
+ def unload!
49
+ ENV.replace(@_original_env)
50
+ end
51
+
52
+ private
53
+
54
+ def stash_current_env!
55
+ @_original_env ||= ENV.to_h.dup.freeze
56
+ end
57
+
58
+ def format_env(params)
59
+ params.map{|k,v| [k.upcase, v]}.to_h
60
+ end
61
+
62
+ def validate_params!(params)
63
+ unless params.is_a?(Hash)
64
+ raise ArgumentError.new("`params` must be a hash")
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,44 @@
1
+ module Chambermaid
2
+ class Namespace
3
+ # @param [String] path
4
+ # @param [Boolean] overload
5
+ def initialize(path:, overload: false)
6
+ @path = path
7
+ @overload = overload
8
+
9
+ @store = ParameterStore.new(path: path)
10
+ @env = Environment.new({})
11
+ end
12
+
13
+ def self.load!(path:, overload: false)
14
+ namespace = new(path: path, overload: overload)
15
+ namespace.load!
16
+ namespace
17
+ end
18
+
19
+ def load!
20
+ @store.load!
21
+ load_env!
22
+ end
23
+
24
+ def reload!
25
+ @env.unload!
26
+ @store.reload!
27
+ load_env!
28
+ end
29
+
30
+ def unload!
31
+ @env.unload!
32
+ Chambermaid.logger.info("unloaded #{@env.size} params from ENV")
33
+ end
34
+
35
+ private
36
+
37
+ # Inject into ENV
38
+ def load_env!
39
+ @env.replace(@store.params)
40
+ @overload ? @env.overload! : @env.load!
41
+ Chambermaid.logger.info("loaded #{@env.size} params into ENV from `#{@path}`")
42
+ end
43
+ end
44
+ end
@@ -10,6 +10,15 @@ module Chambermaid
10
10
  fetch_ssm_params!
11
11
  end
12
12
 
13
+ def reload!
14
+ clear_params!
15
+ fetch_ssm_params!
16
+ end
17
+
18
+ def loaded?
19
+ !@params_list.empty?
20
+ end
21
+
13
22
  def self.load!(path:)
14
23
  store = new(path: path)
15
24
  store.load!
@@ -24,12 +33,6 @@ module Chambermaid
24
33
 
25
34
  alias :to_h :params
26
35
 
27
- def to_env
28
- params.inject("") do |env_str, param|
29
- env_str + "#{param[0]}=#{param[1]}\n"
30
- end
31
- end
32
-
33
36
  private
34
37
 
35
38
  def client
@@ -37,14 +40,20 @@ module Chambermaid
37
40
  end
38
41
 
39
42
  def fetch_ssm_params!
43
+ Chambermaid.logger.debug("fetching AWS SSM parameters from `#{@path}`")
40
44
  @param_list = []
41
45
  response = nil
42
46
  loop do
43
47
  response = fetch_ssm_param_batch!(response&.next_token)
44
48
  @param_list.concat(response.parameters)
45
49
 
46
- break unless response.next_token
50
+ if response.next_token
51
+ Chambermaid.logger.debug("response.next_token found, continuing fetch")
52
+ else
53
+ break
54
+ end
47
55
  end
56
+ Chambermaid.logger.debug("fetched #{@param_list.size} parameters from `#{@path}`")
48
57
  end
49
58
 
50
59
  def fetch_ssm_param_batch!(next_token = nil)
@@ -55,5 +64,10 @@ module Chambermaid
55
64
  next_token: next_token
56
65
  )
57
66
  end
67
+
68
+ def clear_params!
69
+ @params = nil
70
+ @params_list = []
71
+ end
58
72
  end
59
73
  end
@@ -0,0 +1,8 @@
1
+ module Chambermaid
2
+ class Railtie < Rails::Railtie
3
+ config.before_configuration do
4
+ Chambermaid.logger = Rails.logger
5
+ Chambermaid.load!
6
+ end
7
+ end
8
+ end
@@ -1,3 +1,3 @@
1
1
  module Chambermaid
2
- VERSION = "0.1.0"
2
+ VERSION = "0.4.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chambermaid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Miles Zimmerman
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-01 00:00:00.000000000 Z
11
+ date: 2020-08-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-ssm
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '1.85'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '12.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '12.0'
27
55
  description:
28
56
  email:
29
57
  - miles@asktrim.com
@@ -45,7 +73,10 @@ files:
45
73
  - chambermaid.gemspec
46
74
  - lib/chambermaid.rb
47
75
  - lib/chambermaid/base.rb
76
+ - lib/chambermaid/environment.rb
77
+ - lib/chambermaid/namespace.rb
48
78
  - lib/chambermaid/parameter_store.rb
79
+ - lib/chambermaid/railtie.rb
49
80
  - lib/chambermaid/version.rb
50
81
  homepage: https://github.com/mileszim/chambermaid
51
82
  licenses: