dynport_tools 0.2.8 → 0.2.9
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/VERSION +1 -1
- data/dynport_tools.gemspec +2 -2
- data/lib/dynport_tools.rb +5 -0
- data/lib/dynport_tools/eta.rb +1 -1
- data/lib/dynport_tools/jenkins.rb +154 -19
- data/lib/dynport_tools/xml_file.rb +9 -4
- data/spec/dynport_tools/eta_spec.rb +1 -2
- data/spec/dynport_tools/jenkins_spec.rb +197 -41
- data/spec/dynport_tools/xml_file_spec.rb +24 -0
- data/spec/fixtures/jenkins_job.xml +30 -6
- metadata +4 -4
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.9
|
data/dynport_tools.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{dynport_tools}
|
8
|
-
s.version = "0.2.
|
8
|
+
s.version = "0.2.9"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Tobias Schwab"]
|
12
|
-
s.date = %q{2011-08-
|
12
|
+
s.date = %q{2011-08-24}
|
13
13
|
s.description = %q{Collection of various tools}
|
14
14
|
s.email = %q{tobias.schwab@dynport.de}
|
15
15
|
s.executables = ["xmldiff", "redis_dumper"]
|
data/lib/dynport_tools.rb
CHANGED
data/lib/dynport_tools/eta.rb
CHANGED
@@ -1,6 +1,3 @@
|
|
1
|
-
require "typhoeus"
|
2
|
-
require "nokogiri"
|
3
|
-
|
4
1
|
class DynportTools::Jenkins
|
5
2
|
attr_accessor :url
|
6
3
|
|
@@ -12,8 +9,49 @@ class DynportTools::Jenkins
|
|
12
9
|
@hydra ||= Typhoeus::Hydra.new
|
13
10
|
end
|
14
11
|
|
15
|
-
def
|
16
|
-
|
12
|
+
def create_project(name, xml)
|
13
|
+
post_request "createItem?name=#{escape_job_name(name)}", :headers => { "Content-Type" => "application/xml" }, :body => xml
|
14
|
+
end
|
15
|
+
|
16
|
+
def update_project(name, xml)
|
17
|
+
post_request "job/#{escape_job_name(name)}/config.xml", :headers => { "Content-Type" => "application/xml" }, :body => xml
|
18
|
+
end
|
19
|
+
|
20
|
+
def delete_project(name)
|
21
|
+
send_to_project(name, "doDelete")
|
22
|
+
end
|
23
|
+
|
24
|
+
def build_project(name)
|
25
|
+
send_to_project(name, "build")
|
26
|
+
end
|
27
|
+
|
28
|
+
def disable_project(name)
|
29
|
+
send_to_project(name, "disable")
|
30
|
+
end
|
31
|
+
|
32
|
+
def enable_project(name)
|
33
|
+
send_to_project(name, "enable")
|
34
|
+
end
|
35
|
+
|
36
|
+
def send_to_project(name, action)
|
37
|
+
post_request "job/#{escape_job_name(name)}/#{action}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def post_request(path, options = nil)
|
41
|
+
@cache = {}
|
42
|
+
Typhoeus::Request.post(*["#{url}/#{path}", options].compact)
|
43
|
+
end
|
44
|
+
|
45
|
+
def cache
|
46
|
+
@cache ||= {}
|
47
|
+
end
|
48
|
+
|
49
|
+
def escape_job_name(name)
|
50
|
+
URI.escape(name)
|
51
|
+
end
|
52
|
+
|
53
|
+
def projects_hash
|
54
|
+
cache[:projects_hash] ||= Nokogiri::XML(Typhoeus::Request.get("#{url}/api/xml").body).search("job").inject({}) do |hash, node|
|
17
55
|
url = node.at("url").inner_text.strip if node.at("url")
|
18
56
|
name = node.at("name").inner_text.strip if node.at("name")
|
19
57
|
hash[url] = { :url => url, :name => name }
|
@@ -21,9 +59,10 @@ class DynportTools::Jenkins
|
|
21
59
|
end
|
22
60
|
end
|
23
61
|
|
24
|
-
def
|
62
|
+
def project_details
|
63
|
+
return cache[:projects_details] if cache[:projects_details]
|
25
64
|
jobs = {}
|
26
|
-
|
65
|
+
projects_hash.each do |url, job|
|
27
66
|
request = Typhoeus::Request.new("#{url}config.xml")
|
28
67
|
request.on_complete do |response|
|
29
68
|
xml = Nokogiri::XML(response.body).to_s
|
@@ -32,24 +71,100 @@ class DynportTools::Jenkins
|
|
32
71
|
hydra.queue(request)
|
33
72
|
end
|
34
73
|
hydra.run
|
35
|
-
jobs
|
74
|
+
cache[:projects_details] = jobs
|
75
|
+
end
|
76
|
+
|
77
|
+
def remote_projects
|
78
|
+
project_details.inject({}) do |hash, (url, project_hash)|
|
79
|
+
hash.merge!(project_hash[:name] => RemoteProject.new(:url => project_hash[:url], :name => project_hash[:name], :xml => project_hash[:body]))
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class RemoteProject
|
84
|
+
attr_accessor :url, :name, :xml
|
85
|
+
|
86
|
+
def initialize(options = {})
|
87
|
+
options.each do |key, value|
|
88
|
+
self.send(:"#{key}=", value) if self.respond_to?(:"#{key}=")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def doc
|
93
|
+
@doc ||= Nokogiri::XML(xml) if xml
|
94
|
+
end
|
95
|
+
|
96
|
+
def md5
|
97
|
+
Digest::MD5.hexdigest(xml) if xml
|
98
|
+
end
|
99
|
+
|
100
|
+
def days_to_keep
|
101
|
+
logrotate_value_when_set("daysToKeep")
|
102
|
+
end
|
103
|
+
|
104
|
+
def num_to_keep
|
105
|
+
logrotate_value_when_set("numToKeep")
|
106
|
+
end
|
107
|
+
|
108
|
+
def logrotate_value_when_set(key)
|
109
|
+
if node = doc.at("/project/logRotator/#{key}")
|
110
|
+
node.inner_text.to_i if node.inner_text.to_i != -1
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def commands
|
115
|
+
doc.xpath("/project/builders/hudson.tasks.Shell/command").map(&:inner_text)
|
116
|
+
end
|
117
|
+
|
118
|
+
def crontab_patterns
|
119
|
+
doc.xpath("/project/triggers/hudson.triggers.TimerTrigger/spec").map(&:inner_text)
|
120
|
+
end
|
121
|
+
|
122
|
+
def disabled?
|
123
|
+
doc.at("/project/disabled/text()").to_s == "true"
|
124
|
+
end
|
125
|
+
|
126
|
+
def child_projects
|
127
|
+
if projects = doc.xpath("/project/publishers/hudson.tasks.BuildTrigger/childProjects").first
|
128
|
+
projects.inner_text.split(/\s*,\s*/)
|
129
|
+
else
|
130
|
+
[]
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def email_addresses
|
135
|
+
doc.xpath("/project/publishers/hudson.tasks.Mailer/recipients").map { |rec| rec.inner_text.split(",") }.flatten
|
136
|
+
end
|
137
|
+
|
138
|
+
def node
|
139
|
+
doc.xpath("/project/assignedNode").map { |n| n.inner_text }.first
|
140
|
+
end
|
141
|
+
|
142
|
+
def locks
|
143
|
+
doc.xpath("/project/buildWrappers/hudson.plugins.locksandlatches.LockWrapper/locks/hudson.plugins.locksandlatches.LockWrapper_-LockWaitConfig/name").map(&:inner_text)
|
144
|
+
end
|
36
145
|
end
|
37
146
|
|
38
147
|
class Project
|
39
|
-
attr_accessor :name, :commands, :crontab_pattern, :days_to_keep, :num_to_keep, :node, :child_projects
|
148
|
+
attr_accessor :name, :commands, :crontab_pattern, :days_to_keep, :num_to_keep, :node, :child_projects, :locks, :disabled, :description, :email_addresses
|
40
149
|
DEFAUL_SCM = "hudson.scm.NullSCM"
|
41
150
|
|
42
|
-
def initialize(name)
|
151
|
+
def initialize(name = nil)
|
43
152
|
self.name = name
|
44
153
|
self.commands = []
|
45
154
|
self.child_projects = []
|
155
|
+
self.email_addresses = []
|
156
|
+
self.locks = []
|
157
|
+
end
|
158
|
+
|
159
|
+
def md5
|
160
|
+
Digest::MD5.hexdigest(to_xml)
|
46
161
|
end
|
47
162
|
|
48
163
|
def to_xml
|
49
164
|
Nokogiri::XML::Builder.new(:encoding => "UTF-8") do |xml|
|
50
165
|
xml.project do
|
51
166
|
xml.actions
|
52
|
-
xml.description
|
167
|
+
xml.description *[description].compact
|
53
168
|
if days_to_keep || num_to_keep
|
54
169
|
xml.logRotator do
|
55
170
|
xml.daysToKeep days_to_keep || -1
|
@@ -58,14 +173,18 @@ class DynportTools::Jenkins
|
|
58
173
|
xml.artifactNumToKeep -1
|
59
174
|
end
|
60
175
|
end
|
61
|
-
xml.keepDependencies
|
176
|
+
xml.keepDependencies false
|
62
177
|
xml.properties
|
63
178
|
xml.scm(:class => DEFAUL_SCM)
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
179
|
+
if node
|
180
|
+
xml.assignedNode node
|
181
|
+
xml.canRoam false
|
182
|
+
else
|
183
|
+
xml.canRoam true
|
184
|
+
end
|
185
|
+
xml.disabled disabled ? true : false
|
186
|
+
xml.blockBuildWhenDownstreamBuilding false
|
187
|
+
xml.blockBuildWhenUpstreamBuilding false
|
69
188
|
xml.triggers(:class => "vector") do
|
70
189
|
if crontab_pattern
|
71
190
|
xml.send("hudson.triggers.TimerTrigger") do
|
@@ -73,11 +192,11 @@ class DynportTools::Jenkins
|
|
73
192
|
end
|
74
193
|
end
|
75
194
|
end
|
76
|
-
xml.concurrentBuild
|
195
|
+
xml.concurrentBuild false
|
77
196
|
xml.builders do
|
78
197
|
commands.each do |command|
|
79
198
|
xml.send("hudson.tasks.Shell") do
|
80
|
-
xml.command
|
199
|
+
xml.command command
|
81
200
|
end
|
82
201
|
end
|
83
202
|
end
|
@@ -92,8 +211,24 @@ class DynportTools::Jenkins
|
|
92
211
|
end
|
93
212
|
end
|
94
213
|
end
|
214
|
+
if email_addresses.any?
|
215
|
+
xml.send("hudson.tasks.Mailer") do
|
216
|
+
xml.recipients email_addresses.join(",")
|
217
|
+
xml.dontNotifyEveryUnstableBuild true
|
218
|
+
xml.sendToIndividuals false
|
219
|
+
end
|
220
|
+
end
|
95
221
|
end
|
96
222
|
xml.buildWrappers do
|
223
|
+
if locks.any?
|
224
|
+
xml.send("hudson.plugins.locksandlatches.LockWrapper") do
|
225
|
+
xml.locks do
|
226
|
+
locks.each do |lock|
|
227
|
+
xml.send("hudson.plugins.locksandlatches.LockWrapper_-LockWaitConfig") { xml.name lock }
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
97
232
|
end
|
98
233
|
end
|
99
234
|
end.to_xml
|
@@ -1,10 +1,15 @@
|
|
1
1
|
require "nokogiri"
|
2
2
|
|
3
3
|
class DynportTools::XmlFile
|
4
|
-
attr_accessor :path
|
4
|
+
attr_accessor :path, :content
|
5
5
|
|
6
|
-
def initialize(
|
7
|
-
|
6
|
+
def initialize(path_or_options = nil)
|
7
|
+
if path_or_options.is_a?(Hash)
|
8
|
+
self.path = path_or_options[:path].to_s if path_or_options[:path].to_s
|
9
|
+
self.content = path_or_options[:content]
|
10
|
+
elsif !path_or_options.nil?
|
11
|
+
self.path = path_or_options.to_s
|
12
|
+
end
|
8
13
|
end
|
9
14
|
|
10
15
|
def nodes_hash
|
@@ -12,7 +17,7 @@ class DynportTools::XmlFile
|
|
12
17
|
end
|
13
18
|
|
14
19
|
def doc
|
15
|
-
@doc ||= Nokogiri::XML(File.open(path))
|
20
|
+
@doc ||= Nokogiri::XML(content || File.open(path))
|
16
21
|
end
|
17
22
|
|
18
23
|
def parse_node(node)
|
@@ -1,5 +1,4 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
-
require "time"
|
3
2
|
|
4
3
|
describe "DynportTools::ETA" do
|
5
4
|
let(:eta) { DynportTools::ETA.new(:current => 17, :total => 100) }
|
@@ -101,7 +100,7 @@ describe "DynportTools::ETA" do
|
|
101
100
|
end
|
102
101
|
|
103
102
|
it "returns the correct string" do
|
104
|
-
DynportTools::ETA.new(:current => 10, :total => 100, :started => time - 1).to_s.should == "10.
|
103
|
+
DynportTools::ETA.new(:current => 10, :total => 100, :started => time - 1).to_s.should == "10.00%, 10.00/second, ETA: 2011-02-03T04:50:09+01:00"
|
105
104
|
end
|
106
105
|
|
107
106
|
describe "#from_time_string" do
|
@@ -5,6 +5,91 @@ require "dynport_tools/jenkins"
|
|
5
5
|
describe "DynportTools::Jenkins" do
|
6
6
|
let(:url) { "http://some.url.com:8098" }
|
7
7
|
let(:jenkins) { DynportTools::Jenkins.new(url) }
|
8
|
+
before(:each) do
|
9
|
+
Typhoeus::Request.stub!(:post).and_return nil
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "RemoteProject" do
|
13
|
+
let(:remote_project) do
|
14
|
+
xml = File.read(root.join("spec/fixtures/jenkins_job.xml"))
|
15
|
+
remote_project = DynportTools::Jenkins::RemoteProject.new(:xml => xml)
|
16
|
+
remote_project
|
17
|
+
end
|
18
|
+
|
19
|
+
it "can be initialized" do
|
20
|
+
DynportTools::Jenkins::RemoteProject.new(:url => "some/url", :name => "Some Name", :rgne => "true").should return_values(:url => "some/url",
|
21
|
+
:name => "Some Name"
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "returns the correct " do
|
26
|
+
remote_project.commands.should == [%(ssh some.host \"touch /some/path/running.pid\")]
|
27
|
+
end
|
28
|
+
|
29
|
+
it "returns an empty array when no commands found" do
|
30
|
+
DynportTools::Jenkins::RemoteProject.new(:url => "some/url", :name => "Some Name", :xml => "<project/>").commands.should be_empty
|
31
|
+
end
|
32
|
+
|
33
|
+
it "returns the correct crontab_patterns" do
|
34
|
+
remote_project.crontab_patterns.should == ["0 4 * * *"]
|
35
|
+
end
|
36
|
+
|
37
|
+
it "returns the correct childProjects" do
|
38
|
+
remote_project.child_projects.should == ["Project 2", "Project 6", "Prohect 9"]
|
39
|
+
end
|
40
|
+
|
41
|
+
it "returns the correct locks" do
|
42
|
+
remote_project.locks.should == %w(Import)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "returns the correct md5" do
|
46
|
+
remote_project.stub!(:xml).and_return "some xml"
|
47
|
+
remote_project.md5.should == "53bdfcda073f189a71901011123abf9a"
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "logrotate" do
|
51
|
+
it "returns the correct amount of days_to_keep" do
|
52
|
+
remote_project.days_to_keep.should == 7
|
53
|
+
end
|
54
|
+
|
55
|
+
it "returns nil when days_to_keep == -1" do
|
56
|
+
DynportTools::Jenkins::RemoteProject.new(:xml => "<project><logRotator><daysToKeep>-1</daysToKeep></logRotator></project>").days_to_keep.should be_nil
|
57
|
+
end
|
58
|
+
|
59
|
+
it "returns nil for num_to_keep when -1" do
|
60
|
+
remote_project.num_to_keep.should be_nil
|
61
|
+
end
|
62
|
+
|
63
|
+
it "returns the correct value for num_to_keep when set" do
|
64
|
+
DynportTools::Jenkins::RemoteProject.new(:xml => "<project><logRotator><numToKeep>20</numToKeep></logRotator></project>").num_to_keep.should == 20
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it "returns the correct disabled status" do
|
69
|
+
remote_project.should be_disabled
|
70
|
+
end
|
71
|
+
|
72
|
+
it "returns the correct email_addresses" do
|
73
|
+
remote_project.email_addresses.should == %w(test@test.xx)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "returns false when not disabled" do
|
77
|
+
DynportTools::Jenkins::RemoteProject.new(:xml => "<project><disabled>false</disabled></project>").should_not be_disabled
|
78
|
+
end
|
79
|
+
|
80
|
+
it "extracts the correct node" do
|
81
|
+
remote_project.node.should == "Import"
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "#with nothing found" do
|
85
|
+
let(:empty_remote_project) { DynportTools::Jenkins::RemoteProject.new(:xml => "<project/>") }
|
86
|
+
[:child_projects, :commands, :crontab_patterns, :locks].each do |method|
|
87
|
+
it "returns an empty array for #{method}" do
|
88
|
+
empty_remote_project.send(method).should == []
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
8
93
|
|
9
94
|
describe "Project" do
|
10
95
|
let(:job) { DynportTools::Jenkins::Project.new("Some Name") }
|
@@ -19,6 +104,14 @@ describe "DynportTools::Jenkins" do
|
|
19
104
|
job.child_projects.should == []
|
20
105
|
end
|
21
106
|
|
107
|
+
it "sets the commands to an empty array" do
|
108
|
+
job.locks.should == []
|
109
|
+
end
|
110
|
+
|
111
|
+
it "sets the email addresses to an empty array" do
|
112
|
+
job.email_addresses.should == []
|
113
|
+
end
|
114
|
+
|
22
115
|
it "sets the name" do
|
23
116
|
job.name.should == "Some Name"
|
24
117
|
end
|
@@ -38,12 +131,19 @@ describe "DynportTools::Jenkins" do
|
|
38
131
|
job.to_xml.should include("</project>")
|
39
132
|
end
|
40
133
|
|
41
|
-
%w(actions description properties
|
134
|
+
%w(actions description properties publishers buildWrappers).each do |key|
|
42
135
|
it "includes an empty node #{key}" do
|
43
136
|
doc.at("/project/#{key}").children.should be_empty
|
44
137
|
end
|
45
138
|
end
|
46
139
|
|
140
|
+
it "sets the correct email_addresses when present" do
|
141
|
+
job.email_addresses = %w(test@test.xx test2@test.xx)
|
142
|
+
doc.xpath("/project/publishers/hudson.tasks.Mailer/recipients").map(&:inner_text).should == ["test@test.xx,test2@test.xx"]
|
143
|
+
doc.at("/project/publishers/hudson.tasks.Mailer/dontNotifyEveryUnstableBuild").inner_text.should == "true"
|
144
|
+
doc.at("/project/publishers/hudson.tasks.Mailer/sendToIndividuals").inner_text.should == "false"
|
145
|
+
end
|
146
|
+
|
47
147
|
{
|
48
148
|
"keepDependencies" => "false",
|
49
149
|
"canRoam" => "true",
|
@@ -57,6 +157,11 @@ describe "DynportTools::Jenkins" do
|
|
57
157
|
end
|
58
158
|
end
|
59
159
|
|
160
|
+
it "sets disabled to true when set" do
|
161
|
+
job.disabled = true
|
162
|
+
doc.at("/project/disabled").inner_text.should == "true"
|
163
|
+
end
|
164
|
+
|
60
165
|
{ "scm" => "hudson.scm.NullSCM", "triggers" => "vector" }.each do |key, clazz|
|
61
166
|
it "sets the class of #{key} to #{clazz}" do
|
62
167
|
doc.at("/project/#{key}")["class"].should == clazz
|
@@ -68,7 +173,7 @@ describe "DynportTools::Jenkins" do
|
|
68
173
|
job.commands << "date"
|
69
174
|
shell_tasks = doc.search("project/builders/*")
|
70
175
|
shell_tasks.map(&:name).should == ["hudson.tasks.Shell", "hudson.tasks.Shell"]
|
71
|
-
shell_tasks.map { |node| node.at("command").inner_text }.should == ["
|
176
|
+
shell_tasks.map { |node| node.at("command").inner_text }.should == ["hostname", "date"]
|
72
177
|
end
|
73
178
|
|
74
179
|
it "includes crontab like triggers" do
|
@@ -88,6 +193,17 @@ describe "DynportTools::Jenkins" do
|
|
88
193
|
it "sets assignedNode when node is set" do
|
89
194
|
job.node = "processor"
|
90
195
|
doc.at("/project/assignedNode").inner_text.should == "processor"
|
196
|
+
doc.at("/project/canRoam").inner_text.should == "false"
|
197
|
+
end
|
198
|
+
|
199
|
+
it "allows setting a description" do
|
200
|
+
job.description = "some description"
|
201
|
+
doc.at("/project/description").inner_text.should == "some description"
|
202
|
+
end
|
203
|
+
|
204
|
+
it "returns the correct md5" do
|
205
|
+
job.stub(:to_xml).and_return "some test"
|
206
|
+
job.md5.should == "f1b75ac7689ff88e1ecc40c84b115785"
|
91
207
|
end
|
92
208
|
|
93
209
|
describe "with days_to_keep set" do
|
@@ -150,6 +266,22 @@ describe "DynportTools::Jenkins" do
|
|
150
266
|
end
|
151
267
|
end
|
152
268
|
end
|
269
|
+
|
270
|
+
describe "#with locks" do
|
271
|
+
let(:locks) { doc.xpath("/project/buildWrappers/hudson.plugins.locksandlatches.LockWrapper/locks/hudson.plugins.locksandlatches.LockWrapper_-LockWaitConfig") }
|
272
|
+
before(:each) do
|
273
|
+
job.locks << "exclusive3"
|
274
|
+
job.locks << "exclusive2"
|
275
|
+
end
|
276
|
+
|
277
|
+
it "sets the correct amount of locks" do
|
278
|
+
locks.count.should == 2
|
279
|
+
end
|
280
|
+
|
281
|
+
it "sets the correct locks" do
|
282
|
+
locks.map { |l| l.at("name").inner_text }.should == %w(exclusive3 exclusive2)
|
283
|
+
end
|
284
|
+
end
|
153
285
|
end
|
154
286
|
end
|
155
287
|
|
@@ -159,7 +291,15 @@ describe "DynportTools::Jenkins" do
|
|
159
291
|
end
|
160
292
|
end
|
161
293
|
|
162
|
-
describe "#
|
294
|
+
describe "#post_request" do
|
295
|
+
it "clears the local cache" do
|
296
|
+
jenkins.instance_variable_set("@cache", { :a => 1 })
|
297
|
+
jenkins.post_request("some/path")
|
298
|
+
jenkins.instance_variable_get("@cache").should == {}
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
describe "#projects_hash" do
|
163
303
|
let(:body) do
|
164
304
|
html =<<-HTML
|
165
305
|
<hudson>
|
@@ -194,19 +334,45 @@ describe "DynportTools::Jenkins" do
|
|
194
334
|
|
195
335
|
it "fetches the correct url" do
|
196
336
|
Typhoeus::Request.should_receive(:get).with("http://some.url.com:8098/api/xml")
|
197
|
-
jenkins.
|
337
|
+
jenkins.projects_hash
|
198
338
|
end
|
199
339
|
|
200
|
-
it "returns the correct
|
201
|
-
jobs = jenkins.
|
340
|
+
it "returns the correct projects_hash" do
|
341
|
+
jobs = jenkins.projects_hash
|
202
342
|
jobs["http://hudson.host:8080/job/Job1/"].should == { :url => "http://hudson.host:8080/job/Job1/", :name => "Job 1"}
|
203
343
|
jobs["http://hudson.host:8080/job/Job2/"].should == { :url => "http://hudson.host:8080/job/Job2/", :name => "Job 2"}
|
204
344
|
end
|
205
345
|
end
|
346
|
+
|
347
|
+
it "sends the correct Typhoeus request when creating a project" do
|
348
|
+
xml = "some_xml"
|
349
|
+
Typhoeus::Request.should_receive(:post).with("http://some.url.com:8098/createItem?name=Test%20Job",
|
350
|
+
:headers => { "Content-Type" => "application/xml" }, :body => "some_xml"
|
351
|
+
)
|
352
|
+
jenkins.create_project("Test Job", xml)
|
353
|
+
end
|
354
|
+
|
355
|
+
it "sends the correct request when updating a project" do
|
356
|
+
xml = "some_update"
|
357
|
+
Typhoeus::Request.should_receive(:post).with("http://some.url.com:8098/job/Test%20Job/config.xml",
|
358
|
+
:headers => { "Content-Type" => "application/xml" }, :body => "some_update"
|
359
|
+
)
|
360
|
+
jenkins.update_project("Test Job", xml)
|
361
|
+
end
|
362
|
+
|
363
|
+
{
|
364
|
+
:delete_project => "doDelete", :build_project => "build", :disable_project => "disable",
|
365
|
+
:enable_project => "enable"
|
366
|
+
}.each do |method, action|
|
367
|
+
it "posts to the correct url when calling #{action}" do
|
368
|
+
Typhoeus::Request.should_receive(:post).with("http://some.url.com:8098/job/Test%20Job/#{action}")
|
369
|
+
jenkins.send(method, "Test Job")
|
370
|
+
end
|
371
|
+
end
|
206
372
|
|
207
|
-
describe "#
|
373
|
+
describe "#project_details" do
|
208
374
|
before(:each) do
|
209
|
-
jenkins.stub!(:
|
375
|
+
jenkins.stub!(:projects_hash).and_return(
|
210
376
|
"http://hudson.host:8080/job/Job1/" => { :url => "http://hudson.host:8080/job/Job1/", :name => "Job 1"},
|
211
377
|
"http://hudson.host:8080/job/Job2/" => { :url => "http://hudson.host:8080/job/Job2/", :name => "Job 2"}
|
212
378
|
)
|
@@ -217,7 +383,7 @@ describe "DynportTools::Jenkins" do
|
|
217
383
|
response2 = Typhoeus::Response.new(:code => 200, :headers => "", :body => "<root><a>test2</a><b></b></root>")
|
218
384
|
jenkins.hydra.stub(:get, "http://hudson.host:8080/job/Job1/config.xml").and_return(response1)
|
219
385
|
jenkins.hydra.stub(:get, "http://hudson.host:8080/job/Job2/config.xml").and_return(response2)
|
220
|
-
details = jenkins.
|
386
|
+
details = jenkins.project_details
|
221
387
|
details.should be_an_instance_of(Hash)
|
222
388
|
details["http://hudson.host:8080/job/Job2/"].should == {
|
223
389
|
:body=>"<?xml version=\"1.0\"?>\n<root>\n <a>test2</a>\n <b/>\n</root>\n",
|
@@ -228,39 +394,29 @@ describe "DynportTools::Jenkins" do
|
|
228
394
|
:md5=>"14fa3890bea86820f7e45ce7f5a3ada4", :name=>"Job 1", :url=>"http://hudson.host:8080/job/Job1/"
|
229
395
|
}
|
230
396
|
end
|
397
|
+
end
|
398
|
+
|
399
|
+
describe "#remote_projects" do
|
400
|
+
before(:each) do
|
401
|
+
jenkins.stub(:project_details).and_return({})
|
402
|
+
end
|
403
|
+
it "calls project_details" do
|
404
|
+
jenkins.should_receive(:project_details).and_return({})
|
405
|
+
jenkins.remote_projects
|
406
|
+
end
|
231
407
|
|
232
|
-
it "
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
xml.triggers(:class => "vector")
|
245
|
-
xml.concurrentBuild false
|
246
|
-
xml.builders do
|
247
|
-
xml.send("hudson.tasks.Shell") do
|
248
|
-
xml.command %(#!/bin/sh\nssh some.host "cd /some/path && ./script/runner -e production 'Some.command'")
|
249
|
-
end
|
250
|
-
end
|
251
|
-
xml.publishers
|
252
|
-
xml.buildWrappers do
|
253
|
-
xml.send("hudson.plugins.locksandlatches.LockWrapper") do
|
254
|
-
xml.locks do
|
255
|
-
xml.send("hudson.plugins.locksandlatches.LockWrapper_-LockWaitConfig") do
|
256
|
-
xml.name "Popularities"
|
257
|
-
end
|
258
|
-
end
|
259
|
-
end
|
260
|
-
end
|
261
|
-
}
|
262
|
-
end
|
263
|
-
builder.to_xml.should == Nokogiri::XML(File.read(root.join("spec/fixtures/jenkins_job.xml"))).to_s
|
408
|
+
it "returns a hash" do
|
409
|
+
jenkins.remote_projects.should be_kind_of(Hash)
|
410
|
+
end
|
411
|
+
|
412
|
+
it "sets RemoteProject as values for hash" do
|
413
|
+
jenkins.should_receive(:project_details).and_return(
|
414
|
+
"url1" => { :name => "Project 1", :body => "some xml", :url => "url1" },
|
415
|
+
"url2" => { :name => "Project 2", :body => "some other xml", :url => "url2" }
|
416
|
+
)
|
417
|
+
remote_projects = jenkins.remote_projects
|
418
|
+
remote_projects.values.map(&:class).should == [DynportTools::Jenkins::RemoteProject, DynportTools::Jenkins::RemoteProject]
|
419
|
+
remote_projects["Project 1"].should return_values(:url => "url1", :name => "Project 1", :xml => "some xml")
|
264
420
|
end
|
265
421
|
end
|
266
422
|
end
|
@@ -11,6 +11,30 @@ describe "DynportTools::XmlFile" do
|
|
11
11
|
it "sets the correct path" do
|
12
12
|
DynportTools::XmlFile.new(FILE1).path.should == FILE1.to_s
|
13
13
|
end
|
14
|
+
|
15
|
+
it "also sets the pathwhen given as hash" do
|
16
|
+
DynportTools::XmlFile.new(:path => FILE1).path.should == FILE1.to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
it "sets content when given" do
|
20
|
+
DynportTools::XmlFile.new(:content => "some content").content.should == "some content"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#doc" do
|
25
|
+
it "opens a file when set" do
|
26
|
+
f = double("f")
|
27
|
+
File.should_receive(:open).with("/some/path").and_return f
|
28
|
+
Nokogiri.should_receive(:XML).with(f).and_return nil
|
29
|
+
DynportTools::XmlFile.new("/some/path").doc
|
30
|
+
end
|
31
|
+
|
32
|
+
it "parses the direct content when present" do
|
33
|
+
file = DynportTools::XmlFile.new
|
34
|
+
file.content = "some content"
|
35
|
+
Nokogiri.should_receive(:XML).with("some content").and_return nil
|
36
|
+
file.doc
|
37
|
+
end
|
14
38
|
end
|
15
39
|
|
16
40
|
describe "#nodes_hash" do
|
@@ -2,27 +2,51 @@
|
|
2
2
|
<project>
|
3
3
|
<actions/>
|
4
4
|
<description></description>
|
5
|
+
<logRotator>
|
6
|
+
<daysToKeep>7</daysToKeep>
|
7
|
+
<numToKeep>-1</numToKeep>
|
8
|
+
<artifactDaysToKeep>-1</artifactDaysToKeep>
|
9
|
+
<artifactNumToKeep>-1</artifactNumToKeep>
|
10
|
+
</logRotator>
|
5
11
|
<keepDependencies>false</keepDependencies>
|
6
12
|
<properties/>
|
7
13
|
<scm class="hudson.scm.NullSCM"/>
|
14
|
+
<assignedNode>Import</assignedNode>
|
8
15
|
<canRoam>true</canRoam>
|
9
|
-
<disabled>
|
16
|
+
<disabled>true</disabled>
|
10
17
|
<blockBuildWhenDownstreamBuilding>false</blockBuildWhenDownstreamBuilding>
|
11
18
|
<blockBuildWhenUpstreamBuilding>false</blockBuildWhenUpstreamBuilding>
|
12
|
-
<triggers class="vector"
|
19
|
+
<triggers class="vector">
|
20
|
+
<hudson.triggers.TimerTrigger>
|
21
|
+
<spec>0 4 * * *</spec>
|
22
|
+
</hudson.triggers.TimerTrigger>
|
23
|
+
</triggers>
|
13
24
|
<concurrentBuild>false</concurrentBuild>
|
14
25
|
<builders>
|
15
26
|
<hudson.tasks.Shell>
|
16
|
-
<command
|
17
|
-
ssh some.host "cd /some/path && ./script/runner -e production 'Some.command'"</command>
|
27
|
+
<command>ssh some.host "touch /some/path/running.pid"</command>
|
18
28
|
</hudson.tasks.Shell>
|
19
29
|
</builders>
|
20
|
-
<publishers
|
30
|
+
<publishers>
|
31
|
+
<hudson.tasks.BuildTrigger>
|
32
|
+
<childProjects>Project 2,Project 6, Prohect 9</childProjects>
|
33
|
+
<threshold>
|
34
|
+
<name>SUCCESS</name>
|
35
|
+
<ordinal>0</ordinal>
|
36
|
+
<color>BLUE</color>
|
37
|
+
</threshold>
|
38
|
+
</hudson.tasks.BuildTrigger>
|
39
|
+
<hudson.tasks.Mailer>
|
40
|
+
<recipients>test@test.xx</recipients>
|
41
|
+
<dontNotifyEveryUnstableBuild>true</dontNotifyEveryUnstableBuild>
|
42
|
+
<sendToIndividuals>false</sendToIndividuals>
|
43
|
+
</hudson.tasks.Mailer>
|
44
|
+
</publishers>
|
21
45
|
<buildWrappers>
|
22
46
|
<hudson.plugins.locksandlatches.LockWrapper>
|
23
47
|
<locks>
|
24
48
|
<hudson.plugins.locksandlatches.LockWrapper_-LockWaitConfig>
|
25
|
-
<name>
|
49
|
+
<name>Import</name>
|
26
50
|
</hudson.plugins.locksandlatches.LockWrapper_-LockWaitConfig>
|
27
51
|
</locks>
|
28
52
|
</hudson.plugins.locksandlatches.LockWrapper>
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynport_tools
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 5
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 9
|
10
|
+
version: 0.2.9
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Tobias Schwab
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-08-
|
18
|
+
date: 2011-08-24 00:00:00 +02:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|