[Pkg-puppet-devel] [facter] 43/180: (FACT-185) Update ec2 facts to use new ec2 query classes

Stig Sandbeck Mathisen ssm at debian.org
Mon Jun 30 15:06:29 UTC 2014


This is an automated email from the git hooks/post-receive script.

ssm pushed a commit to branch master
in repository facter.

commit 07f5dfbeee62aaab2c6028c21b5b308b13b3f267
Author: Adrien Thebo <git at somethingsinistral.net>
Date:   Wed Apr 2 16:33:10 2014 -0700

    (FACT-185) Update ec2 facts to use new ec2 query classes
---
 lib/facter/ec2.rb     |  59 +++++++------
 spec/unit/ec2_spec.rb | 228 +++++++++++++++++---------------------------------
 2 files changed, 112 insertions(+), 175 deletions(-)

diff --git a/lib/facter/ec2.rb b/lib/facter/ec2.rb
index 09e0109..2e57592 100644
--- a/lib/facter/ec2.rb
+++ b/lib/facter/ec2.rb
@@ -1,37 +1,44 @@
-require 'facter/util/ec2'
-require 'open-uri'
+require 'facter/ec2/rest'
 
-def metadata(id = "")
-  open("http://169.254.169.254/2008-02-01/meta-data/#{id||=''}").read.
-    split("\n").each do |o|
-    key = "#{id}#{o.gsub(/\=.*$/, '/')}"
-    if key[-1..-1] != '/'
-      value = open("http://169.254.169.254/2008-02-01/meta-data/#{key}").read.
-        split("\n")
-      symbol = "ec2_#{key.gsub(/\-|\//, '_')}".to_sym
-      Facter.add(symbol) { setcode { value.join(',') } }
-    else
-      metadata(key)
+Facter.define_fact(:ec2_metadata) do
+  define_resolution(:rest) do
+    confine do
+      Facter.value(:virtual).match /^xen/
+    end
+
+    @querier = Facter::EC2::Metadata.new
+    confine do
+      @querier.reachable?
+    end
+
+    setcode do
+      @querier.fetch
     end
   end
-rescue => details
-  Facter.warn "Could not retrieve ec2 metadata: #{details.message}"
 end
 
-def userdata()
-  Facter.add(:ec2_userdata) do
+Facter.define_fact(:ec2_userdata) do
+  define_resolution(:rest) do
+    confine do
+      Facter.value(:virtual).match /^xen/
+    end
+
+    @querier = Facter::EC2::Userdata.new
+    confine do
+      @querier.reachable?
+    end
+
     setcode do
-      if userdata = Facter::Util::EC2.userdata
-        userdata.split
-      end
+      @querier.fetch
     end
   end
 end
 
-if (Facter::Util::EC2.has_euca_mac? || Facter::Util::EC2.has_openstack_mac? ||
-    Facter::Util::EC2.has_ec2_arp?) && Facter::Util::EC2.can_connect?
-  metadata
-  userdata
-else
-  Facter.debug "Not an EC2 host"
+# The flattened version of the EC2 facts are deprecated and will be removed in
+# a future release of Facter.
+if (ec2_metadata = Facter.value(:ec2_metadata))
+  ec2_facts = Facter::Util::Values.flatten_structure("ec2", ec2_metadata)
+  ec2_facts.each_pair do |factname, factvalue|
+    Facter.add(factname, :value => factvalue)
+  end
 end
diff --git a/spec/unit/ec2_spec.rb b/spec/unit/ec2_spec.rb
index f26a613..bf2aa2f 100755
--- a/spec/unit/ec2_spec.rb
+++ b/spec/unit/ec2_spec.rb
@@ -1,187 +1,117 @@
-#! /usr/bin/env ruby
-
 require 'spec_helper'
-require 'facter/util/ec2'
-
-describe "ec2 facts" do
-  # This is the standard prefix for making an API call in EC2 (or fake)
-  # environments.
-  let(:api_prefix) { "http://169.254.169.254" }
-
-  describe "when running on ec2" do
-    before :each do
-      # This is an ec2 instance, not a eucalyptus instance
-      Facter::Util::EC2.stubs(:has_euca_mac?).returns(false)
-      Facter::Util::EC2.stubs(:has_openstack_mac?).returns(false)
-      Facter::Util::EC2.stubs(:has_ec2_arp?).returns(true)
-
-      # Assume we can connect
-      Facter::Util::EC2.stubs(:can_connect?).returns(true)
-    end
-
-    it "should create flat meta-data facts" do
-      Object.any_instance.expects(:open).
-        with("#{api_prefix}/2008-02-01/meta-data/").
-        at_least_once.returns(StringIO.new("foo"))
+require 'facter/ec2/rest'
 
-      Object.any_instance.expects(:open).
-        with("#{api_prefix}/2008-02-01/meta-data/foo").
-        at_least_once.returns(StringIO.new("bar"))
+describe "ec2_metadata" do
+  let(:querier) { stub('EC2 metadata querier') }
 
