aws_metadata 0.1.5 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +26 -1
- data/aws_metadata.gemspec +1 -0
- data/lib/aws_metadata/instance_metadata.rb +75 -80
- data/lib/aws_metadata/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1f0ca59df969c0d034320866c73989b1c0f3cbb5
|
4
|
+
data.tar.gz: 3fc7e4c98941ddac033aef01b4764e7378d8710f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6bcda2f9346359f806bb8a0ad052fa965277514f62eafd1afc79ad2f85880eede8d80e84438c44a2ae580339b2545da8b68e3e16b48adc3c6654a20c490b9008
|
7
|
+
data.tar.gz: 119731a5c0fbfa70bd4de71a9ac2466d91dbcfd1aae6e41286a823c53aad55bdf053412cc43cf4146bc5e69f20f84dc2db569c4c318b53cf0f04d0a701a78e6c
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -30,6 +30,27 @@ puts AWS::Instance.dynamic.instance_identity.document.account_id
|
|
30
30
|
puts AWS::Instance.user_data
|
31
31
|
```
|
32
32
|
|
33
|
+
AWS::Instance is lazy loaded and only makes calls to 169.254.169.254 for the paths requested. In other words, the entire
|
34
|
+
object hierarchy is not built at once, thereby reducing the total number of HTTP requests and reducing the chance
|
35
|
+
of being throttled by AWS.
|
36
|
+
|
37
|
+
You can alternatively pass the relative endpoint to `metadata` and `dynamic`
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
puts AWS::Instance.metadata(path: 'instance-id')
|
41
|
+
puts AWS::Instance.dynamic( path: ('instance-identity/document').account_id
|
42
|
+
```
|
43
|
+
|
44
|
+
This has the added benefit of reducing the number of HTTP calls even further if needed/desired. For instance `AWS::Instance.metadata.instance_id`
|
45
|
+
will make 2 calls, 1 for `/meta-data` and another for `meta-data/instance-id`, where `AWS::Instance.metadata(path: 'instance-id')`
|
46
|
+
will only make a single call to `/meta-data/instance-id`.
|
47
|
+
|
48
|
+
All calls are cached.
|
49
|
+
|
50
|
+
Calls are retried upto 10 times in 1 second intervals if a 200 response is not received.
|
51
|
+
|
52
|
+
|
53
|
+
|
33
54
|
To return stubbed responses, you can add this to an initializer:
|
34
55
|
|
35
56
|
```ruby
|
@@ -135,7 +156,11 @@ The code for `AWS::Instance` is mostly a copy directly from the aws_instmd repo.
|
|
135
156
|
1. The class name. We removed the MD(metadata) from the name since this gem also has the StackOutput namespace and it's all really metadata.
|
136
157
|
2. `AWS::InstMD.meta_data` to `AWS::Instance.metadata`. We changed meta_data to metadata to be consistent with the naming in our SDK and APIs.
|
137
158
|
3. The `AWS::Instance.dynamic.instance_identity.document` returns a Hashish object you can call methods on, rather than a JSON document that has to be parsed manually into a hash. So `AWS::Instance.dynamic.instance_identity.document.account_id` just works.
|
138
|
-
4. We added the ability to have stubbed responses returned. See the usage section
|
159
|
+
4. We added the ability to have stubbed responses returned. See the usage section above.
|
160
|
+
|
161
|
+
## Dependencies
|
162
|
+
Ruby >= 2.0
|
163
|
+
aws-sdk gem
|
139
164
|
|
140
165
|
## Contributing
|
141
166
|
|
data/aws_metadata.gemspec
CHANGED
@@ -18,6 +18,7 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
+
spec.required_ruby_version = '>= 2.0.0'
|
21
22
|
spec.add_development_dependency "bundler", "~> 1.11"
|
22
23
|
spec.add_development_dependency "rake", "~> 10.0"
|
23
24
|
spec.add_development_dependency 'yard'
|
@@ -4,11 +4,45 @@
|
|
4
4
|
require 'net/http'
|
5
5
|
|
6
6
|
module AWS
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
module Instance
|
8
|
+
def self.metadata(path: nil, version: 'latest', host: '169.254.169.254', port: '80')
|
9
|
+
load_stubs
|
10
|
+
url_prefix = "/#{version}/meta-data/"
|
11
|
+
if path.present?
|
12
|
+
@metadata_path ||= Hashish.new
|
13
|
+
@metadata_path[path] ||= value_by_path(path, @metadata) do
|
14
|
+
query(http(host, port), "#{url_prefix}#{path}")
|
15
|
+
end
|
16
|
+
else
|
17
|
+
@metadata ||= Treeish.new http(host, port), url_prefix
|
18
|
+
raise 'no metadata' if @metadata.blank? # There should always be metadata
|
19
|
+
@metadata
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.user_data(version: 'latest', host: '169.254.169.254', port: '80')
|
24
|
+
load_stubs
|
25
|
+
@user_data ||= query(http(host, port), "/#{version}/user-data")
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.dynamic(path: nil, version: 'latest', host: '169.254.169.254', port: '80')
|
29
|
+
load_stubs
|
30
|
+
url_prefix = "/#{version}/dynamic/"
|
31
|
+
if path.present?
|
32
|
+
@dynamic_path ||= Hashish.new
|
33
|
+
@dynamic_path[path] ||= value_by_path(path, @dynamic) do
|
34
|
+
query(http(host, port), "#{url_prefix}#{path}")
|
35
|
+
end
|
36
|
+
else
|
37
|
+
@dynamic ||= Treeish.new http(host, port), url_prefix
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# All the metadata from 169.254.169.254
|
42
|
+
#
|
43
|
+
# The hashes are Hashish objects that allows regular method like calls where all method names are the keys underscored.
|
44
|
+
def self.to_hash
|
45
|
+
{ :metadata => metadata.merge(Hash(@metadata_path)), :user_data => user_data, :dynamic => dynamic.merge(Hash(@dynamic_path)) }
|
12
46
|
end
|
13
47
|
|
14
48
|
# Can't be the first one to make that pun.
|
@@ -21,115 +55,76 @@ module AWS
|
|
21
55
|
end
|
22
56
|
end
|
23
57
|
|
24
|
-
def method_missing
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
self[name.to_s.gsub('_', '-')]
|
29
|
-
end
|
58
|
+
def method_missing(name)
|
59
|
+
attr = name.to_s.gsub('_', '-')
|
60
|
+
self[attr] = self[attr].call if self[attr].is_a?(Proc)
|
61
|
+
self[attr]
|
30
62
|
end
|
31
63
|
end
|
32
64
|
|
33
65
|
# @private
|
34
66
|
class Treeish < Hashish
|
35
67
|
private
|
36
|
-
def initialize
|
37
|
-
entries = Instance.query
|
68
|
+
def initialize(http, prefix)
|
69
|
+
entries = Instance.query(http, prefix)
|
38
70
|
entries.lines.each do |l|
|
39
71
|
l.chomp!
|
40
72
|
if l.end_with? '/'
|
41
|
-
self[l[0..-2]] = Treeish.new http, "#{prefix}#{l}"
|
73
|
+
self[l[0..-2]] = Proc.new { Treeish.new http, "#{prefix}#{l}" }
|
42
74
|
# meta-data/public-keys/ entries have a '0=foo' format
|
43
75
|
elsif l =~ /(\d+)=(.*)/
|
44
76
|
number, name = $1, $2
|
45
|
-
self[name] = Treeish.new http, "#{prefix}#{number}/"
|
77
|
+
self[name] = Proc.new { Treeish.new http, "#{prefix}#{number}/" }
|
46
78
|
else
|
47
|
-
self[l] = Instance.query
|
79
|
+
self[l] = Proc.new { Instance.query(http, "#{prefix}#{l}") }
|
48
80
|
end
|
49
81
|
end
|
50
82
|
end
|
51
83
|
end
|
52
84
|
|
53
|
-
|
85
|
+
private_class_method
|
54
86
|
|
55
|
-
# Amazon, Y U NO trailing slash entries
|
56
|
-
# in /, /$version and /$version/dynamic/??
|
57
|
-
# There is waaay too much code here.
|
58
87
|
# @private
|
59
|
-
def
|
60
|
-
|
61
|
-
load_stubs
|
62
|
-
return
|
63
|
-
end
|
64
|
-
http = Net::HTTP.new host, port
|
65
|
-
load_metadata(http, version)
|
66
|
-
load_user_data(http, version)
|
67
|
-
load_dynamic(http, version)
|
88
|
+
def self.http(host, port)
|
89
|
+
@http ||= Net::HTTP.new host, port
|
68
90
|
end
|
69
91
|
|
70
92
|
# @private
|
71
|
-
def self.query
|
72
|
-
rep = http.request Net::HTTP::Get.new path
|
73
|
-
unless Net::HTTPOK === rep
|
74
|
-
return nil
|
75
|
-
end
|
76
|
-
rep.body
|
77
|
-
end
|
78
|
-
|
79
|
-
# All the metadata from 169.254.169.254
|
80
|
-
#
|
81
|
-
# The hashes are Hashish objects that allows regular method like calls where all method names are the keys underscored.
|
82
|
-
def to_hash
|
83
|
-
{ :metadata => @metadata, :user_data => @user_data, :dynamic => @dynamic }
|
84
|
-
end
|
85
|
-
|
86
|
-
private
|
87
|
-
|
88
|
-
# Load data from the meta-data URL
|
89
|
-
# @private
|
90
|
-
def load_metadata(http, version)
|
93
|
+
def self.query(http, path)
|
91
94
|
tries ||= 1
|
92
|
-
|
93
|
-
raise
|
95
|
+
rep = http.request Net::HTTP::Get.new path
|
96
|
+
raise "bad request: #{path}" unless Net::HTTPOK === rep
|
97
|
+
value = JSON.parse(rep.body)
|
98
|
+
value.is_a?(Hash) ? Hashish.new(value) : value
|
99
|
+
rescue JSON::ParserError
|
100
|
+
rep.body
|
94
101
|
rescue
|
95
|
-
|
102
|
+
return '' if tries >= 10
|
96
103
|
sleep 1
|
97
104
|
tries += 1
|
98
105
|
retry
|
99
106
|
end
|
100
107
|
|
101
|
-
#
|
108
|
+
# Helper method to provide "stubs" for non aws environments, ie. development and test
|
102
109
|
# @private
|
103
|
-
def
|
104
|
-
|
105
|
-
|
106
|
-
@
|
110
|
+
def self.load_stubs
|
111
|
+
return unless AWS::Metadata.stub_responses && @metadata.blank?
|
112
|
+
@yaml ||= Pathname.new(File.join(AWS::Metadata.aws_identity_stubs_path, 'aws_identity_stubs.yml'))
|
113
|
+
@responses ||= YAML.load(ERB.new(@yaml.read).result)
|
114
|
+
@metadata ||= Hashish.new @responses[:metadata]
|
115
|
+
@user_data ||= @responses[:user_data]
|
116
|
+
@dynamic ||= Hashish.new @responses[:dynamic]
|
117
|
+
@dynamic['instance-identity']['document'] = @dynamic['instance-identity']['document'].to_json
|
107
118
|
end
|
108
119
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
dynamic_stuff = []
|
117
|
-
end
|
118
|
-
dynamic_stuff.each do |e|
|
119
|
-
e = e.chomp.chomp '/'
|
120
|
-
@dynamic[e] = Treeish.new http, "/#{version}/dynamic/#{e}/"
|
120
|
+
def self.value_by_path(path, obj)
|
121
|
+
if AWS::Metadata.stub_responses
|
122
|
+
path.split('/').inject(obj) do |o, method|
|
123
|
+
o.send method.to_s.underscore
|
124
|
+
end
|
125
|
+
else
|
126
|
+
yield
|
121
127
|
end
|
122
128
|
end
|
123
|
-
|
124
|
-
# Helper method to provide "stubs" for non aws deployments
|
125
|
-
# @private
|
126
|
-
def load_stubs
|
127
|
-
yaml = Pathname.new(File.join(AWS::Metadata.aws_identity_stubs_path, 'aws_identity_stubs.yml'))
|
128
|
-
responses = YAML.load(ERB.new(yaml.read).result)
|
129
|
-
@metadata = Hashish.new responses[:metadata]
|
130
|
-
@user_data = responses[:user_data]
|
131
|
-
@dynamic = Hashish.new responses[:dynamic]
|
132
|
-
@dynamic['instance-identity']['document'] = @dynamic['instance-identity']['document'].to_json
|
133
|
-
end
|
134
129
|
end
|
135
130
|
end
|
data/lib/aws_metadata/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aws_metadata
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Evident.io
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-11-
|
11
|
+
date: 2016-11-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -120,7 +120,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
120
120
|
requirements:
|
121
121
|
- - ">="
|
122
122
|
- !ruby/object:Gem::Version
|
123
|
-
version:
|
123
|
+
version: 2.0.0
|
124
124
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
125
|
requirements:
|
126
126
|
- - ">="
|