aws_metadata 0.1.5 → 0.2.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 +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
|
- - ">="
|