module GClouder::Resources::Remote

FIXME: should this be split out into a separate module that deals with remote state?

Public Class Methods

instances(path: [], ignore_keys: [], skip_instances: {}, args: nil) click to toggle source
# File lib/gclouder/resources.rb, line 67
def self.instances(path: [], ignore_keys: [], skip_instances: {}, args: nil)
  resource_name = path.join(" ").to_sym

  Resource.list(resource_name, args).each_with_object({}) do |resource, collection|
    skip = false

    skip_instances.each do |key, value|
      next unless resource.key?(key)
      if resource[key] =~ value
        skip = true
        break
      end
    end

    next if skip

    # FIXME: this is so keys with partial matches work..
    file_mapping_key = path.join("::")
    file_mapping = YAML.load_file(File.join(File.dirname(__FILE__), "../../assets/mappings/file.yml")).fetch(file_mapping_key, nil)

    resource_representation_path = file_mapping.nil? ? path : file_mapping

    #ap GClouder::Config::ResourceRepresentations.properties

    # contains list of non-output-only remote properties
    resource_representation = GClouder::Config::ResourceRepresentations.section(resource_representation_path)

    #ap resource_representation

    # FIXME: partial key matches here are bad.. i.e: [compute, networks]  matches [compute, networks, subnetworks]
    # maps remote property names back to arguments
    property_mappings_key = path.join("::")
    property_mappings = YAML.load_file(File.join(File.dirname(__FILE__), "../../assets/mappings/property.yml")).fetch(property_mappings_key, [])

    # Assume global, unless we can find or infer a region...
    region = "global"
    region = resource["region"] if resource.key?("region")
    zone = resource["zone"] if !resource.key?("region") && resource.key?("zone")

    if resource.key?("selfLink") && resource["selfLink"].match(/zones\//) && !zone
      zone = resource["selfLink"].match(/zones\/([^\/]+)/)[1]
    end

    if zone
      resource["zone"] = zone
      region = zone.sub(/-[a-z]$/, "")
    end

    # 1: convert key names to snake_case
    resource = resource.to_snake_keys

    # 2: delete any keys not in resource_representations (because they're output only)
    # FIXME: warn about deleting keys?
    resource.delete_if do |key, _value|
      resource_representation[key] == "OutputOnly" && key != "name"
    end

    # 3: convert the names of any keys using the mappings file
    property_mappings.each do |argument, resource_representation|
      # FIXME: don't overwrite arguments..
      resource[argument] = resource.dig(*resource_representation)
      resource.delete(resource_representation)
    end

    ignore_keys.each do |key|
      next unless resource.key?(key)
      resource.delete(key)
    end

    # ?: if there are any keys *not* in the resource_representations file then we have a problem

    # ?: if there are any keys which dont match an argument, then we have a problem

    collection[region] ||= []
    collection[region] << resource
  end
end