orch 0.0.3 → 0.0.4

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: 4fc678adcfcacd47d4c3424fffae37cfba36f7f1
4
- data.tar.gz: deba3fb34b70a3b486c400b71ff395b869fa0a9a
3
+ metadata.gz: 92d6e7c901a8497b6b574287ef7060ee8f9a178f
4
+ data.tar.gz: 0c4ca4a8ef6895df3f06b5e6e05b9458c4102f8b
5
5
  SHA512:
6
- metadata.gz: bf766eea2fd37950ac0fa9fcbe2528e4b51748570f0ae104cc73796bc667403d994e64e310c964fd882bfb2adca49aaaaefe4e412e39df7bf2c7ddcf08ef6b95
7
- data.tar.gz: 5f1e9ce4837fb1a4ca65cefc4fc12005ffb0d6f94d98a3f58c45b059b972725120310374df0cc02cc7bcce63f447e7e1cfe06e5938bc52257c6d55aa8bccca08
6
+ metadata.gz: 27ae0267fff9f2c200760596168ff9268a66bdafdfcf4b2079b0262b9db765157e0e3cff27617bd143aec194e2436da87459cbd1e310bc0c645fc8600066976c
7
+ data.tar.gz: 5bb49d8171aa924f015c048b2bb40bb472ac3ea786a9579c8c61e7d7bf5bcc29692809fff2fcdf8ae6367b65890abcda7753afbf9286c9c662ecc293f39e37e1
data/README.md CHANGED
@@ -24,14 +24,14 @@ The orch Yaml format is really a wrapper for multiple Marathon or Chronos job de
24
24
 
25
25
  The basic orch syntax is as follows:
26
26
  ```
27
- version: alpha1
27
+ version: 1.0
28
28
  applications:
29
29
  - kind: Chronos
30
30
  chronos_spec:
31
31
  ...
32
32
  ```
33
33
 
34
- The **version:** field must currently always be alpha1. Eventually, this tool may need to support a revised format and this can be used to support multiple versions.
34
+ The **version:** field must currently always be 1.0. Eventually, this tool may need to support a revised format and this can be used to support multiple versions.
35
35
 
36
36
  The **applications:** field contains an array of Chronos or Marathon configurations. Each array must have a **kind:** field with a value of _Chronos_ or _Marathon_ which simply tells orch what type of config this is. Depending on the value of **kind:** a field of **chronos_spec:** or **marathon_spec:** is also required.
37
37
 
