1
0
Fork 0
mirror of https://github.com/fog/fog.git synced 2022-11-09 13:51:43 -05:00

Merge pull request #2460 from maestrodev/google-operations

[google] Implement operation model
This commit is contained in:
Nat Welch 2013-12-06 15:20:59 -08:00
commit 216cf26899
14 changed files with 270 additions and 43 deletions

View file

@ -29,13 +29,16 @@ module Fog
request :get_network request :get_network
request :get_zone request :get_zone
request :get_snapshot request :get_snapshot
request :get_global_operation
request :get_zone_operation
request :delete_disk request :delete_disk
request :delete_firewall request :delete_firewall
request :delete_image request :delete_image
request :delete_network request :delete_network
request :delete_operation
request :delete_server request :delete_server
request :delete_global_operation
request :delete_zone_operation
request :insert_disk request :insert_disk
request :insert_firewall request :insert_firewall
@ -59,6 +62,9 @@ module Fog
model :disk model :disk
collection :disks collection :disks
model :operation
collection :operations
model :snapshot model :snapshot
collection :snapshots collection :snapshots
@ -73,10 +79,10 @@ module Fog
@api_version = 'v1beta16' @api_version = 'v1beta16'
end end
def build_excon_response(body) def build_excon_response(body, status=200)
response = Excon::Response.new response = Excon::Response.new
response.body = body response.body = body
if response.body["error"] if response.body and response.body["error"]
response.status = response.body["error"]["code"] response.status = response.body["error"]["code"]
msg = response.body["error"]["errors"].map{|error| error["message"]}.join(", ") msg = response.body["error"]["errors"].map{|error| error["message"]}.join(", ")
case response.status case response.status
@ -86,7 +92,7 @@ module Fog
raise Fog::Errors::Error.new(msg) raise Fog::Errors::Error.new(msg)
end end
else else
response.status = 200 response.status = status
end end
response response
end end
@ -763,7 +769,8 @@ module Fog
} }
end, end,
:images => {}, :images => {},
:disks => {} :disks => {},
:operations => {}
} }
end end
end end
@ -782,6 +789,9 @@ module Fog
self.class.data(api_version).delete(@project) self.class.data(api_version).delete(@project)
end end
def random_operation
"operation-#{Fog::Mock.random_numbers(13)}-#{Fog::Mock.random_hex(13)}-#{Fog::Mock.random_hex(8)}"
end
end end
class Real class Real
@ -842,7 +852,7 @@ module Fog
# result = Google::APIClient::Result # result = Google::APIClient::Result
# returns Excon::Response # returns Excon::Response
def build_response(result) 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
end end

View file

@ -38,7 +38,13 @@ module Fog
def destroy def destroy
requires :name, :zone_name 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 end
def zone def zone

View 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

View 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

View file

@ -30,7 +30,13 @@ module Fog
def destroy def destroy
requires :name, :zone 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 end
def image def image

View file

@ -6,23 +6,26 @@ module Fog
def delete_disk(disk_name, zone_name) def delete_disk(disk_name, zone_name)
get_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", "kind" => "compute#operation",
"id" => "7145812689701515415", "id" => Fog::Mock.random_numbers(19).to_s,
"name" => "operation-1385125998242-4ebc3c7173e70-11e1ad0b", "name" => operation,
"zone" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}", "zone" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}",
"operationType" => "delete", "operationType" => "delete",
"targetLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/disks/#{disk_name}", "targetLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/disks/#{disk_name}",
"targetId" => "6817095360746367667", "targetId" => self.data[:disks][disk_name]["id"],
"status" => "PENDING", "status" => Fog::Compute::Google::Operation::PENDING_STATE,
"user" => "123456789012-qwertyuiopasdfghjkl1234567890qwe@developer.gserviceaccount.com", "user" => "123456789012-qwertyuiopasdfghjkl1234567890qwe@developer.gserviceaccount.com",
"progress" => 0, "progress" => 0,
"insertTime" => Time.now.iso8601, "insertTime" => Time.now.iso8601,
"startTime" => 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
end end

View 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

View file

