diff options
author | Javier Sánchez Parra <jsanchez@soleta.eu> | 2021-06-04 12:46:15 +0200 |
---|---|---|
committer | OpenGnSys Support Team <soporte-og@soleta.eu> | 2021-06-10 17:00:01 +0200 |
commit | 1fdb7e6d1cf0709b1079b2d9990c0d53d8740461 (patch) | |
tree | e13f19f28e2ee379150171bad00fecec59168901 | |
parent | 893101ffc6162d64cfbe5827c32d4e6de5e35f42 (diff) |
#915 Add commands and procedures to procedure creation
Adds the possibility to create a procedure with commands and other
procedures integrated as steps.
Note: "steps" parameter is optional and "steps" array object order
defines execution order.
Request:
POST /procedure/add
{
"center": "1",
"name": "procedure",
"description": "My procedure",
"steps": [
{
"command": "wol",
"params": { "type": "broadcast" }
},
{
"procedure": 22
},
{
"command": "poweroff",
"params": {}
}
]
}
Response:
200 OK
This commit also updates unit tests for /procedure/add POST method to
include steps.
-rw-r--r-- | src/json.c | 72 | ||||
-rw-r--r-- | src/json.h | 27 | ||||
-rw-r--r-- | src/rest.c | 76 | ||||
-rw-r--r-- | tests/units/test_0033_post_procedure_add.py | 5 |
4 files changed, 176 insertions, 4 deletions
@@ -140,3 +140,75 @@ int og_json_parse_partition(json_t *element, struct og_partition *part, return err; } + +static int og_json_parse_procedure_cmd(json_t *element, int position, + struct og_procedure *proc) +{ + struct og_procedure_step *step; + uint32_t err = 0; + const char *key; + json_t *value; + + step = &proc->steps[proc->num_steps++]; + step->type = OG_STEP_COMMAND; + step->position = position; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "command")) + err = og_json_parse_string(value, &step->cmd.type); + else if (!strcmp(key, "params")) + step->cmd.json = value; + else + return -1; + } + + return err; +} + +static int og_json_parse_procedure_call(json_t *element, int position, + struct og_procedure *proc) +{ + struct og_procedure_step *step; + uint32_t err = 0; + const char *key; + json_t *value; + + step = &proc->steps[proc->num_steps++]; + step->type = OG_STEP_PROCEDURE; + step->position = position; + + json_object_foreach(element, key, value) { + if (!strcmp(key, "procedure")) + err = og_json_parse_uint64(value, &step->procedure.id); + else + return -1; + } + + return err; +} + +int og_json_parse_procedure(json_t *element, struct og_procedure *proc) +{ + unsigned int i; + json_t *item; + int err = 0; + + if (json_typeof(element) != JSON_ARRAY) + return -1; + + for (i = 0; i < json_array_size(element) && i < OG_PROCEDURE_STEPS_MAX; ++i) { + item = json_array_get(element, i); + + if (json_object_get(item, "command")) + err = og_json_parse_procedure_cmd(item, i, proc); + else if (json_object_get(item, "procedure")) + err = og_json_parse_procedure_call(item, i, proc); + else + err = -1; + + if (err) + break; + } + + return err; +} @@ -98,4 +98,31 @@ struct og_cmd_json { uint32_t flags; }; +enum og_procedure_step_type { + OG_STEP_COMMAND = 0, + OG_STEP_PROCEDURE, +}; + +#define OG_PROCEDURE_STEPS_MAX 256 + +struct og_procedure_step { + enum og_procedure_step_type type; + uint32_t position; + + union { + struct og_cmd_json cmd; + struct { + uint64_t id; + } procedure; + }; +}; + +struct og_procedure { + uint64_t id; + struct og_procedure_step steps[OG_PROCEDURE_STEPS_MAX]; + uint32_t num_steps; +}; + +int og_json_parse_procedure(json_t *element, struct og_procedure *proc); + #endif @@ -4076,9 +4076,72 @@ static int og_cmd_post_center_delete(json_t *element, return 0; } +int og_procedure_add_steps(struct og_dbi *dbi, struct og_procedure *proc) +{ + struct og_procedure_step *step; + uint64_t procedure = 0; + const char *legacy_params; + const char *msglog; + dbi_result result; + int i; + + for (i = 0; i < proc->num_steps; i++) { + step = &proc->steps[i]; + switch (step->type) { + case OG_STEP_COMMAND: + legacy_params = og_msg_params_to_legacy(&step->cmd); + if (!legacy_params) { + og_dbi_close(dbi); + return -1; + } + result = dbi_conn_queryf(dbi->conn, + "INSERT INTO procedimientos_acciones " + "(idprocedimiento, orden, parametros) " + "VALUES (%d, %d, '%s')", + procedure, + step->position, + legacy_params); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, + "failed to add procedure command to database (%s:%d) %s\n", + __func__, __LINE__, msglog); + og_dbi_close(dbi); + free((char *)legacy_params); + return -1; + } + + dbi_result_free(result); + free((char *)legacy_params); + break; + case OG_STEP_PROCEDURE: + result = dbi_conn_queryf(dbi->conn, + "INSERT INTO procedimientos_acciones " + "(idprocedimiento, orden, procedimientoid) " + "VALUES (%d, %d, %d)", + procedure, + step->position, + step->procedure.id); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, + "failed to add procedure child to database (%s:%d) %s\n", + __func__, __LINE__, msglog); + og_dbi_close(dbi); + return -1; + } + dbi_result_free(result); + break; + } + } + + return 0; +} + static int og_cmd_post_procedure_add(json_t *element, struct og_msg_params *params) { + struct og_procedure proc = {}; const char *key, *msglog; struct og_dbi *dbi; dbi_result result; @@ -4092,8 +4155,11 @@ static int og_cmd_post_procedure_add(json_t *element, } else if (!strcmp(key, "name")) { err = og_json_parse_string(value, ¶ms->name); params->flags |= OG_REST_PARAM_NAME; - } else if (!strcmp(key, "description")) + } else if (!strcmp(key, "description")) { err = og_json_parse_string(value, ¶ms->comment); + } else if (!strcmp(key, "steps")) { + err = og_json_parse_procedure(value, &proc); + } if (err < 0) return err; @@ -4147,10 +4213,14 @@ static int og_cmd_post_procedure_add(json_t *element, og_dbi_close(dbi); return -1; } - dbi_result_free(result); + + proc.id = dbi_conn_sequence_last(dbi->conn, NULL); + err = og_procedure_add_steps(dbi, &proc); + og_dbi_close(dbi); - return 0; + + return err; } static int og_cmd_post_room_add(json_t *element, diff --git a/tests/units/test_0033_post_procedure_add.py b/tests/units/test_0033_post_procedure_add.py index b31ac70..89a21c7 100644 --- a/tests/units/test_0033_post_procedure_add.py +++ b/tests/units/test_0033_post_procedure_add.py @@ -8,7 +8,10 @@ class TestPostProcedureAddMethods(unittest.TestCase): self.headers = {'Authorization' : '07b3bfe728954619b58f0107ad73acc1'} self.full_json = { "center": "1", "name": "procedure1", - "description": "procedure test" } + "description": "procedure test", + "steps": [ { "command": "wol", + "params": { "type": "broadcast" } }, + { "procedure": 22 } ] } self.minimal_json = { "center": "1", "name": "procedure2" } self.duplicated_procedure_json = { "center": "1", |