deltacloud-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From <di...@fast.au.fujitsu.com>
Subject [PATCH] CIMI: system and system_template support for mock driver, with unit tests. Just GET for now, no subcollections
Date Tue, 19 Feb 2013 02:59:49 GMT
From: Dies Koper <diesk@fast.au.fujitsu.com>

---
 server/lib/cimi/collections/system_templates.rb    |  72 ++++++++
 server/lib/cimi/collections/systems.rb             | 198 +++++++++++++++++++++
 server/lib/cimi/models.rb                          |   2 +
 server/lib/cimi/models/system.rb                   |  68 +++++++
 server/lib/cimi/models/system_template.rb          |  64 +++++++
 .../drivers/mock/data/cimi/system/system1.json     |  12 ++
 .../drivers/mock/data/cimi/system/system2.json     |  12 ++
 .../mock/data/cimi/system_template/template1.json  |  28 +++
 .../drivers/mock/mock_driver_cimi_methods.rb       |  31 ++++
 .../cimi/collections/system_templates_test.rb      | 124 +++++++++++++
 server/tests/cimi/collections/systems_test.rb      | 124 +++++++++++++
 11 files changed, 735 insertions(+)
 create mode 100644 server/lib/cimi/collections/system_templates.rb
 create mode 100644 server/lib/cimi/collections/systems.rb
 create mode 100644 server/lib/cimi/models/system.rb
 create mode 100644 server/lib/cimi/models/system_template.rb
 create mode 100644 server/lib/deltacloud/drivers/mock/data/cimi/system/system1.json
 create mode 100644 server/lib/deltacloud/drivers/mock/data/cimi/system/system2.json
 create mode 100644 server/lib/deltacloud/drivers/mock/data/cimi/system_template/template1.json
 create mode 100644 server/tests/cimi/collections/system_templates_test.rb
 create mode 100644 server/tests/cimi/collections/systems_test.rb

