customresource-route53 0.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.bundle/config +2 -0
- data/.rakeTasks +7 -0
- data/ChangeLog.md +4 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +78 -0
- data/LICENSE +201 -0
- data/LICENSE.txt +203 -0
- data/README.md +2 -0
- data/Rakefile +30 -0
- data/bin/cfn-customresource-route53 +16 -0
- data/customresource-route53.gemspec +34 -0
- data/features/.gitkeep +0 -0
- data/features/customresource-route53.feature +1 -0
- data/features/step_definitions/.gitkeep +0 -0
- data/features/step_definitions/customresource-route53_steps.rb +1 -0
- data/lib/customresource/route53.rb +2 -0
- data/lib/customresource/route53/cli.rb +59 -0
- data/lib/customresource/route53/mixins/actions.rb +339 -0
- data/lib/customresource/route53/mixins/cli.rb +158 -0
- data/lib/customresource/route53/version.rb +6 -0
- data/tests/route53.privatehostedzone.create.log +21 -0
- data/tests/route53.privatehostedzone.delete.log +23 -0
- data/tests/route53.privatehostedzone.update.log +22 -0
- data/tests/route53.reversednsentry.create.id.log +8 -0
- data/tests/route53.reversednsentry.create.name.log +9 -0
- data/tests/route53.reversednsentry.delete.id.log +16 -0
- data/tests/route53.reversednsentry.delete.name.log +17 -0
- data/tests/route53.reversednsentry.delete.name.rr.log +16 -0
- data/tests/route53.reversednsentry.update.name.log +9 -0
- data/tests/update.sh +17 -0
- metadata +248 -0
    
        data/README.md
    ADDED
    
    
    
        data/Rakefile
    ADDED
    
    | @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'rubygems'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            begin
         | 
| 6 | 
            +
              require 'bundler'
         | 
| 7 | 
            +
            rescue LoadError => e
         | 
| 8 | 
            +
              warn e.message
         | 
| 9 | 
            +
              warn "Run `gem install bundler` to install Bundler."
         | 
| 10 | 
            +
              exit -1
         | 
| 11 | 
            +
            end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
            begin
         | 
| 14 | 
            +
              Bundler.setup(:development)
         | 
| 15 | 
            +
            rescue Bundler::BundlerError => e
         | 
| 16 | 
            +
              warn e.message
         | 
| 17 | 
            +
              warn "Run `bundle install` to install missing gems."
         | 
| 18 | 
            +
              exit e.status_code
         | 
| 19 | 
            +
            end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
            require 'rake'
         | 
| 22 | 
            +
             | 
| 23 | 
            +
            require 'rubygems/tasks'
         | 
| 24 | 
            +
            Gem::Tasks.new
         | 
| 25 | 
            +
             | 
| 26 | 
            +
            require 'cucumber/rake/task'
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            Cucumber::Rake::Task.new do |t|
         | 
| 29 | 
            +
              t.cucumber_opts = %w[--format pretty]
         | 
| 30 | 
            +
            end
         | 
| @@ -0,0 +1,16 @@ | |
| 1 | 
            +
            #!/usr/bin/env ruby
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            # Adjust lib path
         | 
| 4 | 
            +
            _lib=File.expand_path(File.dirname(__FILE__) + '/../lib')
         | 
| 5 | 
            +
            $:.unshift(_lib) unless $:.include?(_lib)
         | 
| 6 | 
            +
            require 'customresource/route53/cli'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            # =====================================================================================================================
         | 
| 9 | 
            +
            rc = CustomResource::Route53::Cli.start(ARGV)
         | 
| 10 | 
            +
            if rc.is_a?(Fixnum)
         | 
| 11 | 
            +
              exit rc
         | 
| 12 | 
            +
            else
         | 
| 13 | 
            +
              puts rc.ai
         | 
| 14 | 
            +
              exit 0
         | 
| 15 | 
            +
            end
         | 
| 16 | 
            +
             | 
| @@ -0,0 +1,34 @@ | |
| 1 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require File.expand_path('../lib/customresource/route53/version', __FILE__)
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            Gem::Specification.new do |gem|
         | 
