cloudspin-stack 0.1.19 → 0.1.20
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 +4 -4
- data/lib/cloudspin/cli.rb +7 -4
- data/lib/cloudspin/stack/instance.rb +83 -47
- data/lib/cloudspin/stack/instance_configuration.rb +61 -15
- data/lib/cloudspin/stack/version.rb +1 -1
- metadata +2 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 7367da5398e58437223ee59141a3acfde89306c4
         | 
| 4 | 
            +
              data.tar.gz: c7d4175e095df03cbd6e51bb8ba81a7cb9e9bef4
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 8677124654c9c41f12a14c60d825d565d2574ae98ae07bc6fba1fdb86d9b60c0aefadc392dde3e54ceae77260519e05f7bb8b17fe633c3c0e23eb85f88a84732
         | 
| 7 | 
            +
              data.tar.gz: c6f53cae6e58db92b63b72a32d869a5a40557affbc5d6c78d17387953c8235a442fbc3321432e2494f753959791c6fa12976c425922c01e02b8f64dea17e702b
         | 
    
        data/lib/cloudspin/cli.rb
    CHANGED
    
    | @@ -20,13 +20,15 @@ module Cloudspin | |
| 20 20 |  | 
| 21 21 | 
             
                class_option :environment,
         | 
| 22 22 | 
             
                  :aliases => '-e',
         | 
| 23 | 
            -
                  :banner => ' | 
| 24 | 
            -
                  :desc => 'An environment instance to manage.'
         | 
| 23 | 
            +
                  :banner => 'environment_id',
         | 
| 24 | 
            +
                  :desc => 'An environment instance to manage. File ./environments/stack-instance-ENVIRONMENT_ID.yaml must exist.'
         | 
| 25 25 |  | 
| 26 26 | 
             
                desc 'up', 'Create or update the stack instance'
         | 
| 27 27 | 
             
                option :dry, :type => :boolean, :default => false
         | 
| 28 28 | 
             
                option :plan, :type => :boolean, :default => false
         | 
| 29 | 
            +
                option :'show-init', :type => :boolean, :default => true
         | 
| 29 30 | 
             
                def up
         | 
| 31 | 
            +
                  puts instance.init_dry if options[:'show-init']
         | 
| 30 32 | 
             
                  if options[:plan] && options[:dry]
         | 
| 31 33 | 
             
                    puts instance.plan_dry
         | 
| 32 34 | 
             
                  elsif options[:plan] && ! options[:dry]
         | 
| @@ -41,7 +43,9 @@ module Cloudspin | |
| 41 43 | 
             
                desc 'down', 'Destroy the stack instance'
         | 
| 42 44 | 
             
                option :dry, :type => :boolean, :default => false
         | 
| 43 45 | 
             
                option :plan, :type => :boolean, :default => false
         | 
| 46 | 
            +
                option :'show-init', :type => :boolean, :default => true
         | 
| 44 47 | 
             
                def down
         | 
| 48 | 
            +
                  puts instance.init_dry if options[:'show-init']
         | 
| 45 49 | 
             
                  if options[:plan] && options[:dry]
         | 
| 46 50 | 
             
                    puts instance.plan_dry(plan_destroy: true)
         | 
| 47 51 | 
             
                  elsif options[:plan] && ! options[:dry]
         | 
| @@ -69,8 +73,7 @@ module Cloudspin | |
| 69 73 | 
             
                    Cloudspin::Stack::Instance.from_files(
         | 
| 70 74 | 
             
                      instance_configuration_files,
         | 
| 71 75 | 
             
                      stack_definition: stack_definition,
         | 
| 72 | 
            -
                      base_working_folder: './work' | 
| 73 | 
            -
                      base_statefile_folder: './state'
         | 
| 76 | 
            +
                      base_working_folder: './work'
         | 
| 74 77 | 
             
                    )
         | 
| 75 78 | 
             
                  end
         | 
| 76 79 |  | 
| @@ -9,51 +9,50 @@ module Cloudspin | |
| 9 9 |  | 
| 10 10 | 
             
                  attr_reader :id,
         | 
| 11 11 | 
             
                      :working_folder,
         | 
