Skip to content

Instantly share code, notes, and snippets.

@butlern
Created June 28, 2016 14:19
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save butlern/9addb732e2f8c78179a88dea711c80b2 to your computer and use it in GitHub Desktop.
Save butlern/9addb732e2f8c78179a88dea711c80b2 to your computer and use it in GitHub Desktop.
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment