marathon_deploy 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +16 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/NOTES +5 -0
- data/README.md +31 -0
- data/Rakefile +2 -0
- data/TODO +11 -0
- data/bin/deploy +3 -0
- data/bin/deploy.rb +106 -0
- data/bin/json2yaml.rb +5 -0
- data/examples/deploy.json +66 -0
- data/examples/deploy.yaml +54 -0
- data/examples/jondeploy.yaml +16 -0
- data/examples/jondeploy2.yaml +24 -0
- data/examples/nohealthchecks.yaml +18 -0
- data/examples/public-search-germany-webapp.pre.json +67 -0
- data/examples/run.sh +3 -0
- data/examples/testout.json +68 -0
- data/examples/testout.yaml +54 -0
- data/input.txt +66 -0
- data/lib/marathon_deploy.rb +5 -0
- data/lib/marathon_deploy/application.rb +85 -0
- data/lib/marathon_deploy/deployment.rb +269 -0
- data/lib/marathon_deploy/environment.rb +28 -0
- data/lib/marathon_deploy/error.rb +21 -0
- data/lib/marathon_deploy/http_util.rb +91 -0
- data/lib/marathon_deploy/macro.rb +71 -0
- data/lib/marathon_deploy/marathon_client.rb +79 -0
- data/lib/marathon_deploy/marathon_defaults.rb +83 -0
- data/lib/marathon_deploy/utils.rb +31 -0
- data/lib/marathon_deploy/version.rb +3 -0
- data/lib/marathon_deploy/yaml_json.rb +45 -0
- data/marathon_deploy.gemspec +28 -0
- metadata +136 -0
data/examples/run.sh
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
{
|
2
|
+
"args": [
|
3
|
+
"properties.py && FOO=\"`cat /opt/etc/public-search-germany-webapp.properties | grep -v '^\\s*#' | grep -E '.+=.+'`\"; echo $FOO; echo; env $FOO; echo; env $FOO hostName=$HOSTNAME backend.instance.name=$HOSTNAME java -Dhttp.port=8080 -Dajp.port=8009 -Dinstance.confdir=file:///opt/etc -Dbackend.logdir=$MESOS_SANDBOX -Dlog.rootDir=$MESOS_SANDBOX -DlogDir=$MESOS_SANDBOX $CMD_OPTS -Xmx$JAVA_XMX -Xms$JAVA_XMS -jar $MESOS_SANDBOX/public-search-germany-webapp*.jar"
|
4
|
+
],
|
5
|
+
"cmd": null,
|
6
|
+
"container": {
|
7
|
+
"docker": {
|
8
|
+
"image": "dockerregistry.mobile.rz/mobile-java8:latest",
|
9
|
+
"network": "BRIDGE",
|
10
|
+
"portMappings": [
|
11
|
+
{
|
12
|
+
"containerPort": 8080,
|
13
|
+
"hostPort": 0,
|
14
|
+
"protocol": "tcp"
|
15
|
+
},
|
16
|
+
{
|
17
|
+
"containerPort": 8009,
|
18
|
+
"hostPort": 0,
|
19
|
+
"protocol": "tcp"
|
20
|
+
}
|
21
|
+
]
|
22
|
+
},
|
23
|
+
"type": "DOCKER"
|
24
|
+
},
|
25
|
+
"cpus": 0.1,
|
26
|
+
"env": {
|
27
|
+
"APPLICATION_NAME": "public-search-germany-webapp",
|
28
|
+
"CMD_OPTS": "",
|
29
|
+
"CONFIG_ASSEMBLER_BASE_URL": "http://mobile-config-assembler.service.consul/config-assembler",
|
30
|
+
"DATACENTER_NUMBER": "44",
|
31
|
+
"JAVA_XMS": "252m",
|
32
|
+
"JAVA_XMX": "504m",
|
33
|
+
"SERVERCLASS_NAME": "pubse",
|
34
|
+
"SERVICE_8009_NAME": "public-search-germany-webapp",
|
35
|
+
"SERVICE_8009_TAGS": "ajp",
|
36
|
+
"SERVICE_8080_CHECK_SCRIPT": "curl --fail --silent $HOST_IP:$SERVICE_PORT/fz/release-info",
|
37
|
+
"SERVICE_8080_NAME": "public-search-germany-webapp",
|
38
|
+
"SERVICE_8080_TAGS": "http,haproxy"
|
39
|
+
},
|
40
|
+
"healthChecks": [
|
41
|
+
{
|
42
|
+
"gracePeriodSeconds": 30,
|
43
|
+
"intervalSeconds": 10,
|
44
|
+
"maxConsecutiveFailures": 3,
|
45
|
+
"portIndex": 0,
|
46
|
+
"protocol": "TCP",
|
47
|
+
"timeoutSeconds": 30
|
48
|
+
},
|
49
|
+
{
|
50
|
+
"gracePeriodSeconds": 30,
|
51
|
+
"intervalSeconds": 10,
|
52
|
+
"maxConsecutiveFailures": 3,
|
53
|
+
"path": "/fz/release-info",
|
54
|
+
"portIndex": 0,
|
55
|
+
"protocol": "HTTP",
|
56
|
+
"timeoutSeconds": 30
|
57
|
+
}
|
58
|
+
],
|
59
|
+
"id": "somename",
|
60
|
+
"instances": 4,
|
61
|
+
"mem": 512,
|
62
|
+
"storeUrls": [
|
63
|
+
"http://maven-download.mobile.rz/maven/hosted-mobile-deployment-productive-releases/de/mobile/public-search-germany-webapp/ecs-1558-gb70c745/public-search-germany-webapp-ecs-1558-gb70c745.jar"
|
64
|
+
],
|
65
|
+
"uris": [
|
66
|
+
|
67
|
+
]
|
68
|
+
}
|
@@ -0,0 +1,54 @@
|
|
1
|
+
---
|
2
|
+
args:
|
3
|
+
- properties.py && FOO="`cat /opt/etc/public-search-germany-webapp.properties | grep
|
4
|
+
-v '^\s*#' | grep -E '.+=.+'`"; echo $FOO; echo; env $FOO; echo; env $FOO hostName=$HOSTNAME
|
5
|
+
backend.instance.name=$HOSTNAME java -Dhttp.port=8080 -Dajp.port=8009 -Dinstance.confdir=file:///opt/etc
|
6
|
+
-Dbackend.logdir=$MESOS_SANDBOX -Dlog.rootDir=$MESOS_SANDBOX -DlogDir=$MESOS_SANDBOX
|
7
|
+
$CMD_OPTS -Xmx$JAVA_XMX -Xms$JAVA_XMS -jar $MESOS_SANDBOX/public-search-germany-webapp*.jar
|
8
|
+
cmd:
|
9
|
+
container:
|
10
|
+
docker:
|
11
|
+
image: dockerregistry.mobile.rz/mobile-java8:latest
|
12
|
+
network: BRIDGE
|
13
|
+
portMappings:
|
14
|
+
- containerPort: 8080
|
15
|
+
hostPort: 0
|
16
|
+
protocol: tcp
|
17
|
+
- containerPort: 8009
|
18
|
+
hostPort: 0
|
19
|
+
protocol: tcp
|
20
|
+
type: DOCKER
|
21
|
+
cpus: 0.1
|
22
|
+
env:
|
23
|
+
APPLICATION_NAME: public-search-germany-webapp
|
24
|
+
CMD_OPTS: ''
|
25
|
+
CONFIG_ASSEMBLER_BASE_URL: http://mobile-config-assembler.service.consul/config-assembler
|
26
|
+
DATACENTER_NUMBER: '44'
|
27
|
+
JAVA_XMS: 252m
|
28
|
+
JAVA_XMX: 504m
|
29
|
+
SERVERCLASS_NAME: pubse
|
30
|
+
SERVICE_8009_NAME: public-search-germany-webapp
|
31
|
+
SERVICE_8009_TAGS: ajp
|
32
|
+
SERVICE_8080_CHECK_SCRIPT: curl --fail --silent $HOST_IP:$SERVICE_PORT/fz/release-info
|
33
|
+
SERVICE_8080_NAME: public-search-germany-webapp
|
34
|
+
SERVICE_8080_TAGS: http,haproxy
|
35
|
+
healthChecks:
|
36
|
+
- gracePeriodSeconds: 30
|
37
|
+
intervalSeconds: 10
|
38
|
+
maxConsecutiveFailures: 3
|
39
|
+
portIndex: 0
|
40
|
+
protocol: TCP
|
41
|
+
timeoutSeconds: 30
|
42
|
+
- gracePeriodSeconds: 30
|
43
|
+
intervalSeconds: 10
|
44
|
+
maxConsecutiveFailures: 3
|
45
|
+
path: "/fz/release-info"
|
46
|
+
portIndex: 0
|
47
|
+
protocol: HTTP
|
48
|
+
timeoutSeconds: 30
|
49
|
+
id: public-search-germany-webapp
|
50
|
+
instances: 99
|
51
|
+
mem: 512
|
52
|
+
storeUrls:
|
53
|
+
- http://maven-download.mobile.rz/maven/hosted-mobile-deployment-productive-releases/de/mobile/public-search-germany-webapp/ecs-1558-gb70c745/public-search-germany-webapp-ecs-1558-gb70c745.jar
|
54
|
+
uris: []
|
data/input.txt
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
{
|
2
|
+
"args": [
|
3
|
+
"properties.py && FOO=\"`cat /opt/etc/public-search-germany-webapp-%FIRST_VAR%.properties | grep -v '^\\s*#' | grep -E '.+=.+'`\"; echo $FOO; echo; env $FOO; echo; env %SECOND_VAR%$FOO hostName=$HOSTNAME backend.instance.name=$HOSTNAME java -Dhttp.port=8080 -Dajp.port=8009 -Dinstance.confdir=file:///opt/etc -Dbackend.logdir=$MESOS_SANDBOX -Dlog.rootDir=$MESOS_SANDBOX -DlogDir=$MESOS_SANDBOX $CMD_OPTS -Xmx$JAVA_XMX -Xms$JAVA_XMS -jar $MESOS_SANDBOX/public-search-germany-webapp*.jar"
|
4
|
+
],
|
5
|
+
"cmd": null,
|
6
|
+
"container": {
|
7
|
+
"docker": {
|
8
|
+
"image": "dockerregistry.mobile.rz/mobile-java8:latest",
|
9
|
+
"network": "BRIDGE",
|
10
|
+
"portMappings": [
|
11
|
+
{
|
12
|
+
"containerPort": 8080,
|
13
|
+
"hostPort": 0,
|
14
|
+
"protocol": "tcp"
|
15
|
+
},
|
16
|
+
{
|
17
|
+
"containerPort": 8009,
|
18
|
+
"hostPort": 0,
|
19
|
+
"protocol": "tcp"
|
20
|
+
}
|
21
|
+
]
|
22
|
+
},
|
23
|
+
"type": "DOCKER"
|
24
|
+
},
|
25
|
+
"cpus": 0.1,
|
26
|
+
"env": {
|
27
|
+
"APPLICATION_NAME": "public-search-germany-webapp",
|
28
|
+
"CMD_OPTS": "",
|
29
|
+
"CONFIG_ASSEMBLER_BASE_URL": "http://mobile-config-assembler.service.consul/config-assembler",
|
30
|
+
"DATACENTER_NUMBER": "44",
|
31
|
+
"JAVA_XMS": "252m",
|
32
|
+
"JAVA_XMX": "504m",
|
33
|
+
"SERVERCLASS_NAME": "pubse",
|
34
|
+
"SERVICE_8009_NAME": "public-search-germany-webapp",
|
35
|
+
"SERVICE_8009_TAGS": "ajp",
|
36
|
+
"SERVICE_8080_CHECK_SCRIPT": "curl --fail --silent $HOST_IP:%SERVICE_PORT%/fz/release-info",
|
37
|
+
"SERVICE_8080_NAME": "public-search-germany-webapp",
|
38
|
+
"SERVICE_8080_TAGS": "http,haproxy"
|
39
|
+
},
|
40
|
+
"healthChecks": [
|
41
|
+
{
|
42
|
+
"gracePeriodSeconds": 30,
|
43
|
+
"intervalSeconds": 10,
|
44
|
+
"maxConsecutiveFailures": 3,
|
45
|
+
"portIndex": 0,
|
46
|
+
"protocol": "TCP",
|
47
|
+
"timeoutSeconds": 30
|
48
|
+
},
|
49
|
+
{
|
50
|
+
"gracePeriodSeconds": 30,
|
51
|
+
"intervalSeconds": 10,
|
52
|
+
"maxConsecutiveFailures": 3,
|
53
|
+
"path": "/%CONTEXT%%TRICKY%/release-info",
|
54
|
+
"portIndex": 0,
|
55
|
+
"protocol": "HTTP",
|
56
|
+
"timeoutSeconds": 30
|
57
|
+
}
|
58
|
+
],
|
59
|
+
"id": "public-search-germany-webapp",
|
60
|
+
"instances": 4,
|
61
|
+
"mem": 512,
|
62
|
+
"storeUrls": [
|
63
|
+
"http://maven-download.mobile.rz/maven/hosted-mobile-deployment-productive-releases/de/mobile/public-search-germany-webapp/ecs-1558-gb70c745/public-search-germany-webapp-ecs-1558-gb70c745.jar"
|
64
|
+
],
|
65
|
+
"uris": []
|
66
|
+
}
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'marathon_deploy/marathon_defaults'
|
2
|
+
require 'marathon_deploy/yaml_json'
|
3
|
+
require 'marathon_deploy/error'
|
4
|
+
require 'marathon_deploy/utils'
|
5
|
+
|
6
|
+
class Application
|
7
|
+
|
8
|
+
attr_reader :json, :id
|
9
|
+
attr_accessor :envs
|
10
|
+
|
11
|
+
def initialize(deployfile)
|
12
|
+
|
13
|
+
if (!File.exist?(File.join(Dir.pwd,deployfile)))
|
14
|
+
message = "#{deployfile} not found in current directory #{File.join(Dir.pwd)}"
|
15
|
+
raise Error::IOError, message, caller
|
16
|
+
end
|
17
|
+
|
18
|
+
extension = File.extname(deployfile)
|
19
|
+
|
20
|
+
case extension
|
21
|
+
when '.json'
|
22
|
+
@json = YamlJson.read_json(deployfile)
|
23
|
+
when '.yaml'
|
24
|
+
@json = YamlJson.yaml2json(deployfile)
|
25
|
+
else
|
26
|
+
message = "File extension #{extension} is not supported for deployment file #{deployfile}"
|
27
|
+
raise Error::UnsupportedFileExtension, message, caller
|
28
|
+
end
|
29
|
+
|
30
|
+
missing_attributes = MarathonDefaults.missing_attributes(@json)
|
31
|
+
|
32
|
+
if(!missing_attributes.empty?)
|
33
|
+
message = "#{deployfile} is missing required marathon API attributes: #{missing_attributes.join(',')}"
|
34
|
+
raise Error::MissingMarathonAttributesError, message, caller
|
35
|
+
end
|
36
|
+
|
37
|
+
missing_envs = MarathonDefaults.missing_envs(@json)
|
38
|
+
if(!missing_envs.empty?)
|
39
|
+
message = "#{deployfile} is missing required environment variables: #{missing_envs.join(',')}"
|
40
|
+
raise Error::MissingMarathonAttributesError, message, caller
|
41
|
+
end
|
42
|
+
|
43
|
+
@deployfile = deployfile
|
44
|
+
@json = Utils.deep_symbolize(@json)
|
45
|
+
add_identifier
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
def overlay_preproduction_settings
|
50
|
+
@json = MarathonDefaults.overlay_preproduction_settings(@json)
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_identifier
|
54
|
+
random = Utils.random
|
55
|
+
# Time.now.to_i
|
56
|
+
json[:env]['UNIQUE_ID'] = "#{id}_#{random}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_s
|
60
|
+
return id
|
61
|
+
end
|
62
|
+
|
63
|
+
def id
|
64
|
+
if (@json[:id])
|
65
|
+
return @json[:id]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def add_envs(envs)
|
70
|
+
if (envs.is_a?(Hash))
|
71
|
+
envs.each do |key,value|
|
72
|
+
@json[:env][key] = value
|
73
|
+
end
|
74
|
+
else
|
75
|
+
raise Error::BadFormatError, "argument must be a hash", caller
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def instances
|
80
|
+
if (@json[:instances])
|
81
|
+
return @json[:instances]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
@@ -0,0 +1,269 @@
|
|
1
|
+
require 'marathon_deploy/http_util'
|
2
|
+
require 'marathon_deploy/utils'
|
3
|
+
require 'marathon_deploy/marathon_defaults'
|
4
|
+
require 'timeout'
|
5
|
+
|
6
|
+
class Deployment
|
7
|
+
|
8
|
+
DEPLOYMENT_RECHECK_INTERVAL = MarathonDefaults::DEPLOYMENT_RECHECK_INTERVAL
|
9
|
+
DEPLOYMENT_TIMEOUT = MarathonDefaults::DEPLOYMENT_TIMEOUT
|
10
|
+
HEALTHY_WAIT_TIMEOUT = MarathonDefaults::HEALTHY_WAIT_TIMEOUT
|
11
|
+
HEALTHY_WAIT_RECHECK_INTERVAL = MarathonDefaults::HEALTHY_WAIT_RECHECK_INTERVAL
|
12
|
+
|
13
|
+
attr_reader :url, :application, :deploymentId
|
14
|
+
|
15
|
+
def initialize(url, application)
|
16
|
+
raise ArgumentError, "second argument to deployment object must be an Application", caller unless (!application.nil? && application.class == Application)
|
17
|
+
raise Error::BadURLError, "invalid url => #{url}", caller if (!HttpUtil.valid_url(url))
|
18
|
+
@url = HttpUtil.clean_url(url)
|
19
|
+
@application = application
|
20
|
+
end
|
21
|
+
|
22
|
+
def timeout
|
23
|
+
return DEPLOYMENT_TIMEOUT
|
24
|
+
end
|
25
|
+
|
26
|
+
def healthcheck_timeout
|
27
|
+
return HEALTHY_WAIT_TIMEOUT
|
28
|
+
end
|
29
|
+
|
30
|
+
def versions
|
31
|
+
if (!applicationExists?)
|
32
|
+
response = HttpUtil.get(@url + MarathonDefaults::MARATHON_APPS_REST_PATH + @application.id + '/versions')
|
33
|
+
response_body = Utils.response_body(response)
|
34
|
+
return response_body[:versions]
|
35
|
+
else
|
36
|
+
return Array.new
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def wait_for_deployment_id(message = "Deployment with deploymentId #{@deploymentId} in progress")
|
41
|
+
startTime = Time.now
|
42
|
+
deployment_seen = false
|
43
|
+
Timeout::timeout(DEPLOYMENT_TIMEOUT) do
|
44
|
+
while running_for_deployment_id?
|
45
|
+
|
46
|
+
deployment_seen = true
|
47
|
+
#response = list_all
|
48
|
+
#STDOUT.print "." if ( $LOG.level == 1 )
|
49
|
+
elapsedTime = '%.2f' % (Time.now - startTime)
|
50
|
+
$LOG.info(message + " (elapsed time #{elapsedTime}s)")
|
51
|
+
deployments = deployments_for_deployment_id
|
52
|
+
deployments.each do |item|
|
53
|
+
$LOG.debug(deployment_string(item))
|
54
|
+
end
|
55
|
+
sleep(DEPLOYMENT_RECHECK_INTERVAL)
|
56
|
+
end
|
57
|
+
#STDOUT.puts "" if ( $LOG.level == 1 )
|
58
|
+
if (deployment_seen)
|
59
|
+
elapsedTime = '%.2f' % (Time.now - startTime)
|
60
|
+
$LOG.info("Deployment with deploymentId #{@deploymentId} ended (Total time #{elapsedTime}s )")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def wait_for_application(message = "Deployment of application #{@application.id} in progress")
|
66
|
+
deployment_seen = false
|
67
|
+
Timeout::timeout(DEPLOYMENT_TIMEOUT) do
|
68
|
+
while running_for_application_id?
|
69
|
+
deployment_seen = true
|
70
|
+
#response = list_all
|
71
|
+
#STDOUT.print "." if ( $LOG.level == 1 )
|
72
|
+
$LOG.info(message)
|
73
|
+
deployments_for_application_id.each do |item|
|
74
|
+
$LOG.debug(deployment_string(item))
|
75
|
+
end
|
76
|
+
#$LOG.debug(JSON.pretty_generate(JSON.parse(response.body)))
|
77
|
+
sleep(DEPLOYMENT_RECHECK_INTERVAL)
|
78
|
+
end
|
79
|
+
#STDOUT.puts "" if ( $LOG.level == 1 )
|
80
|
+
if (deployment_seen)
|
81
|
+
$LOG.info("Deployment of application #{@application.id} ended")
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def wait_until_healthy
|
87
|
+
Timeout::timeout(HEALTHY_WAIT_TIMEOUT) do
|
88
|
+
loop do
|
89
|
+
break if (!health_checks_defined?)
|
90
|
+
sick = get_alive("false")
|
91
|
+
if (!sick.empty?)
|
92
|
+
$LOG.info("#{sick.size}/#{@application.instances} instances are not healthy => " + sick.join(','))
|
93
|
+
else
|
94
|
+
healthy = get_alive("true")
|
95
|
+
if (healthy.size == @application.instances)
|
96
|
+
$LOG.info("#{healthy.size}/#{@application.instances} instances are healthy => " + healthy.join(','))
|
97
|
+
break
|
98
|
+
else
|
99
|
+
$LOG.info("#{healthy.size}/#{@application.instances} healthy instances seen, retrying")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
sleep(HEALTHY_WAIT_RECHECK_INTERVAL)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def cancel(deploymentId,force=false)
|
108
|
+
raise Error::BadURLError, "deploymentId must be specified to cancel deployment", caller if (deploymentId.empty?)
|
109
|
+
if (running_for_deployment_id?(deploymentId))
|
110
|
+
response = HttpUtil.delete(@url + MarathonDefaults::MARATHON_DEPLOYMENT_REST_PATH + deploymentId + "?force=#{force}")
|
111
|
+
$LOG.debug("Cancellation response [#{response.code}] => " + JSON.pretty_generate(JSON.parse(response.body)))
|
112
|
+
end
|
113
|
+
return response
|
114
|
+
end
|
115
|
+
|
116
|
+
def applicationExists?
|
117
|
+
response = list_app
|
118
|
+
if (response.code.to_i == 200)
|
119
|
+
return true
|
120
|
+
end
|
121
|
+
return false
|
122
|
+
end
|
123
|
+
|
124
|
+
def create_app
|
125
|
+
response = HttpUtil.post(@url + MarathonDefaults::MARATHON_APPS_REST_PATH,@application.json)
|
126
|
+
@deploymentId = get_deployment_id
|
127
|
+
return response
|
128
|
+
end
|
129
|
+
|
130
|
+
def update_app(force=false)
|
131
|
+
url = @url + MarathonDefaults::MARATHON_APPS_REST_PATH + @application.id
|
132
|
+
url += force ? '?force=true' : ''
|
133
|
+
$LOG.debug("Updating app #{@application.id} #{url}")
|
134
|
+
response = HttpUtil.put(url,@application.json)
|
135
|
+
@deploymentId = Utils.response_body(response)[:deploymentId]
|
136
|
+
return response
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
def rolling_restart
|
141
|
+
url = @url + MarathonDefaults::MARATHON_APPS_REST_PATH + @application.id + '/restart'
|
142
|
+
$LOG.debug("Calling marathon api with url: #{url}")
|
143
|
+
response = HttpUtil.post(url,{})
|
144
|
+
$LOG.info("Restart of #{@application.id} returned status code: #{response.code}")
|
145
|
+
$LOG.info(JSON.pretty_generate(JSON.parse(response.body)))
|
146
|
+
end
|
147
|
+
|
148
|
+
def health_checks_defined?
|
149
|
+
response = list_app
|
150
|
+
response_body = Utils.response_body(response)
|
151
|
+
return response_body[:app][:healthChecks].size == 0 ? false : true
|
152
|
+
end
|
153
|
+
|
154
|
+
####### PRIVATE METHODS ##########
|
155
|
+
private
|
156
|
+
|
157
|
+
def get_alive(value)
|
158
|
+
state = Array.new
|
159
|
+
|
160
|
+
if (health_checks_defined?)
|
161
|
+
response = list_app
|
162
|
+
response_body = Utils.response_body(response)
|
163
|
+
if (response_body[:app].empty?)
|
164
|
+
raise Error::DeploymentError, "Marathon returned an empty app json object", caller
|
165
|
+
else
|
166
|
+
get_healthcheck_results.flatten.each do |result|
|
167
|
+
next if result.nil?
|
168
|
+
alive = result[:alive].to_s
|
169
|
+
taskId = result[:taskId].to_s
|
170
|
+
if (!alive.nil? && !taskId.nil?)
|
171
|
+
state << taskId if (alive == value)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
else
|
176
|
+
$LOG.info("No health checks defined. Cannot determine application health of #{@application.id}.")
|
177
|
+
end
|
178
|
+
return state
|
179
|
+
end
|
180
|
+
|
181
|
+
def get_task_ids
|
182
|
+
response = list_app
|
183
|
+
response_body = Utils.response_body(response)
|
184
|
+
return response_body[:app][:tasks].collect { |task| task[:id]}
|
185
|
+
end
|
186
|
+
|
187
|
+
def get_healthcheck_results
|
188
|
+
response = list_app
|
189
|
+
response_body = Utils.response_body(response)
|
190
|
+
return response_body[:app][:tasks].collect { |task| task[:healthCheckResults]}
|
191
|
+
end
|
192
|
+
|
193
|
+
def get_deployment_id
|
194
|
+
response = list_app
|
195
|
+
payload = Utils.response_body(response)
|
196
|
+
return payload[:app][:deployments].first[:id] unless (payload[:app].nil?)
|
197
|
+
return nil
|
198
|
+
end
|
199
|
+
|
200
|
+
def list_all
|
201
|
+
HttpUtil.get(@url + MarathonDefaults::MARATHON_DEPLOYMENT_REST_PATH)
|
202
|
+
end
|
203
|
+
|
204
|
+
def running_for_application_id?
|
205
|
+
if (deployment_running? && !deployments_for_application_id.empty?)
|
206
|
+
return true
|
207
|
+
end
|
208
|
+
return false
|
209
|
+
end
|
210
|
+
|
211
|
+
def running_for_deployment_id?
|
212
|
+
if (deployment_running? && !deployments_for_deployment_id.empty?)
|
213
|
+
return true
|
214
|
+
end
|
215
|
+
return false
|
216
|
+
end
|
217
|
+
|
218
|
+
def deployment_running?
|
219
|
+
response = list_all
|
220
|
+
body = JSON.parse(response.body)
|
221
|
+
return false if body.empty?
|
222
|
+
return true
|
223
|
+
end
|
224
|
+
|
225
|
+
def get_deployment_ids
|
226
|
+
response = list_all
|
227
|
+
payload = JSON.parse(response.body)
|
228
|
+
return payload.collect { |d| d['id'] }
|
229
|
+
end
|
230
|
+
|
231
|
+
def list_app
|
232
|
+
HttpUtil.get(@url + MarathonDefaults::MARATHON_APPS_REST_PATH + @application.id)
|
233
|
+
end
|
234
|
+
|
235
|
+
# DONT USE: the response seems to be broken in marathon for /v2/apps/application-id/tasks
|
236
|
+
#def get_tasks
|
237
|
+
# HttpUtil.get(@url + MarathonDefaults::MARATHON_APPS_REST_PATH + @application.id + '/tasks')
|
238
|
+
#end
|
239
|
+
|
240
|
+
def deployment_string(deploymentJsonObject)
|
241
|
+
string = "\n" + "+-" * 25 + " DEPLOYMENT INFO " + "+-" * 25 + "\n"
|
242
|
+
deploymentJsonObject.sort.each do |k,v|
|
243
|
+
case v
|
244
|
+
when String
|
245
|
+
string += k + " => " + v + "\n"
|
246
|
+
when Fixnum
|
247
|
+
string += k + " => " + v.to_s + "\n"
|
248
|
+
when Array
|
249
|
+
string += k + " => " + v.join(',') + "\n"
|
250
|
+
else
|
251
|
+
string += "#{k} + #{v}\n"
|
252
|
+
end
|
253
|
+
end
|
254
|
+
return string
|
255
|
+
end
|
256
|
+
|
257
|
+
def deployments_for_deployment_id
|
258
|
+
response = list_all
|
259
|
+
payload = JSON.parse(response.body)
|
260
|
+
return payload.find_all { |d| d['id'] == @deploymentId }
|
261
|
+
end
|
262
|
+
|
263
|
+
def deployments_for_application_id
|
264
|
+
response = list_all
|
265
|
+
payload = JSON.parse(response.body)
|
266
|
+
return payload.find_all { |d| d['affectedApps'].include?('/' + @application.id) }
|
267
|
+
end
|
268
|
+
|
269
|
+
end
|