#include #include #include #include "action.h" #include "block.h" #include "any_log.h" void action_perform(action_t *action, block_t *block, config_t *config) { block_t *target = block; bool warned = false; bool notify = false; for (size_t i = 0; i < action->length; i++) { const char *key = action->parts[i].key; const char *value = action->parts[i].value; switch (action->parts[i].type) { case ACTION_TARGET: { if (strncmp(value, "block.", 6)) log_panic("Invalid target %s", value); if (!strcmp(value + 6, "default")) { target = block; } else { for (size_t i = 0; i < config->n_blocks; i++) { if (!strcmp(value + 6, config->blocks[i]->label)) { target = config->blocks[i]; break; } } } if (notify && target->scheme->validate_change) { assert(target->scheme->validate_fn != NULL); int errors = target->scheme->validate_fn(target, config); if (config->action_failfast && errors) { log_debug("Aborted action '%s' for %d errors", action->label, errors); return; } } notify = false; warned = false; break; } case ACTION_SET_PAIR: { assert(target != NULL); if (!warned && target->scheme->change_fn == NULL) { log_warn("Block '%s' does not support 'set' actions", target->label); warned = true; continue; } // Skip "set-" in key bool success = block_change(target, config, key + 4, value); if (config->action_failfast && !success) { log_debug("Aborted action '%s'", action->label); return; } notify = true; break; } case ACTION_RUN_SCRIPT: { log_panic("TODO"); break; } default: unreachable(); } log_value_trace("Performed action step", "i:type", action->parts[i].type, "s:key", key, "s:value", value); } if (notify && target->scheme->validate_change) { assert(target->scheme->validate_fn != NULL); int errors = target->scheme->validate_fn(target, config); if (config->action_failfast && errors) { log_debug("Aborted action '%s' for %d errors", action->label, errors); return; } } log_debug("Performed action '%s'", action->label); } int action_validate(action_t *action, config_t *config) { // TODO return 0; } void action_free(action_t *action) { for (size_t i = 0; i < action->length; i++) { free(action->parts[i].key); free(action->parts[i].value); } free(action->parts); free(action->label); }