Skip to content

Commit aab7ff0

Browse files
committed
Extract hook task target app resolution into dedicated step
1 parent 9165d29 commit aab7ff0

3 files changed

Lines changed: 131 additions & 93 deletions

File tree

multiapps-controller-process/src/main/java/org/cloudfoundry/multiapps/controller/process/steps/ExecuteTaskStep.java

Lines changed: 2 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import java.text.MessageFormat;
44
import java.time.Duration;
55
import java.util.List;
6-
import java.util.Map;
76
import java.util.function.LongSupplier;
87

98
import jakarta.inject.Inject;
@@ -12,14 +11,10 @@
1211
import org.cloudfoundry.multiapps.controller.client.facade.domain.CloudTask;
1312
import org.cloudfoundry.multiapps.controller.client.lib.domain.CloudApplicationExtended;
1413
import org.cloudfoundry.multiapps.controller.core.cf.CloudControllerClientFactory;
15-
import org.cloudfoundry.multiapps.controller.core.model.ApplicationColor;
16-
import org.cloudfoundry.multiapps.controller.core.model.HookPhaseProcessType;
17-
import org.cloudfoundry.multiapps.controller.core.model.SupportedParameters;
1814
import org.cloudfoundry.multiapps.controller.core.security.token.TokenService;
1915
import org.cloudfoundry.multiapps.controller.process.Messages;
2016
import org.cloudfoundry.multiapps.controller.process.util.TimeoutType;
2117
import org.cloudfoundry.multiapps.controller.process.variables.Variables;
22-
import org.cloudfoundry.multiapps.mta.model.Hook;
2318
import org.springframework.beans.factory.config.BeanDefinition;
2419
import org.springframework.context.annotation.Scope;
2520