| 12 | 
            -
                      :statefile_folder,
         | 
| 13 12 | 
             
                      :configuration
         | 
| 14 13 |  | 
| 15 14 | 
             
                  def initialize(
         | 
| 16 15 | 
             
                        id:,
         | 
| 17 16 | 
             
                        stack_definition:,
         | 
| 18 17 | 
             
                        working_folder:,
         | 
| 19 | 
            -
                        statefile_folder:,
         | 
| 20 18 | 
             
                        configuration:
         | 
| 21 19 | 
             
                  )
         | 
| 22 20 | 
             
                    validate_id(id)
         | 
| 23 21 | 
             
                    @id = id
         | 
| 24 22 | 
             
                    @stack_definition = stack_definition
         | 
| 25 | 
            -
                    @working_folder | 
| 26 | 
            -
                    @ | 
| 27 | 
            -
                    @configuration = configuration
         | 
| 28 | 
            -
                    @backend_config = {}
         | 
| 23 | 
            +
                    @working_folder   = working_folder
         | 
| 24 | 
            +
                    @configuration    = configuration
         | 
| 29 25 | 
             
                  end
         | 
| 30 26 |  | 
| 31 27 | 
             
                  def self.from_folder(
         | 
| 32 28 | 
             
                        *instance_configuration_files,
         | 
| 33 29 | 
             
                        definition_folder:,
         | 
| 34 | 
            -
                         | 
| 35 | 
            -
                         | 
| 30 | 
            +
                        base_folder: '.',
         | 
| 31 | 
            +
                        base_working_folder:
         | 
| 36 32 | 
             
                  )
         | 
| 37 33 | 
             
                    self.from_files(
         | 
| 38 34 | 
             
                        instance_configuration_files,
         | 
| 39 35 | 
             
                        stack_definition: Definition.from_folder(definition_folder),
         | 
| 40 | 
            -
                         | 
| 41 | 
            -
                         | 
| 36 | 
            +
                        base_folder: base_folder,
         | 
| 37 | 
            +
                        base_working_folder: base_working_folder
         | 
| 42 38 | 
             
                      )
         | 
| 43 39 | 
             
                  end
         | 
| 44 40 |  | 
| 45 41 | 
             
                  def self.from_files(
         | 
| 46 42 | 
             
                        *instance_configuration_files,
         | 
| 47 43 | 
             
                        stack_definition:,
         | 
| 48 | 
            -
                         | 
| 49 | 
            -
                         | 
| 44 | 
            +
                        base_folder: '.',
         | 
| 45 | 
            +
                        base_working_folder:
         | 
| 50 46 | 
             
                  )
         | 
| 51 | 
            -
                    instance_configuration = InstanceConfiguration.from_files( | 
| 47 | 
            +
                    instance_configuration = InstanceConfiguration.from_files(
         | 
| 48 | 
            +
                      instance_configuration_files,
         | 
| 49 | 
            +
                      stack_definition: stack_definition,
         | 
| 50 | 
            +
                      base_folder: base_folder
         | 
| 51 | 
            +
                    )
         | 
| 52 52 | 
             
                    self.new(
         | 
| 53 53 | 
             
                        id: instance_configuration.instance_identifier,
         | 
| 54 54 | 
             
                        stack_definition: stack_definition,
         | 
| 55 55 | 
             
                        working_folder: ensure_folder("#{base_working_folder}/#{instance_configuration.instance_identifier}"),
         | 
| 56 | 
            -
                        statefile_folder: ensure_folder("#{base_statefile_folder}/#{instance_configuration.instance_identifier}"),
         | 
| 57 56 | 
             
                        configuration: instance_configuration
         | 
| 58 57 | 
             
                      )
         | 
| 59 58 | 
             
                  end
         | 
| @@ -81,24 +80,20 @@ module Cloudspin | |
| 81 80 | 
             
                    RubyTerraform.clean(directory: working_folder)
         | 
| 82 81 | 
             
                    mkdir_p File.dirname(working_folder)
         | 
| 83 82 | 
             
                    cp_r @stack_definition.source_path, working_folder
         | 
| 83 | 
            +
                    ensure_state_folder
         | 
| 84 84 | 
             
                    Dir.chdir(working_folder) do
         | 
| 85 | 
            -
                       | 
| 86 | 
            -
                      RubyTerraform.plan(
         | 
| 87 | 
            -
                        destroy: plan_destroy,
         | 
| 88 | 
            -
                        state: terraform_statefile,
         | 
| 89 | 
            -
                        vars: terraform_variables
         | 
| 90 | 
            -
                      )
         | 
| 85 | 
            +
                      terraform_init
         | 
| 86 | 
            +
                      RubyTerraform.plan(terraform_command_parameters(destroy: plan_destroy))
         | 
| 91 87 | 
             
                    end
         | 
| 92 88 | 
             
                  end
         | 
| 93 89 |  | 
| 94 90 | 
             
                  def plan_dry(plan_destroy: false)
         | 
| 95 91 | 
             
                    plan_command = RubyTerraform::Commands::Plan.new
         | 
| 96 92 | 
             
                    command_line_builder = plan_command.instantiate_builder
         | 
| 97 | 
            -
                    configured_command = plan_command.configure_command( | 
| 98 | 
            -
                       | 
| 99 | 
            -
                      : | 
| 100 | 
            -
             | 
| 101 | 
            -
                    })
         | 
| 93 | 
            +
                    configured_command = plan_command.configure_command(
         | 
| 94 | 
            +
                      command_line_builder,
         | 
| 95 | 
            +
                      terraform_command_parameters(:destroy => plan_destroy)
         | 
| 96 | 
            +
                    )
         | 
| 102 97 | 
             
                    built_command = configured_command.build
         | 
| 103 98 | 
             
                    "cd #{working_folder} && #{built_command.to_s}"
         | 
| 104 99 | 
             
                  end
         | 
| @@ -107,23 +102,17 @@ module Cloudspin | |
| 107 102 | 
             
                    RubyTerraform.clean(directory: working_folder)
         | 
| 108 103 | 
             
                    mkdir_p File.dirname(working_folder)
         | 
| 109 104 | 
             
                    cp_r @stack_definition.source_path, working_folder
         | 
| 105 | 
            +
                    ensure_state_folder
         | 
| 110 106 | 
             
                    Dir.chdir(working_folder) do
         | 
| 111 | 
            -
                       | 
| 112 | 
            -
                      RubyTerraform.apply(
         | 
| 113 | 
            -
                        auto_approve: true,
         | 
| 114 | 
            -
                        state: terraform_statefile,
         | 
| 115 | 
            -
                        vars: terraform_variables
         | 
| 116 | 
            -
                      )
         | 
| 107 | 
            +
                      terraform_init
         | 
| 108 | 
            +
                      RubyTerraform.apply(terraform_command_parameters(auto_approve: true))
         | 
| 117 109 | 
             
                    end
         | 
| 118 110 | 
             
                  end
         | 
| 119 111 |  | 
| 120 112 | 
             
                  def up_dry
         | 
| 121 113 | 
             
                    up_command = RubyTerraform::Commands::Apply.new
         | 
| 122 114 | 
             
                    command_line_builder = up_command.instantiate_builder
         | 
| 123 | 
            -
                    configured_command = up_command.configure_command(command_line_builder,  | 
| 124 | 
            -
                      :state => terraform_statefile,
         | 
| 125 | 
            -
                      :vars => terraform_variables
         | 
| 126 | 
            -
                    })
         | 
| 115 | 
            +
                    configured_command = up_command.configure_command(command_line_builder, terraform_command_parameters)
         | 
| 127 116 | 
             
                    built_command = configured_command.build
         | 
| 128 117 | 
             
                    "cd #{working_folder} && #{built_command.to_s}"
         | 
| 129 118 | 
             
                  end
         | 
| @@ -132,35 +121,82 @@ module Cloudspin | |
| 132 121 | 
             
                    RubyTerraform.clean(directory: working_folder)
         | 
| 133 122 | 
             
                    mkdir_p File.dirname(working_folder)
         | 
| 134 123 | 
             
                    cp_r @stack_definition.source_path, working_folder
         | 
