From 7ba02fbe679cafbf9aaade96a6f57ba1121b332b Mon Sep 17 00:00:00 2001 From: Nick Osborn Date: Mon, 14 Oct 2013 23:34:34 +0100 Subject: [PATCH] [vcloud_director] Add general queries handler. --- lib/fog/vcloud_director/compute.rb | 1 + .../requests/compute/get_execute_query.rb | 460 ++++++++++++++++++ .../requests/compute/query_tests.rb | 34 ++ 3 files changed, 495 insertions(+) create mode 100644 lib/fog/vcloud_director/requests/compute/get_execute_query.rb create mode 100644 tests/vcloud_director/requests/compute/query_tests.rb diff --git a/lib/fog/vcloud_director/compute.rb b/lib/fog/vcloud_director/compute.rb index 7b2f0a8cb..4433aabc1 100644 --- a/lib/fog/vcloud_director/compute.rb +++ b/lib/fog/vcloud_director/compute.rb @@ -109,6 +109,7 @@ module Fog request :get_disks_rasd_items_list request :get_edge_gateway request :get_entity + request :get_execute_query request :get_groups_from_query request :get_guest_customization_system_section_vapp request :get_guest_customization_system_section_vapp_template diff --git a/lib/fog/vcloud_director/requests/compute/get_execute_query.rb b/lib/fog/vcloud_director/requests/compute/get_execute_query.rb new file mode 100644 index 000000000..5f48e4cb7 --- /dev/null +++ b/lib/fog/vcloud_director/requests/compute/get_execute_query.rb @@ -0,0 +1,460 @@ +module Fog + module Compute + class VcloudDirector + class Real + # REST API General queries handler. + # + # @param [String] type The type of the query. Type names are + # case-sensitive. You can retrieve a summary list of all typed + # queries types accessible to the currently authenticated user by + # making a request with type=nil. + # @param [Hash] options + # @option options [String] :sortAsc (Sorted by database ID) Sort + # results by attribute-name in ascending order. attribute-name cannot + # include metadata. + # @option options [String] :sortDesc (Sorted by database ID) Sort + # results by attribute-name in descending order. attribute-name + # cannot include metadata. + # @option options [Integer] :page (1) If the query results span + # multiple pages, return this page. + # @option options [Integer] :pageSize (25) Number of results per page, + # to a maximum of 128. + # @option options [String] :format (records) One of the following + # types: + # - *references* Returns a reference to each object, including its + # :name, :type, and :href attributes. + # - *records* Returns all database records for each object, with each + # record as an attribute. + # - *idrecords* Identical to the records format, except that object + # references are returned in :id format rather than :href format. + # @option options [Array] :fields (all static attribute names) + # List of attribute names or metadata key names to return. + # @option options [Integer] :offset (0) Integer value specifying the + # first record to return. Record numbers < offset are not returned. + # @option options [String] :filter (none) Filter expression. + # @return [Excon::Response] if type is specified. + # * hash<~Hash>: + # * :href<~String> - The URI of the entity. + # * :type<~String> - The MIME type of the entity. + # * :name<~String> - Query name that generated this result set. + # * :page<~String> - Page of the result set that this container + # holds. The first page is page number 1. + # * :pageSize<~String> - Page size, as a number of records or + # references. + # * :total<~String> - Total number of records or references in the + # container. + # * :Link<~Array>: + # * :href<~String> - Contains the URI to the entity. + # * :type<~String> - Contains the type of the entity. + # * :rel<~String> - Defines the relationship of the link to the + # object that contains it. + # * :Record<~Array> - The name and content of this item + # varies according to the type and format of the query. + # * :firstPage<~Integer> - First page in the result set. + # * :previousPage<~Integer> - Previous page in the result set. + # * :nextPage<~Integer> - Next page in the result set. + # * :lastPage<~Integer> - Last page in the result set. + # @return [Excon::Response] if type is nil. + # * hash<~Hash>: + # * :href<~String> - The URI of the entity. + # * :type<~String> - The MIME type of the entity. + # * :Link<~Array>: + # * :href<~String> - Contains the URI to the entity. + # * :name<~String> - Contains the name of the entity. + # * :type<~String> - Contains the type of the entity. + # * :rel<~String> - Defines the relationship of the link to the + # object that contains it. + # + # @see http://pubs.vmware.com/vcd-55/topic/com.vmware.vcloud.api.reference.doc_55/doc/operations/GET-ExecuteQuery.html + # @since vCloud API version 1.5 + def get_execute_query(type=nil, options={}) + if type.nil? + response = request( + :expects => 200, + :idempotent => true, + :method => 'GET', + :parser => Fog::ToHashDocument.new, + :path => 'query' + ) + else + query = ["type=#{type}"] + query << "sortAsc=#{options[:sortAsc]}" if options[:sortAsc] + query << "sortDesc=#{options[:sortDesc]}" if options[:sortDesc] + query << "page=#{options[:page]}" if options[:page] + query << "pageSize=#{options[:pageSize]}" if options[:pageSize] + query << "format=#{options[:format]}" if options[:format] + query << "fields=#{Array(options[:fields]).join(',')}" if options[:fields] + query << "offset=#{options[:offset]}" if options[:offset] + query << "filter=#{options[:filter]}" if options[:filter] + + response = request( + :expects => 200, + :idempotent => true, + :method => 'GET', + :parser => Fog::ToHashDocument.new, + :path => 'query', + :query => query.map {|q| URI.escape(q)}.join('&') + ) + response.body[:Link] = [response.body[:Link]] if response.body[:Link].is_a?(Hash) + record = "#{response.body[:name]}Record".to_sym + response.body[record] ||= [] + response.body[record] = [response.body[record]] if response.body[record].is_a?(Hash) + + %w[firstPage previousPage nextPage lastPage].each do |rel| + if link = response.body[:Link].detect {|l| l[:rel] == rel} + href = Nokogiri::XML.fragment(link[:href]) + query = CGI.parse(URI.parse(href.text).query) + response.body[rel.to_sym] = query['page'].first.to_i + response.body[:pageSize] ||= query['pageSize'].first.to_i + end + end + + response + end + end + end + + class Mock + def get_execute_query(type=nil, options={}) + if type.nil? + body = + {:xmlns=>xmlns, + :xmlns_xsi=>xmlns_xsi, + :type=>"application/vnd.vmware.vcloud.query.queryList+xml", + :href=>make_href('query'), + :xsi_schemaLocation=>xsi_schema_location, + :Link=> + [{:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"organization", + :href=>make_href('query?type=organization&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"organization", + :href=>make_href('query?type=organization&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"organization", + :href=>make_href('query?type=organization&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"orgVdc", + :href=>make_href('query?type=orgVdc&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"orgVdc", + :href=>make_href('query?type=orgVdc&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"orgVdc", + :href=>make_href('query?type=orgVdc&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"media", + :href=>make_href('query?type=media&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"media", + :href=>make_href('query?type=media&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"media", + :href=>make_href('query?type=media&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"vAppTemplate", + :href=>make_href('query?type=vAppTemplate&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"vAppTemplate", + :href=>make_href('query?type=vAppTemplate&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"vAppTemplate", + :href=>make_href('query?type=vAppTemplate&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"vApp", + :href=>make_href('query?type=vApp&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"vApp", + :href=>make_href('query?type=vApp&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"vApp", + :href=>make_href('query?type=vApp&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"vm", + :href=>make_href('query?type=vm&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"vm", + :href=>make_href('query?type=vm&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"vm", + :href=>make_href('query?type=vm&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"orgNetwork", + :href=>make_href('query?type=orgNetwork&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"orgNetwork", + :href=>make_href('query?type=orgNetwork&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"orgNetwork", + :href=>make_href('query?type=orgNetwork&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"vAppNetwork", + :href=>make_href('query?type=vAppNetwork&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"vAppNetwork", + :href=>make_href('query?type=vAppNetwork&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"vAppNetwork", + :href=>make_href('query?type=vAppNetwork&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"catalog", + :href=>make_href('query?type=catalog&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"catalog", + :href=>make_href('query?type=catalog&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"catalog", + :href=>make_href('query?type=catalog&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"group", + :href=>make_href('query?type=group&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"group", + :href=>make_href('query?type=group&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"group", + :href=>make_href('query?type=group&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"user", + :href=>make_href('query?type=user&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"user", + :href=>make_href('query?type=user&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"user", + :href=>make_href('query?type=user&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"strandedUser", + :href=>make_href('query?type=strandedUser&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"strandedUser", + :href=>make_href('query?type=strandedUser&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"strandedUser", + :href=>make_href('query?type=strandedUser&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"role", + :href=>make_href('query?type=role&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"role", + :href=>make_href('query?type=role&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"role", + :href=>make_href('query?type=role&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"allocatedExternalAddress", + :href=>make_href('query?type=allocatedExternalAddress&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"allocatedExternalAddress", + :href=>make_href('query?type=allocatedExternalAddress&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"event", + :href=>make_href('query?type=event&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"event", + :href=>make_href('query?type=event&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"right", + :href=>make_href('query?type=right&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"right", + :href=>make_href('query?type=right&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"right", + :href=>make_href('query?type=right&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"vAppOrgNetworkRelation", + :href=>make_href('query?type=vAppOrgNetworkRelation&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"vAppOrgNetworkRelation", + :href=>make_href('query?type=vAppOrgNetworkRelation&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"vAppOrgNetworkRelation", + :href=>make_href('query?type=vAppOrgNetworkRelation&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"catalogItem", + :href=>make_href('query?type=catalogItem&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"catalogItem", + :href=>make_href('query?type=catalogItem&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"catalogItem", + :href=>make_href('query?type=catalogItem&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"task", + :href=>make_href('query?type=task&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"task", + :href=>make_href('query?type=task&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"task", + :href=>make_href('query?type=task&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"disk", + :href=>make_href('query?type=disk&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"disk", + :href=>make_href('query?type=disk&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"disk", + :href=>make_href('query?type=disk&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"vmDiskRelation", + :href=>make_href('query?type=vmDiskRelation&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"vmDiskRelation", + :href=>make_href('query?type=vmDiskRelation&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"service", + :href=>make_href('query?type=service&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"service", + :href=>make_href('query?type=service&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"service", + :href=>make_href('query?type=service&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"orgVdcStorageProfile", + :href=>make_href('query?type=orgVdcStorageProfile&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"orgVdcStorageProfile", + :href=>make_href('query?type=orgVdcStorageProfile&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"orgVdcStorageProfile", + :href=>make_href('query?type=orgVdcStorageProfile&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"apiDefinition", + :href=>make_href('query?type=apiDefinition&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"apiDefinition", + :href=>make_href('query?type=apiDefinition&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"apiDefinition", + :href=>make_href('query?type=apiDefinition&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"fileDescriptor", + :href=>make_href('query?type=fileDescriptor&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"fileDescriptor", + :href=>make_href('query?type=fileDescriptor&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"edgeGateway", + :href=>make_href('query?type=edgeGateway&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"edgeGateway", + :href=>make_href('query?type=edgeGateway&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"edgeGateway", + :href=>make_href('query?type=edgeGateway&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"orgVdcNetwork", + :href=>make_href('query?type=orgVdcNetwork&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"orgVdcNetwork", + :href=>make_href('query?type=orgVdcNetwork&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"orgVdcNetwork", + :href=>make_href('query?type=orgVdcNetwork&format=idrecords')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.references+xml", + :name=>"vAppOrgVdcNetworkRelation", + :href=>make_href('query?type=vAppOrgVdcNetworkRelation&format=references')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.records+xml", + :name=>"vAppOrgVdcNetworkRelation", + :href=>make_href('query?type=vAppOrgVdcNetworkRelation&format=records')}, + {:rel=>"down", + :type=>"application/vnd.vmware.vcloud.query.idrecords+xml", + :name=>"vAppOrgVdcNetworkRelation", + :href=>make_href('query?type=vAppOrgVdcNetworkRelation&format=idrecords')}]} + + Excon::Response.new( + :status => 200, + :headers => {'Content-Type' => "#{body[:type]};version=#{api_version}"}, + :body => body + ) + else + Fog::Mock.not_implemented + end + end + end + end + end +end diff --git a/tests/vcloud_director/requests/compute/query_tests.rb b/tests/vcloud_director/requests/compute/query_tests.rb new file mode 100644 index 000000000..3e9e7ead0 --- /dev/null +++ b/tests/vcloud_director/requests/compute/query_tests.rb @@ -0,0 +1,34 @@ +Shindo.tests('Compute::VcloudDirector | query requests', ['vclouddirector']) do + + @service = Fog::Compute::VcloudDirector.new + + tests('retrieve a summary list of all typed queries types') do + tests('#get_execute_query') do + @query_list = @service.get_execute_query.body + tests(':type').returns('application/vnd.vmware.vcloud.query.queryList+xml') do + @query_list[:type] + end + end + end + + pending if Fog.mocking? + + @query_list[:Link].select do |link| + link[:rel] == 'down' + end.sort_by do |link| + [link[:name], link[:href]] + end.each do |link| + href = Nokogiri::XML.fragment(link[:href]) + query = CGI.parse(URI.parse(href.text).query) + type = query['type'].first + format = query['format'].first + next if %w[right role strandedUser].include?(type) + tests("type => #{type}, format => #{format}") do + tests("#get_execute_query").data_matches_schema(VcloudDirector::Compute::Schema::CONTAINER_TYPE) do + @body = @service.get_execute_query(type, :format => format).body + end + tests("resource type").returns(link[:type]) { @body[:type] } + end + end + +end