mirror of
https://github.com/fog/fog.git
synced 2022-11-09 13:51:43 -05:00
[google] Implement operation model
Check that server and disk destroy operation starts successfully Implement get and delete requests Handle 204 responses without body Return excon response with same status as the api returned Delete delete_operation api method that doesn't exist Add mocks for operations and use them in disk and server
This commit is contained in:
parent
a7c4ce3971
commit
8db39e3637
14 changed files with 270 additions and 43 deletions
|
@ -29,13 +29,16 @@ module Fog
|
|||
request :get_network
|
||||
request :get_zone
|
||||
request :get_snapshot
|
||||
request :get_global_operation
|
||||
request :get_zone_operation
|
||||
|
||||
request :delete_disk
|
||||
request :delete_firewall
|
||||
request :delete_image
|
||||
request :delete_network
|
||||
request :delete_operation
|
||||
request :delete_server
|
||||
request :delete_global_operation
|
||||
request :delete_zone_operation
|
||||
|
||||
request :insert_disk
|
||||
request :insert_firewall
|
||||
|
@ -59,6 +62,9 @@ module Fog
|
|||
model :disk
|
||||
collection :disks
|
||||
|
||||
model :operation
|
||||
collection :operations
|
||||
|
||||
model :snapshot
|
||||
collection :snapshots
|
||||
|
||||
|
@ -73,10 +79,10 @@ module Fog
|
|||
@api_version = 'v1beta16'
|
||||
end
|
||||
|
||||
def build_excon_response(body)
|
||||
def build_excon_response(body, status=200)
|
||||
response = Excon::Response.new
|
||||
response.body = body
|
||||
if response.body["error"]
|
||||
if response.body and response.body["error"]
|
||||
response.status = response.body["error"]["code"]
|
||||
msg = response.body["error"]["errors"].map{|error| error["message"]}.join(", ")
|
||||
case response.status
|
||||
|
@ -86,7 +92,7 @@ module Fog
|
|||
raise Fog::Errors::Error.new(msg)
|
||||
end
|
||||
else
|
||||
response.status = 200
|
||||
response.status = status
|
||||
end
|
||||
response
|
||||
end
|
||||
|
@ -763,7 +769,8 @@ module Fog
|
|||
}
|
||||
end,
|
||||
:images => {},
|
||||
:disks => {}
|
||||
:disks => {},
|
||||
:operations => {}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
@ -782,6 +789,9 @@ module Fog
|
|||
self.class.data(api_version).delete(@project)
|
||||
end
|
||||
|
||||
def random_operation
|
||||
"operation-#{Fog::Mock.random_numbers(13)}-#{Fog::Mock.random_hex(13)}-#{Fog::Mock.random_hex(8)}"
|
||||
end
|
||||
end
|
||||
|
||||
class Real
|
||||
|
@ -842,7 +852,7 @@ module Fog
|
|||
# result = Google::APIClient::Result
|
||||
# returns Excon::Response
|
||||
def build_response(result)
|
||||
build_excon_response(Fog::JSON.decode(result.body))
|
||||
build_excon_response(result.body.nil? ? nil : Fog::JSON.decode(result.body), result.status)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -38,7 +38,13 @@ module Fog
|
|||
|
||||
def destroy
|
||||
requires :name, :zone_name
|
||||
service.delete_disk(name, zone_name)
|
||||
operation = service.delete_disk(name, zone_name)
|
||||
# wait until "RUNNING" or "DONE" to ensure the operation doesn't fail, raises exception on error
|
||||
Fog.wait_for do
|
||||
operation = service.get_zone_operation(zone_name, operation.body["name"])
|
||||
operation.body["status"] != "PENDING"
|
||||
end
|
||||
operation
|
||||
end
|
||||
|
||||
def zone
|
||||
|
|
42
lib/fog/google/models/compute/operation.rb
Normal file
42
lib/fog/google/models/compute/operation.rb
Normal file
|
@ -0,0 +1,42 @@
|
|||
require 'fog/core/model'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Google
|
||||
|
||||
class Operation < Fog::Model
|
||||
|
||||
identity :name
|
||||
|
||||
attribute :kind, :aliases => 'kind'
|
||||
attribute :id, :aliases => 'id'
|
||||
attribute :creation_timestamp, :aliases => 'creationTimestamp'
|
||||
attribute :zone_name, :aliases => 'zone'
|
||||
attribute :status, :aliases => 'status'
|
||||
attribute :self_link, :aliases => 'selfLink'
|
||||
|
||||
def ready?
|
||||
self.status == DONE_STATE
|
||||
end
|
||||
|
||||
def pending?
|
||||
self.status == PENDING_STATE
|
||||
end
|
||||
|
||||
def reload
|
||||
requires :identity
|
||||
|
||||
data = collection.get(identity, zone)
|
||||
new_attributes = data.attributes
|
||||
merge_attributes(new_attributes)
|
||||
self
|
||||
end
|
||||
|
||||
PENDING_STATE = "PENDING"
|
||||
RUNNING_STATE = "RUNNING"
|
||||
DONE_STATE = "DONE"
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
26
lib/fog/google/models/compute/operations.rb
Normal file
26
lib/fog/google/models/compute/operations.rb
Normal file
|
@ -0,0 +1,26 @@
|
|||
require 'fog/core/collection'
|
||||
require 'fog/google/models/compute/operation'
|
||||
|
||||
module Fog
|
||||
module Compute
|
||||
class Google
|
||||
|
||||
class Operations < Fog::Collection
|
||||
|
||||
model Fog::Compute::Google::Operation
|
||||
|
||||
def get(identity, zone=nil)
|
||||
if zone.nil?
|
||||
response = service.get_global_operation(identity)
|
||||
else
|
||||
response = service.get_zone_operation(zone, identity)
|
||||
end
|
||||
return nil if response.nil?
|
||||
new(response.body)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
|
@ -30,7 +30,13 @@ module Fog
|
|||
|
||||
def destroy
|
||||
requires :name, :zone
|
||||
service.delete_server(name, zone)
|
||||
operation = service.delete_server(name, zone)
|
||||
# wait until "RUNNING" or "DONE" to ensure the operation doesn't fail, raises exception on error
|
||||
Fog.wait_for do
|
||||
operation = service.get_zone_operation(zone_name, operation.body["name"])
|
||||
operation.body["status"] != "PENDING"
|
||||
end
|
||||
operation
|
||||
end
|
||||
|
||||
def image
|
||||
|
|
|
@ -6,23 +6,26 @@ module Fog
|
|||
|
||||
def delete_disk(disk_name, zone_name)
|
||||
get_disk(disk_name, zone_name)
|
||||
self.data[:disks].delete disk_name
|
||||
|
||||
build_response(:body => {
|
||||
operation = self.random_operation
|
||||
self.data[:operations][operation] = {
|
||||
"kind" => "compute#operation",
|
||||
"id" => "7145812689701515415",
|
||||
"name" => "operation-1385125998242-4ebc3c7173e70-11e1ad0b",
|
||||
"id" => Fog::Mock.random_numbers(19).to_s,
|
||||
"name" => operation,
|
||||
"zone" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}",
|
||||
"operationType" => "delete",
|
||||
"targetLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/disks/#{disk_name}",
|
||||
"targetId" => "6817095360746367667",
|
||||
"status" => "PENDING",
|
||||
"targetId" => self.data[:disks][disk_name]["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-1385125998242-4ebc3c7173e70-11e1ad0b"
|
||||
})
|
||||
"selfLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/operations/#{operation}"
|
||||
}
|
||||
self.data[:disks].delete disk_name
|
||||
|
||||
build_response(:body => self.data[:operations][operation])
|
||||
end
|
||||
|
||||
end
|
||||
|
|
29
lib/fog/google/requests/compute/delete_global_operation.rb
Normal file
29
lib/fog/google/requests/compute/delete_global_operation.rb
Normal file
|
@ -0,0 +1,29 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class Google
|
||||
|
||||
class Mock
|
||||
|
||||
def delete_global_operation(operation)
|
||||
Fog::Mock.not_implemented
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Real
|
||||
# https://developers.google.com/compute/docs/reference/latest/globalOperations
|
||||
|
||||
def delete_global_operation(operation)
|
||||
api_method = @compute.global_operations.delete
|
||||
parameters = {
|
||||
'project' => @project,
|
||||
'operation' => operation
|
||||
}
|
||||
|
||||
result = self.build_result(api_method, parameters)
|
||||
response = self.build_response(result)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -28,21 +28,25 @@ module Fog
|
|||
server = self.data[:servers][server_name]
|
||||
server["status"] = "STOPPED"
|
||||
server["mock-deletionTimestamp"] = Time.now.iso8601
|
||||
build_response(:body => {
|
||||
|
||||
operation = self.random_operation
|
||||
self.data[:operations][operation] = {
|
||||
"kind" => "compute#operation",
|
||||
"id" => "10035781241131638365",
|
||||
"name" => "operation-1380213292196-4e74bf2fbc3c1-ae707d47",
|
||||
"id" => Fog::Mock.random_numbers(19).to_s,
|
||||
"name" => operation,
|
||||
"zone" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}",
|
||||
"operationType" => "delete",
|
||||
"targetLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/instances/#{server_name}",
|
||||
"targetId" => "14544909043643897380",
|
||||
"status" => "PENDING",
|
||||
"targetId" => self.data[:servers][server_name]["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-1380213292196-4e74bf2fbc3c1-ae707d47"
|
||||
})
|
||||
"selfLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/operations/#{operation}"
|
||||
}
|
||||
|
||||
build_response(:body => self.data[:operations][operation])
|
||||
end
|
||||
|
||||
end
|
||||
|
|
33
lib/fog/google/requests/compute/delete_zone_operation.rb
Normal file
33
lib/fog/google/requests/compute/delete_zone_operation.rb
Normal file
|
@ -0,0 +1,33 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class Google
|
||||
|
||||
class Mock
|
||||
|
||||
def delete_zone_operation(zone, operation)
|
||||
Fog::Mock.not_implemented
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Real
|
||||
# https://developers.google.com/compute/docs/reference/latest/zoneOperations
|
||||
|
||||
def delete_zone_operation(zone_name, operation)
|
||||
if zone_name.start_with? 'http'
|
||||
zone_name = zone_name.split('/')[-1]
|
||||
end
|
||||
api_method = @compute.zone_operations.delete
|
||||
parameters = {
|
||||
'project' => @project,
|
||||
'zone' => zone_name,
|
||||
'operation' => operation
|
||||
}
|
||||
|
||||
result = self.build_result(api_method, parameters)
|
||||
response = self.build_response(result)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -4,27 +4,26 @@ module Fog
|
|||
|
||||
class Mock
|
||||
|
||||
def delete_operation(operation_name)
|
||||
def get_global_operation(operation)
|
||||
Fog::Mock.not_implemented
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class Real
|
||||
# https://developers.google.com/compute/docs/reference/latest/globalOperations
|
||||
|
||||
def delete_operation(operation_name)
|
||||
api_method = @compute.operations.delete
|
||||
def get_global_operation(operation)
|
||||
api_method = @compute.global_operations.get
|
||||
parameters = {
|
||||
'project' => @project,
|
||||
'operation' => operation_name
|
||||
'operation' => operation
|
||||
}
|
||||
|
||||
result = self.build_result(api_method, parameters)
|
||||
response = self.build_response(result)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
58
lib/fog/google/requests/compute/get_zone_operation.rb
Normal file
58
lib/fog/google/requests/compute/get_zone_operation.rb
Normal file
|
@ -0,0 +1,58 @@
|
|||
module Fog
|
||||
module Compute
|
||||
class Google
|
||||
|
||||
class Mock
|
||||
|
||||
def get_zone_operation(zone_name, operation)
|
||||
operation = self.data[:operations][operation]
|
||||
if operation
|
||||
case operation["status"]
|
||||
when Fog::Compute::Google::Operation::PENDING_STATE
|
||||
operation["status"] = Fog::Compute::Google::Operation::RUNNING_STATE
|
||||
operation["progress"] = 50
|
||||
else
|
||||
operation["status"] = Fog::Compute::Google::Operation::DONE_STATE
|
||||
operation["progress"] = 100
|
||||
end
|
||||
else
|
||||
operation = {
|
||||
"error" => {
|
||||
"errors" => [
|
||||
{
|
||||
"domain" => "global",
|
||||
"reason" => "notFound",
|
||||
"message" => "The resource 'projects/#{project}/zones/#{zone_name}/operations/#{operation}' was not found"
|
||||
}
|
||||
],
|
||||
"code" => 404,
|
||||
"message" => "The resource 'projects/#{project}/zones/#{zone_name}/operations/#{operation}' was not found"
|
||||
}
|
||||
}
|
||||
end
|
||||
build_response(:body => operation)
|
||||
end
|
||||
end
|
||||
|
||||
class Real
|
||||
# https://developers.google.com/compute/docs/reference/latest/zoneOperations
|
||||
|
||||
def get_zone_operation(zone_name, operation)
|
||||
if zone_name.start_with? 'http'
|
||||
zone_name = zone_name.split('/')[-1]
|
||||
end
|
||||
|
||||
api_method = @compute.zone_operations.get
|
||||
parameters = {
|
||||
'project' => @project,
|
||||
'zone' => zone_name,
|
||||
'operation' => operation
|
||||
}
|
||||
|
||||
result = self.build_result(api_method, parameters)
|
||||
response = self.build_response(result)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -16,9 +16,10 @@ module Fog
|
|||
end
|
||||
get_zone(zone_name)
|
||||
|
||||
id = Fog::Mock.random_numbers(19).to_s
|
||||
self.data[:disks][disk_name] = {
|
||||
"kind" => "compute#disk",
|
||||
"id" => Fog::Mock.random_numbers(19),
|
||||
"id" => id,
|
||||
"creationTimestamp" => Time.now.iso8601,
|
||||
"zone" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}",
|
||||
"status" => "READY",
|
||||
|
@ -27,20 +28,24 @@ module Fog
|
|||
"selfLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/disks/#{disk_name}"
|
||||
}
|
||||
|
||||
build_response(:body => {
|
||||
operation = self.random_operation
|
||||
self.data[:operations][operation] = {
|
||||
"kind" => "compute#operation",
|
||||
"id" => "12498846269172327286",
|
||||
"name" => "operation-1385124218076-4ebc35cfbe9f1-476486c5",
|
||||
"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}/disks/#{disk_name}",
|
||||
"status" => "PENDING",
|
||||
"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-1385124218076-4ebc35cfbe9f1-476486c5"
|
||||
})
|
||||
"selfLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/operations/#{operation}"
|
||||
}
|
||||
|
||||
build_response(:body => self.data[:operations][operation])
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -37,9 +37,10 @@ module Fog
|
|||
end
|
||||
get_zone(zone_name)
|
||||
|
||||
id = Fog::Mock.random_numbers(19).to_s
|
||||
self.data[:servers][server_name] = {
|
||||
"kind" => "compute#instance",
|
||||
"id" => Fog::Mock.random_numbers(19),
|
||||
"id" => id,
|
||||
"creationTimestamp" => Time.now.iso8601,
|
||||
"zone" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}",
|
||||
"status" => "PROVISIONING",
|
||||
|
@ -85,20 +86,24 @@ module Fog
|
|||
"selfLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/instances/#{server_name}"
|
||||
}
|
||||
|
||||
build_response(:body => {
|
||||
operation = self.random_operation
|
||||
self.data[:operations][operation] = {
|
||||
"kind" => "compute#operation",
|
||||
"id" => "4639689000254420481",
|
||||
"name" => "operation-1380213292196-4e74bf2fbc3c1-ae707d47",
|
||||
"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}",
|
||||
"status" => "PENDING",
|
||||
"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-1380213292196-4e74bf2fbc3c1-ae707d47"
|
||||
})
|
||||
"selfLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/operations/#{operation}"
|
||||
}
|
||||
|
||||
build_response(:body => self.data[:operations][operation])
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -11,6 +11,7 @@ module Fog
|
|||
end
|
||||
|
||||
class Real
|
||||
# https://developers.google.com/compute/docs/reference/latest/zoneOperations
|
||||
|
||||
def list_zone_operations(zone)
|
||||
api_method = @compute.zone_operations.list
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue