ec2-metadata 0.1.0 → 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.
- data/.gitignore +15 -14
- data/README.rdoc +45 -1
- data/Rakefile +5 -0
- data/VERSION +1 -1
- data/bin/ec2-metadata +44 -0
- data/ec2-metadata.gemspec +85 -0
- data/lib/ec2_metadata.rb +27 -5
- data/lib/ec2_metadata/base.rb +36 -3
- data/lib/ec2_metadata/command.rb +68 -0
- data/lib/ec2_metadata/dummy.rb +38 -0
- data/lib/ec2_metadata/dummy.yml +34 -0
- data/lib/ec2_metadata/http_client.rb +29 -0
- data/lib/hash_key_orderable.rb +23 -0
- data/spec/ec2_metadata/base_spec.rb +16 -15
- data/spec/ec2_metadata/command_spec.rb +101 -0
- data/spec/ec2_metadata/dummy_spec.rb +92 -0
- data/spec/ec2_metadata/http_client_spec.rb +34 -0
- data/spec/ec2_metadata/revision_spec.rb +2 -2
- data/spec/ec2_metadata/root_spec.rb +7 -7
- data/spec/ec2_metadata_spec.rb +8 -8
- data/spec/hash_key_orderable_spec.rb +50 -0
- data/spec/introduction_spec.rb +27 -27
- data/spec/rcov.opts +1 -0
- data/spec/to_hash_spec.rb +121 -0
- metadata +24 -7
- data/lib/ec2_metadata/named_base.rb +0 -17
data/.gitignore
CHANGED
@@ -1,21 +1,22 @@
|
|
1
|
-
## MAC OS
|
2
|
-
.DS_Store
|
3
1
|
|
4
|
-
## TEXTMATE
|
5
|
-
*.tmproj
|
6
|
-
tmtags
|
7
2
|
|
8
|
-
## EMACS
|
9
|
-
*~
|
10
|
-
\#*
|
11
|
-
.\#*
|
12
3
|
|
13
|
-
## VIM
|
14
|
-
*.swp
|
15
4
|
|
5
|
+
|
6
|
+
## EMACS
|
7
|
+
## MAC OS
|
16
8
|
## PROJECT::GENERAL
|
9
|
+
## PROJECT::SPECIFIC
|
10
|
+
## TEXTMATE
|
11
|
+
## VIM
|
12
|
+
*.swp
|
13
|
+
*.tmproj
|
14
|
+
*~
|
15
|
+
.DS_Store
|
16
|
+
.\#*
|
17
|
+
/ec2-metadata-0.1.0.gem
|
18
|
+
\#*
|
17
19
|
coverage
|
18
|
-
rdoc
|
19
20
|
pkg
|
20
|
-
|
21
|
-
|
21
|
+
rdoc
|
22
|
+
tmtags
|
data/README.rdoc
CHANGED
@@ -1,6 +1,50 @@
|
|
1
1
|
= ec2-metadata
|
2
2
|
|
3
|
-
|
3
|
+
== Install
|
4
|
+
$ [sudo] gem install ec2-metadata
|
5
|
+
|
6
|
+
== As ruby library
|
7
|
+
ec-metadata provides a way to access meta-data and user-data on EC2 instance.
|
8
|
+
|
9
|
+
Ec2Metadata[:instance_id]
|
10
|
+
Ec2Metadata['instance_id']
|
11
|
+
Ec2Metadata[:'instance-id']
|
12
|
+
Ec2Metadata['instance-id']
|
13
|
+
|
14
|
+
If you want to specify API version, you can get data like this:
|
15
|
+
Ec2Metadata['1.0'][:instance_id]
|
16
|
+
|
17
|
+
If you can also get it like this:
|
18
|
+
Ec2Metadata['1.0']['meta-data'][:instance_id]
|
19
|
+
|
20
|
+
For more detail, see also:
|
21
|
+
http://github.com/akm/ec2-metadata/blob/master/spec/introduction_spec.rb
|
22
|
+
|
23
|
+
|
24
|
+
== As a command
|
25
|
+
ec2-metadata shows various meta-data and user-data
|
26
|
+
$ ec2-metadata
|
27
|
+
|
28
|
+
For more detail, type
|
29
|
+
$ ec2-metadata -h
|
30
|
+
|
31
|
+
|
32
|
+
== Dummy YAML
|
33
|
+
If you want to access meta-data or user-data not on EC2 Instance like on it,
|
34
|
+
make one of these files
|
35
|
+
./config/ec2_metadata.yml
|
36
|
+
./ec2_metadata.yml
|
37
|
+
~/ec2_metadata.yml
|
38
|
+
/etc/ec2_metadata.yml
|
39
|
+
|
40
|
+
Dummy YAML file must be like output of ec2-metadata on EC2 instance.
|
41
|
+
You can export it on EC2 instance like this:
|
42
|
+
$ ec2-medatata > ec2_metadata.yml
|
43
|
+
$ cp ec2_metadata.yml /path/to/dir/for/non/ec2/instance
|
44
|
+
|
45
|
+
Or if you don't have EC2 instance, you can get an example by
|
46
|
+
$ ec2-metadata -d
|
47
|
+
|
4
48
|
|
5
49
|
== Note on Patches/Pull Requests
|
6
50
|
|
data/Rakefile
CHANGED
@@ -10,6 +10,8 @@ begin
|
|
10
10
|
gem.email = "akm2000@gmail.com"
|
11
11
|
gem.homepage = "http://github.com/akm/ec2-metadata"
|
12
12
|
gem.authors = ["Takeshi AKIMA"]
|
13
|
+
gem.bindir = 'bin'
|
14
|
+
gem.executables = ['ec2-metadata']
|
13
15
|
gem.add_development_dependency "rspec", ">= 1.2.9"
|
14
16
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
15
17
|
end
|
@@ -28,6 +30,9 @@ Spec::Rake::SpecTask.new(:rcov) do |spec|
|
|
28
30
|
spec.libs << 'lib' << 'spec'
|
29
31
|
spec.pattern = 'spec/**/*_spec.rb'
|
30
32
|
spec.rcov = true
|
33
|
+
spec.rcov_opts = lambda do
|
34
|
+
IO.readlines("spec/rcov.opts").map {|l| l.chomp.split " "}.flatten
|
35
|
+
end
|
31
36
|
end
|
32
37
|
|
33
38
|
task :spec => :check_dependencies
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/bin/ec2-metadata
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'ec2_metadata'
|
5
|
+
require 'yaml'
|
6
|
+
require 'optparse'
|
7
|
+
|
8
|
+
options = {:api_version => 'latest'}
|
9
|
+
|
10
|
+
ARGV.options do |o|
|
11
|
+
o.banner = 'Usage: ec2-metadata [options]'
|
12
|
+
|
13
|
+
o.on("-a [api-version]", '--api-version',
|
14
|
+
"Specify an API version. default is 'latest'.") do |v|
|
15
|
+
options[:api_version] = v
|
16
|
+
end
|
17
|
+
|
18
|
+
o.on("-V", '--display-api-versions',
|
19
|
+
"Display API versions and quit.") do
|
20
|
+
Ec2Metadata::Command.show_api_versions
|
21
|
+
exit
|
22
|
+
end
|
23
|
+
|
24
|
+
o.on("-d", '--display-dummy-yaml',
|
25
|
+
"Display a dummy YAML and quit.") do
|
26
|
+
Ec2Metadata::Command.show_dummy_yaml
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
|
30
|
+
o.separator("General Options:")
|
31
|
+
|
32
|
+
o.on("-v", '--version', "Show the version number.") do
|
33
|
+
puts("ec2-metadata " <<
|
34
|
+
IO.read(File.join(File.dirname(__FILE__), "../VERSION")))
|
35
|
+
exit
|
36
|
+
end
|
37
|
+
|
38
|
+
o.on("-h", '--help', "Show this help message."){ puts o; exit}
|
39
|
+
|
40
|
+
o.parse!
|
41
|
+
end
|
42
|
+
|
43
|
+
Ec2Metadata::Command.show(options[:api_version])
|
44
|
+
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{ec2-metadata}
|
8
|
+
s.version = "0.2.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Takeshi AKIMA"]
|
12
|
+
s.date = %q{2010-04-08}
|
13
|
+
s.default_executable = %q{ec2-metadata}
|
14
|
+
s.description = %q{ec2-metadata provides to access metadata, and you can use in outside of ec2 like in ec2}
|
15
|
+
s.email = %q{akm2000@gmail.com}
|
16
|
+
s.executables = ["ec2-metadata"]
|
17
|
+
s.extra_rdoc_files = [
|
18
|
+
"LICENSE",
|
19
|
+
"README.rdoc"
|
20
|
+
]
|
21
|
+
s.files = [
|
22
|
+
".document",
|
23
|
+
".gitignore",
|
24
|
+
"LICENSE",
|
25
|
+
"README.rdoc",
|
26
|
+
"Rakefile",
|
27
|
+
"VERSION",
|
28
|
+
"bin/ec2-metadata",
|
29
|
+
"ec2-metadata.gemspec",
|
30
|
+
"lib/ec2_metadata.rb",
|
31
|
+
"lib/ec2_metadata/base.rb",
|
32
|
+
"lib/ec2_metadata/command.rb",
|
33
|
+
"lib/ec2_metadata/dummy.rb",
|
34
|
+
"lib/ec2_metadata/dummy.yml",
|
35
|
+
"lib/ec2_metadata/http_client.rb",
|
36
|
+
"lib/ec2_metadata/revision.rb",
|
37
|
+
"lib/ec2_metadata/root.rb",
|
38
|
+
"lib/hash_key_orderable.rb",
|
39
|
+
"spec/ec2_metadata/base_spec.rb",
|
40
|
+
"spec/ec2_metadata/command_spec.rb",
|
41
|
+
"spec/ec2_metadata/dummy_spec.rb",
|
42
|
+
"spec/ec2_metadata/http_client_spec.rb",
|
43
|
+
"spec/ec2_metadata/revision_spec.rb",
|
44
|
+
"spec/ec2_metadata/root_spec.rb",
|
45
|
+
"spec/ec2_metadata_spec.rb",
|
46
|
+
"spec/hash_key_orderable_spec.rb",
|
47
|
+
"spec/introduction_spec.rb",
|
48
|
+
"spec/rcov.opts",
|
49
|
+
"spec/spec.opts",
|
50
|
+
"spec/spec_helper.rb",
|
51
|
+
"spec/to_hash_spec.rb"
|
52
|
+
]
|
53
|
+
s.homepage = %q{http://github.com/akm/ec2-metadata}
|
54
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
55
|
+
s.require_paths = ["lib"]
|
56
|
+
s.rubygems_version = %q{1.3.6}
|
57
|
+
s.summary = %q{ec2-metadata provides to access metadata}
|
58
|
+
s.test_files = [
|
59
|
+
"spec/ec2_metadata/base_spec.rb",
|
60
|
+
"spec/ec2_metadata/command_spec.rb",
|
61
|
+
"spec/ec2_metadata/dummy_spec.rb",
|
62
|
+
"spec/ec2_metadata/http_client_spec.rb",
|
63
|
+
"spec/ec2_metadata/revision_spec.rb",
|
64
|
+
"spec/ec2_metadata/root_spec.rb",
|
65
|
+
"spec/ec2_metadata_spec.rb",
|
66
|
+
"spec/hash_key_orderable_spec.rb",
|
67
|
+
"spec/introduction_spec.rb",
|
68
|
+
"spec/spec_helper.rb",
|
69
|
+
"spec/to_hash_spec.rb"
|
70
|
+
]
|
71
|
+
|
72
|
+
if s.respond_to? :specification_version then
|
73
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
74
|
+
s.specification_version = 3
|
75
|
+
|
76
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
77
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
78
|
+
else
|
79
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
80
|
+
end
|
81
|
+
else
|
82
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
data/lib/ec2_metadata.rb
CHANGED
@@ -1,12 +1,19 @@
|
|
1
1
|
require 'net/http'
|
2
|
+
Net::HTTP.version_1_2
|
2
3
|
|
3
4
|
module Ec2Metadata
|
4
5
|
DEFAULT_HOST = "169.254.169.254".freeze
|
5
6
|
|
7
|
+
autoload :HttpClient, 'ec2_metadata/http_client'
|
6
8
|
autoload :Base, 'ec2_metadata/base'
|
7
|
-
autoload :NamedBase, 'ec2_metadata/named_base'
|
8
9
|
autoload :Root, 'ec2_metadata/root'
|
9
10
|
autoload :Revision, 'ec2_metadata/revision'
|
11
|
+
autoload :Dummy, 'ec2_metadata/dummy'
|
12
|
+
autoload :Command, 'ec2_metadata/command'
|
13
|
+
|
14
|
+
DEFAULT_REVISION = 'latest'
|
15
|
+
|
16
|
+
extend HttpClient
|
10
17
|
|
11
18
|
class << self
|
12
19
|
def instance
|
@@ -21,10 +28,21 @@ module Ec2Metadata
|
|
21
28
|
instance[key]
|
22
29
|
end
|
23
30
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
27
|
-
|
31
|
+
def to_hash(revision = DEFAULT_REVISION)
|
32
|
+
self[revision].to_hash
|
33
|
+
end
|
34
|
+
|
35
|
+
def from_hash(hash, revision = DEFAULT_REVISION)
|
36
|
+
# hash = {revision => hash}
|
37
|
+
# instance.from_hash(hash)
|
38
|
+
rev_obj = instance.new_child(revision)
|
39
|
+
instance.instance_variable_set(:@children, {revision => rev_obj})
|
40
|
+
instance.instance_variable_set(:@child_keys, [revision])
|
41
|
+
rev_obj.from_hash(hash)
|
42
|
+
end
|
43
|
+
|
44
|
+
def formalize_key(key)
|
45
|
+
key.to_s.gsub(/_/, '-')
|
28
46
|
end
|
29
47
|
|
30
48
|
def logging(msg)
|
@@ -46,3 +64,7 @@ module Ec2Metadata
|
|
46
64
|
end
|
47
65
|
|
48
66
|
end
|
67
|
+
|
68
|
+
unless ENV['EC2_METADATA_DUMMY_DISABLED'] =~ /yes|true|on/i
|
69
|
+
Ec2Metadata::Dummy.search_and_load_yaml
|
70
|
+
end
|
data/lib/ec2_metadata/base.rb
CHANGED
@@ -36,7 +36,7 @@ module Ec2Metadata
|
|
36
36
|
|
37
37
|
def get(child_key)
|
38
38
|
logging("#{self.class.name}.get(#{child_key.inspect})") do
|
39
|
-
child_key =
|
39
|
+
child_key = Ec2Metadata.formalize_key(child_key)
|
40
40
|
if children.has_key?(child_key)
|
41
41
|
result = children[child_key]
|
42
42
|
else
|
@@ -61,13 +61,17 @@ module Ec2Metadata
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def is_struct?(child_key)
|
64
|
-
k =
|
64
|
+
k = Ec2Metadata.formalize_key(child_key) << '/'
|
65
65
|
child_keys.include?(k) || (defined?(@child_names) && @child_names.keys.include?(child_key))
|
66
66
|
end
|
67
67
|
|
68
68
|
def new_child(child_key)
|
69
69
|
if defined?(@child_names) && (name = @child_names[child_key])
|
70
|
-
|
70
|
+
grandchild = Base.new("#{path}#{child_key}/")
|
71
|
+
child = Base.new("#{path}#{child_key}/")
|
72
|
+
child.instance_variable_set(:@children, {name => grandchild})
|
73
|
+
child.instance_variable_set(:@child_keys, [name])
|
74
|
+
child
|
71
75
|
else
|
72
76
|
Base.new("#{path}#{child_key}/")
|
73
77
|
end
|
@@ -81,6 +85,35 @@ module Ec2Metadata
|
|
81
85
|
end
|
82
86
|
end
|
83
87
|
|
88
|
+
def to_hash
|
89
|
+
keys.inject({}) do |dest, key|
|
90
|
+
key = key.sub(/\/$/, '')
|
91
|
+
value = get(key)
|
92
|
+
dest[key] = value.respond_to?(:to_hash) ? value.to_hash : value
|
93
|
+
dest
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def from_hash(hash)
|
98
|
+
hash = hash.inject({}){|d, (k, v)| d[Ec2Metadata.formalize_key(k)] = v; d}
|
99
|
+
@child_keys = hash.keys
|
100
|
+
@children = {}
|
101
|
+
hash.each do |key, value|
|
102
|
+
if value.is_a?(Array)
|
103
|
+
idx = 0
|
104
|
+
value = value.inject({}){|d, v| d[idx] = v; idx += 1; d}
|
105
|
+
end
|
106
|
+
if value.is_a?(Hash)
|
107
|
+
child = new_child(key)
|
108
|
+
@children[key] = child
|
109
|
+
child.from_hash(value)
|
110
|
+
else
|
111
|
+
@children[key] = value
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
|
84
117
|
private
|
85
118
|
def logging(msg, &block)
|
86
119
|
Ec2Metadata.logging(msg, &block)
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'ec2_metadata'
|
3
|
+
require 'hash_key_orderable'
|
4
|
+
|
5
|
+
module Ec2Metadata
|
6
|
+
module Command
|
7
|
+
class << self
|
8
|
+
DATA_KEY_ORDER = %w(meta-data user-data)
|
9
|
+
# %w(...)の中に改行を入れるとrcovがパスしていることを認識してくれないので、各行毎に%w(..)します
|
10
|
+
META_DATA_KEY_ORDER =
|
11
|
+
%w(ami-id ami-launch-index ami-manifest-path ancestor-ami-ids) +
|
12
|
+
%w(instance-id instance-type instance-action) +
|
13
|
+
%w(public-keys/ placement/ security-groups) +
|
14
|
+
%w(hostname) +
|
15
|
+
%w(public-hostname public-ipv4) +
|
16
|
+
%w(local-hostname local-ipv4) +
|
17
|
+
%w(block-device-mapping/) +
|
18
|
+
%w(kernel-id) +
|
19
|
+
%w(ramdisk-id) +
|
20
|
+
%w(reservation-id)
|
21
|
+
|
22
|
+
def show(api_version = 'latest')
|
23
|
+
timeout do
|
24
|
+
v = (api_version || '').strip
|
25
|
+
unless Ec2Metadata.instance.keys.include?(v)
|
26
|
+
raise ArgumentError, "API version must be one of #{Ec2Metadata.instance.keys.inspect} but was #{api_version.inspect}"
|
27
|
+
end
|
28
|
+
show_yaml_path_if_loaded
|
29
|
+
data = Ec2Metadata[v].to_hash
|
30
|
+
data.extend(HashKeyOrderable)
|
31
|
+
data.key_order = DATA_KEY_ORDER
|
32
|
+
meta_data = data['meta-data']
|
33
|
+
meta_data.extend(HashKeyOrderable)
|
34
|
+
meta_data.key_order = META_DATA_KEY_ORDER
|
35
|
+
puts YAML.dump(data)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def show_api_versions
|
40
|
+
timeout do
|
41
|
+
show_yaml_path_if_loaded
|
42
|
+
puts Ec2Metadata.instance.keys
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def show_dummy_yaml
|
47
|
+
show_yaml_path_if_loaded
|
48
|
+
puts IO.read(File.expand_path(File.join(File.dirname(__FILE__), 'dummy.yml')))
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
def timeout
|
53
|
+
begin
|
54
|
+
yield
|
55
|
+
rescue Timeout::Error, SystemCallError => error
|
56
|
+
puts "HTTP request timed out. You can use dummy YAML for non EC2 Instance. #{Dummy.yaml_paths.inspect}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def show_yaml_path_if_loaded
|
61
|
+
if path = Ec2Metadata::Dummy.loaded_yaml_path
|
62
|
+
puts "Actually these data is based on a DUMMY yaml file: #{path}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Ec2Metadata
|
2
|
+
module Dummy
|
3
|
+
YAML_FILENAME = 'ec2_metadata.yml'.freeze
|
4
|
+
YAML_SEARCH_DIRS = ['./config', '.', '~', '/etc'].freeze
|
5
|
+
ENV_SPECIFIED_PATH = "EC2_METADATA_DUMMY_YAML".freeze
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def yaml_paths
|
9
|
+
dirs = YAML_SEARCH_DIRS.dup
|
10
|
+
if Module.constants.include?('RAILS_ROOT')
|
11
|
+
dirs.unshift(File.join(Module.const_get('RAILS_ROOT'), 'config'))
|
12
|
+
end
|
13
|
+
result = dirs.map{|d| File.join(d, YAML_FILENAME)}
|
14
|
+
if specified_path = ENV[ENV_SPECIFIED_PATH]
|
15
|
+
result.unshift(specified_path)
|
16
|
+
end
|
17
|
+
result
|
18
|
+
end
|
19
|
+
|
20
|
+
def search_and_load_yaml
|
21
|
+
paths = Dir.glob(yaml_paths.map{|path| File.expand_path(path)})
|
22
|
+
load_yaml(paths.first) unless paths.empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
def load_yaml(path)
|
26
|
+
erb = ERB.new(IO.read(path))
|
27
|
+
erb.filename = path
|
28
|
+
text = erb.result
|
29
|
+
Ec2Metadata.from_hash(YAML.load(text))
|
30
|
+
@loaded_yaml_path = path
|
31
|
+
end
|
32
|
+
|
33
|
+
def loaded_yaml_path
|
34
|
+
@loaded_yaml_path
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|