From: Martyn Taylor mtaylor@redhat.com
This will help separate the warehouse and factory models --- lib/aeolus_image.rb | 21 +-- lib/aeolus_image/model/image.rb | 91 ---------- lib/aeolus_image/model/image_build.rb | 68 -------- lib/aeolus_image/model/provider_image.rb | 46 ----- lib/aeolus_image/model/target_image.rb | 56 ------ lib/aeolus_image/model/template.rb | 29 --- lib/aeolus_image/model/warehouse/image.rb | 93 ++++++++++ lib/aeolus_image/model/warehouse/image_build.rb | 70 ++++++++ lib/aeolus_image/model/warehouse/provider_image.rb | 48 +++++ lib/aeolus_image/model/warehouse/target_image.rb | 58 +++++++ lib/aeolus_image/model/warehouse/template.rb | 31 ++++ .../model/warehouse/warehouse_client.rb | 178 +++++++++++++++++++ .../model/warehouse/warehouse_model.rb | 162 ++++++++++++++++++ lib/aeolus_image/model/warehouse_client.rb | 180 -------------------- lib/aeolus_image/model/warehouse_model.rb | 162 ------------------ 15 files changed, 647 insertions(+), 646 deletions(-) delete mode 100644 lib/aeolus_image/model/image.rb delete mode 100644 lib/aeolus_image/model/image_build.rb delete mode 100644 lib/aeolus_image/model/provider_image.rb delete mode 100644 lib/aeolus_image/model/target_image.rb delete mode 100644 lib/aeolus_image/model/template.rb create mode 100644 lib/aeolus_image/model/warehouse/image.rb create mode 100644 lib/aeolus_image/model/warehouse/image_build.rb create mode 100644 lib/aeolus_image/model/warehouse/provider_image.rb create mode 100644 lib/aeolus_image/model/warehouse/target_image.rb create mode 100644 lib/aeolus_image/model/warehouse/template.rb create mode 100644 lib/aeolus_image/model/warehouse/warehouse_client.rb create mode 100644 lib/aeolus_image/model/warehouse/warehouse_model.rb delete mode 100644 lib/aeolus_image/model/warehouse_client.rb delete mode 100644 lib/aeolus_image/model/warehouse_model.rb
diff --git a/lib/aeolus_image.rb b/lib/aeolus_image.rb index f17ed66..ce23933 100644 --- a/lib/aeolus_image.rb +++ b/lib/aeolus_image.rb @@ -14,17 +14,10 @@
require 'optparse' require 'logger' -require File.join(File.dirname(__FILE__), 'aeolus_image/command', 'base_command') -require File.join(File.dirname(__FILE__), 'aeolus_image/command', 'list_command') -require File.join(File.dirname(__FILE__), 'aeolus_image/command', 'build_command') -require File.join(File.dirname(__FILE__), 'aeolus_image/command', 'push_command') -require File.join(File.dirname(__FILE__), 'aeolus_image/command', 'import_command') -require File.join(File.dirname(__FILE__), 'aeolus_image/command', 'delete_command') -require File.join(File.dirname(__FILE__), 'aeolus_image/command', 'config_parser') -require File.join(File.dirname(__FILE__), 'aeolus_image/model', 'warehouse_client') # Not sure we need this -require File.join(File.dirname(__FILE__), 'aeolus_image/model', 'warehouse_model') # We may be able to factor this out? -require File.join(File.dirname(__FILE__), 'aeolus_image/model', 'image') -require File.join(File.dirname(__FILE__), 'aeolus_image/model', 'image_build') -require File.join(File.dirname(__FILE__), 'aeolus_image/model', 'provider_image') -require File.join(File.dirname(__FILE__), 'aeolus_image/model', 'target_image') -require File.join(File.dirname(__FILE__), 'aeolus_image/model', 'template') +require File.join(File.dirname(__FILE__), 'aeolus_image/model/warehouse', 'warehouse_client') # Not sure we need this +require File.join(File.dirname(__FILE__), 'aeolus_image/model/warehouse', 'warehouse_model') # We may be able to factor this out? +require File.join(File.dirname(__FILE__), 'aeolus_image/model/warehouse', 'image') +require File.join(File.dirname(__FILE__), 'aeolus_image/model/warehouse', 'image_build') +require File.join(File.dirname(__FILE__), 'aeolus_image/model/warehouse', 'provider_image') +require File.join(File.dirname(__FILE__), 'aeolus_image/model/warehouse', 'target_image') +require File.join(File.dirname(__FILE__), 'aeolus_image/model/warehouse', 'template') diff --git a/lib/aeolus_image/model/image.rb b/lib/aeolus_image/model/image.rb deleted file mode 100644 index 73b004e..0000000 --- a/lib/aeolus_image/model/image.rb +++ /dev/null @@ -1,91 +0,0 @@ -# Copyright 2011 Red Hat, Inc. -# -# Licensed 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 Aeolus - module Image - class Image < WarehouseModel - OS = Struct.new(:name, :version, :arch) - - @bucket_name = 'images' - - def initialize(attrs) - attrs.each do |k,v| - if k.to_sym == :latest_build - sym = :attr_writer - else - sym = :attr_accessor - end - self.class.send(sym, k.to_sym) unless respond_to?(:"#{k}=") - send(:"#{k}=", v) - end - @xml_body = Nokogiri::XML @body - end - - def template_xml - unless @template_xml - begin - @template_xml = Nokogiri::XML image_builds.first.target_images.first.target_template.body - rescue - @template_xml = Nokogiri::XML "<template></template>" - end - end - @template_xml - end - - def latest_pushed_build - ImageBuild.find(@latest_build) if @latest_build - end - - def image_builds - ImageBuild.find_all_by_image_uuid(@uuid) - end - - #TODO: We should get the image fields from the object body once we have it defined. - def name - unless @name - @name = @xml_body.xpath("/image/name").text - if @name.empty? - @name = template_xml.xpath("/template/name").text - end - end - @name - end - - def os - unless @os - @os = OS.new(template_xml.xpath("/template/os/name").text, template_xml.xpath("/template/os/version").text, template_xml.xpath("/template/os/arch").text) - end - @os - end - - def description - unless @description - @description = template_xml.xpath("/template/description").text - end - @description - end - - # Delete this image and all child objects - def delete! - begin - image_builds.each do |build| - build.delete! - end - rescue NoMethodError - end - Image.delete(@uuid) - end - end - end -end diff --git a/lib/aeolus_image/model/image_build.rb b/lib/aeolus_image/model/image_build.rb deleted file mode 100644 index b751117..0000000 --- a/lib/aeolus_image/model/image_build.rb +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2011 Red Hat, Inc. -# -# Licensed 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 Aeolus - module Image - class ImageBuild < WarehouseModel - @bucket_name = 'builds' - - def initialize(attrs) - attrs.each do |k,v| - if k.to_sym == :image - sym = :attr_writer - else - sym = :attr_accessor - end - self.class.send(sym, k.to_sym) unless respond_to?(:"#{k}=") - send(:"#{k}=", v) - end - end - - def self.find_all_by_image_uuid(uuid) - self.set_warehouse_and_bucket if self.bucket.nil? - self.bucket.objects.map do |wh_object| - if wh_object.attr('image') == uuid - ImageBuild.new(wh_object.attrs(wh_object.attr_list)) - end - end.compact - end - - def image - Image.find(@image) if @image - end - - def target_images - TargetImage.all.select {|ti| ti.build and (ti.build.uuid == self.uuid)} - end - - def provider_images - targets = target_images - ProviderImage.all.select do |pi| - targets.include?(pi.target_image) - end - end - - # Deletes this image and all child objects - def delete! - begin - target_images.each do |ti| - ti.delete! - end - rescue NoMethodError - end - ImageBuild.delete(@uuid) - end - end - end -end diff --git a/lib/aeolus_image/model/provider_image.rb b/lib/aeolus_image/model/provider_image.rb deleted file mode 100644 index a5f319d..0000000 --- a/lib/aeolus_image/model/provider_image.rb +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2011 Red Hat, Inc. -# -# Licensed 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 Aeolus - module Image - class ProviderImage < WarehouseModel - @bucket_name = 'provider_images' - - def initialize(attrs) - attrs.each do |k,v| - if [:provider, :target_image].include?(k.to_sym) - sym = :attr_writer - else - sym = :attr_accessor - end - self.class.send(sym, k.to_sym) unless respond_to?(:"#{k}=") - send(:"#{k}=", v) - end - end - - def target_image - TargetImage.find(@target_image) if @target_image - end - - def provider_name - @provider - end - - # Deletes this provider image - def delete! - ProviderImage.delete(@uuid) - end - end - end -end diff --git a/lib/aeolus_image/model/target_image.rb b/lib/aeolus_image/model/target_image.rb deleted file mode 100644 index c029430..0000000 --- a/lib/aeolus_image/model/target_image.rb +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright 2011 Red Hat, Inc. -# -# Licensed 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 Aeolus - module Image - class TargetImage < WarehouseModel - @bucket_name = 'target_images' - - def initialize(attrs) - attrs.each do |k,v| - if k.to_sym == :build - sym = :attr_writer - else - sym = :attr_accessor - end - self.class.send(sym, k.to_sym) unless respond_to?(:"#{k}=") - send(:"#{k}=", v) - end - end - - def build - ImageBuild.find(@build) if @build - end - - def provider_images - ProviderImage.all.select{|pi| pi.target_image and (pi.target_image.uuid == self.uuid)} - end - - def target_template - Template.find(@template) if @template - end - - # Deletes this targetimage and all child objects - def delete! - begin - provider_images.each do |pi| - pi.delete! - end - rescue NoMethodError - end - TargetImage.delete(@uuid) - end - end - end -end diff --git a/lib/aeolus_image/model/template.rb b/lib/aeolus_image/model/template.rb deleted file mode 100644 index e1ac3cb..0000000 --- a/lib/aeolus_image/model/template.rb +++ /dev/null @@ -1,29 +0,0 @@ -# Copyright 2011 Red Hat, Inc. -# -# Licensed 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 Aeolus - module Image - class Template < WarehouseModel - @bucket_name = 'templates' - - def initialize(attrs) - attrs.each do |k,v| - sym = :attr_accessor - self.class.send(sym, k.to_sym) unless respond_to?(:"#{k}=") - send(:"#{k}=", v) - end - end - end - end -end diff --git a/lib/aeolus_image/model/warehouse/image.rb b/lib/aeolus_image/model/warehouse/image.rb new file mode 100644 index 0000000..7a7a4f3 --- /dev/null +++ b/lib/aeolus_image/model/warehouse/image.rb @@ -0,0 +1,93 @@ +# Copyright 2011 Red Hat, Inc. +# +# Licensed 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 Aeolus + module Image + module Warehouse + class Image < WarehouseModel + OS = Struct.new(:name, :version, :arch) + + @bucket_name = 'images' + + def initialize(attrs) + attrs.each do |k,v| + if k.to_sym == :latest_build + sym = :attr_writer + else + sym = :attr_accessor + end + self.class.send(sym, k.to_sym) unless respond_to?(:"#{k}=") + send(:"#{k}=", v) + end + @xml_body = Nokogiri::XML @body + end + + def template_xml + unless @template_xml + begin + @template_xml = Nokogiri::XML image_builds.first.target_images.first.target_template.body + rescue + @template_xml = Nokogiri::XML "<template></template>" + end + end + @template_xml + end + + def latest_pushed_build + ImageBuild.find(@latest_build) if @latest_build + end + + def image_builds + ImageBuild.find_all_by_image_uuid(@uuid) + end + + #TODO: We should get the image fields from the object body once we have it defined. + def name + unless @name + @name = @xml_body.xpath("/image/name").text + if @name.empty? + @name = template_xml.xpath("/template/name").text + end + end + @name + end + + def os + unless @os + @os = OS.new(template_xml.xpath("/template/os/name").text, template_xml.xpath("/template/os/version").text, template_xml.xpath("/template/os/arch").text) + end + @os + end + + def description + unless @description + @description = template_xml.xpath("/template/description").text + end + @description + end + + # Delete this image and all child objects + def delete! + begin + image_builds.each do |build| + build.delete! + end + rescue NoMethodError + end + Image.delete(@uuid) + end + end + end + end +end \ No newline at end of file diff --git a/lib/aeolus_image/model/warehouse/image_build.rb b/lib/aeolus_image/model/warehouse/image_build.rb new file mode 100644 index 0000000..d99069d --- /dev/null +++ b/lib/aeolus_image/model/warehouse/image_build.rb @@ -0,0 +1,70 @@ +# Copyright 2011 Red Hat, Inc. +# +# Licensed 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 Aeolus + module Image + module Warehouse + class ImageBuild < WarehouseModel + @bucket_name = 'builds' + + def initialize(attrs) + attrs.each do |k,v| + if k.to_sym == :image + sym = :attr_writer + else + sym = :attr_accessor + end + self.class.send(sym, k.to_sym) unless respond_to?(:"#{k}=") + send(:"#{k}=", v) + end + end + + def self.find_all_by_image_uuid(uuid) + self.set_warehouse_and_bucket if self.bucket.nil? + self.bucket.objects.map do |wh_object| + if wh_object.attr('image') == uuid + ImageBuild.new(wh_object.attrs(wh_object.attr_list)) + end + end.compact + end + + def image + Image.find(@image) if @image + end + + def target_images + TargetImage.all.select {|ti| ti.build and (ti.build.uuid == self.uuid)} + end + + def provider_images + targets = target_images + ProviderImage.all.select do |pi| + targets.include?(pi.target_image) + end + end + + # Deletes this image and all child objects + def delete! + begin + target_images.each do |ti| + ti.delete! + end + rescue NoMethodError + end + ImageBuild.delete(@uuid) + end + end + end + end +end \ No newline at end of file diff --git a/lib/aeolus_image/model/warehouse/provider_image.rb b/lib/aeolus_image/model/warehouse/provider_image.rb new file mode 100644 index 0000000..acd0386 --- /dev/null +++ b/lib/aeolus_image/model/warehouse/provider_image.rb @@ -0,0 +1,48 @@ +# Copyright 2011 Red Hat, Inc. +# +# Licensed 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 Aeolus + module Image + module Warehouse + class ProviderImage < WarehouseModel + @bucket_name = 'provider_images' + + def initialize(attrs) + attrs.each do |k,v| + if [:provider, :target_image].include?(k.to_sym) + sym = :attr_writer + else + sym = :attr_accessor + end + self.class.send(sym, k.to_sym) unless respond_to?(:"#{k}=") + send(:"#{k}=", v) + end + end + + def target_image + TargetImage.find(@target_image) if @target_image + end + + def provider_name + @provider + end + + # Deletes this provider image + def delete! + ProviderImage.delete(@uuid) + end + end + end + end +end \ No newline at end of file diff --git a/lib/aeolus_image/model/warehouse/target_image.rb b/lib/aeolus_image/model/warehouse/target_image.rb new file mode 100644 index 0000000..8636694 --- /dev/null +++ b/lib/aeolus_image/model/warehouse/target_image.rb @@ -0,0 +1,58 @@ +# Copyright 2011 Red Hat, Inc. +# +# Licensed 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 Aeolus + module Image + module Warehouse + class TargetImage < WarehouseModel + @bucket_name = 'target_images' + + def initialize(attrs) + attrs.each do |k,v| + if k.to_sym == :build + sym = :attr_writer + else + sym = :attr_accessor + end + self.class.send(sym, k.to_sym) unless respond_to?(:"#{k}=") + send(:"#{k}=", v) + end + end + + def build + ImageBuild.find(@build) if @build + end + + def provider_images + ProviderImage.all.select{|pi| pi.target_image and (pi.target_image.uuid == self.uuid)} + end + + def target_template + Template.find(@template) if @template + end + + # Deletes this targetimage and all child objects + def delete! + begin + provider_images.each do |pi| + pi.delete! + end + rescue NoMethodError + end + TargetImage.delete(@uuid) + end + end + end + end +end \ No newline at end of file diff --git a/lib/aeolus_image/model/warehouse/template.rb b/lib/aeolus_image/model/warehouse/template.rb new file mode 100644 index 0000000..a3b9ec5 --- /dev/null +++ b/lib/aeolus_image/model/warehouse/template.rb @@ -0,0 +1,31 @@ +# Copyright 2011 Red Hat, Inc. +# +# Licensed 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 Aeolus + module Image + module Warehouse + class Template < WarehouseModel + @bucket_name = 'templates' + + def initialize(attrs) + attrs.each do |k,v| + sym = :attr_accessor + self.class.send(sym, k.to_sym) unless respond_to?(:"#{k}=") + send(:"#{k}=", v) + end + end + end + end + end +end \ No newline at end of file diff --git a/lib/aeolus_image/model/warehouse/warehouse_client.rb b/lib/aeolus_image/model/warehouse/warehouse_client.rb new file mode 100644 index 0000000..4df83a1 --- /dev/null +++ b/lib/aeolus_image/model/warehouse/warehouse_client.rb @@ -0,0 +1,178 @@ +# Copyright 2011 Red Hat, Inc. +# +# Licensed 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. + +require 'rubygems' + +require 'rest-client' +require 'nokogiri' + +#TODO: perform iwhd version-dependent URI mapping +module Aeolus + module Image + module Warehouse + class BucketObject + attr_reader :key + + def initialize(connection, key, bucket) + @connection = connection + @key = key + @bucket = bucket + @path = "/#{@bucket.name}/#{@key}" + end + + def self.create(connection, key, bucket, body, attrs = {}) + obj = new(connection, key, bucket) + obj.set_body(body) + obj.set_attrs(attrs) + obj + end + + def body + @connection.do_request @path, :plain => true + end + + def set_body(body) + @connection.do_request @path, :content => body, :method => :put + end + + def attr_list + result = @connection.do_request @path, :content => 'op=parts', :method => :post + return result.xpath('/object/object_attr/@name').to_a.map {|item| item.value} + end + + def attrs(list) + attrs = {} + list.each do |att| + next if att.match('-') + attrs[att] = (@connection.do_request("#{@path}/#{att}", :plain => true) rescue nil) + end + attrs[:body] = body + attrs + end + + def attr(name) + attrs([name])[name] + end + + def set_attrs(hash) + hash.each do |name, content| + set_attr(name, content) + end + end + + def set_attr(name, content) + path = "#{@path}/#{name}" + @connection.do_request path, :content => content, :method => :put + end + + def delete! + @connection.do_request @path, :method => :delete + true + end + + end + + class Bucket + attr_accessor :name + + def initialize(name, connection) + @name = name + @connection = connection + end + + def to_s + "Bucket: #{@name}" + end + + def object_names + result = @connection.do_request "/#{@name}" + result.xpath('/objects/object').map do |obj| + obj.at_xpath('./key/text()').to_s + end + end + + def objects + object_names.map do |name| + object(name) + end + end + + def object(key) + BucketObject.new @connection, key, self + end + + def create_object(key, body, attrs) + BucketObject.create(@connection, key, self, body, attrs) + end + + def include?(key) + object_names.include?(key) + end + end + + class Connection + attr_accessor :uri + + def initialize(uri) + @uri = uri + end + + def do_request(path = '', opts={}) + opts[:method] ||= :get + opts[:content] ||= '' + opts[:plain] ||= false + opts[:headers] ||= {} + + result = RestClient::Request.execute :method => opts[:method], :url => @uri + path, :payload => opts[:content], :headers => opts[:headers] + + return Nokogiri::XML result unless opts[:plain] + return result + end + + end + + class Client + + def initialize(uri) + @connection = Connection.new(uri) + end + + def create_bucket(bucket) + @connection.do_request "/#{bucket}", :method => :put rescue RestClient::InternalServerError + Bucket.new(bucket, @connection) + end + + def bucket(bucket) + Bucket.new bucket, @connection + end + + def buckets + @connection.do_request.xpath('/api/link[@rel="bucket"]').map do |obj| + obj.at_xpath('./@href').to_s.gsub(/.*//, '') + end + end + + def get_iwhd_version + result = @connection.do_request.at_xpath('/api[@service="image_warehouse"]/@version') + raise "Response does not contain <api> tag or version information" if result == nil + return result.value + end + + def query(bucket_name, query_string) + @connection.do_request "/#{bucket_name}/_query", {:method => :post, :content => query_string} + end + end + end + end +end diff --git a/lib/aeolus_image/model/warehouse/warehouse_model.rb b/lib/aeolus_image/model/warehouse/warehouse_model.rb new file mode 100644 index 0000000..2631c5b --- /dev/null +++ b/lib/aeolus_image/model/warehouse/warehouse_model.rb @@ -0,0 +1,162 @@ +# Copyright 2011 Red Hat, Inc. +# +# Licensed 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 Aeolus + module Image + module Warehouse + class BucketObjectNotFound < Exception;end + class BucketNotFound < Exception;end + + class WarehouseModel + + def ==(other_obj) + # If the objects have different instance variables defined, they're definitely not == + return false unless instance_variables.sort == other_obj.instance_variables.sort + # Otherwise, ensure that they're all the same + instance_variables.each do |iv| + return false unless other_obj.instance_variable_get(iv) == instance_variable_get(iv) + end + # They have the same instance variables and values, so they're equal + true + end + + class << self + attr_accessor :warehouse, :bucket, :bucket_name + + def set_warehouse_and_bucket + begin + @@config ||= load_config + self.warehouse = Warehouse::Client.new(@@config[:iwhd][:url]) + self.bucket = self.warehouse.bucket(@bucket_name) + rescue + raise BucketNotFound + end + end + + def bucket_objects + self.set_warehouse_and_bucket if self.bucket.nil? + + begin + self.bucket.objects + rescue RestClient::ResourceNotFound + [] + end + end + + def first + obj = bucket_objects.first + obj ? self.new(obj.attrs(obj.attr_list)) : nil + end + + def last + obj = bucket_objects.last + obj ? self.new(obj.attrs(obj.attr_list)) : nil + end + + def all + bucket_objects.map do |wh_object| + self.new(wh_object.attrs(wh_object.attr_list)) + end + end + + def find(uuid) + self.set_warehouse_and_bucket if self.bucket.nil? + begin + if self.bucket.include?(uuid) + self.new(self.bucket.object(uuid).attrs(self.bucket.object(uuid).attr_list)) + else + nil + end + rescue RestClient::ResourceNotFound + nil + end + end + + def where(query_string) + self.set_warehouse_and_bucket if self.bucket.nil? + self.warehouse.query(@bucket_name, query_string) + end + + def delete(uuid) + self.set_warehouse_and_bucket if self.bucket.nil? + begin + if self.bucket.include?(uuid) + self.bucket.object(uuid).delete! + else + false + end + rescue RestClient::ResourceNotFound + false + end + end + + protected + # Copy over entirely too much code to load the config file + def load_config + # TODO - Is this always the case? We should probably have /etc/aeolus-cli or something too? + # Or allow Rails to override this + @config_location ||= "~/.aeolus-cli" + begin + file_str = read_file(@config_location) + if is_file?(@config_location) && !file_str.include?(":url") + lines = File.readlines(File.expand_path(@config_location)).map do |line| + "#" + line + end + File.open(File.expand_path(@config_location), 'w') do |file| + file.puts lines + end + write_file + end + write_file unless is_file?(@config_location) + YAML::load(File.open(File.expand_path(@config_location))) + rescue Errno::ENOENT + #TODO: Create a custom exception to wrap CLI Exceptions + raise "Unable to locate or write configuration file: "" + @config_location + """ + end + end + + def write_file + example = File.read(File.expand_path(File.dirname(__FILE__) + "/../../examples/aeolus-cli")) + File.open(File.expand_path(@config_location), 'a+') do |f| + f.write(example) + end + end + + def read_file(path) + begin + full_path = File.expand_path(path) + if is_file?(path) + File.read(full_path) + else + return nil + end + rescue + nil + end + end + + def is_file?(path) + full_path = File.expand_path(path) + if File.exist?(full_path) && !File.directory?(full_path) + return true + end + false + end + + end + + end + end + end +end \ No newline at end of file diff --git a/lib/aeolus_image/model/warehouse_client.rb b/lib/aeolus_image/model/warehouse_client.rb deleted file mode 100644 index f0da7ff..0000000 --- a/lib/aeolus_image/model/warehouse_client.rb +++ /dev/null @@ -1,180 +0,0 @@ -# Copyright 2011 Red Hat, Inc. -# -# Licensed 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. - -require 'rubygems' - -require 'rest-client' -require 'nokogiri' - -#TODO: perform iwhd version-dependent URI mapping -module Aeolus - module Image - module Warehouse - - class BucketObject - attr_reader :key - - def initialize(connection, key, bucket) - @connection = connection - @key = key - @bucket = bucket - @path = "/#{@bucket.name}/#{@key}" - end - - def self.create(connection, key, bucket, body, attrs = {}) - obj = new(connection, key, bucket) - obj.set_body(body) - obj.set_attrs(attrs) - obj - end - - def body - @connection.do_request @path, :plain => true - end - - def set_body(body) - @connection.do_request @path, :content => body, :method => :put - end - - def attr_list - result = @connection.do_request @path, :content => 'op=parts', :method => :post - return result.xpath('/object/object_attr/@name').to_a.map {|item| item.value} - end - - def attrs(list) - attrs = {} - list.each do |att| - next if att.match('-') - attrs[att] = (@connection.do_request("#{@path}/#{att}", :plain => true) rescue nil) - end - attrs[:body] = body - attrs - end - - def attr(name) - attrs([name])[name] - end - - def set_attrs(hash) - hash.each do |name, content| - set_attr(name, content) - end - end - - def set_attr(name, content) - path = "#{@path}/#{name}" - @connection.do_request path, :content => content, :method => :put - end - - def delete! - @connection.do_request @path, :method => :delete - true - end - - end - - class Bucket - attr_accessor :name - - def initialize(name, connection) - @name = name - @connection = connection - end - - def to_s - "Bucket: #{@name}" - end - - def object_names - result = @connection.do_request "/#{@name}" - result.xpath('/objects/object').map do |obj| - obj.at_xpath('./key/text()').to_s - end - end - - def objects - object_names.map do |name| - object(name) - end - end - - def object(key) - BucketObject.new @connection, key, self - end - - def create_object(key, body, attrs) - BucketObject.create(@connection, key, self, body, attrs) - end - - def include?(key) - object_names.include?(key) - end - end - - class Connection - attr_accessor :uri - - def initialize(uri) - @uri = uri - end - - def do_request(path = '', opts={}) - opts[:method] ||= :get - opts[:content] ||= '' - opts[:plain] ||= false - opts[:headers] ||= {} - - result = RestClient::Request.execute :method => opts[:method], :url => @uri + path, :payload => opts[:content], :headers => opts[:headers] - - return Nokogiri::XML result unless opts[:plain] - return result - end - - end - - class Client - - def initialize(uri) - @connection = Connection.new(uri) - end - - def create_bucket(bucket) - @connection.do_request "/#{bucket}", :method => :put rescue RestClient::InternalServerError - Bucket.new(bucket, @connection) - end - - def bucket(bucket) - Bucket.new bucket, @connection - end - - def buckets - @connection.do_request.xpath('/api/link[@rel="bucket"]').map do |obj| - obj.at_xpath('./@href').to_s.gsub(/.*//, '') - end - end - - def get_iwhd_version - result = @connection.do_request.at_xpath('/api[@service="image_warehouse"]/@version') - raise "Response does not contain <api> tag or version information" if result == nil - return result.value - end - - def query(bucket_name, query_string) - @connection.do_request "/#{bucket_name}/_query", {:method => :post, :content => query_string} - end - end - - end - end -end diff --git a/lib/aeolus_image/model/warehouse_model.rb b/lib/aeolus_image/model/warehouse_model.rb deleted file mode 100644 index 2586f6d..0000000 --- a/lib/aeolus_image/model/warehouse_model.rb +++ /dev/null @@ -1,162 +0,0 @@ -# Copyright 2011 Red Hat, Inc. -# -# Licensed 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 Aeolus - module Image - # require 'warehouse_client' - include Warehouse - class BucketObjectNotFound < Exception;end - class BucketNotFound < Exception;end - - class WarehouseModel - - def ==(other_obj) - # If the objects have different instance variables defined, they're definitely not == - return false unless instance_variables.sort == other_obj.instance_variables.sort - # Otherwise, ensure that they're all the same - instance_variables.each do |iv| - return false unless other_obj.instance_variable_get(iv) == instance_variable_get(iv) - end - # They have the same instance variables and values, so they're equal - true - end - - class << self - attr_accessor :warehouse, :bucket, :bucket_name - - def set_warehouse_and_bucket - begin - @@config ||= load_config - self.warehouse = Warehouse::Client.new(@@config[:iwhd][:url]) - self.bucket = self.warehouse.bucket(@bucket_name) - rescue - raise BucketNotFound - end - end - - def bucket_objects - self.set_warehouse_and_bucket if self.bucket.nil? - - begin - self.bucket.objects - rescue RestClient::ResourceNotFound - [] - end - end - - def first - obj = bucket_objects.first - obj ? self.new(obj.attrs(obj.attr_list)) : nil - end - - def last - obj = bucket_objects.last - obj ? self.new(obj.attrs(obj.attr_list)) : nil - end - - def all - bucket_objects.map do |wh_object| - self.new(wh_object.attrs(wh_object.attr_list)) - end - end - - def find(uuid) - self.set_warehouse_and_bucket if self.bucket.nil? - begin - if self.bucket.include?(uuid) - self.new(self.bucket.object(uuid).attrs(self.bucket.object(uuid).attr_list)) - else - nil - end - rescue RestClient::ResourceNotFound - nil - end - end - - def where(query_string) - self.set_warehouse_and_bucket if self.bucket.nil? - self.warehouse.query(@bucket_name, query_string) - end - - def delete(uuid) - self.set_warehouse_and_bucket if self.bucket.nil? - begin - if self.bucket.include?(uuid) - self.bucket.object(uuid).delete! - else - false - end - rescue RestClient::ResourceNotFound - false - end - end - - protected - # Copy over entirely too much code to load the config file - def load_config - # TODO - Is this always the case? We should probably have /etc/aeolus-cli or something too? - # Or allow Rails to override this - @config_location ||= "~/.aeolus-cli" - begin - file_str = read_file(@config_location) - if is_file?(@config_location) && !file_str.include?(":url") - lines = File.readlines(File.expand_path(@config_location)).map do |line| - "#" + line - end - File.open(File.expand_path(@config_location), 'w') do |file| - file.puts lines - end - write_file - end - write_file unless is_file?(@config_location) - YAML::load(File.open(File.expand_path(@config_location))) - rescue Errno::ENOENT - #TODO: Create a custom exception to wrap CLI Exceptions - raise "Unable to locate or write configuration file: "" + @config_location + """ - end - end - - def write_file - example = File.read(File.expand_path(File.dirname(__FILE__) + "/../../examples/aeolus-cli")) - File.open(File.expand_path(@config_location), 'a+') do |f| - f.write(example) - end - end - - def read_file(path) - begin - full_path = File.expand_path(path) - if is_file?(path) - File.read(full_path) - else - return nil - end - rescue - nil - end - end - - def is_file?(path) - full_path = File.expand_path(path) - if File.exist?(full_path) && !File.directory?(full_path) - return true - end - false - end - - end - - end - end -end
aeolus-devel@lists.fedorahosted.org