class Chef::Provider::AwsRoute53HostedZone
Constants
- CREATE
- DELETE
- RRS_COMMENT
- UPDATE
Attributes
record_set_list[RW]
Public Instance Methods
create_aws_object()
click to toggle source
# File lib/chef/resource/aws_route53_hosted_zone.rb, line 107 def create_aws_object converge_by "create new Route 53 zone #{new_resource}" do # AWS stores some attributes off to the side here. hosted_zone_config = make_hosted_zone_config(new_resource) values = { name: new_resource.name, hosted_zone_config: hosted_zone_config, caller_reference: "chef-provisioning-aws-#{SecureRandom.uuid.upcase}", # required, unique each call } # this will validate the record_set resources prior to making any AWS calls. record_set_resources = get_record_sets_from_resource(new_resource) zone = new_resource.driver.route53_client.create_hosted_zone(values).hosted_zone new_resource.aws_route53_zone_id(zone.id) if record_set_resources populate_zone_info(record_set_resources, zone) change_list = record_set_resources.map { |rs| rs.to_aws_change_struct(UPDATE) } new_resource.driver.route53_client.change_resource_record_sets(hosted_zone_id: new_resource.aws_route53_zone_id, change_batch: { comment: RRS_COMMENT, changes: change_list }) end zone end end
destroy_aws_object(hosted_zone)
click to toggle source
# File lib/chef/resource/aws_route53_hosted_zone.rb, line 198 def destroy_aws_object(hosted_zone) converge_by "delete Route53 zone #{new_resource}" do Chef::Log.info("Deleting all non-SOA/NS records for #{hosted_zone.name}") rr_changes = hosted_zone.resource_record_sets.reject do |aws_rr| %w{SOA NS}.include?(aws_rr.type) end.map do |aws_rr| { action: DELETE, resource_record_set: aws_rr.to_change_struct } end unless rr_changes.empty? aws_struct = { hosted_zone_id: hosted_zone.id, change_batch: { comment: "Purging RRs prior to deleting resource", changes: rr_changes } } new_resource.driver.route53_client.change_resource_record_sets(aws_struct) end result = new_resource.driver.route53_client.delete_hosted_zone(id: hosted_zone.id) end end
get_record_sets_from_resource(new_resource)
click to toggle source
`record_sets` is defined on the `aws_route53_hosted_zone` resource as a block attribute, so compile that, validate it, and return a list of AWSRoute53RecordSet resource objects.
# File lib/chef/resource/aws_route53_hosted_zone.rb, line 229 def get_record_sets_from_resource(new_resource) return nil unless new_resource.record_sets instance_eval(&new_resource.record_sets) # because we're in the provider, the RecordSet resources happen in their own mini Chef run, and they're the # only things in the resource_collection. record_set_resources = run_context.resource_collection.to_a return nil unless record_set_resources record_set_resources.each do |rs| rs.aws_route53_hosted_zone(new_resource) rs.aws_route53_zone_name(new_resource.name) if new_resource.defaults new_resource.class::DEFAULTABLE_ATTRS.each do |att| # check if the RecordSet has its own value, without triggering validation. in Chef >= 12.5, there is # #property_is_set?. if rs.instance_variable_get("@#{att}").nil? && !new_resource.defaults[att].nil? rs.send(att, new_resource.defaults[att]) end end end rs.validate! end Chef::Resource::AwsRoute53RecordSet.verify_unique!(record_set_resources) record_set_resources end
make_hosted_zone_config(new_resource)
click to toggle source
# File lib/chef/resource/aws_route53_hosted_zone.rb, line 90 def make_hosted_zone_config(new_resource) config = {} # add :private_zone here once VPC validation is enabled. [:comment].each do |attr| value = new_resource.send(attr) config[attr] = value if value end config end
populate_zone_info(record_set_resources, hosted_zone)
click to toggle source
this happens at a slightly different time in the lifecycle from get_record_sets_from_resource
.
# File lib/chef/resource/aws_route53_hosted_zone.rb, line 101 def populate_zone_info(record_set_resources, hosted_zone) record_set_resources.each do |rs| rs.aws_route53_zone_id(hosted_zone.id) end end
update_aws_object(hosted_zone)
click to toggle source
# File lib/chef/resource/aws_route53_hosted_zone.rb, line 139 def update_aws_object(hosted_zone) new_resource.aws_route53_zone_id(hosted_zone.id) # this will validate the record_set resources prior to making any AWS calls. record_set_resources = get_record_sets_from_resource(new_resource) if new_resource.comment != hosted_zone.config.comment new_resource.driver.route53_client.update_hosted_zone_comment(id: hosted_zone.id, comment: new_resource.comment) end if record_set_resources populate_zone_info(record_set_resources, hosted_zone) aws_record_sets = hosted_zone.resource_record_sets change_list = [] # TODO: the SOA and NS records have identical :name properties (the zone name), so one of them will # be overwritten in the `keyed_aws_objects` hash. mostly we're declining to operate on SOA and NS, # so it probably doesn't matter, but bears investigating. # we already checked for duplicate Chef RR resources in #get_record_sets_from_resource. keyed_chef_resources = record_set_resources.each_with_object({}) { |rs, coll| (coll[rs.aws_key] ||= []) << rs; } keyed_aws_objects = aws_record_sets.each_with_object({}) { |rs, coll| coll[rs.aws_key] = rs; } # because DNS is important, we're going to err on the side of caution and only operate on records for # which we have a Chef resource. "total management" might be a nice resource option to have. keyed_chef_resources.each do |key, chef_resource_ary| chef_resource_ary.each do |chef_resource| # RR already exists... if keyed_aws_objects.key?(key) # ... do we want to delete it? if chef_resource.action.first == :destroy change_list << chef_resource.to_aws_change_struct(DELETE) # ... update it, then, only if the fields differ. elsif chef_resource.to_aws_struct != keyed_aws_objects[key] change_list << chef_resource.to_aws_change_struct(UPDATE) end # otherwise, RR does not already exist... else # using UPSERT instead of CREATE; there are merits to both. change_list << chef_resource.to_aws_change_struct(UPSERT) end end end Chef::Log.debug("RecordSet changes: #{change_list.inspect}") if !change_list.empty? new_resource.driver.route53_client.change_resource_record_sets(hosted_zone_id: new_resource.aws_route53_zone_id, change_batch: { comment: RRS_COMMENT, changes: change_list }) else Chef::Log.info("All aws_route53_record_set resources up to date (nothing to do).") end end end