kumogata 0.1.0
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/.gitignore +20 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +127 -0
- data/Rakefile +6 -0
- data/bin/kumogata +48 -0
- data/kumogata.gemspec +31 -0
- data/lib/kumogata/argument_parser.rb +142 -0
- data/lib/kumogata/client.rb +324 -0
- data/lib/kumogata/ext/string_ext.rb +41 -0
- data/lib/kumogata/logger.rb +23 -0
- data/lib/kumogata/version.rb +3 -0
- data/lib/kumogata.rb +19 -0
- data/packer/CentOS-6.4-x86_64-with_Updates-Asia_Pacific.json +26 -0
- data/packer/Ubuntu-12.04.4-LTS-x86_64-ebs-Asia_Pacific.json +28 -0
- data/spec/kumogata_convert_spec.rb +96 -0
- data/spec/kumogata_create_spec.rb +183 -0
- data/spec/kumogata_delete_spec.rb +20 -0
- data/spec/kumogata_update_spec.rb +121 -0
- data/spec/kumogata_validate_spec.rb +135 -0
- data/spec/spec_helper.rb +68 -0
- metadata +214 -0
| @@ -0,0 +1,324 @@ | |
| 1 | 
            +
            class Kumogata::Client
         | 
| 2 | 
            +
              def initialize(options)
         | 
| 3 | 
            +
                @options = options
         | 
| 4 | 
            +
                @options = Hashie::Mash.new(@options) unless @options.kind_of?(Hashie::Mash)
         | 
| 5 | 
            +
                @cloud_formation = AWS::CloudFormation.new
         | 
| 6 | 
            +
              end
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              def create(path_or_url, stack_name = nil)
         | 
| 9 | 
            +
                @options.delete_stack = false if stack_name
         | 
| 10 | 
            +
                template = open_template(path_or_url)
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                if @options.delete_stack?
         | 
| 13 | 
            +
                  template['Resources'].each do |k, v|
         | 
| 14 | 
            +
                    v['DeletionPolicy'] = 'Retain'
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                create_stack(template, stack_name)
         | 
| 19 | 
            +
                nil
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              def validate(path_or_url)
         | 
| 23 | 
            +
                template = open_template(path_or_url)
         | 
| 24 | 
            +
                validate_template(template)
         | 
| 25 | 
            +
                nil
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              def convert(path_or_url)
         | 
| 29 | 
            +
                template = open_template(path_or_url)
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                if ruby_template?(path_or_url)
         | 
| 32 | 
            +
                  JSON.pretty_generate(template)
         | 
| 33 | 
            +
                else
         | 
| 34 | 
            +
                  devaluate_template(template).chomp
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              def update(path_or_url, stack_name)
         | 
| 39 | 
            +
                template = open(path_or_url) do |f|
         | 
| 40 | 
            +
                  evaluate_template(f)
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                update_stack(template, stack_name)
         | 
| 44 | 
            +
                nil
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
              def delete(stack_name)
         | 
| 48 | 
            +
                if @options.force? or agree("Aare you sure you want to delete `#{stack_name}`? ".yellow)
         | 
| 49 | 
            +
                  delete_stack(stack_name)
         | 
| 50 | 
            +
                end
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                nil
         | 
| 53 | 
            +
              end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
              def list(stack_name = nil)
         | 
| 56 | 
            +
                stacks = describe_stacks(stack_name)
         | 
| 57 | 
            +
                JSON.pretty_generate(stacks)
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              private ###########################################################
         | 
| 61 | 
            +
             | 
| 62 | 
            +
              def open_template(path_or_url)
         | 
| 63 | 
            +
                open(path_or_url) do |f|
         | 
| 64 | 
            +
                  if ruby_template?(path_or_url)
         | 
| 65 | 
            +
                    evaluate_template(f)
         | 
| 66 | 
            +
                  else
         | 
| 67 | 
            +
                    JSON.parse(f.read)
         | 