| 6 | 
            +
              gem.name          = 'customresource-route53'
         | 
| 7 | 
            +
              gem.version       = CustomResource::Route53::VERSION
         | 
| 8 | 
            +
              gem.summary       = %q{An action command for aws-cfn-resource-bridge to implement CloudFormation custom resources}
         | 
| 9 | 
            +
              gem.description   = %q{An action command for aws-cfn-resource-bridge to implement CloudFormation custom resources}
         | 
| 10 | 
            +
              gem.license       = 'Apachev2'
         | 
| 11 | 
            +
              gem.authors       = ['Christo De Lange']
         | 
| 12 | 
            +
              gem.email         = 'rubygems@dldinternet.com'
         | 
| 13 | 
            +
              gem.homepage      = 'https://rubygems.org/gems/customresource-route53'
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              gem.files         = `git ls-files`.split($/)
         | 
| 16 | 
            +
              gem.executables   = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
         | 
| 17 | 
            +
              gem.test_files    = gem.files.grep(%r{^(test|spec|features)/})
         | 
| 18 | 
            +
              gem.require_paths = ['lib']
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              gem.add_development_dependency  'bundler', '~> 1.0'
         | 
| 21 | 
            +
              gem.add_development_dependency  'rake', '~> 10'
         | 
| 22 | 
            +
              gem.add_development_dependency  'rubygems-tasks', '~> 0.2'
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              gem.add_dependency              'thor', '~> 0.19'
         | 
| 25 | 
            +
              gem.add_dependency              'awesome_print', '~> 1.2'
         | 
| 26 | 
            +
              gem.add_dependency              'colorize', '~> 0.7.3'
         | 
| 27 | 
            +
              gem.add_dependency              'aws-sdk-core', '~> 2.0'
         | 
| 28 | 
            +
              gem.add_dependency              'inifile', '~> 3'
         | 
| 29 | 
            +
              gem.add_dependency              'dldinternet-mixlib-thor-nocommands', '~> 0.2'
         | 
| 30 | 
            +
              gem.add_dependency              'dldinternet-mixlib-logging', '~> 0.4'
         | 
| 31 | 
            +
              gem.add_dependency              'ipaddress', '~> 0.8'
         | 
| 32 | 
            +
              gem.add_dependency              'customresource-base', '~> 0'
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            end
         | 
    
        data/features/.gitkeep
    ADDED
    
    | 
            File without changes
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            Feature: Blah blah blah
         | 
| 
            File without changes
         | 
| @@ -0,0 +1 @@ | |
| 1 | 
            +
            @wip
         | 
| @@ -0,0 +1,59 @@ | |
| 1 | 
            +
            require 'thor'
         | 
| 2 | 
            +
            require 'awesome_print'
         | 
| 3 | 
            +
            require 'colorize'
         | 
| 4 | 
            +
            require 'aws-sdk-core'
         | 
| 5 | 
            +
            require 'yaml'
         | 
| 6 | 
            +
            require 'customresource/route53/version'
         | 
| 7 | 
            +
            require 'aws/ec2/instance_data'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            module CustomResource
         | 
| 10 | 
            +
              module Route53
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                class Cli < Thor
         | 
| 13 | 
            +
                  class_option :verbose,      :type => :boolean
         | 
| 14 | 
            +
                  class_option :debug,        :type => :boolean
         | 
| 15 | 
            +
                  class_option :trace,        :type => :boolean
         | 
| 16 | 
            +
                  class_option :log_level,    :type => :string, :banner => 'Log level ([:trace, :debug, :info, :step, :warn, :error, :fatal, :todo])'
         | 
| 17 | 
            +
                  class_option :log_file,     :type => :string
         | 
| 18 | 
            +
                  class_option :inifile,      :type => :string
         | 
| 19 | 
            +
                  class_option :input,        :type => :string
         | 
| 20 | 
            +
                  class_option :ip_address,   :type => :string
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  no_commands do
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    require 'dldinternet/mixlib/thor/no_commands'
         | 
