teamcity-rest-client 0.1.0 → 0.1.1

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 CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.1.1
@@ -23,6 +23,41 @@ module TeamcityRestClient
23
23
  end
24
24
  end
25
25
 
26
+ class HttpBasicAuthentication
27
+ def initialize host, port, user, password
28
+ @host, @port, @user, @password = host, port, user, password
29
+ end
30
+
31
+ def get path
32
+ open(url(path), :http_basic_authentication => [@user, @password]).read
33
+ end
34
+
35
+ def url path
36
+ "http://#{@host}:#{@port}/httpAuth#{path}"
37
+ end
38
+
39
+ def to_s
40
+ "HttpBasicAuthentication #{@user}:#{@password}"
41
+ end
42
+ end
43
+
44
+ class Open
45
+ def initialize host, port
46
+ @host, @port = host, port
47
+ end
48
+
49
+ def get path
50
+ open(url(path)).read
51
+ end
52
+
53
+ def url path
54
+ "http://#{@host}:#{@port}#{path}"
55
+ end
56
+
57
+ def to_s
58
+ "No Authentication"
59
+ end
60
+ end
26
61
  end
27
62
 
28
63
  class REXML::Element
@@ -33,10 +68,15 @@ end
33
68
 
34
69
  class Teamcity
35
70
 
36
- attr_reader :host, :port, :user, :password
71
+ attr_reader :host, :port, :authentication
37
72
 
38
73
  def initialize host, port, user = nil, password = nil
39
- @host, @port, @user, @password = host, port, user, password
74
+ @host, @port = host, port
75
+ if user != nil && password != nil
76
+ @authentication = TeamcityRestClient::HttpBasicAuthentication.new host, port, user, password
77
+ else
78
+ @authentication = TeamcityRestClient::Open.new host, port
79
+ end
40
80
  end
41
81
 
42
82
  def project spec
@@ -47,37 +87,39 @@ class Teamcity
47
87
  end
48
88
 
49
89
  def projects
50
- doc(get(url('/app/rest/projects'))).elements.collect('//project') do |e|
90
+ doc(get('/app/rest/projects')).elements.collect('//project') do |e|
51
91
  TeamcityRestClient::Project.new(self, e.att("name"), e.att("id"), url(e.att("href")))
52
92
  end
53
93
  end
54
94
 
55
95
  def build_types
56
- doc(get(url('/app/rest/buildTypes'))).elements.collect('//buildType') do |e|
96
+ doc(get('/app/rest/buildTypes')).elements.collect('//buildType') do |e|
57
97
  TeamcityRestClient::BuildType.new(e.att("id"), e.att("name"), url(e.att("href")), e.att('projectName'), e.att('projectId'), e.att('webUrl'))
58
98
  end
59
99
  end
60
100
 
61
101
  def builds
62
- doc(get(url('/app/rest/builds')).gsub(/&buildTypeId/,'&buildTypeId')).elements.collect('//build') do |e|
102
+ doc(get('/app/rest/builds').gsub(/&buildTypeId/,'&buildTypeId')).elements.collect('//build') do |e|
63
103
  TeamcityRestClient::Build.new(e.att('id'), e.att('number'), e.att('status').to_sym, e.att('buildTypeId'), e.att('startDate'), url(e.att('href')), e.att('webUrl'))
64
104
  end
65
105
  end
66
-
67
- def url path
68
- if user != nil && password != nil
69
- "http://#{user}:#{password}@#{host}:#{port}#{path}"
70
- else
71
- "http://#{host}:#{port}#{path}"
72
- end
73
- end
74
106
 
107
+ def to_s
108
+ "Teamcity @ http://#{host}:#{port}"
109
+ end
110
+
75
111
  private
76
112
  def doc string
77
113
  REXML::Document.new string
78
114
  end
115
+
116
+ def get path
117
+ result = @authentication.get(path)
118
+ raise "Teamcity returned html, perhaps you need to use authentication??" if result =~ /.*<html.*<\/html>.*/im
119
+ result
120
+ end
79
121
 
80
- def get url
81
- open(url).read
122
+ def url path
123
+ @authentication.url(path)
82
124
  end
83
- end
125
+ end
data/spec/spec_helper.rb CHANGED
@@ -10,3 +10,7 @@ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
10
10
  RSpec.configure do |config|
11
11
 
12
12
  end
13
+
14
+ def sample_xml name
15
+ File.open("#{File.dirname(__FILE__)}/samples/#{name}.xml").read
16
+ end
@@ -1,51 +1,117 @@
1
1
  require_relative 'spec_helper'
2
2
 
3
- describe TeamcityRestClient::Project do
4
- before :each do
5
- @bt11 = stub('bt11', :id => "bt11", :name => "project1-build1", :project_id => "project1")
6
- @bt12 = stub('bt12', :id => "bt12", :name => "project1-build2", :project_id => "project1")
7
- @bt21 = stub('bt21', :id => "bt21", :name => "project2-build1", :project_id => "project2")
3
+ module TeamcityRestClient
4
+
5
+ describe Project do
6
+ before :each do
7
+ @bt11 = stub('bt11', :id => "bt11", :name => "project1-build1", :project_id => "project1")
8
+ @bt12 = stub('bt12', :id => "bt12", :name => "project1-build2", :project_id => "project1")
9
+ @bt21 = stub('bt21', :id => "bt21", :name => "project2-build1", :project_id => "project2")
8
10
 
9
- @bt11_1 = stub('bt11_1', :id => "1", :build_type_id => "bt11")
10
- @bt11_2 = stub('bt11_2', :id => "2", :build_type_id => "bt11")
11
- @bt12_33 = stub('bt12_33', :id => "33", :build_type_id => "bt12")
12
- @bt21_666 = stub('bt21_666', :id => "666", :build_type_id => "bt21")
11
+ @bt11_1 = stub('bt11_1', :id => "1", :build_type_id => "bt11")
12
+ @bt11_2 = stub('bt11_2', :id => "2", :build_type_id => "bt11")
13
+ @bt12_33 = stub('bt12_33', :id => "33", :build_type_id => "bt12")
14
+ @bt21_666 = stub('bt21_666', :id => "666", :build_type_id => "bt21")
13
15
 
14
- @tc = stub('teamcity', :build_types => [@bt11, @bt12, @bt21], :builds => [@bt11_1, @bt11_2, @bt12_33, @bt21_666])
15
- @project1 = TeamcityRestClient::Project.new @tc, "Project 1", "project1", "http://www.example.com"
16
- end
16
+ @tc = stub('teamcity', :build_types => [@bt11, @bt12, @bt21], :builds => [@bt11_1, @bt11_2, @bt12_33, @bt21_666])
17
+ @project1 = Project.new @tc, "Project 1", "project1", "http://www.example.com"
18
+ end
17
19
 
18
- describe "asking it for it's build types" do
20
+ describe "asking it for it's build types" do
21
+ before :each do
22
+ @build_types = @project1.build_types
23
+ end
24
+
25
+ it "should have only those for project 1" do
26
+ @build_types.should == [@bt11, @bt12]
27
+ end
28
+ end
29
+
30
+ describe "asking it for it's builds" do
31
+ before :each do
32
+ @builds = @project1.builds
33
+ end
34
+
35
+ it "should have only builds for project 1" do
36
+ @builds.should == [@bt11_1, @bt11_2, @bt12_33]
37
+ end
38
+ end
39
+ end
40
+
41
+ describe HttpBasicAuthentication do
19
42
  before :each do
20
- @build_types = @project1.build_types
43
+ @host, @port, @user, @password = "auth.example.com", 2233, "john", "wayne"
44
+ @auth = HttpBasicAuthentication.new @host, @port, @user, @password
45
+ @io = stub(:read => "<xml/>")
21
46
  end
22
47
 