| 68 | 
            +
                  end
         | 
| 69 | 
            +
                end
         | 
| 70 | 
            +
              end
         | 
| 71 | 
            +
             | 
| 72 | 
            +
              def ruby_template?(path_or_url)
         | 
| 73 | 
            +
                File.extname(path_or_url) == '.rb'
         | 
| 74 | 
            +
              end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
              def evaluate_template(template)
         | 
| 77 | 
            +
                key_converter = proc do |key|
         | 
| 78 | 
            +
                  key = key.to_s
         | 
| 79 | 
            +
                  key.gsub!('__', '::') if @options.replace_underscore?
         | 
| 80 | 
            +
                  key
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                value_converter = proc do |v|
         | 
| 84 | 
            +
                  case v
         | 
| 85 | 
            +
                  when Hash, Array
         | 
| 86 | 
            +
                    v
         | 
| 87 | 
            +
                  else
         | 
| 88 | 
            +
                    v.to_s
         | 
| 89 | 
            +
                  end
         | 
| 90 | 
            +
                end
         | 
| 91 | 
            +
             | 
| 92 | 
            +
                Dslh.eval(template.read, {
         | 
| 93 | 
            +
                  :key_conv   => key_converter,
         | 
| 94 | 
            +
                  :value_conv => value_converter,
         | 
| 95 | 
            +
                  :scope_hook => method(:define_template_func),
         | 
| 96 | 
            +
                  :filename   => template.path,
         | 
| 97 | 
            +
                })
         | 
| 98 | 
            +
              end
         | 
| 99 | 
            +
             | 
| 100 | 
            +
              def devaluate_template(template)
         | 
| 101 | 
            +
                exclude_key = proc do |k|
         | 
| 102 | 
            +
                  k = k.to_s.gsub('::', '__')
         | 
| 103 | 
            +
                  k !~ /\A[_a-z]\w+\Z/i and k !~ %r|\A/\S*\Z|
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                key_conv = proc do |k|
         | 
| 107 | 
            +
                  k = k.to_s
         | 
| 108 | 
            +
             | 
| 109 | 
            +
                  if k =~ %r|\A/\S*\Z|
         | 
| 110 | 
            +
                    proc do |v, nested|
         | 
| 111 | 
            +
                      if nested
         | 
| 112 | 
            +
                        "_path(#{k.inspect}) #{v}"
         | 
| 113 | 
            +
                      else
         | 
| 114 | 
            +
                        "_path #{k.inspect}, #{v}"
         | 
| 115 | 
            +
                      end
         | 
| 116 | 
            +
                    end
         | 
| 117 | 
            +
                  else
         | 
| 118 | 
            +
                    k.gsub('::', '__')
         | 
| 119 | 
            +
                  end
         | 
| 120 | 
            +
                end
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                Dslh.deval(template, :key_conv => key_conv, :exclude_key => exclude_key)
         | 
| 123 | 
            +
              end
         | 
| 124 | 
            +
             | 
| 125 | 
            +
              def define_template_func(scope)
         | 
| 126 | 
            +
                scope.instance_eval do
         | 
| 127 | 
            +
                  def _user_data(data)
         | 
| 128 | 
            +
                    data.strip_lines.encode64
         | 
| 129 | 
            +
                  end
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                  def _path(path, value = nil, &block)
         | 
| 132 | 
            +
                    if block
         | 
| 133 | 
            +
                      value = Dslh::ScopeBlock.nest(binding, 'block')
         | 
| 134 | 
            +
                    end
         | 
| 135 | 
            +
             | 
| 136 | 
            +
                    @__hash__[path] = value
         | 
| 137 | 
            +
                  end
         | 
| 138 | 
            +
                end
         | 
| 139 | 
            +
              end
         | 
| 140 | 
            +
             | 
| 141 | 
            +
              def describe_stacks(stack_name)
         | 
| 142 | 
            +
                AWS.memoize do
         | 
