bellows 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source "http://rubygems.org"
2
+ # Add dependencies required to use your gem here.
3
+ # Example:
4
+ # gem "activesupport", ">= 2.3.5"
5
+
6
+ # Add dependencies to develop your gem here.
7
+ # Include everything needed to run rake, tests, features, etc.
8
+ group :development do
9
+ gem "bundler", "~> 1.0.0"
10
+ gem "jeweler", "~> 1.6.4"
11
+ gem "thor", "~> 0.14.6"
12
+ gem "json", "~> 1.4.6"
13
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Dan Prince
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,58 @@
1
+ Bellows
2
+ =======
3
+
4
+ Description
5
+ -----------
6
+
7
+ Fire it up! SmokeStack automation w/ Gerrit.
8
+
9
+ CLI to drive SmokeStack test creation and maintenance based on Gerrit reviews.
10
+
11
+ Installation
12
+ ------------
13
+
14
+ gem install bellows
15
+
16
+ #create the bellows config in your $HOME dir:
17
+ cat > ~/.bellows.conf <<"EOF_CAT"
18
+ smokestack_url: http://localhost:3000
19
+ smokestack_username: admin
20
+ smokestack_password: cloud
21
+
22
+ config_template_ids:
23
+ - 1
24
+ - 2
25
+
26
+ test_suite_ids:
27
+ - 1
28
+ EOF_CAT
29
+
30
+
31
+ Examples
32
+ --------
33
+
34
+ Available bellows tasks:
35
+
36
+ Tasks:
37
+ bellows help [TASK] # Describe available tasks or one specific task
38
+ bellows purge PROJECT # Purge merged reviews from SmokeStack
39
+ bellows sync PROJECT # Create tests & update refspecs for active reviews.
40
+ bellows update PROJECT # Update tests suite and configuration selections.
41
+
42
+ Run bellows sync to create smokestack test configurations and update refspecs for active reviews:
43
+
44
+ bellows sync nova
45
+
46
+ Purge 'merged' reviews from SmokeStack:
47
+
48
+ bellows purge nova
49
+
50
+ Update the selected configuration template and test suite choices for active reviews in SmokeStack (based on the selections in your .bellows.conf file):
51
+
52
+ bellows update nova
53
+
54
+ All commands support creating and maintaining test configs for nova, glance, and keystone.
55
+
56
+ License
57
+ -------
58
+ Copyright (c) 2011 Dan Prince. See LICENSE.txt for further details.
data/Rakefile ADDED
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "bellows"
18
+ gem.executables = "bellows"
19
+ gem.homepage = "http://github.com/dprince/bellows"
20
+ gem.license = "MIT"
21
+ gem.summary = %Q{Fire it up! SmokeStack automation w/ Gerrit.}
22
+ gem.description = %Q{CLI to drive SmokeStack test creation and maintenance based on Gerrit reviews.}
23
+ gem.email = "dan.prince@rackspace.com"
24
+ gem.authors = ["Dan Prince"]
25
+ # dependencies defined in Gemfile
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ require 'rake/testtask'
30
+ Rake::TestTask.new(:test) do |test|
31
+ #test.libs << 'lib' << 'test'
32
+ test.pattern = 'test/**/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+
36
+ =begin
37
+ require 'rcov/rcovtask'
38
+ Rcov::RcovTask.new do |test|
39
+ test.libs << 'test'
40
+ test.pattern = 'test/**/test_*.rb'
41
+ test.verbose = true
42
+ test.rcov_opts << '--exclude "gems/*"'
43
+ end
44
+ =end
45
+
46
+ task :default => :test
47
+
48
+ require 'rake/rdoctask'
49
+ Rake::RDocTask.new do |rdoc|
50
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
51
+
52
+ rdoc.rdoc_dir = 'rdoc'
53
+ rdoc.title = "bellows #{version}"
54
+ rdoc.rdoc_files.include('README*')
55
+ rdoc.rdoc_files.include('lib/**/*.rb')
56
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
data/bellows.gemspec ADDED
@@ -0,0 +1,65 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{bellows}
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Dan Prince"]
12
+ s.date = %q{2011-10-13}
13
+ s.default_executable = %q{bellows}
14
+ s.description = %q{CLI to drive SmokeStack test creation and maintenance based on Gerrit reviews.}
15
+ s.email = %q{dan.prince@rackspace.com}
16
+ s.executables = ["bellows"]
17
+ s.extra_rdoc_files = [
18
+ "LICENSE.txt",
19
+ "README.md"
20
+ ]
21
+ s.files = [
22
+ ".document",
23
+ "Gemfile",
24
+ "LICENSE.txt",
25
+ "Rakefile",
26
+ "VERSION",
27
+ "bin/bellows",
28
+ "lib/bellows.rb",
29
+ "lib/bellows/gerrit.rb",
30
+ "lib/bellows/http.rb",
31
+ "lib/bellows/smoke_stack.rb",
32
+ "lib/bellows/tasks.rb",
33
+ "lib/bellows/util.rb",
34
+ "test/helper.rb",
35
+ "test/test_util.rb"
36
+ ]
37
+ s.homepage = %q{http://github.com/dprince/bellows}
38
+ s.licenses = ["MIT"]
39
+ s.require_paths = ["lib"]
40
+ s.rubygems_version = %q{1.3.7}
41
+ s.summary = %q{Fire it up! SmokeStack automation w/ Gerrit.}
42
+
43
+ if s.respond_to? :specification_version then
44
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
45
+ s.specification_version = 3
46
+
47
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
48
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
49
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
50
+ s.add_development_dependency(%q<thor>, ["~> 0.14.6"])
51
+ s.add_development_dependency(%q<json>, ["~> 1.4.6"])
52
+ else
53
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
54
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
55
+ s.add_dependency(%q<thor>, ["~> 0.14.6"])
56
+ s.add_dependency(%q<json>, ["~> 1.4.6"])
57
+ end
58
+ else
59
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
60
+ s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
61
+ s.add_dependency(%q<thor>, ["~> 0.14.6"])
62
+ s.add_dependency(%q<json>, ["~> 1.4.6"])
63
+ end
64
+ end
65
+
data/bin/bellows ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rubygems"
4
+ require "thor"
5
+ #if not $release
6
+ #$:.unshift File.dirname(__FILE__) + "/../lib"
7
+ #end
8
+ require "bellows"
9
+
10
+ Bellows::Tasks.start
@@ -0,0 +1,23 @@
1
+ require 'json'
2
+
3
+ module Bellows
4
+ class Gerrit
5
+
6
+ def self.reviews(project, status="open")
7
+ reviews = []
8
+ out=%x{ssh review gerrit query "status: #{status}" --current-patch-set --format JSON}
9
+ out.each_line do |line|
10
+ data = JSON.parse(line)
11
+ if data['project'] and data['project'] == "openstack/#{project}"
12
+ if block_given?
13
+ yield data
14
+ else
15
+ reviews << data
16
+ end
17
+ end
18
+ end
19
+ reviews
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,205 @@
1
+ require 'uri'
2
+ require 'net/http'
3
+ require 'net/https'
4
+ require 'openssl'
5
+ require 'openssl/x509'
6
+ require 'bellows/util'
7
+
8
+ module Net
9
+ module HTTPHeader
10
+
11
+ def set_form_data(params, sep = '&')
12
+ query = URI.encode_www_form(params)
13
+ query.gsub!(/&/, sep) if sep != '&'
14
+ self.body = query
15
+ self.content_type = 'application/x-www-form-urlencoded'
16
+ end
17
+ alias form_data= set_form_data
18
+
19
+ end
20
+ end
21
+
22
+ module URI
23
+
24
+ def self.encode_www_form(enum)
25
+ enum.map do |k,v|
26
+ if v.nil?
27
+ k
28
+ elsif v.respond_to?(:to_ary)
29
+ v.to_ary.map do |w|
30
+ str = k.dup
31
+ unless w.nil?
32
+ str << '='
33
+ str << w
34
+ end
35
+ end.join('&')
36
+ else
37
+ str = k.dup
38
+ str << '='
39
+ str << v.to_s
40
+ end
41
+ end.join('&')
42
+ end
43
+
44
+ end
45
+
46
+ module Bellows
47
+ class HTTP
48
+
49
+ MULTI_PART_BOUNDARY="jtZ!pZ1973um"
50
+
51
+ @@http=nil
52
+ @@auth_user=nil
53
+ @@auth_password=nil
54
+
55
+ def self.init_connection
56
+
57
+ configs=Util.load_configs
58
+
59
+ base_url = configs["smokestack_url"]
60
+ @@auth_user = configs["smokestack_username"]
61
+ @@auth_password = configs["smokestack_password"]
62
+
63
+ ssl_key = configs["ssl_key"]
64
+ ssl_cert = configs["ssl_cert"]
65
+ ssl_ca_cert = configs["ssl_ca_cert"]
66
+
67
+ url=URI.parse(base_url)
68
+ @@http = Net::HTTP.new(url.host,url.port)
69
+
70
+ if base_url =~ /^https/
71
+ @@http.use_ssl = true
72
+ if ssl_ca_cert then
73
+ @@http.verify_mode = OpenSSL::SSL::VERIFY_PEER
74
+ else
75
+ @@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
76
+ end
77
+
78
+ if ssl_key then
79
+ pkey_data=IO.read(ssl_key)
80
+ if pkey_data =~ /^-----BEGIN RSA PRIVATE KEY-----/
81
+ @@http.key=OpenSSL::PKey::RSA.new(pkey_data)
82
+ else
83
+ @@http.key=OpenSSL::PKey::DSA.new(pkey_data)
84
+ end
85
+ end
86
+ @@http.cert=OpenSSL::X509::Certificate.new(IO.read(ssl_cert)) if ssl_cert
87
+ @@http.ca_file=ssl_ca_cert if ssl_ca_cert
88
+ end
89
+
90
+ end
91
+
92
+ def self.file_upload(url_path, file_data={}, post_data={})
93
+ init_connection if @@http.nil?
94
+ req = Net::HTTP::Post.new(url_path)
95
+
96
+ post_arr=[]
97
+ post_data.each_pair do |key, value|
98
+ post_arr << "--#{MULTI_PART_BOUNDARY}\r\n"
99
+ post_arr << "Content-Disposition: form-data; name=\"#{key}\"\r\n"
100
+ post_arr << "\r\n"
101
+ post_arr << value
102
+ post_arr << "\r\n"
103
+ end
104
+
105
+ file_data.each_pair do |name, file|
106
+ post_arr << "--#{MULTI_PART_BOUNDARY}\r\n"
107
+ post_arr << "Content-Disposition: form-data; name=\"#{name}\"; filename=\"#{File.basename(file)}\"\r\n"
108
+ post_arr << "Content-Type: text/plain\r\n"
109
+ post_arr << "\r\n"
110
+ post_arr << File.read(file)
111
+ post_arr << "\r\n--#{MULTI_PART_BOUNDARY}--\r\n"
112
+ end
113
+ post_arr << "--#{MULTI_PART_BOUNDARY}--\r\n\r\n"
114
+
115
+ req.body=post_arr.join
116
+
117
+ req.basic_auth @@auth_user, @@auth_password if @@auth_user and @@auth_password
118
+ req["Content-Type"] = "multipart/form-data, boundary=#{MULTI_PART_BOUNDARY}"
119
+
120
+ response = @@http.request(req)
121
+ case response
122
+ when Net::HTTPSuccess
123
+ return response.body
124
+ else
125
+ puts response.body
126
+ response.error!
127
+ end
128
+ end
129
+
130
+ def self.post(url_path, post_data)
131
+ init_connection if @@http.nil?
132
+ req = Net::HTTP::Post.new(url_path)
133
+ if post_data.kind_of?(String) then
134
+ req.body=post_data
135
+ elsif post_data.kind_of?(Hash) then
136
+ req.form_data=post_data
137
+ else
138
+ raise "Invalid post data type."
139
+ end
140
+ req.basic_auth @@auth_user, @@auth_password if @@auth_user and @@auth_password
141
+ response = @@http.request(req)
142
+ case response
143
+ when Net::HTTPSuccess
144
+ return response.body
145
+ when Net::HTTPRedirection
146
+ return response['location']
147
+ else
148
+ puts response.body
149
+ response.error!
150
+ end
151
+ end
152
+
153
+ def self.put(url_path, put_data)
154
+ init_connection if @@http.nil?
155
+ req = Net::HTTP::Put.new(url_path)
156
+ if put_data.kind_of?(String) then
157
+ req.body=put_data
158
+ elsif put_data.kind_of?(Hash) then
159
+ req.form_data=put_data
160
+ else
161
+ raise "Invalid put data type."
162
+ end
163
+ req.basic_auth @@auth_user, @@auth_password if @@auth_user and @@auth_password
164
+ response = @@http.request(req)
165
+ case response
166
+ when Net::HTTPSuccess
167
+ return response.body
168
+ when Net::HTTPRedirection
169
+ return response['location']
170
+ else
171
+ puts response.body
172
+ response.error!
173
+ end
174
+ end
175
+
176
+ def self.get(url_path)
177
+ init_connection if @@http.nil?
178
+ req = Net::HTTP::Get.new(url_path)
179
+ req.basic_auth @@auth_user, @@auth_password if @@auth_user and @@auth_password
180
+ response = @@http.request(req)
181
+ case response
182
+ when Net::HTTPSuccess
183
+ return response.body
184
+ else
185
+ response.error!
186
+ end
187
+ end
188
+
189
+ def self.delete(url_path)
190
+ init_connection if @@http.nil?
191
+ req = Net::HTTP::Delete.new(url_path)
192
+ req.basic_auth @@auth_user, @@auth_password if @@auth_user and @@auth_password
193
+ response = @@http.request(req)
194
+ case response
195
+ when Net::HTTPSuccess
196
+ return response.body
197
+ when Net::HTTPRedirection
198
+ return response['location']
199
+ else
200
+ response.error!
201
+ end
202
+ end
203
+
204
+ end
205
+ end
@@ -0,0 +1,83 @@
1
+ require 'json'
2
+ require 'bellows/http'
3
+ require 'bellows/util'
4
+
5
+ module Bellows
6
+ class SmokeStack
7
+
8
+ def self.get_smoke_tests(project)
9
+ smoke_tests = {}
10
+ data = JSON.parse(Bellows::HTTP.get("/smoke_tests.json"))
11
+ data.each do |item|
12
+ branch = item['smoke_test']["#{project}_package_builder"]['branch']
13
+ if branch and not branch.empty? then
14
+ smoke_tests.store(Bellows::Util.short_spec(branch), item['smoke_test'])
15
+ end
16
+ end
17
+ smoke_tests
18
+ end
19
+
20
+ def self.format_request(smoke_test)
21
+ req={}
22
+ smoke_test.each_pair do |name, item|
23
+ #only builders should be hashes
24
+ if item.kind_of?(Hash) then
25
+ item.each_pair do |builder_name, builder|
26
+ req.store("smoke_test[#{name}_attributes][#{builder_name}]", builder)
27
+ end
28
+ elsif item.kind_of?(Array) then
29
+ req.store("smoke_test[#{name}][]", item)
30
+ else
31
+ req.store("smoke_test[#{name}]", item)
32
+ end
33
+ end
34
+ req.delete("smoke_test['id']")
35
+ req
36
+ end
37
+
38
+ def self.update_smoke_test(id, updates={})
39
+
40
+ data = JSON.parse(Bellows::HTTP.get("/smoke_tests/#{id}.json"))
41
+ ['nova', 'glance', 'keystone'].each do |proj|
42
+ if updates["#{proj}_package_builder"]
43
+ data["smoke_test"]["#{proj}_package_builder"].merge!(updates["#{proj}_package_builder"])
44
+ updates.delete("#{proj}_package_builder")
45
+ end
46
+ end
47
+ data['smoke_test'].merge!(updates)
48
+ post_data = format_request(data['smoke_test'])
49
+ Bellows::HTTP.put("/smoke_tests/#{id}", post_data)
50
+
51
+ end
52
+
53
+ def self.create_smoke_test(project, description, refspec, config_template_ids, test_suite_ids)
54
+
55
+ post_data = { "smoke_test[description]" => description }
56
+
57
+ ['nova', 'glance', 'keystone'].each do |proj|
58
+ base_name="smoke_test[#{proj}_package_builder_attributes]"
59
+ if project == proj then
60
+ post_data.store("#{base_name}[url]", "https://review.openstack.org/p/openstack/#{project}")
61
+ post_data.store("#{base_name}[branch]", refspec)
62
+ post_data.store("#{base_name}[merge_trunk]", "1")
63
+ else
64
+ post_data.store("#{base_name}[url]", "git://github.com/openstack/#{proj}.git")
65
+ post_data.store("#{base_name}[branch]", "master")
66
+ post_data.store("#{base_name}[merge_trunk]", "0")
67
+ end
68
+ end
69
+
70
+ configurations = []
71
+ config_template_ids.each {|id| configurations << id.to_s}
72
+ post_data.store("smoke_test[config_template_ids][]", configurations)
73
+
74
+ test_suites = []
75
+ test_suite_ids.each {|id| test_suites << id.to_s}
76
+ post_data.store("smoke_test[test_suite_ids][]", test_suites)
77
+
78
+ Bellows::HTTP.post("/smoke_tests", post_data)
79
+
80
+ end
81
+
82
+ end
83
+ end
@@ -0,0 +1,85 @@
1
+ require 'json'
2
+ require 'bellows/http'
3
+ require 'bellows/util'
4
+ require 'bellows/gerrit'
5
+ require 'bellows/smoke_stack'
6
+
7
+ module Bellows
8
+ class Tasks < Thor
9
+
10
+ desc "sync PROJECT", "Create tests & update refspecs for active reviews."
11
+ method_options :test => :boolean
12
+ def sync(project)
13
+ if not ['nova', 'glance', 'keystone'].include?(project) then
14
+ puts "ERROR: Please specify a valid project name."
15
+ exit 1
16
+ end
17
+ test = options[:test]
18
+ smoke_tests = Bellows::SmokeStack.get_smoke_tests(project)
19
+ configs=Util.load_configs
20
+ test_suite_ids = configs['test_suite_ids'].collect {|x| x.to_s }
21
+ config_template_ids = configs['config_template_ids'].collect {|x| x.to_s }
22
+
23
+ Bellows::Gerrit.reviews(project) do |review|
24
+ owner = review['owner']['name']
25
+ refspec = review['currentPatchSet']['ref']
26
+ review_id = Bellows::Util.short_spec(refspec)
27
+ smoke_test = smoke_tests[review_id]
28
+ desc = owner + ": " +review['subject']
29
+ if not smoke_test
30
+ puts "Creating... " + desc
31
+ Bellows::SmokeStack.create_smoke_test(project, desc, refspec, config_template_ids, test_suite_ids) if not test
32
+ else
33
+ if smoke_test["#{project}_package_builder"]['branch'] != refspec then
34
+ puts "Updating... " + desc
35
+ puts "refspec: " + refspec
36
+ Bellows::SmokeStack.update_smoke_test(smoke_test['id'], {"#{project}_package_builder" => { "branch" => refspec}}) if not test
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ desc "purge PROJECT", "Purge merged reviews from SmokeStack"
43
+ method_options :test => :boolean
44
+ def purge(project)
45
+ if not ['nova', 'glance', 'keystone'].include?(project) then
46
+ puts "ERROR: Please specify a valid project name."
47
+ exit 1
48
+ end
49
+ test = options[:test]
50
+ smoke_tests = Bellows::SmokeStack.get_smoke_tests(project)
51
+ Bellows::Gerrit.reviews(project, "merged") do |review|
52
+ refspec = review['currentPatchSet']['ref']
53
+ review_id = Bellows::Util.short_spec(refspec)
54
+ smoke_test = smoke_tests[review_id]
55
+ desc = review['owner']['name'] + ": " +review['subject']
56
+ if smoke_test
57
+ puts "Deleting... " + desc
58
+ Bellows::HTTP.delete("/smoke_tests/#{smoke_test['id']}") if not test
59
+ end
60
+ end
61
+ end
62
+
63
+ desc "update PROJECT", "Update tests suite and configuration selections."
64
+ def update(project)
65
+ if not ['nova', 'glance', 'keystone'].include?(project) then
66
+ puts "ERROR: Please specify a valid project name."
67
+ exit 1
68
+ end
69
+ test = options[:test]
70
+ smoke_tests = Bellows::SmokeStack.get_smoke_tests(project)
71
+ configs=Util.load_configs
72
+ test_suite_ids = configs['test_suite_ids'].collect {|x| x.to_s }
73
+ config_template_ids = configs['config_template_ids'].collect {|x| x.to_s }
74
+ Bellows::Gerrit.reviews(project) do |review|
75
+ refspec = review['currentPatchSet']['ref']
76
+ review_id = Bellows::Util.short_spec(refspec)
77
+ smoke_test = smoke_tests[review_id]
78
+ if smoke_test
79
+ Bellows::SmokeStack.update_smoke_test(smoke_test['id'], {"test_suite_ids" => test_suite_ids, "config_template_ids" => config_template_ids})
80
+ end
81
+ end
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,48 @@
1
+ require 'yaml'
2
+ require 'socket'
3
+
4
+ module Bellows
5
+ module Util
6
+
7
+ @@configs=nil
8
+
9
+ def self.load_configs
10
+
11
+ return @@configs if not @@configs.nil?
12
+
13
+ config_file=ENV['BELLOWS_CONFIG_FILE']
14
+ if config_file.nil? then
15
+
16
+ config_file=ENV['HOME']+File::SEPARATOR+".bellows.conf"
17
+ if not File.exists?(config_file) then
18
+ config_file="/etc/bellows.conf"
19
+ end
20
+
21
+ end
22
+
23
+ if File.exists?(config_file) then
24
+ configs=YAML.load_file(config_file)
25
+ raise_if_nil_or_empty(configs, "smokestack_url")
26
+ raise_if_nil_or_empty(configs, "smokestack_username")
27
+ raise_if_nil_or_empty(configs, "smokestack_password")
28
+ @@configs=configs
29
+ else
30
+ raise "Failed to load bellows config file. Please configure /etc/bellows.conf or create a .bellows.conf config file in your HOME directory."
31
+ end
32
+
33
+ @@configs
34
+
35
+ end
36
+
37
+ def self.raise_if_nil_or_empty(options, key)
38
+ if not options or options[key].nil? or options[key].empty? then
39
+ raise "Please specify a valid #{key.to_s} parameter."
40
+ end
41
+ end
42
+
43
+ def self.short_spec(refspec)
44
+ refspec.sub(/\/[^\/]*$/, "")
45
+ end
46
+
47
+ end
48
+ end
data/lib/bellows.rb ADDED
@@ -0,0 +1,7 @@
1
+ require 'rubygems'
2
+ require 'bellows/util'
3
+ require 'bellows/http'
4
+ require 'bellows/tasks'
5
+
6
+ module Bellows
7
+ end
data/test/helper.rb ADDED
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ require 'thor'
4
+ begin
5
+ Bundler.setup(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+ require 'test/unit'
12
+
13
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
15
+ require 'bellows'
16
+
17
+ class Test::Unit::TestCase
18
+ end
data/test/test_util.rb ADDED
@@ -0,0 +1,10 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+ require 'helper'
3
+
4
+ class UtilTest < Test::Unit::TestCase
5
+
6
+ def test_short_spec
7
+ assert_equal "123/123", Bellows::Util.short_spec("123/123/123")
8
+ end
9
+
10
+ end
metadata ADDED
@@ -0,0 +1,146 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bellows
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Dan Prince
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-10-13 00:00:00 -04:00
19
+ default_executable: bellows
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ prerelease: false
23
+ name: bundler
24
+ version_requirements: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 23
30
+ segments:
31
+ - 1
32
+ - 0
33
+ - 0
34
+ version: 1.0.0
35
+ requirement: *id001
36
+ type: :development
37
+ - !ruby/object:Gem::Dependency
38
+ prerelease: false
39
+ name: jeweler
40
+ version_requirements: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 7
46
+ segments:
47
+ - 1
48
+ - 6
49
+ - 4
50
+ version: 1.6.4
51
+ requirement: *id002
52
+ type: :development
53
+ - !ruby/object:Gem::Dependency
54
+ prerelease: false
55
+ name: thor
56
+ version_requirements: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ hash: 43
62
+ segments:
63
+ - 0
64
+ - 14
65
+ - 6
66
+ version: 0.14.6
67
+ requirement: *id003
68
+ type: :development
69
+ - !ruby/object:Gem::Dependency
70
+ prerelease: false
71
+ name: json
72
+ version_requirements: &id004 !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ hash: 11
78
+ segments:
79
+ - 1
80
+ - 4
81
+ - 6
82
+ version: 1.4.6
83
+ requirement: *id004
84
+ type: :development
85
+ description: CLI to drive SmokeStack test creation and maintenance based on Gerrit reviews.
86
+ email: dan.prince@rackspace.com
87
+ executables:
88
+ - bellows
89
+ extensions: []
90
+
91
+ extra_rdoc_files:
92
+ - LICENSE.txt
93
+ - README.md
94
+ files:
95
+ - .document
96
+ - Gemfile
97
+ - LICENSE.txt
98
+ - README.md
99
+ - Rakefile
100
+ - VERSION
101
+ - bellows.gemspec
102
+ - bin/bellows
103
+ - lib/bellows.rb
104
+ - lib/bellows/gerrit.rb
105
+ - lib/bellows/http.rb
106
+ - lib/bellows/smoke_stack.rb
107
+ - lib/bellows/tasks.rb
108
+ - lib/bellows/util.rb
109
+ - test/helper.rb
110
+ - test/test_util.rb
111
+ has_rdoc: true
112
+ homepage: http://github.com/dprince/bellows
113
+ licenses:
114
+ - MIT
115
+ post_install_message:
116
+ rdoc_options: []
117
+
118
+ require_paths:
119
+ - lib
120
+ required_ruby_version: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ">="
124
+ - !ruby/object:Gem::Version
125
+ hash: 3
126
+ segments:
127
+ - 0
128
+ version: "0"
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ none: false
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ hash: 3
135
+ segments:
136
+ - 0
137
+ version: "0"
138
+ requirements: []
139
+
140
+ rubyforge_project:
141
+ rubygems_version: 1.3.7
142
+ signing_key:
143
+ specification_version: 3
144
+ summary: Fire it up! SmokeStack automation w/ Gerrit.
145
+ test_files: []
146
+