class Hiera::Backend::Sf_hiera_aws_backend
Public Class Methods
new()
click to toggle source
# File lib/hiera/backend/sf_hiera_aws_backend.rb, line 46 def initialize require 'aws-sdk-resources' read_link_local_data unless @instance_identity.nil? Aws.config.update(region: @instance_identity['region']) end Hiera.debug('Hiera AWS SDK backend started') end
Public Instance Methods
aws_config()
click to toggle source
# File lib/hiera/backend/sf_hiera_aws_backend.rb, line 113 def aws_config require 'yaml' config_file = config_file_name if File.exist?(config_file) config = YAML.load_file(config_file) else Hiera.warn("No config file #{config_file} found") config = {} end # Merge configs from the config directory too config_directory = config_directory_name if File.directory?(config_directory) Dir.entries(config_directory).sort.each do |p| next if p == '.' or p == '..' to_merge = YAML.load_file( File.join( config_directory, p ) ) config.merge! to_merge end end config end
config_directory_name()
click to toggle source
# File lib/hiera/backend/sf_hiera_aws_backend.rb, line 98 def config_directory_name default_config_path = '/etc/puppet/sf_hiera_aws.d' if !Config[:aws_sdk].nil? config_dir = Config[:aws_sdk][:config_directory] || default_config_path else config_dir = default_config_path end return config_dir end
config_file_name()
click to toggle source
# File lib/hiera/backend/sf_hiera_aws_backend.rb, line 84 def config_file_name default_config_path = '/etc/puppet/sf_hiera_aws.yaml' if !Config[:aws_sdk].nil? config_file = Config[:aws_sdk][:config_file] || default_config_path else config_file = default_config_path end return config_file end
lookup(key, scope, _order_override, _resolution_type)
click to toggle source
# File lib/hiera/backend/sf_hiera_aws_backend.rb, line 57 def lookup(key, scope, _order_override, _resolution_type) config = recursive_interpolate_config(aws_config, scope) Hiera.debug("Looking up '#{key} in AWS SDK backend") return nil unless config.key? key Hiera.debug("Config: #{config[key].inspect}") type = config[key]['type'] if methods.include? "type_#{type}".to_sym begin answer = send("type_#{type}".to_sym, config[key]) Hiera.debug(answer) return answer rescue Aws::Errors::MissingRegionError, Aws::Errors::MissingCredentialsError Hiera.warn('No IAM role or ENV based AWS config - skipping') return nil end end Hiera.debug("Type of AWS SDK lookup '#{type}' invalid") nil end
recursive_interpolate_config(h, scope)
click to toggle source
# File lib/hiera/backend/sf_hiera_aws_backend.rb, line 141 def recursive_interpolate_config(h, scope) case h when Hash Hash[ h.map do |k, v| [Backend.parse_answer(k, scope), recursive_interpolate_config(v, scope)] end ] when Enumerable h.map { |v| recursive_interpolate_config(v, scope) } when String Backend.parse_answer(h, scope) else h end end
type_autoscaling_group(options)
click to toggle source
# File lib/hiera/backend/sf_hiera_aws_backend.rb, line 394 def type_autoscaling_group(options) autoscaling = get_autoscaling_client if options.key? 'auto_scaling_group_names' asgs = autoscaling.describe_auto_scaling_groups( auto_scaling_group_names: options['auto_scaling_group_names'], ).auto_scaling_groups else asgs = autoscaling.describe_auto_scaling_groups.auto_scaling_groups end if !options.key? 'return' return asgs.collect do |asg| { 'auto_scaling_group_name' => asg.auto_scaling_group_name, 'launch_configuration_name' => asg.launch_configuration_name, 'load_balancer_names' => asg.load_balancer_names, 'instances' => asg.instances.collect do | instance | { 'instance_id' => instance.instance_id, 'availability_zone' => instance.availability_zone, 'lifecycle_state' => instance.lifecycle_state, 'health_status' => instance.health_status, 'launch_configuration_name' => instance.launch_configuration_name, 'protected_from_scale_in' => instance.protected_from_scale_in } end } end else unless options.key? 'auto_scaling_group_names' Hiera.warn('Requested to return hash of instances for auto scaling group, but no auto_scaling_group_names specified') return nil end end if options['return'] == :instance_details_inservice_ip instances = [] asgs = asgs.collect do |asg| { 'instances' => asg.instances.select{|i| i.lifecycle_state == 'InService'}.map { |instance| { 'instance_id' => instance.instance_id } } } end asgs.each do |asg| instances += asg['instances'] end ec2_options = { 'filters' => [{ 'name' => 'instance-id', 'values' => instances.map { |i| i['instance_id'] } }], 'return' => [ 'private_ip_address'] } return type_ec2_instance(ec2_options) else asgs.collect do |a| if options['return'].is_a?(Array) # If the 'return' option is a list, we treat these # as a list of desired hash keys, and return a hash # containing only those keys from the API call Hash[options['return'].map do |f| [f.to_s, a.key?(f) ? a[f] : nil] end] elsif options['return'].is_a?(Symbol) # If the 'return' option is a symbol, we treat that # as the one hash key we care about, and return a list # of that. a.key?(options['return']) ? a[options['return']] : nil end end end end
type_ec2_instance(options)
click to toggle source
# File lib/hiera/backend/sf_hiera_aws_backend.rb, line 158 def type_ec2_instance(options) options = { 'return' => [ :instance_id, :private_ip_address, :private_dns_name, ] }.merge(options) ec2 = get_ec2_client instances = [] if options.key? 'filters' ec2.describe_instances(filters: options['filters']).reservations.each do |r| r.instances.each do |i| instances << i end end else ec2.describe_instances().reservations.each do |r| r.instances.each do |i| instances << i end end end instances.collect do |i| if options['return'].is_a?(Array) # If the 'return' option is a list, we treat these # as a list of desired hash keys, and return a hash # containing only those keys from the API call Hash[options['return'].map do |f| [f.to_s, i.key?(f) ? i[f] : nil] end] elsif options['return'].is_a?(Symbol) # If the 'return' option is a symbol, we treat that # as the one hash key we care about, and return a list # of that. i.key?(options['return']) ? i[options['return']] : nil end end end
type_elasticache_cache_cluster(options)
click to toggle source
# File lib/hiera/backend/sf_hiera_aws_backend.rb, line 257 def type_elasticache_cache_cluster(options) elasticache = get_elasticache_client if options.key? 'cache_cluster_id' clusters = elasticache.describe_cache_clusters( cache_cluster_id: options['cache_cluster_id'], show_cache_node_info: true, ).cache_clusters else clusters = elasticache.describe_cache_clusters( show_cache_node_info: true ).cache_clusters end if !options.key? 'return' return clusters.collect do |i| { 'cache_cluster_id' => i.cache_cluster_id, 'cache_nodes' => i.cache_nodes.collect do |n| { 'cache_node_id' => n.cache_node_id, 'endpoint_address' => n.endpoint.address, 'endpoint_port' => n.endpoint.port, } end } end end if options['return'] == :hostname nodes = [] clusters.each do |c| c.cache_nodes.each do |n| nodes.push(n.endpoint.address) end end return nodes elsif options['return'] == :hostname_and_port nodes = [] clusters.each do |c| c.cache_nodes.each do |n| nodes.push( [ n.endpoint.address, n.endpoint.port ].join(':') ) end end return nodes end end
type_elasticache_replication_group(options)
click to toggle source
# File lib/hiera/backend/sf_hiera_aws_backend.rb, line 316 def type_elasticache_replication_group(options) elasticache = get_elasticache_client if options.key? 'replication_group_id' replgroups = elasticache.describe_replication_groups( replication_group_id: options['replication_group_id'], ).replication_groups else replgroups = elasticache.describe_replication_groups.replication_groups end if !options.key? 'return' return replgroups.collect do |rg| { 'replication_group_id' => rg.replication_group_id, 'primary_endpoint_address' => rg.node_groups[0].primary_endpoint.address, 'primary_endpoint_port' => rg.node_groups[0].primary_endpoint.port, 'node_group_members' => rg.node_groups[0].node_group_members.collect do |ngm| { 'cache_node_id' => ngm.cache_node_id, 'cache_cluster_id' => ngm.cache_cluster_id, 'read_endpoint_address' => ngm.read_endpoint.address, 'read_endpoint_port' => ngm.read_endpoint.port, 'current_role' => ngm.current_role, } end } end end if options['return'] == :read_endpoints if options.key? 'replication_group_id' return replgroups[0].node_groups[0].node_group_members.map { |ngm| ngm.read_endpoint.address } else Hiera.warn('Requested to return array of read endpoints for replication group, but no replication_group_id specified') return nil end end if options['return'] == :read_endpoints_and_ports if options.key? 'replication_group_id' return replgroups[0].node_groups[0].node_group_members.map { |ngm| "#{ngm.read_endpoint.address}:#{ngm.read_endpoint.port}" } else Hiera.warn('Requested to return array of read endpoints and ports for replication group, but no replication_group_id specified') return nil end end if options['return'] == :primary_endpoint primary_endpoints = [] replgroups.each do |rg| primary_endpoints.push(rg.node_groups[0].primary_endpoint.address) end return primary_endpoints elsif options['return'] == :primary_endpoint_and_port primary_endpoints = [] replgroups.each do |rg| primary_endpoints.push( [ rg.node_groups[0].primary_endpoint.address, rg.node_groups[0].primary_endpoint.port ].join(':') ) end return primary_endpoints end end
type_rds_db_instance(options)
click to toggle source
# File lib/hiera/backend/sf_hiera_aws_backend.rb, line 212 def type_rds_db_instance(options) rds = get_rds_client if options.key? 'db_instance_identifier' instances = rds.describe_db_instances( db_instance_identifier: options['db_instance_identifier'] ).db_instances else instances = rds.describe_db_instances.db_instances end if !options.key? 'return' return instances.collect do |i| { 'db_instance_identifier' => i.db_instance_identifier, 'endpoint_address' => i.endpoint.address, 'endpoint_port' => i.endpoint.port, } end end if options['return'] == :hostname return instances.first.endpoint.address elsif options['return'] == :hostname_and_port return [ instances.first.endpoint.address, instances.first.endpoint.port, ].join(':') else Hiera.warn("No return handler for #{options['return']} in rds_db_instance") return nil end end
Private Instance Methods
get_autoscaling_client()
click to toggle source
# File lib/hiera/backend/sf_hiera_aws_backend.rb, line 40 def get_autoscaling_client Aws::AutoScaling::Client.new end
get_ec2_client()
click to toggle source
# File lib/hiera/backend/sf_hiera_aws_backend.rb, line 32 def get_ec2_client Aws::EC2::Client.new end
get_elasticache_client()
click to toggle source
# File lib/hiera/backend/sf_hiera_aws_backend.rb, line 36 def get_elasticache_client Aws::ElastiCache::Client.new end
get_rds_client()
click to toggle source
Wrapped these in getters for dependency injection purposes
# File lib/hiera/backend/sf_hiera_aws_backend.rb, line 28 def get_rds_client Aws::RDS::Client.new end
read_link_local_data()
click to toggle source
# File lib/hiera/backend/sf_hiera_aws_backend.rb, line 8 def read_link_local_data require 'net/http' require 'json' begin http = Net::HTTP.new('169.254.169.254', 80) http.open_timeout = 1 http.read_timeout = 1 request = http.request(Net::HTTP::Get.new('/latest/dynamic/instance-identity/document')).body @instance_identity = JSON.parse(request) rescue Errno::EHOSTUNREACH, Net::OpenTimeout, Timeout::Error Hiera.warn('No link-local endpoint - can\'t calculate region') rescue JSON::ParserError Hiera.warn("HTTP response from link-local endpoint returned invalid JSON: #{request}") rescue => e Hiera.warn("Exception while finding instance identity: #{e.inspect}") end end