orch 0.0.4 → 0.0.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 92d6e7c901a8497b6b574287ef7060ee8f9a178f
4
- data.tar.gz: 0c4ca4a8ef6895df3f06b5e6e05b9458c4102f8b
3
+ metadata.gz: 04fbdee432700312da01a5a00e9e87ba6ebf9fe5
4
+ data.tar.gz: a143d1aebe861e1795ba378197550690880cbca2
5
5
  SHA512:
6
- metadata.gz: 27ae0267fff9f2c200760596168ff9268a66bdafdfcf4b2079b0262b9db765157e0e3cff27617bd143aec194e2436da87459cbd1e310bc0c645fc8600066976c
7
- data.tar.gz: 5bb49d8171aa924f015c048b2bb40bb472ac3ea786a9579c8c61e7d7bf5bcc29692809fff2fcdf8ae6367b65890abcda7753afbf9286c9c662ecc293f39e37e1
6
+ metadata.gz: d204d5456449f9998875804e7b45be9b1845d9a4cfd5e38999cb8790ffb1ad0ba5059f161e44a3dc0a6def3b979cae096176f4e54b9e5e64d8974c863f5d5ca2
7
+ data.tar.gz: 35eee1a4a9d6fe8b1c955fc0f8431a55064706592653427b7bf5fb037b43903e288b1046a268e696615965951107e5f962ce72eeda4730c0d501c74121fbbed0
data/README.md CHANGED
@@ -180,6 +180,8 @@ A url in the config section would apply to all applications in the specification
180
180
 
181
181
  Finally, you can also pass --chronos_url or --marathon_url options to the "orch deploy" command to override all other specifications. You may want to use this option in automated deployment scenerios where you want to manage were things get deployed in another system.
182
182
 
183
+ In more robust implementations you may have a list of redundant frameworks you can deploy to. All of these configurations support passing a semi-colon seperated list of URLs. If network related errors occur Orch will attempt to call additional specified URLs. Also, if your framework has basic auth credentials required you may specify those credentials in the config like this: http://user:password@myframework.mycompany.com
184
+
183
185
  ## Examples
184
186
 
185
187
  The examples directory contains various examples of the features of orch.
@@ -24,11 +24,15 @@ deploy_vars:
24
24
  - dev
25
25
  - test
26
26
  - prod
27
+ COLO:
28
+ - west
29
+ - east
27
30
  env:
28
31
  DEBUG_FLAG: true
29
32
  applications:
30
33
  - <<: *DEFAULT_JOB
31
34
  DEPLOY_ENV: dev
35
+ COLO: west
32
36
  marathon_spec:
33
37
  <<: *DEFAULT_SPEC
34
38
  container:
@@ -38,7 +42,16 @@ applications:
38
42
  forcePullImage: true
39
43
  - <<: *DEFAULT_JOB
40
44
  DEPLOY_ENV: test
45
+ COLO: west
41
46
  - <<: *DEFAULT_JOB
42
47
  DEPLOY_ENV: prod
48
+ COLO: west
49
+ marathon_url: http://admin:m%40rA4h0n@ypec-prod1-mesos1.wc1.yellowpages.com:8080;http://ypec-prod1-mesos1.wc1.yellowpages.com:8080;http://ypec-prod1-mesos2.wc1.yellowpages.com:8080;http://ypec-prod1-mesos3.wc1.yellowpages.com:8080;http://ypec-prod1-mesos4.wc1.yellowpages.com:8080
50
+ env:
51
+ DEBUG_FLAG: false
52
+ - <<: *DEFAULT_JOB
53
+ DEPLOY_ENV: prod
54
+ COLO: east
55
+ marathon_url: http://admin:m%40rA4h0n@ypec-prod1-mesos1.ev1.yellowpages.com:8080;http://ypec-prod1-mesos2.ev1.yellowpages.com:8080;http://ypec-prod1-mesos3.ev1.yellowpages.com:8080;http://ypec-prod1-mesos4.ev1.yellowpages.com:8080
43
56
  env:
44
57
  DEBUG_FLAG: false
@@ -16,15 +16,11 @@ module Orch
16
16
  def initialize(options)
17
17
  end
18
18
 
19
- def deploy(url, app_id, bamboo_spec)
20
- if url.nil?
19
+ def deploy(url_list, app_id, bamboo_spec)
20
+ if url_list.nil?
21
21
  exit_with_msg "bamboo_url not defined"
22
22
  end
23
23
 
24
- uri = URI(url)
25
- json_headers = {"Content-Type" => "application/json",
26
- "Accept" => "application/json"}
27
-
28
24
  # Create the real json
29
25
  bamboo_json = {}
30
26
  bamboo_json["id"] = (app_id[0] == '/') ? app_id : ("/" + app_id)
@@ -32,12 +28,7 @@ module Orch
32
28
 
33
29
  # curl -i -X PUT -d '{"id":"/ExampleAppGroup/app1", "acl":"path_beg -i /group/app-1"}' http://localhost:8000/api/services//ExampleAppGroup/app1
34
30
  # {"/adam-web-dev":{"Id":"/adam-web-dev","Acl":"hdr(host) -i adam-web-dev.ypec.int.yp.com"
35
- http = Net::HTTP.new(uri.host, uri.port)
36
- begin
37
- response = http.put("/api/services/#{app_id}", bamboo_json.to_json, json_headers)
38
- rescue *HTTP_ERRORS => error
39
- http_fault(error)
40
- end
31
+ response = http_put(url_list, "/api/services/#{app_id}", bamboo_json.to_json, JSON_HEADERS)
41
32
 
42
33
  if response.code == 200.to_s
43
34
  puts "successfully created bamboo spec for marathon job: #{app_id}"
@@ -48,22 +39,12 @@ module Orch
48
39
  return response
49
40
  end
50
41
 
51
- def delete(url, app_id)
52
- if url.nil?
42
+ def delete(url_list, app_id)
43
+ if url_list.nil?
53
44
  exit_with_msg "bamboo_url not defined"
54
45
  end
55
46
 
56
- uri = URI(url)
57
- json_headers = {"Content-Type" => "application/json",
58
- "Accept" => "application/json"}
59
-
60
- puts "curl -i -X DELETE #{uri}/api/services/#{app_id}"
61
- http = Net::HTTP.new(uri.host, uri.port)
62
- begin
63
- response = http.delete("/api/services/#{app_id}", json_headers)
64
- rescue *HTTP_ERRORS => error
65
- http_fault(error)
66
- end
47
+ response = http_delete(url_list, "/api/services/#{app_id}", JSON_HEADERS)
67
48
 
68
49
  if response.code != 200.to_s
69
50
  puts "Response #{response.code} #{response.message}: #{response.body}"
@@ -72,23 +53,14 @@ module Orch
72
53
  return response
73
54
  end
74
55
 
75
- def verify(url, app_id, spec)
76
- if url.nil?
56
+ def verify(url_list, app_id, spec)
57
+ if url_list.nil?
77
58
  puts "no bamboo_url - can not verify with server"
78
59
  return
79
60
  end
80
61
 
81
- uri = URI(url)
82
- json_headers = {"Content-Type" => "application/json",
83
- "Accept" => "application/json"}
84
-
85
62
  # TODO: will this work or do I need to parse through all services like chronos
86
- http = Net::HTTP.new(uri.host, uri.port)
87
- begin
88
- response = http.get("/api/services", json_headers)
89
- rescue *HTTP_ERRORS => error
90
- http_fault(error)
91
- end
63
+ response = http_get(url_list, "/api/services", JSON_HEADERS)
92
64
 
93
65
  if response.code != 200.to_s
94
66
  puts "Response #{response.code} #{response.message}: #{response.body}"
@@ -16,15 +16,11 @@ module Orch
16
16
  def initialize(options)
17
17
  end
18
18
 
