module Fog module Compute class Google class Mock include Shared def handle_disks(options, zone_name) disks = [] i = 0 options.delete("disks").each do |disk| disk = Disk.new(disk) unless disk.is_a? Disk disks << { "kind" => "compute#attachedDisk", "index" => i, "type" => "PERSISTENT", "mode" => "READ_WRITE", "source" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/disks/#{disk.name}", "deviceName" => "persistent-disk-#{i}", "boot" => true } i += 1 end disks end def insert_server(server_name, zone_name, options = {}, *_deprecated_args) # check that zone exists get_zone(zone_name) if options["disks"].nil? || options["disks"].empty? raise ArgumentError.new "Empty value for field 'disks'. Boot disk must be specified" end id = Fog::Mock.random_numbers(19).to_s data[:servers][server_name] = { "kind" => "compute#instance", "id" => id, "creationTimestamp" => Time.now.iso8601, "zone" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}", "status" => "PROVISIONING", "name" => server_name, "tags" => { "fingerprint" => "42WmSpB8rSM=" }, "machineType" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/machineTypes/#{options['machineType']}", "canIpForward" => false, "networkInterfaces" => [ { "network" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/global/networks/default", "networkIP" => Fog::Mock.random_ip, "name" => "nic0", "accessConfigs" => [ { "kind" => "compute#accessConfig", "type" => "ONE_TO_ONE_NAT", "name" => "External NAT", "natIP" => Fog::Mock.random_ip } ] } ], "disks" => handle_disks(options, zone_name), "metadata" => { "kind" => "compute#metadata", "fingerprint" => "5_hasd_gC3E=", "items" => [ { "key" => "sshKeys", "value" => "sysadmin:ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAgEA1zc7mx+0H8Roywet/L0aVX6MUdkDfzd/17kZhprAbpUXYOILv9AG4lIzQk6xGxDIltghytjfVGme/4A42Sb0Z9LN0pxB4KnWTNoOSHPJtp6jbXpq6PdN9r3Z5NKQg0A/Tfw7gt2N0GDsj6vpK8VbHHdW78JAVUxql18ootJxjaksdocsiHNK8iA6/v9qiLRhX3fOgtK7KpxxdZxLRzFg9vkp8jcGISgpZt27kOgXWhR5YLhi8pRJookzphO5O4yhflgoHoAE65XkfrsRCe0HU5QTbY2jH88rBVkq0KVlZh/lEsuwfmG4d77kEqaCGGro+j1Wrvo2K3DSQ+rEcvPp2CYRUySjhaeLF18UzQLtxNeoN14QOYqlm9ITdkCnmq5w4Wn007MjSOFp8LEq2RekrnddGXjg1/vgmXtaVSGzJAlXwtVfZor3dTRmF0JCpr7DsiupBaDFtLUlGFFlSKmPDVMPOOB5wajexmcvSp2Vu4U3yP8Lai/9/ZxMdsGPhpdCsWVL83B5tF4oYj1HVIycbYIxIIfFqOxZcCru3CMfe9jmzKgKLv2UtkfOS8jpS/Os2gAiB3wPweH3agvtwYAYBVMDwt5cnrhgHYWoOz7ABD8KgmCrD7Y9HikiCqIUNkgUFd9YmjcYi5FkU5rFXIawN7efs341lsdf923lsdf923fs= johndoe@acme" } ] }, "selfLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/instances/#{server_name}" } operation = random_operation data[:operations][operation] = { "kind" => "compute#operation", "id" => Fog::Mock.random_numbers(19).to_s, "name" => operation, "zone" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}", "operationType" => "insert", "targetLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/instances/#{server_name}", "targetId" => id, "status" => Fog::Compute::Google::Operation::PENDING_STATE, "user" => "123456789012-qwertyuiopasdfghjkl1234567890qwe@developer.gserviceaccount.com", "progress" => 0, "insertTime" => Time.now.iso8601, "startTime" => Time.now.iso8601, "selfLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/operations/#{operation}" } build_excon_response(data[:operations][operation]) end end class Real include Shared def handle_disks(options) disks = [] # An array of persistent disks. You must supply a boot disk as the first disk in # this array and mark it as a boot disk using the disks[].boot property. options.delete("disks").each do |disk| if disk.is_a? Disk disks << disk.get_object else disks << disk end end disks.first["boot"] = true disks end def format_metadata(metadata) { "items" => metadata.map { |k, v| { "key" => k, "value" => v } } } end def insert_server(server_name, zone_name, options = {}, *deprecated_args) if deprecated_args.length > 0 || !options.is_a?(Hash) raise ArgumentError.new "Too many parameters specified. This may be the cause of code written for an outdated"\ " version of fog. Usage: server_name, zone_name, [options]" end api_method = @compute.instances.insert parameters = { "project" => @project, "zone" => zone_name } body_object = { :name => server_name } body_object["machineType"] = @api_url + @project + "/zones/#{zone_name}/machineTypes/#{options.delete 'machineType'}" network = nil if options.key? "network" network = options.delete "network" else network = GOOGLE_COMPUTE_DEFAULT_NETWORK end # ExternalIP is default value for server creation access_config = { "type" => "ONE_TO_ONE_NAT", "name" => "External NAT" } # leave natIP undefined to use an IP from a shared ephemeral IP address pool if options.key? "externalIp" access_config["natIP"] = options.delete "externalIp" # If set to 'false', that would mean user does no want to allocate an external IP access_config = nil if access_config["natIP"] == false end networkInterfaces = [] unless network.nil? networkInterface = { "network" => @api_url + @project + "/global/networks/#{network}" } networkInterface["accessConfigs"] = [access_config] if access_config networkInterfaces << networkInterface end scheduling = { "automaticRestart" => false, "onHostMaintenance" => "MIGRATE", "preemptible" => false } if options.key? "auto_restart" scheduling["automaticRestart"] = options.delete "auto_restart" scheduling["automaticRestart"] = scheduling["automaticRestart"].class == TrueClass end if options.key? "preemptible" scheduling["preemptible"] = options.delete "preemptible" scheduling["preemptible"] = scheduling["preemptible"].class == TrueClass # If we don't have an explicit value for "on_host_maintenance, then # force the value to be 'TERMINATE' as it's the default and # only-accepted value for preemptible vms scheduling["onHostMaintenance"] = "TERMINATE" unless options.key? "on_host_maintenance" end if options.key? "on_host_maintenance" ohm = options.delete "on_host_maintenance" scheduling["onHostMaintenance"] = (ohm.respond_to?("upcase") && ohm.upcase == "MIGRATE" && "MIGRATE") || "TERMINATE" end body_object["scheduling"] = scheduling # @see https://developers.google.com/compute/docs/networking#canipforward if options.key? "can_ip_forward" body_object["canIpForward"] = options.delete "can_ip_forward" end # TODO: add other networks body_object["networkInterfaces"] = networkInterfaces if options["disks"].nil? || options["disks"].empty? raise ArgumentError.new "Empty value for field 'disks'. Boot disk must be specified" end body_object["disks"] = handle_disks(options) options["metadata"] = format_metadata options["metadata"] if options["metadata"] body_object["tags"] = { "items" => options.delete("tags") } if options["tags"] body_object.merge!(options) # Adds in all remaining options that weren't explicitly handled. request(api_method, parameters, body_object = body_object) end end end end end