module CustomResource::Route53::MixIns::Actions
Constants
- WAIT_PERIOD_INSYNC
Public Instance Methods
action(verb,section,proc)
click to toggle source
# File lib/customresource/route53/mixins/actions.rb, line 13 def action(verb,section,proc) prepare # data = {} restyp = section.gsub(/s$/,'').downcase method = "#{verb}_#{restyp}" resource = @event['ResourceProperties'] @logger.debug "#{method} #{resource.ai}" # Convert the 'String' keys to :string symbols params = properties_to_params(resource.dup) # Weed out the invalid properties invalid_keys = validate_params(section,params) if invalid_keys.size > 0 @logger.warn "Invalid keys in #{params[:name] || params.ai}:\n#{invalid_keys.ai}" end params = delete_invalid_keys(params,invalid_keys) # Restore these exceptions to the rule from the resource 'String' set e.g. :codec_options => { 'String': Value, } params = restore_exception_params(section,params,resource) params = infer_params(section,Mash.new(params)) @logger.debug params.ai data = proc.call(params, restyp, method, resource) @logger.debug data respond('SUCCESS', data) 0 end
change_resource_record_sets(zone, changes)
click to toggle source
# File lib/customresource/route53/mixins/actions.rb, line 305 def change_resource_record_sets(zone, changes) while true begin resp = @awssdk.change_resource_record_sets( hosted_zone_id: zone[:id], change_batch: { changes: changes } ) wait_for_insync(resp) return resp rescue Aws::Route53::Errors::PriorRequestNotComplete sleep WAIT_PERIOD_INSYNC end end end
create(section)
click to toggle source
# File lib/customresource/route53/mixins/actions.rb, line 41 def create(section) case section when /PrivateHostedZones/ action('create', section, lambda do |params, restyp, method, resource| begin require 'date' data = nil set = list_hosted_zones(params) if set.size == 0 @logger.info "create #{params[:name]}" resp = @awssdk.create_hosted_zone( name: params[:hostedzone], vpc: { vpc_region: @region, vpc_id: params[:vpcid] }, caller_reference: "#{params[:name]}::#{DateTime::now.strftime('%Y%m%dT%H%M%S%z')}", hosted_zone_config: { comment: params[:comment], # private_zone: true, } ) wait_for_insync(resp) zone = get_hosted_zone(params) else zone = set[0] # get_hosted_zone(params) @logger.info "Existing hosted_zone #{zone[:id]}::#{zone[:name]}" resp = @awssdk.update_hosted_zone_comment( id: zone[:id], comment: params[:comment] ) unless resp and resp[:hosted_zone] abort! "Failed to set comment on zone #{zone[:id]}::#{zone[:name]}" end zone = Mash.new(resp[:hosted_zone].to_hash) end if params[:ttl] rrs = list_resource_record_sets(zone) existing = rrs.select{ |rr| %w(NS SOA).include?(rr[:type]) } changes = [] if existing.size > 0 existing.each do |rr| rrc = rr.dup rrc[:ttl] = params[:ttl] changes << { action: 'UPSERT', resource_record_set: rrc } end end if changes.size > 0 resp = change_resource_record_sets(zone, changes) end end data = get_item_data(zone, section, params) data rescue Exception => e abort! "#{restyp}/#{params[:name]}: #{e.message}" end end ) when /ReverseDNSEntries/ action('create', section, lambda do |params, restyp, method, resource| begin data = nil zone = get_hosted_zone(params) @logger.info "Found hosted_zone #{zone[:id]}::#{zone[:name]}" rrs = list_resource_record_sets(zone) existing = rrs.select{ |rr| rr[:name] == params[:name] } changes = [] if existing.size > 0 existing.each do |rr| changes << { action: 'UPSERT', resource_record_set: { name: rr[:name], type: rr[:type], ttl: params[:ttl], resource_records: params[:resourcerecords] || rr[:resource_records].map{ |r| { value: params[:value] } } } } end else changes << { action: 'CREATE', resource_record_set: { name: params[:name], type: params[:type], ttl: params[:ttl], resource_records: params[:resourcerecords] || [ { value: params[:value] } ] } } end if changes.size > 0 resp = change_resource_record_sets(zone, changes) end data = get_item_data(params, section, params) data rescue SystemExit => e raise e rescue Exception => e abort! "#{section}/#{params[:name]}: #{e.message}" end end ) else abort! "Unsupported section #{section}" end end
delete(section)
click to toggle source
# File lib/customresource/route53/mixins/actions.rb, line 154 def delete(section) case section when /PrivateHostedZones/ action('delete', section, lambda do |params, restyp, method, resource| begin data = nil set = list_hosted_zones(params) unless set.size == 0 zone = set[0] @logger.info "Delete existing hosted_zone #{zone[:id]}::#{zone[:name]}" # if zone[:resource_record_set_count] > 2 # rrs = list_resource_record_sets(zone) # changes = [] # rrs.each do |rr| # changes << { # action: 'DELETE', # resource_record_set: { # name: rr[:name], # type: rr[:type], # ttl: rr[:ttl], # resource_records: rr[:resource_records].map{ |r| { value: r[:value] } } # } # } unless %w(NS SOA).include?(rr[:type]) # end # if changes.size > 0 # change_resource_record_sets(zone, changes) # end # end @awssdk.delete_hosted_zone( { id: zone[:id] }) data = get_item_data(Mash.new({ id: zone[:id] }.merge(params)), section, params) end data rescue Exception => e abort! "#{restyp}/#{params[:name]}: #{e.message}" end end ) when /ReverseDNSEntries/ action('delete', section, lambda do |params, restyp, method, resource| begin data = nil zone = get_hosted_zone(params) @logger.info "Found hosted_zone #{zone[:id]}::#{zone[:name]}" changes = [] rrs = list_resource_record_sets(zone) if params[:resourcerecords] rrs.select! do |rr| rr[:name] == params[:name] end changes << { action: 'DELETE', resource_record_set: { name: params[:name], type: params[:type], ttl: params[:ttl], resource_records: params[:resourcerecords] } } if rrs.size > 0 else rrs.each do |rr| rrd = rr.dup changes << { action: 'DELETE', resource_record_set: rrd } if rr[:name] == params[:name] end end if changes.size > 0 # abort! "Cannot delete #{params[:name]} from #{zone[:id]}::#{zone[:name]}" change_resource_record_sets(zone,changes) end data = get_item_data(params, section, params) data rescue NoSuchHostedZone => e # [2014-12-15 Christo] TODO: May need to rethink considering the MIA ZoneId a successful deletion. The motivator for this is the fact that a stack will be stuck of someone manually deletes/recreates the zone ... :O respond('SUCCESS', nil, e.message) rescue SystemExit => e raise e rescue Exception => e abort! "#{section}/#{params[:name]}: #{e.message}" end end ) else abort! "Unsupported section #{section}" end end
get_hosted_zone(params)
click to toggle source
# File lib/customresource/route53/mixins/actions.rb, line 246 def get_hosted_zone(params) zone = nil begin if params[:hostedzoneid] resp = @awssdk.get_hosted_zone(id: params[:hostedzoneid]) if resp zone = Mash.new(resp.hosted_zone.to_hash) end else set = list_hosted_zones(params) if set.size == 0 raise NoSuchHostedZone.new("Cannot find hosted zone #{params[:hostedzone]}") else zone = set[0] end end zone rescue Aws::Route53::Errors::NoSuchHostedZone => e raise NoSuchHostedZone.new(e.message) end end
list_hosted_zones(params)
click to toggle source
# File lib/customresource/route53/mixins/actions.rb, line 288 def list_hosted_zones(params) set = [] resp = @awssdk.list_hosted_zones if resp resp.hosted_zones.map { |item| set << item.to_h } while resp[:marker] resp = @awssdk.list_hosted_zones(marker: resp[:marker]) if resp resp.hosted_zones.map { |item| set << Mash.new(item.to_h) } end end # Let's see if we have hostedzones which match this :name set.select!{ |item| item[:name].match(/^#{params[:hostedzone]}$/) and item[:config][:private_zone] == true } end set end
list_resource_record_sets(zone)
click to toggle source
# File lib/customresource/route53/mixins/actions.rb, line 322 def list_resource_record_sets(zone) rrs = [] resp = @awssdk.list_resource_record_sets(hosted_zone_id: zone[:id]) while resp resp.resource_record_sets.map { |rr| rrs << Mash.new(rr.to_hash) } resp = if resp[:is_truncated] @awssdk.list_resource_record_sets(hosted_zone_id: zone[:id], marker: resp[:marker]) else nil end end rrs end
update(section)
click to toggle source
# File lib/customresource/route53/mixins/actions.rb, line 150 def update(section) create section end
wait_for_insync(resp)
click to toggle source
# File lib/customresource/route53/mixins/actions.rb, line 268 def wait_for_insync(resp) unless resp and resp[:change_info] abort! 'Bad response to change_resource_record_sets' end change_info = Mash.new(resp[:change_info].to_hash) while resp resp = @awssdk.get_change(id: change_info[:id]) unless resp and resp[:change_info] abort! "Bad response to get_change[id: #{change_info[:id]}]" end change_info = Mash.new(resp[:change_info].to_hash) if change_info[:status] != 'INSYNC' @logger.info "Change #{change_info[:id]} is #{change_info[:status]} ... Waiting #{WAIT_PERIOD_INSYNC}s" sleep WAIT_PERIOD_INSYNC else resp = nil end end end