19
- def deploy(url, json_payload)
20
- if url.nil?
19
+ def deploy(url_list, json_payload)
20
+ if url_list.nil?
21
21
  exit_with_msg "chronos_url not defined"
22
22
  end
23
23
 
24
- uri = URI(url)
25
- json_headers = {"Content-Type" => "application/json",
26
- "Accept" => "application/json"}
27
-
28
24
  path = nil
29
25
  path = "/scheduler/iso8601" unless json_payload["schedule"].nil?
30
26
  path = "/scheduler/dependency" unless json_payload["parents"].nil?
@@ -32,12 +28,7 @@ module Orch
32
28
  exit_with_msg "neither schedule nor parents fields defined for Chronos job"
33
29
  end
34
30
 
35
- http = Net::HTTP.new(uri.host, uri.port)
36
- begin
37
- response = http.post(path, json_payload, json_headers)
38
- rescue *HTTP_ERRORS => error
39
- http_fault(error)
40
- end
31
+ response = http_post(url_list, path, json_payload, JSON_HEADERS)
41
32
 
42
33
  if response.code != 204.to_s
43
34
  puts "Response #{response.code} #{response.message}: #{response.body}"
@@ -46,22 +37,13 @@ module Orch
46
37
  return response
47
38
  end
48
39
 
49
- def delete(url, name)
50
- if url.nil?
40
+ def delete(url_list, name)
41
+ if url_list.nil?
51
42
  exit_with_msg "chronos_url not defined"
52
43
  end
53
44
 
54
- uri = URI(url)
55
- json_headers = {"Content-Type" => "application/json",
56
- "Accept" => "application/json"}
57
-
58
45
  # curl -L -X DELETE chronos-node:8080/scheduler/job/request_event_counter_hourly
59
- http = Net::HTTP.new(uri.host, uri.port)
60
- begin
61
- response = http.delete("/scheduler/job/#{name}", json_headers)
62
- rescue *HTTP_ERRORS => error
63
- http_fault(error)
64
- end
46
+ response = http_delete(url_list, "/scheduler/job/#{name}", JSON_HEADERS)
65
47
 
66
48
  if response.code != 204.to_s
67
49
  puts "Response #{response.code} #{response.message}: #{response.body}"
@@ -70,24 +52,15 @@ module Orch
70
52
  return response
71
53
  end
72
54
 
73
- def verify(url, json_payload)
74
- if url.nil?
55
+ def verify(url_list, json_payload)
56
+ if url_list.nil?
75
57
  puts "no chronos_url - can not verify with server"
76
58
  return
77
59
  end
78
60
 
79
61
  spec = Hashie::Mash.new(JSON.parse(json_payload))
80
62
 
81
- uri = URI(url)
82
- json_headers = {"Content-Type" => "application/json",
83
- "Accept" => "application/json"}
84
-
85
- http = Net::HTTP.new(uri.host, uri.port)
86
- begin
87
- response = http.get("/scheduler/jobs/search?name=#{spec.name}", json_headers)
88
- rescue *HTTP_ERRORS => error
89
- http_fault(error)
90
- end
63
+ response = http_get(url_list, "/scheduler/jobs/search?name=#{spec.name}", JSON_HEADERS)
91
64
 
92
65
  if response.code != 200.to_s
93
66
  puts "Response #{response.code} #{response.message}: #{response.body}"
@@ -17,74 +17,40 @@ module Orch
17
17
  end
18
18
 
19
19
  def chronos_url(spec, app)
20
- if @options.has_key?("chronos_url")
21
- url = @options["chronos_url"]
22
- return url
23
- end
24
-
25
- if !app.chronos_url.nil?
26
- return app.chronos_url
27
- end
28
-
29
- if !spec.config.nil?
30
- if !spec.config.chronos_url.nil?
31
- return spec.config.chronos_url
32
- end
33
- end
34
-
35
- if !@APP_CONFIG.nil?
36
- if !@APP_CONFIG["chronos_url"].nil?
37
- return @APP_CONFIG["chronos_url"]
38
- end
39
- end
40
-
41
- return nil
20
+ return key_search("chronos_url", spec, app)
42
21
  end