| 143 | 
            +
                  stacks = @cloud_formation.stacks
         | 
| 144 | 
            +
                  stacks = stacks.select {|i| i.name == stack_name } if stack_name
         | 
| 145 | 
            +
             | 
| 146 | 
            +
                  stacks.map do |stack|
         | 
| 147 | 
            +
                    {
         | 
| 148 | 
            +
                      'StackName'    => stack.name,
         | 
| 149 | 
            +
                      'CreationTime' => stack.creation_time,
         | 
| 150 | 
            +
                      'StackStatus'  => stack.status,
         | 
| 151 | 
            +
                      'Description'  => stack.description,
         | 
| 152 | 
            +
                    }
         | 
| 153 | 
            +
                  end
         | 
| 154 | 
            +
                end
         | 
| 155 | 
            +
              end
         | 
| 156 | 
            +
             | 
| 157 | 
            +
              def create_stack(template, stack_name)
         | 
| 158 | 
            +
                stack_name = stack_name || 'kumogata-' + UUIDTools::UUID.timestamp_create
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                Kumogata.logger.info("Creating stack: #{stack_name}".cyan)
         | 
| 161 | 
            +
                stack = @cloud_formation.stacks.create(stack_name, template.to_json, build_create_options)
         | 
| 162 | 
            +
             | 
| 163 | 
            +
                unless while_in_progress(stack, 'CREATE_COMPLETE')
         | 
| 164 | 
            +
                  errmsgs = ['Create failed']
         | 
| 165 | 
            +
                  errmsgs << stack_name
         | 
| 166 | 
            +
                  errmsgs << sstack.tatus_reason if stack.status_reason
         | 
| 167 | 
            +
                  raise errmsgs.join(': ')
         | 
| 168 | 
            +
                end
         | 
| 169 | 
            +
             | 
| 170 | 
            +
                outputs = outputs_for(stack)
         | 
| 171 | 
            +
                summaries = resource_summaries_for(stack)
         | 
| 172 | 
            +
             | 
| 173 | 
            +
                if @options.delete_stack?
         | 
| 174 | 
            +
                  delete_stack(stack_name)
         | 
| 175 | 
            +
                end
         | 
| 176 | 
            +
             | 
| 177 | 
            +
                output_result(stack_name, outputs, summaries)
         | 
| 178 | 
            +
              end
         | 
| 179 | 
            +
             | 
| 180 | 
            +
              def update_stack(template, stack_name)
         | 
| 181 | 
            +
                stack = @cloud_formation.stacks[stack_name]
         | 
| 182 | 
            +
                stack.status
         | 
| 183 | 
            +
                stack.update(build_update_options(template.to_json))
         | 
| 184 | 
            +
             | 
| 185 | 
            +
                Kumogata.logger.info("Updating stack: #{stack_name}".green)
         | 
| 186 | 
            +
             | 
| 187 | 
            +
                unless while_in_progress(stack, 'UPDATE_COMPLETE')
         | 
| 188 | 
            +
                  errmsgs = ['Update failed']
         | 
| 189 | 
            +
                  errmsgs << stack_name
         | 
| 190 | 
            +
                  errmsgs << sstack.tatus_reason if stack.status_reason
         | 
| 191 | 
            +
                  raise errmsgs.join(': ')
         | 
| 192 | 
            +
                end
         | 
| 193 | 
            +
             | 
| 194 | 
            +
                outputs = outputs_for(stack)
         | 
| 195 | 
            +
                summaries = resource_summaries_for(stack)
         | 
| 196 | 
            +
                output_result(stack_name, outputs, summaries)
         | 
| 197 | 
            +
              end
         | 
| 198 | 
            +
             | 
| 199 | 
            +
              def delete_stack(stack_name)
         | 
| 200 | 
            +
                stack = @cloud_formation.stacks[stack_name]
         | 
| 201 | 
            +
                stack.status
         | 
| 202 | 
            +
             | 