| 25 | 
            +
                    include DLDInternet::MixLib::Thor::No_Commands
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    require 'customresource/route53/mixins/cli'
         | 
| 28 | 
            +
                    include CustomResource::Route53::MixIns::Cli
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                    require 'customresource/route53/mixins/actions'
         | 
| 31 | 
            +
                    include CustomResource::Route53::MixIns::Actions
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                  end # no_commands
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  def initialize(args = [], local_options = {}, config = {})
         | 
| 36 | 
            +
                    super(args,local_options,config)
         | 
| 37 | 
            +
                    @log_level = :step
         | 
| 38 | 
            +
                  end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                  desc 'version', 'display current version'
         | 
| 41 | 
            +
                  def version()
         | 
| 42 | 
            +
                    puts ::CustomResource::Route53::VERSION
         | 
| 43 | 
            +
                    exit 0
         | 
| 44 | 
            +
                  end
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                  desc 'privatehostedzone', 'CRUD for privatehostedzones'
         | 
| 47 | 
            +
                  def privatehostedzone()
         | 
| 48 | 
            +
                    process('PrivateHostedZones')
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                  desc 'reversednsentry', 'CRUD for reversednsentries'
         | 
| 52 | 
            +
                  def reversednsentry()
         | 
| 53 | 
            +
                    process('ReverseDNSEntries')
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
             | 
| 56 | 
            +
                end
         | 
| 57 | 
            +
              end
         | 
| 58 | 
            +
            end
         | 
| 59 | 
            +
             | 
| @@ -0,0 +1,339 @@ | |
| 1 | 
            +
            require 'customresource/base/mixins/actions'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module CustomResource
         | 
| 4 | 
            +
              module Route53
         | 
| 5 | 
            +
                module MixIns
         | 
| 6 | 
            +
                  module Actions
         | 
| 7 | 
            +
                    include CustomResource::Base::MixIns::Actions
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    WAIT_PERIOD_INSYNC = 30
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                    class NoSuchHostedZone < StandardError ; end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                    def action(verb,section,proc)
         | 
| 14 | 
            +
                      prepare
         | 
| 15 | 
            +
                      # data = {}
         | 
| 16 | 
            +
                      restyp = section.gsub(/s$/,'').downcase
         | 
| 17 | 
            +
                      method = "#{verb}_#{restyp}"
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                      resource = @event['ResourceProperties']
         | 
| 20 | 
            +
                      @logger.debug "#{method} #{resource.ai}"
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                      # Convert the 'String' keys to :string symbols
         | 
| 23 | 
            +
                      params = properties_to_params(resource.dup)
         | 
| 24 | 
            +
                      # Weed out the invalid properties
         | 
| 25 | 
            +
                      invalid_keys = validate_params(section,params)
         | 
| 26 | 
            +
                      if invalid_keys.size > 0
         | 
| 27 | 
            +
                        @logger.warn "Invalid keys in #{params[:name] || params.ai}:\n#{invalid_keys.ai}"
         | 
| 28 | 
            +
                      end
         | 
| 29 | 
            +
                      params = delete_invalid_keys(params,invalid_keys)
         | 
| 30 | 
            +
                      # Restore these exceptions to the rule from the resource 'String' set e.g. :codec_options => { 'String': Value, }
         | 
| 31 | 
            +
                      params = restore_exception_params(section,params,resource)
         | 
| 32 | 
            +
                      params = infer_params(section,Mash.new(params))
         | 
| 33 | 
            +
                      @logger.debug params.ai
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                      data = proc.call(params, restyp, method, resource)
         | 
| 36 | 
            +
                      @logger.debug data
         | 
| 37 | 
            +
                      respond('SUCCESS', data)
         | 
| 38 | 
            +
                      0
         | 
| 39 | 
            +
                    end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                    def create(section)
         | 
| 42 | 
            +
                      case section
         | 
| 43 | 
            +
                      when /PrivateHostedZones/
         | 
