diff --git a/conf/reflect-config.json b/conf/reflect-config.json index 15495642..428d0269 100644 --- a/conf/reflect-config.json +++ b/conf/reflect-config.json @@ -1154,6 +1154,12 @@ "queryAllDeclaredMethods":true, "methods":[{"name":"","parameterTypes":[] }] }, +{ + "name":"io.seqera.tower.cli.commands.datastudios.StopCmd", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, { "name":"io.seqera.tower.cli.commands.datastudios.ViewCmd", "allDeclaredFields":true, @@ -1853,6 +1859,12 @@ "queryAllDeclaredMethods":true, "queryAllDeclaredConstructors":true }, +{ + "name":"io.seqera.tower.cli.responses.datastudios.DataStudioStopSubmitted", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true +}, { "name":"io.seqera.tower.cli.responses.datastudios.DataStudiosList", "allDeclaredFields":true, @@ -2707,6 +2719,13 @@ "queryAllDeclaredConstructors":true, "methods":[{"name":"","parameterTypes":[] }, {"name":"getLastUpdate","parameterTypes":[] }, {"name":"getMessage","parameterTypes":[] }, {"name":"getStatus","parameterTypes":[] }, {"name":"setLastUpdate","parameterTypes":["java.time.OffsetDateTime"] }, {"name":"setMessage","parameterTypes":["java.lang.String"] }, {"name":"setStatus","parameterTypes":["io.seqera.tower.model.DataStudioStatus"] }] }, +{ + "name":"io.seqera.tower.model.DataStudioStopResponse", + "allDeclaredFields":true, + "queryAllDeclaredMethods":true, + "queryAllDeclaredConstructors":true, + "methods":[{"name":"","parameterTypes":[] }, {"name":"setJobSubmitted","parameterTypes":["java.lang.Boolean"] }, {"name":"setSessionId","parameterTypes":["java.lang.String"] }, {"name":"setStatusInfo","parameterTypes":["io.seqera.tower.model.DataStudioStatusInfo"] }] +}, { "name":"io.seqera.tower.model.DataStudioTemplate", "allDeclaredFields":true, diff --git a/src/main/java/io/seqera/tower/cli/commands/DataStudiosCmd.java b/src/main/java/io/seqera/tower/cli/commands/DataStudiosCmd.java index 675ea035..4b9a2844 100644 --- a/src/main/java/io/seqera/tower/cli/commands/DataStudiosCmd.java +++ b/src/main/java/io/seqera/tower/cli/commands/DataStudiosCmd.java @@ -19,6 +19,7 @@ import io.seqera.tower.cli.commands.datastudios.ListCmd; import io.seqera.tower.cli.commands.datastudios.StartCmd; +import io.seqera.tower.cli.commands.datastudios.StopCmd; import io.seqera.tower.cli.commands.datastudios.ViewCmd; import picocli.CommandLine; @@ -29,6 +30,7 @@ ViewCmd.class, ListCmd.class, StartCmd.class, + StopCmd.class, } ) public class DataStudiosCmd extends AbstractRootCmd { diff --git a/src/main/java/io/seqera/tower/cli/commands/datastudios/StopCmd.java b/src/main/java/io/seqera/tower/cli/commands/datastudios/StopCmd.java new file mode 100644 index 00000000..62d1b492 --- /dev/null +++ b/src/main/java/io/seqera/tower/cli/commands/datastudios/StopCmd.java @@ -0,0 +1,59 @@ +/* + * Copyright 2021-2023, Seqera. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package io.seqera.tower.cli.commands.datastudios; + +import io.seqera.tower.ApiException; +import io.seqera.tower.cli.commands.global.WorkspaceOptionalOptions; +import io.seqera.tower.cli.exceptions.DataStudioNotFoundException; +import io.seqera.tower.cli.exceptions.TowerException; +import io.seqera.tower.cli.responses.Response; +import io.seqera.tower.cli.responses.datastudios.DataStudioStopSubmitted; +import io.seqera.tower.model.DataStudioStopResponse; +import picocli.CommandLine; + +@CommandLine.Command( + name = "stop", + description = "Stop a data studio." +) +public class StopCmd extends AbstractStudiosCmd { + + @CommandLine.Mixin + public WorkspaceOptionalOptions workspace; + + @CommandLine.Mixin + public DataStudioRefOptions dataStudioRefOptions; + + @Override + protected Response exec() throws ApiException { + Long wspId = workspaceId(workspace.workspace); + + try { + DataStudioStopResponse response = api().stopDataStudio(dataStudioRefOptions.dataStudio.sessionId, wspId); + + return new DataStudioStopSubmitted(dataStudioRefOptions.dataStudio.sessionId, wspId, workspaceRef(wspId), response.getJobSubmitted()); + } catch (ApiException e) { + if (e.getCode() == 404) { + throw new DataStudioNotFoundException(dataStudioRefOptions.dataStudio.sessionId, wspId); + } + if (e.getCode() == 403) { + throw new TowerException(String.format("User not entitled to view studio '%s' at %s workspace", dataStudioRefOptions.dataStudio.sessionId, wspId)); + } + throw e; + } + } +} \ No newline at end of file diff --git a/src/main/java/io/seqera/tower/cli/responses/datastudios/DataStudioStopSubmitted.java b/src/main/java/io/seqera/tower/cli/responses/datastudios/DataStudioStopSubmitted.java new file mode 100644 index 00000000..b4ad0ef1 --- /dev/null +++ b/src/main/java/io/seqera/tower/cli/responses/datastudios/DataStudioStopSubmitted.java @@ -0,0 +1,43 @@ +/* + * Copyright 2021-2023, Seqera. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package io.seqera.tower.cli.responses.datastudios; + +import io.seqera.tower.cli.responses.Response; + +public class DataStudioStopSubmitted extends Response { + + public final String sessionId; + + public final Long workspaceId; + public final String workspaceRef; + public final Boolean jobSubmitted; + + public DataStudioStopSubmitted(String sessionId, Long workspaceId, String workspaceRef, Boolean jobSubmitted) { + this.sessionId = sessionId; + this.workspaceId = workspaceId; + this.workspaceRef = workspaceRef; + this.jobSubmitted = jobSubmitted; + } + + @Override + public String toString() { + String isSuccess = jobSubmitted ? "successfully submitted" : "failed to submit"; + return ansi(String.format("%n @|yellow Data Studio %s STOP %s at %s workspace.|@%n%n ", sessionId, isSuccess, workspaceRef)); + } + +} diff --git a/src/test/java/io/seqera/tower/cli/datastudios/DataStudiosCmdTest.java b/src/test/java/io/seqera/tower/cli/datastudios/DataStudiosCmdTest.java index d5d60257..157dc654 100644 --- a/src/test/java/io/seqera/tower/cli/datastudios/DataStudiosCmdTest.java +++ b/src/test/java/io/seqera/tower/cli/datastudios/DataStudiosCmdTest.java @@ -21,6 +21,7 @@ import io.seqera.tower.cli.BaseCmdTest; import io.seqera.tower.cli.commands.enums.OutputType; import io.seqera.tower.cli.responses.datastudios.DataStudioStartSubmitted; +import io.seqera.tower.cli.responses.datastudios.DataStudioStopSubmitted; import io.seqera.tower.cli.responses.datastudios.DataStudiosList; import io.seqera.tower.cli.responses.datastudios.DataStudiosView; import io.seqera.tower.cli.utils.PaginationInfo; @@ -681,4 +682,44 @@ void testStartWithWait(OutputType format, MockServerClient mock) { // verify the API has been polled additionally for the status mock.verify(request().withMethod("GET").withPath("/studios/3e8370e7"), VerificationTimes.exactly(4)); } + + + @ParameterizedTest + @EnumSource(OutputType.class) + void testStop(OutputType format, MockServerClient mock) { + + mock.when( + request().withMethod("GET").withPath("/user-info"), exactly(1) + ).respond( + response().withStatusCode(200).withBody(loadResource("user")).withContentType(MediaType.APPLICATION_JSON) + ); + + mock.when( + request().withMethod("GET").withPath("/user/1264/workspaces"), exactly(1) + ).respond( + response().withStatusCode(200).withBody(loadResource("workspaces/workspaces_list")).withContentType(MediaType.APPLICATION_JSON) + ); + + mock.when( + request().withMethod("PUT").withPath("/studios/3e8370e7/stop").withQueryStringParameter("workspaceId", "75887156211589"), exactly(1) + ).respond( + response().withStatusCode(200).withBody(json(""" + { + "jobSubmitted": true, + "sessionId": "3e8370e7", + "statusInfo": { + "status": "stopping", + "message": "", + "lastUpdate": "2025-01-22T15:16:11.508692Z" + } + } + """)).withContentType(MediaType.APPLICATION_JSON) + ); + + + ExecOut out = exec(format, mock, "studios", "stop", "-w", "75887156211589", "-i" ,"3e8370e7"); + + assertOutput(format, out, new DataStudioStopSubmitted("3e8370e7", 75887156211589L, "[organization1 / workspace1]", true)); + } + }