| 203 | 
            +
                Kumogata.logger.info("Deleting stack: #{stack_name}".red)
         | 
| 204 | 
            +
                stack.delete
         | 
| 205 | 
            +
             | 
| 206 | 
            +
                completed = false
         | 
| 207 | 
            +
             | 
| 208 | 
            +
                begin
         | 
| 209 | 
            +
                  completed = while_in_progress(stack, 'DELETE_COMPLETE')
         | 
| 210 | 
            +
                rescue AWS::CloudFormation::Errors::ValidationError
         | 
| 211 | 
            +
                  # Handle `Stack does not exist`
         | 
| 212 | 
            +
                  completed = true
         | 
| 213 | 
            +
                  Kumogata.logger.info('Successfully')
         | 
| 214 | 
            +
                end
         | 
| 215 | 
            +
             | 
| 216 | 
            +
                unless completed
         | 
| 217 | 
            +
                  errmsgs = ['Delete failed']
         | 
| 218 | 
            +
                  errmsgs << stack_name
         | 
| 219 | 
            +
                  errmsgs << sstack.tatus_reason if stack.status_reason
         | 
| 220 | 
            +
                  raise errmsgs.join(': ')
         | 
| 221 | 
            +
                end
         | 
| 222 | 
            +
              end
         | 
| 223 | 
            +
             | 
| 224 | 
            +
              def while_in_progress(stack, complete_status)
         | 
| 225 | 
            +
                while stack.status =~ /_IN_PROGRESS\Z/
         | 
| 226 | 
            +
                  print '.'.intense_black unless @options.debug?
         | 
| 227 | 
            +
                  sleep 1
         | 
| 228 | 
            +
                end
         | 
| 229 | 
            +
             | 
| 230 | 
            +
                completed = (stack.status == complete_status)
         | 
| 231 | 
            +
                Kumogata.logger.info(completed ? 'Successfully' : 'Failed')
         | 
| 232 | 
            +
                return completed
         | 
| 233 | 
            +
              end
         | 
| 234 | 
            +
             | 
| 235 | 
            +
              def build_create_options
         | 
| 236 | 
            +
                opts = {}
         | 
| 237 | 
            +
                add_parameters(opts)
         | 
| 238 | 
            +
             | 
| 239 | 
            +
                [:capabilities, :disable_rollback, :notify, :timeout].each do |k|
         | 
| 240 | 
            +
                  opts[k] = @options[k] if @options[k]
         | 
| 241 | 
            +
                end
         | 
| 242 | 
            +
             | 
| 243 | 
            +
                return opts
         | 
| 244 | 
            +
              end
         | 
| 245 | 
            +
             | 
| 246 | 
            +
              def build_update_options(template)
         | 
| 247 | 
            +
                opts = {:template => template}
         | 
| 248 | 
            +
                add_parameters(opts)
         | 
| 249 | 
            +
                return opts
         | 
| 250 | 
            +
              end
         | 
| 251 | 
            +
             | 
| 252 | 
            +
              def add_parameters(hash)
         | 
| 253 | 
            +
                if @options.parameters?
         | 
| 254 | 
            +
                  parameters = {}
         | 
| 255 | 
            +
             | 
| 256 | 
            +
                  @options.parameters.each do |i|
         | 
| 257 | 
            +
                    key, value = i.split('=', 2)
         | 
| 258 | 
            +
                    parameters[key] = value
         | 
| 259 | 
            +
                  end
         | 
| 260 | 
            +
             | 
| 261 | 
            +
                  hash[:parameters] = parameters
         | 
| 262 | 
            +
                end
         | 
| 263 | 
            +
              end
         | 
| 264 | 
            +
             | 
| 265 | 
            +
              def validate_template(template)
         | 
| 266 | 
            +
                result = @cloud_formation.validate_template(template.to_json)
         | 
| 267 | 
            +
             | 
| 268 | 
            +
                if result[:code]
         | 
| 269 | 
            +
                  raise result.values_at(:code, :message).join(': ')
         | 