43
22
 
44
23
  def marathon_url(spec, app)
45
- if @options.has_key?("marathon_url")
46
- url = @options["marathon_url"]
47
- return url
48
- end
49
-
50
- if !app.marathon_url.nil?
51
- return app.marathon_url
52
- end
53
-
54
- if !spec.config.nil?
55
- if !spec.config.marathon_url.nil?
56
- return spec.config.marathon_url
57
- end
58
- end
59
-
60
- if !@APP_CONFIG.nil?
61
- if !@APP_CONFIG["marathon_url"].nil?
62
- return @APP_CONFIG["marathon_url"]
63
- end
64
- end
65
-
66
- return nil
24
+ return key_search("marathon_url", spec, app)
67
25
  end
68
26
 
69
27
  def bamboo_url(spec, app)
70
- if @options.has_key?("bamboo_url")
71
- url = @options["bamboo_url"]
28
+ return key_search("bamboo_url", spec, app)
29
+ end
30
+
31
+ def key_search(key, spec, app)
32
+ # First look if key was passed in as option
33
+ if @options.has_key?(key)
34
+ url = @options[key]
72
35
  return url
73
36
  end
74
37
 
75
- if !app.bamboo_url.nil?
76
- return app.bamboo_url
38
+ # Second look in the application level spec
39
+ if !app[key].nil?
40
+ return app[key]
77
41
  end
78
42
 
43
+ # Third look in the config portion of the spec
79
44
  if !spec.config.nil?
80
- if !spec.config.bamboo_url.nil?
81
- return spec.config.bamboo_url
45
+ if !spec.config[key].nil?
46
+ return spec.config[key]
82
47
  end
83
48
  end
84
49
 
50
+ # Forth look in the config file
85
51
  if !@APP_CONFIG.nil?
86
- if !@APP_CONFIG["bamboo_url"].nil?
87
- return @APP_CONFIG["bamboo_url"]
52
+ if !@APP_CONFIG[key].nil?
53
+ return @APP_CONFIG[key]
88
54
  end
89
55
  end
90
56
 
@@ -16,27 +16,21 @@ module Orch
16
16
  def initialize(options)
17
17
  end
18
18
 
19
- def deploy(url, app_id, json_payload)
20
- if url.nil?
19
+ def deploy(url_list, app_id, json_payload)
20
+ if url_list.nil?
21
21
  exit_with_msg "marathon_url not defined"
22
22
  end
23
23
 
24
- uri = URI(url)
25
- json_headers = {"Content-Type" => "application/json",
26
- "Accept" => "application/json"}
27
-
28
- http = Net::HTTP.new(uri.host, uri.port)
29
- begin
30
- response = http.put("/v2/apps/#{app_id}", json_payload, json_headers)
31
- rescue *HTTP_ERRORS => error
32
- http_fault(error)
33
- end
24
+ response = http_put(url_list, "/v2/apps/#{app_id}", json_payload, JSON_HEADERS)
34
25
 
35
26
  # TODO: should we do anyting with version or deploymentId that gets returned?
36
27
  if response.code == 201.to_s
37
28
  puts "successfully created marathon job: #{app_id}"
38
29
  elsif response.code == 200.to_s
39
30
  puts "successfully updated marathon job: #{app_id}"
31
+ elsif response.code == 401.to_s
32
+ puts "Authentication required"
33
+ exit 1
40
34
  else
41
35
  puts "Response #{response.code} #{response.message}: #{response.body}"
42
36
  end
@@ -44,21 +38,12 @@ module Orch
44
38
  return response
45
39
  end
46
40
 
47
- def delete(url, id)
48
- if url.nil?
41
+ def delete(url_list, id)
42
+ if url_list.nil?
49
43
  exit_with_msg "marathon_url not defined"
50
44
  end
