Add support for properties that span across all action of a job
Added support for action_defaults Change-Id: Iccc6faf6472cce12c69d4bcbe7fe05cffa902df1
This commit is contained in:
parent
f86560268e
commit
bdb743aef6
65
README.rst
65
README.rst
|
@ -566,6 +566,71 @@ Finished job with result::
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
8.2 Actions default value
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
It is possible to define properties that span accross multiple actions
|
||||||
|
This allow not to rewrite values that might be the same in multiple actions.
|
||||||
|
If properties are specificaly set in one action, then the specified value is the one used.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
"job": {
|
||||||
|
"action_defaults": {
|
||||||
|
"log_file": "/tmp/freezer_tmp_log",
|
||||||
|
"container": "my_backup_container"
|
||||||
|
},
|
||||||
|
"job_actions":
|
||||||
|
[
|
||||||
|
{"freezer_action":{
|
||||||
|
"action" : "backup",
|
||||||
|
"mode" : "fs",
|
||||||
|
"src_file" : "/home/user1/file",
|
||||||
|
"backup_name" : "user1_backup"}},
|
||||||
|
{"freezer_action":{
|
||||||
|
"action" : "backup",
|
||||||
|
"mode" : "fs",
|
||||||
|
"src_file" : "/home/user2/file",
|
||||||
|
"backup_name" : "user2_backup"}},
|
||||||
|
{"freezer_action":{
|
||||||
|
"action" : "backup",
|
||||||
|
"mode" : "fs",
|
||||||
|
"src_file" : "/home/user3/file",
|
||||||
|
"backup_name" : "user2_backup",
|
||||||
|
"log_file" : "/home/user3/specific_log_file" }}
|
||||||
|
]
|
||||||
|
"description": "scheduled one shot"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Is Equivalent to::
|
||||||
|
"job": {
|
||||||
|
"job_actions":
|
||||||
|
[
|
||||||
|
{"freezer_action":{
|
||||||
|
"action" : "backup",
|
||||||
|
"mode" : "fs",
|
||||||
|
"src_file" : "/home/user1/file",
|
||||||
|
"backup_name" : "user1_backup",
|
||||||
|
"log_file": "/tmp/freezer_tmp_log",
|
||||||
|
"container": "my_backup_container"}},
|
||||||
|
{"freezer_action":{
|
||||||
|
"action" : "backup",
|
||||||
|
"mode" : "fs",
|
||||||
|
"src_file" : "/home/user2/file",
|
||||||
|
"backup_name" : "user2_backup",
|
||||||
|
"log_file": "/tmp/freezer_tmp_log",
|
||||||
|
"container": "my_backup_container"}},
|
||||||
|
{"freezer_action":{
|
||||||
|
"action" : "backup",
|
||||||
|
"mode" : "fs",
|
||||||
|
"src_file" : "/home/user3/file",
|
||||||
|
"backup_name" : "user2_backup",
|
||||||
|
"log_file" : "/home/user3/specific_log_file",
|
||||||
|
"container": "my_backup_container"}},
|
||||||
|
]
|
||||||
|
"description": "scheduled one shot"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
9 Actions
|
9 Actions
|
||||||
=========
|
=========
|
||||||
|
|
|
@ -79,14 +79,14 @@ class JobsCollectionResource(JobsBaseResource):
|
||||||
def on_post(self, req, resp):
|
def on_post(self, req, resp):
|
||||||
# POST /v1/jobs Creates job entry
|
# POST /v1/jobs Creates job entry
|
||||||
try:
|
try:
|
||||||
doc = self.json_body(req)
|
job = Job(self.json_body(req))
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise freezer_api_exc.BadDataFormat(
|
raise freezer_api_exc.BadDataFormat(
|
||||||
message='Missing request body')
|
message='Missing request body')
|
||||||
|
|
||||||
user_id = req.get_header('X-User-ID')
|
user_id = req.get_header('X-User-ID')
|
||||||
self.update_actions_in_job(user_id, doc)
|
self.update_actions_in_job(user_id, job.doc)
|
||||||
job_id = self.db.add_job(user_id=user_id, doc=doc)
|
job_id = self.db.add_job(user_id=user_id, doc=job.doc)
|
||||||
resp.status = falcon.HTTP_201
|
resp.status = falcon.HTTP_201
|
||||||
resp.body = {'job_id': job_id}
|
resp.body = {'job_id': job_id}
|
||||||
|
|
||||||
|
@ -116,21 +116,21 @@ class JobsResource(JobsBaseResource):
|
||||||
def on_patch(self, req, resp, job_id):
|
def on_patch(self, req, resp, job_id):
|
||||||
# PATCH /v1/jobs/{job_id} updates the specified job
|
# PATCH /v1/jobs/{job_id} updates the specified job
|
||||||
user_id = req.get_header('X-User-ID') or ''
|
user_id = req.get_header('X-User-ID') or ''
|
||||||
doc = self.json_body(req)
|
job = Job(self.json_body(req))
|
||||||
self.update_actions_in_job(user_id, doc)
|
self.update_actions_in_job(user_id, job.doc)
|
||||||
new_version = self.db.update_job(user_id=user_id,
|
new_version = self.db.update_job(user_id=user_id,
|
||||||
job_id=job_id,
|
job_id=job_id,
|
||||||
patch_doc=doc)
|
patch_doc=job.doc)
|
||||||
resp.body = {'job_id': job_id, 'version': new_version}
|
resp.body = {'job_id': job_id, 'version': new_version}
|
||||||
|
|
||||||
def on_post(self, req, resp, job_id):
|
def on_post(self, req, resp, job_id):
|
||||||
# PUT /v1/jobs/{job_id} creates/replaces the specified job
|
# PUT /v1/jobs/{job_id} creates/replaces the specified job
|
||||||
user_id = req.get_header('X-User-ID') or ''
|
user_id = req.get_header('X-User-ID') or ''
|
||||||
doc = self.json_body(req)
|
job = Job(self.json_body(req))
|
||||||
self.update_actions_in_job(user_id, doc)
|
self.update_actions_in_job(user_id, job.doc)
|
||||||
new_version = self.db.replace_job(user_id=user_id,
|
new_version = self.db.replace_job(user_id=user_id,
|
||||||
job_id=job_id,
|
job_id=job_id,
|
||||||
doc=doc)
|
doc=job.doc)
|
||||||
resp.status = falcon.HTTP_201
|
resp.status = falcon.HTTP_201
|
||||||
resp.body = {'job_id': job_id, 'version': new_version}
|
resp.body = {'job_id': job_id, 'version': new_version}
|
||||||
|
|
||||||
|
@ -215,6 +215,8 @@ class Job(object):
|
||||||
"""
|
"""
|
||||||
def __init__(self, doc):
|
def __init__(self, doc):
|
||||||
self.doc = doc
|
self.doc = doc
|
||||||
|
if self.doc.get("action_defaults") is not None:
|
||||||
|
self.expand_default_properties()
|
||||||
self.event_result = ''
|
self.event_result = ''
|
||||||
self.need_update = False
|
self.need_update = False
|
||||||
if 'job_schedule' not in doc:
|
if 'job_schedule' not in doc:
|
||||||
|
@ -282,3 +284,14 @@ class Job(object):
|
||||||
"""
|
"""
|
||||||
for action_doc in self.doc.get('job_actions', []):
|
for action_doc in self.doc.get('job_actions', []):
|
||||||
yield Action(action_doc)
|
yield Action(action_doc)
|
||||||
|
|
||||||
|
def expand_default_properties(self):
|
||||||
|
action_defaults = self.doc.pop("action_defaults")
|
||||||
|
if isinstance(action_defaults, dict):
|
||||||
|
for key, val in action_defaults.items():
|
||||||
|
for action in self.doc.get("job_actions"):
|
||||||
|
if action["freezer_action"].get(key) is None:
|
||||||
|
action["freezer_action"][key] = val
|
||||||
|
else:
|
||||||
|
raise freezer_api_exc.BadDataForma(message="action_defaults should"
|
||||||
|
"be a dictionary")
|
||||||
|
|
|
@ -215,6 +215,9 @@ job_schema = {
|
||||||
"_version": {
|
"_version": {
|
||||||
"id": "_version",
|
"id": "_version",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"action_defaults": {
|
||||||
|
"$ref": "#/definitions/freezer_action"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": False,
|
"additionalProperties": False,
|
||||||
|
@ -304,6 +307,9 @@ job_patch_schema = {
|
||||||
"_version": {
|
"_version": {
|
||||||
"id": "_version",
|
"id": "_version",
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"action_defaults": {
|
||||||
|
"$ref": "#/definitions/freezer_action"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"additionalProperties": False
|
"additionalProperties": False
|
||||||
|
|
|
@ -204,7 +204,8 @@ class TestJobsResource(unittest.TestCase):
|
||||||
new_version = random.randint(0, 99)
|
new_version = random.randint(0, 99)
|
||||||
self.mock_db.update_job.return_value = new_version
|
self.mock_db.update_job.return_value = new_version
|
||||||
patch_doc = {'some_field': 'some_value',
|
patch_doc = {'some_field': 'some_value',
|
||||||
'because': 'size_matters'}
|
'because': 'size_matters',
|
||||||
|
'job_schedule': {}}
|
||||||
self.mock_req.stream.read.return_value = json.dumps(patch_doc)
|
self.mock_req.stream.read.return_value = json.dumps(patch_doc)
|
||||||
expected_result = {'job_id': fake_job_0_job_id,
|
expected_result = {'job_id': fake_job_0_job_id,
|
||||||
'version': new_version}
|
'version': new_version}
|
||||||
|
@ -472,3 +473,22 @@ class TestJobs(unittest.TestCase):
|
||||||
def test_execute_raises_BadDataFormat_when_event_not_implemented(self):
|
def test_execute_raises_BadDataFormat_when_event_not_implemented(self):
|
||||||
job = v1_jobs.Job({})
|
job = v1_jobs.Job({})
|
||||||
self.assertRaises(BadDataFormat, job.execute_event, 'smile', 'my_params')
|
self.assertRaises(BadDataFormat, job.execute_event, 'smile', 'my_params')
|
||||||
|
|
||||||
|
def test_expand_action_defaults(self):
|
||||||
|
job_doc = {
|
||||||
|
'action_defaults': {'that_field': 'that_value'},
|
||||||
|
'job_actions': [
|
||||||
|
{'freezer_action': {'not_that_field': 'some_value'}},
|
||||||
|
{'freezer_action': {'that_field': 'another_value'}}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
expected_job_doc = {
|
||||||
|
'job_actions': [
|
||||||
|
{'freezer_action': {'not_that_field': 'some_value',
|
||||||
|
'that_field': 'that_value'}},
|
||||||
|
{'freezer_action': {'that_field': 'another_value'}}
|
||||||
|
],
|
||||||
|
'job_schedule': {}
|
||||||
|
}
|
||||||
|
job = v1_jobs.Job(job_doc)
|
||||||
|
self.assertEqual(job.doc, expected_job_doc)
|
||||||
|
|
Loading…
Reference in New Issue