| 270 | 
            +
                end
         | 
| 271 | 
            +
             | 
| 272 | 
            +
                Kumogata.logger.info('Template validated successfully'.green)
         | 
| 273 | 
            +
              end
         | 
| 274 | 
            +
             | 
| 275 | 
            +
              def outputs_for(stack)
         | 
| 276 | 
            +
                outputs_hash = {}
         | 
| 277 | 
            +
             | 
| 278 | 
            +
                stack.outputs.each do |output|
         | 
| 279 | 
            +
                  outputs_hash[output.key] = output.value
         | 
| 280 | 
            +
                end
         | 
| 281 | 
            +
             | 
| 282 | 
            +
                return outputs_hash
         | 
| 283 | 
            +
              end
         | 
| 284 | 
            +
             | 
| 285 | 
            +
              def resource_summaries_for(stack)
         | 
| 286 | 
            +
                stack.resource_summaries.map do |summary|
         | 
| 287 | 
            +
                  summary_hash = {}
         | 
| 288 | 
            +
             | 
| 289 | 
            +
                  [
         | 
| 290 | 
            +
                    :logical_resource_id,
         | 
| 291 | 
            +
                    :physical_resource_id,
         | 
| 292 | 
            +
                    :resource_type,
         | 
| 293 | 
            +
                    :resource_status,
         | 
| 294 | 
            +
                    :resource_status_reason,
         | 
| 295 | 
            +
                    :last_updated_timestamp
         | 
| 296 | 
            +
                  ].each do |k|
         | 
| 297 | 
            +
                    summary_hash[k.to_s.camelcase] = summary[k]
         | 
| 298 | 
            +
                  end
         | 
| 299 | 
            +
             | 
| 300 | 
            +
                  summary_hash
         | 
| 301 | 
            +
                end
         | 
| 302 | 
            +
              end
         | 
| 303 | 
            +
             | 
| 304 | 
            +
              def output_result(stack_name, outputs, summaries)
         | 
| 305 | 
            +
                puts <<-EOS
         | 
| 306 | 
            +
             | 
| 307 | 
            +
            Outputs:
         | 
| 308 | 
            +
            #{JSON.pretty_generate(outputs)}
         | 
| 309 | 
            +
             | 
| 310 | 
            +
            Stack Resource Summaries:
         | 
| 311 | 
            +
            #{JSON.pretty_generate(summaries)}
         | 
| 312 | 
            +
             | 
| 313 | 
            +
            (Save to `#{@options.result_log}`)
         | 
| 314 | 
            +
                EOS
         | 
| 315 | 
            +
             | 
| 316 | 
            +
                open(@options.result_log, 'wb') do |f|
         | 
| 317 | 
            +
                  f.puts JSON.pretty_generate({
         | 
| 318 | 
            +
                    'StackName' => stack_name,
         | 
| 319 | 
            +
                    'Outputs' => outputs,
         | 
| 320 | 
            +
                    'StackResourceSummaries' => summaries,
         | 
| 321 | 
            +
                  })
         | 
| 322 | 
            +
                end
         | 
| 323 | 
            +
              end
         | 
| 324 | 
            +
            end
         | 
| @@ -0,0 +1,41 @@ | |
| 1 | 
            +
            require 'term/ansicolor'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            class String
         | 
| 4 | 
            +
              @@colorize = false
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              class << self
         | 
| 7 | 
            +
                def colorize=(value)
         | 
| 8 | 
            +
                  @@colorize = value
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                def colorize
         | 
| 12 | 
            +
                  @@colorize
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
              end # of class methods
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              Term::ANSIColor::Attribute.named_attributes.map do |attribute|
         | 
| 17 | 
            +
                class_eval(<<-EOS, __FILE__, __LINE__ + 1)
         | 
| 18 | 
            +
                  def #{attribute.name}
         | 
| 19 | 
            +
                    if @@colorize
         | 