diff --git a/server/lib/cimi/collections/system_templates.rb b/server/lib/cimi/collections/system_templates.rb
new file mode 100644
index 0000000..88fbe30
--- /dev/null
+++ b/server/lib/cimi/collections/system_templates.rb
@@ -0,0 +1,72 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class SystemTemplates < Base
+
+    set :capability, lambda { |t| true }
+
+    collection :system_templates do
+
+      operation :index do
+        description "List all system templates"
+        control do
+          system_templates = CIMI::Model::SystemTemplate.list(self).select_by(params['$select'])
+          respond_to do |format|
+            format.xml { system_templates.to_xml }
+            format.json { system_templates.to_json }
+          end
+        end
+      end
+
+      operation :show do
+        description "Show specific system template"
+        control do
+          system_template = CIMI::Model::SystemTemplate.find(params[:id], self)
+          respond_to do |format|
+            format.xml { system_template.to_xml }
+            format.json { system_template.to_json }
+          end
+        end
+      end
+
+      operation :create do
+        description "Create new system template"
+        control do
+          if grab_content_type(request.content_type, request.body) == :json
+            new_system_template = CIMI::Model::SystemTemplate.create_from_json(request.body.read,
self)
+          else
+            new_system_template = CIMI::Model::SystemTemplate.create_from_xml(request.body.read,
self)
+          end
+          headers_for_create new_system_template
+          respond_to do |format|
+            format.json { new_system_template.to_json }
+            format.xml { new_system_template.to_xml }
+          end
+        end
+      end
+
+      operation :destroy do
+        description "Delete a specified system template"
+        control do
+          CIMI::Model::SystemTemplate.delete!(params[:id], self)
+          no_content_with_status(200)
+        end
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/cimi/collections/systems.rb b/server/lib/cimi/collections/systems.rb
new file mode 100644
index 0000000..42fbd06
--- /dev/null
+++ b/server/lib/cimi/collections/systems.rb
@@ -0,0 +1,198 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+module CIMI::Collections
+  class Systems < Base
+
+    set :capability, lambda { |m| driver.respond_to? m }
+
+    collection :systems do
+      description 'List all systems'
+
+      operation :index, :with_capability => :systems do
+        description "List all systems"
+        control do
+          systems = System.list(self).select_by(params['$select']).filter_by(params['$filter'])
+          respond_to do |format|
+            format.xml { systems.to_xml }
+            format.json { systems.to_json }
+          end
+        end
+      end
+
+      operation :show, :with_capability => :systems do
+        description "Show specific system."
+        control do
+          system = System.find(params[:id], self)
+          respond_to do |format|
+            format.xml { system.to_xml }
+            format.json { system.to_json }
+          end
+        end
+      end
+
+      operation :create, :with_capability => :create_system do
+        description "Create a new System entity."
+        control do
+          if grab_content_type(request.content_type, request.body) == :json
+            new_system = System.create_from_json(request.body.read, self)
+          else
+            new_system = System.create_from_xml(request.body.read, self)
+          end
+          headers_for_create new_system
+          respond_to do |format|
+            format.json { new_system.to_json }
+            format.xml { new_system.to_xml }
+          end
+        end
+      end
+
+      operation :destroy, :with_capability => :destroy_system do
+        description "Delete a specified system."
+        control do
+          System.delete!(params[:id], self)
+          no_content_with_status(200)
+        end
+      end
+
+      action :stop, :with_capability => :stop_system do
+        description "Stop specific system."
+        param :id,          :string,    :required
+        control do
+          system = System.find(params[:id], self)
+          if grab_content_type(request.content_type, request.body) == :json
+            action = Action.from_json(request.body.read)
+          else
+            action = Action.from_xml(request.body.read)
+          end
+          system.perform(action, self) do |operation|
+            no_content_with_status(202) if operation.success?
+            # Handle errors using operation.failure?
+          end
+        end
+      end
+
+      action :restart, :with_capability => :reboot_system do
+        description "Restart specific system."
+        param :id,          :string,    :required
+        control do
+          system = System.find(params[:id], self)
+          if  grab_content_type(request.content_type, request.body) == :json
+            action = Action.from_json(request.body.read.gsub("restart", "reboot"))
+          else
+            action = Action.from_xml(request.body.read.gsub("restart", "reboot"))
+          end
+          system.perform(action, self) do |operation|
+            no_content_with_status(202) if operation.success?
+            # Handle errors using operation.failure?
+          end
+        end
+      end
+
+      action :start, :with_capability => :start_system do
+        description "Start specific system."
+        param :id,          :string,    :required
+        control do
+          system = System.find(params[:id], self)
+          if  grab_content_type(request.content_type, request.body) == :json
+            action = Action.from_json(request.body.read)
+          else
+            action = Action.from_xml(request.body.read)
+          end
+          system.perform(action, self) do |operation|
+            no_content_with_status(202) if operation.success?
+            # Handle errors using operation.failure?
+          end
+        end
+      end
+
+      action :pause, :with_capability => :pause_system do
+        description "Pause specific system."
+        param :id,          :string,    :required
+        control do
+          system = System.find(params[:id], self)
+          if  grab_content_type(request.content_type, request.body) == :json
+            action = Action.from_json(request.body.read)
+          else
+            action = Action.from_xml(request.body.read)
+          end
+          system.perform(action, self) do |operation|
+            no_content_with_status(202) if operation.success?
+            # Handle errors using operation.failure?
+          end
+        end
+      end
+
+      action :suspend, :with_capability => :suspend_system do
+        description "Suspend specific system."
+        param :id,          :string,    :required
+        control do
+          system = System.find(params[:id], self)
+          if  grab_content_type(request.content_type, request.body) == :json
+            action = Action.from_json(request.body.read)
+          else
+            action = Action.from_xml(request.body.read)
+          end
+          system.perform(action, self) do |operation|
+            no_content_with_status(202) if operation.success?
+            # Handle errors using operation.failure?
+          end
+        end
+      end
+
+      #use rabbit subcollections for volumes index/show:
+      collection :volumes, :with_id => :vol_id do
+
+        operation :index, :with_capability => :storage_volumes do
+          description "Retrieve the System's SystemVolumeCollection"
+          control do
+            volumes = CIMI::Model::SystemVolume.collection_for_system(params[:id], self)
+            respond_to do |format|
+              format.json {volumes.to_json}
+              format.xml  {volumes.to_xml}
+            end
+          end
+        end
+
+        operation :show, :with_capability => :storage_volumes do
+          description "Retrieve a System's specific SystemVolume"
+          control do
+            volume = CIMI::Model::SystemVolume.find(params[:id], self, params[:vol_id])
+            respond_to do |format|
+              format.json {volume.to_json}
+              format.xml  {volume.to_xml}
+            end
+          end
+        end
+
+        operation :destroy, :with_capability => :detach_storage_volume do
+          description "Remove/detach a volume from the System's SystemVolumeCollection"
+          control do
+            system_volume = CIMI::Model::SystemVolume.find(params[:id], self, params[:vol_id])
+            location = system_volume.initial_location
+            system_volumes = System.detach_volume(params[:vol_id], location, self)
+            respond_to do |format|
+              format.json{ system_volumes.to_json}
+              format.xml{ system_volumes.to_xml}
+            end
+          end
+        end
+
+      end
+
+    end
+
+  end
+end
diff --git a/server/lib/cimi/models.rb b/server/lib/cimi/models.rb
index 39beae4..c48b531 100644
--- a/server/lib/cimi/models.rb
+++ b/server/lib/cimi/models.rb
@@ -79,3 +79,5 @@ require_relative './models/address'
 require_relative './models/address_template'
 require_relative './models/forwarding_group'
 require_relative './models/forwarding_group_template'
+require_relative './models/system_template'
+require_relative './models/system'
diff --git a/server/lib/cimi/models/system.rb b/server/lib/cimi/models/system.rb
new file mode 100644
index 0000000..c2b94db
--- /dev/null
+++ b/server/lib/cimi/models/system.rb
@@ -0,0 +1,68 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::System < CIMI::Model::Base
+
+  acts_as_root_entity
+
+  text :state
+
+#  collection :systems, :class => CIMI::Model::SystemSystem
+#  collection :machines, :class => CIMI::Model::SystemMachine
+#  collection :credentials, :class => CIMI::Model::SystemCredential
+#  collection :volumes, :class => CIMI::Model::SystemVolume
+#  collection :networks, :class => CIMI::Model::SystemNetwork
+#  collection :network_ports, :class => CIMI::Model::SystemNetworkPort
+#  collection :addresses, :class => CIMI::Model::SystemAddress
+#  collection :forwarding_groups, :class => CIMI::Model::SystemForwardingGroup
+
+#  array :meters do
+#    scalar :href
+#  end
+
+#  href :event_log
+
+  array :operations do
+    scalar :rel, :href
+  end
+
+  def self.find(id, context)
+    systems = []
+    if id == :all
+      systems = context.driver.systems(context.credentials, {:env=>context})
+    else
+      system = context.driver.systems(context.credentials, {:env=>context, :id=>id})
+      raise CIMI::Model::NotFound unless system
+      system
+    end
+  end
+
+  def perform(action, context, &block)
+    begin
+      if context.driver.send(:"#{action.name}_system", context.credentials, self.id.split("/").last)
+        block.callback :success
+      else
+        raise "Operation failed to execute on given System"
+      end
+    rescue => e
+      block.callback :failure, e.message
+    end
+  end
+
+  def self.delete!(id, context)
+    context.driver.destroy_system(context.credentials, id)
+  end
+
+end
diff --git a/server/lib/cimi/models/system_template.rb b/server/lib/cimi/models/system_template.rb
new file mode 100644
index 0000000..b98119a
--- /dev/null
+++ b/server/lib/cimi/models/system_template.rb
@@ -0,0 +1,64 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+class CIMI::Model::SystemTemplate < CIMI::Model::Base
+
+  acts_as_root_entity
+
+  array :component_descriptors do
+    text :name, :description
+    hash :properties
+    text :type
+    #component_template, comprises:
+#    struct :machine_template, :class => CIMI::Model::MachineTemplate
+#    struct :system_template, :class => CIMI::Model::SystemTemplate
+#    struct :credential_template, :class => CIMI::Model::CredentialTemplate
+#    struct :volume_template, :class => CIMI::Model::VolumeTemplate
+#    struct :network_template, :class => CIMI::Model::NetworkTemplate
+#    struct :network_port_template, :class => CIMI::Model::NetworkPortTemplate
+#    struct :forwarding_group_template, :class => CIMI::Model::ForwardingGroupTemplate
+#    struct :address_template, :class => CIMI::Model::AddressTemplate
+    text :quantity
+  end
+
+#  array :meter_templates do
+#    scalar :href
+#  end
+
+#  href :event_log_template
+ 
+  array :operations do
+    scalar :rel, :href
+  end
+
+  class << self
+    def find(id, context)
+      templates = []
+      if id == :all
+        templates = context.driver.system_templates(context.credentials, {:env=>context})
+      else
+        template = context.driver.system_templates(context.credentials, {:env=>context,
:id=>id})
+        raise CIMI::Model::NotFound unless template
+        template
+      end
+    end
+
+    def delete!(id, context)
+      context.driver.destroy_system_template(context.credentials, id)
+    end
+
+  end
+
+end
diff --git a/server/lib/deltacloud/drivers/mock/data/cimi/system/system1.json b/server/lib/deltacloud/drivers/mock/data/cimi/system/system1.json
new file mode 100644
index 0000000..689ba60
--- /dev/null
+++ b/server/lib/deltacloud/drivers/mock/data/cimi/system/system1.json
@@ -0,0 +1,12 @@
+{ "id": "http://cimi.example.org/systems/system1",
+  "name": "system1",
+  "description": "the first system",
+  "created": "Fri Feb 08 15:25:41 EET 2013",
+  "state": "STOPPED",
+  "machines": { "href": "http://cimi.example.org/systems/system1/machines"},
+  "networks": { "href": "http://cimi.example.org/systems/system1/networks"},
+  "operations": [
+    { "rel": "edit", "href": "http://cimi.example.org/systems/system1" },
+    { "rel": "delete", "href": "http://cimi.example.org/systems/system1" }
+  ]
+}
diff --git a/server/lib/deltacloud/drivers/mock/data/cimi/system/system2.json b/server/lib/deltacloud/drivers/mock/data/cimi/system/system2.json
new file mode 100644
index 0000000..4062fb0
--- /dev/null
+++ b/server/lib/deltacloud/drivers/mock/data/cimi/system/system2.json
@@ -0,0 +1,12 @@
+{ "id": "http://cimi.example.org/systems/system2",
+  "name": "system2",
+  "description": "the second system",
+  "created": "Fri Feb 08 15:25:41 EET 2013",
+  "state": "STOPPED",
+  "machines": { "href": "http://cimi.example.org/systems/system2/machines"},
+  "networks": { "href": "http://cimi.example.org/systems/system2/networks"},
+  "operations": [
+    { "rel": "edit", "href": "http://cimi.example.org/systems/system2" },
+    { "rel": "delete", "href": "http://cimi.example.org/systems/system2" }
+  ]
+}
diff --git a/server/lib/deltacloud/drivers/mock/data/cimi/system_template/template1.json b/server/lib/deltacloud/drivers/mock/data/cimi/system_template/template1.json
new file mode 100644
index 0000000..495fc24
--- /dev/null
+++ b/server/lib/deltacloud/drivers/mock/data/cimi/system_template/template1.json
@@ -0,0 +1,28 @@
+{ "id": "http://cimi.example.org/system_templates/template1",
+  "name": "template1",
+  "description": "A mock system template",
+  "created": "Fri Feb 08 12:15:15 EET 2013",
+  "componentDescriptors": [
+    { "name": "my machine",
+      "type": "http://schemas.dmtf.org/cimi/1/Machine",
+      "description": "an inline mock machine template",
+      "machineTemplate": {
+        "name": "machine in mock system",
+        "description": "machine in system",
+        "machineConfig": { "href": "http://example.com/configs/m1-small" },
+        "machineImage": { "href": "http://example.com/images/img1" }
+      }
+    },
+    { "name": "my network",
+      "type": "http://schemas.dmtf.org/cimi/1/Network",
+      "description": "a reference to an existing mock network template",
+      "networkTemplate": {
+        "href": "http://cimi.example.org/network_templates/template1"
+      }
+    }
+  ],
+  "operations": [
+    { "rel": "edit", "href": "http://cimi.example.org/system_templates/template1" },
+    { "rel": "delete", "href": "http://cimi.example.org/system_templates/template1" }
+  ]
+}
diff --git a/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb b/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb
index 336f77b..7be1aea 100644
--- a/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb
+++ b/server/lib/deltacloud/drivers/mock/mock_driver_cimi_methods.rb
@@ -20,6 +20,37 @@
 module Deltacloud::Drivers::Mock
 
   class MockDriver < Deltacloud::BaseDriver