@@ -58,7 +58,7 @@ This example will define an environment variable named **DEPLOY_ENV**. (You can
58
58
 
59
59
  You then would need to specify that variable in your application sections like this:
60
60
  ```
61
- version: alpha1
61
+ version: 1.0
62
62
  deploy_vars:
63
63
  DEPLOY_ENV:
64
64
  - dev
@@ -86,7 +86,7 @@ Chronos and Marathon use different syntx to specify environment variables. Also
86
86
 
87
87
  The env field could be used at the top level of the spec to be used across all applications in the spec:
88
88
  ```
89
- version: alpha1
89
+ version: 1.0
90
90
  env:
91
91
  GOOGLE_URL: http://www.google.com
92
92
  YP_URL: http://www.yp.com
@@ -96,7 +96,7 @@ env:
96
96
 
97
97
  Or you can also specify it at the application level as an alternative syntax to specifying it in the *marathon_spec:* or *chronos_spec:* sections - like this:
98
98
  ```
99
- version: alpha1
99
+ version: 1.0
100
100
  env:
101
101
  GOOGLE_URL: http://www.google.com
102
102
  YP_URL: http://www.yp.com
@@ -109,7 +109,7 @@ env:
109
109
  ...
110
110
  ```
111
111
 
112
- Lower level definitions of an env var will supeceed higher level version. That is if you specify an env value in the *marathon_spec* or *chronos_spec* level it will override anything set at the *app* or *orch* level.
112
+ Lower level definitions of an env var will superceed a higher level version. That is if you specify an env value in the *marathon_spec* or *chronos_spec* level it will override anything set at the *app* or *orch* level.
113
113
  ### Yaml anchors and aliases
114
114
 
115
115
  The nice thing about using Yaml as the spec format is the ability to use Yaml's anchors (&) and alias (*) syntax. This allows you to specify sections of your configuration that can be reused across multiple jobs. Typically if you have a job for multiple deployment environments you what them all to have the same spec - except perhaps override one or two things. (Like an envionment value or the docker image.)
@@ -133,7 +133,7 @@ TODO: finish this section
133
133
 
134
134
  Orch provides a way to also configure your Bamboo server from your orch config. Here is an example:
135
135
  ```
136
- version: alpha1
136
+ version: 1.0
137
137
  applications:
138
138
  - kind: Marathon
139
139
  marathon_spec:
@@ -150,12 +150,35 @@ Note: you will also need to set the **bamboo_url:** feild of your configutation.
150
150
 
151
151
  ## Configuration Options
152
152
 
153
- Run the following command to interactively create a config file.
153
+ There are a few ways to configure orch to know about the urls for various mesos services. These provide options
154
+ for various automation and deployment scenerios.
155
+
156
+ The first option is to set up a config file with the urls for your Mesos frameworks. Run the following command to interactively create a config file.
154
157
  ```
155
158
  $> orch config
156
159
  ```
157
160
 
158
- The file ~/.orch/config.yaml would contain values for "chronos_url" and "marathon_url". You can also pass --chronos_url or --marathon_url options to the "orch deploy" command to override what is in the config file.
161
+ The file ~/.orch/config.yaml would contain values for "chronos_url" and "marathon_url".
162
+
163
+ You can also specify the framework urls directly in your configuration. There are two places in the specification that could the url can be set. You would use the keys chronos_url:, marathon_url: or bamboo_url:
164
+ Here is an example:
165
+ ```
166
+ version: 1.0
167
+ config:
168
+ chronos_url: http://chronos.mycompany.com:8080
169
+ applications:
170
+ - kind: Marathon
171
+ marathon_url: http://marathon.mycompany.com
172
+ marathon_spec:
173
+ ...
174
+ bamboo_url: http://bamboo.mycompany.com
175
+ bamboo_spec:
176
+ acl: "hdr(host) -i web.example.com"
177
+ ```
178
+
179
+ A url in the config section would apply to all applications in the specification. A url at the application level would superceed any definitions in the config section. This can be useful if you have a specification that needs to deploy to multiple clusters such as in a multi-datacenter scenerio. Any urls specified in a YAML specification would override those in the .orch/config.yaml file.
180
+
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.
159
182
 
160
183
  ## Examples
161
184
 
@@ -11,16 +11,16 @@ default_job: &DEFAULT_JOB
11
11
  container: &DEFAULT_CONTAINER
12
12
  type: "DOCKER"
13
13
  docker: &DEFAULT_DOCKER
14
- image: "nginx"
14
+ image: "ypengineering/milieu"
15
15
  network: "BRIDGE"
16
16
  portMappings:
17
17
  -
18
18
  containerPort: 80
19
19
  hostPort: 0
20
20
  protocol: "tcp"
21
- forcePullImage: false
21
+ forcePullImage: true
22
22
 
23
- version: alpha1
23
+ version: 1.0
24
24
  deploy_vars:
25
25
  DEPLOY_ENV:
26
26
  - dev
@@ -19,7 +19,7 @@ default_job: &DEFAULT_JOB
19
19
  value: "/var/{{DEPLOY_ENV}}"
20
20
  command: "echo \"log here: $LOG_LOCATION\"; echo \"ENV: $DEPLOY_ENV\";sleep 10; echo bye"
21
21
 
22
- version: alpha1
22
+ version: 1.0
23
23
  deploy_vars:
24
24
  DEPLOY_ENV:
25
25
  - dev
@@ -18,7 +18,7 @@ default_job: &DEFAULT_JOB
18
18
  protocol: "tcp"
19
19
  forcePullImage: false
20
20
 
21
- version: alpha1
21
+ version: 1.0
22
22
  deploy_vars:
23
23
  DEPLOY_ENV:
24
24
  - dev
@@ -1,4 +1,4 @@
1
- version: alpha1
1
+ version: 1.0
2
2
  applications:
3
3
  - kind: Chronos
4
4
  chronos_spec:
@@ -1,4 +1,4 @@
1
- version: alpha1
1
+ version: 1.0
2
2
  applications:
3
3
  - kind: Marathon
4
4
  DEPLOY_ENV: dev
data/lib/bamboo.rb CHANGED
@@ -14,11 +14,14 @@ end
14
14
  module Orch
15
15
  class Bamboo
16
16
  def initialize(options)
17
- @config = Orch::Config.new(options)
18
17
  end
19
18
 
20
- def deploy(app_id, bamboo_spec)
21
- uri = URI(@config.bamboo_url)
19
+ def deploy(url, app_id, bamboo_spec)
20
+ if url.nil?
21
+ exit_with_msg "bamboo_url not defined"
22
+ end
23
+
24
+ uri = URI(url)
22
25
  json_headers = {"Content-Type" => "application/json",
23
26
  "Accept" => "application/json"}
24
27
 
@@ -30,7 +33,11 @@ module Orch
30
33
  # curl -i -X PUT -d '{"id":"/ExampleAppGroup/app1", "acl":"path_beg -i /group/app-1"}' http://localhost:8000/api/services//ExampleAppGroup/app1
31
34
  # {"/adam-web-dev":{"Id":"/adam-web-dev","Acl":"hdr(host) -i adam-web-dev.ypec.int.yp.com"
32
35
  http = Net::HTTP.new(uri.host, uri.port)
33
- response = http.put("/api/services/#{app_id}", bamboo_json.to_json, json_headers)
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
34
41
 
35
42
  if response.code == 200.to_s
36
43
  puts "successfully created bamboo spec for marathon job: #{app_id}"
@@ -41,37 +48,47 @@ module Orch
41
48
  return response
42
49
  end
43
50
 
44
- def delete(app_id)
45
- uri = URI(@config.chronos_url)
51
+ def delete(url, app_id)
52
+ if url.nil?
53
+ exit_with_msg "bamboo_url not defined"
54
+ end
55
+
56
+ uri = URI(url)
46
57
  json_headers = {"Content-Type" => "application/json",
47
58
  "Accept" => "application/json"}
48
59
 
49
60
  puts "curl -i -X DELETE #{uri}/api/services/#{app_id}"
50
61
  http = Net::HTTP.new(uri.host, uri.port)
51
- response = http.delete("/api/services/#{app_id}", json_headers)
62
+ begin
63
+ response = http.delete("/api/services/#{app_id}", json_headers)
64
+ rescue *HTTP_ERRORS => error
65
+ http_fault(error)
66
+ end
52
67
 
53
68
  if response.code != 200.to_s
54
69
  puts "Response #{response.code} #{response.message}: #{response.body}"
55
70
  end
56
71
 
57
- # TODO: handle error codes better?
58
-
59
72
  return response
60
73
  end
61
74
 
62
- def verify(app_id, spec)
63
- if @config.check_for_bamboo_url == false
75
+ def verify(url, app_id, spec)
76
+ if url.nil?
64
77
  puts "no bamboo_url - can not verify with server"
65
78
  return
66
79
  end
67
80
 
68
- uri = URI(@config.bamboo_url)
81
+ uri = URI(url)
69
82
  json_headers = {"Content-Type" => "application/json",
70
83
  "Accept" => "application/json"}
71
84
 
72
85
  # TODO: will this work or do I need to parse through all services like chronos
73
86
  http = Net::HTTP.new(uri.host, uri.port)
74
- response = http.get("/api/services", json_headers)
87
+ begin
88
+ response = http.get("/api/services", json_headers)
89
+ rescue *HTTP_ERRORS => error
90
+ http_fault(error)
91
+ end
75
92
 
76
93
  if response.code != 200.to_s
77
94
  puts "Response #{response.code} #{response.message}: #{response.body}"
data/lib/chronos.rb CHANGED
@@ -14,12 +14,14 @@ end
14
14
  module Orch
15
15
  class Chronos
16
16
  def initialize(options)
17
- # TODO: get chronos and marathon urls from diffferent ways: param, env, .config
18
- @config = Orch::Config.new(options)
19
17
  end
20
18
 
21
- def deploy(json_payload)
22
- uri = URI(@config.chronos_url)
19
+ def deploy(url, json_payload)
20
+ if url.nil?
21
+ exit_with_msg "chronos_url not defined"
22
+ end
23
+
24
+ uri = URI(url)
23
25
  json_headers = {"Content-Type" => "application/json",
24
26
  "Accept" => "application/json"}
25
27
 
@@ -27,54 +29,65 @@ module Orch
27
29
  path = "/scheduler/iso8601" unless json_payload["schedule"].nil?
28
30
  path = "/scheduler/dependency" unless json_payload["parents"].nil?
29
31
  if path.nil?
30
- puts "neither schedule nor parents fields defined for Chronos job"
31
- exit 1
32
+ exit_with_msg "neither schedule nor parents fields defined for Chronos job"
32
33
  end
33
34
 
34
35
  http = Net::HTTP.new(uri.host, uri.port)
35
- response = http.post(path, json_payload, json_headers)
36
+ begin
37
+ response = http.post(path, json_payload, json_headers)
38
+ rescue *HTTP_ERRORS => error
39
+ http_fault(error)
40
+ end
36
41
 
37
42
  if response.code != 204.to_s
38
43
  puts "Response #{response.code} #{response.message}: #{response.body}"
39
44
  end
40
45
 
41
- # TODO: handle error codes better?
42
-
43
46
  return response
44
47
  end
45
48
 
46
- def delete(name)
47
- uri = URI(@config.chronos_url)
49
+ def delete(url, name)
50
+ if url.nil?
51
+ exit_with_msg "chronos_url not defined"
52
+ end
53
+
54
+ uri = URI(url)
48
55
  json_headers = {"Content-Type" => "application/json",
49
56
  "Accept" => "application/json"}
50
57
 
51
58
  # curl -L -X DELETE chronos-node:8080/scheduler/job/request_event_counter_hourly
52
59
  http = Net::HTTP.new(uri.host, uri.port)
53
- response = http.delete("/scheduler/job/#{name}", json_headers)
60
+ begin
61
+ response = http.delete("/scheduler/job/#{name}", json_headers)
62
+ rescue *HTTP_ERRORS => error
63
+ http_fault(error)
64
+ end
54
65
 
55
66
  if response.code != 204.to_s
56
67
  puts "Response #{response.code} #{response.message}: #{response.body}"
57
68
  end
58
69
 
59
- # TODO: handle error codes better?
60
-
61
70
  return response
62
71
  end
63
72
 
64
- def verify(json_payload)
65
- if @config.check_for_chronos_url == false
73
+ def verify(url, json_payload)
74
+ if url.nil?
66
75
  puts "no chronos_url - can not verify with server"
67
76
  return
68
77
  end
69
78
 
70
79
  spec = Hashie::Mash.new(JSON.parse(json_payload))
71
80
 
72
- uri = URI(@config.chronos_url)
81
+ uri = URI(url)
73
82
  json_headers = {"Content-Type" => "application/json",
74
83
  "Accept" => "application/json"}
75
84
 
76
85
  http = Net::HTTP.new(uri.host, uri.port)
77
- response = http.get("/scheduler/jobs/search?name=#{spec.name}", json_headers)
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
78
91
 
79
92
  if response.code != 200.to_s
80
93
  puts "Response #{response.code} #{response.message}: #{response.body}"
@@ -97,8 +110,6 @@ module Orch
97
110
  foundDiffs = true
98
111
  end
99
112
 
100
- # TODO: handle error codes better?
101
-
102
113
  return foundDiffs
103
114
  end
104
115
 
@@ -114,9 +125,9 @@ module Orch
114
125
  end
115
126
  if spec[key].is_a?(Array)
116
127
  if spec[key].length != job[key].length
117
- printf "difference for field: #{key} - length of array is different\n"
118
- printf " spec: #{spec[key].to_json}\n"
119
- printf " server: #{job[key].to_json}\n"
128
+ printf("difference for field: %s - length of array is different\n", key)
129
+ printf(" spec: %s\n", spec[key].to_json)
130
+ printf(" server: %s\n", job[key].to_json)
120
131
  foundDiff = true
121
132
  next
122
133
  end
@@ -140,9 +151,9 @@ module Orch
140
151
  if foundDiff == false
141
152
  puts "Differences found in job"
142
153
  end
143
- printf "difference for field: #{key}\n"
144
- printf " spec: #{specVal}\n"
145
- printf " server: #{jobVal}\n"
154
+ printf("difference for field: %s\n", key)
155
+ printf(" spec: %s\n", specVal)
156
+ printf(" server: %s\n", jobVal)
146
157
  foundDiff = true
147
158
  end
148
159
  end
data/lib/config.rb CHANGED
@@ -16,73 +16,79 @@ module Orch
16
16
  end
17
17
  end
18
18
 
19
- def check_for_chronos_url
20
- if (! @options.has_key?("chronos_url")) && (@APP_CONFIG.nil? || @APP_CONFIG["chronos_url"].nil?)
21
- return false
22
- else
23
- return true
24
- end
25
- end
26
-
27
- def check_for_marathon_url
28
- if (! @options.has_key?("marathon_url")) && (@APP_CONFIG.nil? || @APP_CONFIG["marathon_url"].nil?)
29
- return false
30
- else
31
- return true
19
+ def chronos_url(spec, app)
20
+ if @options.has_key?("chronos_url")
21
+ url = @options["chronos_url"]
22
+ return url
32
23
  end
33
- end
34
24
 
35
- def check_for_bamboo_url
36
- if (! @options.has_key?("bamboo_url")) && (@APP_CONFIG.nil? || @APP_CONFIG["bamboo_url"].nil?)
37
- return false
38
- else
39
- return true
25
+ if !app.chronos_url.nil?
26
+ return app.chronos_url
40
27
  end
41
- end
42
28
 
43
- def chronos_url
44
- if @options.has_key?("chronos_url")
45
- # If passed in on command line override what is in config file
46
- url = @options["chronos_url"]
47
- return url
29
+ if !spec.config.nil?
30
+ if !spec.config.chronos_url.nil?
31
+ return spec.config.chronos_url
32
+ end
48
33
  end
49
34
 
50
- if @APP_CONFIG.nil? || @APP_CONFIG["chronos_url"].nil?
51
- puts "chronos_url not specified, use --chronos_url or set in ~/.orch/config.yml"
52
- exit 1
35
+ if !@APP_CONFIG.nil?
36
+ if !@APP_CONFIG["chronos_url"].nil?
37
+ return @APP_CONFIG["chronos_url"]
38
+ end
53
39
  end
54
40
 
55
- return @APP_CONFIG["chronos_url"]
41
+ return nil
56
42
  end
57
43
 
58
- def marathon_url
44
+ def marathon_url(spec, app)
59
45
  if @options.has_key?("marathon_url")
60
- # If passed in on command line override what is in config file
61
46
  url = @options["marathon_url"]
62
47
  return url
63
48
  end
64
49
 
65
- if @APP_CONFIG.nil? || @APP_CONFIG["marathon_url"].nil?
66
- puts "marathon_url not specified, use --marathon_url or set in ~/.orch/config.yml"
67
- exit 1
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
68
64
  end
69
65
 
70
- return @APP_CONFIG["marathon_url"]
66
+ return nil
71
67
  end
72
68
 
73
- def bamboo_url
69
+ def bamboo_url(spec, app)
74
70
  if @options.has_key?("bamboo_url")
75
- # If passed in on command line override what is in config file
76
71
  url = @options["bamboo_url"]
77
72
  return url
78
73
  end
79
74
 
80
- if @APP_CONFIG.nil? || @APP_CONFIG["bamboo_url"].nil?
81
- puts "bamboo_url not specified, use --bamboo_url or set in ~/.orch/config.yml"
82
- exit 1
75
+ if !app.bamboo_url.nil?
76
+ return app.bamboo_url
77
+ end
78
+
79
+ if !spec.config.nil?
80
+ if !spec.config.bamboo_url.nil?
81
+ return spec.config.bamboo_url
82
+ end
83
+ end
84
+
85
+ if !@APP_CONFIG.nil?
86
+ if !@APP_CONFIG["bamboo_url"].nil?
87
+ return @APP_CONFIG["bamboo_url"]
88
+ end
83
89
  end
84
90
 
85
- return @APP_CONFIG["bamboo_url"]
91
+ return nil
86
92
  end
87
93
 
88
94
  def setup_config(settings)
data/lib/marathon.rb CHANGED
@@ -14,17 +14,23 @@ end
14
14
  module Orch
15
15
  class Marathon
16
16
  def initialize(options)
17
- # TODO: get chronos and marathon urls from diffferent ways: param, env, .config
18
- @config = Orch::Config.new(options)
19
17
  end
20
18
 
21
- def deploy(app_id, json_payload)
22
- uri = URI(@config.marathon_url)
19
+ def deploy(url, app_id, json_payload)
20
+ if url.nil?
21
+ exit_with_msg "marathon_url not defined"
22
+ end
23
+
24
+ uri = URI(url)
23
25
  json_headers = {"Content-Type" => "application/json",
24
26
  "Accept" => "application/json"}
25
27
 
26
28
  http = Net::HTTP.new(uri.host, uri.port)
27
- response = http.put("/v2/apps/#{app_id}", json_payload, json_headers)
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
28
34
 
29
35
  # TODO: should we do anyting with version or deploymentId that gets returned?
30
36
  if response.code == 201.to_s
@@ -38,13 +44,21 @@ module Orch
38
44
  return response
39
45
  end
40
46
 
41
- def delete(id)
42
- uri = URI(@config.marathon_url)
47
+ def delete(url, id)
48
+ if url.nil?
49
+ exit_with_msg "marathon_url not defined"
50
+ end
51
+
52
+ uri = URI(url)
43
53
  json_headers = {"Content-Type" => "application/json",
44
54
  "Accept" => "application/json"}
45
55
 
46
56
  http = Net::HTTP.new(uri.host, uri.port)
47
- response = http.delete("/v2/apps/#{id}", json_headers)
57
+ begin
58
+ response = http.delete("/v2/apps/#{id}", json_headers)
59
+ rescue *HTTP_ERRORS => error
60
+ http_fault(error)
61
+ end
48
62
 
49
63
  if response.code == 200.to_s
50
64
  puts "successfully deleted #{id}"
@@ -57,20 +71,24 @@ module Orch
57
71
  return response
58
72
  end
59
73
 
60
- def verify(json_payload)
61
- if @config.check_for_marathon_url == false
74
+ def verify(url, json_payload)
75
+ if url.nil?
62
76
  puts "no marathon_url - can not verify with server"
63
77
  return
64
78
  end
65
79
 
66
80
  spec = Hashie::Mash.new(JSON.parse(json_payload))
67
81
 
68
- uri = URI(@config.marathon_url)
82
+ uri = URI(url)
69
83
  json_headers = {"Content-Type" => "application/json",
70
84
  "Accept" => "application/json"}
71
85
 
72
86
  http = Net::HTTP.new(uri.host, uri.port)
73
- response = http.get("/v2/apps/#{spec.id}", json_headers)
87
+ begin
88
+ response = http.get("/v2/apps/#{spec.id}", json_headers)
89
+ rescue *HTTP_ERRORS => error
90
+ http_fault(error)
91
+ end
74
92
 
75
93
  if response.code == 200.to_s
76
94
  job = Hashie::Mash.new(JSON.parse(response.body))
@@ -86,14 +104,23 @@ module Orch
86
104
  return foundDiffs
87
105
  end
88
106
 
89
- def restart(app_id)
107
+ def restart(url, app_id)
108
+ if url.nil?
109
+ exit_with_msg "marathon_url not defined"
110
+ end
111
+
112
+ uri = URI(url)
113
+
90
114
  # POST /v2/apps/{appId}/restart: Rolling restart of all tasks of the given app
91
- uri = URI(@config.marathon_url)
92
115
  json_headers = {"Content-Type" => "application/json",
93
116
  "Accept" => "application/json"}
94
117
 
95
118
  http = Net::HTTP.new(uri.host, uri.port)
96
- response = http.post("/v2/apps/#{app_id}/restart", {}.to_json, json_headers)
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
97
124
 
98
125
  if response.code == 200.to_s
99
126
  puts "success"
data/lib/orch/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Orch
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
data/lib/orch.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "orch/version"
2
+ require 'util'
2
3
  require 'hashie'
3
4
  require 'json'
4
5
  require 'thor'
@@ -13,7 +14,7 @@ module Orch
13
14
 
14
15
  desc 'config', 'Interactive way to build ~/.orch/config.yml file'
15
16
  def config
16
- config = Orch::Config.new(options)
17
+ $ORCH_CONFIG = Orch::Config.new(options)
17
18
 
18
19
  if File.file?("#{Dir.home}/.orch/config.yml")
19
20
  say "This will over-write your existing ~/.orch/config.yaml file", :yellow
@@ -28,7 +29,7 @@ module Orch
28
29
  settings["chronos_url"] = ask("Chronos URL: ")
29
30
  settings["bamboo_url"] = ask("Bamboo URL: ")
30
31
 
31
- config.setup_config(settings)
32
+ $ORCH_CONFIG.setup_config(settings)
32
33
  end
33
34
 
34
35
  option :deploy_kind, :default => 'all',
@@ -41,17 +42,30 @@ module Orch
41
42
  :desc => 'show the json result that would be sent to Chronos or Marathon'
42
43
  option :server_verify, :default => true,
43
44
  :desc => 'verify the configuration against the server'
44
- desc 'verify PATH', 'Checks basic syntax and does not deploy'
45
+ option :chronos_url,
46
+ :desc => 'url to chronos master'
47
+ option :marathon_url,
48
+ :desc => 'url to marathon master'
49
+ option :bamboo_url,
50
+ :desc => 'url to bamboo server'
51
+ desc 'verify PATH', 'Checks basic syntax, server configuration and does not deploy'
45
52
  def verify(file_name)
53
+ $ORCH_CONFIG = Orch::Config.new(options)
46
54
  parser = Orch::Parse.new(file_name, options)
47
55
  result = parser.parse(true)
48
- puts "Number of configs found: #{result.length}"
56
+
57
+ numToDeploy = 0
58
+ result.each do |app|
59
+ numToDeploy += 1 if app[:deploy] == true
60
+ end
61
+ puts "Number of configs found: #{result.length} - #{numToDeploy} would deploy"
49
62
 
50
63
  marathon = Orch::Marathon.new(options)
51
64
  chronos = Orch::Chronos.new(options)
52
65
  bamboo = Orch::Bamboo.new(options)
53
66
  result.each do |app|
54
- printf "Name: %s, Type: %s, Deploy?: %s", app[:name], app[:type], app[:deploy]
67
+ next if app[:deploy] == false
68
+ printf "Name: %s, Type: %s", app[:name], app[:type]
55
69
  app[:env_vars].each do |key, value|
56
70
  printf ", %s: %s", key, value
57
71
  end
@@ -62,12 +76,12 @@ module Orch
62
76
  end
63
77
  foundDiffs = false
64
78
  if (app[:type] == "Chronos") && (options[:server_verify] == true)
65
- foundDiffs = chronos.verify(app[:json].to_json)
79
+ foundDiffs = chronos.verify(app[:url], app[:json].to_json)
66
80
  end
67
81
  if (app[:type] == "Marathon") && (options[:server_verify] == true)
68
- foundDiffs = marathon.verify(app[:json].to_json)
82
+ foundDiffs = marathon.verify(app[:url], app[:json].to_json)
69
83
  if app[:bamboo_spec]
70
- bambooDiffs = bamboo.verify(app[:name], app[:bamboo_spec])
84
+ bambooDiffs = bamboo.verify(app[:bamboo_url], app[:name], app[:bamboo_spec])
71
85
  foundDiffs = foundDiffs || bambooDiffs
72
86
  end
73
87
  end
@@ -81,16 +95,17 @@ module Orch
81
95
  :desc => 'deploys only the given application kind: chronos, marathon, all'
82
96
  option :deploy_var, :default => 'all',
83
97
  :desc => 'DEPLOY_VAR=VALUE deploys only if a deploy_var matches the given value'
98
+ option :subst,
99
+ :desc => 'KEY=VALUE substitute KEY with VALUE globaly in your config'
84
100
  option :chronos_url,
85
101
  :desc => 'url to chronos master'
86
102
  option :marathon_url,
87
103
  :desc => 'url to marathon master'
88
104
  option :bamboo_url,
89
105
  :desc => 'url to bamboo server'
90
- option :subst,
91
- :desc => 'KEY=VALUE substitute KEY with VALUE globaly in your config'
92
- desc 'deploy PATH', 'Deploys config to mesos frameworks.'
106
+ desc 'deploy PATH', 'Deploys application(s) to mesos frameworks.'
93
107
  def deploy(file_name)
108
+ $ORCH_CONFIG = Orch::Config.new(options)
94
109
  parser = Orch::Parse.new(file_name, options)
95
110
  result = parser.parse(false)
96
111
 
@@ -109,12 +124,12 @@ module Orch
109
124
  puts "deploying #{app[:name]} to #{app[:type]}"
110
125
  #puts "#{app[:json]}" - should I support show_json here as well?
111
126
  if app[:type] == "Chronos"
112
- chronos.deploy(app[:json].to_json)
127
+ chronos.deploy(app[:url], app[:json].to_json)
113
128
  end
114
129
  if app[:type] == "Marathon"
115
- marathon.deploy(app[:name], app[:json].to_json)
130
+ marathon.deploy(app[:url], app[:name], app[:json].to_json)
116
131
  if app[:bamboo_spec]
117
- bamboo.deploy(app[:name], app[:bamboo_spec])
132
+ bamboo.deploy(app[:bamboo_url], app[:name], app[:bamboo_spec])
118
133
  end
119
134
  end
120
135
  end
@@ -124,16 +139,17 @@ module Orch
124
139
  :desc => 'deletes only the given application kind: chronos, marathon, all'
125
140
  option :deploy_var, :default => 'all',
126
141
  :desc => 'DEPLOY_VAR=VALUE deletes only if a deploy_var matches the given value'
142
+ option :subst,
143
+ :desc => 'KEY=VALUE substitute KEY with VALUE globaly in your config'
127
144
  option :chronos_url,
128
145
  :desc => 'url to chronos master'
129
146
  option :marathon_url,
130
147
  :desc => 'url to marathon master'
131
148
  option :bamboo_url,
132
149
  :desc => 'url to bamboo server'
133
- option :subst,
134
- :desc => 'KEY=VALUE substitute KEY with VALUE globaly in your config'
135
- desc 'delete PATH', 'Deletes config from mesos frameworks.'
150
+ desc 'delete PATH', 'Deletes application(s) from mesos frameworks.'
136
151
  def delete(file_name)
152
+ $ORCH_CONFIG = Orch::Config.new(options)
137
153
  parser = Orch::Parse.new(file_name, options)
138
154
  result = parser.parse(false)
139
155
 
@@ -152,12 +168,12 @@ module Orch
152
168
  end
153
169
  puts "deleting #{app[:name]} from #{app[:type]}"
154
170
  if app[:type] == "Chronos"
155
- chronos.delete(app[:name])
171
+ chronos.delete(app[:url], app[:name])
156
172
  end
157
173
  if app[:type] == "Marathon"
158
- marathon.delete(app[:name])
174
+ marathon.delete(app[:url], app[:name])
159
175
  if app[:bamboo_spec]
160
- bamboo.delete(app[:name])
176
+ bamboo.delete(app[:url], app[:name])
161
177
  end
162
178
  end
163
179
  end
@@ -173,6 +189,7 @@ module Orch
173
189
  :desc => 'KEY=VALUE substitute KEY with VALUE globaly in your config'
174
190
  desc 'restart PATH', 'Restarts specified application(s) on server'
175
191
  def restart(file_name)
192
+ $ORCH_CONFIG = Orch::Config.new(options)
176
193
  parser = Orch::Parse.new(file_name, options)
177
194
  result = parser.parse(false)
178
195
 
@@ -188,7 +205,7 @@ module Orch
188
205
  end
189
206
  puts "restarting #{app[:name]} on #{app[:type]}"
190
207
  if app[:type] == "Marathon"
191
- marathon.restart(app[:name])
208
+ marathon.restart(app[:url], app[:name])
192
209
  end
193
210
  end
194
211
  end
data/lib/parse.rb CHANGED
@@ -1,20 +1,20 @@
1
1
  require 'yaml'
2
2
  require 'json'
3
3
 
4
+ CURRENT_SPEC_VERSION=1.0
5
+
4
6
  module Orch
5
7
  class Parse
6
8
 
7
9
  def initialize(path, options)
8
10
  if ! File.file?(path)
9
- puts "file does not exist: #{path}"
10
- exit 1
11
+ exit_with_msg "file does not exist: #{path}"
11
12
  end
12
13
 
13
14
  begin
14
15
  yaml = ::YAML.load_file(path)
15
16
  rescue Psych::SyntaxError => e
16
- puts "error parsing yaml file #{e}"
17
- exit 1
17
+ exit_with_msg "error parsing yaml file #{e}"
18
18
  end
19
19
 
20
20
  @options = options
@@ -25,19 +25,9 @@ module Orch
25
25
  def parse(dry_run)
26
26
  @dry_run = dry_run
27
27
  check_option_syntax
28
+ check_version
28
29
  spec = @spec
29
30
 
30
- # Check for valid version paramter
31
- if spec.version.nil?
32
- puts "required field version was not found"
33
- exit 1
34
- end
35
- if spec.version != "alpha1"
36
- puts "unsupported orch version specified: #{spec.version}"
37
- puts "application only understands version alpha1"
38
- exit 1
39
- end
40
-
41
31
  # Check for vault vars
42
32
  env_var_values = parse_vault_vars(@spec)
43
33
 
@@ -47,21 +37,18 @@ module Orch
47
37
  end
48
38
 
49
39
  if spec.applications.nil?
50
- puts "required section applications: must have at least one application defined"
51
- exit 1
40
+ exit_with_msg "required section applications: must have at least one application defined"
52
41
  end
53
42
 
54
43
  results = []
55
44
  spec.applications.each do |app|
56
45
  # Check for valid kind paramter
57
46
  if app.kind.nil?
58
- puts "required field 'kind:' was not found"
59
- exit 1
47
+ exit_with_msg "required field 'kind:' was not found"
60
48
  end
61
49
 
62
50
  if !(app.kind == "Chronos" || app.kind == "Marathon")
63
- puts "unsupported kind specified: #{app.kind} - must be: Chronos | Marathon"
64
- exit 1
51
+ exit_with_msg "unsupported kind specified: #{app.kind} - must be: Chronos | Marathon"
65
52
  end
66
53
 
67
54
  # Generate any deploy variables that need to be merged in
@@ -76,18 +63,34 @@ module Orch
76
63
  if (app.kind == "Chronos")
77
64
  chronos_spec = parse_chronos(app, app_var_values)
78
65
 
79
- result = {:name => chronos_spec["name"], :type => app.kind, :deploy => should_deploy?(app), :env_vars => deploy_vars, :json => chronos_spec}
66
+ result = {
67
+ :name => chronos_spec["name"],
68
+ :type => app.kind,
69
+ :deploy => should_deploy?(app),
70
+ :env_vars => deploy_vars,
71
+ :json => chronos_spec,
72
+ :url => $ORCH_CONFIG.chronos_url(spec, app)
73
+ }
74
+
80
75
  results << result
81
76
  end
82
77
 
83
78
  if (app.kind == "Marathon")
84
79
  marathon_spec = parse_marathon(app, app_var_values)
85
80
 
86
- result = {:name => marathon_spec["id"], :type => app.kind, :deploy => should_deploy?(app), :env_vars => deploy_vars, :json => marathon_spec}
81
+ result = {
82
+ :name => marathon_spec["id"],
83
+ :type => app.kind,
84
+ :deploy => should_deploy?(app),
85
+ :env_vars => deploy_vars,
86
+ :json => marathon_spec,
87
+ :url => $ORCH_CONFIG.marathon_url(spec, app)
88
+ }
87
89
 
88
90
  if app.bamboo_spec
89
91
  bamboo_spec = parse_bamboo(app, app_var_values)
90
92
  result[:bamboo_spec] = bamboo_spec
93
+ result[:bamboo_url] = $ORCH_CONFIG.bamboo_url(spec, app)
91
94
  end
92
95
 
93
96
  results << result
@@ -103,13 +106,11 @@ module Orch
103
106
  if (! @spec.deploy_vars.nil?)
104
107
  @spec.deploy_vars.each do |key, value|
105
108
  if app[key].nil?
106
- puts "environments_var #{key} specified - but not included in app"
109
+ exit_with_msg "deploy_var #{key} specified - but not included in app"
107
110
  # TODO: would be nice to put the app name...
108
- exit 1
109
111
  end
110
112
  if ! @spec.deploy_vars[key].include? app[key]
111
- puts "#{key} value \"#{app[key]}\" not in #{@spec.deploy_vars[key].to_s}"
112
- exit 1
113
+ exit_with_msg "#{key} value \"#{app[key]}\" not in #{@spec.deploy_vars[key].to_s}"
113
114
  end
114
115
  result[key] = app[key]
115
116
  end
@@ -132,8 +133,7 @@ module Orch
132
133
 
133
134
  def parse_chronos(app, env_var_values)
134
135
  if app.chronos_spec.nil?
135
- puts "App of kind: Chronos requires a 'chronos_spec:' field"
136
- exit 1
136
+ exit_with_msg "App of kind: Chronos requires a 'chronos_spec:' field"
137
137
  end
138
138
  chronos_spec = app.chronos_spec
139
139
 
@@ -159,8 +159,7 @@ module Orch
159
159
 
160
160
  def parse_marathon(app, env_var_values)
161
161
  if app.marathon_spec.nil?
162
- puts "App of kind: Marathon requires a 'marathon_spec:' field"
163
- exit 1
162
+ exit_with_msg "App of kind: Marathon requires a 'marathon_spec:' field"
164
163
  end
165
164
  marathon_spec = app.marathon_spec
166
165
 
@@ -173,8 +172,7 @@ module Orch
173
172
  if marathon_spec.id
174
173
  marathon_spec.id = (marathon_spec.id[0] == '/') ? marathon_spec.id : ("/" + marathon_spec.id)
175
174
  else
176
- puts "id: is a required field for a marathon spec"
177
- exit 1
175
+ exit_with_msg "id: is a required field for a marathon spec"
178
176
  end
179
177
 
180
178
  spec_str = do_subst(marathon_spec, app)
@@ -207,8 +205,7 @@ module Orch
207
205
  deployVar = pair[0]
208
206
  deployVal = pair[1]
209
207
  if app[deployVar].nil?
210
- puts "environment var of '#{deployVar}' not found in app"
211
- exit 1
208
+ exit_with_msg "environment var of '#{deployVar}' not found in app"
212
209
  end
213
210
  if app[deployVar] != deployVal
214
211
  result = false
@@ -237,17 +234,48 @@ module Orch
237
234
  end
238
235
  end
239
236
 
237
+ # Check if any substitution variables still exist
238
+ tag_match = /{{\w+}}/.match(spec_str)
239
+ if !tag_match.nil?
240
+ exit_with_msg "unsubstituted varaibles still remain in spec: #{tag_match.to_s}"
241
+ end
242
+
240
243
  return spec_str
241
244
  end
242
245
 
246
+ def check_version
247
+
248
+ # Check for valid version paramter
249
+ if @spec.version.nil?
250
+ exit_with_msg "required field version was not found"
251
+ end
252
+
253
+ if @spec.version == "alpha1"
254
+ # Getting rid of alpha1 syntax and just going to number syntax. Will support this for a little bit...
255
+ version = 1.0
256
+ else
257
+
258
+ number = Float( @spec.version ) rescue nil
259
+ if number.nil?
260
+ exit_with_msg "invalid value \"#{@spec.version}\" for version field of spec"
261
+ end
262
+ version = number
263
+ end
264
+
265
+ if version > CURRENT_SPEC_VERSION
266
+ STDERR.puts "warning: spec version greater than software supports - may get failure or unexpected behavior"
267
+ end
268
+
269
+ # If we get to point where we need to support older formats - determine that here.
270
+ end
271
+
243
272
  def check_option_syntax
244
273
  if @dry_run
245
274
  return
246
275
  end
247
276
 
248
277
  if ! ['chronos', 'marathon', 'all'].include?(@options[:deploy_kind])
249
- puts "value of --deploy-type was #{@options[:deploy_kind]}, must be chronos, marathon or all"
250
- exit 1
278
+ exit_with_msg "value of --deploy-type was #{@options[:deploy_kind]}, must be chronos, marathon or all"
251
279
  end
252
280
  end
253
281
  end
data/lib/util.rb ADDED
@@ -0,0 +1,22 @@
1
+ require 'net/http'
2
+
3
+ HTTP_ERRORS = [
4
+ EOFError,
5
+ Errno::ECONNRESET,
6
+ Errno::EINVAL,
7
+ Net::HTTPBadResponse,
8
+ Net::HTTPHeaderSyntaxError,
9
+ Net::ProtocolError,
10
+ Timeout::Error,
11
+ Errno::ECONNREFUSED
12
+ ]
13
+
14
+ def http_fault(error)
15
+ puts "Networking error talking to framework: #{error.to_s}"
16
+ exit 1
17
+ end
18
+
19
+ def exit_with_msg(err_msg)
20
+ puts err_msg
21
+ exit 1
22
+ 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.3
4
+ version: 0.0.4
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-08-28 00:00:00.000000000 Z
11
+ date: 2015-11-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -93,6 +93,7 @@ files:
93
93
  - lib/orch.rb
94
94
  - lib/orch/version.rb
95
95
  - lib/parse.rb
96
+ - lib/util.rb
96
97
  - orch.gemspec
97
98
  homepage: https://github.com/rayjohnson/orch
98
99
  licenses:
@@ -114,7 +115,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
115
  version: '0'
115
116
  requirements: []
116
117
  rubyforge_project:
117
- rubygems_version: 2.4.6
118
+ rubygems_version: 2.0.14
118
119
  signing_key:
119
120
  specification_version: 4
120
121
  summary: orch uses yaml to deploy to Mesos' Marathon and Chronos frameworks