|
require 'facter' |
|
require 'time' |
|
require 'yaml' |
|
require 'json' |
|
|
|
if Facter.value("ec2_instance_id") != nil |
|
# Inspired by: http://puppetlabs.com/blog/facter-part-3-caching-and-ttl |
|
# |
|
# facts cache directory/file on puppet agent: |
|
facts_cache_dir='/etc/puppet/facts.d' |
|
ec2_cache_file=facts_cache_dir+'/ec2.yaml' |
|
# facts cache time to live in seconds (1 hour) |
|
facts_cache_ttl=3600 |
|
|
|
if File::exist?(ec2_cache_file) and YAML.load_file(ec2_cache_file) then |
|
ec2_cache=YAML.load_file(ec2_cache_file) |
|
ec2_data=ec2_cache |
|
cache_time=File.mtime(ec2_cache_file) |
|
else |
|
Facter.debug("Debug: no ec2.yaml local cache. Generating...") |
|
ec2_cache={} |
|
cache_time=Time.at(0) |
|
end |
|
|
|
# retrieve new ec2 data if no local cache, or fact exceeds TTL |
|
if ec2_cache.empty? || (Time.now - cache_time) > facts_cache_ttl |
|
begin |
|
require 'aws' |
|
instance_id = Facter.value("ec2_instance_id") |
|
region = Facter.value("ec2_placement_availability_zone")[0..-2] |
|
# IAM User 'ec2reader', read-only EC2 credentials, until we move to IAM Roles |
|
AWS.config( |
|
"access_key_id" => "XXXXXXXXX", |
|
"secret_access_key" => "XXXXXXXXXXXX", |
|
"region" => region |
|
) |
|
|
|
ec2 = AWS.ec2 |
|
ec2_data = ec2.instances[instance_id].tags.to_h |
|
raise "No EC2 tags found for #{instance_id}" if ec2_data.empty? |
|
# Prepend "ec2_tag_" to each tag name |
|
ec2_data = Hash[ec2_data.map { |k, v| ["ec2_tag_#{k.downcase}", v] }] |
|
|
|
begin |
|
Dir.mkdir(facts_cache_dir) if !File::exists?(facts_cache_dir) |
|
File.open(ec2_cache_file, 'w') do |out| |
|
YAML.dump(ec2_data, out) |
|
end |
|
rescue |
|
Facter.warn("Err: failed to write ec2.yaml cache file.") |
|
end |
|
rescue => e |
|
Facter.warn("Err: failed to obtain ec2 data from api. #{e}") |
|
ec2_data=ec2_cache |
|
end |
|
end |
|
|
|
# add facts to Facter |
|
ec2_data.each_pair do |name, value| |
|
# This allows us to push arrays up as tags, since tags only support strings |
|
# Could just use eval here...security? |
|
# |
|
# Does it look like an array, e.g "['foo', 'bar']" |
|
if /\[(?:[^,]+,)*[^,]+\]/ =~ value |
|
value.gsub!("'", '"') |
|
value = JSON.parse(value) |
|
end |
|
Facter.add(name) { setcode { value } } |
|
end |
|
end |