Skip to content

Commit f72ea6e

Browse files
committed
Add WorkflowCancel implementation (#472)
1 parent 36f6c29 commit f72ea6e

3 files changed

Lines changed: 284 additions & 0 deletions

File tree

src/main/java/zowe/client/sdk/zosmfworkflow/WorkflowConstants.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,5 +70,9 @@ private WorkflowConstants() {
7070
* Operations start path segment for workflow start operation.
7171
*/
7272
public static final String OPERATIONS_START = URL_PATH_DELIM + "operations" + URL_PATH_DELIM + "start";
73+
/**
74+
* Operations cancel path segment for workflow cancel operation.
75+
*/
76+
public static final String OPERATIONS_CANCEL = URL_PATH_DELIM + "operations" + URL_PATH_DELIM + "cancel";
7377

7478
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/*
2+
* This program and the accompanying materials are made available under the terms of the
3+
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
4+
* https://www.eclipse.org/legal/epl-v20.html
5+
*
6+
* SPDX-License-Identifier: EPL-2.0
7+
*
8+
* Copyright Contributors to the Zowe Project.
9+
*/
10+
package zowe.client.sdk.zosmfworkflow.methods;
11+
12+
import zowe.client.sdk.core.ZosConnection;
13+
import zowe.client.sdk.rest.*;
14+
import zowe.client.sdk.rest.exception.ZosmfRequestException;
15+
import zowe.client.sdk.rest.type.ZosmfRequestType;
16+
import zowe.client.sdk.utility.EncodeUtils;
17+
import zowe.client.sdk.utility.ValidateUtils;
18+
import zowe.client.sdk.zosmfworkflow.WorkflowConstants;
19+
20+
/**
21+
* Provides cancel workflow functionality through the z/OSMF workflow REST API.
22+
* <p>
23+
* <a href="https://www.ibm.com/docs/en/zos/3.2.0?topic=services-cancel-workflow">z/OSMF REST API</a>
24+
*
25+
* @author Jorge Samaniego
26+
* @version 7.0
27+
*/
28+
public class WorkflowCancel {
29+
30+
private final ZosConnection connection;
31+
private ZosmfRequest request;
32+
33+
/**
34+
* WorkflowCancel constructor.
35+
*
36+
* @param connection for connection information, see ZosConnection object
37+
*/
38+
public WorkflowCancel(final ZosConnection connection) {
39+
ValidateUtils.checkNullParameter(connection, "connection");
40+
this.connection = connection;
41+
}
42+
43+
/**
44+
* Alternative WorkflowCancel constructor with ZosmfRequest object.
45+
* This is mainly used for internal code unit testing with Mockito,
46+
* and it is not recommended to be used by the larger community.
47+
* <p>
48+
* This constructor is package-private.
49+
*
50+
* @param connection for connection information, see ZosConnection object
51+
* @param request compatible ZosmfRequest interface object
52+
*/
53+
WorkflowCancel(final ZosConnection connection, final ZosmfRequest request) {
54+
ValidateUtils.checkNullParameter(connection, "connection");
55+
ValidateUtils.checkNullParameter(request, "request");
56+
this.connection = connection;
57+
if (!(request instanceof PutJsonZosmfRequest)) {
58+
throw new IllegalStateException("PUT_JSON request type required");
59+
}
60+
this.request = request;
61+
}
62+
63+
/**
64+
* Cancel a z/OSMF workflow on a z/OS system.
65+
* <p>
66+
* Canceling a workflow does not undo any actions already performed.
67+
* A canceled workflow cannot be resumed.
68+
*
69+
* @param workflowKey workflow key identifying the workflow to cancel
70+
* @return http response object
71+
* @throws ZosmfRequestException request error state
72+
*/
73+
public Response cancel(final String workflowKey) throws ZosmfRequestException {
74+
ValidateUtils.checkIllegalParameter(workflowKey, "workflowKey");
75+
76+
final String url = connection.getZosmfUrl() +
77+
WorkflowConstants.WORKFLOWS_RESOURCE +
78+
UrlConstants.URL_PATH_DELIM +
79+
EncodeUtils.encodeURIComponent(workflowKey) +
80+
WorkflowConstants.OPERATIONS_CANCEL;
81+
82+
if (request == null) {
83+
request = ZosmfRequestFactory.buildRequest(connection, ZosmfRequestType.PUT_JSON);
84+
}
85+
request.setUrl(url);
86+
request.setBody("{}");
87+
88+
return request.executeRequest();
89+
}
90+
91+
}
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
/*
2+
* This program and the accompanying materials are made available under the terms of the
3+
* Eclipse Public License v2.0 which accompanies this distribution, and is available at
4+
* https://www.eclipse.org/legal/epl-v20.html
5+
*
6+
* SPDX-License-Identifier: EPL-2.0
7+
*
8+
* Copyright Contributors to the Zowe Project.
9+
*/
10+
package zowe.client.sdk.zosmfworkflow.methods;
11+
12+
import kong.unirest.core.Cookie;
13+
import org.json.simple.JSONObject;
14+
import org.junit.jupiter.api.Test;
15+
import org.mockito.Mockito;
16+
import zowe.client.sdk.core.ZosConnection;
17+
import zowe.client.sdk.core.ZosConnectionFactory;
18+
import zowe.client.sdk.rest.PutJsonZosmfRequest;
19+
import zowe.client.sdk.rest.Response;
20+
import zowe.client.sdk.rest.ZosmfRequest;
21+
import zowe.client.sdk.rest.exception.ZosmfRequestException;
22+
23+
import static org.junit.jupiter.api.Assertions.*;
24+
import static org.mockito.ArgumentMatchers.any;
25+
import static org.mockito.ArgumentMatchers.anyMap;
26+
import static org.mockito.Mockito.doCallRealMethod;
27+
import static org.mockito.Mockito.withSettings;
28+
29+
/**
30+
* Class containing unit tests for WorkflowCancel.
31+
*
32+
* @author Jorge Samaniego
33+
* @version 7.0
34+
*/
35+
public class WorkflowCancelTest {
36+
37+
private final ZosConnection connection = ZosConnectionFactory
38+
.createBasicConnection("1", 443, "1", "1");
39+
private final ZosConnection tokenConnection = ZosConnectionFactory
40+
.createTokenConnection("1", 443, new Cookie("hello=hello"));
41+
42+
@Test
43+
public void tstWorkflowCancelSecondaryConstructorWithValidRequestTypeSuccess() {
44+
ZosmfRequest request = Mockito.mock(PutJsonZosmfRequest.class);
45+
WorkflowCancel workflowCancel = new WorkflowCancel(connection, request);
46+
assertNotNull(workflowCancel);
47+
}
48+
49+
@Test
50+
public void tstWorkflowCancelSecondaryConstructorWithNullConnectionFailure() {
51+
ZosmfRequest request = Mockito.mock(PutJsonZosmfRequest.class);
52+
NullPointerException exception = assertThrows(
53+
NullPointerException.class,
54+
() -> new WorkflowCancel(null, request)
55+
);
56+
assertEquals("connection is null", exception.getMessage());
57+
}
58+
59+
@Test
60+
public void tstWorkflowCancelSecondaryConstructorWithNullRequestFailure() {
61+
NullPointerException exception = assertThrows(
62+
NullPointerException.class,
63+
() -> new WorkflowCancel(connection, null)
64+
);
65+
assertEquals("request is null", exception.getMessage());
66+
}
67+
68+
@Test
69+
public void tstWorkflowCancelSecondaryConstructorWithInvalidRequestTypeFailure() {
70+
ZosmfRequest request = Mockito.mock(ZosmfRequest.class);
71+
IllegalStateException exception = assertThrows(
72+
IllegalStateException.class,
73+
() -> new WorkflowCancel(connection, request)
74+
);
75+
assertEquals("PUT_JSON request type required", exception.getMessage());
76+
}
77+
78+
@Test
79+
public void tstWorkflowCancelPrimaryConstructorWithValidConnectionSuccess() {
80+
WorkflowCancel workflowCancel = new WorkflowCancel(connection);
81+
assertNotNull(workflowCancel);
82+
}
83+
84+
@Test
85+
public void tstWorkflowCancelPrimaryConstructorWithNullConnectionFailure() {
86+
NullPointerException exception = assertThrows(
87+
NullPointerException.class,
88+
() -> new WorkflowCancel(null)
89+
);
90+
assertEquals("connection is null", exception.getMessage());
91+
}
92+
93+
@Test
94+
public void tstWorkflowCancelSuccess() throws ZosmfRequestException {
95+
ZosConnection mockConnection = Mockito.mock(ZosConnection.class);
96+
Mockito.when(mockConnection.getZosmfUrl()).thenReturn("https://1:443");
97+
PutJsonZosmfRequest mockPutRequest = Mockito.mock(PutJsonZosmfRequest.class);
98+
Mockito.when(mockPutRequest.executeRequest()).thenReturn(new Response(new JSONObject(), 200, "success"));
99+
100+
doCallRealMethod().when(mockPutRequest).setUrl(any());
101+
doCallRealMethod().when(mockPutRequest).getUrl();
102+
103+
WorkflowCancel workflowCancel = new WorkflowCancel(mockConnection, mockPutRequest);
104+
Response response = workflowCancel.cancel("TESTKEY");
105+
106+
assertEquals("{}", response.getResponsePhrase().orElse("n\\a").toString());
107+
assertEquals(200, response.getStatusCode().orElse(-1));
108+
assertEquals("success", response.getStatusText().orElse("n\\a"));
109+
}
110+
111+
@Test
112+
public void tstWorkflowCancelWithNullWorkflowKeyFailure() {
113+
WorkflowCancel workflowCancel = new WorkflowCancel(connection);
114+
IllegalArgumentException exception = assertThrows(
115+
IllegalArgumentException.class,
116+
() -> workflowCancel.cancel(null)
117+
);
118+
assertEquals("workflowKey is either null or empty", exception.getMessage());
119+
}
120+
121+
@Test
122+
public void tstWorkflowCancelSecondaryConstructorObjectCreateSuccess() {
123+
PutJsonZosmfRequest request = Mockito.mock(PutJsonZosmfRequest.class);
124+
boolean noError = false;
125+
try {
126+
new WorkflowCancel(connection, request);
127+
} catch (IllegalStateException e) {
128+
noError = true;
129+
}
130+
assertFalse(noError);
131+
}
132+
133+
@Test
134+
public void tstWorkflowCancelUrlGenerationSuccess() throws ZosmfRequestException {
135+
ZosConnection mockConnection = Mockito.mock(ZosConnection.class);
136+
Mockito.when(mockConnection.getZosmfUrl()).thenReturn("https://1:443/zosmf");
137+
PutJsonZosmfRequest mockPutRequest = Mockito.mock(PutJsonZosmfRequest.class);
138+
Mockito.when(mockPutRequest.executeRequest()).thenReturn(new Response(new JSONObject(), 200, "success"));
139+
140+
doCallRealMethod().when(mockPutRequest).setUrl(any());
141+
doCallRealMethod().when(mockPutRequest).getUrl();
142+
143+
WorkflowCancel workflowCancel = new WorkflowCancel(mockConnection, mockPutRequest);
144+
workflowCancel.cancel("TESTKEY");
145+
146+
assertEquals(
147+
"https://1:443/zosmf/workflow/rest/1.0/workflows/TESTKEY/operations/cancel",
148+
mockPutRequest.getUrl()
149+
);
150+
}
151+
152+
@Test
153+
public void tstWorkflowCancelKeyEmptyFailure() {
154+
ZosConnection mockConnection = Mockito.mock(ZosConnection.class);
155+
Mockito.when(mockConnection.getZosmfUrl()).thenReturn("https://1:443/zosmf");
156+
PutJsonZosmfRequest mockPutRequest = Mockito.mock(PutJsonZosmfRequest.class);
157+
WorkflowCancel workflowCancel = new WorkflowCancel(mockConnection, mockPutRequest);
158+
IllegalArgumentException exception = assertThrows(
159+
IllegalArgumentException.class,
160+
() -> workflowCancel.cancel("")
161+
);
162+
assertEquals("workflowKey is either null or empty", exception.getMessage());
163+
}
164+
165+
@Test
166+
public void tstWorkflowCancelTokenSuccess() throws ZosmfRequestException {
167+
PutJsonZosmfRequest mockPutRequestToken = Mockito.mock(PutJsonZosmfRequest.class,
168+
withSettings().useConstructor(tokenConnection));
169+
Mockito.when(mockPutRequestToken.executeRequest()).thenReturn(
170+
new Response(new JSONObject(), 200, "success"));
171+
doCallRealMethod().when(mockPutRequestToken).setHeaders(anyMap());
172+
doCallRealMethod().when(mockPutRequestToken).setStandardHeaders();
173+
doCallRealMethod().when(mockPutRequestToken).setUrl(any());
174+
doCallRealMethod().when(mockPutRequestToken).getHeaders();
175+
doCallRealMethod().when(mockPutRequestToken).getUrl();
176+
177+
WorkflowCancel workflowCancel = new WorkflowCancel(tokenConnection, mockPutRequestToken);
178+
Response response = workflowCancel.cancel("test-key");
179+
180+
assertEquals("{X-CSRF-ZOSMF-HEADER=true, Content-Type=application/json}",
181+
mockPutRequestToken.getHeaders().toString());
182+
assertEquals("{}", response.getResponsePhrase().orElse("n\\a").toString());
183+
assertEquals(200, response.getStatusCode().orElse(-1));
184+
assertEquals("success", response.getStatusText().orElse("n\\a"));
185+
assertEquals("https://1:443/zosmf/workflow/rest/1.0/workflows/test-key/operations/cancel",
186+
mockPutRequestToken.getUrl());
187+
}
188+
189+
}

0 commit comments

Comments
 (0)