imagefactory-console 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile +77 -0
- data/lib/imagefactory.rb +2 -0
- data/lib/imagefactory/base_handler.rb +56 -0
- data/lib/imagefactory/console.rb +251 -0
- data/spec/image_factory/console_spec.rb +217 -0
- data/spec/spec_helper.rb +3 -0
- metadata +72 -0
data/Rakefile
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2011 Red Hat, Inc.
|
3
|
+
# Written by Jason Guiditta <jguiditt@redhat.com>
|
4
|
+
#
|
5
|
+
# This program is free software; you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation; version 2 of the License.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
17
|
+
# MA 02110-1301, USA. A copy of the GNU General Public License is
|
18
|
+
# also available at http://www.gnu.org/copyleft/gpl.html.
|
19
|
+
|
20
|
+
|
21
|
+
require 'rubygems'
|
22
|
+
require 'rake'
|
23
|
+
require 'rake/clean'
|
24
|
+
require 'rake/gempackagetask'
|
25
|
+
require 'rake/rdoctask'
|
26
|
+
require 'rake/testtask'
|
27
|
+
require 'spec/rake/spectask'
|
28
|
+
require 'rake/rpmtask'
|
29
|
+
|
30
|
+
RPMBUILD_DIR = "#{File.expand_path('~')}/rpmbuild"
|
31
|
+
RPM_SPEC = "rubygem-imagefactory-console.spec"
|
32
|
+
|
33
|
+
spec = Gem::Specification.new do |s|
|
34
|
+
s.name = 'imagefactory-console'
|
35
|
+
s.version = '0.4.0'
|
36
|
+
s.has_rdoc = true
|
37
|
+
#s.extra_rdoc_files = ['README', 'COPYING']
|
38
|
+
s.summary = 'QMF Console for Aeolus Image Factory'
|
39
|
+
s.description = s.summary
|
40
|
+
s.author = 'Jason Guiditta'
|
41
|
+
s.email = 'jguiditt@redhat.com'
|
42
|
+
# s.executables = ['your_executable_here']
|
43
|
+
s.files = %w(Rakefile) + Dir.glob("{bin,lib,spec}/**/*")
|
44
|
+
s.require_path = "lib"
|
45
|
+
s.bindir = "bin"
|
46
|
+
end
|
47
|
+
|
48
|
+
Rake::GemPackageTask.new(spec) do |p|
|
49
|
+
p.gem_spec = spec
|
50
|
+
p.need_tar = true
|
51
|
+
p.need_zip = true
|
52
|
+
end
|
53
|
+
|
54
|
+
Rake::RDocTask.new do |rdoc|
|
55
|
+
files =['lib/**/*.rb'] #'README', 'COPYING',
|
56
|
+
rdoc.rdoc_files.add(files)
|
57
|
+
#rdoc.main = "README" # page to start on
|
58
|
+
rdoc.title = "console Docs"
|
59
|
+
rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
|
60
|
+
rdoc.options << '--line-numbers'
|
61
|
+
end
|
62
|
+
|
63
|
+
Rake::TestTask.new do |t|
|
64
|
+
t.test_files = FileList['test/**/*.rb']
|
65
|
+
end
|
66
|
+
|
67
|
+
Spec::Rake::SpecTask.new do |t|
|
68
|
+
t.libs << 'lib'
|
69
|
+
t.spec_files = FileList['spec/**/*.rb']
|
70
|
+
t.spec_opts = ['--color', '--format nested']
|
71
|
+
end
|
72
|
+
|
73
|
+
Rake::RpmTask.new(RPM_SPEC) do |rpm|
|
74
|
+
rpm.need_tar = true
|
75
|
+
rpm.package_files.include("lib/*")
|
76
|
+
rpm.topdir = "#{RPMBUILD_DIR}"
|
77
|
+
end
|
data/lib/imagefactory.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2011 Red Hat, Inc.
|
3
|
+
# Written by Jason Guiditta <jguiditt@redhat.com>
|
4
|
+
#
|
5
|
+
# This program is free software; you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation; version 2 of the License.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
17
|
+
# MA 02110-1301, USA. A copy of the GNU General Public License is
|
18
|
+
# also available at http://www.gnu.org/copyleft/gpl.html.
|
19
|
+
|
20
|
+
require 'logger'
|
21
|
+
|
22
|
+
class BaseHandler
|
23
|
+
|
24
|
+
def initialize(logger=nil)
|
25
|
+
logger(logger)
|
26
|
+
end
|
27
|
+
|
28
|
+
def handle(data)
|
29
|
+
logger.debug "====== Type of event: #{data.event}"
|
30
|
+
if data.event == 'STATUS'
|
31
|
+
logger.debug "calling handle status in base handler"
|
32
|
+
handle_status(data)
|
33
|
+
elsif data.event == 'FAILURE'
|
34
|
+
handle_failed(data)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def handle_status(data)
|
39
|
+
logger.debug "{data.event}, #{data.new_status}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def handle_failed(data)
|
43
|
+
logger.error "#{data.to_s}"
|
44
|
+
end
|
45
|
+
|
46
|
+
protected
|
47
|
+
def logger(logger=nil)
|
48
|
+
@logger ||= logger
|
49
|
+
unless @logger
|
50
|
+
@logger = Logger.new(STDOUT)
|
51
|
+
@logger.level = Logger::ERROR
|
52
|
+
@logger.datetime_format = "%Y-%m-%d %H:%M:%S"
|
53
|
+
end
|
54
|
+
return @logger
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,251 @@
|
|
1
|
+
#
|
2
|
+
# Copyright (C) 2011 Red Hat, Inc.
|
3
|
+
# Written by Jason Guiditta <jguiditt@redhat.com>
|
4
|
+
#
|
5
|
+
# This program is free software; you can redistribute it and/or modify
|
6
|
+
# it under the terms of the GNU General Public License as published by
|
7
|
+
# the Free Software Foundation; version 2 of the License.
|
8
|
+
#
|
9
|
+
# This program is distributed in the hope that it will be useful,
|
10
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
# GNU General Public License for more details.
|
13
|
+
#
|
14
|
+
# You should have received a copy of the GNU General Public License
|
15
|
+
# along with this program; if not, write to the Free Software
|
16
|
+
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
17
|
+
# MA 02110-1301, USA. A copy of the GNU General Public License is
|
18
|
+
# also available at http://www.gnu.org/copyleft/gpl.html.
|
19
|
+
|
20
|
+
# TODO: figure out what I am doing wrong here that I need this line
|
21
|
+
$: << File.expand_path(File.join(File.dirname(__FILE__), "."))
|
22
|
+
require 'cqpid'
|
23
|
+
require 'qmf2'
|
24
|
+
require 'logger'
|
25
|
+
require 'base_handler'
|
26
|
+
|
27
|
+
class ImageFactoryConsole < Qmf2::ConsoleHandler
|
28
|
+
|
29
|
+
attr_accessor :q, :handler
|
30
|
+
|
31
|
+
def initialize(args={})
|
32
|
+
# @retry_limit = args.include?(:retry_limit) ? args[:retry_limit] : 20
|
33
|
+
# @delay = args.include?(:delay) ? args[:delay] : 15
|
34
|
+
host = args.include?(:host) ? args[:host] : "localhost"
|
35
|
+
port = args.include?(:port) ? args[:port] : 5672
|
36
|
+
# url = "amqp://#{host}:#{port}" <- the amqp part here doesnt work yet
|
37
|
+
url = "#{host}:#{port}"
|
38
|
+
opts = {"reconnect"=>"true"}
|
39
|
+
@connection = Cqpid::Connection.new(url, opts)
|
40
|
+
@connection.open
|
41
|
+
@session = Qmf2::ConsoleSession.new(@connection)
|
42
|
+
@session.open
|
43
|
+
@session.set_agent_filter("[and, [eq, _vendor, [quote, 'redhat.com']], [eq, _product, [quote, 'imagefactory']]]")
|
44
|
+
|
45
|
+
if args.include?(:logger)
|
46
|
+
@logger = args[:logger]
|
47
|
+
else
|
48
|
+
@logger = Logger.new(STDOUT)
|
49
|
+
@logger.level = Logger::ERROR
|
50
|
+
@logger.datetime_format = "%Y-%m-%d %H:%M:%S"
|
51
|
+
end
|
52
|
+
@handler = args.include?(:handler)? args[:handler]: BaseHandler.new(@logger)
|
53
|
+
super(@session)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Call this method to initiate a build, and get back an
|
57
|
+
# array of BuildAdaptor objects.
|
58
|
+
# * template => String
|
59
|
+
# Description of what to build. Can be xml, uuid, or url
|
60
|
+
# * targets => Array
|
61
|
+
# Represents the names of the clouds to target (ec2, mock, rackspace, etc)
|
62
|
+
# * image_id => String
|
63
|
+
# The UUID of an image previously built
|
64
|
+
# * build_id => String
|
65
|
+
# The UUID of a previous build of the image
|
66
|
+
# * Returns => an array of BuildAdaptor objects
|
67
|
+
#
|
68
|
+
def build(template, targets, image='', build='')
|
69
|
+
targets = [targets] unless targets.instance_of?(Array)
|
70
|
+
# TODO: return error if there is a problem calling this method or getting
|
71
|
+
# a factory instance
|
72
|
+
begin
|
73
|
+
response = factory.build_image(image, build, template, targets)
|
74
|
+
build_adaptors(response)
|
75
|
+
rescue Exception => e
|
76
|
+
@logger.debug "Encountered error in build_image: #{e}"
|
77
|
+
return e
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Call this method to push an image to a provider, and get back an
|
82
|
+
# array of BuildAdaptor objects.
|
83
|
+
# * providers => Array
|
84
|
+
# Represents the target providers to build for (ec2-us-east, mock1, etc)
|
85
|
+
# * credentials => String
|
86
|
+
# XML block to be used for registration, upload, etc
|
87
|
+
# * image_id => String
|
88
|
+
# The UUID of an image previously built
|
89
|
+
# * build_id => String
|
90
|
+
# The UUID of a previous build of the image
|
91
|
+
# * Returns => an array of BuildAdaptor objects
|
92
|
+
#
|
93
|
+
def push(providers, credentials, image_id, build_id='')
|
94
|
+
providers = [providers] unless providers.instance_of?(Array)
|
95
|
+
# TODO: return error if there is a problem calling this method or getting
|
96
|
+
# a factory instance
|
97
|
+
begin
|
98
|
+
response = factory.push_image(image_id, build_id, providers, credentials)
|
99
|
+
build_adaptors(response)
|
100
|
+
rescue Exception => e
|
101
|
+
@logger.debug "Encountered error in push_image: #{e}"
|
102
|
+
return e
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Call this method to import an image
|
107
|
+
# array of BuildAdaptor objects.
|
108
|
+
# * image => string
|
109
|
+
# The uuid of an existing image
|
110
|
+
# * build => string
|
111
|
+
# the uuid of an existing build, or the empty string
|
112
|
+
# * target_identifier => string
|
113
|
+
# the target specific image ID
|
114
|
+
# * image_desc => string
|
115
|
+
# an xml string description of the image
|
116
|
+
# * target => string
|
117
|
+
# name of the cloud to target
|
118
|
+
# * provider => string
|
119
|
+
# the name of the cloud provider, often a region
|
120
|
+
# Returns => a map including UUIDs as strings for 'target_image', 'build', 'image', 'provider_image'
|
121
|
+
|
122
|
+
def import_image(image, build, target_identifier, image_description, target, provider)
|
123
|
+
# TODO: return error if there is a problem calling this method or getting
|
124
|
+
# a factory instance
|
125
|
+
begin
|
126
|
+
factory.import_image(image, build, target_identifier, image_description, target, provider)
|
127
|
+
rescue Exception => e
|
128
|
+
@logger.debug "Encountered error in import_image: #{e}"
|
129
|
+
return e
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# <b>DEPRECATED:</b> Please use <tt>build</tt> instead.
|
134
|
+
# Call this method to initiate a build, and get back an
|
135
|
+
# BuildAdaptor object.
|
136
|
+
# * descriptor => String
|
137
|
+
# This can be either xml or a url pointing to the xml
|
138
|
+
# * target => String
|
139
|
+
# Represents the target provider type to build for (ec2, mock, etc)
|
140
|
+
# * Returns => a BuildAdaptor object
|
141
|
+
#
|
142
|
+
def build_image(descriptor, target)
|
143
|
+
@logger.warn "[DEPRECATION] 'build_image' is deprecated. Please use 'build' instead."
|
144
|
+
# TODO: return error if there is a problem calling this method or getting
|
145
|
+
# a factory instance
|
146
|
+
begin
|
147
|
+
response = factory.image(descriptor, target)
|
148
|
+
build_adaptor(response)
|
149
|
+
rescue Exception => e
|
150
|
+
@logger.debug "Encountered error in build_image: #{e}"
|
151
|
+
return e
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# <b>DEPRECATED:</b> Please use <tt>push</tt> instead.
|
156
|
+
# Call this method to push an image to a provider, and get back an
|
157
|
+
# BuildAdaptor object.
|
158
|
+
# * image_id => String (uuid)
|
159
|
+
# * provider => String
|
160
|
+
# Represents the target provider to build for (ec2-us-east, mock, etc)
|
161
|
+
# * credentials => String
|
162
|
+
# XML block to be used for registration, upload, etc
|
163
|
+
# * Returns => a BuildAdaptor object
|
164
|
+
#
|
165
|
+
def push_image(image_id, provider, credentials)
|
166
|
+
@logger.warn "[DEPRECATION] 'push_image' is deprecated. Please use 'push' instead."
|
167
|
+
# TODO: return error if there is a problem calling this method or getting
|
168
|
+
# a factory instance
|
169
|
+
begin
|
170
|
+
response = factory.provider_image(image_id, provider, credentials)
|
171
|
+
build_adaptor(response)
|
172
|
+
rescue Exception => e
|
173
|
+
@logger.debug "Encountered error in push_image: #{e}"
|
174
|
+
return e
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
#TODO: enhance both of these methods to handle multiple agents
|
179
|
+
def agent_added(agent)
|
180
|
+
@logger.debug "GOT AN AGENT: #{agent} at #{Time.now.utc}"
|
181
|
+
@q = agent if agent.product == "imagefactory"
|
182
|
+
end
|
183
|
+
|
184
|
+
def agent_deleted(agent, reason)
|
185
|
+
@logger.debug "AGENT GONE: #{agent} at #{Time.now.utc}, because #{reason}"
|
186
|
+
unless @q==nil
|
187
|
+
@q = nil if (@q.product == agent.product && @q.name.eql?(agent.name))
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# TODO: handle agent restart events (this will be more useful when
|
192
|
+
# restarted agent can recover an in-process build
|
193
|
+
def agent_restarted(agent)
|
194
|
+
@logger.debug "AGENT RESTARTED: #{agent.product}"
|
195
|
+
end
|
196
|
+
|
197
|
+
# TODO: handle schema updates. This will be more useful when/if
|
198
|
+
# we make this a more generic console to talk to different agents.
|
199
|
+
def agent_schema_updated(agent)
|
200
|
+
@logger.debug "AGENT SCHEMA UPDATED: #{agent.product}"
|
201
|
+
end
|
202
|
+
|
203
|
+
def event_raised(agent, data, timestamp, severity)
|
204
|
+
@logger.debug "GOT AN EVENT: #{agent}, #{data} at #{timestamp}"
|
205
|
+
@handler.handle(data)
|
206
|
+
end
|
207
|
+
|
208
|
+
def shutdown
|
209
|
+
@logger.debug "Closing connections.."
|
210
|
+
if @session
|
211
|
+
@session.close
|
212
|
+
end
|
213
|
+
@connection.close
|
214
|
+
|
215
|
+
#TODO Replace this with some control flow to manage the cancelling of the console handler, atm
|
216
|
+
# this code swallows error message generated by closing connection, then cancelling console.
|
217
|
+
begin
|
218
|
+
self.cancel
|
219
|
+
rescue QmfError
|
220
|
+
# TODO We should be logging to a file rather than STDOUT, uncomment this code when logging is configured properly
|
221
|
+
# Commented out to clean up user output
|
222
|
+
#@logger.error "Issue Closing Console Handler"
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
private
|
227
|
+
|
228
|
+
def factory
|
229
|
+
@factory ||= @q.query("{class:ImageFactory, package:'com.redhat.imagefactory'}").first
|
230
|
+
end
|
231
|
+
|
232
|
+
def build_adaptors(response)
|
233
|
+
ret = []
|
234
|
+
response['build_adaptors'].each do |imgfacaddr|
|
235
|
+
query = Qmf2::Query.new(Qmf2::DataAddr.new(imgfacaddr))
|
236
|
+
ret << @q.query(query,5).first
|
237
|
+
end
|
238
|
+
ret
|
239
|
+
end
|
240
|
+
|
241
|
+
def build_adaptor(response)
|
242
|
+
@logger.warn "[DEPRECATION] 'build_adaptor' is deprecated. Please use 'build_adaptors' instead."
|
243
|
+
imgfacaddr = Qmf2::DataAddr.new(response['build_adaptor'])
|
244
|
+
query = Qmf2::Query.new(imgfacaddr)
|
245
|
+
@q.query(query,5).first
|
246
|
+
end
|
247
|
+
|
248
|
+
def make_array(a)
|
249
|
+
return a ||= [a] unless a.instance_of?(Array)
|
250
|
+
end
|
251
|
+
end
|
@@ -0,0 +1,217 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module ImageFactory
|
4
|
+
describe ImageFactoryConsole do
|
5
|
+
context "needs a real agent running" do
|
6
|
+
# for now, these all require an actual agent on the bus
|
7
|
+
before(:all) do
|
8
|
+
@logger = Logger.new(STDOUT)
|
9
|
+
@logger.level = Logger::DEBUG
|
10
|
+
@logger.datetime_format = "%Y-%m-%d %H:%M:%S"
|
11
|
+
@i = ImageFactoryConsole.new() # Pass this in for more logging: (:logger => @logger)
|
12
|
+
@i.start
|
13
|
+
# Sadly, this is needed so we wait for an agent to appear.
|
14
|
+
# We might be able to extract this somewhere to hold off
|
15
|
+
# on tests until we get an agent_added notification
|
16
|
+
sleep(5)
|
17
|
+
#TODO: take this snippet and make a fixture of some sort to use in tests
|
18
|
+
#tmpl = '<template> <name>tmpl1</name> <description>foo</description> <os> <name>Fedora</name>
|
19
|
+
# <arch>x86_64</arch> <version>14</version> <install type="url">
|
20
|
+
# <url>http://download.fedoraproject.org/pub/fedora/linux/releases/14/Fedora/x86_64/os/</url> </install>
|
21
|
+
# </os> <repositories> <repository name="custom"> <url>http://repos.fedorapeople.org/repos/aeolus/demo/webapp/</url>
|
22
|
+
# <signed>false</signed> </repository> </repositories> </template>'
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#q" do
|
26
|
+
it "should get an agent set" do
|
27
|
+
@i.q.should_not be_nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#build_image" do
|
32
|
+
it "should return a build-adaptor with uuid" do
|
33
|
+
@i.build_image("<template></template>", "mock").image_id.should_not be_nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#push_image" do
|
38
|
+
it "should return a build-adaptor with uuid" do
|
39
|
+
@image = @i.build_image("<template></template>", "mock")
|
40
|
+
#@i.handler = BaseHandler.new(@logger)
|
41
|
+
@i.handler.should_not_receive(:handle_failed)
|
42
|
+
@i.push_image(@image.image_id, "mock", "some creds").image_id.should_not be_nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#import_image" do
|
47
|
+
it "should return a build-adaptor with uuid" do
|
48
|
+
@import = @i.import_image("", "", "ami-test", "<image><name>Test Image</name></image>", "ec2", "ec2-us-east-1")
|
49
|
+
is_uuid?(@import['image']).should == true
|
50
|
+
is_uuid?(@import['target_image']).should == true
|
51
|
+
is_uuid?(@import['build']).should == true
|
52
|
+
is_uuid?(@import['provider_image']).should == true
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "#build" do
|
57
|
+
it "should return an array of build-adaptors with uuids" do
|
58
|
+
@i.build("<template></template>", ["mock"]).each do |adaptor|
|
59
|
+
adaptor.image_id.should_not be_nil
|
60
|
+
adaptor.image.should_not be_nil
|
61
|
+
adaptor.build.should_not be_nil
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should work with single target as string" do
|
66
|
+
@i.build("<template></template>", "mock").each do |adaptor|
|
67
|
+
adaptor.image_id.should_not be_nil
|
68
|
+
adaptor.image.should_not be_nil
|
69
|
+
adaptor.build.should_not be_nil
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "#push" do
|
75
|
+
it "should return an array of build-adaptors with uuids" do
|
76
|
+
@i.build("<template></template>", ["mock"]).each do |adaptor|
|
77
|
+
#@i.handler = BaseHandler.new(@logger)
|
78
|
+
@i.handler.should_not_receive(:handle_failed)
|
79
|
+
@i.push(["mock"], "<provider_credentials/>", adaptor.image).each do |a|
|
80
|
+
a.image_id.should_not be_nil
|
81
|
+
a.image.should_not be_nil
|
82
|
+
a.build.should_not be_nil
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should work with single provider as string" do
|
88
|
+
@i.build("<template></template>", "mock").each do |adaptor|
|
89
|
+
#@i.handler = BaseHandler.new(@logger)
|
90
|
+
@i.handler.should_not_receive(:handle_failed)
|
91
|
+
@i.push("mock1", "<provider_credentials/>", adaptor.image).each do |a|
|
92
|
+
a.image_id.should_not be_nil
|
93
|
+
a.image.should_not be_nil
|
94
|
+
a.build.should_not be_nil
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
after(:all) do
|
101
|
+
@i.shutdown
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context "agent is stubbed" do
|
106
|
+
before(:each) do
|
107
|
+
@agent = mock('agent', :null_object => true)
|
108
|
+
@agent.stub(:product).and_return("imagefactory")
|
109
|
+
@agent.stub(:name).and_return("redhat.com:imagefactory:b9e131c7-7905-409e-bfb5-dd4848a776a7")
|
110
|
+
@output = double('output')
|
111
|
+
@i2 = ImageFactoryConsole.new(:logger => @output)
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "#agent_added" do
|
115
|
+
it "logs when a new agent appears" do
|
116
|
+
@output.should_receive(:debug).with(/GOT AN AGENT/).as_null_object
|
117
|
+
@i2.agent_added(@agent)
|
118
|
+
end
|
119
|
+
|
120
|
+
it "stores a reference to that agent if it is a factory" do
|
121
|
+
@output.should_receive(:debug).with(/GOT AN AGENT/)
|
122
|
+
@i2.agent_added(@agent)
|
123
|
+
@i2.q.should respond_to(:product)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe "#agent_deleted" do
|
128
|
+
before(:each) do
|
129
|
+
@old_agent = mock('agent', :null_object => true)
|
130
|
+
@old_agent.stub(:product).and_return("imagefactory")
|
131
|
+
@old_agent.stub(:name).and_return("redhat.com:imagefactory:4eb3776e-d91e-4239-9a73-3ab43ecc7e15")
|
132
|
+
@output.should_receive(:debug).with(/GOT AN AGENT/)
|
133
|
+
@i2.agent_added(@agent)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "logs when an agent is removed" do
|
137
|
+
@output.should_receive(:debug).with(/AGENT GONE/).as_null_object
|
138
|
+
@i2.agent_deleted(@agent, "aged")
|
139
|
+
end
|
140
|
+
|
141
|
+
it "removes the agent reference if removed agent is the same as console reference" do
|
142
|
+
@output.should_receive(:debug).with(/AGENT GONE/).as_null_object
|
143
|
+
@i2.agent_deleted(@agent, "aged")
|
144
|
+
@i2.q.should be_nil
|
145
|
+
end
|
146
|
+
|
147
|
+
it "does not remove the agent reference if removed agent is the not same as console reference" do
|
148
|
+
@output.should_receive(:debug).with(/AGENT GONE/).as_null_object
|
149
|
+
@i2.agent_deleted(@old_agent, "aged")
|
150
|
+
@i2.q.should_not be_nil
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
describe "#event_raised" do
|
155
|
+
before(:each) do
|
156
|
+
@data = mock('data', :null_object => true)
|
157
|
+
@data.stub(:event).and_return("STATUS")
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should call handle on an event" do
|
161
|
+
@output.should_receive(:debug).with(/GOT AN EVENT/)
|
162
|
+
|
163
|
+
@i2.handler.should_receive(:handle).once
|
164
|
+
@i2.event_raised(@agent, @data, Time.now, "horrid")
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "#build_image" do
|
169
|
+
it "should gracefully handle errors" do
|
170
|
+
@output.should_receive(:debug).with(/Encountered error in build_image/)
|
171
|
+
@output.should_receive(:warn).with("[DEPRECATION] 'build_image' is deprecated. Please use 'build' instead.")
|
172
|
+
@i2.q=nil
|
173
|
+
error = @i2.build_image("<template></template>", "mock")
|
174
|
+
error.to_s.should include("undefined method")
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
describe "#push_image" do
|
179
|
+
it "should gracefully handle errors" do
|
180
|
+
@output.should_receive(:debug).with(/Encountered error in push_image/)
|
181
|
+
@output.should_receive(:warn).with("[DEPRECATION] 'push_image' is deprecated. Please use 'push' instead.")
|
182
|
+
@i2.q=nil
|
183
|
+
error = @i2.push_image(123, "mock", "some creds")
|
184
|
+
error.to_s.should include("undefined method")
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
describe "#build" do
|
189
|
+
it "should gracefully handle errors" do
|
190
|
+
@output.should_receive(:debug).with(/Encountered error in build_image/)
|
191
|
+
@i2.q=nil
|
192
|
+
error = @i2.build("<template></template>", "mock")
|
193
|
+
error.to_s.should include("undefined method")
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
describe "#push" do
|
198
|
+
it "should gracefully handle errors" do
|
199
|
+
@output.should_receive(:debug).with(/Encountered error in push_image/)
|
200
|
+
@i2.q=nil
|
201
|
+
error = @i2.push(123, "mock", "some creds")
|
202
|
+
error.to_s.should include("undefined method")
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
after(:each) do
|
207
|
+
@output.should_receive(:debug).with(/Closing/)
|
208
|
+
@i2.shutdown
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
def is_uuid?(test_string)
|
213
|
+
regexp = Regexp.new('^[\w]{8}[-][\w]{4}[-][\w]{4}[-][\w]{4}[-][\w]{12}')
|
214
|
+
regexp.match(test_string) ? true : false
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: imagefactory-console
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 15
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 4
|
9
|
+
- 0
|
10
|
+
version: 0.4.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Jason Guiditta
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-07-22 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: QMF Console for Aeolus Image Factory
|
23
|
+
email: jguiditt@redhat.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- Rakefile
|
32
|
+
- lib/imagefactory.rb
|
33
|
+
- lib/imagefactory/base_handler.rb
|
34
|
+
- lib/imagefactory/console.rb
|
35
|
+
- spec/spec_helper.rb
|
36
|
+
- spec/image_factory/console_spec.rb
|
37
|
+
has_rdoc: true
|
38
|
+
homepage:
|
39
|
+
licenses: []
|
40
|
+
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options: []
|
43
|
+
|
44
|
+
require_paths:
|
45
|
+
- lib
|
46
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
hash: 3
|
52
|
+
segments:
|
53
|
+
- 0
|
54
|
+
version: "0"
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
hash: 3
|
61
|
+
segments:
|
62
|
+
- 0
|
63
|
+
version: "0"
|
64
|
+
requirements: []
|
65
|
+
|
66
|
+
rubyforge_project:
|
67
|
+
rubygems_version: 1.3.7
|
68
|
+
signing_key:
|
69
|
+
specification_version: 3
|
70
|
+
summary: QMF Console for Aeolus Image Factory
|
71
|
+
test_files: []
|
72
|
+
|