class Topo::Provision::CloudFormationConverter

Constants

FIELDS

Public Instance Methods

camel_to_underscore(str) click to toggle source
# File lib/topo/converter/cloudformation/converter.rb, line 172
def camel_to_underscore(str)
  str.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    downcase
end
convert(data) click to toggle source
# File lib/topo/converter/cloudformation/converter.rb, line 28
def convert(data)
  @input = data if data
  
  @output['name'] = @input['name'] || "CloudFormation"
  
  create_provisioning

  @input['Resources'].each do |name, resource|
    convert_resource(name, resource)
  end
  
  @output
end
convert_auto_scaling_group(name, resource) click to toggle source
# File lib/topo/converter/cloudformation/converter.rb, line 135
def convert_auto_scaling_group(name, resource)
  
  node = { 
    "name" => name,
    "provisioning" => { "machine_options" => {}, "node_group" => { "auto_scaling" => {}} }       
  }
  # find asg properties
  asg_props = value_from_path(resource, %w[Properties]).clone || {}
  asg_props = fields_to_i(:auto_scaling_group, keys_to_underscore(asg_props))
  asg_props.delete("launch_configuration_name")
  asg_props.delete("load_balancer_names")
  %w[availability_zones load_balancers].each do |key|
    node["provisioning"]["node_group"]["auto_scaling"][key] = asg_props[key] if asg_props.key? key
    asg_props.delete(key)
  end 
  node["provisioning"]["node_group"]["auto_scaling"]["group_options"] = asg_props
            
  # find the launch config
  lc_name = value_from_path(resource, %w[Properties LaunchConfigurationName Ref])
  lc_props = keys_to_underscore(value_from_path(@input, ['Resources', lc_name, 'Properties'])) || {}
  lc_props = fields_to_bool(:bootstrap_options, lc_props)
  node["provisioning"]["node_group"]["auto_scaling"]["launch_configuration_options"] = lc_props
  
  # find the load balancers
  lb_refs = value_from_path(resource, %w[Properties LoadBalancerNames]) || []
  load_balancers = lb_refs.map{|lb_ref| lb_ref['Ref'] }
  # TODO should this be a topo ref instead? - needs to pick up load balancer name
  if load_balancers.length > 0
    node["provisioning"]["node_group"]["auto_scaling"]["load_balancers"] = load_balancers
  end
  
  node
  
end
convert_instance(name, resource) click to toggle source
# File lib/topo/converter/cloudformation/converter.rb, line 93
def convert_instance(name, resource)

  instance = { 
    "name" => name,
    "provisioning" => { "machine_options" => {} }
  }
    
  props = value_from_path(resource, ["Properties"]) || {}
  props = keys_to_underscore props
  props = fields_to_v1(:bootstrap_options, fields_to_bool(:bootstrap_options, props))
  
  # Need to convert object arrays (TODO helpers)
  if props["tags"]
    props["tags"].each_with_index do | tag, index | 
      props["tags"][index] = keys_to_underscore(tag) 
      STDERR.puts "WARN: Setting AWS tags on instances is not supported yet"
      instance["provisioning"]["tags"] = props["tags"]
      props.delete("tags")
    end
  end
  if props["network_interfaces"]
    props["network_interfaces"].each_with_index do | network_interface, index | 
      temp = fields_to_i(:network_interface, keys_to_underscore(network_interface))
      temp = fields_to_bool(:network_interface, temp) 
      props["network_interfaces"][index] = temp
      # if one of the network interfaces had associate_public_ip_address: true, then
      # set that in bootstrap
      if temp['associate_public_ip_address']
        props['associate_public_ip_address'] = temp['associate_public_ip_address']
      end
    end
    STDERR.puts "WARN: Setting network_interfaces on instances is not supported"
    instance["provisioning"]["network_interfaces"] = props["network_interfaces"]
    props.delete("network_interfaces")
  end
  
  instance["provisioning"]["machine_options"]["bootstrap_options"] = props
  
  instance
  
end
convert_resource(name, resource) click to toggle source

CloudFormation keys are camelcase - convert to underscore CloudFormation values are all strings - convert to proper type CloudFormation is using AWS V2, chef-provisioning-aws is using AWS V1

# File lib/topo/converter/cloudformation/converter.rb, line 71
def convert_resource(name, resource)
  
  props = value_from_path(resource, ["Properties"]) || {}
  props = keys_to_underscore props
   
  case resource['Type']
  when "AWS::EC2::Instance"
    @output['nodes'] << convert_instance(name, resource)

  when "AWS::ElasticLoadBalancing::LoadBalancer"
    listeners = value_from_path(props, ["listeners"]) || []
    props["listeners"] = listeners.map{|listener|             
      fields_to_v1(:listener, fields_to_i(:listener, keys_to_underscore(listener)))
    } 
    @output['services'] << { "name" => name, "type" => "load_balancer", 
      "provisioning" => { "load_balancer_options" => props } }

  when "AWS::AutoScaling::AutoScalingGroup"
    @output['nodes'] << convert_auto_scaling_group(name, resource)
  end
end
create_provisioning() click to toggle source
# File lib/topo/converter/cloudformation/converter.rb, line 43
def create_provisioning
  @output['provisioning'] = {'driver' => "aws", 'machine_options'=> {  }}
end
fields_to_bool(field_name, hash) click to toggle source
# File lib/topo/converter/cloudformation/converter.rb, line 197
def fields_to_bool(field_name, hash)
  FIELDS[:boolean][field_name].each do | key |
    if hash.key? key
      hash[key] = (hash[key].downcase == "true")
    end
  end
  hash
end
fields_to_i(field_name, hash) click to toggle source
# File lib/topo/converter/cloudformation/converter.rb, line 189
def fields_to_i(field_name, hash)
  FIELDS[:integer][field_name].each do | key |
    hash[key] = hash[key].to_i if hash.key? key
  end
 
  hash
end
fields_to_v1(field_name, hash) click to toggle source
# File lib/topo/converter/cloudformation/converter.rb, line 206
  def fields_to_v1(field_name, hash)
    FIELDS[:maptov1][field_name].each do | key, value |
     if hash.key? key
       hash[value] = hash[key]
       hash.delete(key)
     end
    end
   
    hash
end
keys_to_underscore(hash) click to toggle source
# File lib/topo/converter/cloudformation/converter.rb, line 178
def keys_to_underscore(hash)
  converted = Hash[hash.map{|key, val|
    if (val.kind_of? Hash)
      [ camel_to_underscore(key), keys_to_underscore(val) ]
    else
      [camel_to_underscore(key), val]
    end
  }]
end