@ -28,21 +28,25 @@ module Fog
server = self.data[:servers][server_name] server = self.data[:servers][server_name]
server["status"] = "STOPPED" server["status"] = "STOPPED"
server["mock-deletionTimestamp"] = Time.now.iso8601 server["mock-deletionTimestamp"] = Time.now.iso8601
build_response(:body => {
operation = self.random_operation
self.data[:operations][operation] = {
"kind" => "compute#operation", "kind" => "compute#operation",
"id" => "10035781241131638365", "id" => Fog::Mock.random_numbers(19).to_s,
"name" => "operation-1380213292196-4e74bf2fbc3c1-ae707d47", "name" => operation,
"zone" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}", "zone" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}",
"operationType" => "delete", "operationType" => "delete",
"targetLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/instances/#{server_name}", "targetLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/instances/#{server_name}",
"targetId" => "14544909043643897380", "targetId" => self.data[:servers][server_name]["id"],
"status" => "PENDING", "status" => Fog::Compute::Google::Operation::PENDING_STATE,
"user" => "123456789012-qwertyuiopasdfghjkl1234567890qwe@developer.gserviceaccount.com", "user" => "123456789012-qwertyuiopasdfghjkl1234567890qwe@developer.gserviceaccount.com",
"progress" => 0, "progress" => 0,
"insertTime" => Time.now.iso8601, "insertTime" => Time.now.iso8601,
"startTime" => 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
end end

View 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

View file

@ -4,27 +4,26 @@ module Fog
class Mock class Mock
def delete_operation(operation_name) def get_global_operation(operation)
Fog::Mock.not_implemented Fog::Mock.not_implemented
end end
end end
class Real class Real
# https://developers.google.com/compute/docs/reference/latest/globalOperations
def delete_operation(operation_name) def get_global_operation(operation)
api_method = @compute.operations.delete api_method = @compute.global_operations.get
parameters = { parameters = {
'project' => @project, 'project' => @project,
'operation' => operation_name 'operation' => operation
} }
result = self.build_result(api_method, parameters) result = self.build_result(api_method, parameters)
response = self.build_response(result) response = self.build_response(result)
end end
end end
end end
end end
end end

View 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

View file

@ -16,9 +16,10 @@ module Fog
end end
get_zone(zone_name) get_zone(zone_name)
id = Fog::Mock.random_numbers(19).to_s
self.data[:disks][disk_name] = { self.data[:disks][disk_name] = {
"kind" => "compute#disk", "kind" => "compute#disk",
"id" => Fog::Mock.random_numbers(19), "id" => id,
"creationTimestamp" => Time.now.iso8601, "creationTimestamp" => Time.now.iso8601,
"zone" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}", "zone" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}",
"status" => "READY", "status" => "READY",
@ -27,20 +28,24 @@ module Fog
"selfLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/disks/#{disk_name}" "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", "kind" => "compute#operation",
"id" => "12498846269172327286", "id" => Fog::Mock.random_numbers(19).to_s,
"name" => "operation-1385124218076-4ebc35cfbe9f1-476486c5", "name" => operation,
"zone" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}", "zone" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}",
"operationType" => "insert", "operationType" => "insert",
"targetLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/disks/#{disk_name}", "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", "user" => "123456789012-qwertyuiopasdfghjkl1234567890qwe@developer.gserviceaccount.com",
"progress" => 0, "progress" => 0,
"insertTime" => Time.now.iso8601, "insertTime" => Time.now.iso8601,
"startTime" => 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
end end

View file

@ -37,9 +37,10 @@ module Fog
end end
get_zone(zone_name) get_zone(zone_name)
id = Fog::Mock.random_numbers(19).to_s
self.data[:servers][server_name] = { self.data[:servers][server_name] = {
"kind" => "compute#instance", "kind" => "compute#instance",
"id" => Fog::Mock.random_numbers(19), "id" => id,
"creationTimestamp" => Time.now.iso8601, "creationTimestamp" => Time.now.iso8601,
"zone" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}", "zone" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}",
"status" => "PROVISIONING", "status" => "PROVISIONING",
@ -85,20 +86,24 @@ module Fog
"selfLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/instances/#{server_name}" "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", "kind" => "compute#operation",
"id" => "4639689000254420481", "id" => Fog::Mock.random_numbers(19).to_s,
"name" => "operation-1380213292196-4e74bf2fbc3c1-ae707d47", "name" => operation,
"zone" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}", "zone" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}",
"operationType" => "insert", "operationType" => "insert",
"targetLink" => "https://www.googleapis.com/compute/#{api_version}/projects/#{@project}/zones/#{zone_name}/instances/#{server_name}", "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", "user" => "123456789012-qwertyuiopasdfghjkl1234567890qwe@developer.gserviceaccount.com",
"progress" => 0, "progress" => 0,
"insertTime" => Time.now.iso8601, "insertTime" => Time.now.iso8601,
"startTime" => 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
end end

View file

@ -11,6 +11,7 @@ module Fog
end end
class Real class Real
# https://developers.google.com/compute/docs/reference/latest/zoneOperations
def list_zone_operations(zone) def list_zone_operations(zone)
api_method = @compute.zone_operations.list api_method = @compute.zone_operations.list