#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.
master
Javier Sánchez Parra 2021-06-04 12:46:15 +02:00 committed by OpenGnSys Support Team
parent 893101ffc6
commit 1fdb7e6d1c
4 changed files with 176 additions and 4 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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, &params->name);
params->flags |= OG_REST_PARAM_NAME;
} else if (!strcmp(key, "description"))
} else if (!strcmp(key, "description")) {
err = og_json_parse_string(value, &params->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,

View File

@ -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",