sf-hiera-aws 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5158fadbf94eccfdfafaebf7b175d3c11f36a841
4
- data.tar.gz: d69011bbc8cd91207d999bbcb1889b88171a29cf
3
+ metadata.gz: 743247150dec1c5548e31200315a1fdd765afd22
4
+ data.tar.gz: ad06bef85101602ce5b65565289a60a5b13d2920
5
5
  SHA512:
6
- metadata.gz: bca35ff02edb74348a7e3d5a85e3160f6841b553ae8a09fbf350b741344f052eb7f92c21621069bbf2e58f4d2d9b3d5365b75b99d2d925bc6fe8c47364bdf378
7
- data.tar.gz: e6dd2449724903a05aa7b013868cd4237e02d6dc816ae126ce221a4a8d4af04a264f03fb6a2eaf24932685fa7c070a7c06574de1c873b6d100a37959294cba6a
6
+ metadata.gz: 5ab644f595db9b4752aac825b44286dd181282ba06d24ae1e4228a7b539c9a93c7aa9afc4c208b77a2c923f7d2412fea1728261f5124a253dfeb86c3556dc2d5
7
+ data.tar.gz: 1e701867da2da23d371b5d43f2b8c2e08f3663a06c9afcd5f71fbcae3138c59c912a6779f6d6086894ed375b4fe363af0ac94faccefdbdc28443f37b44fff673
data/.gitignore CHANGED
@@ -7,3 +7,5 @@
7
7
  /pkg/
8
8
  /spec/reports/
9
9
  /tmp/
10
+ .ruby-version
11
+ *.swp
data/.rubocop.yml ADDED
@@ -0,0 +1,5 @@
1
+ Style/IndentationWidth:
2
+ Width: 4
3
+
4
+ Style/TrailingComma:
5
+ Enabled: false
data/CHANGELOG.md ADDED
@@ -0,0 +1,14 @@
1
+ ## 0.0.3 (16 December 2015)
2
+
3
+ * Add rspec tests
4
+ * Support configuration under a directory
5
+ * Configurable changes to return values
6
+
7
+ ## 0.0.2 (3 September 2015)
8
+
9
+ * Calculate AWS region from link-local data source
10
+
11
+ ## 0.0.1 (2 September 2015)
12
+
13
+ * Initial release
14
+
data/Gemfile CHANGED
@@ -2,3 +2,13 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in sf-hiera-aws.gemspec
4
4
  gemspec
5
+
6
+ group :development do
7
+ gem 'rspec'
8
+ gem 'rspec-mocks'
9
+ gem 'webmock'
10
+ gem 'hiera'
11
+ gem 'mocha'
12
+ gem 'rubocop'
13
+ gem 'simplecov'
14
+ end
data/README.md CHANGED
@@ -42,6 +42,7 @@ The IAM role will need the following permissions:
42
42
  ## Configuration
43
43
 
44
44
  The plugin expects to find a configuration file under `/etc/puppet/sf_hiera_aws.yaml`, defining how we look up named keys. The keys at the top level of this file determine the names of the hiera keys the plugin will provide; the configuration determines how these are looked up.
45
+ Additional configuration can be given in files under `/etc/puppet/sf_hiera_aws.d`, which are evaluated in alphanumerical order. If a duplicate key is encountered in files evaluated later, this will override the earlier config.
45
46
 
46
47
  ### Example - EC2 nodes by tag
47
48
 
@@ -68,7 +69,9 @@ aws_am_bullseye_rds:
68
69
  db_instance_identifier: "%{::sf_location}-%{::sf_environment}-db"
69
70
  ```
70
71
 
71
- Calls to `:rds_db_instance` type keys return the instance identifier, endpoint address and endpoint port.
72
+ Calls to `:rds_db_instance` type keys return the instance identifier, endpoint address and endpoint port in a hash.
73
+ Pass a `return` key with value `:hostname` to have the hostname of the first matching instance returned.
74
+ Pass a `return` key with value `:hostname_and_port` to have a `"<hostname>:<port>"` string of the first matching instance returned.
72
75
 
73
76
  ### Example - ElastiCache cluster by name
74
77
 
@@ -79,5 +82,6 @@ aws_am_bullseye_redis:
79
82
  ```
80
83
 
81
84
  Calls to `:elasticache_cache_cluster` type keys return a list of cache nodes, their IDs and endpoint address/ports.
82
-
85
+ Pass a `return` key with value `:hostname` to have a list of hostnames of keys of all cache nodes matching the cache_cluster_id returned.
86
+ Pass a `return` key with value `:hostname_and_port` to have a list of `"<hostname>:<port>"` strings returned.
83
87
 