| 44 | 
            +
                        action('create', section, lambda do |params, restyp, method, resource|
         | 
| 45 | 
            +
                          begin
         | 
| 46 | 
            +
                            require 'date'
         | 
| 47 | 
            +
                            data = nil
         | 
| 48 | 
            +
                            set = list_hosted_zones(params)
         | 
| 49 | 
            +
                            if set.size == 0
         | 
| 50 | 
            +
                              @logger.info "create #{params[:name]}"
         | 
| 51 | 
            +
                              resp = @awssdk.create_hosted_zone(
         | 
| 52 | 
            +
                                                                  name: params[:hostedzone],
         | 
| 53 | 
            +
                                                                   vpc: {
         | 
| 54 | 
            +
                                                                          vpc_region: @region,
         | 
| 55 | 
            +
                                                                              vpc_id: params[:vpcid]
         | 
| 56 | 
            +
                                                                        },
         | 
| 57 | 
            +
                                                                  caller_reference: "#{params[:name]}::#{DateTime::now.strftime('%Y%m%dT%H%M%S%z')}",
         | 
| 58 | 
            +
                                                                  hosted_zone_config: {
         | 
| 59 | 
            +
                                                                                             comment: params[:comment],
         | 
| 60 | 
            +
                                                                                        # private_zone: true,
         | 
| 61 | 
            +
                                                                                      }
         | 
| 62 | 
            +
                                                                )
         | 
| 63 | 
            +
                              wait_for_insync(resp)
         | 
| 64 | 
            +
                              zone = get_hosted_zone(params)
         | 
| 65 | 
            +
                            else
         | 
| 66 | 
            +
                              zone = set[0] # get_hosted_zone(params)
         | 
| 67 | 
            +
                              @logger.info "Existing hosted_zone #{zone[:id]}::#{zone[:name]}"
         | 
| 68 | 
            +
                              resp = @awssdk.update_hosted_zone_comment( id: zone[:id], comment: params[:comment] )
         | 
| 69 | 
            +
                              unless resp and resp[:hosted_zone]
         | 
| 70 | 
            +
                                abort! "Failed to set comment on zone #{zone[:id]}::#{zone[:name]}"
         | 
| 71 | 
            +
                              end
         | 
| 72 | 
            +
                              zone = Mash.new(resp[:hosted_zone].to_hash)
         | 
| 73 | 
            +
                            end
         | 
| 74 | 
            +
                            if params[:ttl]
         | 
| 75 | 
            +
                              rrs = list_resource_record_sets(zone)
         | 
| 76 | 
            +
                              existing = rrs.select{ |rr| %w(NS SOA).include?(rr[:type]) }
         | 
| 77 | 
            +
                              changes = []
         | 
| 78 | 
            +
                              if existing.size > 0
         | 
| 79 | 
            +
                                existing.each do |rr|
         | 
| 80 | 
            +
                                  rrc = rr.dup
         | 
| 81 | 
            +
                                  rrc[:ttl] = params[:ttl]
         | 
| 82 | 
            +
                                  changes << {
         | 
| 83 | 
            +
                                      action: 'UPSERT',
         | 
| 84 | 
            +
                                      resource_record_set: rrc
         | 
| 85 | 
            +
                                  }
         | 
| 86 | 
            +
                                end
         | 
| 87 | 
            +
                              end
         | 
| 88 | 
            +
                              if changes.size > 0
         | 
| 89 | 
            +
                                resp = change_resource_record_sets(zone, changes)
         | 
| 90 | 
            +
                              end
         | 
| 91 | 
            +
                            end
         | 
| 92 | 
            +
                            data = get_item_data(zone, section, params)
         | 
| 93 | 
            +
                            data
         | 
| 94 | 
            +
                          rescue Exception => e
         | 
| 95 | 
            +
                            abort! "#{restyp}/#{params[:name]}: #{e.message}"
         | 
| 96 | 
            +
                          end
         | 
| 97 | 
            +
                        end
         | 
| 98 | 
            +
                        )
         | 
| 99 | 
            +
                      when /ReverseDNSEntries/
         | 
