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 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
- ## PROJECT::SPECIFIC
21
+ rdoc
22
+ tmtags
data/README.rdoc CHANGED
@@ -1,6 +1,50 @@
1
1
  = ec2-metadata
2
2
 
3
- Description goes here.
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
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 get(path)
25
- logging("Ec2Metadata.get(#{path.inspect})") do
26
- Net::HTTP.get(DEFAULT_HOST, path)
27
- end
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
@@ -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 = child_key.to_s.gsub(/_/, '-')
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 = child_key.to_s.gsub(/_/, '-') << '/'
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
- NamedBase.new(name, "#{path}#{child_key}/")
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