51
45
 
52
- uri = URI(url)
53
- json_headers = {"Content-Type" => "application/json",
54
- "Accept" => "application/json"}
55
-
56
- http = Net::HTTP.new(uri.host, uri.port)
57
- begin
58
- response = http.delete("/v2/apps/#{id}", json_headers)
59
- rescue *HTTP_ERRORS => error
60
- http_fault(error)
61
- end
46
+ response = http_delete(url_list, "/v2/apps/#{id}", JSON_HEADERS)
62
47
 
63
48
  if response.code == 200.to_s
64
49
  puts "successfully deleted #{id}"
@@ -71,28 +56,22 @@ module Orch
71
56
  return response
72
57
  end
73
58
 
74
- def verify(url, json_payload)
75
- if url.nil?
59
+ def verify(url_list, json_payload)
60
+ if url_list.nil?
76
61
  puts "no marathon_url - can not verify with server"
77
62
  return
78
63
  end
79
64
 
80
65
  spec = Hashie::Mash.new(JSON.parse(json_payload))
81
66
 
82
- uri = URI(url)
83
- json_headers = {"Content-Type" => "application/json",
84
- "Accept" => "application/json"}
85
-
86
- http = Net::HTTP.new(uri.host, uri.port)
87
- begin
88
- response = http.get("/v2/apps/#{spec.id}", json_headers)
89
- rescue *HTTP_ERRORS => error
90
- http_fault(error)
91
- end
67
+ response = http_get(url_list, "/v2/apps/#{spec.id}", JSON_HEADERS)
92
68
 
93
69
  if response.code == 200.to_s
94
70
  job = Hashie::Mash.new(JSON.parse(response.body))
95
71
  foundDiffs = find_diffs(spec, job.app)
72
+ elsif response.code == 401.to_s
73
+ puts "Authentication required"
74
+ exit 1
96
75
  elsif response.code == 404.to_s
97
76
  puts "job: #{spec.id} - not defined in Marathon"
98
77
  foundDiffs = true
@@ -104,23 +83,13 @@ module Orch
104
83
  return foundDiffs
105
84
  end
106
85
 
107
- def restart(url, app_id)
108
- if url.nil?
86
+ def restart(url_list, app_id)
87
+ if url_list.nil?
109
88
  exit_with_msg "marathon_url not defined"
110
89
  end
111
90
 
112
- uri = URI(url)
113
-
114
91
  # POST /v2/apps/{appId}/restart: Rolling restart of all tasks of the given app
115
- json_headers = {"Content-Type" => "application/json",
116
- "Accept" => "application/json"}
117
-
118
- http = Net::HTTP.new(uri.host, uri.port)
119
- begin
120
- response = http.post("/v2/apps/#{app_id}/restart", {}.to_json, json_headers)
121
- rescue *HTTP_ERRORS => error
122
- http_fault(error)
123
- end
92
+ response = http_post(url_list, "/v2/apps/#{app_id}/restart", {}.to_json, JSON_HEADERS)
124
93
 
125
94
  if response.code == 200.to_s
126
95
  puts "success"
@@ -1,3 +1,3 @@
1
1
  module Orch
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -1,4 +1,5 @@
1
1
  require 'net/http'
2
+ require 'uri'
2
3
 