+
+    def systems(credentials, opts={})
+      check_credentials(credentials)
+      if opts[:id].nil?
+        systems = @client.load_all_cimi(:system).map{|sys| CIMI::Model::System.from_json(sys)}
+        systems.map{|sys|convert_cimi_mock_urls(:system, sys ,opts[:env])}.flatten
+      else
+        begin
+          system = CIMI::Model::System.from_json(@client.load_cimi(:system, opts[:id]))
+          convert_cimi_mock_urls(:system, system, opts[:env])
+        rescue Errno::ENOENT
+          nil
+        end
+      end
+    end
+
+    def system_templates(credentials, opts={})
+      check_credentials(credentials)
+      if opts[:id].nil?
+        system_templates = @client.load_all_cimi(:system_template).map{|sys_templ| CIMI::Model::SystemTemplate.from_json(sys_templ)}
+        system_templates.map{|sys_templ|convert_cimi_mock_urls(:system_template, sys_templ,
opts[:env])}.flatten
+      else
+        begin
+          system_template = CIMI::Model::SystemTemplate.from_json(@client.load_cimi(:system_template,
opts[:id]))
+          convert_cimi_mock_urls(:system_template, system_template, opts[:env])
+        rescue Errno::ENOENT
+          nil
+        end
+      end
+    end
+
     def networks(credentials, opts={})
       check_credentials(credentials)
       if opts[:id].nil?