| 100 | 
            +
                        action('create',
         | 
| 101 | 
            +
                               section,
         | 
| 102 | 
            +
                               lambda do |params, restyp, method, resource|
         | 
| 103 | 
            +
                                 begin
         | 
| 104 | 
            +
                                   data = nil
         | 
| 105 | 
            +
                                   zone = get_hosted_zone(params)
         | 
| 106 | 
            +
                                   @logger.info "Found hosted_zone #{zone[:id]}::#{zone[:name]}"
         | 
| 107 | 
            +
                                   rrs = list_resource_record_sets(zone)
         | 
| 108 | 
            +
                                   existing = rrs.select{ |rr| rr[:name] == params[:name] }
         | 
| 109 | 
            +
                                   changes = []
         | 
| 110 | 
            +
                                   if existing.size > 0
         | 
| 111 | 
            +
                                     existing.each do |rr|
         | 
| 112 | 
            +
                                       changes << {
         | 
| 113 | 
            +
                                           action: 'UPSERT',
         | 
| 114 | 
            +
                                           resource_record_set: {
         | 
| 115 | 
            +
                                               name: rr[:name],
         | 
| 116 | 
            +
                                               type: rr[:type],
         | 
| 117 | 
            +
                                               ttl: params[:ttl],
         | 
| 118 | 
            +
                                               resource_records: params[:resourcerecords] || rr[:resource_records].map{ |r| { value: params[:value] } }
         | 
| 119 | 
            +
                                           }
         | 
| 120 | 
            +
                                       }
         | 
| 121 | 
            +
                                     end
         | 
| 122 | 
            +
                                   else
         | 
| 123 | 
            +
                                     changes << {
         | 
| 124 | 
            +
                                         action: 'CREATE',
         | 
| 125 | 
            +
                                         resource_record_set: {
         | 
| 126 | 
            +
                                             name: params[:name],
         | 
| 127 | 
            +
                                             type: params[:type],
         | 
| 128 | 
            +
                                             ttl: params[:ttl],
         | 
| 129 | 
            +
                                             resource_records: params[:resourcerecords] || [ { value: params[:value] } ]
         | 
| 130 | 
            +
                                         }
         | 
| 131 | 
            +
                                     }
         | 
| 132 | 
            +
                                   end
         | 
| 133 | 
            +
                                   if changes.size > 0
         | 
| 134 | 
            +
                                     resp = change_resource_record_sets(zone, changes)
         | 
| 135 | 
            +
                                   end
         | 
| 136 | 
            +
                                   data = get_item_data(params, section, params)
         | 
| 137 | 
            +
                                   data
         | 
| 138 | 
            +
                                 rescue SystemExit => e
         | 
| 139 | 
            +
                                   raise e
         | 
| 140 | 
            +
                                 rescue Exception => e
         | 
| 141 | 
            +
                                   abort! "#{section}/#{params[:name]}: #{e.message}"
         | 
| 142 | 
            +
                                 end
         | 
| 143 | 
            +
                               end
         | 
| 144 | 
            +
                        )
         | 
| 145 | 
            +
                      else
         | 
| 146 | 
            +
                        abort! "Unsupported section #{section}"
         | 
| 147 | 
            +
                      end
         | 
| 148 | 
            +
                    end
         | 
| 149 | 
            +
             | 
| 150 | 
            +
                    def update(section)
         | 
| 151 | 
            +
                      create section
         | 
| 152 | 
            +
                    end
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                    def delete(section)
         | 
| 155 | 
            +
                      case section
         | 
| 156 | 
            +
                        when /PrivateHostedZones/
         | 