| 20 | 
            +
                      Term::ANSIColor.send(#{attribute.name.inspect}, self)
         | 
| 21 | 
            +
                    else
         | 
| 22 | 
            +
                      self
         | 
| 23 | 
            +
                    end
         | 
| 24 | 
            +
                  end
         | 
| 25 | 
            +
                EOS
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              def camelcase
         | 
| 29 | 
            +
                self.split(/[-_]/).map {|str|
         | 
| 30 | 
            +
                  str[0, 1].upcase + str[1..-1].downcase
         | 
| 31 | 
            +
                }.join
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              def encode64
         | 
| 35 | 
            +
                Base64.encode64(self).delete("\n")
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              def strip_lines
         | 
| 39 | 
            +
                self.strip.split("\n").map {|i| i.strip }.join("\n")
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
            end
         | 
| @@ -0,0 +1,23 @@ | |
| 1 | 
            +
            module Kumogata
         | 
| 2 | 
            +
              def self.logger
         | 
| 3 | 
            +
                Kumogata::Logger.instance
         | 
| 4 | 
            +
              end
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              class Logger < ::Logger
         | 
| 7 | 
            +
                include Singleton
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                def initialize
         | 
| 10 | 
            +
                  super($stdout)
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  self.formatter = proc do |severity, datetime, progname, msg|
         | 
| 13 | 
            +
                    "#{msg}\n"
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  self.level = Logger::INFO
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                def set_debug(value)
         | 
| 20 | 
            +
                  self.level = value ? Logger::DEBUG : Logger::INFO
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
            end
         | 
    
        data/lib/kumogata.rb
    ADDED
    
    | @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            module Kumogata; end
         | 
| 2 | 
            +
            require 'kumogata/version'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            require 'aws-sdk'
         | 
| 5 | 
            +
            require 'base64'
         | 
| 6 | 
            +
            require 'dslh'
         | 
| 7 | 
            +
            require 'hashie'
         | 
| 8 | 
            +
            require 'highline/import'
         | 
| 9 | 
            +
            require 'json'
         | 
| 10 | 
            +
            require 'logger'
         | 
| 11 | 
            +
            require 'open-uri'
         | 
| 12 | 
            +
            require 'optparse'
         | 
| 13 | 
            +
            require 'singleton'
         | 
| 14 | 
            +
            require 'uuidtools'
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            require 'kumogata/argument_parser'
         | 
| 17 | 
            +
            require 'kumogata/client'
         | 
| 18 | 
            +
            require 'kumogata/ext/string_ext'
         | 
| 19 | 
            +
            require 'kumogata/logger'
         | 
| @@ -0,0 +1,26 @@ | |
| 1 | 
            +
            {
         | 
| 2 | 
            +
              "variables": {
         | 
| 3 | 
            +
                "aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}",
         | 
| 4 | 
            +
                "aws_secret_key": "{{env `AWS_SECRET_ACCESS_KEY`}}"
         | 
| 5 | 
            +
              },
         | 
| 6 | 
            +
              "builders": [{
         | 
| 7 | 
            +
                "type": "amazon-ebs",
         | 
| 8 | 
            +
                "ami_name": "CentOS-6.4-x86_64-with_Updates-{{timestamp}}",
         | 
| 9 | 
            +
                "access_key": "{{user `aws_access_key`}}",
         | 
| 10 | 
            +
                "secret_key": "{{user `aws_secret_key`}}",
         | 
| 11 | 
            +
                "region": "ap-northeast-1",
         | 
| 12 | 
            +
                "source_ami": "ami-31e86030",
         | 
| 13 | 
            +
                "instance_type": "t1.micro",
         | 
| 14 | 
            +
                "ssh_username": "root",
         | 
| 15 | 
            +
                "ssh_timeout": "3m"
         | 
| 16 | 
            +
              }],
         | 
| 17 | 
            +
              "provisioners": [{
         | 
| 18 | 
            +
                "type": "shell",
         | 
| 19 | 
            +
                "inline": [
         | 
| 20 | 
            +
                  "yum install -y http://ftp.iij.ad.jp/pub/linux/fedora/epel/6/i386/epel-release-6-8.noarch.rpm",
         | 
| 21 | 
            +
                  "yum install -y cloud-init",
         | 
| 22 | 
            +
                  "yum install -y https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.amzn1.noarch.rpm",
         | 
| 23 | 
            +
                  "rm -rf /root/.ssh"
         | 
| 24 | 
            +
                ]
         | 
| 25 | 
            +
              }]
         | 
| 26 | 
            +
            }
         | 
| @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            {
         | 
| 2 | 
            +
              "variables": {
         | 
| 3 | 
            +
                "aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}",
         | 
| 4 | 
            +
                "aws_secret_key": "{{env `AWS_SECRET_ACCESS_KEY`}}"
         | 
| 5 | 
            +
              },
         | 
| 6 | 
            +
              "builders": [{
         | 
| 7 | 
            +
                "type": "amazon-ebs",
         | 
| 8 | 
            +
                "ami_name": "Ubuntu-12.04.4-LTS-x86_64-ebs-{{timestamp}}",
         | 
| 9 | 
            +
                "access_key": "{{user `aws_access_key`}}",
         | 
| 10 | 
            +
                "secret_key": "{{user `aws_secret_key`}}",
         | 
| 11 | 
            +
                "region": "ap-northeast-1",
         | 
| 12 | 
            +
                "source_ami": "ami-f381f5f2",
         | 
| 13 | 
            +
                "instance_type": "t1.micro",
         | 
| 14 | 
            +
                "ssh_username": "ubuntu",
         | 
| 15 | 
            +
                "ssh_timeout": "3m"
         | 
| 16 | 
            +
              }],
         | 
| 17 | 
            +
              "provisioners": [{
         | 
| 18 | 
            +
                "type": "shell",
         | 
| 19 | 
            +
                "inline": [
         | 
| 20 | 
            +
                  "sudo apt-get -y install python-setuptools",
         | 
| 21 | 
            +
                  "wget -P /tmp https://s3.amazonaws.com/cloudformation-examples/aws-cfn-bootstrap-latest.tar.gz",
         | 
| 22 | 
            +
                  "sudo mkdir -p /tmp/aws-cfn-bootstrap-latest",
         | 
| 23 | 
            +
                  "sudo tar xvfz /tmp/aws-cfn-bootstrap-latest.tar.gz --strip-components=1 -C /tmp/aws-cfn-bootstrap-latest",
         | 
| 24 | 
            +
                  "sudo easy_install /tmp/aws-cfn-bootstrap-latest/",
         | 
| 25 | 
            +
                  "sudo rm -rf /tmp/aws-cfn-bootstrap-latest"
         | 
| 26 | 
            +
                ]
         | 
| 27 | 
            +
              }]
         | 
| 28 | 
            +
            }
         | 
| @@ -0,0 +1,96 @@ | |
| 1 | 
            +
            describe 'Kumogata::Client#convert' do
         | 
| 2 | 
            +
              it 'convert Ruby template to JSON template' do
         | 
| 3 | 
            +
                template = <<-EOS
         | 
| 4 | 
            +
            Resources do
         | 
| 5 | 
            +
              myEC2Instance do
         | 
| 6 | 
            +
                Type "AWS::EC2::Instance"
         | 
| 7 | 
            +
                Properties do
         | 
| 8 | 
            +
                  ImageId "ami-XXXXXXXX"
         | 
| 9 | 
            +
                  InstanceType "t1.micro"
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
            end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            Outputs do
         | 
| 15 | 
            +
              AZ do
         | 
| 16 | 
            +
                Value do
         | 
| 17 | 
            +
                  Fn__GetAtt "myEC2Instance", "AvailabilityZone"
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
            end
         | 
| 21 | 
            +
                EOS
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                json_template = run_client(:convert, :template => template)
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                expect(json_template).to eq((<<-EOS).chomp)
         | 
| 26 | 
            +
            {
         | 
| 27 | 
            +
              "Resources": {
         | 
| 28 | 
            +
                "myEC2Instance": {
         | 
| 29 | 
            +
                  "Type": "AWS::EC2::Instance",
         | 
| 30 | 
            +
                  "Properties": {
         | 
| 31 | 
            +
                    "ImageId": "ami-XXXXXXXX",
         | 
| 32 | 
            +
                    "InstanceType": "t1.micro"
         | 
| 33 | 
            +
                  }
         | 
| 34 | 
            +
                }
         | 
| 35 | 
            +
              },
         | 
| 36 | 
            +
              "Outputs": {
         | 
| 37 | 
            +
                "AZ": {
         | 
| 38 | 
            +
                  "Value": {
         | 
| 39 | 
            +
                    "Fn::GetAtt": [
         | 
| 40 | 
            +
                      "myEC2Instance",
         | 
| 41 | 
            +
                      "AvailabilityZone"
         | 
| 42 | 
            +
                    ]
         | 
| 43 | 
            +
                  }
         | 
| 44 | 
            +
                }
         | 
| 45 | 
            +
              }
         | 
| 46 | 
            +
            }
         | 
| 47 | 
            +
                EOS
         | 
| 48 | 
            +
              end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
              it 'convert Ruby template to JSON template' do
         | 
| 51 | 
            +
                template = <<-EOS
         | 
| 52 | 
            +
            {
         | 
| 53 | 
            +
              "Resources": {
         | 
| 54 | 
            +
                "myEC2Instance": {
         | 
| 55 | 
            +
                  "Type": "AWS::EC2::Instance",
         | 
| 56 | 
            +
                  "Properties": {
         | 
| 57 | 
            +
                    "ImageId": "ami-07f68106",
         | 
| 58 | 
            +
                    "InstanceType": "t1.micro"
         | 
| 59 | 
            +
                  }
         | 
| 60 | 
            +
                }
         | 
| 61 | 
            +
              },
         | 
| 62 | 
            +
              "Outputs": {
         | 
| 63 | 
            +
                "AZ": {
         | 
| 64 | 
            +
                  "Value": {
         | 
| 65 | 
            +
                    "Fn::GetAtt": [
         | 
| 66 | 
            +
                      "myEC2Instance",
         | 
| 67 | 
            +
                      "AvailabilityZone"
         | 
| 68 | 
            +
                    ]
         | 
| 69 | 
            +
                  }
         | 
| 70 | 
            +
                }
         | 
| 71 | 
            +
              }
         | 
| 72 | 
            +
            }
         | 
| 73 | 
            +
                EOS
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                ruby_template = run_client(:convert, :template => template, :template_ext => '.template')
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                expect(ruby_template).to eq((<<-EOS).chomp)
         | 
| 78 | 
            +
            Resources do
         | 
| 79 | 
            +
              myEC2Instance do
         | 
| 80 | 
            +
                Type "AWS::EC2::Instance"
         | 
| 81 | 
            +
                Properties do
         | 
| 82 | 
            +
                  ImageId "ami-07f68106"
         | 
| 83 | 
            +
                  InstanceType "t1.micro"
         | 
| 84 | 
            +
                end
         | 
| 85 | 
            +
              end
         | 
| 86 | 
            +
            end
         | 
| 87 | 
            +
            Outputs do
         | 
| 88 | 
            +
              AZ do
         | 
| 89 | 
            +
                Value do
         | 
| 90 | 
            +
                  Fn__GetAtt "myEC2Instance", "AvailabilityZone"
         | 
| 91 | 
            +
                end
         | 
| 92 | 
            +
              end
         | 
| 93 | 
            +
            end
         | 
| 94 | 
            +
                EOS
         | 
| 95 | 
            +
              end
         | 
| 96 | 
            +
            end
         |