| 124 | 
            +
                    ensure_state_folder
         | 
| 135 125 | 
             
                    Dir.chdir(working_folder) do
         | 
| 136 | 
            -
                       | 
| 137 | 
            -
                      RubyTerraform.destroy(
         | 
| 138 | 
            -
                        force: true,
         | 
| 139 | 
            -
                        state: terraform_statefile,
         | 
| 140 | 
            -
                        vars: terraform_variables
         | 
| 141 | 
            -
                      )
         | 
| 126 | 
            +
                      terraform_init
         | 
| 127 | 
            +
                      RubyTerraform.destroy(terraform_command_parameters(force: true))
         | 
| 142 128 | 
             
                    end
         | 
| 143 129 | 
             
                  end
         | 
| 144 130 |  | 
| 145 131 | 
             
                  def down_dry
         | 
| 146 132 | 
             
                    down_command = RubyTerraform::Commands::Destroy.new
         | 
| 147 133 | 
             
                    command_line_builder = down_command.instantiate_builder
         | 
| 148 | 
            -
                    configured_command = down_command.configure_command(command_line_builder,  | 
| 149 | 
            -
                      :state => terraform_statefile,
         | 
| 150 | 
            -
                      :vars => terraform_variables
         | 
| 151 | 
            -
                    })
         | 
| 134 | 
            +
                    configured_command = down_command.configure_command(command_line_builder, terraform_command_parameters)
         | 
| 152 135 | 
             
                    built_command = configured_command.build
         | 
| 153 136 | 
             
                    "cd #{working_folder} && #{built_command.to_s}"
         | 
| 154 137 | 
             
                  end
         | 
| 155 138 |  | 
| 139 | 
            +
                  def terraform_init
         | 
| 140 | 
            +
                    RubyTerraform.init(terraform_init_params)
         | 
| 141 | 
            +
                  end
         | 
| 142 | 
            +
             | 
| 143 | 
            +
                  def init_dry
         | 
| 144 | 
            +
                    init_command = RubyTerraform::Commands::Init.new
         | 
| 145 | 
            +
                    command_line_builder = init_command.instantiate_builder
         | 
| 146 | 
            +
                    configured_command = init_command.configure_command(
         | 
| 147 | 
            +
                      command_line_builder,
         | 
| 148 | 
            +
                      terraform_init_params
         | 
| 149 | 
            +
                    )
         | 
| 150 | 
            +
                    built_command = configured_command.build
         | 
| 151 | 
            +
                    "cd #{working_folder} && #{built_command.to_s}"
         | 
| 152 | 
            +
                  end
         | 
| 153 | 
            +
             | 
| 154 | 
            +
                  def terraform_init_params
         | 
| 155 | 
            +
                    if configuration.has_remote_state_configuration?
         | 
| 156 | 
            +
                      {
         | 
| 157 | 
            +
                        backend: 's3',
         | 
| 158 | 
            +
                        backend_config: backend_parameters
         | 
| 159 | 
            +
                      }
         | 
| 160 | 
            +
                    else
         | 
| 161 | 
            +
                      {}
         | 
| 162 | 
            +
                    end
         | 
| 163 | 
            +
                  end
         | 
| 164 | 
            +
             | 
| 165 | 
            +
                  def ensure_state_folder
         | 
| 166 | 
            +
                    if configuration.has_local_state_configuration?
         | 
| 167 | 
            +
                      Instance.ensure_folder(configuration.terraform_backend['statefile_folder'])
         | 
| 168 | 
            +
                    end
         | 
| 169 | 
            +
                  end
         | 
| 170 | 
            +
             | 
| 171 | 
            +
                  def terraform_command_parameters(added_parameters = {})
         | 
| 172 | 
            +
                    {
         | 
| 173 | 
            +
                      vars: terraform_variables
         | 
| 174 | 
            +
                    }.merge(local_state_parameters).merge(added_parameters)
         | 
| 175 | 
            +
                  end
         | 
| 176 | 
            +
             | 
| 156 177 | 
             
                  def terraform_variables
         | 
