diff --git a/README.md b/README.md
index ac711ef3..31a2bce5 100644
--- a/README.md
+++ b/README.md
@@ -106,12 +106,12 @@ Use the spring boot's dev profile to use default values that are just for non-pr
#### From Command Line
-1.Start with oauth
+1. Start with oauth profile
```shell
./mvmw clean install -DskipTests
$ java -jar target/terra-boot-*.jar\
---spring.profiles.active=oauth \
+--spring.profiles.active=oauth,dev \
--authorization.token.type=${token-type} \
--authorization.server.endpoint=${server-endpoint} \
--authorization.api.client.id=${client-id} \
@@ -123,7 +123,7 @@ $ java -jar target/terra-boot-*.jar\
```shell
./mvmw clean install -DskipTests
-$ java -jar target/terra-boot-*.jar
+$ java -jar --spring.profiles.active=dev target/terra-boot-*.jar
```
#### From IDE
@@ -147,6 +147,39 @@ http://localhost:9090
http://localhost:9090/swagger-ui/index.html
```
+### AMQP support
+#### Start AMQP Broker
+
+Use RabbitMQ as the default provider for AMQP. Start the broker and create queues using the following command:
+
+```shell
+mkdir -p ~/docker/rabbitmq/data
+docker run -d \
+--user 1000:1000 \
+--name xpanse-rabbitmq \
+-p 5672:5672 \
+-p 15672:15672 \
+-v ~/docker/rabbitmq/data:/var/lib/rabbitmq \
+-e RABBITMQ_DEFAULT_USER=xpanse \
+-e RABBITMQ_DEFAULT_PASS=Xpanse@2023 \
+rabbitmq:4.0.7-management
+```
+Access the RabbitMQ management console at http://localhost:15672 with username `xpanse` and password `Xpanse@2023` after the container is started.
+
+#### Enable AMQP
+Start the application with the `amqp` profile.
+
+```shell
+./mvmw clean install -DskipTests
+$ java -jar --spring.profiles.active=dev,amqp target/terra-boot-*.jar
+```
+
+#### AsyncApi Docs and UI
+
+When the application started with the `amqp` profile, the AsyncApi docs and UI Console are enabled.
+The AsyncApi docs can be accessed at http://localhost:9090/queues/docs.
+The AsyncApi UI can be accessed at http://localhost:9090/queues/asyncapi-ui.html.
+
### Production
#### Docker Image
diff --git a/pom.xml b/pom.xml
index 8c355b71..76fdebfc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -35,6 +35,7 @@
3.5.2
3.5.0
2.44.2
+ 1.11.0
@@ -63,6 +64,32 @@
com.github.ben-manes.caffeine
caffeine
+
+
+ org.springframework.boot
+ spring-boot-starter-amqp
+
+
+
+ io.github.springwolf
+ springwolf-asyncapi
+ ${springwolf.version}
+
+
+ io.github.springwolf
+ springwolf-core
+ ${springwolf.version}
+
+
+ io.github.springwolf
+ springwolf-amqp
+ ${springwolf.version}
+
+
+ io.github.springwolf
+ springwolf-ui
+ ${springwolf.version}
+
org.projectlombok
lombok
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/api/config/JacksonConfig.java b/src/main/java/org/eclipse/xpanse/terra/boot/api/config/JacksonConfig.java
new file mode 100644
index 00000000..7d3f3465
--- /dev/null
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/api/config/JacksonConfig.java
@@ -0,0 +1,50 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * SPDX-FileCopyrightText: Huawei Inc.
+ */
+
+package org.eclipse.xpanse.terra.boot.api.config;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import org.eclipse.xpanse.terra.boot.models.request.TerraformRequest;
+import org.eclipse.xpanse.terra.boot.models.request.TerraformRequestDeserializer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+
+/** Configuration class for Jackson. */
+@Configuration
+public class JacksonConfig {
+
+ /**
+ * Create a ObjectMapper with the given module.
+ *
+ * @return objectMapper bean.
+ */
+ @Bean
+ @Primary
+ public ObjectMapper objectMapper() {
+ ObjectMapper mapper = new ObjectMapper();
+ SimpleModule terraformRequestModule = new SimpleModule();
+ terraformRequestModule.addDeserializer(
+ TerraformRequest.class, new TerraformRequestDeserializer());
+ mapper.registerModule(terraformRequestModule);
+ mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+ return mapper;
+ }
+
+ /**
+ * Define MappingJackson2HttpMessageConverter with the given objectMapper.
+ *
+ * @param objectMapper objectMapper
+ * @return mappingJackson2HttpMessageConverter bean
+ */
+ @Bean
+ public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(
+ ObjectMapper objectMapper) {
+ return new MappingJackson2HttpMessageConverter(objectMapper);
+ }
+}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootAdminApi.java b/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootAdminApi.java
index 41e70e92..0a820755 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootAdminApi.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootAdminApi.java
@@ -7,11 +7,13 @@
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletRequest;
+import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
-import org.eclipse.xpanse.terra.boot.models.TerraBootSystemStatus;
-import org.eclipse.xpanse.terra.boot.terraform.service.TerraformDirectoryService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
+import org.eclipse.xpanse.terra.boot.models.response.TerraBootSystemStatus;
+import org.eclipse.xpanse.terra.boot.terraform.service.TerraformRequestService;
+import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.CrossOrigin;
@@ -19,22 +21,18 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
/** REST controller for admin services of terra-boot. */
@Slf4j
@CrossOrigin
+@Profile("!amqp")
@RestController
@RequestMapping("/terra-boot")
public class TerraBootAdminApi {
- private final TerraformDirectoryService terraformDirectoryService;
-
- @Autowired
- public TerraBootAdminApi(
- @Qualifier("terraformDirectoryService")
- TerraformDirectoryService terraformDirectoryService) {
- this.terraformDirectoryService = terraformDirectoryService;
- }
+ @Resource private TerraformRequestService requestService;
/**
* Method to find out the current state of the system.
@@ -46,6 +44,12 @@ public TerraBootAdminApi(
@GetMapping(value = "/health", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public TerraBootSystemStatus healthCheck() {
- return terraformDirectoryService.tfHealthCheck();
+ TerraBootSystemStatus healthStatus = requestService.healthCheck(UUID.randomUUID());
+ HttpServletRequest request =
+ ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes())
+ .getRequest();
+ healthStatus.setServiceType(request.getScheme());
+ healthStatus.setServiceUrl(request.getRequestURL().toString());
+ return healthStatus;
}
}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootFromDirectoryApi.java b/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootFromDirectoryApi.java
index 4972e03e..1f6e3401 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootFromDirectoryApi.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootFromDirectoryApi.java
@@ -5,56 +5,37 @@
package org.eclipse.xpanse.terra.boot.api.controllers;
-import static org.eclipse.xpanse.terra.boot.logging.CustomRequestIdGenerator.REQUEST_ID;
-
import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.Pattern;
-import java.io.File;
-import java.util.List;
-import java.util.Objects;
-import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
-import org.eclipse.xpanse.terra.boot.models.plan.TerraformPlan;
-import org.eclipse.xpanse.terra.boot.models.plan.TerraformPlanFromDirectoryRequest;
-import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformAsyncDeployFromDirectoryRequest;
-import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformAsyncDestroyFromDirectoryRequest;
-import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformAsyncModifyFromDirectoryRequest;
-import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformDeployFromDirectoryRequest;
-import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformDestroyFromDirectoryRequest;
-import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformModifyFromDirectoryRequest;
+import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformAsyncRequestWithScriptsDirectory;
+import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformRequestWithScriptsDirectory;
+import org.eclipse.xpanse.terra.boot.models.response.TerraformPlan;
import org.eclipse.xpanse.terra.boot.models.response.TerraformResult;
-import org.eclipse.xpanse.terra.boot.models.validation.TerraformValidationResult;
-import org.eclipse.xpanse.terra.boot.terraform.service.TerraformDirectoryService;
-import org.eclipse.xpanse.terra.boot.terraform.service.TerraformScriptsHelper;
-import org.eclipse.xpanse.terra.boot.terraform.tool.TerraformVersionsHelper;
-import org.slf4j.MDC;
+import org.eclipse.xpanse.terra.boot.models.response.validation.TerraformValidationResult;
+import org.eclipse.xpanse.terra.boot.terraform.service.TerraformRequestService;
+import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;
/** REST controller for running terraform modules directly on the provided directory. */
@Slf4j
+@Profile("!amqp")
@CrossOrigin
@RestController
@RequestMapping("/terra-boot/directory")
public class TerraBootFromDirectoryApi {
- @Resource private TerraformDirectoryService directoryService;
- @Resource private TerraformScriptsHelper scriptsHelper;
+ @Resource private TerraformRequestService requestService;
/**
* Method to validate Terraform modules.
@@ -65,26 +46,26 @@ public class TerraBootFromDirectoryApi {
name = "TerraformFromDirectory",
description = "APIs for running Terraform commands inside a provided directory.")
@Operation(description = "Validate the Terraform modules in the given directory.")
- @GetMapping(
- value = "/validate/{module_directory}/{terraform_version}",
- produces = MediaType.APPLICATION_JSON_VALUE)
+ @PostMapping(value = "/validate", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public TerraformValidationResult validateFromDirectory(
- @Parameter(
- name = "module_directory",
- description = "directory name where the Terraform module files exist.")
- @PathVariable("module_directory")
- String moduleDirectory,
- @Parameter(
- name = "terraform_version",
- description = "version of Terraform to execute the module files.")
- @NotBlank
- @Pattern(regexp = TerraformVersionsHelper.TERRAFORM_REQUIRED_VERSION_REGEX)
- @PathVariable("terraform_version")
- String terraformVersion) {
- UUID uuid = UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- return directoryService.tfValidateFromDirectory(moduleDirectory, terraformVersion);
+ @Valid @RequestBody TerraformRequestWithScriptsDirectory request) {
+ return requestService.handleTerraformValidateRequest(request);
+ }
+
+ /**
+ * Method to get Terraform plan as a JSON string from a directory.
+ *
+ * @return Returns the terraform plan as a JSON string.
+ */
+ @Tag(
+ name = "TerraformFromDirectory",
+ description = "APIs for running Terraform commands inside a provided directory.")
+ @Operation(description = "Get Terraform Plan as JSON string from the given directory.")
+ @PostMapping(value = "/plan", produces = MediaType.APPLICATION_JSON_VALUE)
+ @ResponseStatus(HttpStatus.OK)
+ public TerraformPlan plan(@Valid @RequestBody TerraformRequestWithScriptsDirectory request) {
+ return requestService.handleTerraformPlanRequest(request);
}
/**
@@ -96,23 +77,11 @@ public TerraformValidationResult validateFromDirectory(
name = "TerraformFromDirectory",
description = "APIs for running Terraform commands inside a provided directory.")
@Operation(description = "Deploy resources via Terraform from the given directory.")
- @PostMapping(value = "/deploy/{module_directory}", produces = MediaType.APPLICATION_JSON_VALUE)
+ @PostMapping(value = "/deploy", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public TerraformResult deployFromDirectory(
- @Parameter(
- name = "module_directory",
- description = "directory name where the Terraform module files exist.")
- @PathVariable("module_directory")
- String moduleDirectory,
- @Valid @RequestBody TerraformDeployFromDirectoryRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- List scriptFiles = scriptsHelper.getDeploymentFilesFromTaskWorkspace(moduleDirectory);
- return directoryService.deployFromDirectory(request, moduleDirectory, scriptFiles);
+ @Valid @RequestBody TerraformRequestWithScriptsDirectory request) {
+ return requestService.handleTerraformDeploymentRequest(request);
}
/**
@@ -124,23 +93,11 @@ public TerraformResult deployFromDirectory(
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)
+ @PostMapping(value = "/modify", 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) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- List scriptFiles = scriptsHelper.getDeploymentFilesFromTaskWorkspace(moduleDirectory);
- return directoryService.modifyFromDirectory(request, moduleDirectory, scriptFiles);
+ @Valid @RequestBody TerraformRequestWithScriptsDirectory request) {
+ return requestService.handleTerraformDeploymentRequest(request);
}
/**
@@ -152,53 +109,11 @@ public TerraformResult modifyFromDirectory(
name = "TerraformFromDirectory",
description = "APIs for running Terraform commands inside a provided directory.")
@Operation(description = "Destroy the resources from the given directory.")
- @DeleteMapping(
- value = "/destroy/{module_directory}",
- produces = MediaType.APPLICATION_JSON_VALUE)
+ @DeleteMapping(value = "/destroy", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public TerraformResult destroyFromDirectory(
- @Parameter(
- name = "module_directory",
- description = "directory name where the Terraform module files exist.")
- @PathVariable("module_directory")
- String moduleDirectory,
- @Valid @RequestBody TerraformDestroyFromDirectoryRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- List scriptFiles = scriptsHelper.getDeploymentFilesFromTaskWorkspace(moduleDirectory);
- return directoryService.destroyFromDirectory(request, moduleDirectory, scriptFiles);
- }
-
- /**
- * Method to get Terraform plan as a JSON string from a directory.
- *
- * @return Returns the terraform plan as a JSON string.
- */
- @Tag(
- name = "TerraformFromDirectory",
- description = "APIs for running Terraform commands inside a provided directory.")
- @Operation(description = "Get Terraform Plan as JSON string from the given directory.")
- @PostMapping(value = "/plan/{module_directory}", produces = MediaType.APPLICATION_JSON_VALUE)
- @ResponseStatus(HttpStatus.OK)
- public TerraformPlan plan(
- @Parameter(
- name = "module_directory",
- description = "directory name where the Terraform module files exist.")
- @PathVariable("module_directory")
- String moduleDirectory,
- @Valid @RequestBody TerraformPlanFromDirectoryRequest request,
- @RequestHeader(name = "X-Custom-RequestId", required = false) UUID uuid) {
- uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : (Objects.nonNull(uuid) ? uuid : UUID.randomUUID());
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- return directoryService.getTerraformPlanFromDirectory(request, moduleDirectory);
+ @Valid @RequestBody TerraformRequestWithScriptsDirectory request) {
+ return requestService.handleTerraformDeploymentRequest(request);
}
/** Method to async deploy resources from the given directory. */
@@ -206,25 +121,11 @@ public TerraformPlan plan(
name = "TerraformFromDirectory",
description = "APIs for running Terraform commands inside a provided directory.")
@Operation(description = "async deploy resources via Terraform from the given directory.")
- @PostMapping(
- value = "/deploy/async/{module_directory}",
- produces = MediaType.APPLICATION_JSON_VALUE)
+ @PostMapping(value = "/deploy/async", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.ACCEPTED)
public void asyncDeployFromDirectory(
- @Parameter(
- name = "module_directory",
- description = "directory name where the Terraform module files exist.")
- @PathVariable("module_directory")
- String moduleDirectory,
- @Valid @RequestBody TerraformAsyncDeployFromDirectoryRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- List scriptFiles = scriptsHelper.getDeploymentFilesFromTaskWorkspace(moduleDirectory);
- directoryService.asyncDeployWithScripts(request, moduleDirectory, scriptFiles);
+ @Valid @RequestBody TerraformAsyncRequestWithScriptsDirectory request) {
+ requestService.processAsyncDeploymentRequest(request);
}
/** Method to async modify resources from the given directory. */
@@ -232,25 +133,11 @@ public void asyncDeployFromDirectory(
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)
+ @PostMapping(value = "/modify/async", 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 request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- List scriptFiles = scriptsHelper.getDeploymentFilesFromTaskWorkspace(moduleDirectory);
- directoryService.asyncModifyWithScripts(request, moduleDirectory, scriptFiles);
+ @Valid @RequestBody TerraformAsyncRequestWithScriptsDirectory request) {
+ requestService.processAsyncDeploymentRequest(request);
}
/** Method to async destroy resources from the given directory. */
@@ -258,24 +145,10 @@ public void asyncModifyFromDirectory(
name = "TerraformFromDirectory",
description = "APIs for running Terraform commands inside a provided directory.")
@Operation(description = "async destroy resources via Terraform from the given directory.")
- @DeleteMapping(
- value = "/destroy/async/{module_directory}",
- produces = MediaType.APPLICATION_JSON_VALUE)
+ @DeleteMapping(value = "/destroy/async", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.ACCEPTED)
public void asyncDestroyFromDirectory(
- @Parameter(
- name = "module_directory",
- description = "directory name where the Terraform module files exist.")
- @PathVariable("module_directory")
- String moduleDirectory,
- @Valid @RequestBody TerraformAsyncDestroyFromDirectoryRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- List scriptFiles = scriptsHelper.getDeploymentFilesFromTaskWorkspace(moduleDirectory);
- directoryService.asyncDestroyWithScripts(request, moduleDirectory, scriptFiles);
+ @Valid @RequestBody TerraformAsyncRequestWithScriptsDirectory request) {
+ requestService.processAsyncDeploymentRequest(request);
}
}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootFromGitRepoApi.java b/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootFromGitRepoApi.java
index 2689ddea..8ac6d9e3 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootFromGitRepoApi.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootFromGitRepoApi.java
@@ -5,26 +5,18 @@
package org.eclipse.xpanse.terra.boot.api.controllers;
-import static org.eclipse.xpanse.terra.boot.logging.CustomRequestIdGenerator.REQUEST_ID;
-
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
import jakarta.validation.Valid;
-import java.util.Objects;
-import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
-import org.eclipse.xpanse.terra.boot.models.plan.TerraformPlan;
-import org.eclipse.xpanse.terra.boot.models.plan.TerraformPlanFromGitRepoRequest;
-import org.eclipse.xpanse.terra.boot.models.request.git.TerraformAsyncDeployFromGitRepoRequest;
-import org.eclipse.xpanse.terra.boot.models.request.git.TerraformAsyncDestroyFromGitRepoRequest;
-import org.eclipse.xpanse.terra.boot.models.request.git.TerraformAsyncModifyFromGitRepoRequest;
-import org.eclipse.xpanse.terra.boot.models.request.git.TerraformDeployFromGitRepoRequest;
-import org.eclipse.xpanse.terra.boot.models.request.git.TerraformDestroyFromGitRepoRequest;
-import org.eclipse.xpanse.terra.boot.models.request.git.TerraformModifyFromGitRepoRequest;
+import org.eclipse.xpanse.terra.boot.models.request.git.TerraformAsyncRequestWithScriptsGitRepo;
+import org.eclipse.xpanse.terra.boot.models.request.git.TerraformRequestWithScriptsGitRepo;
+import org.eclipse.xpanse.terra.boot.models.response.TerraformPlan;
import org.eclipse.xpanse.terra.boot.models.response.TerraformResult;
-import org.eclipse.xpanse.terra.boot.models.validation.TerraformValidationResult;
-import org.eclipse.xpanse.terra.boot.terraform.service.TerraformGitRepoService;
-import org.slf4j.MDC;
+import org.eclipse.xpanse.terra.boot.models.response.validation.TerraformValidationResult;
+import org.eclipse.xpanse.terra.boot.terraform.service.TerraformRequestService;
+import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.CrossOrigin;
@@ -38,15 +30,12 @@
/** REST controller for running terraform modules from a GIT repo. */
@Slf4j
@CrossOrigin
+@Profile("!amqp")
@RestController
@RequestMapping("/terra-boot/git")
public class TerraBootFromGitRepoApi {
- private final TerraformGitRepoService terraformGitRepoService;
-
- public TerraBootFromGitRepoApi(TerraformGitRepoService terraformGitRepoService) {
- this.terraformGitRepoService = terraformGitRepoService;
- }
+ @Resource private TerraformRequestService requestService;
/**
* Method to validate resources by scripts.
@@ -61,14 +50,8 @@ public TerraBootFromGitRepoApi(TerraformGitRepoService terraformGitRepoService)
@PostMapping(value = "/validate", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public TerraformValidationResult validateScriptsFromGitRepo(
- @Valid @RequestBody TerraformDeployFromGitRepoRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- return terraformGitRepoService.validateWithScripts(request);
+ @Valid @RequestBody TerraformRequestWithScriptsGitRepo request) {
+ return requestService.handleTerraformValidateRequest(request);
}
/**
@@ -86,14 +69,8 @@ public TerraformValidationResult validateScriptsFromGitRepo(
@PostMapping(value = "/plan", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public TerraformPlan planFromGitRepo(
- @Valid @RequestBody TerraformPlanFromGitRepoRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- return terraformGitRepoService.getTerraformPlanFromGitRepo(request, uuid);
+ @Valid @RequestBody TerraformRequestWithScriptsGitRepo request) {
+ return requestService.handleTerraformPlanRequest(request);
}
/**
@@ -109,14 +86,8 @@ public TerraformPlan planFromGitRepo(
@PostMapping(value = "/deploy", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public TerraformResult deployFromGitRepo(
- @Valid @RequestBody TerraformDeployFromGitRepoRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- return terraformGitRepoService.deployFromGitRepo(request, uuid);
+ @Valid @RequestBody TerraformRequestWithScriptsGitRepo request) {
+ return requestService.handleTerraformDeploymentRequest(request);
}
/**
@@ -132,14 +103,8 @@ public TerraformResult deployFromGitRepo(
@PostMapping(value = "/modify", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public TerraformResult modifyFromGitRepo(
- @Valid @RequestBody TerraformModifyFromGitRepoRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- return terraformGitRepoService.modifyFromGitRepo(request, uuid);
+ @Valid @RequestBody TerraformRequestWithScriptsGitRepo request) {
+ return requestService.handleTerraformDeploymentRequest(request);
}
/**
@@ -155,14 +120,8 @@ public TerraformResult modifyFromGitRepo(
@PostMapping(value = "/destroy", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public TerraformResult destroyFromGitRepo(
- @Valid @RequestBody TerraformDestroyFromGitRepoRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- return terraformGitRepoService.destroyFromGitRepo(request, uuid);
+ @Valid @RequestBody TerraformRequestWithScriptsGitRepo request) {
+ return requestService.handleTerraformDeploymentRequest(request);
}
/** Method to async deploy resources from the provided GIT Repo. */
@@ -174,14 +133,8 @@ public TerraformResult destroyFromGitRepo(
@PostMapping(value = "/deploy/async", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.ACCEPTED)
public void asyncDeployFromGitRepo(
- @Valid @RequestBody TerraformAsyncDeployFromGitRepoRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- terraformGitRepoService.asyncDeployFromGitRepo(request, uuid);
+ @Valid @RequestBody TerraformAsyncRequestWithScriptsGitRepo request) {
+ requestService.processAsyncDeploymentRequest(request);
}
/** Method to async modify resources from the provided GIT Repo. */
@@ -193,14 +146,8 @@ public void asyncDeployFromGitRepo(
@PostMapping(value = "/modify/async", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.ACCEPTED)
public void asyncModifyFromGitRepo(
- @Valid @RequestBody TerraformAsyncModifyFromGitRepoRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- terraformGitRepoService.asyncModifyFromGitRepo(request, uuid);
+ @Valid @RequestBody TerraformAsyncRequestWithScriptsGitRepo request) {
+ requestService.processAsyncDeploymentRequest(request);
}
/** Method to async destroy resources by scripts. */
@@ -212,13 +159,7 @@ public void asyncModifyFromGitRepo(
@DeleteMapping(value = "/destroy/async", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.ACCEPTED)
public void asyncDestroyFromGitRepo(
- @Valid @RequestBody TerraformAsyncDestroyFromGitRepoRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- terraformGitRepoService.asyncDestroyFromGitRepo(request, uuid);
+ @Valid @RequestBody TerraformAsyncRequestWithScriptsGitRepo request) {
+ requestService.processAsyncDeploymentRequest(request);
}
}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootFromScriptsApi.java b/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootFromScriptsApi.java
index f29dff62..8cd98a92 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootFromScriptsApi.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootFromScriptsApi.java
@@ -5,26 +5,18 @@
package org.eclipse.xpanse.terra.boot.api.controllers;
-import static org.eclipse.xpanse.terra.boot.logging.CustomRequestIdGenerator.REQUEST_ID;
-
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
import jakarta.validation.Valid;
-import java.util.Objects;
-import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
-import org.eclipse.xpanse.terra.boot.models.plan.TerraformPlan;
-import org.eclipse.xpanse.terra.boot.models.plan.TerraformPlanWithScriptsRequest;
-import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformAsyncDeployFromScriptsRequest;
-import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformAsyncDestroyFromScriptsRequest;
-import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformAsyncModifyFromScriptsRequest;
-import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformDeployWithScriptsRequest;
-import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformDestroyWithScriptsRequest;
-import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformModifyWithScriptsRequest;
+import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformAsyncRequestWithScripts;
+import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformRequestWithScripts;
+import org.eclipse.xpanse.terra.boot.models.response.TerraformPlan;
import org.eclipse.xpanse.terra.boot.models.response.TerraformResult;
-import org.eclipse.xpanse.terra.boot.models.validation.TerraformValidationResult;
-import org.eclipse.xpanse.terra.boot.terraform.service.TerraformScriptsService;
-import org.slf4j.MDC;
+import org.eclipse.xpanse.terra.boot.models.response.validation.TerraformValidationResult;
+import org.eclipse.xpanse.terra.boot.terraform.service.TerraformRequestService;
+import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.CrossOrigin;
@@ -38,15 +30,12 @@
/** API methods implemented by terra-boot. */
@Slf4j
@CrossOrigin
+@Profile("!amqp")
@RestController
@RequestMapping("/terra-boot/scripts/")
public class TerraBootFromScriptsApi {
- private final TerraformScriptsService terraformScriptsService;
-
- public TerraBootFromScriptsApi(TerraformScriptsService terraformScriptsService) {
- this.terraformScriptsService = terraformScriptsService;
- }
+ @Resource private TerraformRequestService requestService;
/**
* Method to validate resources by scripts.
@@ -61,14 +50,8 @@ public TerraBootFromScriptsApi(TerraformScriptsService terraformScriptsService)
@PostMapping(value = "/validate", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public TerraformValidationResult validateWithScripts(
- @Valid @RequestBody TerraformDeployWithScriptsRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- return terraformScriptsService.validateWithScripts(request);
+ @Valid @RequestBody TerraformRequestWithScripts request) {
+ return requestService.handleTerraformValidateRequest(request);
}
/**
@@ -84,14 +67,8 @@ public TerraformValidationResult validateWithScripts(
@PostMapping(value = "/deploy", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public TerraformResult deployWithScripts(
- @Valid @RequestBody TerraformDeployWithScriptsRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- return terraformScriptsService.deployWithScripts(request, uuid);
+ @Valid @RequestBody TerraformRequestWithScripts request) {
+ return requestService.handleTerraformDeploymentRequest(request);
}
/**
@@ -107,14 +84,8 @@ public TerraformResult deployWithScripts(
@PostMapping(value = "/modify", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public TerraformResult modifyWithScripts(
- @Valid @RequestBody TerraformModifyWithScriptsRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- return terraformScriptsService.modifyWithScripts(request, uuid);
+ @Valid @RequestBody TerraformRequestWithScripts request) {
+ return requestService.handleTerraformDeploymentRequest(request);
}
/**
@@ -130,14 +101,8 @@ public TerraformResult modifyWithScripts(
@PostMapping(value = "/destroy", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
public TerraformResult destroyWithScripts(
- @Valid @RequestBody TerraformDestroyWithScriptsRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- return terraformScriptsService.destroyWithScripts(request, uuid);
+ @Valid @RequestBody TerraformRequestWithScripts request) {
+ return requestService.handleTerraformDeploymentRequest(request);
}
/** Method to async deploy resources by scripts. */
@@ -149,14 +114,8 @@ public TerraformResult destroyWithScripts(
@PostMapping(value = "/deploy/async", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.ACCEPTED)
public void asyncDeployWithScripts(
- @Valid @RequestBody TerraformAsyncDeployFromScriptsRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- terraformScriptsService.asyncDeployWithScripts(request, uuid);
+ @Valid @RequestBody TerraformAsyncRequestWithScripts request) {
+ requestService.processAsyncDeploymentRequest(request);
}
/** Method to async modify resources by scripts. */
@@ -168,14 +127,8 @@ public void asyncDeployWithScripts(
@PostMapping(value = "/modify/async", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.ACCEPTED)
public void asyncModifyWithScripts(
- @Valid @RequestBody TerraformAsyncModifyFromScriptsRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- terraformScriptsService.asyncModifyWithScripts(request, uuid);
+ @Valid @RequestBody TerraformAsyncRequestWithScripts request) {
+ requestService.processAsyncDeploymentRequest(request);
}
/** Method to async destroy resources by scripts. */
@@ -187,14 +140,8 @@ public void asyncModifyWithScripts(
@DeleteMapping(value = "/destroy/async", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.ACCEPTED)
public void asyncDestroyWithScripts(
- @Valid @RequestBody TerraformAsyncDestroyFromScriptsRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- terraformScriptsService.asyncDestroyWithScripts(request, uuid);
+ @Valid @RequestBody TerraformAsyncRequestWithScripts request) {
+ requestService.processAsyncDeploymentRequest(request);
}
/**
@@ -211,14 +158,7 @@ public void asyncDestroyWithScripts(
"Get Terraform Plan as JSON string from the list of script files provided")
@PostMapping(value = "/plan", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.OK)
- public TerraformPlan planWithScripts(
- @Valid @RequestBody TerraformPlanWithScriptsRequest request) {
- UUID uuid =
- Objects.nonNull(request.getRequestId())
- ? request.getRequestId()
- : UUID.randomUUID();
- MDC.put(REQUEST_ID, uuid.toString());
- request.setRequestId(uuid);
- return terraformScriptsService.getTerraformPlanFromScripts(request, uuid);
+ public TerraformPlan planWithScripts(@Valid @RequestBody TerraformRequestWithScripts request) {
+ return requestService.handleTerraformPlanRequest(request);
}
}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootTaskResultApi.java b/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootTaskResultApi.java
index 9a54be54..c28758cf 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootTaskResultApi.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/api/controllers/TerraBootTaskResultApi.java
@@ -15,6 +15,7 @@
import lombok.extern.slf4j.Slf4j;
import org.eclipse.xpanse.terra.boot.models.response.ReFetchResult;
import org.eclipse.xpanse.terra.boot.terraform.service.TerraformResultPersistenceManage;
+import org.springframework.context.annotation.Profile;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.util.CollectionUtils;
@@ -29,6 +30,7 @@
/** REST controller for manage the task form terra-boot. */
@Slf4j
+@Profile("!amqp")
@CrossOrigin
@RestController
@RequestMapping("/terra-boot/task")
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/AmqpConsumer.java b/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/AmqpConsumer.java
new file mode 100644
index 00000000..d0a7e4f6
--- /dev/null
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/AmqpConsumer.java
@@ -0,0 +1,50 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * SPDX-FileCopyrightText: Huawei Inc.
+ */
+
+package org.eclipse.xpanse.terra.boot.api.queues;
+
+import java.util.UUID;
+import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformRequestWithScriptsDirectory;
+import org.eclipse.xpanse.terra.boot.models.request.git.TerraformRequestWithScriptsGitRepo;
+import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformRequestWithScripts;
+import org.springframework.context.annotation.Profile;
+import org.springframework.messaging.handler.annotation.Payload;
+import org.springframework.stereotype.Component;
+
+/** AMQP consumer. */
+@Profile("amqp")
+@Component
+public interface AmqpConsumer {
+
+ /**
+ * Get terraform health check request and process it.
+ *
+ * @param requestId request id
+ */
+ void processTerraformHealthCheckRequestFromQueue(@Payload UUID requestId);
+
+ /**
+ * Get terraform request with scripts directory from queue and process it.
+ *
+ * @param request request
+ */
+ void processTerraformRequestWithDirectoryFromQueue(
+ @Payload TerraformRequestWithScriptsDirectory request);
+
+ /**
+ * Get terraform request with scripts directory from queue and process it.
+ *
+ * @param request request
+ */
+ void processTerraformRequestWithGitFromQueue(
+ @Payload TerraformRequestWithScriptsGitRepo request);
+
+ /**
+ * Get terraform request with scripts directory from queue and process it.
+ *
+ * @param request request
+ */
+ void processTerraformRequestWithScriptsFromQueue(@Payload TerraformRequestWithScripts request);
+}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/AmqpProducer.java b/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/AmqpProducer.java
new file mode 100644
index 00000000..3b24dd7c
--- /dev/null
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/AmqpProducer.java
@@ -0,0 +1,77 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * SPDX-FileCopyrightText: Huawei Inc.
+ */
+
+package org.eclipse.xpanse.terra.boot.api.queues;
+
+import java.util.UUID;
+import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformRequestWithScriptsDirectory;
+import org.eclipse.xpanse.terra.boot.models.request.git.TerraformRequestWithScriptsGitRepo;
+import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformRequestWithScripts;
+import org.eclipse.xpanse.terra.boot.models.response.TerraBootSystemStatus;
+import org.eclipse.xpanse.terra.boot.models.response.TerraformPlan;
+import org.eclipse.xpanse.terra.boot.models.response.TerraformResult;
+import org.eclipse.xpanse.terra.boot.models.response.validation.TerraformValidationResult;
+import org.springframework.context.annotation.Profile;
+import org.springframework.messaging.handler.annotation.Payload;
+import org.springframework.stereotype.Component;
+
+/** AMQP producer. */
+@Profile("amqp")
+@Component
+public interface AmqpProducer {
+
+ /** Send terraform health check request to amqp queue. */
+ void sendTerraformHealthCheckRequest(@Payload UUID requestId);
+
+ /**
+ * Send terraform request with scripts to amqp queue.
+ *
+ * @param request request to send.
+ */
+ void sendTerraformRequestWithDirectory(@Payload TerraformRequestWithScriptsDirectory request);
+
+ /**
+ * Send terraform request with scripts git repo to amqp queue.
+ *
+ * @param request request to send.
+ */
+ void sendTerraformRequestWithScriptsGitRepo(
+ @Payload TerraformRequestWithScriptsGitRepo request);
+
+ /**
+ * Send terraform request with scripts to amqp queue.
+ *
+ * @param request request to send.
+ */
+ void sendTerraformRequestWithScripts(@Payload TerraformRequestWithScripts request);
+
+ /**
+ * Send terraform health check result to amqp queue.
+ *
+ * @param result result to send.
+ */
+ void sendTerraformHealthCheckResult(@Payload TerraBootSystemStatus result);
+
+ /**
+ * Send terraform plan result to amqp queue.
+ *
+ * @param result result to send.
+ */
+ void sendTerraformPlanResult(@Payload TerraformPlan result);
+
+ /**
+ * Send terraform validation result to amqp queue.
+ *
+ * @param result result to send.
+ */
+ void sendTerraformValidationResult(@Payload TerraformValidationResult result);
+
+ /**
+ * Send terraform deployment result to amqp queue.
+ *
+ * @param result result to send.
+ */
+ void sendTerraformDeploymentResult(@Payload TerraformResult result);
+}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/config/AmqpConfig.java b/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/config/AmqpConfig.java
new file mode 100644
index 00000000..b9c8b52a
--- /dev/null
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/config/AmqpConfig.java
@@ -0,0 +1,175 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * SPDX-FileCopyrightText: Huawei Inc.
+ */
+
+package org.eclipse.xpanse.terra.boot.api.queues.config;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.amqp.core.Binding;
+import org.springframework.amqp.core.BindingBuilder;
+import org.springframework.amqp.core.DirectExchange;
+import org.springframework.amqp.core.Queue;
+import org.springframework.amqp.core.QueueBuilder;
+import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Profile;
+import org.springframework.stereotype.Component;
+
+/** Configuration for Spring AMQP (Advanced Message Queuing Protocol). */
+@Slf4j
+@Profile("amqp")
+@Component
+public class AmqpConfig {
+
+ @Resource private ObjectMapper objectMapper;
+
+ /** Create JSON message converter for Spring AMQP. */
+ @Bean("customJsonMessageConverter")
+ public Jackson2JsonMessageConverter jsonMessageConverter() {
+ ObjectMapper localObjectMapper = objectMapper.copy();
+ localObjectMapper
+ .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
+ .deactivateDefaultTyping()
+ .setSerializationInclusion(JsonInclude.Include.NON_NULL);
+ Jackson2JsonMessageConverter converter =
+ new Jackson2JsonMessageConverter(localObjectMapper);
+ converter.setAlwaysConvertToInferredType(true);
+ return converter;
+ }
+
+ private Queue createDurableQueue(String queueName) {
+ return QueueBuilder.durable(queueName).build();
+ }
+
+ /** Create durable queue for Terraform health check request. */
+ @Bean
+ public Queue queueForTerraformHealthCheckRequest() {
+ return createDurableQueue(AmqpConstants.QUEUE_NAME_FOR_TERRAFORM_HEALTH_CHECK_REQUEST);
+ }
+
+ /** Create durable queue for Terraform request with directory. */
+ @Bean
+ public Queue queueForTerraformRequestWithDirectory() {
+ return createDurableQueue(AmqpConstants.QUEUE_NAME_FOR_TERRAFORM_REQUEST_WITH_DIRECTORY);
+ }
+
+ /** Create durable queue for Terraform request with scripts. */
+ @Bean
+ public Queue queueForTerraformRequestWithScripts() {
+ return createDurableQueue(AmqpConstants.QUEUE_NAME_FOR_TERRAFORM_REQUEST_WITH_SCRIPTS);
+ }
+
+ /** Create durable queue for Terraform request with git repo. */
+ @Bean
+ public Queue queueForTerraformRequestWithScriptsGitRepo() {
+ return createDurableQueue(AmqpConstants.QUEUE_NAME_FOR_TERRAFORM_REQUEST_WITH_GIT);
+ }
+
+ /** Create durable queue for Terraform health check result. */
+ @Bean
+ public Queue queueForTerraformHealthCheckResult() {
+ return createDurableQueue(AmqpConstants.QUEUE_NAME_FOR_TERRAFORM_HEALTH_CHECK_RESULT);
+ }
+
+ /** Create durable queue for Terraform plan result. */
+ @Bean
+ public Queue queueForTerraformPlanResult() {
+ return createDurableQueue(AmqpConstants.QUEUE_NAME_FOR_TERRAFORM_PLAN_RESULT);
+ }
+
+ /** Create durable queue for Terraform validation result. */
+ @Bean
+ public Queue queueForTerraformValidationResult() {
+ return createDurableQueue(AmqpConstants.QUEUE_NAME_FOR_TERRAFORM_VALIDATION_RESULT);
+ }
+
+ /** Create durable queue for Terraform deployment result. */
+ @Bean
+ public Queue queueForTerraformDeploymentResult() {
+ return createDurableQueue(AmqpConstants.QUEUE_NAME_FOR_TERRAFORM_DEPLOYMENT_RESULT);
+ }
+
+ /** Create direct exchange for Terraform message. */
+ @Bean
+ public DirectExchange terraformDirectExchange() {
+ return new DirectExchange(AmqpConstants.EXCHANGE_NAME_FOR_TERRAFORM, true, false);
+ }
+
+ /** Bind Terraform health check request queue to Terraform direct exchange. */
+ @Bean
+ public Binding bindHealthCheckRequest(
+ DirectExchange terraformDirectExchange, Queue queueForTerraformHealthCheckRequest) {
+ return BindingBuilder.bind(queueForTerraformHealthCheckRequest)
+ .to(terraformDirectExchange)
+ .with(AmqpConstants.ROUTING_KEY_FOR_TERRAFORM_HEALTH_CHECK_REQUEST);
+ }
+
+ /** Bind Terraform request with directory queue to Terraform direct exchange. */
+ @Bean
+ public Binding bindRequestWithDirectory(
+ DirectExchange terraformDirectExchange, Queue queueForTerraformRequestWithDirectory) {
+ return BindingBuilder.bind(queueForTerraformRequestWithDirectory)
+ .to(terraformDirectExchange)
+ .with(AmqpConstants.ROUTING_KEY_FOR_TERRAFORM_REQUEST_WITH_DIRECTORY);
+ }
+
+ /** Bind Terraform request with scripts queue to Terraform direct exchange. */
+ @Bean
+ public Binding bindRequestWithScripts(
+ DirectExchange terraformDirectExchange, Queue queueForTerraformRequestWithScripts) {
+ return BindingBuilder.bind(queueForTerraformRequestWithScripts)
+ .to(terraformDirectExchange)
+ .with(AmqpConstants.ROUTING_KEY_FOR_TERRAFORM_REQUEST_WITH_SCRIPTS);
+ }
+
+ /** Bind Terraform request with git repo queue to Terraform direct exchange. */
+ @Bean
+ public Binding bindRequestWithGitRepo(
+ DirectExchange terraformDirectExchange,
+ Queue queueForTerraformRequestWithScriptsGitRepo) {
+ return BindingBuilder.bind(queueForTerraformRequestWithScriptsGitRepo)
+ .to(terraformDirectExchange)
+ .with(AmqpConstants.ROUTING_KEY_FOR_TERRAFORM_REQUEST_WITH_GIT);
+ }
+
+ /** Bind Terraform health check result queue to Terraform direct exchange. */
+ @Bean
+ public Binding bindHealthCheckResult(
+ DirectExchange terraformDirectExchange, Queue queueForTerraformHealthCheckResult) {
+ return BindingBuilder.bind(queueForTerraformHealthCheckResult)
+ .to(terraformDirectExchange)
+ .with(AmqpConstants.ROUTING_KEY_FOR_TERRAFORM_HEALTH_CHECK_RESULT);
+ }
+
+ /** Bind Terraform plan result queue to Terraform direct exchange. */
+ @Bean
+ public Binding bindPlanResult(
+ DirectExchange terraformDirectExchange, Queue queueForTerraformPlanResult) {
+ return BindingBuilder.bind(queueForTerraformPlanResult)
+ .to(terraformDirectExchange)
+ .with(AmqpConstants.ROUTING_KEY_FOR_TERRAFORM_PLAN_RESULT);
+ }
+
+ /** Bind Terraform validation result queue to Terraform direct exchange. */
+ @Bean
+ public Binding bindValidationResult(
+ DirectExchange terraformDirectExchange, Queue queueForTerraformValidationResult) {
+ return BindingBuilder.bind(queueForTerraformValidationResult)
+ .to(terraformDirectExchange)
+ .with(AmqpConstants.ROUTING_KEY_FOR_TERRAFORM_VALIDATION_RESULT);
+ }
+
+ /** Bind Terraform deployment result queue to Terraform direct exchange. */
+ @Bean
+ public Binding bindDeploymentResult(
+ DirectExchange terraformDirectExchange, Queue queueForTerraformDeploymentResult) {
+ return BindingBuilder.bind(queueForTerraformDeploymentResult)
+ .to(terraformDirectExchange)
+ .with(AmqpConstants.ROUTING_KEY_FOR_TERRAFORM_DEPLOYMENT_RESULT);
+ }
+}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/config/AmqpConstants.java b/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/config/AmqpConstants.java
new file mode 100644
index 00000000..87f9957d
--- /dev/null
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/config/AmqpConstants.java
@@ -0,0 +1,76 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * SPDX-FileCopyrightText: Huawei Inc.
+ */
+
+package org.eclipse.xpanse.terra.boot.api.queues.config;
+
+/** Constants for AMQP queues, exchanges, and routing keys. */
+public class AmqpConstants {
+
+ /** Name of the queue for Terraform health check request. */
+ public static final String QUEUE_NAME_FOR_TERRAFORM_HEALTH_CHECK_REQUEST =
+ "org.eclipse.terra.boot.queue.request.health-check";
+
+ /** Name of the queue for Terraform request with scripts in directory. */
+ public static final String QUEUE_NAME_FOR_TERRAFORM_REQUEST_WITH_DIRECTORY =
+ "org.eclipse.terra.boot.queue.request.directory";
+
+ /** Name of the queue for Terraform request with scripts in git repo. */
+ public static final String QUEUE_NAME_FOR_TERRAFORM_REQUEST_WITH_GIT =
+ "org.eclipse.terra.boot.queue.request.git";
+
+ /** Name of the queue for Terraform request with scripts map. */
+ public static final String QUEUE_NAME_FOR_TERRAFORM_REQUEST_WITH_SCRIPTS =
+ "org.eclipse.terra.boot.queue.request.scripts";
+
+ /** Name of the queue for Terraform health check results. */
+ public static final String QUEUE_NAME_FOR_TERRAFORM_HEALTH_CHECK_RESULT =
+ "org.eclipse.terra.boot.queue.result.health-check";
+
+ /** Name of the queue for Terraform health check results. */
+ public static final String QUEUE_NAME_FOR_TERRAFORM_PLAN_RESULT =
+ "org.eclipse.terra.boot.queue.result.plan";
+
+ /** Name of the queue for Terraform health check results. */
+ public static final String QUEUE_NAME_FOR_TERRAFORM_VALIDATION_RESULT =
+ "org.eclipse.terra.boot.queue.result.validation";
+
+ /** Name of the queue for Terraform results. */
+ public static final String QUEUE_NAME_FOR_TERRAFORM_DEPLOYMENT_RESULT =
+ "org.eclipse.terra.boot.queue.result.deployment";
+
+ /** Exchange name for Terraform messages. */
+ public static final String EXCHANGE_NAME_FOR_TERRAFORM = "terraform.direct.exchange";
+
+ /** Routing keys for Terraform health check request. */
+ public static final String ROUTING_KEY_FOR_TERRAFORM_HEALTH_CHECK_REQUEST =
+ "request.health-check";
+
+ /** Routing keys for Terraform request with directory. */
+ public static final String ROUTING_KEY_FOR_TERRAFORM_REQUEST_WITH_DIRECTORY =
+ "request.directory";
+
+ /** Routing keys for Terraform request with scripts. */
+ public static final String ROUTING_KEY_FOR_TERRAFORM_REQUEST_WITH_SCRIPTS = "request.scripts";
+
+ /** Routing keys for Terraform request with git repo. */
+ public static final String ROUTING_KEY_FOR_TERRAFORM_REQUEST_WITH_GIT = "request.git";
+
+ /** Routing keys for result of Terraform health check. */
+ public static final String ROUTING_KEY_FOR_TERRAFORM_HEALTH_CHECK_RESULT =
+ "result.health-check";
+
+ /** Routing keys for result of Terraform plan. */
+ public static final String ROUTING_KEY_FOR_TERRAFORM_PLAN_RESULT = "result.plan";
+
+ /** Routing keys for result of Terraform validation. */
+ public static final String ROUTING_KEY_FOR_TERRAFORM_VALIDATION_RESULT = "result.validation";
+
+ /** Routing keys for result of Terraform deployment. */
+ public static final String ROUTING_KEY_FOR_TERRAFORM_DEPLOYMENT_RESULT = "result.deployment";
+
+ private AmqpConstants() {
+ // Private constructor to prevent instantiation
+ }
+}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/rabbitmq/DisableRabbitAutoConfiguration.java b/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/rabbitmq/DisableRabbitAutoConfiguration.java
new file mode 100644
index 00000000..471fe72d
--- /dev/null
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/rabbitmq/DisableRabbitAutoConfiguration.java
@@ -0,0 +1,19 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * SPDX-FileCopyrightText: Huawei Inc.
+ */
+
+package org.eclipse.xpanse.terra.boot.api.queues.rabbitmq;
+
+import org.springframework.boot.actuate.autoconfigure.amqp.RabbitHealthContributorAutoConfiguration;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+/** Disable AmqpAutoConfigurations when profile amqp is disabled. */
+@Profile("!amqp")
+@Configuration
+@EnableAutoConfiguration(
+ exclude = {RabbitAutoConfiguration.class, RabbitHealthContributorAutoConfiguration.class})
+public class DisableRabbitAutoConfiguration {}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/rabbitmq/RabbitMqConfig.java b/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/rabbitmq/RabbitMqConfig.java
new file mode 100644
index 00000000..7681ec44
--- /dev/null
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/rabbitmq/RabbitMqConfig.java
@@ -0,0 +1,98 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * SPDX-FileCopyrightText: Huawei Inc.
+ */
+
+package org.eclipse.xpanse.terra.boot.api.queues.rabbitmq;
+
+import jakarta.annotation.Resource;
+import org.springframework.amqp.core.AcknowledgeMode;
+import org.springframework.amqp.rabbit.annotation.EnableRabbit;
+import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
+import org.springframework.amqp.rabbit.connection.ConnectionFactory;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.amqp.rabbit.listener.RabbitListenerContainerFactory;
+import org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer;
+import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Profile;
+import org.springframework.retry.backoff.ExponentialBackOffPolicy;
+import org.springframework.retry.policy.SimpleRetryPolicy;
+import org.springframework.retry.support.RetryTemplate;
+import org.springframework.stereotype.Component;
+
+/** RabbitMQ configuration for AMQP. */
+@Component
+@Profile("amqp")
+@ConditionalOnProperty(name = "spring.amqp.provider", havingValue = "rabbitmq")
+@EnableRabbit
+public class RabbitMqConfig {
+
+ @Qualifier("customJsonMessageConverter")
+ @Resource
+ private Jackson2JsonMessageConverter jsonMessageConverter;
+
+ @Value("${spring.rabbitmq.listener.simple.retry.max-attempts:3}")
+ private int retryMaxAttempts;
+
+ @Value("${spring.rabbitmq.listener.simple.retry.initial-interval:5000}")
+ private int retryInitialInterval;
+
+ @Value("${spring.rabbitmq.listener.simple.retry.max-interval:30000}")
+ private int retryMaxInterval;
+
+ /**
+ * Create a RabbitTemplate bean with custom message converter and retry template.
+ *
+ * @param connectionFactory The connection factory used to create the RabbitTemplate.
+ * @return RabbitTemplate bean.
+ */
+ @Bean("customRabbitTemplate")
+ public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
+ final RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
+ rabbitTemplate.setMessageConverter(jsonMessageConverter);
+ rabbitTemplate.setRetryTemplate(retryTemplate());
+ return rabbitTemplate;
+ }
+
+ /**
+ * Create a RabbitListenerContainerFactory bean with custom message converter and retry
+ * template.
+ *
+ * @param connectionFactory The connection factory used to create the
+ * RabbitListenerContainerFactory.
+ * @return rabbitListenerContainerFactory bean.
+ */
+ @Bean("customRabbitListenerContainerFactory")
+ public RabbitListenerContainerFactory
+ rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
+ SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
+ factory.setMessageConverter(jsonMessageConverter);
+ factory.setConnectionFactory(connectionFactory);
+ factory.setAcknowledgeMode(AcknowledgeMode.AUTO);
+ factory.setDefaultRequeueRejected(true);
+ factory.setFailedDeclarationRetryInterval(5000L);
+ factory.setPrefetchCount(100);
+ factory.setRetryTemplate(retryTemplate());
+
+ factory.setBatchSize(10);
+ factory.setConcurrentConsumers(5);
+ factory.setMaxConcurrentConsumers(10);
+ factory.setConsecutiveActiveTrigger(5);
+ factory.setConsecutiveIdleTrigger(10);
+ return factory;
+ }
+
+ private RetryTemplate retryTemplate() {
+ RetryTemplate retryTemplate = new RetryTemplate();
+ retryTemplate.setRetryPolicy(new SimpleRetryPolicy(retryMaxAttempts));
+ ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy();
+ backOffPolicy.setInitialInterval(retryInitialInterval);
+ backOffPolicy.setMaxInterval(retryMaxInterval);
+ retryTemplate.setBackOffPolicy(backOffPolicy);
+ return retryTemplate;
+ }
+}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/rabbitmq/RabbitMqConsumer.java b/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/rabbitmq/RabbitMqConsumer.java
new file mode 100644
index 00000000..a6b129d6
--- /dev/null
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/rabbitmq/RabbitMqConsumer.java
@@ -0,0 +1,152 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * SPDX-FileCopyrightText: Huawei Inc.
+ */
+
+package org.eclipse.xpanse.terra.boot.api.queues.rabbitmq;
+
+import jakarta.annotation.Resource;
+import java.util.Objects;
+import java.util.UUID;
+import lombok.extern.slf4j.Slf4j;
+import org.eclipse.xpanse.terra.boot.api.queues.AmqpConsumer;
+import org.eclipse.xpanse.terra.boot.api.queues.config.AmqpConstants;
+import org.eclipse.xpanse.terra.boot.models.enums.HealthStatus;
+import org.eclipse.xpanse.terra.boot.models.exceptions.UnsupportedEnumValueException;
+import org.eclipse.xpanse.terra.boot.models.request.TerraformRequest;
+import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformRequestWithScriptsDirectory;
+import org.eclipse.xpanse.terra.boot.models.request.git.TerraformRequestWithScriptsGitRepo;
+import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformRequestWithScripts;
+import org.eclipse.xpanse.terra.boot.models.response.TerraBootSystemStatus;
+import org.eclipse.xpanse.terra.boot.terraform.service.TerraformRequestService;
+import org.springframework.amqp.rabbit.annotation.RabbitListener;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.context.annotation.Profile;
+import org.springframework.messaging.handler.annotation.Payload;
+import org.springframework.stereotype.Component;
+
+/** Implementation of AmqpConsumer interface for RabbitMQ. */
+@Slf4j
+@Component
+@Profile("amqp")
+@ConditionalOnProperty(name = "spring.amqp.provider", havingValue = "rabbitmq")
+public class RabbitMqConsumer implements AmqpConsumer {
+
+ @Resource private RabbitMqProducer producer;
+
+ @Lazy @Resource private TerraformRequestService requestService;
+
+ @Value("${springwolf.docket.servers.amqp-server.protocol}")
+ private String serverProtocol;
+
+ @Value("${springwolf.docket.servers.amqp-server.host}")
+ private String serverUrl;
+
+ @RabbitListener(
+ queues = AmqpConstants.QUEUE_NAME_FOR_TERRAFORM_HEALTH_CHECK_REQUEST,
+ containerFactory = "customRabbitListenerContainerFactory")
+ @Override
+ public void processTerraformHealthCheckRequestFromQueue(@Payload UUID requestId) {
+ log.info("Processing received health check request with id {}", requestId);
+ TerraBootSystemStatus result = null;
+ try {
+ result = requestService.healthCheck(requestId);
+ } catch (Exception e) {
+ log.error("Failed to process health request with id {}", requestId, e);
+ result = new TerraBootSystemStatus();
+ result.setRequestId(requestId);
+ result.setHealthStatus(HealthStatus.NOK);
+ result.setErrorMessage(e.getMessage());
+ }
+ result.setServiceType(serverProtocol);
+ result.setServiceUrl(serverUrl);
+ producer.sendTerraformHealthCheckResult(result);
+ }
+
+ @RabbitListener(
+ queues = AmqpConstants.QUEUE_NAME_FOR_TERRAFORM_REQUEST_WITH_DIRECTORY,
+ containerFactory = "customRabbitListenerContainerFactory")
+ @Override
+ public void processTerraformRequestWithDirectoryFromQueue(
+ @Payload TerraformRequestWithScriptsDirectory request) {
+ handleTerraformRequestAndSendResult(request);
+ }
+
+ @RabbitListener(
+ queues = AmqpConstants.QUEUE_NAME_FOR_TERRAFORM_REQUEST_WITH_GIT,
+ containerFactory = "customRabbitListenerContainerFactory")
+ @Override
+ public void processTerraformRequestWithGitFromQueue(
+ @Payload TerraformRequestWithScriptsGitRepo request) {
+ handleTerraformRequestAndSendResult(request);
+ }
+
+ @RabbitListener(
+ queues = AmqpConstants.QUEUE_NAME_FOR_TERRAFORM_REQUEST_WITH_SCRIPTS,
+ containerFactory = "customRabbitListenerContainerFactory")
+ @Override
+ public void processTerraformRequestWithScriptsFromQueue(
+ @Payload TerraformRequestWithScripts request) {
+ handleTerraformRequestAndSendResult(request);
+ }
+
+ private void handleTerraformRequestAndSendResult(TerraformRequest request) {
+ try {
+ processRequestByType(request);
+ } catch (Exception e) {
+ sendErrorResultToQueue(Objects.requireNonNull(request), e);
+ }
+ }
+
+ private void processRequestByType(TerraformRequest request) {
+ switch (request.getRequestType()) {
+ case VALIDATE ->
+ producer.sendTerraformValidationResult(
+ requestService.handleTerraformValidateRequest(request));
+ case PLAN ->
+ producer.sendTerraformPlanResult(
+ requestService.handleTerraformPlanRequest(request));
+ case DEPLOY, MODIFY, DESTROY ->
+ producer.sendTerraformDeploymentResult(
+ requestService.handleTerraformDeploymentRequest(request));
+ default ->
+ throw new UnsupportedEnumValueException(
+ String.format(
+ "RequestType value %s is not supported.",
+ request.getRequestType().toValue()));
+ }
+ }
+
+ private void sendErrorResultToQueue(TerraformRequest request, Exception e) {
+ log.error(
+ "Failed to process request with id {} from amqp queues. {}",
+ request.getRequestId(),
+ e.getMessage(),
+ e);
+ try {
+ processErrorByRequestType(request, e);
+ } catch (Exception innerEx) {
+ log.error("Error handling failed request: {}", innerEx.getMessage(), innerEx);
+ }
+ }
+
+ private void processErrorByRequestType(TerraformRequest request, Exception e) {
+ switch (request.getRequestType()) {
+ case VALIDATE ->
+ producer.sendTerraformValidationResult(
+ requestService.getErrorValidateResult(request, e));
+ case PLAN ->
+ producer.sendTerraformPlanResult(requestService.getErrorPlanResult(request, e));
+ case DEPLOY, MODIFY, DESTROY ->
+ producer.sendTerraformDeploymentResult(
+ requestService.getErrorDeploymentResult(request, e));
+ default ->
+ throw new UnsupportedEnumValueException(
+ String.format(
+ "RequestType value %s is not supported.",
+ request.getRequestType().toValue()));
+ }
+ }
+}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/rabbitmq/RabbitMqProducer.java b/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/rabbitmq/RabbitMqProducer.java
new file mode 100644
index 00000000..52b34c75
--- /dev/null
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/api/queues/rabbitmq/RabbitMqProducer.java
@@ -0,0 +1,176 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * SPDX-FileCopyrightText: Huawei Inc.
+ */
+
+package org.eclipse.xpanse.terra.boot.api.queues.rabbitmq;
+
+import io.github.springwolf.bindings.amqp.annotations.AmqpAsyncOperationBinding;
+import io.github.springwolf.core.asyncapi.annotations.AsyncOperation;
+import io.github.springwolf.core.asyncapi.annotations.AsyncPublisher;
+import jakarta.annotation.Resource;
+import java.util.Objects;
+import java.util.UUID;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.xpanse.terra.boot.api.queues.AmqpProducer;
+import org.eclipse.xpanse.terra.boot.api.queues.config.AmqpConstants;
+import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformRequestWithScriptsDirectory;
+import org.eclipse.xpanse.terra.boot.models.request.git.TerraformRequestWithScriptsGitRepo;
+import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformRequestWithScripts;
+import org.eclipse.xpanse.terra.boot.models.response.TerraBootSystemStatus;
+import org.eclipse.xpanse.terra.boot.models.response.TerraformPlan;
+import org.eclipse.xpanse.terra.boot.models.response.TerraformResult;
+import org.eclipse.xpanse.terra.boot.models.response.validation.TerraformValidationResult;
+import org.springframework.amqp.AmqpException;
+import org.springframework.amqp.rabbit.core.RabbitTemplate;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Profile;
+import org.springframework.messaging.handler.annotation.Payload;
+import org.springframework.stereotype.Component;
+
+/** implementation of AmqpProducer interface for RabbitMQ. */
+@Slf4j
+@Component
+@Profile("amqp")
+@ConditionalOnProperty(name = "spring.amqp.provider", havingValue = "rabbitmq")
+public class RabbitMqProducer implements AmqpProducer {
+
+ @Qualifier("customRabbitTemplate")
+ @Resource
+ private RabbitTemplate rabbitTemplate;
+
+ @AsyncPublisher(
+ operation =
+ @AsyncOperation(
+ channelName =
+ AmqpConstants.QUEUE_NAME_FOR_TERRAFORM_HEALTH_CHECK_REQUEST,
+ description = "Send terraform health check request to rabbitmq queue."))
+ @AmqpAsyncOperationBinding
+ @Override
+ public void sendTerraformHealthCheckRequest(@Payload UUID requestId) {
+ log.info("Received terraform health check request with id {}", requestId);
+ sendMessageViaExchange(
+ AmqpConstants.ROUTING_KEY_FOR_TERRAFORM_HEALTH_CHECK_REQUEST,
+ requestId,
+ "Health check request " + requestId);
+ }
+
+ @AsyncPublisher(
+ operation =
+ @AsyncOperation(
+ channelName =
+ AmqpConstants.QUEUE_NAME_FOR_TERRAFORM_REQUEST_WITH_DIRECTORY,
+ description = "Send terraform request with scripts to rabbitmq queue."))
+ @AmqpAsyncOperationBinding
+ @Override
+ public void sendTerraformRequestWithDirectory(
+ @Payload TerraformRequestWithScriptsDirectory request) {
+ log.info(
+ "Received terraform directory request with type {} and id {}",
+ request.getRequestType(),
+ request.getRequestId());
+ sendMessageViaExchange(
+ AmqpConstants.ROUTING_KEY_FOR_TERRAFORM_REQUEST_WITH_DIRECTORY,
+ request,
+ "Terraform directory request " + request.getRequestId());
+ }
+
+ @AsyncPublisher(
+ operation =
+ @AsyncOperation(
+ channelName =
+ AmqpConstants.QUEUE_NAME_FOR_TERRAFORM_REQUEST_WITH_SCRIPTS,
+ description = "Send terraform request with scripts to rabbitmq queue."))
+ @AmqpAsyncOperationBinding
+ @Override
+ public void sendTerraformRequestWithScripts(@Payload TerraformRequestWithScripts request) {
+ log.info(
+ "Received terraform scripts request with type {} and id {}",
+ request.getRequestType(),
+ request.getRequestId());
+ sendMessageViaExchange(
+ AmqpConstants.ROUTING_KEY_FOR_TERRAFORM_REQUEST_WITH_SCRIPTS,
+ request,
+ "Terraform scripts request " + request.getRequestId());
+ }
+
+ @AsyncPublisher(
+ operation =
+ @AsyncOperation(
+ channelName = AmqpConstants.QUEUE_NAME_FOR_TERRAFORM_REQUEST_WITH_GIT,
+ description =
+ "Send terraform request with scripts git repo to rabbitmq"
+ + " queue."))
+ @AmqpAsyncOperationBinding
+ @Override
+ public void sendTerraformRequestWithScriptsGitRepo(
+ @Payload TerraformRequestWithScriptsGitRepo request) {
+ log.info(
+ "Received terraform git request with type {} and id {}",
+ request.getRequestType(),
+ request.getRequestId());
+ sendMessageViaExchange(
+ AmqpConstants.ROUTING_KEY_FOR_TERRAFORM_REQUEST_WITH_GIT,
+ request,
+ "Terraform git request " + request.getRequestId());
+ }
+
+ @Override
+ public void sendTerraformHealthCheckResult(@Payload TerraBootSystemStatus result) {
+ sendMessageViaExchange(
+ AmqpConstants.ROUTING_KEY_FOR_TERRAFORM_HEALTH_CHECK_RESULT,
+ result,
+ "Terraform health check result " + result.getRequestId());
+ }
+
+ @Override
+ public void sendTerraformPlanResult(@Payload TerraformPlan result) {
+ sendMessageViaExchange(
+ AmqpConstants.ROUTING_KEY_FOR_TERRAFORM_PLAN_RESULT,
+ result,
+ "Terraform plan result " + result.getRequestId());
+ }
+
+ @Override
+ public void sendTerraformValidationResult(@Payload TerraformValidationResult result) {
+ sendMessageViaExchange(
+ AmqpConstants.ROUTING_KEY_FOR_TERRAFORM_VALIDATION_RESULT,
+ result,
+ "Terraform validation result " + result.getRequestId());
+ }
+
+ @Override
+ public void sendTerraformDeploymentResult(@Payload TerraformResult result) {
+ sendMessageViaExchange(
+ AmqpConstants.ROUTING_KEY_FOR_TERRAFORM_DEPLOYMENT_RESULT,
+ result,
+ "Terraform deployment result " + result.getRequestId());
+ }
+
+ private void sendMessageViaExchange(String routingKey, T message, String logPrefix) {
+ try {
+ if (Objects.isNull(message)) {
+ throw new IllegalArgumentException("Message cannot be null");
+ }
+ if (StringUtils.isBlank(routingKey)) {
+ throw new IllegalArgumentException("Routing key cannot be empty");
+ }
+ rabbitTemplate.convertAndSend(
+ AmqpConstants.EXCHANGE_NAME_FOR_TERRAFORM, routingKey, message);
+ log.debug(
+ "{} sent via exchange {} with key {} completed",
+ logPrefix,
+ AmqpConstants.EXCHANGE_NAME_FOR_TERRAFORM,
+ routingKey);
+ } catch (AmqpException e) {
+ String errorMsg =
+ String.format(
+ "Failed to send message to exchange: %s (key: %s). Error: %s",
+ AmqpConstants.EXCHANGE_NAME_FOR_TERRAFORM, routingKey, e.getMessage());
+ log.error("{}", errorMsg, e);
+ throw new AmqpException(errorMsg, e);
+ }
+ }
+}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/TerraBootSystemStatus.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/TerraBootSystemStatus.java
deleted file mode 100644
index ef8b0b69..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/TerraBootSystemStatus.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.boot.models;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotNull;
-import lombok.Data;
-import org.eclipse.xpanse.terra.boot.models.enums.HealthStatus;
-
-/** Describes health status of the system. */
-@Data
-public class TerraBootSystemStatus {
-
- @NotNull
- @Schema(description = "The health status of terra-boot api service.")
- private HealthStatus healthStatus;
-}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/enums/RequestType.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/enums/RequestType.java
new file mode 100644
index 00000000..69c25611
--- /dev/null
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/enums/RequestType.java
@@ -0,0 +1,44 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * SPDX-FileCopyrightText: Huawei Inc.
+ */
+
+package org.eclipse.xpanse.terra.boot.models.enums;
+
+import com.fasterxml.jackson.annotation.JsonCreator;
+import com.fasterxml.jackson.annotation.JsonValue;
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.xpanse.terra.boot.models.exceptions.UnsupportedEnumValueException;
+
+/** The types of terraform request. */
+public enum RequestType {
+ VALIDATE("validate"),
+ PLAN("plan"),
+ DEPLOY("deploy"),
+ MODIFY("modify"),
+ DESTROY("destroy");
+
+ private final String type;
+
+ RequestType(String type) {
+ this.type = type;
+ }
+
+ /** Convert string to RequestType. */
+ @JsonCreator
+ public RequestType getByValue(String value) {
+ for (RequestType type : values()) {
+ if (StringUtils.equalsIgnoreCase(type.type, value)) {
+ return type;
+ }
+ }
+ throw new UnsupportedEnumValueException(
+ String.format("RequestType value %s is not supported.", value));
+ }
+
+ /** For RequestType deserialize. */
+ @JsonValue
+ public String toValue() {
+ return this.type;
+ }
+}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/exceptions/TerraformHealthCheckException.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/exceptions/InvalidTerraformRequestException.java
similarity index 63%
rename from src/main/java/org/eclipse/xpanse/terra/boot/models/exceptions/TerraformHealthCheckException.java
rename to src/main/java/org/eclipse/xpanse/terra/boot/models/exceptions/InvalidTerraformRequestException.java
index 48ba0b80..871f71b2 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/exceptions/TerraformHealthCheckException.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/exceptions/InvalidTerraformRequestException.java
@@ -6,9 +6,9 @@
package org.eclipse.xpanse.terra.boot.models.exceptions;
/** Used to indicate Terraform health check anomalies. */
-public class TerraformHealthCheckException extends RuntimeException {
+public class InvalidTerraformRequestException extends RuntimeException {
- public TerraformHealthCheckException(String message) {
+ public InvalidTerraformRequestException(String message) {
super(message);
}
}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/exceptions/TerraformApiExceptionHandler.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/exceptions/TerraformApiExceptionHandler.java
index f612d87a..b65e1cf7 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/exceptions/TerraformApiExceptionHandler.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/exceptions/TerraformApiExceptionHandler.java
@@ -11,6 +11,7 @@
import lombok.extern.slf4j.Slf4j;
import org.eclipse.xpanse.terra.boot.models.response.Response;
import org.eclipse.xpanse.terra.boot.models.response.ResultType;
+import org.springframework.amqp.AmqpException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.validation.BindingResult;
@@ -42,6 +43,7 @@ public Response handleIllegalArgumentException(IllegalArgumentException ex) {
@ResponseStatus(HttpStatus.BAD_GATEWAY)
@ResponseBody
public Response handleTerraformExecutorException(TerraformExecutorException ex) {
+ log.error("handleTerraformExecutorException: ", ex);
return Response.errorResponse(
ResultType.TERRAFORM_EXECUTION_FAILED, Collections.singletonList(ex.getMessage()));
}
@@ -51,6 +53,7 @@ public Response handleTerraformExecutorException(TerraformExecutorException ex)
@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
@ResponseBody
public Response handleUnsupportedEnumValueException(UnsupportedEnumValueException ex) {
+ log.error("handleUnsupportedEnumValueException: ", ex);
return Response.errorResponse(
ResultType.UNSUPPORTED_ENUM_VALUE, Collections.singletonList(ex.getMessage()));
}
@@ -61,6 +64,7 @@ public Response handleUnsupportedEnumValueException(UnsupportedEnumValueExceptio
@ResponseBody
public Response handleMethodArgumentTypeMismatchException(
MethodArgumentTypeMismatchException ex) {
+ log.error("handleMethodArgumentTypeMismatchException: ", ex);
return Response.errorResponse(
ResultType.UNPROCESSABLE_ENTITY, Collections.singletonList(ex.getMessage()));
}
@@ -89,16 +93,6 @@ public Response handleHttpMessageConversionException(HttpMessageConversionExcept
ResultType.BAD_PARAMETERS, Collections.singletonList(failMessage));
}
- /** Exception handler for TerraformHealthCheckException. */
- @ExceptionHandler({TerraformHealthCheckException.class})
- @ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)
- public Response handleTerraformHealthCheckException(TerraformHealthCheckException ex) {
- log.error("TerraformHealthCheckException: ", ex);
- String failMessage = ex.getMessage();
- return Response.errorResponse(
- ResultType.SERVICE_UNAVAILABLE, Collections.singletonList(failMessage));
- }
-
/** Exception handler for GitRepoCloneException. */
@ExceptionHandler({GitRepoCloneException.class})
@ResponseStatus(HttpStatus.BAD_REQUEST)
@@ -114,6 +108,7 @@ public Response handleGitRepoCloneException(GitRepoCloneException ex) {
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public Response handleInvalidTerraformToolException(InvalidTerraformToolException ex) {
+ log.error("handleInvalidTerraformToolException: ", ex);
return Response.errorResponse(
ResultType.INVALID_TERRAFORM_TOOL, Collections.singletonList(ex.getMessage()));
}
@@ -123,7 +118,28 @@ public Response handleInvalidTerraformToolException(InvalidTerraformToolExceptio
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ResponseBody
public Response handleInvalidTerraformScriptsException(InvalidTerraformScriptsException ex) {
+ log.error("handleInvalidTerraformScriptsException: ", ex);
return Response.errorResponse(
ResultType.INVALID_TERRAFORM_SCRIPTS, Collections.singletonList(ex.getMessage()));
}
+
+ /** Exception handler for InvalidTerraformRequestException. */
+ @ExceptionHandler({InvalidTerraformRequestException.class})
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ResponseBody
+ public Response handleInvalidTerraformRequestException(InvalidTerraformRequestException ex) {
+ log.error("handleInvalidTerraformRequestException: ", ex);
+ return Response.errorResponse(
+ ResultType.INVALID_TERRAFORM_REQUEST, Collections.singletonList(ex.getMessage()));
+ }
+
+ /** Exception handler for AmqpException. */
+ @ExceptionHandler({AmqpException.class})
+ @ResponseStatus(HttpStatus.BAD_REQUEST)
+ @ResponseBody
+ public Response handleAmqpException(AmqpException ex) {
+ log.error("handleAmqpException: ", ex);
+ return Response.errorResponse(
+ ResultType.INVALID_TERRAFORM_REQUEST, Collections.singletonList(ex.getMessage()));
+ }
}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/plan/TerraformPlan.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/plan/TerraformPlan.java
deleted file mode 100644
index 25c2362d..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/plan/TerraformPlan.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.boot.models.plan;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotNull;
-import lombok.Builder;
-import lombok.Data;
-
-/** Data model to represent terraform plan output. */
-@Data
-@Builder
-public class TerraformPlan {
-
- @NotNull
- @Schema(description = "Terraform plan as a JSON string")
- private String plan;
-
- @Schema(description = "The version of the Terraform binary used to execute scripts.")
- private String terraformVersionUsed;
-}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/plan/TerraformPlanFromDirectoryRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/plan/TerraformPlanFromDirectoryRequest.java
deleted file mode 100644
index a1a4607f..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/plan/TerraformPlanFromDirectoryRequest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.boot.models.plan;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Pattern;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-import lombok.Data;
-import org.eclipse.xpanse.terra.boot.terraform.tool.TerraformVersionsHelper;
-
-/** Data model for the generating terraform plan. */
-@Data
-public class TerraformPlanFromDirectoryRequest {
-
- @Schema(description = "Id of the request.")
- private UUID requestId;
-
- @NotNull
- @NotBlank
- @Pattern(regexp = TerraformVersionsHelper.TERRAFORM_REQUIRED_VERSION_REGEX)
- @Schema(description = "The required version of terraform which will execute the scripts.")
- private String terraformVersion;
-
- @NotNull
- @Schema(
- description =
- "Key-value pairs of variables that must be used to execute the "
- + "Terraform request.")
- private Map variables;
-
- @Schema(
- description =
- "Key-value pairs of variables that must be injected as environment "
- + "variables to terraform process.")
- private Map envVariables = new HashMap<>();
-}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/plan/TerraformPlanFromGitRepoRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/plan/TerraformPlanFromGitRepoRequest.java
deleted file mode 100644
index e6900b17..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/plan/TerraformPlanFromGitRepoRequest.java
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.boot.models.plan;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import org.eclipse.xpanse.terra.boot.models.request.git.TerraformScriptGitRepoDetails;
-
-/** Data model for the generating terraform plan using Terraform scripts from a GIT repo. */
-@EqualsAndHashCode(callSuper = true)
-@Data
-public class TerraformPlanFromGitRepoRequest extends TerraformPlanFromDirectoryRequest {
-
- @Schema(description = "GIT Repo details from where the scripts can be fetched.")
- private TerraformScriptGitRepoDetails gitRepoDetails;
-}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/plan/TerraformPlanWithScriptsRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/plan/TerraformPlanWithScriptsRequest.java
deleted file mode 100644
index 25825e65..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/plan/TerraformPlanWithScriptsRequest.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.boot.models.plan;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
-import java.util.Map;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-
-/** Data model for the generating terraform plan. */
-@EqualsAndHashCode(callSuper = true)
-@Data
-public class TerraformPlanWithScriptsRequest extends TerraformPlanFromDirectoryRequest {
-
- @NotNull
- @NotEmpty
- @Schema(
- description =
- "Map stores file name and content of all script files for generating terraform"
- + " plan.")
- private Map scriptFiles;
-}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/TerraformRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/TerraformRequest.java
new file mode 100644
index 00000000..8af21d93
--- /dev/null
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/TerraformRequest.java
@@ -0,0 +1,78 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * SPDX-FileCopyrightText: Huawei Inc.
+ */
+
+package org.eclipse.xpanse.terra.boot.models.request;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Pattern;
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Map;
+import java.util.UUID;
+import lombok.Data;
+import org.eclipse.xpanse.terra.boot.models.enums.RequestType;
+import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformAsyncRequestWithScriptsDirectory;
+import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformRequestWithScriptsDirectory;
+import org.eclipse.xpanse.terra.boot.models.request.git.TerraformAsyncRequestWithScriptsGitRepo;
+import org.eclipse.xpanse.terra.boot.models.request.git.TerraformRequestWithScriptsGitRepo;
+import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformAsyncRequestWithScripts;
+import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformRequestWithScripts;
+import org.eclipse.xpanse.terra.boot.terraform.tool.TerraformVersionsHelper;
+
+/** Data model for the Terraform request. */
+@Data
+@Schema(
+ description = "Terraform request base",
+ subTypes = {
+ TerraformRequestWithScriptsDirectory.class,
+ TerraformAsyncRequestWithScriptsDirectory.class,
+ TerraformRequestWithScripts.class,
+ TerraformAsyncRequestWithScripts.class,
+ TerraformRequestWithScriptsGitRepo.class,
+ TerraformAsyncRequestWithScriptsGitRepo.class,
+ })
+public abstract class TerraformRequest implements Serializable {
+
+ @Serial private static final long serialVersionUID = 10696793105264423L;
+
+ @Schema(description = "Id of the request.")
+ @NotNull
+ private UUID requestId;
+
+ @NotNull
+ @Schema(description = "Type of the terraform request.")
+ private RequestType requestType;
+
+ @NotNull
+ @NotBlank
+ @Pattern(regexp = TerraformVersionsHelper.TERRAFORM_REQUIRED_VERSION_REGEX)
+ @Schema(description = "The required version of terraform which will execute the scripts.")
+ private String terraformVersion;
+
+ @NotNull
+ @Schema(
+ description =
+ "Flag to control if the deployment must only generate the terraform "
+ + "or it must also apply the changes.")
+ private Boolean isPlanOnly;
+
+ @NotNull
+ @Schema(
+ description =
+ "Key-value pairs of variables that must be used to execute the "
+ + "Terraform request.")
+ private Map variables;
+
+ @Schema(
+ description =
+ "Key-value pairs of variables that must be injected as environment "
+ + "variables to terraform process.")
+ private Map envVariables;
+
+ @Schema(description = "Terraform state as a string.")
+ private String tfState;
+}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/TerraformRequestDeserializer.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/TerraformRequestDeserializer.java
new file mode 100644
index 00000000..f8ad23e9
--- /dev/null
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/TerraformRequestDeserializer.java
@@ -0,0 +1,53 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * SPDX-FileCopyrightText: Huawei Inc.
+ */
+
+package org.eclipse.xpanse.terra.boot.models.request;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
+import java.io.IOException;
+import lombok.extern.slf4j.Slf4j;
+import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformAsyncRequestWithScriptsDirectory;
+import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformRequestWithScriptsDirectory;
+import org.eclipse.xpanse.terra.boot.models.request.git.TerraformAsyncRequestWithScriptsGitRepo;
+import org.eclipse.xpanse.terra.boot.models.request.git.TerraformRequestWithScriptsGitRepo;
+import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformAsyncRequestWithScripts;
+
+/** TerraformRequestDeserializer is used to deserialize TerraformRequest. */
+@Slf4j
+public class TerraformRequestDeserializer extends StdDeserializer {
+
+ /** Constructs a new TerraformRequestDeserializer. */
+ public TerraformRequestDeserializer() {
+ super(TerraformRequest.class);
+ }
+
+ @Override
+ public TerraformRequest deserialize(JsonParser p, DeserializationContext ctxt)
+ throws IOException {
+ JsonNode node = p.getCodec().readTree(p);
+ if (node.has("scriptFiles")) {
+ if (node.has("webhookConfig")) {
+ return p.getCodec().treeToValue(node, TerraformAsyncRequestWithScripts.class);
+ }
+ return p.getCodec().treeToValue(node, TerraformAsyncRequestWithScripts.class);
+ } else if (node.has("gitRepoDetails")) {
+ if (node.has("webhookConfig")) {
+ return p.getCodec()
+ .treeToValue(node, TerraformAsyncRequestWithScriptsGitRepo.class);
+ }
+ return p.getCodec().treeToValue(node, TerraformRequestWithScriptsGitRepo.class);
+ } else if (node.has("scriptsDirectory")) {
+ if (node.has("webhookConfig")) {
+ return p.getCodec()
+ .treeToValue(node, TerraformAsyncRequestWithScriptsDirectory.class);
+ }
+ return p.getCodec().treeToValue(node, TerraformRequestWithScriptsDirectory.class);
+ }
+ return p.getCodec().treeToValue(node, TerraformRequest.class);
+ }
+}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformAsyncDestroyFromDirectoryRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformAsyncDestroyFromDirectoryRequest.java
deleted file mode 100644
index 43725005..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformAsyncDestroyFromDirectoryRequest.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.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.terra.boot.models.request.webhook.WebhookConfig;
-
-/** Data model for the terraform async destroy requests. */
-@EqualsAndHashCode(callSuper = true)
-@Data
-public class TerraformAsyncDestroyFromDirectoryRequest
- extends TerraformDestroyFromDirectoryRequest {
-
- @NotNull
- @Schema(description = "Configuration information of webhook.")
- private WebhookConfig webhookConfig;
-}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformAsyncModifyFromDirectoryRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformAsyncModifyFromDirectoryRequest.java
deleted file mode 100644
index 05afb230..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformAsyncModifyFromDirectoryRequest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.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.terra.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/terra/boot/models/request/directory/TerraformAsyncDeployFromDirectoryRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformAsyncRequestWithScriptsDirectory.java
similarity index 53%
rename from src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformAsyncDeployFromDirectoryRequest.java
rename to src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformAsyncRequestWithScriptsDirectory.java
index e9c293b5..3a8ec12e 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformAsyncDeployFromDirectoryRequest.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformAsyncRequestWithScriptsDirectory.java
@@ -7,14 +7,23 @@
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
+import java.io.Serial;
+import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.eclipse.xpanse.terra.boot.models.request.webhook.WebhookConfig;
-/** Data model for the terraform async deploy requests. */
+/**
+ * The terraform async request for executing command based on the directory where the scripts file
+ * exist.
+ */
@EqualsAndHashCode(callSuper = true)
@Data
-public class TerraformAsyncDeployFromDirectoryRequest extends TerraformDeployFromDirectoryRequest {
+@Schema(description = "Terraform async request with directory where scripts files exist")
+public class TerraformAsyncRequestWithScriptsDirectory extends TerraformRequestWithScriptsDirectory
+ implements Serializable {
+
+ @Serial private static final long serialVersionUID = 3604091444011192314L;
@NotNull
@Schema(description = "Configuration information of webhook.")
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformDeployFromDirectoryRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformDeployFromDirectoryRequest.java
deleted file mode 100644
index f723e81c..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformDeployFromDirectoryRequest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.boot.models.request.directory;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Pattern;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-import lombok.Data;
-import org.eclipse.xpanse.terra.boot.terraform.tool.TerraformVersionsHelper;
-
-/** Data model for the terraform deploy requests. */
-@Data
-public class TerraformDeployFromDirectoryRequest {
-
- @Schema(description = "Id of the request")
- private UUID requestId;
-
- @NotNull
- @NotBlank
- @Pattern(regexp = TerraformVersionsHelper.TERRAFORM_REQUIRED_VERSION_REGEX)
- @Schema(description = "The required version of terraform which will execute the scripts.")
- private String terraformVersion;
-
- @NotNull
- @Schema(
- description =
- "Flag to control if the deployment must only generate the terraform "
- + "or it must also apply the changes.")
- private Boolean isPlanOnly;
-
- @NotNull
- @Schema(
- description =
- "Key-value pairs of variables that must be used to execute the "
- + "Terraform request.")
- private Map variables;
-
- @Schema(
- description =
- "Key-value pairs of variables that must be injected as environment "
- + "variables to terraform process.")
- private Map envVariables = new HashMap<>();
-}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformDestroyFromDirectoryRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformDestroyFromDirectoryRequest.java
deleted file mode 100644
index b3957b7d..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformDestroyFromDirectoryRequest.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.boot.models.request.directory;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Pattern;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-import lombok.Data;
-import org.eclipse.xpanse.terra.boot.terraform.tool.TerraformVersionsHelper;
-
-/** Data model for the terraform destroy requests. */
-@Data
-public class TerraformDestroyFromDirectoryRequest {
-
- @Schema(description = "Id of the request")
- private UUID requestId;
-
- @NotNull
- @NotBlank
- @Pattern(regexp = TerraformVersionsHelper.TERRAFORM_REQUIRED_VERSION_REGEX)
- @Schema(description = "The required version of terraform which will execute the scripts.")
- private String terraformVersion;
-
- @NotNull
- @Schema(
- description =
- "Key-value pairs of regular variables that must be used to execute the "
- + "Terraform request.")
- private Map variables;
-
- @Schema(
- description =
- "Key-value pairs of variables that must be injected as environment "
- + "variables to terraform process.")
- private Map envVariables = new HashMap<>();
-}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformModifyFromDirectoryRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformModifyFromDirectoryRequest.java
deleted file mode 100644
index e9ab9749..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformModifyFromDirectoryRequest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.boot.models.request.directory;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Pattern;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
-import lombok.Data;
-import org.eclipse.xpanse.terra.boot.terraform.tool.TerraformVersionsHelper;
-
-/** Data model for the terraform modify requests. */
-@Data
-public class TerraformModifyFromDirectoryRequest {
-
- @Schema(description = "Id of the request")
- private UUID requestId;
-
- @NotNull
- @NotBlank
- @Pattern(regexp = TerraformVersionsHelper.TERRAFORM_REQUIRED_VERSION_REGEX)
- @Schema(description = "The required version of terraform which will execute the scripts.")
- private String terraformVersion;
-
- @NotNull
- @Schema(
- description =
- "Flag to control if the deployment must only generate the terraform "
- + "or it must also apply the changes.")
- private Boolean isPlanOnly;
-
- @NotNull
- @Schema(
- description =
- "Key-value pairs of regular variables that must be used to execute the "
- + "Terraform request.")
- private Map variables;
-
- @Schema(
- description =
- "Key-value pairs of variables that must be injected as environment "
- + "variables to terraform process.")
- private Map envVariables = new HashMap<>();
-}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformRequestWithScriptsDirectory.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformRequestWithScriptsDirectory.java
new file mode 100644
index 00000000..b77d21e0
--- /dev/null
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/directory/TerraformRequestWithScriptsDirectory.java
@@ -0,0 +1,33 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * SPDX-FileCopyrightText: Huawei Inc.
+ */
+
+package org.eclipse.xpanse.terra.boot.models.request.directory;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import io.swagger.v3.oas.annotations.Hidden;
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.io.File;
+import java.util.List;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.eclipse.xpanse.terra.boot.models.request.TerraformRequest;
+
+/**
+ * The terraform request for executing command based on the directory where the scripts file exist.
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(description = "Terraform request with directory where scripts files exist")
+public class TerraformRequestWithScriptsDirectory extends TerraformRequest {
+
+ @NotNull
+ @NotBlank
+ @Schema(description = "Directory where the Terraform scripts files exist.")
+ private String scriptsDirectory;
+
+ @Hidden @JsonIgnore private List scriptFiles;
+}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformAsyncDeployFromGitRepoRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformAsyncDeployFromGitRepoRequest.java
deleted file mode 100644
index bc043535..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformAsyncDeployFromGitRepoRequest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.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.terra.boot.models.request.webhook.WebhookConfig;
-
-/** Data model for the terraform async deploy requests. */
-@EqualsAndHashCode(callSuper = true)
-@Data
-public class TerraformAsyncDeployFromGitRepoRequest extends TerraformDeployFromGitRepoRequest {
-
- @NotNull
- @Schema(description = "Configuration information of webhook.")
- private WebhookConfig webhookConfig;
-}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformAsyncModifyFromGitRepoRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformAsyncModifyFromGitRepoRequest.java
deleted file mode 100644
index 4ac048f0..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformAsyncModifyFromGitRepoRequest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.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.terra.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/terra/boot/models/request/git/TerraformAsyncDestroyFromGitRepoRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformAsyncRequestWithScriptsGitRepo.java
similarity index 56%
rename from src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformAsyncDestroyFromGitRepoRequest.java
rename to src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformAsyncRequestWithScriptsGitRepo.java
index ab1e7b3f..a16bb200 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformAsyncDestroyFromGitRepoRequest.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformAsyncRequestWithScriptsGitRepo.java
@@ -7,14 +7,20 @@
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
+import java.io.Serial;
+import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.eclipse.xpanse.terra.boot.models.request.webhook.WebhookConfig;
-/** Data model for terraform async destroy requests using scripts from a GIT Repo. */
+/** The terraform async request for executing command based on the scripts git repo details. */
@EqualsAndHashCode(callSuper = true)
@Data
-public class TerraformAsyncDestroyFromGitRepoRequest extends TerraformDestroyFromGitRepoRequest {
+@Schema(description = "Terraform request with scripts git repo")
+public class TerraformAsyncRequestWithScriptsGitRepo extends TerraformRequestWithScriptsGitRepo
+ implements Serializable {
+
+ @Serial private static final long serialVersionUID = 6509125273252260415L;
@NotNull
@Schema(description = "Configuration information of webhook.")
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformDeployFromGitRepoRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformDeployFromGitRepoRequest.java
deleted file mode 100644
index ebafa321..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformDeployFromGitRepoRequest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.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.terra.boot.models.request.directory.TerraformDeployFromDirectoryRequest;
-
-/** Data model for terraform deploy requests using scripts from a GIT Repo. */
-@EqualsAndHashCode(callSuper = true)
-@Data
-public class TerraformDeployFromGitRepoRequest extends TerraformDeployFromDirectoryRequest {
-
- @NotNull
- @Schema(description = "GIT Repo details from where the scripts can be fetched.")
- private TerraformScriptGitRepoDetails gitRepoDetails;
-}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformDestroyFromGitRepoRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformDestroyFromGitRepoRequest.java
deleted file mode 100644
index 0193fbd4..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformDestroyFromGitRepoRequest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.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.terra.boot.models.request.directory.TerraformDestroyFromDirectoryRequest;
-
-/** Data model for terraform destroy requests using scripts from a GIT Repo. */
-@EqualsAndHashCode(callSuper = true)
-@Data
-public class TerraformDestroyFromGitRepoRequest extends TerraformDestroyFromDirectoryRequest {
-
- @Schema(description = "GIT Repo details from where the scripts can be fetched.")
- private TerraformScriptGitRepoDetails gitRepoDetails;
-
- @NotNull
- @Schema(description = "The .tfState file content after deployment")
- private String tfState;
-}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformModifyFromGitRepoRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformModifyFromGitRepoRequest.java
deleted file mode 100644
index 229b2dee..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformModifyFromGitRepoRequest.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.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.terra.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.")
- private TerraformScriptGitRepoDetails gitRepoDetails;
-
- @NotNull
- @Schema(description = "The .tfState file content after deployment")
- private String tfState;
-}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformRequestWithScriptsGitRepo.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformRequestWithScriptsGitRepo.java
new file mode 100644
index 00000000..cafca742
--- /dev/null
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformRequestWithScriptsGitRepo.java
@@ -0,0 +1,27 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * SPDX-FileCopyrightText: Huawei Inc.
+ */
+
+package org.eclipse.xpanse.terra.boot.models.request.git;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import java.io.Serial;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.eclipse.xpanse.terra.boot.models.request.TerraformRequest;
+
+/** The terraform request for executing command based on the scripts git repo details. */
+@EqualsAndHashCode(callSuper = true)
+@Data
+@Schema(description = "Terraform async request with scripts git repo")
+public class TerraformRequestWithScriptsGitRepo extends TerraformRequest implements Serializable {
+
+ @Serial private static final long serialVersionUID = -9154036923917579783L;
+
+ @NotNull
+ @Schema(description = "GIT Repo details from where the scripts can be fetched.")
+ private TerraformScriptsGitRepoDetails gitRepoDetails;
+}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformScriptGitRepoDetails.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformScriptsGitRepoDetails.java
similarity index 80%
rename from src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformScriptGitRepoDetails.java
rename to src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformScriptsGitRepoDetails.java
index 5db435a5..7a20d90b 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformScriptGitRepoDetails.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/git/TerraformScriptsGitRepoDetails.java
@@ -7,11 +7,15 @@
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
+import java.io.Serial;
+import java.io.Serializable;
import lombok.Data;
/** Data model for defining the GIT repo information to fetch the scripts. */
@Data
-public class TerraformScriptGitRepoDetails {
+public class TerraformScriptsGitRepoDetails implements Serializable {
+
+ @Serial private static final long serialVersionUID = -8723117896885097332L;
@NotNull
@Schema(description = "url of the GIT repo. This repo will be cloned.")
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformAsyncDestroyFromScriptsRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformAsyncDestroyFromScriptsRequest.java
deleted file mode 100644
index d79a0c33..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformAsyncDestroyFromScriptsRequest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.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.terra.boot.models.request.webhook.WebhookConfig;
-
-/** Data model for the terraform async destroy requests. */
-@EqualsAndHashCode(callSuper = true)
-@Data
-public class TerraformAsyncDestroyFromScriptsRequest extends TerraformDestroyWithScriptsRequest {
-
- @NotNull
- @Schema(description = "Configuration information of webhook.")
- private WebhookConfig webhookConfig;
-}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformAsyncModifyFromScriptsRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformAsyncModifyFromScriptsRequest.java
deleted file mode 100644
index 9d74ff8e..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformAsyncModifyFromScriptsRequest.java
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.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.terra.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/terra/boot/models/request/scripts/TerraformAsyncDeployFromScriptsRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformAsyncRequestWithScripts.java
similarity index 57%
rename from src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformAsyncDeployFromScriptsRequest.java
rename to src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformAsyncRequestWithScripts.java
index 1e9f9202..6b938612 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformAsyncDeployFromScriptsRequest.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformAsyncRequestWithScripts.java
@@ -7,14 +7,20 @@
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
+import java.io.Serial;
+import java.io.Serializable;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.eclipse.xpanse.terra.boot.models.request.webhook.WebhookConfig;
-/** Data model for the terraform async deploy requests. */
+/** The terraform async request for executing command based on the scripts files. */
@EqualsAndHashCode(callSuper = true)
@Data
-public class TerraformAsyncDeployFromScriptsRequest extends TerraformDeployWithScriptsRequest {
+@Schema(description = "Terraform async request with scripts files")
+public class TerraformAsyncRequestWithScripts extends TerraformRequestWithScripts
+ implements Serializable {
+
+ @Serial private static final long serialVersionUID = -751134396582688022L;
@NotNull
@Schema(description = "Configuration information of webhook.")
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformDestroyWithScriptsRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformDestroyWithScriptsRequest.java
deleted file mode 100644
index 21f36806..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformDestroyWithScriptsRequest.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.boot.models.request.scripts;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
-import java.util.Map;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformDestroyFromDirectoryRequest;
-
-/** Terraform uses the request object destroy by the script. */
-@EqualsAndHashCode(callSuper = true)
-@Data
-public class TerraformDestroyWithScriptsRequest extends TerraformDestroyFromDirectoryRequest {
-
- @NotNull
- @NotEmpty
- @Schema(
- description =
- "Map stores file name and content of all script files for destroy request.")
- private Map scriptFiles;
-
- @NotNull
- @Schema(description = "The .tfState file content after deployment")
- private String tfState;
-}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformModifyWithScriptsRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformModifyWithScriptsRequest.java
deleted file mode 100644
index de6c52a5..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformModifyWithScriptsRequest.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.boot.models.request.scripts;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
-import java.util.Map;
-import java.util.UUID;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformModifyFromDirectoryRequest;
-
-/** Terraform uses the request object modify by the script. */
-@EqualsAndHashCode(callSuper = true)
-@Data
-public class TerraformModifyWithScriptsRequest extends TerraformModifyFromDirectoryRequest {
-
- @Schema(description = "Id of the request.")
- private UUID taskId;
-
- @NotNull
- @NotEmpty
- @Schema(
- description =
- "Map stores file name and content of all script files for modify request.")
- private Map scriptFiles;
-
- @NotNull
- @Schema(description = "The .tfState file content after deployment")
- private String tfState;
-}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformDeployWithScriptsRequest.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformRequestWithScripts.java
similarity index 59%
rename from src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformDeployWithScriptsRequest.java
rename to src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformRequestWithScripts.java
index ac0aa2b2..2a11cd12 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformDeployWithScriptsRequest.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/scripts/TerraformRequestWithScripts.java
@@ -8,15 +8,20 @@
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
+import java.io.Serial;
+import java.io.Serializable;
import java.util.Map;
import lombok.Data;
import lombok.EqualsAndHashCode;
-import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformDeployFromDirectoryRequest;
+import org.eclipse.xpanse.terra.boot.models.request.TerraformRequest;
-/** Terraform uses the request object deployed by the script. */
+/** The terraform request for executing command based on the scripts files. */
@EqualsAndHashCode(callSuper = true)
@Data
-public class TerraformDeployWithScriptsRequest extends TerraformDeployFromDirectoryRequest {
+@Schema(description = "Terraform request with scripts files")
+public class TerraformRequestWithScripts extends TerraformRequest implements Serializable {
+
+ @Serial private static final long serialVersionUID = 7464467836284819109L;
@NotNull
@NotEmpty
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/webhook/WebhookConfig.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/webhook/WebhookConfig.java
index 84205ba5..333c52eb 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/request/webhook/WebhookConfig.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/request/webhook/WebhookConfig.java
@@ -7,12 +7,16 @@
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
+import java.io.Serial;
+import java.io.Serializable;
import lombok.Data;
import org.eclipse.xpanse.terra.boot.models.enums.AuthType;
/** Configuration information class of webhook. */
@Data
-public class WebhookConfig {
+public class WebhookConfig implements Serializable {
+
+ @Serial private static final long serialVersionUID = -4689930966905036460L;
@NotNull
@Schema(description = "Callback address after deployment/destroy is completed.")
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/response/ResultType.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/response/ResultType.java
index 736d62c7..890a3ed5 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/response/ResultType.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/response/ResultType.java
@@ -17,9 +17,11 @@ public enum ResultType {
UNSUPPORTED_ENUM_VALUE("Unsupported Enum Value"),
SERVICE_UNAVAILABLE("Service Unavailable"),
UNAUTHORIZED("Unauthorized"),
+ INVALID_TERRAFORM_REQUEST("Invalid Terraform Request"),
INVALID_GIT_REPO_DETAILS("Invalid Git Repo Details"),
INVALID_TERRAFORM_TOOL("Invalid Terraform Tool"),
INVALID_TERRAFORM_SCRIPTS("Invalid Terraform Scripts"),
+ SEND_AMQP_MESSAGE_FAILED("Send Amqp Message Failed"),
RESULT_ALREADY_RETURNED_OR_REQUEST_ID_INVALID("Result Already Returned or RequestId Invalid");
private final String value;
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/response/TerraBootSystemStatus.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/response/TerraBootSystemStatus.java
new file mode 100644
index 00000000..55a735a0
--- /dev/null
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/response/TerraBootSystemStatus.java
@@ -0,0 +1,41 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * SPDX-FileCopyrightText: Huawei Inc.
+ */
+
+package org.eclipse.xpanse.terra.boot.models.response;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.UUID;
+import lombok.Data;
+import org.eclipse.xpanse.terra.boot.models.enums.HealthStatus;
+
+/** Describes health status of the system. */
+@Data
+public class TerraBootSystemStatus implements Serializable {
+
+ @Serial private static final long serialVersionUID = -6039352796356100544L;
+
+ @NotNull
+ @Schema(description = "ID of the request.")
+ private UUID requestId;
+
+ @NotNull
+ @Schema(description = "The health status of terra-boot service.")
+ private HealthStatus healthStatus;
+
+ @NotBlank
+ @Schema(description = "The service type of terra-boot.")
+ private String serviceType;
+
+ @NotBlank
+ @Schema(description = "The url of terra-boot service.")
+ private String serviceUrl;
+
+ @Schema(description = "The error message of terra-boot service.")
+ private String errorMessage;
+}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/response/TerraformPlan.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/response/TerraformPlan.java
new file mode 100644
index 00000000..42eed2c1
--- /dev/null
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/response/TerraformPlan.java
@@ -0,0 +1,40 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * SPDX-FileCopyrightText: Huawei Inc.
+ */
+
+package org.eclipse.xpanse.terra.boot.models.response;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.UUID;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/** Data model to represent terraform plan output. */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class TerraformPlan implements Serializable {
+
+ @Serial private static final long serialVersionUID = 4957985190544009199L;
+
+ @NotNull
+ @Schema(description = "The id of the Terraform plan request")
+ private UUID requestId;
+
+ @NotNull
+ @Schema(description = "Terraform plan as a JSON string")
+ private String plan;
+
+ @Schema(description = "The version of the Terraform binary used to execute scripts.")
+ private String terraformVersionUsed;
+
+ @Schema(description = "The error message of executing terraform plan command.")
+ private String errorMessage;
+}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/response/TerraformResult.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/response/TerraformResult.java
index 18406d1b..6950e3b2 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/response/TerraformResult.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/response/TerraformResult.java
@@ -7,16 +7,25 @@
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
+import java.io.Serial;
+import java.io.Serializable;
import java.util.Map;
import java.util.UUID;
+import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
+import lombok.NoArgsConstructor;
/** Data model for the Terraform command execution results. */
@Data
@Builder
-public class TerraformResult {
+@AllArgsConstructor
+@NoArgsConstructor
+public class TerraformResult implements Serializable {
+ @Serial private static final long serialVersionUID = 5138160212124102583L;
+
+ @NotNull
@Schema(description = "Id of the request")
private UUID requestId;
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/validation/TerraformValidateDiagnostics.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/response/validation/TerraformValidateDiagnostics.java
similarity index 88%
rename from src/main/java/org/eclipse/xpanse/terra/boot/models/validation/TerraformValidateDiagnostics.java
rename to src/main/java/org/eclipse/xpanse/terra/boot/models/response/validation/TerraformValidateDiagnostics.java
index 3a012fe9..1562aab4 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/validation/TerraformValidateDiagnostics.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/response/validation/TerraformValidateDiagnostics.java
@@ -3,7 +3,7 @@
* SPDX-FileCopyrightText: Huawei Inc.
*/
-package org.eclipse.xpanse.terra.boot.models.validation;
+package org.eclipse.xpanse.terra.boot.models.response.validation;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.v3.oas.annotations.media.Schema;
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/models/validation/TerraformValidationResult.java b/src/main/java/org/eclipse/xpanse/terra/boot/models/response/validation/TerraformValidationResult.java
similarity index 64%
rename from src/main/java/org/eclipse/xpanse/terra/boot/models/validation/TerraformValidationResult.java
rename to src/main/java/org/eclipse/xpanse/terra/boot/models/response/validation/TerraformValidationResult.java
index b89ce47b..2d5b1925 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/models/validation/TerraformValidationResult.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/models/response/validation/TerraformValidationResult.java
@@ -3,18 +3,27 @@
* SPDX-FileCopyrightText: Huawei Inc.
*/
-package org.eclipse.xpanse.terra.boot.models.validation;
+package org.eclipse.xpanse.terra.boot.models.response.validation;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
+import java.io.Serial;
+import java.io.Serializable;
import java.util.List;
+import java.util.UUID;
import lombok.Data;
/** Defines the Terraform validation result. */
@Data
@JsonIgnoreProperties(ignoreUnknown = true)
-public class TerraformValidationResult {
+public class TerraformValidationResult implements Serializable {
+
+ @Serial private static final long serialVersionUID = -4992253090497952906L;
+
+ @NotNull
+ @Schema(description = "The request ID of the Terraform scripts validation.")
+ private UUID requestId;
@NotNull
@Schema(description = "Defines if the Terraform scripts is valid.")
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/security/oauth2/config/Oauth2WebSecurityConfig.java b/src/main/java/org/eclipse/xpanse/terra/boot/security/oauth2/config/Oauth2WebSecurityConfig.java
index 8cd13e9f..7065c41a 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/security/oauth2/config/Oauth2WebSecurityConfig.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/security/oauth2/config/Oauth2WebSecurityConfig.java
@@ -63,6 +63,9 @@ public class Oauth2WebSecurityConfig {
@Value("${spring.security.oauth2.resourceserver.opaquetoken.client-secret}")
private String clientSecret;
+ @Value("${springwolf.path.base:/springwolf}")
+ private String springwolfPathBase;
+
@Resource private Oauth2JwtDecoder oauth2JwtDecoder;
/**
@@ -81,6 +84,9 @@ public SecurityFilterChain apiFilterChain(HttpSecurity http) throws Exception {
arc -> {
arc.requestMatchers(AntPathRequestMatcher.antMatcher("/swagger-ui/**"))
.permitAll();
+ arc.requestMatchers(
+ AntPathRequestMatcher.antMatcher(springwolfPathBase + "/**"))
+ .permitAll();
arc.requestMatchers(AntPathRequestMatcher.antMatcher("/v3/**")).permitAll();
arc.requestMatchers(AntPathRequestMatcher.antMatcher("/error")).permitAll();
arc.anyRequest().authenticated();
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformGitRepoService.java b/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformGitRepoService.java
deleted file mode 100644
index 1eb55446..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformGitRepoService.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.boot.terraform.service;
-
-import jakarta.annotation.Resource;
-import java.io.File;
-import java.util.HashMap;
-import java.util.List;
-import java.util.UUID;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
-import org.eclipse.xpanse.terra.boot.async.TaskConfiguration;
-import org.eclipse.xpanse.terra.boot.models.plan.TerraformPlan;
-import org.eclipse.xpanse.terra.boot.models.plan.TerraformPlanFromGitRepoRequest;
-import org.eclipse.xpanse.terra.boot.models.request.git.TerraformAsyncDeployFromGitRepoRequest;
-import org.eclipse.xpanse.terra.boot.models.request.git.TerraformAsyncDestroyFromGitRepoRequest;
-import org.eclipse.xpanse.terra.boot.models.request.git.TerraformAsyncModifyFromGitRepoRequest;
-import org.eclipse.xpanse.terra.boot.models.request.git.TerraformDeployFromGitRepoRequest;
-import org.eclipse.xpanse.terra.boot.models.request.git.TerraformDestroyFromGitRepoRequest;
-import org.eclipse.xpanse.terra.boot.models.request.git.TerraformModifyFromGitRepoRequest;
-import org.eclipse.xpanse.terra.boot.models.request.git.TerraformScriptGitRepoDetails;
-import org.eclipse.xpanse.terra.boot.models.response.TerraformResult;
-import org.eclipse.xpanse.terra.boot.models.validation.TerraformValidationResult;
-import org.springframework.scheduling.annotation.Async;
-import org.springframework.stereotype.Component;
-import org.springframework.web.client.RestClientException;
-import org.springframework.web.client.RestTemplate;
-
-/** Bean to manage all Terraform execution using scripts from a GIT Repo. */
-@Slf4j
-@Component
-public class TerraformGitRepoService {
-
- @Resource private RestTemplate restTemplate;
- @Resource private TerraformScriptsHelper scriptsHelper;
- @Resource private TerraformDirectoryService directoryService;
- @Resource private TerraformResultPersistenceManage terraformResultPersistenceManage;
-
- /** Method of deployment a service using a script. */
- public TerraformValidationResult validateWithScripts(
- TerraformDeployFromGitRepoRequest request) {
- String taskWorkspace = scriptsHelper.buildTaskWorkspace(UUID.randomUUID().toString());
- scriptsHelper.prepareDeploymentFilesWithGitRepo(
- taskWorkspace, request.getGitRepoDetails(), null);
- String scriptsPath =
- getScriptsLocationInTaskWorkspace(request.getGitRepoDetails(), taskWorkspace);
- return directoryService.tfValidateFromDirectory(scriptsPath, request.getTerraformVersion());
- }
-
- /** Method to get terraform plan. */
- public TerraformPlan getTerraformPlanFromGitRepo(
- TerraformPlanFromGitRepoRequest request, UUID uuid) {
- String taskWorkspace = scriptsHelper.buildTaskWorkspace(uuid.toString());
- scriptsHelper.prepareDeploymentFilesWithGitRepo(
- taskWorkspace, request.getGitRepoDetails(), null);
- String scriptsPath =
- getScriptsLocationInTaskWorkspace(request.getGitRepoDetails(), taskWorkspace);
- return directoryService.getTerraformPlanFromDirectory(request, scriptsPath);
- }
-
- /** Method of deployment a service using a script. */
- public TerraformResult deployFromGitRepo(TerraformDeployFromGitRepoRequest request, UUID uuid) {
- String taskWorkspace = scriptsHelper.buildTaskWorkspace(uuid.toString());
- List scriptFiles =
- scriptsHelper.prepareDeploymentFilesWithGitRepo(
- taskWorkspace, request.getGitRepoDetails(), null);
- String scriptsPath =
- getScriptsLocationInTaskWorkspace(request.getGitRepoDetails(), taskWorkspace);
- TerraformResult result =
- directoryService.deployFromDirectory(request, scriptsPath, scriptFiles);
- scriptsHelper.deleteTaskWorkspace(taskWorkspace);
- return result;
- }
-
- /** Method of modify a service using a script. */
- public TerraformResult modifyFromGitRepo(TerraformModifyFromGitRepoRequest request, UUID uuid) {
- String taskWorkspace = scriptsHelper.buildTaskWorkspace(uuid.toString());
- List scriptFiles =
- scriptsHelper.prepareDeploymentFilesWithGitRepo(
- taskWorkspace, request.getGitRepoDetails(), request.getTfState());
- String scriptsPath =
- getScriptsLocationInTaskWorkspace(request.getGitRepoDetails(), taskWorkspace);
- TerraformResult result =
- directoryService.modifyFromDirectory(request, scriptsPath, scriptFiles);
- scriptsHelper.deleteTaskWorkspace(taskWorkspace);
- return result;
- }
-
- /** Method of destroy a service using a script. */
- public TerraformResult destroyFromGitRepo(
- TerraformDestroyFromGitRepoRequest request, UUID uuid) {
- String taskWorkspace = scriptsHelper.buildTaskWorkspace(uuid.toString());
- List scriptFiles =
- scriptsHelper.prepareDeploymentFilesWithGitRepo(
- taskWorkspace, request.getGitRepoDetails(), request.getTfState());
- String scriptsPath =
- getScriptsLocationInTaskWorkspace(request.getGitRepoDetails(), taskWorkspace);
- TerraformResult result =
- directoryService.destroyFromDirectory(request, scriptsPath, scriptFiles);
- scriptsHelper.deleteTaskWorkspace(taskWorkspace);
- return result;
- }
-
- /** Async deploy a source by terraform. */
- @Async(TaskConfiguration.TASK_EXECUTOR_NAME)
- public void asyncDeployFromGitRepo(
- TerraformAsyncDeployFromGitRepoRequest asyncDeployRequest, UUID uuid) {
- TerraformResult result;
- try {
- result = deployFromGitRepo(asyncDeployRequest, uuid);
- } catch (RuntimeException e) {
- result =
- TerraformResult.builder()
- .commandStdOutput(null)
- .commandStdError(e.getMessage())
- .isCommandSuccessful(false)
- .terraformState(null)
- .generatedFileContentMap(new HashMap<>())
- .build();
- }
- result.setRequestId(asyncDeployRequest.getRequestId());
- String url = asyncDeployRequest.getWebhookConfig().getUrl();
- log.info("Deployment service complete, callback POST url:{}, requestBody:{}", url, result);
- sendTerraformResult(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()
- .commandStdOutput(null)
- .commandStdError(e.getMessage())
- .isCommandSuccessful(false)
- .terraformState(null)
- .generatedFileContentMap(new HashMap<>())
- .build();
- }
- result.setRequestId(asyncModifyRequest.getRequestId());
- String url = asyncModifyRequest.getWebhookConfig().getUrl();
- log.info("Modify service complete, callback POST url:{}, requestBody:{}", url, result);
- sendTerraformResult(url, result);
- }
-
- /** Async destroy resource of the service. */
- @Async(TaskConfiguration.TASK_EXECUTOR_NAME)
- public void asyncDestroyFromGitRepo(
- TerraformAsyncDestroyFromGitRepoRequest request, UUID uuid) {
- TerraformResult result;
- try {
- result = destroyFromGitRepo(request, uuid);
- } catch (RuntimeException e) {
- result =
- TerraformResult.builder()
- .commandStdOutput(null)
- .commandStdError(e.getMessage())
- .isCommandSuccessful(false)
- .terraformState(null)
- .generatedFileContentMap(new HashMap<>())
- .build();
- }
- result.setRequestId(request.getRequestId());
- String url = request.getWebhookConfig().getUrl();
- log.info("Destroy service complete, callback POST url:{}, requestBody:{}", url, result);
- sendTerraformResult(url, result);
- }
-
- private void sendTerraformResult(String url, TerraformResult result) {
- try {
- restTemplate.postForLocation(url, result);
- } catch (RestClientException e) {
- log.error("error while sending terraform result", e);
- terraformResultPersistenceManage.persistTerraformResult(result);
- }
- }
-
- private String getScriptsLocationInTaskWorkspace(
- TerraformScriptGitRepoDetails terraformScriptGitRepoDetails, String taskWorkSpace) {
- if (StringUtils.isNotBlank(terraformScriptGitRepoDetails.getScriptPath())) {
- return taskWorkSpace + File.separator + terraformScriptGitRepoDetails.getScriptPath();
- }
- return taskWorkSpace;
- }
-}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformRequestService.java b/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformRequestService.java
new file mode 100644
index 00000000..39c8aebc
--- /dev/null
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformRequestService.java
@@ -0,0 +1,291 @@
+/*
+ * SPDX-License-Identifier: Apache-2.0
+ * SPDX-FileCopyrightText: Huawei Inc.
+ */
+
+package org.eclipse.xpanse.terra.boot.terraform.service;
+
+import static org.eclipse.xpanse.terra.boot.logging.CustomRequestIdGenerator.REQUEST_ID;
+
+import jakarta.annotation.Resource;
+import java.io.File;
+import java.util.List;
+import java.util.UUID;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.xpanse.terra.boot.models.enums.RequestType;
+import org.eclipse.xpanse.terra.boot.models.exceptions.InvalidTerraformRequestException;
+import org.eclipse.xpanse.terra.boot.models.exceptions.UnsupportedEnumValueException;
+import org.eclipse.xpanse.terra.boot.models.request.TerraformRequest;
+import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformAsyncRequestWithScriptsDirectory;
+import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformRequestWithScriptsDirectory;
+import org.eclipse.xpanse.terra.boot.models.request.git.TerraformAsyncRequestWithScriptsGitRepo;
+import org.eclipse.xpanse.terra.boot.models.request.git.TerraformRequestWithScriptsGitRepo;
+import org.eclipse.xpanse.terra.boot.models.request.git.TerraformScriptsGitRepoDetails;
+import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformAsyncRequestWithScripts;
+import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformRequestWithScripts;
+import org.eclipse.xpanse.terra.boot.models.response.TerraBootSystemStatus;
+import org.eclipse.xpanse.terra.boot.models.response.TerraformPlan;
+import org.eclipse.xpanse.terra.boot.models.response.TerraformResult;
+import org.eclipse.xpanse.terra.boot.models.response.validation.TerraformValidateDiagnostics;
+import org.eclipse.xpanse.terra.boot.models.response.validation.TerraformValidationResult;
+import org.slf4j.MDC;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+/** Terraform service classes are deployed form Directory. */
+@Slf4j
+@Service
+public class TerraformRequestService {
+
+ @Resource private TerraformScriptsDirectoryService terraformScriptsDirectoryService;
+ @Resource private TerraformScriptsDirectoryHelper scriptsDirectoryHelper;
+
+ /** Handle the request of health check. */
+ public TerraBootSystemStatus healthCheck(UUID requestId) {
+ MDC.put(REQUEST_ID, requestId.toString());
+ return terraformScriptsDirectoryService.tfHealthCheck(requestId);
+ }
+
+ /**
+ * Handle terraform validate request and return result.
+ *
+ * @param request request.
+ * @return TerraformValidationResult.
+ */
+ public TerraformValidationResult handleTerraformValidateRequest(TerraformRequest request) {
+ TerraformRequestWithScriptsDirectory requestWithDirectory =
+ convertRequestWithScriptsDirectory(request);
+ return terraformScriptsDirectoryService.tfValidateWithScriptsDirectory(
+ requestWithDirectory);
+ }
+
+ /**
+ * Handle the plan request and return the TerraformPlan.
+ *
+ * @param request request.
+ * @return TerraformPlan.
+ */
+ public TerraformPlan handleTerraformPlanRequest(TerraformRequest request) {
+ TerraformRequestWithScriptsDirectory requestWithDirectory =
+ convertRequestWithScriptsDirectory(request);
+ return terraformScriptsDirectoryService.getTerraformPlanWithScriptsDirectory(
+ requestWithDirectory);
+ }
+
+ /**
+ * Handle the terraform request and return the TerraformResult.
+ *
+ * @param request request.
+ * @return TerraformResult.
+ */
+ public TerraformResult handleTerraformDeploymentRequest(TerraformRequest request) {
+ TerraformRequestWithScriptsDirectory requestWithDirectory =
+ convertRequestWithScriptsDirectory(request);
+ switch (request.getRequestType()) {
+ case RequestType.DEPLOY -> {
+ return terraformScriptsDirectoryService.deployWithScriptsDirectory(
+ requestWithDirectory);
+ }
+ case RequestType.MODIFY -> {
+ return terraformScriptsDirectoryService.modifyWithScriptsDirectory(
+ requestWithDirectory);
+ }
+ case RequestType.DESTROY -> {
+ return terraformScriptsDirectoryService.destroyWithScriptsDirectory(
+ requestWithDirectory);
+ }
+ default ->
+ throw new UnsupportedEnumValueException(
+ String.format(
+ "RequestType value %s is not supported.",
+ request.getRequestType().toValue()));
+ }
+ }
+
+ /**
+ * Process the async deployment request.
+ *
+ * @param request request.
+ */
+ public void processAsyncDeploymentRequest(TerraformRequest request) {
+ TerraformAsyncRequestWithScriptsDirectory requestWithDirectory =
+ (TerraformAsyncRequestWithScriptsDirectory)
+ convertRequestWithScriptsDirectory(request);
+ switch (request.getRequestType()) {
+ case RequestType.DEPLOY ->
+ terraformScriptsDirectoryService.asyncDeployWithScriptsDirectory(
+ requestWithDirectory);
+ case RequestType.MODIFY ->
+ terraformScriptsDirectoryService.asyncModifyWithScriptsDirectory(
+ requestWithDirectory);
+ case RequestType.DESTROY ->
+ terraformScriptsDirectoryService.asyncDestroyWithScriptsDirectory(
+ requestWithDirectory);
+ default ->
+ throw new UnsupportedEnumValueException(
+ String.format(
+ "RequestType value %s is not supported.",
+ request.getRequestType().toValue()));
+ }
+ }
+
+ private TerraformRequestWithScriptsDirectory convertRequestWithScriptsDirectory(
+ TerraformRequest request) {
+ validateTerraformRequest(request);
+ return switch (request) {
+ case TerraformRequestWithScriptsDirectory requestWithDirectory -> requestWithDirectory;
+ case TerraformRequestWithScriptsGitRepo requestWithScriptsGitRepo ->
+ convertRequestWithGitToDirectory(requestWithScriptsGitRepo);
+ case TerraformRequestWithScripts requestWithScripts ->
+ convertRequestWithScriptsToDirectory(requestWithScripts);
+ default ->
+ throw new UnsupportedEnumValueException(
+ String.format(
+ "RequestType value %s is not supported.",
+ request.getRequestType().toValue()));
+ };
+ }
+
+ /**
+ * Validate the terraform request.
+ *
+ * @param request request.
+ */
+ private void validateTerraformRequest(TerraformRequest request) {
+ MDC.put(REQUEST_ID, request.getRequestId().toString());
+ if (RequestType.DESTROY == request.getRequestType()
+ || RequestType.MODIFY == request.getRequestType()) {
+ if (StringUtils.isBlank(request.getTfState())) {
+ String errorMessage =
+ String.format(
+ "Terraform state is required for request with order type %s.",
+ request.getRequestType());
+ log.error(errorMessage);
+ throw new InvalidTerraformRequestException(errorMessage);
+ }
+ }
+ if (request instanceof TerraformRequestWithScriptsDirectory requestWithDirectory) {
+ List scriptFiles =
+ scriptsDirectoryHelper.getDeploymentFilesFromTaskWorkspace(
+ requestWithDirectory.getScriptsDirectory());
+ if (CollectionUtils.isEmpty(scriptFiles)) {
+ String errorMessage =
+ String.format(
+ "No Terraform scripts files found in the directory %s.",
+ requestWithDirectory.getScriptsDirectory());
+ log.error(errorMessage);
+ throw new InvalidTerraformRequestException(errorMessage);
+ }
+ requestWithDirectory.setScriptFiles(scriptFiles);
+ }
+ }
+
+ /**
+ * Get the error validate result.
+ *
+ * @param request request
+ * @param e exception
+ * @return TerraformValidationResult
+ */
+ public TerraformValidationResult getErrorValidateResult(TerraformRequest request, Exception e) {
+ TerraformValidationResult result = new TerraformValidationResult();
+ result.setRequestId(request.getRequestId());
+ result.setValid(false);
+ result.setTerraformVersionUsed(request.getTerraformVersion());
+ TerraformValidateDiagnostics diagnostics = new TerraformValidateDiagnostics();
+ diagnostics.setDetail(e.getMessage());
+ result.setDiagnostics(List.of(diagnostics));
+ return result;
+ }
+
+ /**
+ * Get the error plan result.
+ *
+ * @param request request
+ * @param e exception
+ * @return TerraformPlan
+ */
+ public TerraformPlan getErrorPlanResult(TerraformRequest request, Exception e) {
+ return TerraformPlan.builder()
+ .requestId(request.getRequestId())
+ .terraformVersionUsed(request.getTerraformVersion())
+ .errorMessage(e.getMessage())
+ .build();
+ }
+
+ /**
+ * Get the error deployment result.
+ *
+ * @param request request
+ * @param e exception
+ * @return TerraformResult
+ */
+ public TerraformResult getErrorDeploymentResult(TerraformRequest request, Exception e) {
+ return TerraformResult.builder()
+ .requestId(request.getRequestId())
+ .terraformVersionUsed(request.getTerraformVersion())
+ .isCommandSuccessful(false)
+ .commandStdError(e.getMessage())
+ .build();
+ }
+
+ /**
+ * Transform TerraformRequestWithScriptsGitRepo to TerraformRequestWithScriptsDirectory.
+ *
+ * @param request request with git repo.
+ * @return request with scripts directory.
+ */
+ private TerraformRequestWithScriptsDirectory convertRequestWithGitToDirectory(
+ TerraformRequestWithScriptsGitRepo request) {
+ TerraformRequestWithScriptsDirectory requestWithDirectory =
+ new TerraformRequestWithScriptsDirectory();
+ if (request instanceof TerraformAsyncRequestWithScriptsGitRepo) {
+ requestWithDirectory = new TerraformAsyncRequestWithScriptsDirectory();
+ }
+ BeanUtils.copyProperties(request, requestWithDirectory);
+ String taskWorkspace =
+ scriptsDirectoryHelper.buildTaskWorkspace(request.getRequestId().toString());
+ String scriptsPath =
+ getScriptsLocationInTaskWorkspace(request.getGitRepoDetails(), taskWorkspace);
+ requestWithDirectory.setScriptsDirectory(scriptsPath);
+ List scriptFiles =
+ scriptsDirectoryHelper.prepareDeploymentFilesWithGitRepo(
+ taskWorkspace, request.getGitRepoDetails(), request.getTfState());
+ requestWithDirectory.setScriptFiles(scriptFiles);
+ return requestWithDirectory;
+ }
+
+ private String getScriptsLocationInTaskWorkspace(
+ TerraformScriptsGitRepoDetails scriptsGitRepoDetails, String taskWorkSpace) {
+ if (StringUtils.isNotBlank(scriptsGitRepoDetails.getScriptPath())) {
+ return taskWorkSpace + File.separator + scriptsGitRepoDetails.getScriptPath();
+ }
+ return taskWorkSpace;
+ }
+
+ /**
+ * Transform TerraformRequestWithScripts to TerraformRequestWithScriptsDirectory.
+ *
+ * @param request request with scripts.
+ * @return request with scripts directory.
+ */
+ private TerraformRequestWithScriptsDirectory convertRequestWithScriptsToDirectory(
+ TerraformRequestWithScripts request) {
+ TerraformRequestWithScriptsDirectory requestWithDirectory =
+ new TerraformRequestWithScriptsDirectory();
+ if (request instanceof TerraformAsyncRequestWithScripts) {
+ requestWithDirectory = new TerraformAsyncRequestWithScriptsDirectory();
+ }
+ BeanUtils.copyProperties(request, requestWithDirectory);
+ String scriptsPath =
+ scriptsDirectoryHelper.buildTaskWorkspace(request.getRequestId().toString());
+ requestWithDirectory.setScriptsDirectory(scriptsPath);
+ List scriptFilesList =
+ scriptsDirectoryHelper.prepareDeploymentFilesWithScripts(
+ scriptsPath, request.getScriptFiles(), request.getTfState());
+ requestWithDirectory.setScriptFiles(scriptFilesList);
+ return requestWithDirectory;
+ }
+}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformResultPersistenceManage.java b/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformResultPersistenceManage.java
index 062018e5..f9b74eef 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformResultPersistenceManage.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformResultPersistenceManage.java
@@ -30,7 +30,7 @@ public class TerraformResultPersistenceManage {
@Value("${failed.callback.response.store.location}")
private String failedCallbackStoreLocation;
- @Resource private TerraformScriptsHelper scriptsHelper;
+ @Resource private TerraformScriptsDirectoryHelper scriptsHelper;
@Resource private TerraformResultSerializer terraformResultSerializer;
/**
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformScriptsHelper.java b/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformScriptsDirectoryHelper.java
similarity index 96%
rename from src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformScriptsHelper.java
rename to src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformScriptsDirectoryHelper.java
index 82dec38e..41e76e0c 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformScriptsHelper.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformScriptsDirectoryHelper.java
@@ -9,6 +9,7 @@
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
@@ -23,7 +24,7 @@
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.xpanse.terra.boot.models.exceptions.TerraformExecutorException;
-import org.eclipse.xpanse.terra.boot.models.request.git.TerraformScriptGitRepoDetails;
+import org.eclipse.xpanse.terra.boot.models.request.git.TerraformScriptsGitRepoDetails;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
@@ -31,7 +32,7 @@
/** bean to host all generic methods shared from different types of Terraform deployers. */
@Slf4j
@Component
-public class TerraformScriptsHelper {
+public class TerraformScriptsDirectoryHelper {
public static final String TF_SCRIPT_FILE_EXTENSION = ".tf";
private static final String TF_STATE_FILE_NAME = "terraform.tfstate";
@@ -44,7 +45,7 @@ public class TerraformScriptsHelper {
@Value("${clean.workspace.after.deployment.enabled:true}")
private Boolean cleanWorkspaceAfterDeployment;
- @Resource private ScriptsGitRepoManage scriptsGitRepoManage;
+ @Resource private TerraformScriptsGitRepoHelper terraformScriptsGitRepoHelper;
/**
* Create workspace for the Terraform deployment task.
@@ -82,8 +83,7 @@ public File createTfStateFile(String taskWorkspace, String tfState) {
throw new TerraformExecutorException("tfState file create error");
}
File stateFile = new File(taskWorkspace, TF_STATE_FILE_NAME);
- boolean overwrite = stateFile.exists();
- try (FileWriter scriptWriter = new FileWriter(stateFile, overwrite)) {
+ try (FileWriter scriptWriter = new FileWriter(stateFile, StandardCharsets.UTF_8, false)) {
scriptWriter.write(tfState);
log.info("tfState file create success, fileName: {}", stateFile.getAbsolutePath());
return stateFile;
@@ -121,9 +121,9 @@ public List prepareDeploymentFilesWithScripts(
* @return list of script files.
*/
public List prepareDeploymentFilesWithGitRepo(
- String taskWorkspace, TerraformScriptGitRepoDetails gitRepoDetails, String tfState) {
+ String taskWorkspace, TerraformScriptsGitRepoDetails gitRepoDetails, String tfState) {
List scriptFiles =
- scriptsGitRepoManage.checkoutScripts(taskWorkspace, gitRepoDetails);
+ terraformScriptsGitRepoHelper.checkoutScripts(taskWorkspace, gitRepoDetails);
List projectFiles = new ArrayList<>(scriptFiles);
if (StringUtils.isNotBlank(tfState)) {
File tfStateFile = createTfStateFile(taskWorkspace, tfState);
@@ -156,8 +156,7 @@ private List buildScriptFiles(String taskWorkspace, Map sc
private File createScriptFile(String taskWorkspace, String scriptName, String scriptContent) {
File scriptFile = new File(taskWorkspace, scriptName);
- boolean overwrite = scriptFile.exists();
- try (FileWriter scriptWriter = new FileWriter(scriptFile, overwrite)) {
+ try (FileWriter scriptWriter = new FileWriter(scriptFile, StandardCharsets.UTF_8, false)) {
scriptWriter.write(scriptContent);
log.info("Terraform script create success, fileName: {}", scriptFile.getAbsolutePath());
return scriptFile;
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformDirectoryService.java b/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformScriptsDirectoryService.java
similarity index 72%
rename from src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformDirectoryService.java
rename to src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformScriptsDirectoryService.java
index 1df3c7a8..7471139c 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformDirectoryService.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformScriptsDirectoryService.java
@@ -8,27 +8,20 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
-import java.io.File;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
import java.util.UUID;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.xpanse.terra.boot.async.TaskConfiguration;
-import org.eclipse.xpanse.terra.boot.models.TerraBootSystemStatus;
import org.eclipse.xpanse.terra.boot.models.enums.HealthStatus;
import org.eclipse.xpanse.terra.boot.models.exceptions.InvalidTerraformToolException;
import org.eclipse.xpanse.terra.boot.models.exceptions.TerraformExecutorException;
-import org.eclipse.xpanse.terra.boot.models.plan.TerraformPlan;
-import org.eclipse.xpanse.terra.boot.models.plan.TerraformPlanFromDirectoryRequest;
-import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformAsyncDeployFromDirectoryRequest;
-import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformAsyncDestroyFromDirectoryRequest;
-import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformAsyncModifyFromDirectoryRequest;
-import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformDeployFromDirectoryRequest;
-import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformDestroyFromDirectoryRequest;
-import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformModifyFromDirectoryRequest;
+import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformAsyncRequestWithScriptsDirectory;
+import org.eclipse.xpanse.terra.boot.models.request.directory.TerraformRequestWithScriptsDirectory;
+import org.eclipse.xpanse.terra.boot.models.response.TerraBootSystemStatus;
+import org.eclipse.xpanse.terra.boot.models.response.TerraformPlan;
import org.eclipse.xpanse.terra.boot.models.response.TerraformResult;
-import org.eclipse.xpanse.terra.boot.models.validation.TerraformValidationResult;
+import org.eclipse.xpanse.terra.boot.models.response.validation.TerraformValidationResult;
import org.eclipse.xpanse.terra.boot.terraform.TerraformExecutor;
import org.eclipse.xpanse.terra.boot.terraform.tool.TerraformInstaller;
import org.eclipse.xpanse.terra.boot.terraform.tool.TerraformVersionsHelper;
@@ -42,7 +35,8 @@
/** Terraform service classes are deployed form Directory. */
@Slf4j
@Service
-public class TerraformDirectoryService {
+public class TerraformScriptsDirectoryService {
+
private static final String HELLO_WORLD_TF_NAME = "hello_world.tf";
private static final String HELLO_WORLD_TEMPLATE =
"""
@@ -54,7 +48,7 @@ public class TerraformDirectoryService {
@Resource private TerraformInstaller installer;
@Resource private RestTemplate restTemplate;
@Resource private TerraformVersionsHelper versionHelper;
- @Resource private TerraformScriptsHelper scriptsHelper;
+ @Resource private TerraformScriptsDirectoryHelper scriptsHelper;
@Resource private TerraformResultPersistenceManage terraformResultPersistenceManage;
/**
@@ -62,13 +56,16 @@ public class TerraformDirectoryService {
*
* @return TerraBootSystemStatus.
*/
- public TerraBootSystemStatus tfHealthCheck() {
- String taskWorkspace = scriptsHelper.buildTaskWorkspace(UUID.randomUUID().toString());
+ public TerraBootSystemStatus tfHealthCheck(UUID requestId) {
+ String taskWorkspace = scriptsHelper.buildTaskWorkspace(requestId.toString());
scriptsHelper.prepareDeploymentFilesWithScripts(
taskWorkspace, Map.of(HELLO_WORLD_TF_NAME, HELLO_WORLD_TEMPLATE), null);
+ TerraformRequestWithScriptsDirectory request = new TerraformRequestWithScriptsDirectory();
+ request.setScriptsDirectory(taskWorkspace);
TerraformValidationResult terraformValidationResult =
- tfValidateFromDirectory(taskWorkspace, null);
+ tfValidateWithScriptsDirectory(request);
TerraBootSystemStatus systemStatus = new TerraBootSystemStatus();
+ systemStatus.setRequestId(requestId);
if (terraformValidationResult.isValid()) {
systemStatus.setHealthStatus(HealthStatus.OK);
return systemStatus;
@@ -83,29 +80,30 @@ public TerraBootSystemStatus tfHealthCheck() {
*
* @return TfValidationResult.
*/
- public TerraformValidationResult tfValidateFromDirectory(
- String taskWorkspace, String terraformVersion) {
+ public TerraformValidationResult tfValidateWithScriptsDirectory(
+ TerraformRequestWithScriptsDirectory request) {
try {
String executorPath =
- installer.getExecutorPathThatMatchesRequiredVersion(terraformVersion);
- SystemCmdResult result = executor.tfValidate(executorPath, taskWorkspace);
+ installer.getExecutorPathThatMatchesRequiredVersion(
+ request.getTerraformVersion());
+ SystemCmdResult result =
+ executor.tfValidate(executorPath, request.getScriptsDirectory());
TerraformValidationResult validationResult =
new ObjectMapper()
.readValue(
result.getCommandStdOutput(), TerraformValidationResult.class);
+ validationResult.setRequestId(request.getRequestId());
validationResult.setTerraformVersionUsed(
versionHelper.getExactVersionOfExecutor(executorPath));
return validationResult;
- } catch (JsonProcessingException ex) {
- throw new IllegalStateException("Serialising string to object failed.", ex);
+ } catch (JsonProcessingException | InvalidTerraformToolException ex) {
+ throw new TerraformExecutorException("Failed get terraform validation result.", ex);
}
}
/** Deploy a source by terraform. */
- public TerraformResult deployFromDirectory(
- TerraformDeployFromDirectoryRequest request,
- String taskWorkspace,
- List scriptFiles) {
+ public TerraformResult deployWithScriptsDirectory(
+ TerraformRequestWithScriptsDirectory request) {
SystemCmdResult result;
String executorPath = null;
try {
@@ -118,14 +116,14 @@ public TerraformResult deployFromDirectory(
executorPath,
request.getVariables(),
request.getEnvVariables(),
- taskWorkspace);
+ request.getScriptsDirectory());
} else {
result =
executor.tfApply(
executorPath,
request.getVariables(),
request.getEnvVariables(),
- taskWorkspace);
+ request.getScriptsDirectory());
}
} catch (InvalidTerraformToolException | TerraformExecutorException tfEx) {
log.error("Terraform deploy service failed. error:{}", tfEx.getMessage());
@@ -133,19 +131,16 @@ public TerraformResult deployFromDirectory(
result.setCommandSuccessful(false);
result.setCommandStdError(tfEx.getMessage());
}
- TerraformResult terraformResult =
- transSystemCmdResultToTerraformResult(result, taskWorkspace, scriptFiles);
+ TerraformResult terraformResult = transSystemCmdResultToTerraformResult(result, request);
terraformResult.setTerraformVersionUsed(
versionHelper.getExactVersionOfExecutor(executorPath));
- scriptsHelper.deleteTaskWorkspace(taskWorkspace);
+ scriptsHelper.deleteTaskWorkspace(request.getScriptsDirectory());
return terraformResult;
}
/** Modify a source by terraform. */
- public TerraformResult modifyFromDirectory(
- TerraformModifyFromDirectoryRequest request,
- String taskWorkspace,
- List scriptFiles) {
+ public TerraformResult modifyWithScriptsDirectory(
+ TerraformRequestWithScriptsDirectory request) {
SystemCmdResult result;
String executorPath = null;
try {
@@ -158,14 +153,14 @@ public TerraformResult modifyFromDirectory(
executorPath,
request.getVariables(),
request.getEnvVariables(),
- taskWorkspace);
+ request.getScriptsDirectory());
} else {
result =
executor.tfApply(
executorPath,
request.getVariables(),
request.getEnvVariables(),
- taskWorkspace);
+ request.getScriptsDirectory());
}
} catch (InvalidTerraformToolException | TerraformExecutorException tfEx) {
log.error("Terraform deploy service failed. error:{}", tfEx.getMessage());
@@ -173,20 +168,17 @@ public TerraformResult modifyFromDirectory(
result.setCommandSuccessful(false);
result.setCommandStdError(tfEx.getMessage());
}
- TerraformResult terraformResult =
- transSystemCmdResultToTerraformResult(result, taskWorkspace, scriptFiles);
+ TerraformResult terraformResult = transSystemCmdResultToTerraformResult(result, request);
terraformResult.setTerraformVersionUsed(
versionHelper.getExactVersionOfExecutor(executorPath));
- scriptsHelper.deleteTaskWorkspace(taskWorkspace);
+ scriptsHelper.deleteTaskWorkspace(request.getScriptsDirectory());
terraformResult.setRequestId(request.getRequestId());
return terraformResult;
}
/** Destroy resource of the service. */
- public TerraformResult destroyFromDirectory(
- TerraformDestroyFromDirectoryRequest request,
- String taskWorkspace,
- List scriptFiles) {
+ public TerraformResult destroyWithScriptsDirectory(
+ TerraformRequestWithScriptsDirectory request) {
SystemCmdResult result;
String executorPath = null;
try {
@@ -198,25 +190,24 @@ public TerraformResult destroyFromDirectory(
executorPath,
request.getVariables(),
request.getEnvVariables(),
- taskWorkspace);
+ request.getScriptsDirectory());
} catch (InvalidTerraformToolException | TerraformExecutorException tfEx) {
log.error("Terraform destroy service failed. error:{}", tfEx.getMessage());
result = new SystemCmdResult();
result.setCommandSuccessful(false);
result.setCommandStdError(tfEx.getMessage());
}
- TerraformResult terraformResult =
- transSystemCmdResultToTerraformResult(result, taskWorkspace, scriptFiles);
+ TerraformResult terraformResult = transSystemCmdResultToTerraformResult(result, request);
terraformResult.setTerraformVersionUsed(
versionHelper.getExactVersionOfExecutor(executorPath));
- scriptsHelper.deleteTaskWorkspace(taskWorkspace);
+ scriptsHelper.deleteTaskWorkspace(request.getScriptsDirectory());
terraformResult.setRequestId(request.getRequestId());
return terraformResult;
}
/** Executes terraform plan command on a directory and returns the plan as a JSON string. */
- public TerraformPlan getTerraformPlanFromDirectory(
- TerraformPlanFromDirectoryRequest request, String taskWorkspace) {
+ public TerraformPlan getTerraformPlanWithScriptsDirectory(
+ TerraformRequestWithScriptsDirectory request) {
String executorPath =
installer.getExecutorPathThatMatchesRequiredVersion(request.getTerraformVersion());
String result =
@@ -224,9 +215,10 @@ public TerraformPlan getTerraformPlanFromDirectory(
executorPath,
request.getVariables(),
request.getEnvVariables(),
- taskWorkspace);
- scriptsHelper.deleteTaskWorkspace(taskWorkspace);
- TerraformPlan terraformPlan = TerraformPlan.builder().plan(result).build();
+ request.getScriptsDirectory());
+ scriptsHelper.deleteTaskWorkspace(request.getScriptsDirectory());
+ TerraformPlan terraformPlan =
+ TerraformPlan.builder().plan(result).requestId(request.getRequestId()).build();
terraformPlan.setTerraformVersionUsed(
versionHelper.getExactVersionOfExecutor(executorPath));
return terraformPlan;
@@ -234,13 +226,11 @@ public TerraformPlan getTerraformPlanFromDirectory(
/** Async deploy a source by terraform. */
@Async(TaskConfiguration.TASK_EXECUTOR_NAME)
- public void asyncDeployWithScripts(
- TerraformAsyncDeployFromDirectoryRequest asyncDeployRequest,
- String taskWorkspace,
- List scriptFiles) {
+ public void asyncDeployWithScriptsDirectory(
+ TerraformAsyncRequestWithScriptsDirectory asyncDeployRequest) {
TerraformResult result;
try {
- result = deployFromDirectory(asyncDeployRequest, taskWorkspace, scriptFiles);
+ result = deployWithScriptsDirectory(asyncDeployRequest);
} catch (RuntimeException e) {
result =
TerraformResult.builder()
@@ -259,13 +249,11 @@ public void asyncDeployWithScripts(
/** Async modify a source by terraform. */
@Async(TaskConfiguration.TASK_EXECUTOR_NAME)
- public void asyncModifyWithScripts(
- TerraformAsyncModifyFromDirectoryRequest asyncModifyRequest,
- String taskWorkspace,
- List scriptFiles) {
+ public void asyncModifyWithScriptsDirectory(
+ TerraformAsyncRequestWithScriptsDirectory asyncModifyRequest) {
TerraformResult result;
try {
- result = modifyFromDirectory(asyncModifyRequest, taskWorkspace, scriptFiles);
+ result = modifyWithScriptsDirectory(asyncModifyRequest);
} catch (RuntimeException e) {
result =
TerraformResult.builder()
@@ -284,13 +272,11 @@ public void asyncModifyWithScripts(
/** Async destroy resource of the service. */
@Async(TaskConfiguration.TASK_EXECUTOR_NAME)
- public void asyncDestroyWithScripts(
- TerraformAsyncDestroyFromDirectoryRequest request,
- String taskWorkspace,
- List scriptFiles) {
+ public void asyncDestroyWithScriptsDirectory(
+ TerraformAsyncRequestWithScriptsDirectory request) {
TerraformResult result;
try {
- result = destroyFromDirectory(request, taskWorkspace, scriptFiles);
+ result = destroyWithScriptsDirectory(request);
} catch (RuntimeException e) {
result =
TerraformResult.builder()
@@ -317,14 +303,19 @@ private void sendTerraformResult(String url, TerraformResult result) {
}
private TerraformResult transSystemCmdResultToTerraformResult(
- SystemCmdResult result, String taskWorkspace, List scriptFiles) {
+ SystemCmdResult result, TerraformRequestWithScriptsDirectory request) {
TerraformResult terraformResult =
- TerraformResult.builder().isCommandSuccessful(result.isCommandSuccessful()).build();
+ TerraformResult.builder()
+ .isCommandSuccessful(result.isCommandSuccessful())
+ .requestId(request.getRequestId())
+ .build();
try {
BeanUtils.copyProperties(result, terraformResult);
- terraformResult.setTerraformState(scriptsHelper.getTerraformState(taskWorkspace));
+ terraformResult.setTerraformState(
+ scriptsHelper.getTerraformState(request.getScriptsDirectory()));
terraformResult.setGeneratedFileContentMap(
- scriptsHelper.getDeploymentGeneratedFilesContent(taskWorkspace, scriptFiles));
+ scriptsHelper.getDeploymentGeneratedFilesContent(
+ request.getScriptsDirectory(), request.getScriptFiles()));
} catch (Exception e) {
log.error("Failed to get terraform state and generated files content.", e);
}
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/ScriptsGitRepoManage.java b/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformScriptsGitRepoHelper.java
similarity index 91%
rename from src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/ScriptsGitRepoManage.java
rename to src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformScriptsGitRepoHelper.java
index 08e51e39..77dbed7a 100644
--- a/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/ScriptsGitRepoManage.java
+++ b/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformScriptsGitRepoHelper.java
@@ -5,7 +5,7 @@
package org.eclipse.xpanse.terra.boot.terraform.service;
-import static org.eclipse.xpanse.terra.boot.terraform.service.TerraformScriptsHelper.TF_SCRIPT_FILE_EXTENSION;
+import static org.eclipse.xpanse.terra.boot.terraform.service.TerraformScriptsDirectoryHelper.TF_SCRIPT_FILE_EXTENSION;
import java.io.File;
import java.util.ArrayList;
@@ -20,7 +20,7 @@
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.xpanse.terra.boot.models.exceptions.GitRepoCloneException;
import org.eclipse.xpanse.terra.boot.models.exceptions.InvalidTerraformScriptsException;
-import org.eclipse.xpanse.terra.boot.models.request.git.TerraformScriptGitRepoDetails;
+import org.eclipse.xpanse.terra.boot.models.request.git.TerraformScriptsGitRepoDetails;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Retryable;
import org.springframework.retry.support.RetrySynchronizationManager;
@@ -29,7 +29,7 @@
/** Bean to manage GIT clone. */
@Slf4j
@Component
-public class ScriptsGitRepoManage {
+public class TerraformScriptsGitRepoHelper {
/**
* Method to check out scripts from a GIT repo.
@@ -41,7 +41,8 @@ public class ScriptsGitRepoManage {
retryFor = GitRepoCloneException.class,
maxAttemptsExpression = "${spring.retry.max-attempts}",
backoff = @Backoff(delayExpression = "${spring.retry.delay-millions}"))
- public List checkoutScripts(String workspace, TerraformScriptGitRepoDetails scriptsRepo) {
+ public List checkoutScripts(
+ String workspace, TerraformScriptsGitRepoDetails scriptsRepo) {
log.info(
"Clone GIT repo to get the deployment scripts. Retry number: "
+ Objects.requireNonNull(RetrySynchronizationManager.getContext())
@@ -72,7 +73,8 @@ public List checkoutScripts(String workspace, TerraformScriptGitRepoDetail
return files;
}
- private List getSourceFiles(String workspace, TerraformScriptGitRepoDetails scriptsRepo) {
+ private List getSourceFiles(
+ String workspace, TerraformScriptsGitRepoDetails scriptsRepo) {
List sourceFiles = new ArrayList<>();
File directory =
new File(
@@ -96,7 +98,7 @@ private List getSourceFiles(String workspace, TerraformScriptGitRepoDetail
}
private void validateIfFolderContainsTerraformScripts(
- List files, TerraformScriptGitRepoDetails scriptsRepo) {
+ List files, TerraformScriptsGitRepoDetails scriptsRepo) {
boolean isScriptsExisted =
files.stream().anyMatch(file -> file.getName().endsWith(TF_SCRIPT_FILE_EXTENSION));
if (!isScriptsExisted) {
diff --git a/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformScriptsService.java b/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformScriptsService.java
deleted file mode 100644
index 44292b0b..00000000
--- a/src/main/java/org/eclipse/xpanse/terra/boot/terraform/service/TerraformScriptsService.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * SPDX-License-Identifier: Apache-2.0
- * SPDX-FileCopyrightText: Huawei Inc.
- */
-
-package org.eclipse.xpanse.terra.boot.terraform.service;
-
-import jakarta.annotation.Resource;
-import java.io.File;
-import java.util.HashMap;
-import java.util.List;
-import java.util.UUID;
-import lombok.extern.slf4j.Slf4j;
-import org.eclipse.xpanse.terra.boot.async.TaskConfiguration;
-import org.eclipse.xpanse.terra.boot.models.plan.TerraformPlan;
-import org.eclipse.xpanse.terra.boot.models.plan.TerraformPlanWithScriptsRequest;
-import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformAsyncDeployFromScriptsRequest;
-import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformAsyncDestroyFromScriptsRequest;
-import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformAsyncModifyFromScriptsRequest;
-import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformDeployWithScriptsRequest;
-import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformDestroyWithScriptsRequest;
-import org.eclipse.xpanse.terra.boot.models.request.scripts.TerraformModifyWithScriptsRequest;
-import org.eclipse.xpanse.terra.boot.models.response.TerraformResult;
-import org.eclipse.xpanse.terra.boot.models.validation.TerraformValidationResult;
-import org.springframework.scheduling.annotation.Async;
-import org.springframework.stereotype.Service;
-import org.springframework.web.client.RestClientException;
-import org.springframework.web.client.RestTemplate;
-
-/** Terraform service classes are deployed form Scripts. */
-@Slf4j
-@Service
-public class TerraformScriptsService {
-
- @Resource private RestTemplate restTemplate;
- @Resource private TerraformScriptsHelper scriptsHelper;
- @Resource private TerraformDirectoryService directoryService;
- @Resource private TerraformResultPersistenceManage terraformResultPersistenceManage;
-
- /** /** Method of deployment a service using a script. */
- public TerraformValidationResult validateWithScripts(
- TerraformDeployWithScriptsRequest request) {
- String taskWorkspace = scriptsHelper.buildTaskWorkspace(UUID.randomUUID().toString());
- scriptsHelper.prepareDeploymentFilesWithScripts(
- taskWorkspace, request.getScriptFiles(), null);
- return directoryService.tfValidateFromDirectory(
- taskWorkspace, request.getTerraformVersion());
- }
-
- /** Method of deployment a service using a script. */
- public TerraformResult deployWithScripts(TerraformDeployWithScriptsRequest request, UUID uuid) {
- String taskWorkspace = scriptsHelper.buildTaskWorkspace(uuid.toString());
- List files =
- scriptsHelper.prepareDeploymentFilesWithScripts(
- taskWorkspace, request.getScriptFiles(), null);
- return directoryService.deployFromDirectory(request, taskWorkspace, files);
- }
-
- /** Method of modify a service using a script. */
- public TerraformResult modifyWithScripts(TerraformModifyWithScriptsRequest request, UUID uuid) {
- String taskWorkspace = scriptsHelper.buildTaskWorkspace(uuid.toString());
- List files =
- scriptsHelper.prepareDeploymentFilesWithScripts(
- taskWorkspace, request.getScriptFiles(), request.getTfState());
- return directoryService.modifyFromDirectory(request, taskWorkspace, files);
- }
-
- /** Method of destroy a service using a script. */
- public TerraformResult destroyWithScripts(
- TerraformDestroyWithScriptsRequest request, UUID uuid) {
- String taskWorkspace = scriptsHelper.buildTaskWorkspace(uuid.toString());
- List files =
- scriptsHelper.prepareDeploymentFilesWithScripts(
- taskWorkspace, request.getScriptFiles(), request.getTfState());
- return directoryService.destroyFromDirectory(request, taskWorkspace, files);
- }
-
- /** Method to get terraform plan. */
- public TerraformPlan getTerraformPlanFromScripts(
- TerraformPlanWithScriptsRequest request, UUID uuid) {
- String taskWorkspace = scriptsHelper.buildTaskWorkspace(uuid.toString());
- scriptsHelper.prepareDeploymentFilesWithScripts(
- taskWorkspace, request.getScriptFiles(), null);
- return directoryService.getTerraformPlanFromDirectory(request, uuid.toString());
- }
-
- /** Async deploy a source by terraform. */
- @Async(TaskConfiguration.TASK_EXECUTOR_NAME)
- public void asyncDeployWithScripts(
- TerraformAsyncDeployFromScriptsRequest asyncDeployRequest, UUID uuid) {
- TerraformResult result;
- try {
- result = deployWithScripts(asyncDeployRequest, uuid);
- } catch (RuntimeException e) {
- result =
- TerraformResult.builder()
- .commandStdOutput(null)
- .commandStdError(e.getMessage())
- .isCommandSuccessful(false)
- .terraformState(null)
- .generatedFileContentMap(new HashMap<>())
- .build();
- }
- result.setRequestId(asyncDeployRequest.getRequestId());
- String url = asyncDeployRequest.getWebhookConfig().getUrl();
- log.info("Deployment service complete, callback POST url:{}, requestBody:{}", url, result);
- sendTerraformResult(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()
- .commandStdOutput(null)
- .commandStdError(e.getMessage())
- .isCommandSuccessful(false)
- .terraformState(null)
- .generatedFileContentMap(new HashMap<>())
- .build();
- }
- result.setRequestId(asyncModifyRequest.getRequestId());
- String url = asyncModifyRequest.getWebhookConfig().getUrl();
- log.info("Modify service complete, callback POST url:{}, requestBody:{}", url, result);
- sendTerraformResult(url, result);
- }
-
- /** Async destroy resource of the service. */
- @Async(TaskConfiguration.TASK_EXECUTOR_NAME)
- public void asyncDestroyWithScripts(
- TerraformAsyncDestroyFromScriptsRequest request, UUID uuid) {
- TerraformResult result;
- try {
- result = destroyWithScripts(request, uuid);
- } catch (RuntimeException e) {
- result =
- TerraformResult.builder()
- .commandStdOutput(null)
- .commandStdError(e.getMessage())
- .isCommandSuccessful(false)
- .terraformState(null)
- .generatedFileContentMap(new HashMap<>())
- .build();
- }
- result.setRequestId(request.getRequestId());
- String url = request.getWebhookConfig().getUrl();
- log.info("Destroy service complete, callback POST url:{}, requestBody:{}", url, result);
- sendTerraformResult(url, result);
- }
-
- private void sendTerraformResult(String url, TerraformResult result) {
- try {
- restTemplate.postForLocation(url, result);
- } catch (RestClientException e) {
- log.error("error while sending terraform result", e);
- terraformResultPersistenceManage.persistTerraformResult(result);
- }
- }
-}
diff --git a/src/main/resources/application-amqp.properties b/src/main/resources/application-amqp.properties
new file mode 100644
index 00000000..b6fc6bf9
--- /dev/null
+++ b/src/main/resources/application-amqp.properties
@@ -0,0 +1,30 @@
+#
+# SPDX-License-Identifier: Apache-2.0
+# SPDX-FileCopyrightText: Huawei Inc.
+#
+
+# amqp provider, default value: rabbitmq.
+spring.amqp.provider=rabbitmq
+# RabbitMQ Specific
+spring.rabbitmq.host=localhost
+spring.rabbitmq.port=5672
+spring.rabbitmq.username=xpanse
+spring.rabbitmq.password=Xpanse@2023
+# Retry configuration for RabbitMQ listener
+spring.rabbitmq.listener.simple.retry.max-attempts=3
+spring.rabbitmq.listener.simple.retry.initial-interval=3000
+spring.rabbitmq.listener.simple.retry.max-interval=3000
+# springwolf AsyncAPI
+springwolf.enabled=true
+# AsyncAPI Docket
+springwolf.path.base=/queues
+springwolf.path.docs=/docs
+springwolf.docket.info.title=TerraBoot Async Request APIs
+springwolf.docket.info.version=@project.version@
+springwolf.docket.info.description=TerraBoot Async Request APIs.
+springwolf.docket.base-package=org.eclipse.xpanse.terra.boot.api.queues
+springwolf.docket.servers.amqp-server.description=AMQP Server
+springwolf.docket.servers.amqp-server.protocol=amqp
+springwolf.docket.servers.amqp-server.host=${spring.rabbitmq.host}:${spring.rabbitmq.port}
+# AMQP Plugin for springwolf AsyncAPI
+springwolf.plugin.amqp.publishing.enabled=true
\ No newline at end of file
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index ed17c385..3fe88182 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -6,6 +6,7 @@ spring.application.name=terra-boot
server.port=9090
app.version=@project.version@
spring.banner.location=classpath:banner.txt
+springwolf.enabled=false
http.logging.enabled=true
http.logging.exclude.uri=/v3/**,/swagger-ui/**,/favicon.ico,/h2-console/**
log.terraform.stdout.stderr=true