| 157 | 
            +
                          action('delete',
         | 
| 158 | 
            +
                                 section,
         | 
| 159 | 
            +
                                 lambda do |params, restyp, method, resource|
         | 
| 160 | 
            +
                                   begin
         | 
| 161 | 
            +
                                     data = nil
         | 
| 162 | 
            +
                                     set = list_hosted_zones(params)
         | 
| 163 | 
            +
                                     unless set.size == 0
         | 
| 164 | 
            +
                                       zone = set[0]
         | 
| 165 | 
            +
                                       @logger.info "Delete existing hosted_zone #{zone[:id]}::#{zone[:name]}"
         | 
| 166 | 
            +
                                       # if zone[:resource_record_set_count] > 2
         | 
| 167 | 
            +
                                       #   rrs = list_resource_record_sets(zone)
         | 
| 168 | 
            +
                                       #   changes = []
         | 
| 169 | 
            +
                                       #   rrs.each do |rr|
         | 
| 170 | 
            +
                                       #     changes << {
         | 
| 171 | 
            +
                                       #                               action: 'DELETE',
         | 
| 172 | 
            +
                                       #                  resource_record_set: {
         | 
| 173 | 
            +
                                       #                                                     name: rr[:name],
         | 
| 174 | 
            +
                                       #                                                     type: rr[:type],
         | 
| 175 | 
            +
                                       #                                                      ttl: rr[:ttl],
         | 
| 176 | 
            +
                                       #                                         resource_records: rr[:resource_records].map{ |r| { value: r[:value] } }
         | 
| 177 | 
            +
                                       #                                       }
         | 
| 178 | 
            +
                                       #                } unless %w(NS SOA).include?(rr[:type])
         | 
| 179 | 
            +
                                       #   end
         | 
| 180 | 
            +
                                       #   if changes.size > 0
         | 
| 181 | 
            +
                                       #     change_resource_record_sets(zone, changes)
         | 
| 182 | 
            +
                                       #   end
         | 
| 183 | 
            +
                                       # end
         | 
| 184 | 
            +
                                       @awssdk.delete_hosted_zone( { id: zone[:id] })
         | 
| 185 | 
            +
                                       data = get_item_data(Mash.new({ id: zone[:id] }.merge(params)), section, params)
         | 
| 186 | 
            +
                                     end
         | 
| 187 | 
            +
                                     data
         | 
| 188 | 
            +
                                   rescue Exception => e
         | 
| 189 | 
            +
                                     abort! "#{restyp}/#{params[:name]}: #{e.message}"
         | 
| 190 | 
            +
                                   end
         | 
| 191 | 
            +
                                 end
         | 
| 192 | 
            +
                          )
         | 
| 193 | 
            +
                        when /ReverseDNSEntries/
         | 
| 194 | 
            +
                          action('delete',
         | 
| 195 | 
            +
                                 section,
         | 
| 196 | 
            +
                                 lambda do |params, restyp, method, resource|
         | 
| 197 | 
            +
                                   begin
         | 
| 198 | 
            +
                                     data = nil
         | 
| 199 | 
            +
                                     zone = get_hosted_zone(params)
         | 
| 200 | 
            +
                                     @logger.info "Found hosted_zone #{zone[:id]}::#{zone[:name]}"
         | 
| 201 | 
            +
                                     changes = []
         | 
| 202 | 
            +
                                     rrs = list_resource_record_sets(zone)
         | 
| 203 | 
            +
                                     if params[:resourcerecords]
         | 
| 204 | 
            +
                                       rrs.select! do |rr|
         | 
| 205 | 
            +
                                         rr[:name] == params[:name]
         | 
| 206 | 
            +
                                       end
         | 
| 207 | 
            +
                                       changes << {
         | 
| 208 | 
            +
                                           action: 'DELETE',
         | 
| 209 | 
            +
                                           resource_record_set: {
         | 
| 210 | 
            +
                                               name: params[:name],
         | 
| 211 | 
            +
                                               type: params[:type],
         | 
| 212 | 
            +
                                               ttl: params[:ttl],
         | 
| 213 | 
            +
                                               resource_records: params[:resourcerecords]
         | 
| 214 | 
            +
                                           }
         | 
| 215 | 
            +
                                       } if rrs.size > 0
         | 
| 216 | 
            +
                                     else
         | 
| 217 | 
            +
                                       rrs.each do |rr|
         | 
| 218 | 
            +
                                         rrd = rr.dup
         | 
| 219 | 
            +
                                         changes << {
         | 
| 220 | 
            +
                                             action: 'DELETE',
         | 
| 221 | 
            +
                                             resource_record_set: rrd
         | 
| 222 | 
            +
                                         } if rr[:name] == params[:name]
         | 
| 223 | 
            +
                                       end
         | 
| 224 | 
            +
                                     end
         | 
| 225 | 
            +
                                     if changes.size > 0
         | 
| 226 | 
            +
                                       # abort! "Cannot delete #{params[:name]} from #{zone[:id]}::#{zone[:name]}"
         | 
| 227 | 
            +
                                       change_resource_record_sets(zone,changes)
         | 
| 228 | 
            +
                                     end
         | 
| 229 | 
            +
                                     data = get_item_data(params, section, params)
         | 
| 230 | 
            +
                                     data
         | 
| 231 | 
            +
                                   rescue NoSuchHostedZone => e
         | 
| 232 | 
            +
                                     # [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
         | 
| 233 | 
            +
                                     respond('SUCCESS', nil, e.message)
         | 
| 234 | 
            +
                                   rescue SystemExit => e
         | 
| 235 | 
            +
                                     raise e
         | 
| 236 | 
            +
                                   rescue Exception => e
         | 
| 237 | 
            +
                                     abort! "#{section}/#{params[:name]}: #{e.message}"
         | 
| 238 | 
            +
                                   end
         | 
| 239 | 
            +
                                 end
         | 
| 240 | 
            +
                          )
         | 
