ec2-metadata 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|