23
- it "should have only those for project 1" do
24
- @build_types.should == [@bt11, @bt12]
48
+ describe "url" do
49
+ it "should add /httpAuth to path" do
50
+ @auth.url("/something").should == "http://auth.example.com:2233/httpAuth/something"
51
+ end
52
+ end
53
+
54
+ describe "get" do
55
+ it "should call open with http basic auth options" do
56
+ @auth.should_receive(:open).with("http://auth.example.com:2233/httpAuth/somethingElse", :http_basic_authentication=>[@user, @password]).and_return(@io)
57
+ @auth.get("/somethingElse")
58
+ end
25
59
  end
26
60
  end
27
61
 
28
- describe "asking it for it's builds" do
62
+ describe Open do
29
63
  before :each do
30
- @builds = @project1.builds
64
+ @host, @port = "auth.example.com", 2233
65
+ @auth = Open.new @host, @port
66
+ @io = stub(:read => "<xml/>")
31
67
  end
32
68
 
33
- it "should have only builds for project 1" do
34
- @builds.should == [@bt11_1, @bt11_2, @bt12_33]
69
+ describe "url" do
70
+ it "should create valid url" do
71
+ @auth.url("/something").should == "http://auth.example.com:2233/something"
72
+ end
73
+ end
74
+
75
+ describe "get" do
76
+ it "should call open with no auth options" do
77
+ @auth.should_receive(:open).with("http://auth.example.com:2233/somethingElse").and_return(@io)
78
+ @auth.get("/somethingElse")
79
+ end
35
80
  end
36
81
  end
82
+
37
83
  end
38
84
 
39
85
  describe Teamcity do
40
- describe "using basic http authentication" do
86
+ before :all do
87
+ @sample_projects_xml = sample_xml "projects"
88
+ @sample_builds_xml = sample_xml "builds"
89
+ @sample_build_types_xml = sample_xml "buildTypes"
90
+ end
91
+
92
+ describe "specifying username and password" do
41
93
  before :each do
42
- @user = "bob"
43
- @password = "marley"
44
- @tc = Teamcity.new "authtc.example.com", 9999, @user, @password
94
+ @host, @port, @user, @password = "authtc.example.com", 8877, "bob", "marley"
95
+ @authentication = mock('authentication')
96
+ TeamcityRestClient::HttpBasicAuthentication.should_receive(:new).with(@host, @port, @user, @password).and_return(@authentication)
97
+ @tc = Teamcity.new @host, @port, @user, @password
45
98
  end
46
99
 
47
- it "should create a valid url to /something" do
48
- @tc.url("/something").should == "http://bob:marley@authtc.example.com:9999/something"
100
+ it "should create HttpBasicAuthetication" do
101
+ @tc.authentication.should === @authentication
102
+ end
103
+ end
104
+
105
+ describe "specifying no username and password" do
106
+ before :each do
107
+ @host, @port = "authtc.example.com", 8877
108
+ @authentication = mock('authentication')
109
+ TeamcityRestClient::Open.should_receive(:new).with(@host, @port).and_return(@authentication)
110
+ @tc = Teamcity.new @host, @port
111
+ end
112
+
113
+ it "should create HttpBasicAuthetication" do
114
+ @tc.authentication.should === @authentication
49
115
  end
50
116
  end
51
117
 
@@ -83,9 +149,32 @@ describe Teamcity do
83
149
  end
84
150
  end
85
151
 
152
+ describe "when authentication fails" do
153
+ before :each do
154
+ @host, @port = "fail.example.com", 1234
155
+ @authentication = TeamcityRestClient::Open.new @host, @port
156
+ TeamcityRestClient::Open.should_receive(:new).and_return(@authentication)
157
+ fail_html = <<HTML
158
+
159
+ <!DOCTYPE html>
160
+ <html id="htmlId">
161
+ something
162
+ </html>
163
+ HTML
164
+
165
+ @authentication.should_receive(:get).with("/app/rest/buildTypes").and_return(fail_html)
166
+ @tc = Teamcity.new @host, @port
167
+ end
168
+
169
+ it "should raise an error" do
170
+ lambda { @tc.build_types }.should raise_error "Teamcity returned html, perhaps you need to use authentication??"
171
+ end
172
+ end
173
+
86
174
  describe "parsing xml feeds" do