| 241 | 
            +
                        else
         | 
| 242 | 
            +
                          abort! "Unsupported section #{section}"
         | 
| 243 | 
            +
                      end
         | 
| 244 | 
            +
                    end
         | 
| 245 | 
            +
             | 
| 246 | 
            +
                    def get_hosted_zone(params)
         | 
| 247 | 
            +
                      zone = nil
         | 
| 248 | 
            +
                      begin
         | 
| 249 | 
            +
                        if params[:hostedzoneid]
         | 
| 250 | 
            +
                          resp = @awssdk.get_hosted_zone(id: params[:hostedzoneid])
         | 
| 251 | 
            +
                          if resp
         | 
| 252 | 
            +
                            zone = Mash.new(resp.hosted_zone.to_hash)
         | 
| 253 | 
            +
                          end
         | 
| 254 | 
            +
                        else
         | 
| 255 | 
            +
                          set = list_hosted_zones(params)
         | 
| 256 | 
            +
                          if set.size == 0
         | 
| 257 | 
            +
                            raise NoSuchHostedZone.new("Cannot find hosted zone #{params[:hostedzone]}")
         | 
| 258 | 
            +
                          else
         | 
| 259 | 
            +
                            zone = set[0]
         | 
| 260 | 
            +
                          end
         | 
| 261 | 
            +
                        end
         | 
| 262 | 
            +
                        zone
         | 
| 263 | 
            +
                      rescue Aws::Route53::Errors::NoSuchHostedZone => e
         | 
| 264 | 
            +
                        raise NoSuchHostedZone.new(e.message)
         | 
| 265 | 
            +
                      end
         | 
| 266 | 
            +
                    end
         | 
| 267 | 
            +
             | 
| 268 | 
            +
                    def wait_for_insync(resp)
         | 
| 269 | 
            +
                      unless resp and resp[:change_info]
         | 
| 270 | 
            +
                        abort! 'Bad response to change_resource_record_sets'
         | 
| 271 | 
            +
                      end
         | 
| 272 | 
            +
                      change_info = Mash.new(resp[:change_info].to_hash)
         | 
| 273 | 
            +
                      while resp
         | 
| 274 | 
            +
                        resp = @awssdk.get_change(id: change_info[:id])
         | 
| 275 | 
            +
                        unless resp and resp[:change_info]
         | 
| 276 | 
            +
                          abort! "Bad response to get_change[id: #{change_info[:id]}]"
         | 
| 277 | 
            +
                        end
         | 
| 278 | 
            +
                        change_info = Mash.new(resp[:change_info].to_hash)
         | 