@@ -29,10 +24,6 @@ public class ExecuteTaskStep extends TimeoutAsyncFlowableStep {
2924

3025
protected LongSupplier currentTimeSupplier = System::currentTimeMillis;
3126

32-
private static final String PHASE_KEY = "phase";
33-
private static final String TARGET_APP_KEY = "target-app";
34-
private static final String APPLICATION_PHASE_SUBSTRING = ".application.";
35-
3627
@Inject
3728
private CloudControllerClientFactory clientFactory;
3829
@Inject
@@ -44,94 +35,13 @@ protected StepPhase executeAsyncStep(ProcessContext context) {
4435
CloudTask taskToExecute = StepsUtil.getTask(context);
4536
CloudControllerClient client = context.getControllerClient();
4637

47-
String appName = resolveTargetAppName(context, app);
48-
49-
getStepLogger().info(Messages.EXECUTING_TASK_ON_APP, taskToExecute.getName(), appName);
50-
CloudTask startedTask = client.runTask(appName, taskToExecute);
38+
getStepLogger().info(Messages.EXECUTING_TASK_ON_APP, taskToExecute.getName(), app.getName());
39+
CloudTask startedTask = client.runTask(app.getName(), taskToExecute);
5140
context.setVariable(Variables.STARTED_TASK, startedTask);
5241
context.setVariable(Variables.START_TIME, currentTimeSupplier.getAsLong());
5342
return StepPhase.POLL;
5443
}
5544

56-
private String resolveTargetAppName(ProcessContext context, CloudApplicationExtended app) {
57-
Hook hook = context.getVariable(Variables.HOOK_FOR_EXECUTION);
58-
if (hook == null) {
59-
return app.getName();
60-
}
61-
62-
List<Map<String, String>> phasesConfig = getPhasesConfig(hook);
63-
if (phasesConfig.isEmpty()) {
64-
return app.getName();
65-
}
66-
67-
String currentPhase = buildCurrentPhaseString(context, hook);
68-
String targetApp = phasesConfig.stream()
69-
.filter(config -> currentPhase.equals(config.get(PHASE_KEY)))
70-
.map(config -> config.get(TARGET_APP_KEY))
71-
.findFirst()
72-
.orElse(null);
73-
74-
if (targetApp == null) {
75-
return app.getName();
76-
}
77-
78-
return resolveAppNameForTarget(context, app, targetApp);
79-
}
80-
81-
@SuppressWarnings("unchecked")
82-
private List<Map<String, String>> getPhasesConfig(Hook hook) {
83-
Object phasesConfigValue = hook.getParameters()
84-
.get(SupportedParameters.PHASES_CONFIG);
85-
if (phasesConfigValue instanceof List) {
86-
return (List<Map<String, String>>) phasesConfigValue;
87-
}
88-
return List.of();
89-
}
90-
91-
private String buildCurrentPhaseString(ProcessContext context, Hook hook) {
92-
String hookExecutionPhase = context.getVariable(Variables.HOOK_EXECUTION_PHASE);
93-
return hook.getPhases()
94-
.stream()
95-
.filter(p -> p.equals(hookExecutionPhase))
96-
.findFirst()
97-
.orElseGet(() -> hook.getPhases()
98-
.stream()
99-
.filter(p -> p.contains(APPLICATION_PHASE_SUBSTRING))
100-
.findFirst()
101-
.orElse(""));
102-
}
103-
104-
private String resolveAppNameForTarget(ProcessContext context, CloudApplicationExtended app, String targetApp) {
105-
ApplicationColor idleColor = context.getVariable(Variables.IDLE_MTA_COLOR);
106-
ApplicationColor liveColor = context.getVariable(Variables.LIVE_MTA_COLOR);
107-
108-
if (idleColor == null || liveColor == null) {
109-
return app.getName();
110-
}
111-
112-
if (HookPhaseProcessType.HookProcessPhase.IDLE.getType()
113-
.equals(targetApp)) {
114-
return swapColorSuffix(app.getName(), liveColor, idleColor);
115-
}
116-
if (HookPhaseProcessType.HookProcessPhase.LIVE.getType()
117-
.equals(targetApp)) {
118-
return swapColorSuffix(app.getName(), idleColor, liveColor);
119-
}
120-
return app.getName();
121-
}
122-
123-
private String swapColorSuffix(String appName, ApplicationColor fromColor, ApplicationColor toColor) {
124-
String fromSuffix = fromColor.asSuffix();
125-
String toSuffix = toColor.asSuffix();
126-
if (appName.endsWith(fromSuffix)) {
127-
return appName.substring(0, appName.length() - fromSuffix.length()) + toSuffix;
128-
}
129-
if (!appName.endsWith(toSuffix)) {
130-
return appName + toSuffix;
131-
}
132-
return appName;
133-
}
134-
13545
@Override
13646
protected String getStepErrorMessage(ProcessContext context) {
13747
CloudApplicationExtended app = context.getVariable(Variables.APP_TO_PROCESS);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
package org.cloudfoundry.multiapps.controller.process.steps;
2+
3+
import java.text.MessageFormat;
4+
import java.util.List;
5+
import java.util.Map;
6+
7+
import jakarta.inject.Named;
8+
import org.cloudfoundry.multiapps.controller.client.lib.domain.CloudApplicationExtended;
9+
import org.cloudfoundry.multiapps.controller.core.model.ApplicationColor;
10+
import org.cloudfoundry.multiapps.controller.core.model.HookPhaseProcessType;
11+
import org.cloudfoundry.multiapps.controller.core.model.SupportedParameters;
12+
import org.cloudfoundry.multiapps.controller.process.Messages;
13+
import org.cloudfoundry.multiapps.controller.process.variables.Variables;
14+
import org.cloudfoundry.multiapps.mta.model.Hook;
15+
import org.springframework.beans.factory.config.BeanDefinition;
16+
import org.springframework.context.annotation.Scope;
17+
18+
@Named("resolveHookTaskTargetAppStep")
19+
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
20+
public class ResolveHookTaskTargetAppStep extends SyncFlowableStep {
21+
22+
private static final String PHASE_KEY = "phase";
23+
private static final String TARGET_APP_KEY = "target-app";
24+
private static final String APPLICATION_PHASE_SUBSTRING = ".application.";
25+
26+
@Override
27+
protected StepPhase executeStep(ProcessContext context) {
28+
CloudApplicationExtended app = context.getVariable(Variables.APP_TO_PROCESS);
29+
Hook hook = context.getVariable(Variables.HOOK_FOR_EXECUTION);
30+
31+
String resolvedAppName = resolveTargetAppName(context, app, hook);
32+
if (!resolvedAppName.equals(app.getName())) {
33+
context.setVariable(Variables.APP_TO_PROCESS, buildAppWithName(app, resolvedAppName));
34+
}
35+
36+
return StepPhase.DONE;
37+
}
38+
39+
private String resolveTargetAppName(ProcessContext context, CloudApplicationExtended app, Hook hook) {
40+
if (hook == null) {
41+
return app.getName();
42+
}
43+
44+
List<Map<String, String>> phasesConfig = getPhasesConfig(hook);
45+
if (phasesConfig.isEmpty()) {
46+
return app.getName();
47+
}
48+
49+
String currentPhase = buildCurrentPhaseString(context, hook);
50+
String targetApp = phasesConfig.stream()
51+
.filter(config -> currentPhase.equals(config.get(PHASE_KEY)))
52+
.map(config -> config.get(TARGET_APP_KEY))
53+
.findFirst()
54+
.orElse(null);
55+
56+
if (targetApp == null) {
57+
return app.getName();
58+
}
59+
60+
return resolveAppNameForTarget(context, app, targetApp);
61+
}
62+
63+
@SuppressWarnings("unchecked")
64+
private List<Map<String, String>> getPhasesConfig(Hook hook) {
65+
Object phasesConfigValue = hook.getParameters()
66+
.get(SupportedParameters.PHASES_CONFIG);
67+
if (phasesConfigValue instanceof List) {
68+
return (List<Map<String, String>>) phasesConfigValue;
69+
}
70+
return List.of();
71+
}
72+
73+
private String buildCurrentPhaseString(ProcessContext context, Hook hook) {
74+
String hookExecutionPhase = context.getVariable(Variables.HOOK_EXECUTION_PHASE);
75+
return hook.getPhases()
76+
.stream()
77+
.filter(p -> p.equals(hookExecutionPhase))
78+
.findFirst()
79+
.orElseGet(() -> hook.getPhases()
80+
.stream()
81+
.filter(p -> p.contains(APPLICATION_PHASE_SUBSTRING))
82+
.findFirst()
83+
.orElse(""));
84+
}
85+
86+
private String resolveAppNameForTarget(ProcessContext context, CloudApplicationExtended app, String targetApp) {
87+
ApplicationColor idleColor = context.getVariable(Variables.IDLE_MTA_COLOR);
88+
ApplicationColor liveColor = context.getVariable(Variables.LIVE_MTA_COLOR);
89+
90+
if (idleColor == null || liveColor == null) {
91+
return app.getName();
92+
}
93+
94+
if (HookPhaseProcessType.HookProcessPhase.IDLE.getType().equals(targetApp)) {
95+
return swapColorSuffix(app.getName(), liveColor, idleColor);
96+
}
97+
if (HookPhaseProcessType.HookProcessPhase.LIVE.getType().equals(targetApp)) {
98+
return swapColorSuffix(app.getName(), idleColor, liveColor);
99+
}
100+
return app.getName();
101+
}
102+
103+
private String swapColorSuffix(String appName, ApplicationColor fromColor, ApplicationColor toColor) {
104+
String fromSuffix = fromColor.asSuffix();
105+
String toSuffix = toColor.asSuffix();
106+
if (appName.endsWith(fromSuffix)) {
107+
return appName.substring(0, appName.length() - fromSuffix.length()) + toSuffix;
108+
}
109+
if (!appName.endsWith(toSuffix)) {
110+
return appName + toSuffix;
111+
}
112+
return appName;
113+
}
114+
115+
private CloudApplicationExtended buildAppWithName(CloudApplicationExtended app, String resolvedAppName) {
116+
return org.cloudfoundry.multiapps.controller.client.lib.domain.ImmutableCloudApplicationExtended.copyOf(app)
117+
.withName(resolvedAppName);
118+
}
119+
120+
@Override
121+
protected String getStepErrorMessage(ProcessContext context) {
122+
return MessageFormat.format(Messages.ERROR_EXECUTING_HOOK,
123+
context.getVariable(Variables.HOOK_FOR_EXECUTION).getName());
124+
}
125+
126+
}

multiapps-controller-process/src/main/resources/org/cloudfoundry/multiapps/controller/process/execute-hook-tasks.bpmn

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@
99
<startEvent id="startEvent1" flowable:formFieldValidation="true"></startEvent>
1010
<callActivity id="executeTasksCallActivity" name="Execute Tasks Call Activity" flowable:async="true" calledElement="executeTasksSubProcess" flowable:calledElementType="key" flowable:inheritVariables="true" flowable:fallbackToDefaultTenant="false"></callActivity>
1111
<serviceTask id="determineTasksFromHookTask" name="Determine Tasks From Hook Step" flowable:async="true" flowable:delegateExpression="${determineTasksFromHookStep}"></serviceTask>
12+
<serviceTask id="resolveHookTaskTargetAppTask" name="Resolve Hook Task Target App Step" flowable:async="true" flowable:delegateExpression="${resolveHookTaskTargetAppStep}"></serviceTask>
1213
<endEvent id="sid-5A2D8943-12FA-4BC2-B6D0-7878EA87FB75">
1314
<extensionElements>
1415
<flowable:executionListener event="end" delegateExpression="${hooksEndProcessListener}"></flowable:executionListener>
1516
</extensionElements>
1617
</endEvent>
1718
<sequenceFlow id="sid-5112772F-7C51-4FC3-BC2B-E4BEE435FC6D" sourceRef="startEvent1" targetRef="determineTasksFromHookTask"></sequenceFlow>
18-
<sequenceFlow id="sid-9A809249-058E-4637-83DC-547314F6144B" sourceRef="determineTasksFromHookTask" targetRef="executeTasksCallActivity"></sequenceFlow>
19+
<sequenceFlow id="sid-9A809249-058E-4637-83DC-547314F6144B" sourceRef="determineTasksFromHookTask" targetRef="resolveHookTaskTargetAppTask"></sequenceFlow>
20+
<sequenceFlow id="sid-B3C1D2E4-1234-5678-ABCD-EF0123456789" sourceRef="resolveHookTaskTargetAppTask" targetRef="executeTasksCallActivity"></sequenceFlow>
1921
<sequenceFlow id="sid-1E5806F9-54D9-4673-BAE3-91C4E13AF3B0" sourceRef="executeTasksCallActivity" targetRef="sid-5A2D8943-12FA-4BC2-B6D0-7878EA87FB75"></sequenceFlow>
2022
</process>
2123
<bpmndi:BPMNDiagram id="BPMNDiagram_executeHookTasksSubProcess">

0 commit comments

Comments
 (0)