go_api_client 0.5.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +4 -0
  3. data/.travis.yml +26 -0
  4. data/README.md +86 -0
  5. data/go_api_client.gemspec +11 -11
  6. data/lib/go_api_client/api/abstract_api.rb +12 -0
  7. data/lib/go_api_client/api/cctray.rb +53 -0
  8. data/lib/go_api_client/api/config.rb +60 -0
  9. data/lib/go_api_client/api/feed.rb +39 -0
  10. data/lib/go_api_client/api/job.rb +34 -0
  11. data/lib/go_api_client/api/pipeline.rb +87 -0
  12. data/lib/go_api_client/api/properties.rb +43 -0
  13. data/lib/go_api_client/api/stage.rb +45 -0
  14. data/lib/go_api_client/attribute_helper.rb +9 -0
  15. data/lib/go_api_client/client.rb +20 -0
  16. data/lib/go_api_client/domain/artifact.rb +16 -0
  17. data/lib/go_api_client/domain/author.rb +22 -0
  18. data/lib/go_api_client/domain/changeset.rb +13 -0
  19. data/lib/go_api_client/domain/config/job.rb +15 -0
  20. data/lib/go_api_client/domain/config/pipeline.rb +15 -0
  21. data/lib/go_api_client/domain/config/stage.rb +15 -0
  22. data/lib/go_api_client/domain/entry.rb +13 -0
  23. data/lib/go_api_client/domain/feed.rb +13 -0
  24. data/lib/go_api_client/domain/internal_cache.rb +28 -0
  25. data/lib/go_api_client/domain/job.rb +17 -0
  26. data/lib/go_api_client/domain/material.rb +14 -0
  27. data/lib/go_api_client/domain/pipeline.rb +27 -0
  28. data/lib/go_api_client/domain/project.rb +14 -0
  29. data/lib/go_api_client/domain/scheduled_job.rb +12 -0
  30. data/lib/go_api_client/domain/stage.rb +28 -0
  31. data/lib/go_api_client/domain/user.rb +30 -0
  32. data/lib/go_api_client/http_fetcher.rb +73 -48
  33. data/lib/go_api_client/parsers/artifact_parser.rb +17 -0
  34. data/lib/go_api_client/parsers/author_parser.rb +24 -0
  35. data/lib/go_api_client/parsers/changeset.rb +26 -0
  36. data/lib/go_api_client/parsers/config/job_parser.rb +48 -0
  37. data/lib/go_api_client/parsers/config/pipeline_parser.rb +42 -0
  38. data/lib/go_api_client/parsers/config/stage_parser.rb +33 -0
  39. data/lib/go_api_client/parsers/entry_parser.rb +27 -0
  40. data/lib/go_api_client/parsers/feed_parser.rb +27 -0
  41. data/lib/go_api_client/parsers/job_parser.rb +47 -0
  42. data/lib/go_api_client/parsers/material_parser.rb +29 -0
  43. data/lib/go_api_client/parsers/parser_helper.rb +11 -0
  44. data/lib/go_api_client/parsers/pipeline_parser.rb +30 -0
  45. data/lib/go_api_client/parsers/project_parser.rb +26 -0
  46. data/lib/go_api_client/parsers/scheduled_job_parser.rb +28 -0
  47. data/lib/go_api_client/parsers/stage_parser.rb +31 -0
  48. data/lib/go_api_client/parsers/user_parser.rb +12 -0
  49. data/lib/go_api_client/version.rb +4 -4
  50. data/lib/go_api_client.rb +56 -110
  51. data/test/go_api_client/artifact_test.rb +8 -8
  52. data/test/go_api_client/author_test.rb +27 -0
  53. data/test/go_api_client/building_test.rb +21 -19
  54. data/test/go_api_client/{atom/entry_test.rb → entry_test.rb} +8 -8
  55. data/test/go_api_client/job_test.rb +15 -14
  56. data/test/go_api_client/pipeline_test.rb +24 -27
  57. data/test/go_api_client/stage_test.rb +21 -74
  58. data/test/go_api_client/user_test.rb +15 -20
  59. metadata +108 -78
  60. data/.init.sh +0 -8
  61. data/.rbenv-gemsets +0 -1
  62. data/.ruby-version +0 -1
  63. data/.rvmrc +0 -1
  64. data/.yardopts +0 -6
  65. data/Gemfile.lock +0 -32
  66. data/README.textile +0 -64
  67. data/lib/go_api_client/artifact.rb +0 -27
  68. data/lib/go_api_client/atom/author.rb +0 -42
  69. data/lib/go_api_client/atom/entry.rb +0 -34
  70. data/lib/go_api_client/atom/feed.rb +0 -40
  71. data/lib/go_api_client/atom/feed_page.rb +0 -49
  72. data/lib/go_api_client/atom.rb +0 -4
  73. data/lib/go_api_client/commit.rb +0 -30
  74. data/lib/go_api_client/helpers/simple_attribute_support.rb +0 -11
  75. data/lib/go_api_client/helpers.rb +0 -1
  76. data/lib/go_api_client/job.rb +0 -68
  77. data/lib/go_api_client/pipeline.rb +0 -48
  78. data/lib/go_api_client/stage.rb +0 -57
  79. data/lib/go_api_client/user.rb +0 -36
  80. data/test/go_api_client/atom/author_test.rb +0 -27
  81. data/test/go_api_client/atom/feed_page_test.rb +0 -41
  82. data/test/go_api_client/atom/feed_test.rb +0 -39
  83. data/test/go_api_client/commit_test.rb +0 -38
  84. data/test/schedule_test.rb +0 -12