-      Facter.collection.internal_loader.load(:ec2)
-
-      Facter.fact(:ec2_foo).value.should == "bar"
-    end
+  before do
+    Facter::EC2::Metadata.stubs(:new).returns querier
+    Facter.collection.internal_loader.load(:ec2)
+  end
 
-    it "should create flat meta-data facts with comma seperation" do
-      Object.any_instance.expects(:open).
-        with("#{api_prefix}/2008-02-01/meta-data/").
-        at_least_once.returns(StringIO.new("foo"))
+  subject { Facter.fact(:ec2_metadata).resolution(:rest) }
 
-      Object.any_instance.expects(:open).
-        with("#{api_prefix}/2008-02-01/meta-data/foo").
-        at_least_once.returns(StringIO.new("bar\nbaz"))
+  it "is unsuitable if the virtual fact is not xen" do
+    Facter.fact(:virtual).stubs(:value).returns "kvm"
+    expect(subject).to_not be_suitable
+  end
 
-      Facter.collection.internal_loader.load(:ec2)
+  it "is unsuitable if ec2 endpoint is not reachable" do
+    Facter.fact(:virtual).stubs(:value).returns "xen"
+    querier.stubs(:reachable?).returns false
+    expect(subject).to_not be_suitable
+  end
 
-      Facter.fact(:ec2_foo).value.should == "bar,baz"
+  describe "when the ec2 endpoint is reachable" do
+    before do
+      querier.stubs(:reachable?).returns true
     end
 
-    it "should create structured meta-data facts" do
-      Object.any_instance.expects(:open).
-        with("#{api_prefix}/2008-02-01/meta-data/").
-        at_least_once.returns(StringIO.new("foo/"))
-
-      Object.any_instance.expects(:open).
-        with("#{api_prefix}/2008-02-01/meta-data/foo/").
-        at_least_once.returns(StringIO.new("bar"))
+    it "is suitable if the virtual fact is xen" do
+      Facter.fact(:virtual).stubs(:value).returns "xen"
+      subject.suitable?
 
-      Object.any_instance.expects(:open).
-        with("#{api_prefix}/2008-02-01/meta-data/foo/bar").
-        at_least_once.returns(StringIO.new("baz"))
-
-      Facter.collection.internal_loader.load(:ec2)
-
-      Facter.fact(:ec2_foo_bar).value.should == "baz"
+      expect(subject).to be_suitable
     end
 
-    it "should create ec2_user_data fact" do
-      # No meta-data
-      Object.any_instance.expects(:open).
-        with("#{api_prefix}/2008-02-01/meta-data/").
-        at_least_once.returns(StringIO.new(""))
-
-      Facter::Util::EC2.stubs(:read_uri).
-        with("#{api_prefix}/latest/user-data/").
-        returns("test")
-
-      Facter.collection.internal_loader.load(:ec2)
-      Facter.fact(:ec2_userdata).value.should == ["test"]
+    it "is suitable if the virtual fact is xenu" do
+      Facter.fact(:virtual).stubs(:value).returns "xenu"
+      expect(subject).to be_suitable
     end
   end
 
-  describe "when running on eucalyptus" do
-    before :each do
-      # Return false for ec2, true for eucalyptus
-      Facter::Util::EC2.stubs(:has_euca_mac?).returns(true)
-      Facter::Util::EC2.stubs(:has_openstack_mac?).returns(false)
-      Facter::Util::EC2.stubs(:has_ec2_arp?).returns(false)
-
-      # Assume we can connect
-      Facter::Util::EC2.stubs(:can_connect?).returns(true)
-    end
+  it "resolves the value by recursively querying the rest endpoint" do
+    querier.expects(:fetch).returns({"hello" => "world"})
+    expect(subject.value).to eq({"hello" => "world"})
+  end
+end
 
-    it "should create ec2_user_data fact" do
-      # No meta-data
-      Object.any_instance.expects(:open).\
-        with("#{api_prefix}/2008-02-01/meta-data/").\
-        at_least_once.returns(StringIO.new(""))
+describe "ec2_userdata" do
+  let(:querier) { stub('EC2 metadata querier') }
 
-      Facter::Util::EC2.stubs(:read_uri).
-        with("#{api_prefix}/latest/user-data/").
-        returns("test")
+  before do
+    Facter::EC2::Userdata.stubs(:new).returns querier
+    Facter.collection.internal_loader.load(:ec2)
+  end
 
-      # Force a fact load
-      Facter.collection.internal_loader.load(:ec2)
+  subject { Facter.fact(:ec2_userdata).resolution(:rest) }
 
-      Facter.fact(:ec2_userdata).value.should == ["test"]
-    end
+  it "is unsuitable if the virtual fact is not xen" do
+    Facter.fact(:virtual).stubs(:value).returns "kvm"
+    expect(subject).to_not be_suitable
   end
 