| 157 178 | 
             
                    parameter_values.merge(resource_values) { |key, oldval, newval|
         | 
| 158 179 | 
             
                      raise "Duplicate values for terraform variable '#{key}' ('#{oldval}' and '#{newval}')"
         | 
| 159 180 | 
             
                    }.merge({ 'instance_identifier' => id })
         | 
| 160 181 | 
             
                  end
         | 
| 161 182 |  | 
| 162 | 
            -
                  def  | 
| 163 | 
            -
                     | 
| 183 | 
            +
                  def local_state_parameters
         | 
| 184 | 
            +
                    if configuration.has_local_state_configuration?
         | 
| 185 | 
            +
                      { state: configuration.local_statefile }
         | 
| 186 | 
            +
                    else
         | 
| 187 | 
            +
                      {}
         | 
| 188 | 
            +
                    end
         | 
| 189 | 
            +
                  end
         | 
| 190 | 
            +
             | 
| 191 | 
            +
                  def backend_parameters
         | 
| 192 | 
            +
                    if configuration.has_remote_state_configuration?
         | 
| 193 | 
            +
                      {
         | 
| 194 | 
            +
                        'bucket' => configuration.terraform_backend['bucket'],
         | 
| 195 | 
            +
                        'key' => configuration.terraform_backend['key']
         | 
| 196 | 
            +
                      }
         | 
| 197 | 
            +
                    else
         | 
| 198 | 
            +
                      {}
         | 
| 199 | 
            +
                    end
         | 
| 164 200 | 
             
                  end
         | 
| 165 201 |  | 
| 166 202 | 
             
                end
         | 
| @@ -7,28 +7,52 @@ module Cloudspin | |
| 7 7 |  | 
| 8 8 | 
             
                  attr_reader :stack_definition
         | 
| 9 9 | 
             
                  attr_reader :stack_name
         | 
| 10 | 
            +
                  attr_reader :base_folder
         | 
| 10 11 |  | 
| 11 12 | 
             
                  attr_reader :instance_values
         | 
| 12 13 | 
             
                  attr_reader :parameter_values
         | 
| 13 14 | 
             
                  attr_reader :resource_values
         | 
| 14 15 |  | 
| 15 | 
            -
                   | 
| 16 | 
            +
                  attr_reader :terraform_backend
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  def initialize(
         | 
| 19 | 
            +
                      configuration_values: {},
         | 
| 20 | 
            +
                      stack_definition:,
         | 
| 21 | 
            +
                      base_folder: '.'
         | 
| 22 | 
            +
                  )
         | 
| 16 23 | 
             
                    @stack_definition = stack_definition
         | 
| 17 24 | 
             
                    @stack_name = stack_definition.name
         | 
| 18 | 
            -
                    @ | 
| 19 | 
            -
             | 
| 20 | 
            -
                    @ | 
| 25 | 
            +
                    @base_folder = base_folder
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                    @instance_values = configuration_values['instance'] || {}
         | 
| 28 | 
            +
                    @parameter_values = configuration_values['parameters'] || {}
         | 
| 29 | 
            +
                    @resource_values = configuration_values['resources'] || {}
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                    @terraform_backend = configuration_values['terraform_backend'] || {}
         | 
| 32 | 
            +
                    if @terraform_backend.empty?
         | 
| 33 | 
            +
                      @terraform_backend['statefile_folder'] = default_state_folder
         | 
| 34 | 
            +
                    else
         | 
| 35 | 
            +
                      @terraform_backend['key'] = default_state_key
         | 
| 36 | 
            +
                    end
         | 
| 21 37 | 
             
                  end
         | 