@@ -9,6 +9,7 @@ module GoApiClient
9
9
 
10
10
  class HttpError < ConnectionError
11
11
  attr_reader :http_code
12
+
12
13
  def initialize(msg, http_code)
13
14
  super(msg)
14
15
  @http_code = http_code
@@ -16,23 +17,23 @@ module GoApiClient
16
17
  end
17
18
 
18
19
  NET_HTTP_EXCEPTIONS = [
19
- EOFError,
20
- Errno::ECONNABORTED,
21
- Errno::ECONNREFUSED,
22
- Errno::ECONNRESET,
23
- Errno::ECONNRESET, EOFError,
24
- Errno::EINVAL,
25
- Errno::ETIMEDOUT,
26
- Net::HTTPBadResponse,
27
- Net::HTTPClientError,
28
- Net::HTTPError,
29
- Net::HTTPFatalError,
30
- Net::HTTPHeaderSyntaxError,
31
- Net::HTTPRetriableError,
32
- Net::HTTPServerException,
33
- Net::ProtocolError,
34
- SocketError,
35
- Timeout::Error,
20
+ EOFError,
21
+ Errno::ECONNABORTED,
22
+ Errno::ECONNREFUSED,
23
+ Errno::ECONNRESET,
24
+ Errno::ECONNRESET, EOFError,
25
+ Errno::EINVAL,
26
+ Errno::ETIMEDOUT,
27
+ Net::HTTPBadResponse,
28
+ Net::HTTPClientError,
29
+ Net::HTTPError,
30
+ Net::HTTPFatalError,
31
+ Net::HTTPHeaderSyntaxError,
32
+ Net::HTTPRetriableError,
33
+ Net::HTTPServerException,
34
+ Net::ProtocolError,
35
+ SocketError,
36
+ Timeout::Error,
36
37
  ]
37
38
 
38
39
  NET_HTTP_EXCEPTIONS << OpenSSL::SSL::SSLError if defined?(OpenSSL)
@@ -42,12 +43,13 @@ module GoApiClient
42
43
  def initialize(options={})
43
44
  @username = options[:username]
44
45
  @password = options[:password]
46
+ @ssl_verify_mode = options[:ssl_verify_mode]
45
47
  end
46
48
 
47
49
  %w(get post).each do |meth|
48
50
  class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
49
51
  def #{meth}!(url, options={})
50
- response_body = #{meth}(url, options)
52
+ response_body = #{meth}(url, options).body
51
53
  if failure?
52
54
  message = "Could not fetch url \#{url}."
53
55
  GoApiClient.logger.error("\#{message} The response returned status \#{status} with body `\#{response_body}'")
@@ -78,48 +80,71 @@ module GoApiClient
78
80
  private
79
81
 
80
82
 
81
- def get(url, options={})
82
- uri = URI.parse(url)
83
+ def get(url, options={}, limit = 10)
84
+ raise ArgumentError, 'HTTP redirect too deep' if limit == 0
85
+ uri = URI.parse(url)
83
86
 
84
- password = options[:password] || uri.password || @password
85
- username = options[:username] || uri.user || @username
86
- params = options[:params] || {}
87
+ password = options[:password] || uri.password || @password
88
+ username = options[:username] || uri.user || @username
89
+ ssl_verify_mode = options[:ssl_verify_mode] || @ssl_verify_mode
90
+ params = options[:params] || {}
87
91
 
88
- uri.query = URI.encode_www_form(params) if params.any?
92
+ uri.query = URI.encode_www_form(params) if params.any?
89
93
 
90
- http = Net::HTTP.new(uri.host, uri.port)
91
- http.use_ssl = uri.scheme == 'https'
94
+ http = Net::HTTP.new(uri.host, uri.port)
95
+ http.use_ssl = uri.scheme == 'https'
96
+ http.verify_mode = ssl_verify_mode == 0 ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
92
97
 
93
- @response = http.start do |http|
94
- req = Net::HTTP::Get.new(uri.request_uri)
95
- req.basic_auth(username, password) if username || password
96
- http.request(req)
97
- end
98
- return @response.body
98
+
99
+ response = http.start do |http|
100
+ req = Net::HTTP::Get.new(uri.request_uri)
101
+ req.basic_auth(username, password) if username || password
102
+ http.request(req)
99
103
  end
100
104
 
101
- def post(url, options={})
102
- uri = URI.parse(url)
105
+ case response
106
+ when Net::HTTPRedirection then
107
+ @response = get(response['location'], options, limit - 1)
108
+ else
109
+ @response = response
110
+ end
103
111
 
104
- password = options[:password] || uri.password || @password
105
- username = options[:username] || uri.user || @username
106
- params = options[:params] || {}
107
- headers = options[:headers] || {}
112
+ @response
113
+ end
108
114
 
109
- http = Net::HTTP.new(uri.host, uri.port)
110
- http.use_ssl = uri.scheme == 'https'
115
+ def post(url, options={}, limit = 10)
116
+ raise ArgumentError, 'HTTP redirect too deep' if limit == 0
117
+ uri = URI.parse(url)
111
118
 
112
- req = Net::HTTP::Post.new(uri.request_uri)
119
+ password = options[:password] || uri.password || @password
120
+ username = options[:username] || uri.user || @username
121
+ ssl_verify_mode = options[:ssl_verify_mode] || @ssl_verify_mode
122
+ params = options[:params] || {}
123
+ headers = options[:headers] || {}
113
124
 
114
- headers.each do |header_name, value|
115
- req[header_name] = value
116
- end
125
+ http = Net::HTTP.new(uri.host, uri.port)
126
+ http.use_ssl = uri.scheme == 'https'
127
+ http.verify_mode = ssl_verify_mode == 0 ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
117
128
 
118
- req.basic_auth(username, password) if username || password
129
+ req = Net::HTTP::Post.new(uri.request_uri)
119
130
 
120
- req.set_form_data(params)
121
- @response = http.request(req)
122
- return @response.body
131
+ headers.each do |header_name, value|
132
+ req[header_name] = value
123
133
  end