87
175
  before :each do
88
- @tc = Teamcity.new "tc.example.com", 1234
176
+ @host, @port = "tc.example.com", 1234
177
+ @authentication = TeamcityRestClient::Open.new @host, @port
89
178
  end
90
179
 
91
180
  describe "projects" do
@@ -97,7 +186,9 @@ describe Teamcity do
97
186
  <project name="Apache Ant" id="project28" href="/app/rest/projects/id:project28"/>
98
187
  </projects>
99
188
  XML
100
- @tc.should_receive(:open).with("http://tc.example.com:1234/app/rest/projects").and_return(stub(:read => xml))
189
+ @authentication.should_receive(:get).with("/app/rest/projects").and_return(xml)
190
+ TeamcityRestClient::Open.should_receive(:new).and_return(@authentication)
191
+ @tc = Teamcity.new @host, @port
101
192
  @projects = @tc.projects
102
193
  end
103
194
 
@@ -131,7 +222,9 @@ XML
131
222
  projectName="Amazon API client" projectId="project54" webUrl="http://teamcity.jetbrains.com/viewType.html?buildTypeId=bt296"/>
132
223
  </buildTypes>
133
224
  XML
134
- @tc.should_receive(:open).with("http://tc.example.com:1234/app/rest/buildTypes").and_return(stub(:read => xml))
225
+ @authentication.should_receive(:get).with("/app/rest/buildTypes").and_return(xml)
226
+ TeamcityRestClient::Open.should_receive(:new).and_return(@authentication)
227
+ @tc = Teamcity.new @host, @port
135
228
  @build_types = @tc.build_types
136
229
  end
137
230
 
@@ -171,7 +264,9 @@ XML
171
264
  webUrl="http://teamcity.jetbrains.com/viewLog.html?buildId=56262&buildTypeId=bt213"/>
172
265
  </builds>
173
266
  XML
174
- @tc.should_receive(:open).with("http://tc.example.com:1234/app/rest/builds").and_return(stub(:read => xml))
267
+ @authentication.should_receive(:get).with("/app/rest/builds").and_return(xml)
268
+ TeamcityRestClient::Open.should_receive(:new).and_return(@authentication)
269
+ @tc = Teamcity.new @host, @port
175
270
  @builds = @tc.builds
176
271
  end
177
272
 
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "teamcity-rest-client"
8
- s.version = "0.1.0"
8
+ s.version = "0.1.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["simon"]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: teamcity-rest-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-10-24 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &2158820600 !ruby/object:Gem::Requirement
16
+ requirement: &2159395860 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 2.3.0
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *2158820600
24
+ version_requirements: *2159395860
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: bundler
27
- requirement: &2158820120 !ruby/object:Gem::Requirement
27
+ requirement: &2159395380 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.0.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *2158820120
35
+ version_requirements: *2159395380
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: jeweler
38
- requirement: &2158819640 !ruby/object:Gem::Requirement
38
+ requirement: &2159394900 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: 1.6.4
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *2158819640
46
+ version_requirements: *2159394900
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rcov
49
- requirement: &2158819160 !ruby/object:Gem::Requirement
49
+ requirement: &2159394420 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *2158819160
57
+ version_requirements: *2159394420
58
58
  description: Teamcity rest api client (readonly)
59
59
  email: simojenki@gmail.com
60
60
  executables: []
@@ -94,7 +94,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
94
94
  version: '0'
95
95
  segments:
96
96
  - 0
97
- hash: 667469090941014696
97
+ hash: 2223201661142505741
98
98
  required_rubygems_version: !ruby/object:Gem::Requirement
99
99
  none: false
100
100
  requirements: