thefactory/marathon-python — pull request #1 by Codeacious (2014-07-02 21:25:34+00:00)
Title: allowing stagedAt and startedAt keys to be null

The 'startedAt' key can be null in the returned JSON from Marathon about a task if the task has been staged but not started, causing an unhandled TypeError:
```
Traceback (most recent call last):
File "setup_marathon_job.py", line 251, in
main()
File "setup_marathon_job.py", line 204, in setup_service
client.get_app(full_id)
File "/nail/home/jrm/.local/lib/python2.6/site-packages/marathon/client.py", line 100, in get_app
return self._parse_response(response, MarathonApp)
File "/nail/home/jrm/.local/lib/python2.6/site-packages/marathon/client.py", line 44, in _parse_response
return clazz.json_decode(response.json()[resource_name])
File "/nail/home/jrm/.local/lib/python2.6/site-packages/marathon/models/app.py", line 71, in json_decode
tasks=[MarathonTask.json_decode(t) for t in obj.get('tasks', [])],
File "/nail/home/jrm/.local/lib/python2.6/site-packages/marathon/models/task.py", line 47, in json_decode
started_at=datetime.strptime(obj.get('startedAt'), cls.TIMESTAMP_FORMAT)
TypeError: strptime() argument 1 must be string, not None
```

Returned JSON from the app in question:
```
$ curl http://[OMITTED]:5052/v2/apps/mumble.main.yelp5 | python -mjson.tool
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
104 832 104 832 0 0 6279 0 --:--:-- --:--:-- --:--:-- 6991
{
"app": {
"cmd": "",
"constraints": [],
"container": {
"image": "docker:///[OMITTED]/soa_mumble:0.1",
"options": [
"-v",
"/nail/etc/:/nail/etc/:ro"
]
},
"cpus": 1.0,
"disk": 0.0,
"env": {},
"executor": "",
"healthChecks": [],
"id": "mumble.main.yelp5",
"instances": 2,
"mem": 100.0,
"ports": [
11008
],
"taskRateLimit": 1.0,
"tasks": [
{
"host": "[OMITTED]",
"id": "mumble.main.yelp5.30bddf15-0226-11e4-80d4-836ab988308b",
"ports": [
31073
],
"stagedAt": "2014-07-02T20:19:37.789Z",
"startedAt": null,
"version": "2014-07-02T20:19:33.639Z"
},
{
"host": "[OMITTED]",
"id": "mumble.main.yelp5.d3e19b26-0229-11e4-80d4-836ab988308b",
"ports": [
31689
],
"stagedAt": "2014-07-02T20:45:39.966Z",
"startedAt": "2014-07-02T20:45:41.960Z",
"version": "2014-07-02T20:45:36.054Z"
}
],
"tasksRunning": 1,
"tasksStaged": 1,
"uris": [],
"version": "2014-07-02T20:45:36.054Z"
}
}
```

I'm not sure if this can also happen with the stagedAt key (I think a task is only created if it's staged?), but I've added guards for both keys in task.py in case the value of either key is null.