From d044aef3e08b82e1ce2b54d899e4e2e9b44fbb0e Mon Sep 17 00:00:00 2001 From: Alice1319 Date: Tue, 2 Apr 2024 20:30:30 +0800 Subject: [PATCH] introduce option to modify specifications of a service. --- .../OpenTofuMakerFromDirectoryApi.java | 48 +++++++++++++ .../OpenTofuMakerFromGitRepoApi.java | 42 +++++++++++ .../OpenTofuMakerFromScriptsApi.java | 43 +++++++++++ ...yScenario.java => DeploymentScenario.java} | 24 ++++--- ...enTofuAsyncModifyFromDirectoryRequest.java | 24 +++++++ .../OpenTofuDeployFromDirectoryRequest.java | 9 ++- .../OpenTofuDestroyFromDirectoryRequest.java | 10 +-- .../OpenTofuModifyFromDirectoryRequest.java | 42 +++++++++++ ...OpenTofuAsyncModifyFromGitRepoRequest.java | 25 +++++++ .../git/OpenTofuModifyFromGitRepoRequest.java | 27 +++++++ ...OpenTofuAsyncModifyFromScriptsRequest.java | 25 +++++++ .../OpenTofuModifyWithScriptsRequest.java | 29 ++++++++ .../maker/models/response/OpenTofuResult.java | 16 ++--- .../service/OpenTofuDirectoryService.java | 71 +++++++++++++++++-- .../service/OpenTofuGitRepoService.java | 46 +++++++++++- .../service/OpenTofuScriptsService.java | 44 +++++++++++- 16 files changed, 490 insertions(+), 35 deletions(-) rename src/main/java/org/eclipse/xpanse/tofu/maker/models/enums/{DestroyScenario.java => DeploymentScenario.java} (51%) create mode 100644 src/main/java/org/eclipse/xpanse/tofu/maker/models/request/directory/OpenTofuAsyncModifyFromDirectoryRequest.java create mode 100644 src/main/java/org/eclipse/xpanse/tofu/maker/models/request/directory/OpenTofuModifyFromDirectoryRequest.java create mode 100644 src/main/java/org/eclipse/xpanse/tofu/maker/models/request/git/OpenTofuAsyncModifyFromGitRepoRequest.java create mode 100644 src/main/java/org/eclipse/xpanse/tofu/maker/models/request/git/OpenTofuModifyFromGitRepoRequest.java create mode 100644 src/main/java/org/eclipse/xpanse/tofu/maker/models/request/scripts/OpenTofuAsyncModifyFromScriptsRequest.java create mode 100644 src/main/java/org/eclipse/xpanse/tofu/maker/models/request/scripts/OpenTofuModifyWithScriptsRequest.java diff --git a/src/main/java/org/eclipse/xpanse/tofu/maker/api/controllers/OpenTofuMakerFromDirectoryApi.java b/src/main/java/org/eclipse/xpanse/tofu/maker/api/controllers/OpenTofuMakerFromDirectoryApi.java index 60b14a9..8c77351 100644 --- a/src/main/java/org/eclipse/xpanse/tofu/maker/api/controllers/OpenTofuMakerFromDirectoryApi.java +++ b/src/main/java/org/eclipse/xpanse/tofu/maker/api/controllers/OpenTofuMakerFromDirectoryApi.java @@ -16,8 +16,10 @@ import org.eclipse.xpanse.tofu.maker.models.plan.OpenTofuPlanFromDirectoryRequest; import org.eclipse.xpanse.tofu.maker.models.request.directory.OpenTofuAsyncDeployFromDirectoryRequest; import org.eclipse.xpanse.tofu.maker.models.request.directory.OpenTofuAsyncDestroyFromDirectoryRequest; +import org.eclipse.xpanse.tofu.maker.models.request.directory.OpenTofuAsyncModifyFromDirectoryRequest; import org.eclipse.xpanse.tofu.maker.models.request.directory.OpenTofuDeployFromDirectoryRequest; import org.eclipse.xpanse.tofu.maker.models.request.directory.OpenTofuDestroyFromDirectoryRequest; +import org.eclipse.xpanse.tofu.maker.models.request.directory.OpenTofuModifyFromDirectoryRequest; import org.eclipse.xpanse.tofu.maker.models.response.OpenTofuResult; import org.eclipse.xpanse.tofu.maker.models.validation.OpenTofuValidationResult; import org.eclipse.xpanse.tofu.maker.opentofu.service.OpenTofuDirectoryService; @@ -101,6 +103,30 @@ public OpenTofuResult deployFromDirectory( return openTofuDirectoryService.deployFromDirectory(request, moduleDirectory); } + /** + * Method to modify resources requested in a workspace. + * + * @return Returns the status of the deployment. + */ + @Tag(name = "OpenTofuFromDirectory", description = + "APIs for running OpenTofu commands inside a provided directory.") + @Operation(description = "Modify resources via OpenTofu from the given directory.") + @PostMapping(value = "/modify/{module_directory}", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(HttpStatus.OK) + public OpenTofuResult modifyFromDirectory( + @Parameter(name = "module_directory", + description = "directory name where the OpenTofu module files exist.") + @PathVariable("module_directory") String moduleDirectory, + @Valid @RequestBody + OpenTofuModifyFromDirectoryRequest request, + @RequestHeader(name = "X-Custom-RequestId", required = false) UUID uuid) { + if (Objects.isNull(uuid)) { + uuid = UUID.randomUUID(); + } + MDC.put("TASK_ID", uuid.toString()); + return openTofuDirectoryService.modifyFromDirectory(request, moduleDirectory); + } + /** * Method to destroy resources requested in a workspace. * @@ -173,6 +199,28 @@ public void asyncDeployFromDirectory( openTofuDirectoryService.asyncDeployWithScripts(asyncDeployRequest, moduleDirectory); } + /** + * Method to async modify resources from the given directory. + */ + @Tag(name = "OpenTofuFromDirectory", description = + "APIs for running OpenTofu commands inside a provided directory.") + @Operation(description = "async modify resources via OpenTofu from the given directory.") + @PostMapping(value = "/modify/async/{module_directory}", produces = + MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(HttpStatus.ACCEPTED) + public void asyncModifyFromDirectory( + @Parameter(name = "module_directory", + description = "directory name where the OpenTofu module files exist.") + @PathVariable("module_directory") String moduleDirectory, + @Valid @RequestBody OpenTofuAsyncModifyFromDirectoryRequest asyncModifyRequest, + @RequestHeader(name = "X-Custom-RequestId", required = false) UUID uuid) { + if (Objects.isNull(uuid)) { + uuid = UUID.randomUUID(); + } + MDC.put("TASK_ID", uuid.toString()); + openTofuDirectoryService.asyncModifyWithScripts(asyncModifyRequest, moduleDirectory); + } + /** * Method to async destroy resources from the given directory. */ diff --git a/src/main/java/org/eclipse/xpanse/tofu/maker/api/controllers/OpenTofuMakerFromGitRepoApi.java b/src/main/java/org/eclipse/xpanse/tofu/maker/api/controllers/OpenTofuMakerFromGitRepoApi.java index 79ed34c..86d41b9 100644 --- a/src/main/java/org/eclipse/xpanse/tofu/maker/api/controllers/OpenTofuMakerFromGitRepoApi.java +++ b/src/main/java/org/eclipse/xpanse/tofu/maker/api/controllers/OpenTofuMakerFromGitRepoApi.java @@ -15,8 +15,10 @@ import org.eclipse.xpanse.tofu.maker.models.plan.OpenTofuPlanFromGitRepoRequest; import org.eclipse.xpanse.tofu.maker.models.request.git.OpenTofuAsyncDeployFromGitRepoRequest; import org.eclipse.xpanse.tofu.maker.models.request.git.OpenTofuAsyncDestroyFromGitRepoRequest; +import org.eclipse.xpanse.tofu.maker.models.request.git.OpenTofuAsyncModifyFromGitRepoRequest; import org.eclipse.xpanse.tofu.maker.models.request.git.OpenTofuDeployFromGitRepoRequest; import org.eclipse.xpanse.tofu.maker.models.request.git.OpenTofuDestroyFromGitRepoRequest; +import org.eclipse.xpanse.tofu.maker.models.request.git.OpenTofuModifyFromGitRepoRequest; import org.eclipse.xpanse.tofu.maker.models.response.OpenTofuResult; import org.eclipse.xpanse.tofu.maker.models.validation.OpenTofuValidationResult; import org.eclipse.xpanse.tofu.maker.opentofu.service.OpenTofuGitRepoService; @@ -110,6 +112,27 @@ public OpenTofuResult deployFromGitRepo( return openTofuGitRepoService.deployFromGitRepo(request, uuid); } + /** + * Method to modify resources using scripts from the GIT Repo provided. + * + * @return Returns the status of the deployment. + */ + @Tag(name = "OpenTofuFromGitRepo", description = + "APIs for running OpenTofu commands using OpenTofu scripts from a GIT Repo.") + @Operation(description = "Modify resources via OpenTofu") + @PostMapping(value = "/modify", produces = + MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(HttpStatus.OK) + public OpenTofuResult modifyFromGitRepo( + @Valid @RequestBody OpenTofuModifyFromGitRepoRequest request, + @RequestHeader(name = "X-Custom-RequestId", required = false) UUID uuid) { + if (Objects.isNull(uuid)) { + uuid = UUID.randomUUID(); + } + MDC.put("TASK_ID", uuid.toString()); + return openTofuGitRepoService.modifyFromGitRepo(request, uuid); + } + /** * MMethod to deploy resources using scripts from the GIT Repo provided. * @@ -150,6 +173,25 @@ public void asyncDeployFromGitRepo( openTofuGitRepoService.asyncDeployFromGitRepo(asyncDeployRequest, uuid); } + /** + * Method to async modify resources from the provided GIT Repo. + */ + @Tag(name = "OpenTofuFromGitRepo", description = + "APIs for running OpenTofu commands using OpenTofu scripts from a GIT Repo.") + @Operation(description = "async modify resources via OpenTofu") + @PostMapping(value = "/modify/async", produces = + MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(HttpStatus.ACCEPTED) + public void asyncModifyFromGitRepo( + @Valid @RequestBody OpenTofuAsyncModifyFromGitRepoRequest asyncModifyRequest, + @RequestHeader(name = "X-Custom-RequestId", required = false) UUID uuid) { + if (Objects.isNull(uuid)) { + uuid = UUID.randomUUID(); + } + MDC.put("TASK_ID", uuid.toString()); + openTofuGitRepoService.asyncModifyFromGitRepo(asyncModifyRequest, uuid); + } + /** * Method to async destroy resources by scripts. */ diff --git a/src/main/java/org/eclipse/xpanse/tofu/maker/api/controllers/OpenTofuMakerFromScriptsApi.java b/src/main/java/org/eclipse/xpanse/tofu/maker/api/controllers/OpenTofuMakerFromScriptsApi.java index 444ec5a..e68b2f6 100644 --- a/src/main/java/org/eclipse/xpanse/tofu/maker/api/controllers/OpenTofuMakerFromScriptsApi.java +++ b/src/main/java/org/eclipse/xpanse/tofu/maker/api/controllers/OpenTofuMakerFromScriptsApi.java @@ -15,8 +15,10 @@ import org.eclipse.xpanse.tofu.maker.models.plan.OpenTofuPlanWithScriptsRequest; import org.eclipse.xpanse.tofu.maker.models.request.scripts.OpenTofuAsyncDeployFromScriptsRequest; import org.eclipse.xpanse.tofu.maker.models.request.scripts.OpenTofuAsyncDestroyFromScriptsRequest; +import org.eclipse.xpanse.tofu.maker.models.request.scripts.OpenTofuAsyncModifyFromScriptsRequest; import org.eclipse.xpanse.tofu.maker.models.request.scripts.OpenTofuDeployWithScriptsRequest; import org.eclipse.xpanse.tofu.maker.models.request.scripts.OpenTofuDestroyWithScriptsRequest; +import org.eclipse.xpanse.tofu.maker.models.request.scripts.OpenTofuModifyWithScriptsRequest; import org.eclipse.xpanse.tofu.maker.models.response.OpenTofuResult; import org.eclipse.xpanse.tofu.maker.models.validation.OpenTofuValidationResult; import org.eclipse.xpanse.tofu.maker.opentofu.service.OpenTofuScriptsService; @@ -89,6 +91,28 @@ public OpenTofuResult deployWithScripts( return openTofuScriptsService.deployWithScripts(request, uuid); } + /** + * Method to modify resources by scripts. + * + * @return Returns the status of to Modify. + */ + @Tag(name = "OpenTofuFromScripts", description = + "APIs for running OpenTofu commands on the scripts sent via request body.") + @Operation(description = "Modify resources via OpenTofu") + @PostMapping(value = "/modify", produces = + MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(HttpStatus.OK) + public OpenTofuResult modifyWithScripts( + @Valid @RequestBody OpenTofuModifyWithScriptsRequest request, + @RequestHeader(name = "X-Custom-RequestId", required = false) UUID uuid) { + if (Objects.isNull(uuid)) { + uuid = UUID.randomUUID(); + } + MDC.put("TASK_ID", uuid.toString()); + return openTofuScriptsService.modifyWithScripts(request, uuid); + } + + /** * Method to destroy resources by scripts. * @@ -129,6 +153,25 @@ public void asyncDeployWithScripts( openTofuScriptsService.asyncDeployWithScripts(asyncDeployRequest, uuid); } + /** + * Method to async modify resources by scripts. + */ + @Tag(name = "OpenTofuFromScripts", description = + "APIs for running OpenTofu commands on the scripts sent via request body.") + @Operation(description = "async modify resources via OpenTofu") + @PostMapping(value = "/modify/async", produces = + MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(HttpStatus.ACCEPTED) + public void asyncModifyWithScripts( + @Valid @RequestBody OpenTofuAsyncModifyFromScriptsRequest asyncModifyRequest, + @RequestHeader(name = "X-Custom-RequestId", required = false) UUID uuid) { + if (Objects.isNull(uuid)) { + uuid = UUID.randomUUID(); + } + MDC.put("TASK_ID", uuid.toString()); + openTofuScriptsService.asyncModifyWithScripts(asyncModifyRequest, uuid); + } + /** * Method to async destroy resources by scripts. */ diff --git a/src/main/java/org/eclipse/xpanse/tofu/maker/models/enums/DestroyScenario.java b/src/main/java/org/eclipse/xpanse/tofu/maker/models/enums/DeploymentScenario.java similarity index 51% rename from src/main/java/org/eclipse/xpanse/tofu/maker/models/enums/DestroyScenario.java rename to src/main/java/org/eclipse/xpanse/tofu/maker/models/enums/DeploymentScenario.java index 7feb177..bae9f7f 100644 --- a/src/main/java/org/eclipse/xpanse/tofu/maker/models/enums/DestroyScenario.java +++ b/src/main/java/org/eclipse/xpanse/tofu/maker/models/enums/DeploymentScenario.java @@ -11,35 +11,37 @@ import org.eclipse.xpanse.tofu.maker.models.exceptions.UnsupportedEnumValueException; /** - * Destroy Scenario. The destroy scenario is used to set into OpenTofuResult and sent back to the - * client which sent the destroy request in what scenario. + * The deployment scenario is used to set into OpenTofuResult and sent back to the + * client which sent the deployment request in what scenario. */ -public enum DestroyScenario { +public enum DeploymentScenario { + DEPLOY("deploy"), + MODIFY("modify"), DESTROY("destroy"), ROLLBACK("rollback"), PURGE("purge"); private final String scenario; - DestroyScenario(String scenario) { + DeploymentScenario(String scenario) { this.scenario = scenario; } /** - * For DestroyScenario deserialize. + * For DeploymentScenario deserialize. */ @JsonCreator - public static DestroyScenario getByValue(String scenario) { - for (DestroyScenario destroyScenario : values()) { - if (StringUtils.equalsIgnoreCase(destroyScenario.scenario, scenario)) { - return destroyScenario; + public static DeploymentScenario getByValue(String scenario) { + for (DeploymentScenario deploymentScenario : values()) { + if (StringUtils.equalsIgnoreCase(deploymentScenario.scenario, scenario)) { + return deploymentScenario; } } throw new UnsupportedEnumValueException( - String.format("DestroyScenario value %s is not supported.", scenario)); + String.format("DeploymentScenario value %s is not supported.", scenario)); } /** - * For DestroyScenario serialize. + * For DeploymentScenario serialize. */ @JsonValue public String toValue() { diff --git a/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/directory/OpenTofuAsyncModifyFromDirectoryRequest.java b/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/directory/OpenTofuAsyncModifyFromDirectoryRequest.java new file mode 100644 index 0000000..c32e396 --- /dev/null +++ b/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/directory/OpenTofuAsyncModifyFromDirectoryRequest.java @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * SPDX-FileCopyrightText: Huawei Inc. + */ + +package org.eclipse.xpanse.tofu.maker.models.request.directory; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.eclipse.xpanse.tofu.maker.models.request.webhook.WebhookConfig; + +/** + * Data model for the OpenTofu async modify requests. + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class OpenTofuAsyncModifyFromDirectoryRequest extends OpenTofuModifyFromDirectoryRequest { + + @NotNull + @Schema(description = "Configuration information of webhook.") + private WebhookConfig webhookConfig; +} diff --git a/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/directory/OpenTofuDeployFromDirectoryRequest.java b/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/directory/OpenTofuDeployFromDirectoryRequest.java index 1596f99..b9efb4f 100644 --- a/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/directory/OpenTofuDeployFromDirectoryRequest.java +++ b/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/directory/OpenTofuDeployFromDirectoryRequest.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.Map; import lombok.Data; +import org.eclipse.xpanse.tofu.maker.models.enums.DeploymentScenario; /** * Data model for the OpenTofu deploy requests. @@ -19,9 +20,15 @@ public class OpenTofuDeployFromDirectoryRequest { @NotNull @Schema(description = "Flag to control if the deployment must only generate the OpenTofu " - + "or it must also apply the changes.") + + "or it must also apply the changes.") Boolean isPlanOnly; + @Schema(description = "This value can be set by the client if they wish to know the type of" + + "request for which the callback response is generated from tofu-maker. There will be" + + "no difference in the way request is executed. This information is only set in the" + + "callback response again for the client to handle the callback response accordingly.") + DeploymentScenario deploymentScenario; + @NotNull @Schema(description = "Key-value pairs of variables that must be used to execute the " + "OpenTofu request.", diff --git a/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/directory/OpenTofuDestroyFromDirectoryRequest.java b/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/directory/OpenTofuDestroyFromDirectoryRequest.java index 9aeec6b..e7c95ad 100644 --- a/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/directory/OpenTofuDestroyFromDirectoryRequest.java +++ b/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/directory/OpenTofuDestroyFromDirectoryRequest.java @@ -12,7 +12,7 @@ import java.util.HashMap; import java.util.Map; import lombok.Data; -import org.eclipse.xpanse.tofu.maker.models.enums.DestroyScenario; +import org.eclipse.xpanse.tofu.maker.models.enums.DeploymentScenario; /** * Data model for the OpenTofu destroy requests. @@ -20,9 +20,11 @@ @Data public class OpenTofuDestroyFromDirectoryRequest { - @Schema(description = "The destroy scenario when the Xpanse client send the destroy request. " - + "Valid values: destroy,rollback,purge.") - DestroyScenario destroyScenario; + @Schema(description = "This value can be set by the client if they wish to know the type of" + + "request for which the callback response is generated from tofu-maker. There will be" + + "no difference in the way request is executed. This information is only set in the" + + "callback response again for the client to handle the callback response accordingly.") + DeploymentScenario deploymentScenario; @NotNull @Schema(description = "Key-value pairs of regular variables that must be used to execute the " diff --git a/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/directory/OpenTofuModifyFromDirectoryRequest.java b/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/directory/OpenTofuModifyFromDirectoryRequest.java new file mode 100644 index 0000000..3d1fe3f --- /dev/null +++ b/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/directory/OpenTofuModifyFromDirectoryRequest.java @@ -0,0 +1,42 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * SPDX-FileCopyrightText: Huawei Inc. + */ + +package org.eclipse.xpanse.tofu.maker.models.request.directory; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import java.util.HashMap; +import java.util.Map; +import lombok.Data; +import org.eclipse.xpanse.tofu.maker.models.enums.DeploymentScenario; + +/** + * Data model for the OpenTofu modify requests. + */ +@Data +public class OpenTofuModifyFromDirectoryRequest { + + @NotNull + @Schema(description = "Flag to control if the deployment must only generate the OpenTofu " + + "or it must also apply the changes.") + Boolean isPlanOnly; + + @Schema(description = "This value can be set by the client if they wish to know the type of" + + "request for which the callback response is generated from tofu-maker. There will be" + + "no difference in the way request is executed. This information is only set in the" + + "callback response again for the client to handle the callback response accordingly.") + DeploymentScenario deploymentScenario; + + @NotNull + @Schema(description = "Key-value pairs of variables that must be used to execute the " + + "OpenTofu request.", + additionalProperties = Schema.AdditionalPropertiesValue.TRUE) + Map variables; + + @Schema(description = "Key-value pairs of variables that must be injected as environment " + + "variables to OpenTofu process.", + additionalProperties = Schema.AdditionalPropertiesValue.TRUE) + Map envVariables = new HashMap<>(); +} diff --git a/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/git/OpenTofuAsyncModifyFromGitRepoRequest.java b/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/git/OpenTofuAsyncModifyFromGitRepoRequest.java new file mode 100644 index 0000000..01246a1 --- /dev/null +++ b/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/git/OpenTofuAsyncModifyFromGitRepoRequest.java @@ -0,0 +1,25 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * SPDX-FileCopyrightText: Huawei Inc. + */ + +package org.eclipse.xpanse.tofu.maker.models.request.git; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.eclipse.xpanse.tofu.maker.models.request.webhook.WebhookConfig; + +/** + * Data model for open tofu async modify requests using scripts from a GIT Repo. + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class OpenTofuAsyncModifyFromGitRepoRequest extends OpenTofuModifyFromGitRepoRequest { + + @NotNull + @Schema(description = "Configuration information of webhook.") + private WebhookConfig webhookConfig; + +} diff --git a/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/git/OpenTofuModifyFromGitRepoRequest.java b/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/git/OpenTofuModifyFromGitRepoRequest.java new file mode 100644 index 0000000..2817e04 --- /dev/null +++ b/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/git/OpenTofuModifyFromGitRepoRequest.java @@ -0,0 +1,27 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * SPDX-FileCopyrightText: Huawei Inc. + */ + +package org.eclipse.xpanse.tofu.maker.models.request.git; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.eclipse.xpanse.tofu.maker.models.request.directory.OpenTofuModifyFromDirectoryRequest; + +/** + * Data model for open tofu modify requests using scripts from a GIT Repo. + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class OpenTofuModifyFromGitRepoRequest extends OpenTofuModifyFromDirectoryRequest { + + @Schema(description = "GIT Repo details from where the scripts can be fetched.") + OpenTofuScriptGitRepoDetails gitRepoDetails; + + @NotNull + @Schema(description = "The .tfState file content after deployment") + private String tfState; +} diff --git a/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/scripts/OpenTofuAsyncModifyFromScriptsRequest.java b/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/scripts/OpenTofuAsyncModifyFromScriptsRequest.java new file mode 100644 index 0000000..7baaa5c --- /dev/null +++ b/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/scripts/OpenTofuAsyncModifyFromScriptsRequest.java @@ -0,0 +1,25 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * SPDX-FileCopyrightText: Huawei Inc. + */ + +package org.eclipse.xpanse.tofu.maker.models.request.scripts; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.eclipse.xpanse.tofu.maker.models.request.webhook.WebhookConfig; + +/** + * Data model for the openTofu async modify requests. + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class OpenTofuAsyncModifyFromScriptsRequest extends OpenTofuModifyWithScriptsRequest { + + @NotNull + @Schema(description = "Configuration information of webhook.") + private WebhookConfig webhookConfig; + +} diff --git a/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/scripts/OpenTofuModifyWithScriptsRequest.java b/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/scripts/OpenTofuModifyWithScriptsRequest.java new file mode 100644 index 0000000..f7f49da --- /dev/null +++ b/src/main/java/org/eclipse/xpanse/tofu/maker/models/request/scripts/OpenTofuModifyWithScriptsRequest.java @@ -0,0 +1,29 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * SPDX-FileCopyrightText: Huawei Inc. + */ + +package org.eclipse.xpanse.tofu.maker.models.request.scripts; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import java.util.List; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.eclipse.xpanse.tofu.maker.models.request.directory.OpenTofuModifyFromDirectoryRequest; + +/** + * OpenTofu uses the request object modify by the script. + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class OpenTofuModifyWithScriptsRequest extends OpenTofuModifyFromDirectoryRequest { + + @NotNull + @Schema(description = "List of script files for modify requests deployed via scripts") + private List scripts; + + @NotNull + @Schema(description = "The .tfState file content after deployment") + private String tfState; +} diff --git a/src/main/java/org/eclipse/xpanse/tofu/maker/models/response/OpenTofuResult.java b/src/main/java/org/eclipse/xpanse/tofu/maker/models/response/OpenTofuResult.java index 9ddba05..1cfa00d 100644 --- a/src/main/java/org/eclipse/xpanse/tofu/maker/models/response/OpenTofuResult.java +++ b/src/main/java/org/eclipse/xpanse/tofu/maker/models/response/OpenTofuResult.java @@ -10,7 +10,7 @@ import java.util.Map; import lombok.Builder; import lombok.Data; -import org.eclipse.xpanse.tofu.maker.models.enums.DestroyScenario; +import org.eclipse.xpanse.tofu.maker.models.enums.DeploymentScenario; /** * Data model for the OpenTofu command execution results. @@ -19,15 +19,11 @@ @Builder public class OpenTofuResult { - @Schema(description = - "This value is set only if the same is set in the request as well. This is useful only" - + " for the caller to differentiate what type of destroy it is. No difference" - + " in the way destroy will be executed." - + "based on this flag. User may use this flag in case callback are used. " - + "So the calling application can know " - + "the result is for which specific destroy use case within the " - + "calling system.") - private DestroyScenario destroyScenario; + @Schema(description = "This value can be set by the client if they wish to know the type of" + + "request for which the callback response is generated from tofu-maker. There will be" + + "no difference in the way request is executed. This information is only set in the" + + "callback response again for the client to handle the callback response accordingly.") + private DeploymentScenario deploymentScenario; @Schema(description = "defines if the command was successfully executed") @NotNull private boolean isCommandSuccessful; diff --git a/src/main/java/org/eclipse/xpanse/tofu/maker/opentofu/service/OpenTofuDirectoryService.java b/src/main/java/org/eclipse/xpanse/tofu/maker/opentofu/service/OpenTofuDirectoryService.java index 3bfa7ed..3d6d5e6 100644 --- a/src/main/java/org/eclipse/xpanse/tofu/maker/opentofu/service/OpenTofuDirectoryService.java +++ b/src/main/java/org/eclipse/xpanse/tofu/maker/opentofu/service/OpenTofuDirectoryService.java @@ -24,7 +24,7 @@ import lombok.extern.slf4j.Slf4j; import org.eclipse.xpanse.tofu.maker.async.TaskConfiguration; import org.eclipse.xpanse.tofu.maker.models.OpenTofuMakerSystemStatus; -import org.eclipse.xpanse.tofu.maker.models.enums.DestroyScenario; +import org.eclipse.xpanse.tofu.maker.models.enums.DeploymentScenario; import org.eclipse.xpanse.tofu.maker.models.enums.HealthStatus; import org.eclipse.xpanse.tofu.maker.models.exceptions.OpenTofuExecutorException; import org.eclipse.xpanse.tofu.maker.models.exceptions.OpenTofuHealthCheckException; @@ -32,8 +32,10 @@ import org.eclipse.xpanse.tofu.maker.models.plan.OpenTofuPlanFromDirectoryRequest; import org.eclipse.xpanse.tofu.maker.models.request.directory.OpenTofuAsyncDeployFromDirectoryRequest; import org.eclipse.xpanse.tofu.maker.models.request.directory.OpenTofuAsyncDestroyFromDirectoryRequest; +import org.eclipse.xpanse.tofu.maker.models.request.directory.OpenTofuAsyncModifyFromDirectoryRequest; import org.eclipse.xpanse.tofu.maker.models.request.directory.OpenTofuDeployFromDirectoryRequest; import org.eclipse.xpanse.tofu.maker.models.request.directory.OpenTofuDestroyFromDirectoryRequest; +import org.eclipse.xpanse.tofu.maker.models.request.directory.OpenTofuModifyFromDirectoryRequest; import org.eclipse.xpanse.tofu.maker.models.response.OpenTofuResult; import org.eclipse.xpanse.tofu.maker.models.validation.OpenTofuValidationResult; import org.eclipse.xpanse.tofu.maker.opentofu.OpenTofuExecutor; @@ -144,7 +146,38 @@ public OpenTofuResult deployFromDirectory(OpenTofuDeployFromDirectoryRequest req } String workspace = executor.getModuleFullPath(moduleDirectory); OpenTofuResult openTofuResult = - transSystemCmdResultToOpenTofuResult(result, workspace, null); + transSystemCmdResultToOpenTofuResult(result, workspace, + request.getDeploymentScenario()); + if (cleanWorkspaceAfterDeployment) { + deleteWorkspace(workspace); + } + return openTofuResult; + } + + /** + * Modify a source by openTofu. + */ + public OpenTofuResult modifyFromDirectory(OpenTofuModifyFromDirectoryRequest request, + String moduleDirectory) { + SystemCmdResult result; + try { + if (Boolean.TRUE.equals(request.getIsPlanOnly())) { + result = executor.tfPlan(request.getVariables(), request.getEnvVariables(), + moduleDirectory); + } else { + result = executor.tfApply(request.getVariables(), request.getEnvVariables(), + moduleDirectory); + } + } catch (OpenTofuExecutorException tfEx) { + log.error("OpenTofu modify service failed. error:{}", tfEx.getMessage()); + result = new SystemCmdResult(); + result.setCommandSuccessful(false); + result.setCommandStdError(tfEx.getMessage()); + } + String workspace = executor.getModuleFullPath(moduleDirectory); + OpenTofuResult openTofuResult = + transSystemCmdResultToOpenTofuResult(result, workspace, + request.getDeploymentScenario()); if (cleanWorkspaceAfterDeployment) { deleteWorkspace(workspace); } @@ -168,7 +201,7 @@ public OpenTofuResult destroyFromDirectory(OpenTofuDestroyFromDirectoryRequest r } String workspace = executor.getModuleFullPath(moduleDirectory); OpenTofuResult openTofuResult = transSystemCmdResultToOpenTofuResult( - result, workspace, request.getDestroyScenario()); + result, workspace, request.getDeploymentScenario()); deleteWorkspace(workspace); return openTofuResult; } @@ -195,6 +228,7 @@ public void asyncDeployWithScripts( result = deployFromDirectory(asyncDeployRequest, moduleDirectory); } catch (RuntimeException e) { result = OpenTofuResult.builder() + .deploymentScenario(asyncDeployRequest.getDeploymentScenario()) .commandStdOutput(null) .commandStdError(e.getMessage()) .isCommandSuccessful(false) @@ -207,6 +241,30 @@ public void asyncDeployWithScripts( restTemplate.postForLocation(url, result); } + /** + * Async modify a source by openTofu. + */ + @Async(TaskConfiguration.TASK_EXECUTOR_NAME) + public void asyncModifyWithScripts( + OpenTofuAsyncModifyFromDirectoryRequest asyncModifyRequest, String moduleDirectory) { + OpenTofuResult result; + try { + result = modifyFromDirectory(asyncModifyRequest, moduleDirectory); + } catch (RuntimeException e) { + result = OpenTofuResult.builder() + .deploymentScenario(asyncModifyRequest.getDeploymentScenario()) + .commandStdOutput(null) + .commandStdError(e.getMessage()) + .isCommandSuccessful(false) + .terraformState(null) + .importantFileContentMap(new HashMap<>()) + .build(); + } + String url = asyncModifyRequest.getWebhookConfig().getUrl(); + log.info("Modify service complete, callback POST url:{}, requestBody:{}", url, result); + restTemplate.postForLocation(url, result); + } + /** * Async destroy resource of the service. */ @@ -218,7 +276,7 @@ public void asyncDestroyWithScripts(OpenTofuAsyncDestroyFromDirectoryRequest req result = destroyFromDirectory(request, moduleDirectory); } catch (RuntimeException e) { result = OpenTofuResult.builder() - .destroyScenario(request.getDestroyScenario()) + .deploymentScenario(request.getDeploymentScenario()) .commandStdOutput(null) .commandStdError(e.getMessage()) .isCommandSuccessful(false) @@ -234,10 +292,11 @@ public void asyncDestroyWithScripts(OpenTofuAsyncDestroyFromDirectoryRequest req private OpenTofuResult transSystemCmdResultToOpenTofuResult(SystemCmdResult result, String workspace, - DestroyScenario destroyScenario) { + DeploymentScenario + deploymentScenario) { OpenTofuResult openTofuResult = OpenTofuResult.builder().build(); BeanUtils.copyProperties(result, openTofuResult); - openTofuResult.setDestroyScenario(destroyScenario); + openTofuResult.setDeploymentScenario(deploymentScenario); openTofuResult.setTerraformState(getTerraformState(workspace)); openTofuResult.setImportantFileContentMap(getImportantFilesContent(workspace)); return openTofuResult; diff --git a/src/main/java/org/eclipse/xpanse/tofu/maker/opentofu/service/OpenTofuGitRepoService.java b/src/main/java/org/eclipse/xpanse/tofu/maker/opentofu/service/OpenTofuGitRepoService.java index 88b289f..ec08e6b 100644 --- a/src/main/java/org/eclipse/xpanse/tofu/maker/opentofu/service/OpenTofuGitRepoService.java +++ b/src/main/java/org/eclipse/xpanse/tofu/maker/opentofu/service/OpenTofuGitRepoService.java @@ -27,8 +27,10 @@ import org.eclipse.xpanse.tofu.maker.models.plan.OpenTofuPlanFromGitRepoRequest; import org.eclipse.xpanse.tofu.maker.models.request.git.OpenTofuAsyncDeployFromGitRepoRequest; import org.eclipse.xpanse.tofu.maker.models.request.git.OpenTofuAsyncDestroyFromGitRepoRequest; +import org.eclipse.xpanse.tofu.maker.models.request.git.OpenTofuAsyncModifyFromGitRepoRequest; import org.eclipse.xpanse.tofu.maker.models.request.git.OpenTofuDeployFromGitRepoRequest; import org.eclipse.xpanse.tofu.maker.models.request.git.OpenTofuDestroyFromGitRepoRequest; +import org.eclipse.xpanse.tofu.maker.models.request.git.OpenTofuModifyFromGitRepoRequest; import org.eclipse.xpanse.tofu.maker.models.request.git.OpenTofuScriptGitRepoDetails; import org.eclipse.xpanse.tofu.maker.models.response.OpenTofuResult; import org.eclipse.xpanse.tofu.maker.models.validation.OpenTofuValidationResult; @@ -92,6 +94,16 @@ public OpenTofuResult deployFromGitRepo(OpenTofuDeployFromGitRepoRequest request request.getGitRepoDetails(), uuid)); } + /** + * Method of modify a service using a script. + */ + public OpenTofuResult modifyFromGitRepo(OpenTofuModifyFromGitRepoRequest request, UUID uuid) { + uuid = getUuidToCreateEmptyWorkspace(uuid); + buildModifyEnv(request.getGitRepoDetails(), request.getTfState(), uuid); + return modifyFromDirectory(request, getScriptsLocationInRepo( + request.getGitRepoDetails(), uuid)); + } + /** * Method of destroy a service using a script. */ @@ -114,6 +126,7 @@ public void asyncDeployFromGitRepo( result = deployFromGitRepo(asyncDeployRequest, uuid); } catch (RuntimeException e) { result = OpenTofuResult.builder() + .deploymentScenario(asyncDeployRequest.getDeploymentScenario()) .commandStdOutput(null) .commandStdError(e.getMessage()) .isCommandSuccessful(false) @@ -126,6 +139,30 @@ public void asyncDeployFromGitRepo( restTemplate.postForLocation(url, result); } + /** + * Async modify a source by openTofu. + */ + @Async(TaskConfiguration.TASK_EXECUTOR_NAME) + public void asyncModifyFromGitRepo( + OpenTofuAsyncModifyFromGitRepoRequest asyncModifyRequest, UUID uuid) { + OpenTofuResult result; + try { + result = modifyFromGitRepo(asyncModifyRequest, uuid); + } catch (RuntimeException e) { + result = OpenTofuResult.builder() + .deploymentScenario(asyncModifyRequest.getDeploymentScenario()) + .commandStdOutput(null) + .commandStdError(e.getMessage()) + .isCommandSuccessful(false) + .terraformState(null) + .importantFileContentMap(new HashMap<>()) + .build(); + } + String url = asyncModifyRequest.getWebhookConfig().getUrl(); + log.info("Modify service complete, callback POST url:{}, requestBody:{}", url, result); + restTemplate.postForLocation(url, result); + } + /** * Async destroy resource of the service. */ @@ -137,7 +174,7 @@ public void asyncDestroyFromGitRepo(OpenTofuAsyncDestroyFromGitRepoRequest reque result = destroyFromGitRepo(request, uuid); } catch (RuntimeException e) { result = OpenTofuResult.builder() - .destroyScenario(request.getDestroyScenario()) + .deploymentScenario(request.getDeploymentScenario()) .commandStdOutput(null) .commandStdError(e.getMessage()) .isCommandSuccessful(false) @@ -158,6 +195,13 @@ private void buildDeployEnv(OpenTofuScriptGitRepoDetails openTofuScriptGitRepoDe extractScripts(workspace, openTofuScriptGitRepoDetails); } + private void buildModifyEnv(OpenTofuScriptGitRepoDetails openTofuScriptGitRepoDetails, + String tfState, UUID uuid) { + buildDeployEnv(openTofuScriptGitRepoDetails, uuid); + openTofuScriptsHelper.createTfStateFile(tfState, + uuid + File.separator + openTofuScriptGitRepoDetails.getScriptPath()); + } + private void buildDestroyEnv(OpenTofuScriptGitRepoDetails openTofuScriptGitRepoDetails, String tfState, UUID uuid) { buildDeployEnv(openTofuScriptGitRepoDetails, uuid); diff --git a/src/main/java/org/eclipse/xpanse/tofu/maker/opentofu/service/OpenTofuScriptsService.java b/src/main/java/org/eclipse/xpanse/tofu/maker/opentofu/service/OpenTofuScriptsService.java index 0d44637..acd1be4 100644 --- a/src/main/java/org/eclipse/xpanse/tofu/maker/opentofu/service/OpenTofuScriptsService.java +++ b/src/main/java/org/eclipse/xpanse/tofu/maker/opentofu/service/OpenTofuScriptsService.java @@ -18,8 +18,10 @@ import org.eclipse.xpanse.tofu.maker.models.plan.OpenTofuPlanWithScriptsRequest; import org.eclipse.xpanse.tofu.maker.models.request.scripts.OpenTofuAsyncDeployFromScriptsRequest; import org.eclipse.xpanse.tofu.maker.models.request.scripts.OpenTofuAsyncDestroyFromScriptsRequest; +import org.eclipse.xpanse.tofu.maker.models.request.scripts.OpenTofuAsyncModifyFromScriptsRequest; import org.eclipse.xpanse.tofu.maker.models.request.scripts.OpenTofuDeployWithScriptsRequest; import org.eclipse.xpanse.tofu.maker.models.request.scripts.OpenTofuDestroyWithScriptsRequest; +import org.eclipse.xpanse.tofu.maker.models.request.scripts.OpenTofuModifyWithScriptsRequest; import org.eclipse.xpanse.tofu.maker.models.response.OpenTofuResult; import org.eclipse.xpanse.tofu.maker.models.validation.OpenTofuValidationResult; import org.eclipse.xpanse.tofu.maker.opentofu.OpenTofuExecutor; @@ -72,6 +74,14 @@ public OpenTofuResult deployWithScripts(OpenTofuDeployWithScriptsRequest request return deployFromDirectory(request, uuid.toString()); } + /** + * Method of modify a service using a script. + */ + public OpenTofuResult modifyWithScripts(OpenTofuModifyWithScriptsRequest request, UUID uuid) { + buildModifyEnv(request.getScripts(), request.getTfState(), uuid); + return modifyFromDirectory(request, uuid.toString()); + } + /** * Method of destroy a service using a script. */ @@ -85,7 +95,7 @@ public OpenTofuResult destroyWithScripts(OpenTofuDestroyWithScriptsRequest reque * Method to get OpenTofu plan. */ public OpenTofuPlan getOpenTofuPlanFromScripts(OpenTofuPlanWithScriptsRequest request, - UUID uuid) { + UUID uuid) { buildDeployEnv(request.getScripts(), uuid); return getOpenTofuPlanFromDirectory(request, uuid.toString()); } @@ -101,6 +111,7 @@ public void asyncDeployWithScripts( result = deployWithScripts(asyncDeployRequest, uuid); } catch (RuntimeException e) { result = OpenTofuResult.builder() + .deploymentScenario(asyncDeployRequest.getDeploymentScenario()) .commandStdOutput(null) .commandStdError(e.getMessage()) .isCommandSuccessful(false) @@ -113,6 +124,30 @@ public void asyncDeployWithScripts( restTemplate.postForLocation(url, result); } + /** + * Async deploy a source by OpenTofu. + */ + @Async(TaskConfiguration.TASK_EXECUTOR_NAME) + public void asyncModifyWithScripts( + OpenTofuAsyncModifyFromScriptsRequest asyncModifyRequest, UUID uuid) { + OpenTofuResult result; + try { + result = modifyWithScripts(asyncModifyRequest, uuid); + } catch (RuntimeException e) { + result = OpenTofuResult.builder() + .deploymentScenario(asyncModifyRequest.getDeploymentScenario()) + .commandStdOutput(null) + .commandStdError(e.getMessage()) + .isCommandSuccessful(false) + .terraformState(null) + .importantFileContentMap(new HashMap<>()) + .build(); + } + String url = asyncModifyRequest.getWebhookConfig().getUrl(); + log.info("Modify service complete, callback POST url:{}, requestBody:{}", url, result); + restTemplate.postForLocation(url, result); + } + /** * Async destroy resource of the service. */ @@ -124,7 +159,7 @@ public void asyncDestroyWithScripts(OpenTofuAsyncDestroyFromScriptsRequest reque result = destroyWithScripts(request, uuid); } catch (RuntimeException e) { result = OpenTofuResult.builder() - .destroyScenario(request.getDestroyScenario()) + .deploymentScenario(request.getDeploymentScenario()) .commandStdOutput(null) .commandStdError(e.getMessage()) .isCommandSuccessful(false) @@ -144,6 +179,11 @@ private void buildDeployEnv(List scripts, UUID uuid) { buildScriptFiles(workspace, uuid, scripts); } + private void buildModifyEnv(List scripts, String tfState, UUID uuid) { + buildDeployEnv(scripts, uuid); + openTofuScriptsHelper.createTfStateFile(tfState, uuid.toString()); + } + private void buildDestroyEnv(List scripts, String tfState, UUID uuid) { buildDeployEnv(scripts, uuid); openTofuScriptsHelper.createTfStateFile(tfState, uuid.toString());