go_api_client 0.5.4 → 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.
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