/
ssm_parameter_store.rb
155 lines (124 loc) Β· 3.16 KB
/
ssm_parameter_store.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
require 'aws-sdk-ssm'
module Lamby
class SsmParameterStore
MAX_RESULTS = 10
Param = Struct.new :name, :env, :value
attr_reader :path, :params
class << self
def dotenv(path)
new(path).get!.to_dotenv
end
def get!(path)
parts = path[1..-1].split('/')
env = parts.pop
path = "/#{parts.join('/')}"
param = new(path).get!.params.detect do |p|
p.env == env
end
param&.value
end
end
def initialize(path, options = {})
@path = path
@params = []
@options = options
end
def to_env(overwrite: true)
params.each do |param|
overwrite ? ENV[param.env] = param.value : ENV[param.env] ||= param.value
end
end
def to_dotenv
File.open(dotenv_file, 'a') { |f| f.write(dotenv_contents) }
end
def get!
get_all!
get_history! unless label.to_s.empty?
self
end
def label
ENV['LAMBY_SSM_PARAMS_LABEL'] || @options[:label]
end
def client
@client ||= begin
options = @options[:client_options] || {}
Aws::SSM::Client.new(options)
end
end
private
def dotenv_file
@options[:dotenv_file] || ENV['LAMBY_SSM_PARAMS_FILE'] || Rails.root.join(".env.#{Rails.env}")
end
def dotenv_contents
params.each_with_object('') do |param, contents|
line = "#{param.env}=#{param.value}\n"
contents << line
end
end
# Path
def get_all!
return params if @got_all
get_parse_all
while @all_response.next_token do get_parse_all end
@got_all = true
params
end
def get_parse_all
get_all
parse_all
end
def get_all
@all_response = client.get_parameters_by_path(get_all_options)
end
def get_all_options
{ path: path,
recursive: true,
with_decryption: true,
max_results: MAX_RESULTS
}.tap { |options|
token = @all_response&.next_token
options[:next_token] = token if token
}
end
def parse_all
@all_response.parameters.each do |p|
env = p.name.split('/').last
params << Param.new(p.name, env, p.value)
end
end
# History
def get_history!
return params if @got_history
params.each do |param|
name = param.name
get_parse_history(name)
while @hist_response.next_token do get_parse_history(name) end
end
@got_history = true
params
end
def get_parse_history(name)
get_history(name)
parse_history(name)
end
def get_history(name)
@hist_response = client.get_parameter_history(get_history_options(name))
end
def get_history_options(name)
{ name: name,
with_decryption: true,
max_results: MAX_RESULTS
}.tap { |options|
token = @hist_response&.next_token
options[:next_token] = token if token
}
end
def parse_history(name)
@hist_response.parameters.each do |p|
next unless p.labels.include? label
param = params.detect { |param| param.name == name }
param.value = p.value
end
end
end
end