From a84a0762df3932ff6e8dc2f78d99982f6fa0f9a2 Mon Sep 17 00:00:00 2001 From: Alice1319 Date: Tue, 2 Apr 2024 20:37:11 +0800 Subject: [PATCH] introduce option to modify specifications of a service. --- .../TerraformBootFromDirectoryApi.java | 48 +++++++++++++ .../TerraformBootFromGitRepoApi.java | 42 +++++++++++ .../TerraformBootFromScriptsApi.java | 42 +++++++++++ ...yScenario.java => DeploymentScenario.java} | 24 ++++--- ...raformAsyncModifyFromDirectoryRequest.java | 24 +++++++ .../TerraformDeployFromDirectoryRequest.java | 10 ++- .../TerraformDestroyFromDirectoryRequest.java | 11 +-- .../TerraformModifyFromDirectoryRequest.java | 42 +++++++++++ ...erraformAsyncModifyFromGitRepoRequest.java | 24 +++++++ .../TerraformModifyFromGitRepoRequest.java | 27 ++++++++ ...erraformAsyncModifyFromScriptsRequest.java | 24 +++++++ .../TerraformModifyWithScriptsRequest.java | 28 ++++++++ .../boot/models/response/TerraformResult.java | 17 ++--- .../service/TerraformDirectoryService.java | 69 +++++++++++++++++-- .../service/TerraformGitRepoService.java | 47 ++++++++++++- .../service/TerraformScriptsService.java | 42 ++++++++++- 16 files changed, 487 insertions(+), 34 deletions(-) rename src/main/java/org/eclipse/xpanse/terraform/boot/models/enums/{DestroyScenario.java => DeploymentScenario.java} (51%) create mode 100644 src/main/java/org/eclipse/xpanse/terraform/boot/models/request/directory/TerraformAsyncModifyFromDirectoryRequest.java create mode 100644 src/main/java/org/eclipse/xpanse/terraform/boot/models/request/directory/TerraformModifyFromDirectoryRequest.java create mode 100644 src/main/java/org/eclipse/xpanse/terraform/boot/models/request/git/TerraformAsyncModifyFromGitRepoRequest.java create mode 100644 src/main/java/org/eclipse/xpanse/terraform/boot/models/request/git/TerraformModifyFromGitRepoRequest.java create mode 100644 src/main/java/org/eclipse/xpanse/terraform/boot/models/request/scripts/TerraformAsyncModifyFromScriptsRequest.java create mode 100644 src/main/java/org/eclipse/xpanse/terraform/boot/models/request/scripts/TerraformModifyWithScriptsRequest.java diff --git a/src/main/java/org/eclipse/xpanse/terraform/boot/api/controllers/TerraformBootFromDirectoryApi.java b/src/main/java/org/eclipse/xpanse/terraform/boot/api/controllers/TerraformBootFromDirectoryApi.java index deb5000..9fdd166 100644 --- a/src/main/java/org/eclipse/xpanse/terraform/boot/api/controllers/TerraformBootFromDirectoryApi.java +++ b/src/main/java/org/eclipse/xpanse/terraform/boot/api/controllers/TerraformBootFromDirectoryApi.java @@ -16,8 +16,10 @@ import org.eclipse.xpanse.terraform.boot.models.plan.TerraformPlanFromDirectoryRequest; import org.eclipse.xpanse.terraform.boot.models.request.directory.TerraformAsyncDeployFromDirectoryRequest; import org.eclipse.xpanse.terraform.boot.models.request.directory.TerraformAsyncDestroyFromDirectoryRequest; +import org.eclipse.xpanse.terraform.boot.models.request.directory.TerraformAsyncModifyFromDirectoryRequest; import org.eclipse.xpanse.terraform.boot.models.request.directory.TerraformDeployFromDirectoryRequest; import org.eclipse.xpanse.terraform.boot.models.request.directory.TerraformDestroyFromDirectoryRequest; +import org.eclipse.xpanse.terraform.boot.models.request.directory.TerraformModifyFromDirectoryRequest; import org.eclipse.xpanse.terraform.boot.models.response.TerraformResult; import org.eclipse.xpanse.terraform.boot.models.validation.TerraformValidationResult; import org.eclipse.xpanse.terraform.boot.terraform.service.TerraformDirectoryService; @@ -101,6 +103,30 @@ public TerraformResult deployFromDirectory( return terraformDirectoryService.deployFromDirectory(request, moduleDirectory); } + /** + * Method to modify resources requested in a workspace. + * + * @return Returns the status of the deployment. + */ + @Tag(name = "TerraformFromDirectory", description = + "APIs for running Terraform commands inside a provided directory.") + @Operation(description = "Modify resources via Terraform from the given directory.") + @PostMapping(value = "/modify/{module_directory}", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(HttpStatus.OK) + public TerraformResult modifyFromDirectory( + @Parameter(name = "module_directory", + description = "directory name where the Terraform module files exist.") + @PathVariable("module_directory") String moduleDirectory, + @Valid @RequestBody + TerraformModifyFromDirectoryRequest request, + @RequestHeader(name = "X-Custom-RequestId", required = false) UUID uuid) { + if (Objects.isNull(uuid)) { + uuid = UUID.randomUUID(); + } + MDC.put("TASK_ID", uuid.toString()); + return terraformDirectoryService.modifyFromDirectory(request, moduleDirectory); + } + /** * Method to destroy resources requested in a workspace. * @@ -173,6 +199,28 @@ public void asyncDeployFromDirectory( terraformDirectoryService.asyncDeployWithScripts(asyncDeployRequest, moduleDirectory); } + /** + * Method to async modify resources from the given directory. + */ + @Tag(name = "TerraformFromDirectory", description = + "APIs for running Terraform commands inside a provided directory.") + @Operation(description = "async modify resources via Terraform 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 Terraform module files exist.") + @PathVariable("module_directory") String moduleDirectory, + @Valid @RequestBody TerraformAsyncModifyFromDirectoryRequest asyncModifyRequest, + @RequestHeader(name = "X-Custom-RequestId", required = false) UUID uuid) { + if (Objects.isNull(uuid)) { + uuid = UUID.randomUUID(); + } + MDC.put("TASK_ID", uuid.toString()); + terraformDirectoryService.asyncModifyWithScripts(asyncModifyRequest, moduleDirectory); + } + /** * Method to async destroy resources from the given directory. */ diff --git a/src/main/java/org/eclipse/xpanse/terraform/boot/api/controllers/TerraformBootFromGitRepoApi.java b/src/main/java/org/eclipse/xpanse/terraform/boot/api/controllers/TerraformBootFromGitRepoApi.java index 10f18cb..423be58 100644 --- a/src/main/java/org/eclipse/xpanse/terraform/boot/api/controllers/TerraformBootFromGitRepoApi.java +++ b/src/main/java/org/eclipse/xpanse/terraform/boot/api/controllers/TerraformBootFromGitRepoApi.java @@ -15,8 +15,10 @@ import org.eclipse.xpanse.terraform.boot.models.plan.TerraformPlanFromGitRepoRequest; import org.eclipse.xpanse.terraform.boot.models.request.git.TerraformAsyncDeployFromGitRepoRequest; import org.eclipse.xpanse.terraform.boot.models.request.git.TerraformAsyncDestroyFromGitRepoRequest; +import org.eclipse.xpanse.terraform.boot.models.request.git.TerraformAsyncModifyFromGitRepoRequest; import org.eclipse.xpanse.terraform.boot.models.request.git.TerraformDeployFromGitRepoRequest; import org.eclipse.xpanse.terraform.boot.models.request.git.TerraformDestroyFromGitRepoRequest; +import org.eclipse.xpanse.terraform.boot.models.request.git.TerraformModifyFromGitRepoRequest; import org.eclipse.xpanse.terraform.boot.models.response.TerraformResult; import org.eclipse.xpanse.terraform.boot.models.validation.TerraformValidationResult; import org.eclipse.xpanse.terraform.boot.terraform.service.TerraformGitRepoService; @@ -110,6 +112,27 @@ public TerraformResult deployFromGitRepo( return terraformGitRepoService.deployFromGitRepo(request, uuid); } + /** + * Method to modify resources using scripts from the GIT Repo provided. + * + * @return Returns the status of the deployment. + */ + @Tag(name = "TerraformFromGitRepo", description = + "APIs for running Terraform commands using Terraform scripts from a GIT Repo.") + @Operation(description = "Modify resources via Terraform") + @PostMapping(value = "/modify", produces = + MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(HttpStatus.OK) + public TerraformResult modifyFromGitRepo( + @Valid @RequestBody TerraformModifyFromGitRepoRequest request, + @RequestHeader(name = "X-Custom-RequestId", required = false) UUID uuid) { + if (Objects.isNull(uuid)) { + uuid = UUID.randomUUID(); + } + MDC.put("TASK_ID", uuid.toString()); + return terraformGitRepoService.modifyFromGitRepo(request, uuid); + } + /** * MMethod to deploy resources using scripts from the GIT Repo provided. * @@ -150,6 +173,25 @@ public void asyncDeployFromGitRepo( terraformGitRepoService.asyncDeployFromGitRepo(asyncDeployRequest, uuid); } + /** + * Method to async modify resources from the provided GIT Repo. + */ + @Tag(name = "TerraformFromGitRepo", description = + "APIs for running Terraform commands using Terraform scripts from a GIT Repo.") + @Operation(description = "async deploy resources via Terraform") + @PostMapping(value = "/modify/async", produces = + MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(HttpStatus.ACCEPTED) + public void asyncModifyFromGitRepo( + @Valid @RequestBody TerraformAsyncModifyFromGitRepoRequest asyncModifyRequest, + @RequestHeader(name = "X-Custom-RequestId", required = false) UUID uuid) { + if (Objects.isNull(uuid)) { + uuid = UUID.randomUUID(); + } + MDC.put("TASK_ID", uuid.toString()); + terraformGitRepoService.asyncModifyFromGitRepo(asyncModifyRequest, uuid); + } + /** * Method to async destroy resources by scripts. */ diff --git a/src/main/java/org/eclipse/xpanse/terraform/boot/api/controllers/TerraformBootFromScriptsApi.java b/src/main/java/org/eclipse/xpanse/terraform/boot/api/controllers/TerraformBootFromScriptsApi.java index b4f155d..99c6917 100644 --- a/src/main/java/org/eclipse/xpanse/terraform/boot/api/controllers/TerraformBootFromScriptsApi.java +++ b/src/main/java/org/eclipse/xpanse/terraform/boot/api/controllers/TerraformBootFromScriptsApi.java @@ -15,8 +15,10 @@ import org.eclipse.xpanse.terraform.boot.models.plan.TerraformPlanWithScriptsRequest; import org.eclipse.xpanse.terraform.boot.models.request.scripts.TerraformAsyncDeployFromScriptsRequest; import org.eclipse.xpanse.terraform.boot.models.request.scripts.TerraformAsyncDestroyFromScriptsRequest; +import org.eclipse.xpanse.terraform.boot.models.request.scripts.TerraformAsyncModifyFromScriptsRequest; import org.eclipse.xpanse.terraform.boot.models.request.scripts.TerraformDeployWithScriptsRequest; import org.eclipse.xpanse.terraform.boot.models.request.scripts.TerraformDestroyWithScriptsRequest; +import org.eclipse.xpanse.terraform.boot.models.request.scripts.TerraformModifyWithScriptsRequest; import org.eclipse.xpanse.terraform.boot.models.response.TerraformResult; import org.eclipse.xpanse.terraform.boot.models.validation.TerraformValidationResult; import org.eclipse.xpanse.terraform.boot.terraform.service.TerraformScriptsService; @@ -89,6 +91,27 @@ public TerraformResult deployWithScripts( return terraformScriptsService.deployWithScripts(request, uuid); } + /** + * Method to modify resources by scripts. + * + * @return Returns the status of the deployment. + */ + @Tag(name = "TerraformFromScripts", description = + "APIs for running Terraform commands on the scripts sent via request body.") + @Operation(description = "Modify resources via Terraform") + @PostMapping(value = "/modify", produces = + MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(HttpStatus.OK) + public TerraformResult modifyWithScripts( + @Valid @RequestBody TerraformModifyWithScriptsRequest request, + @RequestHeader(name = "X-Custom-RequestId", required = false) UUID uuid) { + if (Objects.isNull(uuid)) { + uuid = UUID.randomUUID(); + } + MDC.put("TASK_ID", uuid.toString()); + return terraformScriptsService.modifyWithScripts(request, uuid); + } + /** * Method to destroy resources by scripts. * @@ -129,6 +152,25 @@ public void asyncDeployWithScripts( terraformScriptsService.asyncDeployWithScripts(asyncDeployRequest, uuid); } + /** + * Method to async modify resources by scripts. + */ + @Tag(name = "TerraformFromScripts", description = + "APIs for running Terraform commands on the scripts sent via request body.") + @Operation(description = "async modify resources via Terraform") + @PostMapping(value = "/modify/async", produces = + MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(HttpStatus.ACCEPTED) + public void asyncModifyWithScripts( + @Valid @RequestBody TerraformAsyncModifyFromScriptsRequest asyncModifyRequest, + @RequestHeader(name = "X-Custom-RequestId", required = false) UUID uuid) { + if (Objects.isNull(uuid)) { + uuid = UUID.randomUUID(); + } + MDC.put("TASK_ID", uuid.toString()); + terraformScriptsService.asyncModifyWithScripts(asyncModifyRequest, uuid); + } + /** * Method to async destroy resources by scripts. */ diff --git a/src/main/java/org/eclipse/xpanse/terraform/boot/models/enums/DestroyScenario.java b/src/main/java/org/eclipse/xpanse/terraform/boot/models/enums/DeploymentScenario.java similarity index 51% rename from src/main/java/org/eclipse/xpanse/terraform/boot/models/enums/DestroyScenario.java rename to src/main/java/org/eclipse/xpanse/terraform/boot/models/enums/DeploymentScenario.java index f6674c9..de4035e 100644 --- a/src/main/java/org/eclipse/xpanse/terraform/boot/models/enums/DestroyScenario.java +++ b/src/main/java/org/eclipse/xpanse/terraform/boot/models/enums/DeploymentScenario.java @@ -11,35 +11,37 @@ import org.eclipse.xpanse.terraform.boot.models.exceptions.UnsupportedEnumValueException; /** - * Destroy Scenario. The destroy scenario is used to set into TerraformResult and sent back to the - * client which sent the destroy request in what scenario. + * The deployment scenario is used to set into TerraformResult 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/terraform/boot/models/request/directory/TerraformAsyncModifyFromDirectoryRequest.java b/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/directory/TerraformAsyncModifyFromDirectoryRequest.java new file mode 100644 index 0000000..4ca218e --- /dev/null +++ b/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/directory/TerraformAsyncModifyFromDirectoryRequest.java @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * SPDX-FileCopyrightText: Huawei Inc. + */ + +package org.eclipse.xpanse.terraform.boot.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.terraform.boot.models.request.webhook.WebhookConfig; + +/** + * Data model for the terraform async modify requests. + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class TerraformAsyncModifyFromDirectoryRequest extends TerraformModifyFromDirectoryRequest { + + @NotNull + @Schema(description = "Configuration information of webhook.") + private WebhookConfig webhookConfig; +} diff --git a/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/directory/TerraformDeployFromDirectoryRequest.java b/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/directory/TerraformDeployFromDirectoryRequest.java index 9a4b6a6..d230af7 100644 --- a/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/directory/TerraformDeployFromDirectoryRequest.java +++ b/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/directory/TerraformDeployFromDirectoryRequest.java @@ -10,6 +10,7 @@ import java.util.HashMap; import java.util.Map; import lombok.Data; +import org.eclipse.xpanse.terraform.boot.models.enums.DeploymentScenario; /** * Data model for the terraform deploy requests. @@ -19,9 +20,16 @@ public class TerraformDeployFromDirectoryRequest { @NotNull @Schema(description = "Flag to control if the deployment must only generate the terraform " - + "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 terraform-boot. 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 " + "Terraform request.", diff --git a/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/directory/TerraformDestroyFromDirectoryRequest.java b/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/directory/TerraformDestroyFromDirectoryRequest.java index bcc14ab..15a2128 100644 --- a/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/directory/TerraformDestroyFromDirectoryRequest.java +++ b/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/directory/TerraformDestroyFromDirectoryRequest.java @@ -12,7 +12,7 @@ import java.util.HashMap; import java.util.Map; import lombok.Data; -import org.eclipse.xpanse.terraform.boot.models.enums.DestroyScenario; +import org.eclipse.xpanse.terraform.boot.models.enums.DeploymentScenario; /** * Data model for the terraform destroy requests. @@ -20,9 +20,12 @@ @Data public class TerraformDestroyFromDirectoryRequest { - @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 terraform-boot. 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/terraform/boot/models/request/directory/TerraformModifyFromDirectoryRequest.java b/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/directory/TerraformModifyFromDirectoryRequest.java new file mode 100644 index 0000000..e7ef9f4 --- /dev/null +++ b/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/directory/TerraformModifyFromDirectoryRequest.java @@ -0,0 +1,42 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * SPDX-FileCopyrightText: Huawei Inc. + */ + +package org.eclipse.xpanse.terraform.boot.models.request.directory; + +import static io.swagger.v3.oas.annotations.media.Schema.AdditionalPropertiesValue.TRUE; + +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.terraform.boot.models.enums.DeploymentScenario; + +/** + * Data model for the terraform modify requests. + */ +@Data +public class TerraformModifyFromDirectoryRequest { + @NotNull + @Schema(description = "Flag to control if the deployment must only generate the terraform " + + "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 terraform-boot. 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 " + + "Terraform request.", additionalProperties = TRUE) + Map variables; + + @Schema(description = "Key-value pairs of variables that must be injected as environment " + + "variables to terraform process.", additionalProperties = TRUE) + Map envVariables = new HashMap<>(); +} diff --git a/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/git/TerraformAsyncModifyFromGitRepoRequest.java b/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/git/TerraformAsyncModifyFromGitRepoRequest.java new file mode 100644 index 0000000..286dbc7 --- /dev/null +++ b/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/git/TerraformAsyncModifyFromGitRepoRequest.java @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * SPDX-FileCopyrightText: Huawei Inc. + */ + +package org.eclipse.xpanse.terraform.boot.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.terraform.boot.models.request.webhook.WebhookConfig; + +/** + * Data model for terraform async modify requests using scripts from a GIT Repo. + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class TerraformAsyncModifyFromGitRepoRequest extends TerraformModifyFromGitRepoRequest { + + @NotNull + @Schema(description = "Configuration information of webhook.") + private WebhookConfig webhookConfig; +} diff --git a/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/git/TerraformModifyFromGitRepoRequest.java b/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/git/TerraformModifyFromGitRepoRequest.java new file mode 100644 index 0000000..0e874be --- /dev/null +++ b/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/git/TerraformModifyFromGitRepoRequest.java @@ -0,0 +1,27 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * SPDX-FileCopyrightText: Huawei Inc. + */ + +package org.eclipse.xpanse.terraform.boot.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.terraform.boot.models.request.directory.TerraformModifyFromDirectoryRequest; + +/** + * Data model for terraform modify requests using scripts from a GIT Repo. + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class TerraformModifyFromGitRepoRequest extends TerraformModifyFromDirectoryRequest { + + @Schema(description = "GIT Repo details from where the scripts can be fetched.") + TerraformScriptGitRepoDetails gitRepoDetails; + + @NotNull + @Schema(description = "The .tfState file content after deployment") + private String tfState; +} diff --git a/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/scripts/TerraformAsyncModifyFromScriptsRequest.java b/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/scripts/TerraformAsyncModifyFromScriptsRequest.java new file mode 100644 index 0000000..f33e244 --- /dev/null +++ b/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/scripts/TerraformAsyncModifyFromScriptsRequest.java @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * SPDX-FileCopyrightText: Huawei Inc. + */ + +package org.eclipse.xpanse.terraform.boot.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.terraform.boot.models.request.webhook.WebhookConfig; + +/** + * Data model for the terraform async modify requests. + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class TerraformAsyncModifyFromScriptsRequest extends TerraformModifyWithScriptsRequest { + + @NotNull + @Schema(description = "Configuration information of webhook.") + private WebhookConfig webhookConfig; +} diff --git a/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/scripts/TerraformModifyWithScriptsRequest.java b/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/scripts/TerraformModifyWithScriptsRequest.java new file mode 100644 index 0000000..25a6371 --- /dev/null +++ b/src/main/java/org/eclipse/xpanse/terraform/boot/models/request/scripts/TerraformModifyWithScriptsRequest.java @@ -0,0 +1,28 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * SPDX-FileCopyrightText: Huawei Inc. + */ + +package org.eclipse.xpanse.terraform.boot.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.terraform.boot.models.request.directory.TerraformModifyFromDirectoryRequest; + +/** + * Terraform uses the request object modify by the script. + */ +@EqualsAndHashCode(callSuper = true) +@Data +public class TerraformModifyWithScriptsRequest extends TerraformModifyFromDirectoryRequest { + @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/terraform/boot/models/response/TerraformResult.java b/src/main/java/org/eclipse/xpanse/terraform/boot/models/response/TerraformResult.java index 5b8027c..278346e 100644 --- a/src/main/java/org/eclipse/xpanse/terraform/boot/models/response/TerraformResult.java +++ b/src/main/java/org/eclipse/xpanse/terraform/boot/models/response/TerraformResult.java @@ -10,7 +10,7 @@ import java.util.Map; import lombok.Builder; import lombok.Data; -import org.eclipse.xpanse.terraform.boot.models.enums.DestroyScenario; +import org.eclipse.xpanse.terraform.boot.models.enums.DeploymentScenario; /** * Data model for the Terraform command execution results. @@ -19,15 +19,12 @@ @Builder public class TerraformResult { - @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 terraform-boot. 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/terraform/boot/terraform/service/TerraformDirectoryService.java b/src/main/java/org/eclipse/xpanse/terraform/boot/terraform/service/TerraformDirectoryService.java index 70e411d..32cf2be 100644 --- a/src/main/java/org/eclipse/xpanse/terraform/boot/terraform/service/TerraformDirectoryService.java +++ b/src/main/java/org/eclipse/xpanse/terraform/boot/terraform/service/TerraformDirectoryService.java @@ -24,7 +24,7 @@ import lombok.extern.slf4j.Slf4j; import org.eclipse.xpanse.terraform.boot.async.TaskConfiguration; import org.eclipse.xpanse.terraform.boot.models.TerraformBootSystemStatus; -import org.eclipse.xpanse.terraform.boot.models.enums.DestroyScenario; +import org.eclipse.xpanse.terraform.boot.models.enums.DeploymentScenario; import org.eclipse.xpanse.terraform.boot.models.enums.HealthStatus; import org.eclipse.xpanse.terraform.boot.models.exceptions.TerraformExecutorException; import org.eclipse.xpanse.terraform.boot.models.exceptions.TerraformHealthCheckException; @@ -32,8 +32,10 @@ import org.eclipse.xpanse.terraform.boot.models.plan.TerraformPlanFromDirectoryRequest; import org.eclipse.xpanse.terraform.boot.models.request.directory.TerraformAsyncDeployFromDirectoryRequest; import org.eclipse.xpanse.terraform.boot.models.request.directory.TerraformAsyncDestroyFromDirectoryRequest; +import org.eclipse.xpanse.terraform.boot.models.request.directory.TerraformAsyncModifyFromDirectoryRequest; import org.eclipse.xpanse.terraform.boot.models.request.directory.TerraformDeployFromDirectoryRequest; import org.eclipse.xpanse.terraform.boot.models.request.directory.TerraformDestroyFromDirectoryRequest; +import org.eclipse.xpanse.terraform.boot.models.request.directory.TerraformModifyFromDirectoryRequest; import org.eclipse.xpanse.terraform.boot.models.response.TerraformResult; import org.eclipse.xpanse.terraform.boot.models.validation.TerraformValidationResult; import org.eclipse.xpanse.terraform.boot.terraform.TerraformExecutor; @@ -144,7 +146,38 @@ public TerraformResult deployFromDirectory(TerraformDeployFromDirectoryRequest r } String workspace = executor.getModuleFullPath(moduleDirectory); TerraformResult terraformResult = - transSystemCmdResultToTerraformResult(result, workspace, null); + transSystemCmdResultToTerraformResult(result, workspace, + request.getDeploymentScenario()); + if (cleanWorkspaceAfterDeployment) { + deleteWorkspace(workspace); + } + return terraformResult; + } + + /** + * Modify a source by terraform. + */ + public TerraformResult modifyFromDirectory(TerraformModifyFromDirectoryRequest 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 (TerraformExecutorException tfEx) { + log.error("Terraform deploy service failed. error:{}", tfEx.getMessage()); + result = new SystemCmdResult(); + result.setCommandSuccessful(false); + result.setCommandStdError(tfEx.getMessage()); + } + String workspace = executor.getModuleFullPath(moduleDirectory); + TerraformResult terraformResult = + transSystemCmdResultToTerraformResult(result, workspace, + request.getDeploymentScenario()); if (cleanWorkspaceAfterDeployment) { deleteWorkspace(workspace); } @@ -168,7 +201,7 @@ public TerraformResult destroyFromDirectory(TerraformDestroyFromDirectoryRequest } String workspace = executor.getModuleFullPath(moduleDirectory); TerraformResult terraformResult = transSystemCmdResultToTerraformResult(result, workspace, - request.getDestroyScenario()); + request.getDeploymentScenario()); deleteWorkspace(workspace); return terraformResult; } @@ -208,6 +241,29 @@ public void asyncDeployWithScripts(TerraformAsyncDeployFromDirectoryRequest asyn restTemplate.postForLocation(url, result); } + /** + * Async modify a source by terraform. + */ + @Async(TaskConfiguration.TASK_EXECUTOR_NAME) + public void asyncModifyWithScripts(TerraformAsyncModifyFromDirectoryRequest asyncModifyRequest, + String moduleDirectory) { + TerraformResult result; + try { + result = modifyFromDirectory(asyncModifyRequest, moduleDirectory); + } catch (RuntimeException e) { + result = TerraformResult.builder() + .commandStdOutput(null) + .commandStdError(e.getMessage()) + .isCommandSuccessful(false) + .terraformState(null) + .importantFileContentMap(new HashMap<>()) + .build(); + } + String url = asyncModifyRequest.getWebhookConfig().getUrl(); + log.info("Deployment service complete, callback POST url:{}, requestBody:{}", url, result); + restTemplate.postForLocation(url, result); + } + /** * Async destroy resource of the service. */ @@ -219,7 +275,7 @@ public void asyncDestroyWithScripts(TerraformAsyncDestroyFromDirectoryRequest re result = destroyFromDirectory(request, moduleDirectory); } catch (RuntimeException e) { result = TerraformResult.builder() - .destroyScenario(request.getDestroyScenario()) + .deploymentScenario(request.getDeploymentScenario()) .commandStdOutput(null) .commandStdError(e.getMessage()) .isCommandSuccessful(false) @@ -235,10 +291,11 @@ public void asyncDestroyWithScripts(TerraformAsyncDestroyFromDirectoryRequest re private TerraformResult transSystemCmdResultToTerraformResult(SystemCmdResult result, String workspace, - DestroyScenario destroyScenario) { + DeploymentScenario + deploymentScenario) { TerraformResult terraformResult = TerraformResult.builder().build(); BeanUtils.copyProperties(result, terraformResult); - terraformResult.setDestroyScenario(destroyScenario); + terraformResult.setDeploymentScenario(deploymentScenario); terraformResult.setTerraformState(getTerraformState(workspace)); terraformResult.setImportantFileContentMap(getImportantFilesContent(workspace)); return terraformResult; diff --git a/src/main/java/org/eclipse/xpanse/terraform/boot/terraform/service/TerraformGitRepoService.java b/src/main/java/org/eclipse/xpanse/terraform/boot/terraform/service/TerraformGitRepoService.java index b46a01c..bb1fe06 100644 --- a/src/main/java/org/eclipse/xpanse/terraform/boot/terraform/service/TerraformGitRepoService.java +++ b/src/main/java/org/eclipse/xpanse/terraform/boot/terraform/service/TerraformGitRepoService.java @@ -27,8 +27,10 @@ import org.eclipse.xpanse.terraform.boot.models.plan.TerraformPlanFromGitRepoRequest; import org.eclipse.xpanse.terraform.boot.models.request.git.TerraformAsyncDeployFromGitRepoRequest; import org.eclipse.xpanse.terraform.boot.models.request.git.TerraformAsyncDestroyFromGitRepoRequest; +import org.eclipse.xpanse.terraform.boot.models.request.git.TerraformAsyncModifyFromGitRepoRequest; import org.eclipse.xpanse.terraform.boot.models.request.git.TerraformDeployFromGitRepoRequest; import org.eclipse.xpanse.terraform.boot.models.request.git.TerraformDestroyFromGitRepoRequest; +import org.eclipse.xpanse.terraform.boot.models.request.git.TerraformModifyFromGitRepoRequest; import org.eclipse.xpanse.terraform.boot.models.request.git.TerraformScriptGitRepoDetails; import org.eclipse.xpanse.terraform.boot.models.response.TerraformResult; import org.eclipse.xpanse.terraform.boot.models.validation.TerraformValidationResult; @@ -92,6 +94,16 @@ public TerraformResult deployFromGitRepo(TerraformDeployFromGitRepoRequest reque getScriptsLocationInRepo(request.getGitRepoDetails(), uuid)); } + /** + * Method of modify a service using a script. + */ + public TerraformResult modifyFromGitRepo(TerraformModifyFromGitRepoRequest 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(TerraformAsyncDeployFromGitRepoRequest asyncD result = deployFromGitRepo(asyncDeployRequest, uuid); } catch (RuntimeException e) { result = TerraformResult.builder() + .deploymentScenario(asyncDeployRequest.getDeploymentScenario()) .commandStdOutput(null) .commandStdError(e.getMessage()) .isCommandSuccessful(false) @@ -126,6 +139,31 @@ public void asyncDeployFromGitRepo(TerraformAsyncDeployFromGitRepoRequest asyncD restTemplate.postForLocation(url, result); } + /** + * Async modify a source by terraform. + */ + @Async(TaskConfiguration.TASK_EXECUTOR_NAME) + public void asyncModifyFromGitRepo(TerraformAsyncModifyFromGitRepoRequest asyncModifyRequest, + UUID uuid) { + TerraformResult result; + try { + result = modifyFromGitRepo(asyncModifyRequest, uuid); + } catch (RuntimeException e) { + result = TerraformResult.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 +175,7 @@ public void asyncDestroyFromGitRepo(TerraformAsyncDestroyFromGitRepoRequest requ result = destroyFromGitRepo(request, uuid); } catch (RuntimeException e) { result = TerraformResult.builder() - .destroyScenario(request.getDestroyScenario()) + .deploymentScenario(request.getDeploymentScenario()) .commandStdOutput(null) .commandStdError(e.getMessage()) .isCommandSuccessful(false) @@ -158,6 +196,13 @@ private void buildDeployEnv(TerraformScriptGitRepoDetails terraformScriptGitRepo extractScripts(workspace, terraformScriptGitRepoDetails); } + private void buildModifyEnv(TerraformScriptGitRepoDetails terraformScriptGitRepoDetails, + String tfState, UUID uuid) { + buildDeployEnv(terraformScriptGitRepoDetails, uuid); + terraformScriptsHelper.createTfStateFile(tfState, + uuid + File.separator + terraformScriptGitRepoDetails.getScriptPath()); + } + private void buildDestroyEnv(TerraformScriptGitRepoDetails terraformScriptGitRepoDetails, String tfState, UUID uuid) { buildDeployEnv(terraformScriptGitRepoDetails, uuid); diff --git a/src/main/java/org/eclipse/xpanse/terraform/boot/terraform/service/TerraformScriptsService.java b/src/main/java/org/eclipse/xpanse/terraform/boot/terraform/service/TerraformScriptsService.java index 771d1e4..91d9d70 100644 --- a/src/main/java/org/eclipse/xpanse/terraform/boot/terraform/service/TerraformScriptsService.java +++ b/src/main/java/org/eclipse/xpanse/terraform/boot/terraform/service/TerraformScriptsService.java @@ -18,8 +18,10 @@ import org.eclipse.xpanse.terraform.boot.models.plan.TerraformPlanWithScriptsRequest; import org.eclipse.xpanse.terraform.boot.models.request.scripts.TerraformAsyncDeployFromScriptsRequest; import org.eclipse.xpanse.terraform.boot.models.request.scripts.TerraformAsyncDestroyFromScriptsRequest; +import org.eclipse.xpanse.terraform.boot.models.request.scripts.TerraformAsyncModifyFromScriptsRequest; import org.eclipse.xpanse.terraform.boot.models.request.scripts.TerraformDeployWithScriptsRequest; import org.eclipse.xpanse.terraform.boot.models.request.scripts.TerraformDestroyWithScriptsRequest; +import org.eclipse.xpanse.terraform.boot.models.request.scripts.TerraformModifyWithScriptsRequest; import org.eclipse.xpanse.terraform.boot.models.response.TerraformResult; import org.eclipse.xpanse.terraform.boot.models.validation.TerraformValidationResult; import org.eclipse.xpanse.terraform.boot.terraform.TerraformExecutor; @@ -74,6 +76,14 @@ public TerraformResult deployWithScripts(TerraformDeployWithScriptsRequest reque return deployFromDirectory(request, uuid.toString()); } + /** + * Method of modify a service using a script. + */ + public TerraformResult modifyWithScripts(TerraformModifyWithScriptsRequest request, UUID uuid) { + buildModifyEnv(request.getScripts(), request.getTfState(), uuid); + return modifyFromDirectory(request, uuid.toString()); + } + /** * Method of destroy a service using a script. */ @@ -103,6 +113,7 @@ public void asyncDeployWithScripts( result = deployWithScripts(asyncDeployRequest, uuid); } catch (RuntimeException e) { result = TerraformResult.builder() + .deploymentScenario(asyncDeployRequest.getDeploymentScenario()) .commandStdOutput(null) .commandStdError(e.getMessage()) .isCommandSuccessful(false) @@ -115,6 +126,30 @@ public void asyncDeployWithScripts( restTemplate.postForLocation(url, result); } + /** + * Async modify a source by terraform. + */ + @Async(TaskConfiguration.TASK_EXECUTOR_NAME) + public void asyncModifyWithScripts( + TerraformAsyncModifyFromScriptsRequest asyncModifyRequest, UUID uuid) { + TerraformResult result; + try { + result = modifyWithScripts(asyncModifyRequest, uuid); + } catch (RuntimeException e) { + result = TerraformResult.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. */ @@ -126,7 +161,7 @@ public void asyncDestroyWithScripts(TerraformAsyncDestroyFromScriptsRequest requ result = destroyWithScripts(request, uuid); } catch (RuntimeException e) { result = TerraformResult.builder() - .destroyScenario(request.getDestroyScenario()) + .deploymentScenario(request.getDeploymentScenario()) .commandStdOutput(null) .commandStdError(e.getMessage()) .isCommandSuccessful(false) @@ -146,6 +181,11 @@ private void buildDeployEnv(List scripts, UUID uuid) { buildScriptFiles(workspace, uuid, scripts); } + private void buildModifyEnv(List scripts, String tfState, UUID uuid) { + buildDeployEnv(scripts, uuid); + terraformScriptsHelper.createTfStateFile(tfState, uuid.toString()); + } + private void buildDestroyEnv(List scripts, String tfState, UUID uuid) { buildDeployEnv(scripts, uuid); terraformScriptsHelper.createTfStateFile(tfState, uuid.toString());