in src/utils/workflow_utils/src/workflow_utils.c [2661:2810]
ADUC_Result workflow_create_from_inline_step(ADUC_WorkflowHandle base, size_t stepIndex, ADUC_WorkflowHandle* handle)
{
ADUC_Result result = { ADUC_GeneralResult_Failure };
JSON_Status jsonStatus = JSONFailure;
JSON_Value* updateActionValue = NULL;
JSON_Value* updateManifestValue = NULL;
ADUC_Workflow* wf = NULL;
JSON_Array* steps = workflow_get_instructions_steps_array(base);
JSON_Value* stepValue = json_array_get_value(steps, stepIndex);
if (stepValue == NULL)
{
result.ExtendedResultCode = ADUC_ERC_UTILITIES_WORKFLOW_UTIL_INVALID_STEP_INDEX;
goto done;
}
*handle = NULL;
ADUC_Workflow* wfBase = workflow_from_handle(base);
wf = malloc(sizeof(*wf));
if (wf == NULL)
{
result.ExtendedResultCode = ADUC_ERC_NOMEM;
goto done;
}
memset(wf, 0, sizeof(*wf));
updateActionValue = json_value_deep_copy(json_object_get_wrapping_value(wfBase->UpdateActionObject));
if (updateActionValue == NULL)
{
Log_Error("Cannot copy Update Action json from base");
result.ExtendedResultCode = ADUC_ERC_UTILITIES_WORKFLOW_UTIL_COPY_UPDATE_ACTION_FROM_BASE_FAILURE;
goto done;
}
JSON_Object* updateActionObject = json_object(updateActionValue);
updateManifestValue = json_value_deep_copy(json_object_get_wrapping_value(wfBase->UpdateManifestObject));
if (updateManifestValue == NULL)
{
Log_Error("Cannot copy Update Manifest json from base");
result.ExtendedResultCode = ADUC_ERC_UTILITIES_WORKFLOW_UTIL_COPY_UPDATE_ACTION_FROM_BASE_FAILURE;
goto done;
}
JSON_Object* updateManifestObject = json_object(updateManifestValue);
JSON_Object* stepObject = json_object(stepValue);
char* currentStepData = json_serialize_to_string_pretty(stepValue);
Log_Debug("Processing current step:\n%s", currentStepData);
json_free_serialized_string(currentStepData);
// Replace 'updateType' with step's handler type.
const char* updateType = json_object_get_string(stepObject, STEP_PROPERTY_FIELD_HANDLER);
if (updateType == NULL || *updateType == 0)
{
Log_Error("Invalid step entry.");
result.ExtendedResultCode = ADUC_ERC_UTILITIES_WORKFLOW_UTIL_PARSE_STEP_ENTRY_NO_HANDLER_TYPE;
goto done;
}
jsonStatus = json_object_set_string(updateManifestObject, ADUCITF_FIELDNAME_UPDATETYPE, updateType);
if (jsonStatus == JSONFailure)
{
Log_Error("Cannot update step entry updateType.");
result.ExtendedResultCode = ADUC_ERC_UTILITIES_WORKFLOW_UTIL_COPY_UPDATE_ACTION_SET_UPDATE_TYPE_FAILURE;
goto done;
}
// Copy 'handlerProperties'.
JSON_Value* handlerProperties =
json_value_deep_copy(json_object_get_value(stepObject, STEP_PROPERTY_FIELD_HANDLER_PROPERTIES));
jsonStatus =
json_object_set_value(updateManifestObject, STEP_PROPERTY_FIELD_HANDLER_PROPERTIES, handlerProperties);
if (jsonStatus == JSONFailure)
{
json_value_free(handlerProperties);
handlerProperties = NULL;
Log_Error("Cannot copy 'handlerProperties'.");
result.ExtendedResultCode = ADUC_ERC_UTILITIES_WORKFLOW_UTIL_COPY_UPDATE_ACTION_COPY_HANDLER_PROPERTIES_FAILED;
goto done;
}
// Keep only file needed by this step entry. Remove the rest.
JSON_Array* stepFiles = json_object_get_array(stepObject, ADUCITF_FIELDNAME_FILES);
JSON_Object* baseFiles = json_object_get_object(updateManifestObject, ADUCITF_FIELDNAME_FILES);
size_t fileCount = json_object_get_count(baseFiles);
while (fileCount > 0)
{
fileCount--;
const char* baseFileId = json_object_get_name(baseFiles, fileCount);
// If file is in the instruction, merge their properties.
bool fileRequired = false;
size_t stepFilesCount = json_array_get_count(stepFiles);
while (stepFilesCount > 0)
{
stepFilesCount--;
// Note: step's files is an array of file ids.
const char* stepFileId = json_array_get_string(stepFiles, stepFilesCount);
if (baseFileId != NULL && stepFileId != NULL && strcmp(baseFileId, stepFileId) == 0)
{
// Found.
fileRequired = true;
// Done with this file, remove it (and free).
json_array_remove(stepFiles, stepFilesCount);
break;
}
}
// Remove file from base files list, if no longer needed.
if (!fileRequired)
{
json_object_remove(baseFiles, json_object_get_name(baseFiles, fileCount));
}
}
// Remove 'instructions' list...
json_object_set_null(updateManifestObject, "instructions");
wf->UpdateActionObject = updateActionObject;
wf->UpdateManifestObject = updateManifestObject;
{
char* baseWorkfolder = workflow_get_workfolder(base);
workflow_set_workfolder(wf, baseWorkfolder);
workflow_free_string(baseWorkfolder);
}
*handle = wf;
result.ResultCode = ADUC_GeneralResult_Success;
result.ExtendedResultCode = 0;
done:
if (IsAducResultCodeFailure(result.ResultCode))
{
json_value_free(updateActionValue);
json_value_free(updateManifestValue);
workflow_free(wf);
}
return result;
}