diff --git a/server/tests/cimi/collections/system_templates_test.rb b/server/tests/cimi/collections/system_templates_test.rb
new file mode 100644
index 0000000..a4727ef
--- /dev/null
+++ b/server/tests/cimi/collections/system_templates_test.rb
@@ -0,0 +1,124 @@
+require 'rubygems'
+require 'require_relative' if RUBY_VERSION < '1.9'
+require 'minitest/autorun'
+require_relative './common.rb'
+
+describe CIMI::Collections::SystemTemplates do
+
+  before do
+    def app; run_frontend(:cimi) end
+    authorize 'mockuser', 'mockpassword'
+    @collection = CIMI::Collections.collection(:system_templates)
+  end
+
+  it 'has index operation' do
+    @collection.operation(:index).must_equal Sinatra::Rabbit::SystemTemplatesCollection::IndexOperation
+  end
+
+  it 'has show operation' do
+    @collection.operation(:show).must_equal Sinatra::Rabbit::SystemTemplatesCollection::ShowOperation
+  end
+
+  it 'returns list of system templates in various formats with index operation' do
+    formats.each do |format|
+      header 'Accept', format
+      get root_url + '/system_templates'
+      status.must_equal 200
+    end
+  end
+
+  it 'should allow to retrieve the single system template' do
+    get root_url '/system_templates/template1'
+    status.must_equal 200
+    xml.root.name.must_equal 'SystemTemplate'
+  end
+
+  describe "$expand" do
+    def system_template(*expand)
+      url = '/system_templates/template1'
+      url += "?$expand=#{expand.join(",")}" unless expand.empty?
+      get root_url url
+      status.must_equal 200
+    end
+
+    def ids(coll)
+      xml.xpath("/c:SystemTemplate/c:#{coll}/c:id", NS)
+    end
+
+    it "should not expand collections when missing" do
+      system_template
+#      ids(:networks).must_be_empty
+#      ids(:system_templates).must_be_empty
+#      ids(:volumes).must_be_empty
+    end
+
+    it "should expand named collections" do
+      system_template :machines
+#      ids(:machines).size.must_equal 1
+#      ids(:volumes).must_be_empty
+    end
+
+    it "should expand multiple named collections" do
+      system_template :machines, :volumes
+#      ids(:machines).size.must_equal 1
+#      ids(:volumes).size.must_equal 1
+    end
+
+    it "should expand all collections with *" do
+      system_template "*"
+#      ids(:machines).size.must_equal 1
+#      ids(:volumes).size.must_equal 1
+#      ids(:networks).size.must_equal 1
+    end
+  end
+
+  describe '$filter' do
+
+    it 'should filter collection by name attribute' do
+      get root_url("/system_templates?$filter=name='template1'")
+      status.must_equal 200
+      (xml/'Collection/SystemTemplate').wont_be_empty
+      (xml/'Collection/SystemTemplate').size.must_equal 1
+      xml.at('Collection/count').text.must_equal '1'
+      xml.at('Collection/SystemTemplate/name').text.must_equal 'template1'
+    end
+
+    it 'should filter collection by reverse name attribute' do
+      get root_url("/system_templates?$filter=name!='template1'")
+      status.must_equal 200
+      (xml/'Collection/SystemTemplate').wont_be_empty
+      (xml/'Collection/SystemTemplate').size.must_equal 1
+      xml.at('Collection/count').text.must_equal '1'
+      xml.at('Collection/SystemTemplate/name').text.must_equal 'template1'
+    end
+
+  end
+
+  describe '$select' do
+
+    it 'should return only selected attribute' do
+      get root_url('/system_templates?$select=name')
+      status.must_equal 200
+      (xml/'Collection/SystemTemplate/name').wont_be_empty
+      (xml/'Collection/SystemTemplate/name').first.text.wont_be_empty
+      xml.xpath("/c:Collection/c:SystemTemplate/*[not(self::c:name)]", NS).must_be_empty
+    end
+
+    it 'should support multiple selected attributes' do
+      get root_url('/system_templates?$select=name,description')
+      status.must_equal 200
+      (xml/'Collection/SystemTemplate/name').wont_be_empty
+      (xml/'Collection/SystemTemplate/name').first.text.wont_be_empty
+      (xml/'Collection/SystemTemplate/description').wont_be_empty
+      (xml/'Collection/SystemTemplate/description').first.text.wont_be_empty
+      xml.xpath("/c:Collection/c:SystemTemplate/*[not(self::c:name) and not(self::c:description)]",
NS).must_be_empty
+    end
+
+  end
+
+  it 'should not return non-existing system_template' do
+    get root_url '/system_templates/unknown-system_template'
+    status.must_equal 404
+  end
+
+end
diff --git a/server/tests/cimi/collections/systems_test.rb b/server/tests/cimi/collections/systems_test.rb
new file mode 100644
index 0000000..8496a99
--- /dev/null
+++ b/server/tests/cimi/collections/systems_test.rb
@@ -0,0 +1,124 @@
+require 'rubygems'
+require 'require_relative' if RUBY_VERSION < '1.9'
+require 'minitest/autorun'
+require_relative './common.rb'
+
+describe CIMI::Collections::Systems do
+
+  before do
+    def app; run_frontend(:cimi) end
+    authorize 'mockuser', 'mockpassword'
+    @collection = CIMI::Collections.collection(:systems)
+  end
+
+  it 'has index operation' do
+    @collection.operation(:index).must_equal Sinatra::Rabbit::SystemsCollection::IndexOperation
+  end
+
+  it 'has show operation' do
+    @collection.operation(:show).must_equal Sinatra::Rabbit::SystemsCollection::ShowOperation
+  end
+
+  it 'returns list of systems in various formats with index operation' do
+    formats.each do |format|
+      header 'Accept', format
+      get root_url + '/systems'
+      status.must_equal 200
+    end
+  end
+
+  it 'should allow to retrieve the single system' do
+    get root_url '/systems/system1'
+    status.must_equal 200
+    xml.root.name.must_equal 'System'
+  end
+
+  describe "$expand" do
+    def system(*expand)
+      url = '/systems/system1'
+      url += "?$expand=#{expand.join(",")}" unless expand.empty?
+      get root_url url
+      status.must_equal 200
+    end
+
+    def ids(coll)
+      xml.xpath("/c:System/c:#{coll}/c:id", NS)
+    end
+
+    it "should not expand collections when missing" do
+      system
+#      ids(:networks).must_be_empty
+#      ids(:systems).must_be_empty
+#      ids(:volumes).must_be_empty
+    end
+
+    it "should expand named collections" do
+      system :machines
+#      ids(:machines).size.must_equal 1
+#      ids(:volumes).must_be_empty
+    end
+
+    it "should expand multiple named collections" do
+      system :machines, :volumes
+#      ids(:machines).size.must_equal 1
+#      ids(:volumes).size.must_equal 1
+    end
+
+    it "should expand all collections with *" do
+      system "*"
+#      ids(:machines).size.must_equal 1
+#      ids(:volumes).size.must_equal 1
+#      ids(:networks).size.must_equal 1
+    end
+  end
+
+  describe '$filter' do
+
+    it 'should filter collection by name attribute' do
+      get root_url("/systems?$filter=name='system1'")
+      status.must_equal 200
+      (xml/'Collection/System').wont_be_empty
+      (xml/'Collection/System').size.must_equal 1
+      xml.at('Collection/count').text.must_equal '1'
+      xml.at('Collection/System/name').text.must_equal 'system1'
+    end
+
+    it 'should filter collection by reverse name attribute' do
+      get root_url("/systems?$filter=name!='system1'")
+      status.must_equal 200
+      (xml/'Collection/System').wont_be_empty
+      (xml/'Collection/System').size.must_equal 1
+      xml.at('Collection/count').text.must_equal '1'
+      xml.at('Collection/System/name').text.must_equal 'system2'
+    end
+
+  end
+
+  describe '$select' do
+
+    it 'should return only selected attribute' do
+      get root_url('/systems?$select=name')
+      status.must_equal 200
+      (xml/'Collection/System/name').wont_be_empty
+      (xml/'Collection/System/name').first.text.wont_be_empty
+      xml.xpath("/c:Collection/c:System/*[not(self::c:name)]", NS).must_be_empty
+    end
+
+    it 'should support multiple selected attributes' do
+      get root_url('/systems?$select=name,description')
+      status.must_equal 200
+      (xml/'Collection/System/name').wont_be_empty
+      (xml/'Collection/System/name').first.text.wont_be_empty
+      (xml/'Collection/System/description').wont_be_empty
+      (xml/'Collection/System/description').first.text.wont_be_empty
+      xml.xpath("/c:Collection/c:System/*[not(self::c:name) and not(self::c:description)]",
NS).must_be_empty
+    end
+
+  end
+
+  it 'should not return non-existing system' do
+    get root_url '/systems/unknown-system'
+    status.must_equal 404
+  end
+
+end
-- 
1.8.0.msysgit.0



Mime
View raw message