| 22 38 |  | 
| 23 | 
            -
                  def self.from_files( | 
| 24 | 
            -
             | 
| 39 | 
            +
                  def self.from_files(
         | 
| 40 | 
            +
                      *configuration_files,
         | 
| 41 | 
            +
                      stack_definition:,
         | 
| 42 | 
            +
                      base_folder: '.'
         | 
| 43 | 
            +
                  )
         | 
| 44 | 
            +
                    configuration_values = {}
         | 
| 25 45 | 
             
                    configuration_files.flatten.each { |config_file|
         | 
| 26 | 
            -
                       | 
| 46 | 
            +
                      configuration_values = configuration_values.deep_merge(yaml_file_to_hash(config_file))
         | 
| 27 47 | 
             
                    }
         | 
| 28 | 
            -
                     | 
| 48 | 
            +
                    self.new(
         | 
| 49 | 
            +
                      stack_definition: stack_definition,
         | 
| 50 | 
            +
                      base_folder: base_folder,
         | 
| 51 | 
            +
                      configuration_values: configuration_values
         | 
| 52 | 
            +
                    )
         | 
| 29 53 | 
             
                  end
         | 
| 30 54 |  | 
| 31 | 
            -
                  def self. | 
| 55 | 
            +
                  def self.yaml_file_to_hash(yaml_file)
         | 
| 32 56 | 
             
                    if File.exists?(yaml_file)
         | 
| 33 57 | 
             
                      YAML.load_file(yaml_file) || {}
         | 
| 34 58 | 
             
                    else
         | 
| @@ -36,11 +60,24 @@ module Cloudspin | |
| 36 60 | 
             
                    end
         | 
| 37 61 | 
             
                  end
         | 
| 38 62 |  | 
| 39 | 
            -
                  def  | 
| 40 | 
            -
                     | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 63 | 
            +
                  def has_local_state_configuration?
         | 
| 64 | 
            +
                    ! @terraform_backend['statefile_folder'].nil?
         | 
| 65 | 
            +
                  end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                  def local_statefile
         | 
| 68 | 
            +
                    "#{@terraform_backend['statefile_folder']}/#{instance_identifier}.tfstate"
         | 
| 69 | 
            +
                  end
         | 
| 70 | 
            +
             | 
| 71 | 
            +
                  def has_remote_state_configuration?
         | 
| 72 | 
            +
                    ! @terraform_backend['key'].nil?
         | 
| 73 | 
            +
                  end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                  def default_state_folder
         | 
| 76 | 
            +
                    Pathname.new("#{base_folder}/state/#{instance_identifier}").realdirpath.to_s
         | 
| 77 | 
            +
                  end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                  def default_state_key
         | 
| 80 | 
            +
                    "/#{instance_identifier}.tfstate"
         | 
| 44 81 | 
             
                  end
         | 
| 45 82 |  | 
| 46 83 | 
             
                  def instance_identifier
         | 
| @@ -55,9 +92,11 @@ module Cloudspin | |
| 55 92 |  | 
| 56 93 | 
             
                  def to_s
         | 
| 57 94 | 
             
                    {
         | 
| 95 | 
            +
                      'instance_identifier' => instance_identifier,
         | 
| 58 96 | 
             
                      'instance' => instance_values,
         | 
| 59 97 | 
             
                      'parameters' => parameter_values,
         | 
| 60 | 
            -
                      'resources' => resource_values
         | 
| 98 | 
            +
                      'resources' => resource_values,
         | 
| 99 | 
            +
                      'terraform_backend' => terraform_backend
         | 
| 61 100 | 
             
                    }.to_s
         | 
| 62 101 | 
             
                  end
         | 
| 63 102 |  | 
| @@ -66,3 +105,10 @@ module Cloudspin | |
| 66 105 | 
             
              end
         | 
| 67 106 | 
             
            end
         | 
| 68 107 |  | 
| 108 | 
            +
            # hat tip: https://stackoverflow.com/questions/9381553/ruby-merge-nested-hash
         | 
| 109 | 
            +
            class ::Hash
         | 
| 110 | 
            +
              def deep_merge(second)
         | 
| 111 | 
            +
                merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : Array === v1 && Array === v2 ? v1 | v2 : [:undefined, nil, :nil].include?(v2) ? v1 : v2 }
         | 
| 112 | 
            +
                self.merge(second.to_h, &merger)
         | 
| 113 | 
            +
              end
         | 
| 114 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: cloudspin-stack
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.1. | 
| 4 | 
            +
              version: 0.1.20
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - 'kief '
         | 
| 8 8 | 
             
            autorequire: 
         | 
| 9 9 | 
             
            bindir: exe
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2018-09- | 
| 11 | 
            +
            date: 2018-09-24 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: ruby-terraform
         |