134
+
135
+ req.basic_auth(username, password) if username || password
136
+
137
+ req.set_form_data(params)
138
+ response = http.request(req)
139
+
140
+ case response
141
+ when Net::HTTPRedirection then
142
+ @response = post(response['location'], options, limit - 1)
143
+ else
144
+ @response = response
145
+ end
146
+
147
+ @response
148
+ end
124
149
  end
125
150
  end
@@ -0,0 +1,17 @@
1
+ module GoApiClient
2
+ module Parsers
3
+ class Artifact
4
+ class << self
5
+ def parse(uri, root)
6
+ GoApiClient::Domain::Artifact.new(
7
+ {
8
+ :base_uri => uri,
9
+ :src => root.attributes['src'].value,
10
+ :dest => root.attributes['dest'].value,
11
+ :artifact_type => root.attributes['type'].value,
12
+ })
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,24 @@
1
+ module GoApiClient
2
+ module Parsers
3
+ class Author
4
+ class << self
5
+ def parse(root)
6
+ name = root.xpath('xmlns:name').first.content
7
+ email = root.xpath('xmlns:email').first.content rescue nil
8
+ uri = root.xpath('xmlns:uri').first.content rescue nil
9
+ if email.nil? || email.empty?
10
+ if name =~ /(.*) <(.+?)>/
11
+ name, email = $1, $2
12
+ end
13
+ end
14
+ GoApiClient::Domain::Author.new(
15
+ {
16
+ :name => name,
17
+ :email => email,
18
+ :uri => uri
19
+ })
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,26 @@
1
+ require 'time'
2
+
3
+ module GoApiClient
4
+ module Parsers
5
+ class Changeset
6
+ class << self
7
+ def parse(root)
8
+ message = root.xpath('./message').first.content if root.xpath('./message').first
9
+ parsed_user = GoApiClient::Parsers::User.parse(root.xpath('./user').first) if root.xpath('./user').first
10
+ files = root.xpath('./file').collect do |element|
11
+ {:name => element.attributes['name'].value, :action => element.attributes['action'].value}
12
+ end if root.xpath('./file').first
13
+ GoApiClient::Domain::Changeset.new(
14
+ {
15
+ :uri => root.attributes['changesetUri'].value,
16
+ :checkin_time => Time.parse(root.xpath('./checkinTime').first.content).utc,
17
+ :revision => root.xpath('./revision').first.content,
18
+ :message => message,
19
+ :parsed_user => parsed_user,
20
+ :files => files
21
+ })
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,48 @@
1
+ module GoApiClient
2
+ module Parsers
3
+ module Config
4
+ class Job < GoApiClient::Parsers::Helper
5
+ class << self
6
+ def parse(root)
7
+ tasks = root.xpath('./tasks/exec').collect do |element|
8
+ {
9
+ :command => element.attributes['command'].value,
10
+ :args => element.xpath('./arg').first ? element.xpath('./arg').collect do |arg_element|
11
+ arg_element.content
12
+ end : nil,
13
+ :runif => element.xpath('./runif').first ? element.xpath('./runif').first.attributes['status'].value : nil
14
+ }
15
+ end if root.xpath('./tasks/exec')
16
+
17
+ resources = root.xpath('./resources/resource').collect do |element|
18
+ element.content
19
+ end if root.xpath('./resources/resource')
20
+
21
+ tabs = root.xpath('./tabs/tab').collect do |element|
22
+ {:name => element.attributes['name'].value, :path => element.attributes['path'].value}
23
+ end if root.xpath('./tabs/tab')
24
+
25
+ artifacts = root.xpath('./artifacts/artifact').collect do |element|
26
+ {:src => element.attributes['src'].value, :dst => element.attributes['dst'] ? element.attributes['dst'].value : nil}
27
+ end if root.xpath('./tabs/tab')
28
+
29
+ test_artifacts = root.xpath('./artifacts/test').collect do |element|
30
+ {:src => element.attributes['src'].value, :dst => element.attributes['dst'] ? element.attributes['dst'].value : nil}
31
+ end if root.xpath('./artifacts/test')
32
+
33
+ GoApiClient::Domain::Config::Job.new(
34
+ {
35
+ :name => root.attributes['name'].value,
36
+ :parsed_tabs => tabs,
37
+ :parsed_tasks => tasks,
38
+ :parsed_resources => resources,
39
+ :parsed_artifacts => artifacts,
40
+ :parsed_test_artifacts => test_artifacts
41
+ })
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,42 @@
1
+ module GoApiClient
2
+ module Parsers
3
+ module Config
4
+ class Pipeline < GoApiClient::Parsers::Helper
5
+ class << self
6
+ def parse(root)
7
+ template = root.attributes['template'].value if root.attributes['template']
8
+ params = root.xpath('./params/param').collect do |element|
9
+ {:name => element.attributes['name'].value, :value => element.content}
10
+ end if root.xpath('./params/param')
11
+
12
+ env_vars = root.xpath('./environmentvariables/variable').collect do |element|
13
+ secure = true if element.attributes['name']
14
+ value_element = element.xpath('./value').first ? element.xpath('./value') : element.xpath('./encryptedValue')
15
+ {:name => element.attributes['name'].value, :secure => secure, :value => value_element.first.content}
16
+ end if root.xpath('./params/param')
17
+
18
+ timer = root.xpath('./timer').first.content if root.xpath('./timer').first
19
+ label_template = root.attributes['labeltemplate'].value if root.attributes['labeltemplate']
20
+
21
+ stages = root.xpath('./stage').collect do |element|
22
+ GoApiClient::Parsers::Config::Stage.parse(element)
23
+ end
24
+
25
+ GoApiClient::Domain::Config::Pipeline.new(
26
+ {
27
+ :name => root.attributes['name'].value,
28
+ :locked => root.attributes['isLocked'] ? root.attributes['isLocked'].value : 'false',
29
+ :label_template => label_template,
30
+ :timer => timer,
31
+ :template => template,
32
+ :parsed_params => params,
33
+ :parsed_env_vars => env_vars,
34
+ :parsed_stages => stages
35
+ })
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,33 @@
1
+ module GoApiClient
2
+ module Parsers
3
+ module Config
4
+ class Stage < GoApiClient::Parsers::Helper
5
+ class << self
6
+ def parse(root)
7
+
8
+ jobs = root.xpath('./jobs/job').collect do |element|
9
+ GoApiClient::Parsers::Config::Job.parse(element)
10
+ end if root.xpath('./jobs/job')
11
+
12
+ env_vars = root.xpath('./environmentvariables/variable').collect do |element|
13
+ secure = true if element.attributes['name']
14
+ value_element = element.xpath('./value').first ? element.xpath('./value') : element.xpath('./encryptedValue')
15
+ {:name => element.attributes['name'].value, :secure => secure, :value => value_element.first.content}
16
+ end if root.xpath('./params/param')
17
+
18
+ GoApiClient::Domain::Config::Stage.new(
19
+ {
20
+ :name => root.attributes['name'].value,
21
+ :clean_working_dir => root.attributes['cleanWorkingDir'] ? root.attributes['cleanWorkingDir'].value : 'false',
22
+ :fetch_materials => root.attributes['fetchMaterials'] ? root.attributes['fetchMaterials'].value : 'false',
23
+ :approval => root.xpath('./approval').first ? root.xpath('./approval').first.attributes['type'].value : 'automatic',
24
+ :parsed_jobs => jobs,
25
+ :parsed_env_vars => env_vars
26
+ })
27
+ end
28
+
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,27 @@
1
+ require 'time'
2
+
3
+ module GoApiClient
4
+ module Parsers
5
+ class Entry < GoApiClient::Parsers::Helper
6
+ class << self
7
+ def parse(root)
8
+ GoApiClient::Domain::Entry.new(
9
+ {
10
+ :title => root.xpath('xmlns:title').first.content,
11
+ :id => root.xpath('xmlns:id').first.content,
12
+ :updated => Time.parse(root.xpath('xmlns:updated').first.content).utc,
13
+ :stage_uri => href_from(root.xpath("xmlns:link[@type='application/vnd.go+xml' and @rel='alternate']")),
14
+ :pipeline_uri => href_from(root.xpath("xmlns:link[@type='application/vnd.go+xml' and @rel='http://www.thoughtworks-studios.com/ns/relations/go/pipeline']")),
15
+ :parsed_authors => root.xpath('xmlns:author').collect do |element|
16
+ GoApiClient::Parsers::Author.parse(element)
17
+ end,
18
+ :parsed_categories => root.xpath('xmlns:category').collect do |element|
19
+ {:term => element.attributes['term'].value, :label => element.attributes['label'].value}
20
+ end,
21
+ })
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,27 @@
1
+ require 'time'
2
+
3
+ module GoApiClient
4
+ module Parsers
5
+ class Feed < GoApiClient::Parsers::Helper
6
+ class << self
7
+ def parse(root)
8
+ GoApiClient::Domain::Feed.new(
9
+ {
10
+ :title => root.xpath('xmlns:title').first.content,
11
+ :id => root.xpath('xmlns:id').first.content,
12
+ :self_uri => href_from(root.xpath("xmlns:link[@rel='self']")),
13
+ :next_uri => href_from(root.xpath("xmlns:link[@rel='next']")),
14
+ :updated => Time.parse(root.xpath('xmlns:updated').first.content).utc,
15
+ :parsed_authors => root.xpath('xmlns:author').collect do |element|
16
+ GoApiClient::Parsers::Author.parse(element)
17
+ end,
18
+ :parsed_entries => root.xpath('xmlns:entry').collect do |element|
19
+ GoApiClient::Parsers::Entry.parse(element)
20
+ end
21
+ })
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
@@ -0,0 +1,47 @@
1
+ require 'time'
2
+
3
+ module GoApiClient
4
+ module Parsers
5
+ class Job < GoApiClient::Parsers::Helper
6
+
7
+ PROPERTIES = {
8
+ :duration => :cruise_job_duration,
9
+ :result => :cruise_job_result,
10
+ :scheduled => :cruise_timestamp_01_scheduled,
11
+ :assigned => :cruise_timestamp_02_assigned,
12
+ :preparing => :cruise_timestamp_03_preparing,
13
+ :building => :cruise_timestamp_04_building,
14
+ :completing => :cruise_timestamp_05_completing,
15
+ :completed => :cruise_timestamp_06_completed,
16
+ }
17
+
18
+ class << self
19
+ def parse(root)
20
+ artifacts_uri = root.xpath('./artifacts').first.attributes['baseUri'].value
21
+ attributes = {
22
+ :artifacts_uri => artifacts_uri,
23
+ :self_uri => href_from(root.xpath("./link[@rel='self']")),
24
+ :id => root.xpath('./id').first.content,
25
+ :name => root.attributes['name'].value,
26
+ :parsed_artifacts => root.xpath('./artifacts/artifact').collect do |artifact_element|
27
+ GoApiClient::Parsers::Artifact.parse(artifacts_uri, artifact_element)
28
+ end
29
+ }
30
+
31
+ PROPERTIES.each do |variable, property_name|
32
+ property_value = root.xpath("./properties/property[@name='#{property_name}']").first.content rescue nil
33
+ next if property_value.nil? || property_value.empty?
34
+ if property_name =~ /timestamp/
35
+ property_value = Time.parse(property_value).utc
36
+ elsif property_value =~ /^\d+$/
37
+ property_value = property_value.to_i
38
+ end
39
+ attributes = {variable => property_value}.merge(attributes)
40
+ end
41
+
42
+ GoApiClient::Domain::Job.new(attributes)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end