data/Rakefile CHANGED
@@ -1,2 +1,10 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+ require 'rspec/core/rake_task'
2
4
 
5
+ namespace :test do
6
+ RSpec::Core::RakeTask.new(:unit) do |t|
7
+ t.pattern = 'spec/unit/*_test.rb'
8
+ t.rspec_opts = '--color'
9
+ end
10
+ end
@@ -1,14 +1,11 @@
1
1
  class Hiera
2
-
3
2
  module Backend
4
-
5
3
  class Sf_hiera_aws_backend
4
+ private
6
5
 
7
- public
8
-
9
- def initialize
6
+ @instance_identity = nil
10
7
 
11
- require 'aws-sdk-resources'
8
+ def read_link_local_data
12
9
  require 'net/http'
13
10
  require 'json'
14
11
 
@@ -16,88 +13,140 @@ class Hiera
16
13
  http = Net::HTTP.new('169.254.169.254', 80)
17
14
  http.open_timeout = 1
18
15
  http.read_timeout = 1
19
- instance_identity = JSON.parse(http.request(Net::HTTP::Get.new("/latest/dynamic/instance-identity/document")).body)
20
- Aws.config.update({ region: instance_identity['region'] })
21
- rescue Exception
16
+ @instance_identity = JSON.parse(http.request(Net::HTTP::Get.new('/latest/dynamic/instance-identity/document')).body)
17
+ rescue Errno::EHOSTUNREACH, Net::OpenTimeout, Timeout::Error
22
18
  Hiera.warn('No link-local endpoint - can\'t calculate region')
23
19
  end
24
- Hiera.debug('Hiera AWS SDK backend started')
20
+ end
21
+
22
+ # Wrapped these in getters for dependency injection purposes
23
+ def get_rds_client
24
+ Aws::RDS::Client.new
25
+ end
25
26
 
27
+ def get_ec2_client
28
+ Aws::EC2::Client.new
26
29
  end
27
30
 
28
- def lookup (key, scope, order_override, resolution_type)
31
+ def get_elasticache_client
32
+ Aws::ElastiCache::Client.new
33
+ end
29
34
 
35
+ public
36
+
37
+ def initialize
38
+ require 'aws-sdk-resources'
39
+
40
+ read_link_local_data
41
+ unless @instance_identity.nil?
42
+ Aws.config.update(region: @instance_identity['region'])
43
+ end
44
+
45
+ Hiera.debug('Hiera AWS SDK backend started')
46
+ end
47
+
48
+ def lookup(key, scope, _order_override, _resolution_type)
30
49
  config = recursive_interpolate_config(aws_config, scope)
31
50
 
32
51
  Hiera.debug("Looking up '#{key} in AWS SDK backend")
33
52
 
34
- if ! config.key? key
35
- return nil
36
- end
53
+ return nil unless config.key? key
37
54
 
38
55
  Hiera.debug("Config: #{config[key].inspect}")
39
56
  type = config[key]['type']
40
57
 
41
- if self.methods.include? "type_#{type}".to_sym
58
+ if methods.include? "type_#{type}".to_sym
42
59
 
43
60
  begin
44
- answer = self.send("type_#{type}".to_sym, config[key])
45
- Hiera.debug( answer )
61
+ answer = send("type_#{type}".to_sym, config[key])
62
+ Hiera.debug(answer)
46
63
  return answer
47
64
  rescue Aws::Errors::MissingRegionError, Aws::Errors::MissingCredentialsError
48
- Hiera.warn("No IAM role or ENV based AWS config - skipping")
65
+ Hiera.warn('No IAM role or ENV based AWS config - skipping')
49
66
  return nil
50
67
  end
51
68
 
52
69
  end
53
70
 
54
71
  Hiera.debug("Type of AWS SDK lookup '#{type}' invalid")
55
- return nil
56
-
72
+ nil
57
73
  end
58
74
 
59
- def aws_config
60
-
61
- require 'yaml'
75
+ def config_file_name
62
76
 
63
- default_config_path = "/etc/puppet/sf_hiera_aws.yaml"
77
+ default_config_path = '/etc/puppet/sf_hiera_aws.yaml'
64
78
 
65
- if ! Config[:aws_sdk].nil?
79
+ if !Config[:aws_sdk].nil?
66
80
  config_file = Config[:aws_sdk][:config_file] || default_config_path
67
81
  else
68
82
  config_file = default_config_path
69
83
  end
70
84
 
85
+ return config_file
86
+
87
+ end
88
+
89
+ def config_directory_name
90
+
91
+ default_config_path = '/etc/puppet/sf_hiera_aws.d'
92
+
93
+ if !Config[:aws_sdk].nil?
94
+ config_dir = Config[:aws_sdk][:config_directory] || default_config_path
95
+ else
96
+ config_dir = default_config_path
97
+ end
98
+
99
+ return config_dir
100
+
101
+ end
102
+
103
+
104
+ def aws_config
105
+
106
+ require 'yaml'
107
+
108
+ config_file = config_file_name
109
+
71
110
  if File.exist?(config_file)
72
- config = YAML::load_file(config_file)
111
+ config = YAML.load_file(config_file)
73
112
  else
74
113
  Hiera.warn("No config file #{config_file} found")
75
114
  config = {}
76
115
  end
77
116
 
78
- config
117
+ # Merge configs from the config directory too
79
118
 
119
+ config_directory = config_directory_name
120
+
121
+ if File.directory?(config_directory)
122
+ Dir.entries(config_directory).sort.each do |p|
123
+ next if p == '.' or p == '..'
124
+ to_merge = YAML.load_file( File.join( config_directory, p ) )
125
+ config.merge! to_merge
126
+ end
127
+ end
128
+
129
+ config
80
130
  end
81
131
 
82
- def recursive_interpolate_config(h,scope)
132
+ def recursive_interpolate_config(h, scope)
83
133
  case h
84
134
  when Hash
85
135
  Hash[
86
136
  h.map do |k, v|
87
- [ Backend.parse_answer(k, scope), recursive_interpolate_config(v,scope) ]
137
+ [Backend.parse_answer(k, scope), recursive_interpolate_config(v, scope)]
88
138
  end
89
139
  ]
90
140
  when Enumerable
91
- h.map { |v| recursive_interpolate_config(v,scope) }
141
+ h.map { |v| recursive_interpolate_config(v, scope) }
92
142
  when String
93
- Backend.parse_answer(h,scope)
143
+ Backend.parse_answer(h, scope)
94
144
  else
95
145
  h
96
146
  end
97
147
  end
98
148
 
99
149
  def type_ec2_instance(options)
100
-
101
150
  options = {
102
151
  'return' => [
103
152
  :instance_id,
@@ -106,25 +155,23 @@ class Hiera
106
155
  ]
107
156
  }.merge(options)
108
157
 
109
- ec2 = Aws::EC2::Resource.new()
158
+ ec2 = get_ec2_client
110
159
 
111
160
  if options.key? 'filters'
112
- instances = ec2.instances( filters: options['filters'] ) || []
161
+ instances = ec2.describe_instances(filters: options['filters']).reservations.first.instances || []
113
162
  else
114
- instances = ec2.instances() || []
163
+ instances = ec2.describe_instances().reservations.first.instances || []
115
164
  end
116
165
 
117
166
  instances.collect do |i|
118
- Hash[ options['return'].map { |f|
119
- [f.to_s, i.methods.include?(f) ? i.send(f) : nil ]
120
- } ]
167
+ Hash[options['return'].map do |f|
168
+ [f.to_s, i.key?(f) ? i[f] : nil]
169
+ end]
121
170
  end
122
-
123
171
  end
124
172
 
125
173
  def type_rds_db_instance(options)
126
-
127
- rds = Aws::RDS::Client.new()
174
+ rds = get_rds_client
128
175
 
129
176
  if options.key? 'db_instance_identifier'
130
177
  instances = rds.describe_db_instances(
@@ -134,19 +181,42 @@ class Hiera
134
181
  instances = rds.describe_db_instances.db_instances
135
182
  end
136
183
 
137
- instances.collect do |i|
138
- {
139
- 'db_instance_identifier' => i.db_instance_identifier,
140
- 'endpoint_address' => i.endpoint.address,
141
- 'endpoint_port' => i.endpoint.port,
142
- }
184
+ if !options.key? 'return'
185
+
186
+ return instances.collect do |i|
187
+ {
188
+ 'db_instance_identifier' => i.db_instance_identifier,
189
+ 'endpoint_address' => i.endpoint.address,
190
+ 'endpoint_port' => i.endpoint.port,
191
+ }
192
+ end
193
+
143
194
  end
144
195
 
196
+ if options['return'] == :hostname
197
+
198
+ return instances.first.endpoint.address
199
+
200
+ elsif options['return'] == :hostname_and_port
201
+
202
+ return [
203
+ instances.first.endpoint.address,
204
+ instances.first.endpoint.port,
205
+ ].join(':')
206
+
207
+ else
208
+
209
+ Hiera.warn("No return handler for #{options['return']} in rds_db_instance")
210
+ return nil
211
+
212
+ end
213
+
214
+
215
+
145
216
  end
146
217
 
147
218
  def type_elasticache_cache_cluster(options)
148
-
149
- elasticache = Aws::ElastiCache::Client.new()
219
+ elasticache = get_elasticache_client
150
220
 
151
221
  if options.key? 'cache_cluster_id'
152
222
  clusters = elasticache.describe_cache_clusters(
@@ -159,23 +229,50 @@ class Hiera
159
229
  ).cache_clusters
160
230
  end
161
231
 
162
- clusters.collect do |i|
163
- {
164
- 'cache_cluster_id' => i.cache_cluster_id,
165
- 'cache_nodes' => i.cache_nodes.collect do |n|
166
- {
167
- 'cache_node_id' => n.cache_node_id,
168
- 'endpoint_address' => n.endpoint.address,
169
- 'endpoint_port' => n.endpoint.port,
170
- }
232
+ if !options.key? 'return'
233
+
234
+ return clusters.collect do |i|
235
+ {
236
+ 'cache_cluster_id' => i.cache_cluster_id,
237
+ 'cache_nodes' => i.cache_nodes.collect do |n|
238
+ {
239
+ 'cache_node_id' => n.cache_node_id,
240
+ 'endpoint_address' => n.endpoint.address,
241
+ 'endpoint_port' => n.endpoint.port,
242
+ }
243
+ end
244
+ }
245
+ end
246
+
247
+ end
248
+
249
+ if options['return'] == :hostname
250
+
251
+ nodes = []
252
+
253
+ clusters.each do |c|
254
+ c.cache_nodes.each do |n|
255
+ nodes.push(n.endpoint.address)
256
+ end
257
+ end
258
+
259
+ return nodes
260
+
261
+ elsif options['return'] == :hostname_and_port
262
+
263
+ nodes = []
264
+
265
+ clusters.each do |c|
266
+ c.cache_nodes.each do |n|
267
+ nodes.push( [ n.endpoint.address, n.endpoint.port ].join(':') )
171
268
  end
172
- }
269
+ end
270
+
271
+ return nodes
272
+
173
273
  end
174
- end
175
274
 
275
+ end
176
276
  end
177
-
178
277
  end
179
-
180
278
  end
181
-
data/sf-hiera-aws.gemspec CHANGED
@@ -3,21 +3,23 @@ lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.name = "sf-hiera-aws"
7
- spec.version = "0.0.2"
8
- spec.authors = ["Jon Topper"]
9
- spec.email = ["jon@scalefactory.com"]
6
+ spec.name = 'sf-hiera-aws'
7
+ spec.version = '0.0.3'
8
+ spec.authors = ['Jon Topper']
9
+ spec.email = ['jon@scalefactory.com']
10
10
 
11
- spec.summary = %q{Hiera backend for querying AWS resources}
12
- spec.homepage = "https://github.com/scalefactory/sf-hiera-aws"
13
- spec.license = "MIT"
11
+ spec.summary = 'Hiera backend for querying AWS resources'
12
+ spec.homepage = 'https://github.com/scalefactory/sf-hiera-aws'
13
+ spec.license = 'MIT'
14
14
 
15
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
16
- spec.bindir = "exe"
17
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
- spec.require_paths = ["lib"]
15
+ spec.files = `git ls-files -z`.split("\x0").reject { |f|
16
+ f.match(%r{^(test|spec|features)/})
17
+ }
18
+ spec.bindir = 'exe'
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
19
21
 
20
- spec.add_development_dependency "bundler", "~> 1.8"
21
- spec.add_development_dependency "rake", "~> 10.0"
22
- spec.add_dependency "aws-sdk-resources", ">=2.1.18"
22
+ spec.add_development_dependency 'bundler', '~> 1.8'
23
+ spec.add_development_dependency 'rake', '~> 10.0'
24
+ spec.add_dependency 'aws-sdk-resources', '>=2.2.6'
23
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sf-hiera-aws
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Topper
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-09-03 00:00:00.000000000 Z
11
+ date: 2015-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 2.1.18
47
+ version: 2.2.6
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 2.1.18
54
+ version: 2.2.6
55
55
  description:
56
56
  email:
57
57
  - jon@scalefactory.com
@@ -60,6 +60,8 @@ extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
62
  - ".gitignore"
63
+ - ".rubocop.yml"
64
+ - CHANGELOG.md
63
65
  - Gemfile
64
66
  - LICENSE.txt
65
67
  - README.md