-  describe "when running on openstack" do
-    before :each do
-      # Return false for ec2, true for eucalyptus
-      Facter::Util::EC2.stubs(:has_openstack_mac?).returns(true)
-      Facter::Util::EC2.stubs(:has_euca_mac?).returns(false)
-      Facter::Util::EC2.stubs(:has_ec2_arp?).returns(false)
+  it "is unsuitable if ec2 endpoint is not reachable" do
+    Facter.fact(:virtual).stubs(:value).returns "xen"
+    querier.stubs(:reachable?).returns false
+    expect(subject).to_not be_suitable
+  end
 
-      # Assume we can connect
-      Facter::Util::EC2.stubs(:can_connect?).returns(true)
+  describe "when the ec2 endpoint is reachable" do
+    before do
+      querier.stubs(:reachable?).returns true
     end
 
-    it "should create ec2_user_data fact" do
-      # No meta-data
-      Object.any_instance.expects(:open).\
-        with("#{api_prefix}/2008-02-01/meta-data/").\
-        at_least_once.returns(StringIO.new(""))
-
-      Facter::Util::EC2.stubs(:read_uri).
-        with("#{api_prefix}/latest/user-data/").
-        returns("test")
-
-      # Force a fact load
-      Facter.collection.internal_loader.load(:ec2)
-
-      Facter.fact(:ec2_userdata).value.should == ["test"]
+    it "is suitable if the virtual fact is xen" do
+      Facter.fact(:virtual).stubs(:value).returns "xen"
+      expect(subject).to be_suitable
     end
 
-    it "should return nil if open fails" do
-      Facter.stubs(:warn) # do not pollute test output
-      Facter.expects(:warn).with('Could not retrieve ec2 metadata: host unreachable')
-
-      Object.any_instance.expects(:open).
-        with("#{api_prefix}/2008-02-01/meta-data/").
-        at_least_once.raises(RuntimeError, 'host unreachable')
-
-      Facter::Util::EC2.stubs(:read_uri).
-        with("#{api_prefix}/latest/user-data/").
-        raises(RuntimeError, 'host unreachable')
-
-      # Force a fact load
-      Facter.collection.internal_loader.load(:ec2)
-
-      Facter.fact(:ec2_userdata).value.should be_nil
+    it "is suitable if the virtual fact is xenu" do
+      Facter.fact(:virtual).stubs(:value).returns "xenu"
+      expect(subject).to be_suitable
     end
+  end
 
+  it "resolves the value by fetching the rest endpoint" do
+    querier.expects(:fetch).returns "user data!"
+    expect(subject.value).to eq "user data!"
   end
+end
 
-  describe "when api connect test fails" do
-    before :each do
-      Facter.stubs(:warnonce)
-    end
+describe "flattened versions of ec2 facts" do
+  # These facts are tricky to test because they are dynamic facts, and they are
+  # generated from a fact that is defined in the same file. In order to pull
+  # this off we need to define the ec2_metadata fact ahead of time so that we
+  # can stub the value, and then manually load the correct files.
 
-    it "should not populate ec2_userdata" do
-      # Emulate ec2 for now as it matters little to this test
-      Facter::Util::EC2.stubs(:has_euca_mac?).returns(true)
-      Facter::Util::EC2.stubs(:has_ec2_arp?).never
-      Facter::Util::EC2.expects(:can_connect?).at_least_once.returns(false)
+  it "unpacks the ec2_metadata fact" do
+    Facter.define_fact(:ec2_metadata).stubs(:value).returns({"hello" => "world"})
+    Facter.collection.internal_loader.load(:ec2)
 
-      # The API should never be called at this point
-      Object.any_instance.expects(:open).
-        with("#{api_prefix}/2008-02-01/meta-data/").never
-      Object.any_instance.expects(:open).
-        with("#{api_prefix}/2008-02-01/user-data/").never
+    expect(Facter.value("ec2_hello")).to eq "world"
+  end
 
-      # Force a fact load
-      Facter.collection.internal_loader.load(:ec2)
+  it "does not set any flat ec2 facts if the ec2_metadata fact is nil" do
+    Facter.define_fact(:ec2_metadata).stubs(:value)
+    Facter.define_fact(:ec2_userdata).stubs(:value).returns(nil)
 
-      Facter.fact(:ec2_userdata).should == nil
-    end
+    Facter.collection.internal_loader.load(:ec2)
 
-    it "should rescue the exception" do
-      Facter::Util::EC2.expects(:open).with("#{api_prefix}:80/").raises(Timeout::Error)
+    all_facts = Facter.collection.to_hash
 
-      Facter::Util::EC2.should_not be_can_connect
-    end
+    ec2_facts = all_facts.keys.select { |k| k =~ /^ec2_/ }
+    expect(ec2_facts).to be_empty
   end
+
 end

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-puppet/facter.git



More information about the Pkg-puppet-devel mailing list