| 279 | 
            +
                        if change_info[:status] != 'INSYNC'
         | 
| 280 | 
            +
                          @logger.info "Change #{change_info[:id]} is #{change_info[:status]} ... Waiting #{WAIT_PERIOD_INSYNC}s"
         | 
| 281 | 
            +
                          sleep WAIT_PERIOD_INSYNC
         | 
| 282 | 
            +
                        else
         | 
| 283 | 
            +
                          resp = nil
         | 
| 284 | 
            +
                        end
         | 
| 285 | 
            +
                      end
         | 
| 286 | 
            +
                    end
         | 
| 287 | 
            +
             | 
| 288 | 
            +
                    def list_hosted_zones(params)
         | 
| 289 | 
            +
                      set = []
         | 
| 290 | 
            +
                      resp = @awssdk.list_hosted_zones
         | 
| 291 | 
            +
                      if resp
         | 
| 292 | 
            +
                        resp.hosted_zones.map { |item| set << item.to_h }
         | 
| 293 | 
            +
                        while resp[:marker]
         | 
| 294 | 
            +
                          resp = @awssdk.list_hosted_zones(marker: resp[:marker])
         | 
| 295 | 
            +
                          if resp
         | 
| 296 | 
            +
                            resp.hosted_zones.map { |item| set << Mash.new(item.to_h) }
         | 
| 297 | 
            +
                          end
         | 
| 298 | 
            +
                        end
         | 
| 299 | 
            +
                        # Let's see if we have hostedzones which match this :name
         | 
| 300 | 
            +
                        set.select!{ |item|  item[:name].match(/^#{params[:hostedzone]}$/) and item[:config][:private_zone] == true }
         | 
| 301 | 
            +
                      end
         | 
| 302 | 
            +
                      set
         | 
| 303 | 
            +
                    end
         | 
| 304 | 
            +
             | 
| 305 | 
            +
                    def change_resource_record_sets(zone, changes)
         | 
| 306 | 
            +
                      while true
         | 
| 307 | 
            +
                        begin
         | 
| 308 | 
            +
                          resp = @awssdk.change_resource_record_sets(
         | 
| 309 | 
            +
                              hosted_zone_id: zone[:id],
         | 
| 310 | 
            +
                              change_batch: {
         | 
| 311 | 
            +
                                  changes: changes
         | 
| 312 | 
            +
                              }
         | 
| 313 | 
            +
                          )
         | 
| 314 | 
            +
                          wait_for_insync(resp)
         | 
| 315 | 
            +
                          return resp
         | 
| 316 | 
            +
                        rescue Aws::Route53::Errors::PriorRequestNotComplete
         | 
| 317 | 
            +
                          sleep WAIT_PERIOD_INSYNC
         | 
| 318 | 
            +
                        end
         | 
| 319 | 
            +
                      end
         | 
| 320 | 
            +
                    end
         | 
| 321 | 
            +
             | 
| 322 | 
            +
                    def list_resource_record_sets(zone)
         | 
| 323 | 
            +
                      rrs = []
         | 
| 324 | 
            +
                      resp = @awssdk.list_resource_record_sets(hosted_zone_id: zone[:id])
         | 
| 325 | 
            +
                      while resp
         | 
| 326 | 
            +
                        resp.resource_record_sets.map { |rr| rrs << Mash.new(rr.to_hash) }
         | 
| 327 | 
            +
                        resp = if resp[:is_truncated]
         | 
| 328 | 
            +
                                 @awssdk.list_resource_record_sets(hosted_zone_id: zone[:id], marker: resp[:marker])
         | 
| 329 | 
            +
                               else
         | 
| 330 | 
            +
                                 nil
         | 
| 331 | 
            +
                               end
         | 
| 332 | 
            +
                      end
         | 
| 333 | 
            +
                      rrs
         | 
| 334 | 
            +
                    end
         | 
| 335 | 
            +
             | 
| 336 | 
            +
                  end
         | 
| 337 | 
            +
                end
         | 
| 338 | 
            +
              end
         | 
| 339 | 
            +
            end
         |