Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions openapi/openapi-component_provisioner-v1.0.0.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,8 @@ components:
enum:
- success
- error
- deletion_success
- deletion_error
example: error
RestErrorMessage:
properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,11 @@ public class ProvisionResultsApiFacade {

private final ApplicationAuthenticationProvider applicationAuthenticationProvider;

@Value("${component-provisioner.support.create-incident-workflow-id:WORKFLOW}")
private String workflowId;
@Value("${component-provisioner.awx.workflows.create-incident-workflow-id}")
private String createIncidentWorkflowId;

@Value("${component-provisioner.awx.workflows.deletion-wrapper-workflow-id}")
private String deletionWrapperWorkflowId;

public ProvisionResultsApiFacade(AwxService awxService,
ComponentCatalogService componentCatalogService,
Expand All @@ -63,8 +66,10 @@ public AwxResponse requestDeletion(

log.debug("Processing deletion. ProjectKey: {}, componentId: {}", projectKey, componentId);

String deletionWorkflow = getDeletionWorkflow(projectKey, componentId);
validate(projectKey, componentId, deletionWorkflow, createIncidentAction);
String deletionWorkflowId = getDeletionWorkflowId(projectKey, componentId);
String deletionWorkflowName = getDeletionWorkflowName(projectKey, componentId);
String deletionWorkflowTimeoutSeconds = getDeletionWorkflowTimeoutSeconds(projectKey, componentId);
validate(projectKey, componentId, deletionWorkflowId, deletionWorkflowName, createIncidentAction);
addSystemParametersToAction(projectKey, createIncidentAction);

var accessToken = authenticationProvider.getAccessToken();
Expand All @@ -83,7 +88,12 @@ public AwxResponse requestDeletion(
var catalogItemId = provisionService.composeCatalogItemId(projectComponent);
setDeletingState(projectKey, componentId, catalogItemId);

AwxResponse awxResponse = triggerDeletion(projectKey, componentId, deletionWorkflow, createIncidentAction);
var triggerDeletionWrapperWorkflow = Strings.isNotBlank(deletionWorkflowId) || Strings.isNotBlank(deletionWorkflowName);
if (triggerDeletionWrapperWorkflow) {
addDeletionWrapperWorkflowParameters(catalogItemId, deletionWorkflowId, deletionWorkflowName, deletionWorkflowTimeoutSeconds, createIncidentAction);
}

AwxResponse awxResponse = triggerDeletion(projectKey, componentId, triggerDeletionWrapperWorkflow, createIncidentAction);

log.debug("AWX response: {}", awxResponse);
return awxResponse;
Expand All @@ -94,7 +104,7 @@ public boolean isInDeletingState(ProjectComponentExtendedInfo projectComponent)
return ProjectComponentStatus.DELETING.name().equals(projectComponent.getStatus());
}

public AwxResponse triggerAwxWorkflow(String projectKey, String componentId, CreateIncidentAction createIncidentAction) {
public AwxResponse triggerAwxIncidentWorkflow(String projectKey, String componentId, CreateIncidentAction createIncidentAction) {
var workflowJobLaunch = buildAwxWorkflowJobLaunch(projectKey, componentId, createIncidentAction);

var result = awxService.triggerWorkflowJob(ActionType.CREATE_INCIDENT.getValue(), workflowJobLaunch);
Expand All @@ -110,8 +120,8 @@ public AwxResponse triggerAwxWorkflow(String projectKey, String componentId, Cre
.build();
}

public AwxResponse triggerAwxDeletionWorkflow(String projectKey, String componentId, String deletionWorkflow, CreateIncidentAction createIncidentAction) {
var workflowJobLaunch = buildAwxDeletionWorkflowJobLaunch(projectKey, componentId, deletionWorkflow, createIncidentAction);
public AwxResponse triggerAwxDeletionWorkflow(String projectKey, String componentId, CreateIncidentAction createIncidentAction) {
var workflowJobLaunch = buildAwxDeletionWorkflowJobLaunch(projectKey, componentId, createIncidentAction);

var result = awxService.triggerWorkflowJob(ActionType.DELETE.getValue(), workflowJobLaunch);

Expand Down Expand Up @@ -177,11 +187,9 @@ private String resolveCatalogItemId(String accessToken,
}

public void deleteProvisioningStatus(String projectKey, String componentId) {

provisionService.deleteProvisioningStatus(projectKey, componentId);
}


public void validate(String projectKey, String status, String catalogItemId, String catalogItemSlug) {
validate(projectKey, status);

Expand All @@ -207,21 +215,21 @@ public void validate(String projectKey, String status) {
}
}

public void validate(String projectKey, String componentId, String deletionWorkflow, CreateIncidentAction createIncidentAction) {
public void validate(String projectKey, String componentId, String deletionWorkflowId, String deletionWorkflowName, CreateIncidentAction createIncidentAction) {
var isDeployed = getParameterString(createIncidentAction, "is_deployed");
var changeNumber = getParameterString(createIncidentAction, "change_number");
var reason = getParameterString(createIncidentAction, "reason");

var mainParamsAreEmpty = StringUtils.isBlank(projectKey) || StringUtils.isBlank(componentId);
var extraParamsAreEmtpy = StringUtils.isBlank(isDeployed)
var extraParamsAreEmpty = StringUtils.isBlank(isDeployed)
|| StringUtils.isBlank(changeNumber) || StringUtils.isBlank(reason);

if (mainParamsAreEmpty) {
throw new InvalidRestEntityException("project_key, component_id are required.");
}

if (StringUtils.isBlank(deletionWorkflow) && extraParamsAreEmtpy) {
throw new InvalidRestEntityException("Without deletion_workflow, params is_deployed, change_number and reason are required.");
if (StringUtils.isBlank(deletionWorkflowId) && StringUtils.isBlank(deletionWorkflowName) && extraParamsAreEmpty) {
throw new InvalidRestEntityException("The component has no deletion_workflow nor deletion_workflow_name configured, so params is_deployed, change_number and reason are required in the request.");
}
}

Expand Down Expand Up @@ -253,6 +261,49 @@ private void addSendOnDeletionParameters(String projectKey, String componentId,
.forEach(action::addParametersItem);
}

private void addDeletionWrapperWorkflowParameters(String catalogItemId,
String customDeletionWorkflowId,
String customDeletionWorkflowName,
String deletionWorkflowTimeoutSeconds,
CreateIncidentAction action) {
action.addParametersItem(CreateIncidentParameter.builder()
.name("access_token")
.value(authenticationProvider.getAccessToken())
.type(ParameterType.STRING.getValue())
.build()
);
action.addParametersItem(CreateIncidentParameter.builder()
.name("catalog_item_id")
.value(catalogItemId)
.type(ParameterType.STRING.getValue())
.build()
);
if (Strings.isNotBlank(customDeletionWorkflowId)) {
action.addParametersItem(CreateIncidentParameter.builder()
.name("deletion_workflow_id")
.value(customDeletionWorkflowId)
.type(ParameterType.STRING.getValue())
.build()
);
}
if (Strings.isNotBlank(customDeletionWorkflowName)) {
action.addParametersItem(CreateIncidentParameter.builder()
.name("deletion_workflow_name")
.value(customDeletionWorkflowName)
.type(ParameterType.STRING.getValue())
.build()
);
}
if (Strings.isNotBlank(deletionWorkflowTimeoutSeconds)) {
action.addParametersItem(CreateIncidentParameter.builder()
.name("deletion_workflow_timeout_seconds")
.value(deletionWorkflowTimeoutSeconds)
.type(ParameterType.STRING.getValue())
.build()
);
}
}

private void addCallerParameter(CreateIncidentAction action) {
var caller = authenticationProvider.getUserPrincipalName();
action.addParametersItem(CreateIncidentParameter.builder()
Expand All @@ -275,23 +326,30 @@ public String getParameterString(CreateIncidentAction createIncidentAction, Stri
.orElse(Strings.EMPTY);
}

public String getDeletionWorkflow(String projectKey, String componentId) {
return provisionService.getDeletionWorkflow(projectKey, componentId);
public String getDeletionWorkflowId(String projectKey, String componentId) {
return provisionService.getDeletionWorkflowId(projectKey, componentId);
}

public String getDeletionWorkflowName(String projectKey, String componentId) {
return provisionService.getDeletionWorkflowName(projectKey, componentId);
}

public String getDeletionWorkflowTimeoutSeconds(String projectKey, String componentId) {
return provisionService.getDeletionWorkflowTimeoutSeconds(projectKey, componentId);
}

private AwxWorkflowJobLaunch buildAwxWorkflowJobLaunch(String projectKey, String componentId, CreateIncidentAction createIncidentAction) {

addDefaultParameters(projectKey, componentId, workflowId, createIncidentAction);
addDefaultParameters(projectKey, componentId, createIncidentWorkflowId, createIncidentAction);

return entitiesMapper.asAwxWorkflowJobLaunch(createIncidentAction);
}

private AwxWorkflowJobLaunch buildAwxDeletionWorkflowJobLaunch(String projectKey,
String componentId,
String deletionWorkflow,
CreateIncidentAction createIncidentAction) {

addDefaultParameters(projectKey, componentId, deletionWorkflow, createIncidentAction);
addDefaultParameters(projectKey, componentId, deletionWrapperWorkflowId, createIncidentAction);
addSendOnDeletionParameters(projectKey, componentId, createIncidentAction);

return entitiesMapper.asAwxWorkflowJobLaunch(createIncidentAction);
Expand Down Expand Up @@ -339,20 +397,15 @@ private void setDeletingState(String projectKey, String componentId, String cata
private AwxResponse triggerDeletion(
String projectKey,
String componentId,
String deletionWorkflow,
boolean triggerWrapperDeletionWorkflow,
CreateIncidentAction action) {

if (StringUtils.isBlank(deletionWorkflow)) {
if (!triggerWrapperDeletionWorkflow) {
log.debug("Workflow not found for deletion. Creating incident via AWX");
return triggerAwxWorkflow(projectKey, componentId, action);
return triggerAwxIncidentWorkflow(projectKey, componentId, action);
}

log.debug("Workflow found for deletion. Triggering deletion workflow");
return triggerAwxDeletionWorkflow(
projectKey,
componentId,
deletionWorkflow,
action
);
log.debug("Workflow found for deletion. Triggering wrapper for custom deletion workflow");
return triggerAwxDeletionWorkflow(projectKey, componentId, action);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
@Slf4j
public class ProvisionService {

private static final String DELETION_WORKFLOW = "deletion_workflow";
private static final String DELETION_WORKFLOW_ID = "deletion_workflow";
private static final String DELETION_WORKFLOW_NAME = "deletion_workflow_name";
private static final String DELETION_WORKFLOW_TIMEOUT = "deletion_workflow_timeout_seconds";

private final ApiClientsBuilder apiClientsBuilder;
private final ComponentCatalogService componentCatalogService;
Expand Down Expand Up @@ -97,14 +99,40 @@ public List<CreateIncidentParameter> getDeletionParameters(String projectKey, St
return extractDeletionParameters(catalogItem, projectComponent, ActionType.PROVISION.getValue());
}

public String getDeletionWorkflow(String projectKey, String componentId) {
public String getDeletionWorkflowId(String projectKey, String componentId) {
var projectComponent = componentCatalogService.getProjectComponentById(authenticationProvider.getAccessToken(), projectKey, componentId);
var parameterMap = getProjectComponentParameterMap(projectComponent);

if (parameterMap.containsKey(DELETION_WORKFLOW)) {
var deletionWorkflow = parameterMap.get(DELETION_WORKFLOW);
assert deletionWorkflow.getValues() != null;
return deletionWorkflow.getValues().getFirst();
if (parameterMap.containsKey(DELETION_WORKFLOW_ID)) {
var deletionWorkflowId = parameterMap.get(DELETION_WORKFLOW_ID);
assert deletionWorkflowId.getValues() != null;
return deletionWorkflowId.getValues().getFirst();
}

return "";
}

public String getDeletionWorkflowName(String projectKey, String componentId) {
var projectComponent = componentCatalogService.getProjectComponentById(authenticationProvider.getAccessToken(), projectKey, componentId);
var parameterMap = getProjectComponentParameterMap(projectComponent);

if (parameterMap.containsKey(DELETION_WORKFLOW_NAME)) {
var deletionWorkflowName = parameterMap.get(DELETION_WORKFLOW_NAME);
assert deletionWorkflowName.getValues() != null;
return deletionWorkflowName.getValues().getFirst();
}

return "";
}

public String getDeletionWorkflowTimeoutSeconds(String projectKey, String componentId) {
var projectComponent = componentCatalogService.getProjectComponentById(authenticationProvider.getAccessToken(), projectKey, componentId);
var parameterMap = getProjectComponentParameterMap(projectComponent);

if (parameterMap.containsKey(DELETION_WORKFLOW_TIMEOUT)) {
var deletionWorkflowName = parameterMap.get(DELETION_WORKFLOW_TIMEOUT);
assert deletionWorkflowName.getValues() != null;
return deletionWorkflowName.getValues().getFirst();
}

return "";
Expand Down
1 change: 1 addition & 0 deletions src/main/resources/application-local.env.template
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ COMPONENT_CATALOG_PROVISIONER_PASSWORD=<place-your-password-here>
SENSITIVE_PARAMETERS_BLACKLIST=access_token,password,secret,token

CREATE_INCIDENT_WORKFLOW_ID=3361
DELETION_WRAPPER_WORKFLOW_ID=3823

PROJECTS_INFO_SERVICE_BASE_REST_URL="https://projects-info-service-devstack-dev.apps.example.com/v1"
CACHING_PROJECTS_INFO_SERVICE_CACHE_EVICTION_INTERVAL=5s
Expand Down
5 changes: 3 additions & 2 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ component-provisioner:
base-rest-url: ${AWX_SERVICE_BASE_REST_URL}
username: ${AWX_SERVICE_USERNAME}
password: ${AWX_SERVICE_PASSWORD}
workflows:
create-incident-workflow-id: ${CREATE_INCIDENT_WORKFLOW_ID}
deletion-wrapper-workflow-id: ${DELETION_WRAPPER_WORKFLOW_ID}
component-catalog:
service:
base-rest-url: ${COMPONENT_CATALOG_SERVICE_BASE_REST_URL}
Expand All @@ -83,8 +86,6 @@ component-provisioner:
client_secret: ${DEVSTACK_MARKETPLACE_API_CLIENT_SECRET}
scope: ${ODS_API_SERVICE_SERVICE_PARAMS_SCOPE}
override: ${ODS_API_SERVICE_SERVICE_PARAMS_OVERRIDE}
support:
create-incident-workflow-id: ${CREATE_INCIDENT_WORKFLOW_ID}
parameters:
blacklist: ${SENSITIVE_PARAMETERS_BLACKLIST}

Expand Down
Loading
Loading