3
4
  HTTP_ERRORS = [
4
5
  EOFError,
@@ -8,15 +9,125 @@ HTTP_ERRORS = [
8
9
  Net::HTTPHeaderSyntaxError,
9
10
  Net::ProtocolError,
10
11
  Timeout::Error,
11
- Errno::ECONNREFUSED
12
+ Errno::ECONNREFUSED,
13
+ Errno::ETIMEDOUT
12
14
  ]
13
15
 
16
+ JSON_HEADERS = {"Content-Type" => "application/json",
17
+ "Accept" => "application/json"}
18
+
19
+ def http_post(url_list, path, body, headers)
20
+ lastErr = nil
21
+
22
+ url_list.split(';').each do |url|
23
+ uri = URI(url)
24
+
25
+ http = Net::HTTP.new(uri.host, uri.port)
26
+ request = Net::HTTP::Post.new(path, headers)
27
+ request.body = body
28
+ if uri.user
29
+ request.basic_auth URI.unescape(uri.user), URI.unescape(uri.password)
30
+ end
31
+ begin
32
+ #response = http.post(path, body, headers)
33
+ response = http.start {|http| http.request(request) }
34
+ rescue *HTTP_ERRORS => error
35
+ STDERR.puts "Failed http_post to #{url}: #{error} (#{error.class})"
36
+ lastErr = error
37
+ next
38
+ end
39
+
40
+ return response
41
+ end
42
+
43
+ http_fault(lastErr)
44
+ end
45
+
46
+ def http_put(url_list, path, body, headers)
47
+ lastErr = nil
48
+
49
+ url_list.split(';').each do |url|
50
+ uri = URI(url)
51
+
52
+ http = Net::HTTP.new(uri.host, uri.port)
53
+ request = Net::HTTP::Put.new(path, headers)
54
+ request.body = body
55
+ if uri.user
56
+ request.basic_auth URI.unescape(uri.user), URI.unescape(uri.password)
57
+ end
58
+ begin
59
+ #response = http.put(path, body, headers)
60
+ response = http.start {|http| http.request(request) }
61
+ rescue *HTTP_ERRORS => error
62
+ STDERR.puts "Failed http_put to #{url}: #{error} (#{error.class})"
63
+ lastErr = error
64
+ next
65
+ end
66
+
67
+ return response
68
+ end
69
+
70
+ http_fault(lastErr)
71
+ end
72
+
73
+ def http_get(url_list, path, headers)
74
+ lastErr = nil
75
+
76
+ url_list.split(';').each do |url|
77
+ uri = URI(url)
78
+
79
+ http = Net::HTTP.new(uri.host, uri.port)
80
+ request = Net::HTTP::Get.new(path, headers)
81
+ if uri.user
82
+ request.basic_auth URI.unescape(uri.user), URI.unescape(uri.password)
83
+ end
84
+ begin
85
+ #response = http.get(path, headers)
86
+ response = http.start {|http| http.request(request) }
87
+ rescue *HTTP_ERRORS => error
88
+ STDERR.puts "Failed http_get to #{url}: #{error} (#{error.class})"
89
+ lastErr = error
90
+ next
91
+ end
92
+
93
+ return response
94
+ end
95
+
96
+ http_fault(lastErr)
97
+ end
98
+
99
+ def http_delete(url_list, path, headers)
100
+ lastErr = nil
101
+
102
+ url_list.split(';').each do |url|
103
+ uri = URI(url)
104
+
105
+ http = Net::HTTP.new(uri.host, uri.port)
106
+ request = Net::HTTP::Delete.new(path, headers)
107
+ if uri.user
108
+ request.basic_auth URI.unescape(uri.user), URI.unescape(uri.password)
109
+ end
110
+ begin
111
+ # response = http.delete(path, headers)
112
+ response = http.start {|http| http.request(request) }
113
+ rescue *HTTP_ERRORS => error
114
+ STDERR.puts "Failed http_delete to #{url}: #{error} (#{error.class})"
115
+ lastErr = error
116
+ next
117
+ end
118
+
119
+ return response
120
+ end
121
+
122
+ http_fault(lastErr)
123
+ end
124
+
14
125
  def http_fault(error)
15
- puts "Networking error talking to framework: #{error.to_s}"
126
+ STDERR.puts "Fatal networking error talking to framework: #{error.to_s}"
16
127
  exit 1
17
128
  end
18
129
 
19
130
  def exit_with_msg(err_msg)
20
- puts err_msg
131
+ STDERR.puts err_msg
21
132
  exit 1
22
133
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: orch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ray Johnson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-11-12 00:00:00.000000000 Z
11
+ date: 2015-11-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler