diff --git a/service/application/pom.xml b/service/application/pom.xml index 911ee86af..def1b307e 100644 --- a/service/application/pom.xml +++ b/service/application/pom.xml @@ -305,6 +305,9 @@ ${jacocoSurefire} + + **/realTests/** + diff --git a/service/application/src/main/java/com/solace/maas/ep/event/management/agent/command/CommandManager.java b/service/application/src/main/java/com/solace/maas/ep/event/management/agent/command/CommandManager.java index c7bee5129..54d239997 100644 --- a/service/application/src/main/java/com/solace/maas/ep/event/management/agent/command/CommandManager.java +++ b/service/application/src/main/java/com/solace/maas/ep/event/management/agent/command/CommandManager.java @@ -5,19 +5,28 @@ import com.solace.maas.ep.event.management.agent.config.eventPortal.EventPortalProperties; import com.solace.maas.ep.event.management.agent.plugin.command.model.Command; import com.solace.maas.ep.event.management.agent.plugin.command.model.CommandBundle; +import com.solace.maas.ep.event.management.agent.plugin.command.model.CommandResult; +import com.solace.maas.ep.event.management.agent.plugin.command.model.JobStatus; import com.solace.maas.ep.event.management.agent.plugin.service.MessagingServiceDelegateService; import com.solace.maas.ep.event.management.agent.plugin.solace.processor.semp.SempClient; import com.solace.maas.ep.event.management.agent.plugin.solace.processor.semp.SolaceHttpSemp; import com.solace.maas.ep.event.management.agent.plugin.terraform.manager.TerraformManager; import com.solace.maas.ep.event.management.agent.publisher.CommandPublisher; import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.stereotype.Service; +import java.time.OffsetDateTime; import java.util.HashMap; +import java.util.List; import java.util.Map; +import static com.solace.maas.ep.event.management.agent.plugin.terraform.manager.TerraformManager.LOG_LEVEL_ERROR; +import static com.solace.maas.ep.event.management.agent.plugin.terraform.manager.TerraformManager.setCommandError; + @Slf4j @Service +@ConditionalOnProperty(name = "event-portal.gateway.messaging.standalone", havingValue = "false") public class CommandManager { private final TerraformManager terraformManager; private final CommandMapper commandMapper; @@ -36,20 +45,46 @@ public CommandManager(TerraformManager terraformManager, CommandMapper commandMa } public void execute(CommandMessage request) { - Map envVars = setBrokerSpecificEnvVars(request.getServiceId()); + Map envVars; + try { + envVars = setBrokerSpecificEnvVars(request.getServiceId()); + } catch (Exception e) { + log.error("Error getting terraform variables", e); + Command firstCommand = request.getCommandBundles().get(0).getCommands().get(0); + setCommandError(firstCommand, e); + sendResponse(request); + return; + } + for (CommandBundle bundle : request.getCommandBundles()) { // For now everything is run serially for (Command command : bundle.getCommands()) { - switch (command.getCommandType()) { - case terraform: - terraformManager.execute(commandMapper.map(request), command, envVars); - break; - default: - throw new IllegalStateException("Unexpected value: " + command.getCommandType()); + try { + switch (command.getCommandType()) { + case terraform: + terraformManager.execute(commandMapper.map(request), command, envVars); + break; + default: + command.setResult(CommandResult.builder() + .status(JobStatus.error) + .logs(List.of( + Map.of("message", "unknown command type " + command.getCommandType(), + "errorType", "UnknownCommandType", + "level", LOG_LEVEL_ERROR, + "timestamp", OffsetDateTime.now()))) + .build()); + break; + } + } catch (Exception e) { + log.error("Error executing command", e); + setCommandError(command, e); } } } + sendResponse(request); + } + private void sendResponse(CommandMessage request) { Map topicVars = Map.of( "orgId", request.getOrgId(), "runtimeAgentId", eventPortalProperties.getRuntimeAgentId(), diff --git a/service/application/src/test/java/com/solace/maas/ep/event/management/agent/TestConfig.java b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/TestConfig.java index fc54bdf57..e8a77de74 100644 --- a/service/application/src/test/java/com/solace/maas/ep/event/management/agent/TestConfig.java +++ b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/TestConfig.java @@ -1,5 +1,8 @@ package com.solace.maas.ep.event.management.agent; +import com.solace.maas.ep.event.management.agent.command.CommandManager; +import com.solace.maas.ep.event.management.agent.command.mapper.CommandMapper; +import com.solace.maas.ep.event.management.agent.config.eventPortal.EventPortalProperties; import com.solace.maas.ep.event.management.agent.messagingServices.RtoMessagingService; import com.solace.maas.ep.event.management.agent.plugin.config.VMRProperties; import com.solace.maas.ep.event.management.agent.plugin.config.eventPortal.EventPortalPluginProperties; @@ -140,6 +143,15 @@ public CommandPublisher getCommandPublisher() { return mock(CommandPublisher.class); } + @Bean + @Primary + public CommandManager getCommandManager(TerraformManager terraformManager, CommandMapper commandMapper, + CommandPublisher commandPublisher, MessagingServiceDelegateService messagingServiceDelegateService, + EventPortalProperties eventPortalProperties) { + return new CommandManager(terraformManager, commandMapper, commandPublisher, + messagingServiceDelegateService, eventPortalProperties); + } + @Bean @Primary KafkaClientConnection kafkaClientConnection() { diff --git a/service/application/src/test/java/com/solace/maas/ep/event/management/agent/realTests/NegativeTerraformEVMRConnectedTests.java b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/realTests/NegativeTerraformEVMRConnectedTests.java new file mode 100644 index 000000000..7fab323b0 --- /dev/null +++ b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/realTests/NegativeTerraformEVMRConnectedTests.java @@ -0,0 +1,553 @@ +package com.solace.maas.ep.event.management.agent.realTests; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.solace.maas.ep.common.messages.CommandMessage; +import com.solace.maas.ep.event.management.agent.config.eventPortal.EventPortalProperties; +import com.solace.maas.ep.event.management.agent.plugin.command.model.Command; +import com.solace.maas.ep.event.management.agent.plugin.command.model.CommandBundle; +import com.solace.maas.ep.event.management.agent.plugin.command.model.CommandType; +import com.solace.maas.ep.event.management.agent.plugin.command.model.ExecutionType; +import com.solace.maas.ep.event.management.agent.plugin.command.model.JobStatus; +import com.solace.maas.ep.event.management.agent.plugin.mop.MOPUHFlag; +import com.solace.maas.ep.event.management.agent.plugin.publisher.SolacePublisher; +import com.solace.maas.ep.event.management.agent.plugin.terraform.configuration.TerraformProperties; +import com.solace.maas.ep.event.management.agent.realTests.badClasses.BadCommand; +import com.solace.maas.ep.event.management.agent.realTests.badClasses.CommandTypeBad; +import com.solace.messaging.MessagingService; +import com.solace.messaging.receiver.DirectMessageReceiver; +import com.solace.messaging.receiver.InboundMessage; +import com.solace.messaging.resources.TopicSubscription; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.util.FileCopyUtils; + +import java.io.File; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.UncheckedIOException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Base64; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +import static com.solace.maas.ep.event.management.agent.plugin.mop.MOPMessageType.generic; +import static com.solace.maas.ep.event.management.agent.plugin.mop.MOPProtocol.epConfigPush; +import static java.nio.charset.StandardCharsets.UTF_8; + +@SuppressWarnings({"PMD.GodClass", "PMD.UnusedPrivateMethod"}) +@Slf4j +@ActiveProfiles("negativetests") +@EnableAutoConfiguration +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class NegativeTerraformEVMRConnectedTests { + + @Autowired + private ResourceLoader resourceLoader; + @Autowired + private EventPortalProperties eventPortalProperties; + @Autowired + private SolacePublisher solacePublisher; + @Autowired + private MessagingService messagingService; + @Autowired + private TerraformProperties terraformProperties; + + private static final ObjectMapper objectMapper = new ObjectMapper(); + private static final String mainServiceId = "49a23700m80"; + private static String context = "abc123"; + private long startTime; + + static { + objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); + objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES); + } + + @BeforeAll + private static void envVarPrecheck() throws IOException, InterruptedException { + // These tests require some setup. + // + // Make sure the required environment variables are set. + // "SOLACE_SEMP_PASSWORD", "SOLACE_SEMP_URL", "SOLACE_SEMP_USERNAME" are for a valid Solace broker (version 10.4+) + // "OLD_SOLACE_SEMP_PASSWORD", "OLD_SOLACE_SEMP_URL", "OLD_SOLACE_SEMP_USERNAME" are for an older Solace broker (version 10.3-) + // "EP_GATEWAY_MSGVPN", "EP_GATEWAY_PASSWORD", "EP_GATEWAY_URL", "EP_GATEWAY_USERNAME" are for a valid eVMR + // + // They can be set for all Junit tests by going to the "Run" menu in IntelliJ, then "Edit Configuration templates", then + // then "JUnit", and set them in "Environment variables" + // + List requiredEnvVars = List.of("EP_GATEWAY_MSGVPN", "EP_GATEWAY_PASSWORD", "EP_GATEWAY_URL", "EP_GATEWAY_USERNAME", + "EP_ORGANIZATION_ID", "EP_RUNTIME_AGENT_ID", "OLD_SOLACE_SEMP_PASSWORD", "OLD_SOLACE_SEMP_URL", "OLD_SOLACE_SEMP_USERNAME", + "SOLACE_SEMP_PASSWORD", "SOLACE_SEMP_URL", "SOLACE_SEMP_USERNAME"); + List actualEnvVars = List.copyOf(System.getenv().keySet()); + if (!actualEnvVars.containsAll(requiredEnvVars)) { + throw new RuntimeException("Missing required environment variables: " + requiredEnvVars); + } + + // On the valid Solace broker, create a read-only user with username "admin2" and password the same as the "SOLACE_SEMP_PASSWORD" environment variable + // This is required for the "createQueueReadOnlyUserTest" test + log.info("Creating user admin2 with R/O privileges"); + HttpClient httpClient = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_1_1) + .build(); + HttpRequest request = HttpRequest.newBuilder() + .POST(HttpRequest.BodyPublishers.ofString("{\"globalAccessLevel\":\"read-only\",\"msgVpnDefaultAccessLevel\":\"none\",\"password\":\"" + + System.getenv("SOLACE_SEMP_PASSWORD") + "\",\"userName\":\"admin2\"}")) + .setHeader("Accept", "application/json") + .setHeader("Content-Type", "application/json") + .setHeader("Authorization", getBasicAuthenticationHeader(System.getenv("SOLACE_SEMP_USERNAME"), + System.getenv("SOLACE_SEMP_PASSWORD"))) + .uri(java.net.URI.create(System.getenv("SOLACE_SEMP_URL") + "/SEMP/v2/__private_config__/usernames")) + .build(); + httpClient.send(request, HttpResponse.BodyHandlers.ofString()); + } + + private static String getBasicAuthenticationHeader(String username, String password) { + String valueToEncode = username + ":" + password; + return "Basic " + Base64.getEncoder().encodeToString(valueToEncode.getBytes()); + } + + + @BeforeEach + private void beforeEach() { + startTime = System.currentTimeMillis(); + } + + @Test + public void createQueuePositiveTest() { + String correlationId = "myCorrelationId"; + CommandMessage commandResponse = runTest("addQueue.tf", mainServiceId, correlationId, context); + validateSuccessCommandResponse(commandResponse); + } + + @Test + public void deleteQueuePositiveTest() { + String correlationId = "myCorrelationId2"; + CommandMessage commandResponse = runTest("deleteQueue.tf", mainServiceId, correlationId, context); + validateSuccessCommandResponse(commandResponse); + } + + @Test + public void createQueueBadHostTest() { + testOutputMdTitle2(getTestMethodName()); + String correlationId = "myCorrelationId2"; + CommandMessage commandResponse = runTest("addQueueBadHost.tf", mainServiceId, correlationId, context); + validateErrorCommandResponse(commandResponse); + } + + @Test + public void createQueueBadPortTest() { + testOutputMdTitle2(getTestMethodName()); + + String correlationId = "myCorrelationId2"; + CommandMessage commandResponse = runTest("addQueueBadPort.tf", mainServiceId, correlationId, context); + validateErrorCommandResponse(commandResponse); + } + + @Test + public void createQueueBadCredentialsTest() { + testOutputMdTitle2(getTestMethodName()); + + String correlationId = "myCorrelationId2"; + CommandMessage commandResponse = runTest("addQueueBadCredentials.tf", mainServiceId, correlationId, context); + validateErrorCommandResponse(commandResponse); + } + + // Required to add new user admin2 with R/O privileges + @Test + public void createQueueReadOnlyUserTest() { + testOutputMdTitle2(getTestMethodName()); + String correlationId = "myCorrelationId1"; + CommandMessage commandResponse = runTest("AddQueueReadOnlyUser.tf", mainServiceId, correlationId, context); + validateErrorCommandResponse(commandResponse); + } + + @Test + public void createQueueSempFailureTest() { + testOutputMdTitle2(getTestMethodName()); + + // First create the queue + String correlationId = "myCorrelationId"; + CommandMessage commandResponse = runTest("addQueue.tf", mainServiceId, correlationId, context); + validateSuccessCommandResponse(commandResponse); + + // Delete the terraform state file + Path terraformStatePath = Paths.get(terraformProperties.getWorkingDirectoryRoot(), + context + "-" + mainServiceId, "terraform.tfstate"); + try { + Files.delete(terraformStatePath); + } catch (IOException e) { + throw new RuntimeException(e); + } + + // Now try to create the queue again + correlationId = "myCorrelationId2"; + commandResponse = runTest("addQueue.tf", mainServiceId, correlationId, context); + validateErrorCommandResponse(commandResponse); + } + + @Test + public void badBlockHclFailureTest() { + testOutputMdTitle2(getTestMethodName()); + + String correlationId = "myCorrelationId3"; + CommandMessage commandResponse = runTest("badBlockHcl.tf", mainServiceId, correlationId, context); + validateErrorCommandResponse(commandResponse); + } + + @Test + public void badFormatHclFailureTest() { + testOutputMdTitle2(getTestMethodName()); + + String correlationId = "myCorrelationId3"; + CommandMessage commandResponse = runTest("badFormatHcl.tf", mainServiceId, correlationId, context); + validateErrorCommandResponse(commandResponse); + } + + @Test + public void unknownTerraformCommandError() { + testOutputMdTitle2(getTestMethodName()); + + String correlationId = "myCorrelationId3"; + CommandMessage commandResponse = runTest("addQueue.tf", mainServiceId, correlationId, context, this::createCommandMessageBadTerraformCommand); + validateErrorCommandResponse(commandResponse); + } + + @Test + public void sempVersionTooOldTest() { + testOutputMdTitle2(getTestMethodName()); + + String correlationId = "myCorrelationId3"; + String oldServiceId = "v0r806w0bmj"; + CommandMessage commandResponse = runTest("addQueue.tf", oldServiceId, correlationId, context); + validateErrorCommandResponse(commandResponse); + } + + @Test + public void badProviderTest() { + testOutputMdTitle2(getTestMethodName()); + + String correlationId = "myCorrelationId3"; + CommandMessage commandResponse = runTest("badProvider.tf", mainServiceId, correlationId, context); + validateErrorCommandResponse(commandResponse); + } + + @Test + public void badMessagingServiceIdTest() { + testOutputMdTitle2(getTestMethodName()); + + String correlationId = "myCorrelationId1"; + CommandMessage commandResponse = runTest("addQueue.tf", "imABadServiceId", correlationId, context); + validateErrorCommandResponse(commandResponse); + } + + @Test + public void badCommandTypeInCommand() { + testOutputMdTitle2(getTestMethodName()); + + String correlationId = "myCorrelationId3"; + CommandMessage commandResponse = runTest("addQueue.tf", mainServiceId, correlationId, context, this::createCommandMessageBadCommandType); + validateErrorCommandResponse(commandResponse); + } + + + @Test + public void missingParametersInCommand() { + testOutputMdTitle2(getTestMethodName()); + + String correlationId = "myCorrelationId3"; + CommandMessage commandResponse = runTest("addQueue.tf", mainServiceId, correlationId, context, this::createCommandMessageMissingParameters); + validateErrorCommandResponse(commandResponse); + } + + @Test + public void hclCommandIsNotBase64Encoded() { + testOutputMdTitle2(getTestMethodName()); + + String correlationId = "myCorrelationId3"; + CommandMessage commandResponse = runTest("addQueue.tf", mainServiceId, correlationId, context, this::createCommandMessageHclNotBase64Encoded); + validateErrorCommandResponse(commandResponse); + } + + @Test + public void hclHasVariableThatIsNotSetInTerraformPlugin() { + testOutputMdTitle2(getTestMethodName()); + + String correlationId = "myCorrelationId1"; + CommandMessage commandResponse = runTest("addQueueNewVariableNotInPlugin.tf", mainServiceId, correlationId, context); + validateErrorCommandResponse(commandResponse); + } + + @Test + public void manyRequestsForTheSameContextAtTheSameTime() { + + String newQueueTf = asString(resourceLoader.getResource("classpath:hcl" + File.separator + "addQueue.tf")); + String newQueueTfBase64 = Base64.getEncoder().encodeToString(newQueueTf.getBytes(UTF_8)); + + int numberOfMessagesToSend = 10; + + AtomicBoolean keepRunning = new AtomicBoolean(true); + List commandResponseList = new CopyOnWriteArrayList<>(); + setupMessageReceiver(commandResponseList, keepRunning, this::handleCommandResponseMessage, numberOfMessagesToSend); + + for (int i = 0; i < numberOfMessagesToSend; i++) { + log.debug("Sending command " + i); + String correlationId = "myCorrelationId" + i; + CommandMessage message = createCommandMessageCommand(mainServiceId, correlationId, context, newQueueTfBase64); + solacePublisher.publish(message, + "sc/ep/runtime/" + eventPortalProperties.getOrganizationId() + "/" + + eventPortalProperties.getRuntimeAgentId() + "/command/v1/" + + correlationId); + } + + waitForReceivedMessages(keepRunning); + + commandResponseList.forEach(this::validateSuccessCommandResponse); + } + + private CommandMessage runTest(String hclFileName, String serviceId, String correlationId, String context) { + return runTest(hclFileName, serviceId, correlationId, context, this::createCommandMessageCommand); + } + + private CommandMessage runTest(String hclFileName, String serviceId, String correlationId, String context, + Function4ArityWithReturn createCommandMessage) { + + String newQueueTf = asString(resourceLoader.getResource("classpath:hcl" + File.separator + hclFileName)); + String newQueueTfBase64 = Base64.getEncoder().encodeToString(newQueueTf.getBytes(UTF_8)); + + CommandMessage message = createCommandMessage.apply(serviceId, correlationId, context, newQueueTfBase64); + + AtomicBoolean keepRunning = new AtomicBoolean(true); + List commandResponseList = new CopyOnWriteArrayList<>(); + setupMessageReceiver(commandResponseList, keepRunning, this::handleCommandResponseMessage, 1); + + log.debug("Sending command"); + solacePublisher.publish(message, + "sc/ep/runtime/" + eventPortalProperties.getOrganizationId() + "/" + + eventPortalProperties.getRuntimeAgentId() + "/command/v1/" + + correlationId); + + waitForReceivedMessages(keepRunning); + + return commandResponseList.get(0); + } + + private static void waitForReceivedMessages(AtomicBoolean keepRunning) { + while (keepRunning.get()) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + + private void setupMessageReceiver(List commandMessageList, AtomicBoolean keepRunning, + Function5ArityVoidReturn, AtomicBoolean, InboundMessage, Integer, AtomicInteger> messageHandler, + int numberOfExpectedMessages) { + log.debug("TEST: Starting receiver"); + AtomicInteger numberOfMessagesReceived = new AtomicInteger(0); + DirectMessageReceiver directMessageReceiver = messagingService + .createDirectMessageReceiverBuilder() + .withSubscriptions(TopicSubscription.of("sc/ep/runtime/" + + eventPortalProperties.getOrganizationId() + "/" + + eventPortalProperties.getRuntimeAgentId() + + "/commandResponse/v1/>")) + .build() + .start(); + + directMessageReceiver.receiveAsync(inboundMessage -> + messageHandler.apply(commandMessageList, keepRunning, inboundMessage, numberOfExpectedMessages, numberOfMessagesReceived)); + } + + private void handleCommandResponseMessage(List commandResponseList, AtomicBoolean keepRunning, + InboundMessage inboundMessage, int numberOfExpectedMessages, AtomicInteger numberOfMessagesReceived) { + String messageAsString = inboundMessage.getPayloadAsString(); + try { + CommandMessage receivedCommandMessage = objectMapper.readValue(messageAsString, CommandMessage.class); + log.debug("TEST: Received command response"); + commandResponseList.add(receivedCommandMessage); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } finally { + numberOfMessagesReceived.getAndIncrement(); + if (numberOfMessagesReceived.get() >= numberOfExpectedMessages) { + keepRunning.set(false); + } + } + } + + private void validateSuccessCommandResponse(CommandMessage commandResponse) { + List results = commandResponse.getCommandBundles().stream() + .map(commandBundle -> + commandBundle.getCommands().stream() + .map(command -> command.getResult().getStatus()) + .toList()) + .flatMap(List::stream) + .toList(); + results.forEach(result -> { + if (result != JobStatus.success) { + throw new RuntimeException("JobStatus was not success"); + } + }); + } + + private void validateErrorCommandResponse(CommandMessage commandResponse) { + List results = commandResponse.getCommandBundles().stream() + .map(commandBundle -> + commandBundle.getCommands().stream() + .map(command -> command.getResult().getStatus()) + .toList()) + .flatMap(List::stream) + .toList(); + results.forEach(result -> { + if (result != JobStatus.error) { + throw new RuntimeException("JobStatus was not success"); + } + }); + log.debug("Received expected error response"); + testOutput("\nTEST OUTPUT:"); + testOutputMDCodeBlock(); + commandResponse.getCommandBundles().get(0).getCommands().get(0).getResult().getLogs() + .forEach(tflog -> { + testOutput(tflog.toString()); + }); + testOutputMDCodeBlock(); + testOutput("Elapsed time (seconds): " + (System.currentTimeMillis() - startTime) / 1000); + } + + private void setMessageParams(String serviceId, String correlationId, String context, CommandMessage message) { + message.withMessageType(generic); + message.setMopVer("1"); + message.setMopProtocol(epConfigPush); + message.setMopMsgType(generic); + message.setMsgPriority(4); + message.setMsgUh(MOPUHFlag.ignore); + message.setContext(context); + message.setActorId("myActorId"); + message.setOrgId(eventPortalProperties.getOrganizationId()); + message.setTraceId("myTraceId"); + message.setServiceId(serviceId); + message.setCorrelationId(correlationId); + } + + + public static String asString(Resource resource) { + try (Reader reader = new InputStreamReader(resource.getInputStream(), UTF_8)) { + return FileCopyUtils.copyToString(reader); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + private CommandMessage createCommandMessageMissingParameters(String serviceId, String correlationId, String context, + String newQueueTfBase64) { + CommandMessage commandMessage = createCommandMessageCommand(serviceId, correlationId, context, newQueueTfBase64); + Command command = commandMessage.getCommandBundles().get(0).getCommands().get(0); + command.setParameters(Map.of()); + return commandMessage; + } + + private CommandMessage createCommandMessageBadTerraformCommand(String serviceId, String correlationId, String context, + String newQueueTfBase64) { + CommandMessage commandMessage = createCommandMessageCommand(serviceId, correlationId, context, newQueueTfBase64); + Command command = commandMessage.getCommandBundles().get(0).getCommands().get(0); + command.setCommand("badCommand"); + return commandMessage; + } + + private CommandMessage createCommandMessageHclNotBase64Encoded(String serviceId, String correlationId, String context, + String newQueueTfBase64) { + CommandMessage commandMessage = createCommandMessageCommand(serviceId, correlationId, context, newQueueTfBase64); + Command command = commandMessage.getCommandBundles().get(0).getCommands().get(0); + command.setBody("IHaveABadBody"); + return commandMessage; + } + + private CommandMessage createCommandMessageBadCommandType(String serviceId, String correlationId, String context, + String newQueueTfBase64) { + CommandMessage message = new CommandMessage(); + setMessageParams(serviceId, correlationId, context, message); + + BadCommand badCommand = new BadCommand(); + badCommand.setCommandType(CommandTypeBad.badEnum); + badCommand.setBody(newQueueTfBase64); + badCommand.setParameters(Map.of( + "Content-Type", "application/hcl", + "Content-Encoding", "base64")); + badCommand.setCommand("apply"); + + message.setCommandBundles(List.of(CommandBundle.builder() + .executionType(ExecutionType.serial) + .exitOnFailure(true) + .commands( + List.of(badCommand)) + .build())); + return message; + } + + private CommandMessage createCommandMessageCommand(String serviceId, String correlationId, String context, + String newQueueTfBase64) { + CommandMessage message = new CommandMessage(); + setMessageParams(serviceId, correlationId, context, message); + message.setCommandBundles(List.of(CommandBundle.builder() + .executionType(ExecutionType.serial) + .exitOnFailure(true) + .commands( + List.of(Command.builder() + .commandType(CommandType.terraform) + .body(newQueueTfBase64) + .parameters(Map.of( + "Content-Type", "application/hcl", + "Content-Encoding", "base64")) + .command("apply") + .build())) + .build())); + return message; + } + + @FunctionalInterface + public interface Function5ArityVoidReturn { + void apply(A a, B b, C c, D d, E e); + } + + @FunctionalInterface + public interface Function4ArityWithReturn { + R apply(A a, B b, C c, D d); + } + + private void testOutput(String logMessage) { + log.info(logMessage); + } + + private void testOutputMdTitle2(String logMessage) { + log.info("\n## " + logMessage); + } + + private void testOutputMDCodeBlock() { + log.info("```"); + } + + private String getTestMethodName() { + final StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); + return stackTraceElements[2].getMethodName(); + } +} diff --git a/service/application/src/test/java/com/solace/maas/ep/event/management/agent/realTests/OfflineRealTest.java b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/realTests/OfflineRealTest.java new file mode 100644 index 000000000..dbcb60cd1 --- /dev/null +++ b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/realTests/OfflineRealTest.java @@ -0,0 +1,27 @@ +package com.solace.maas.ep.event.management.agent.realTests; + +import com.solace.maas.ep.event.management.agent.config.eventPortal.EventPortalProperties; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; + +import static org.junit.Assert.assertTrue; + +@Slf4j +@ActiveProfiles("offlinetests") +@EnableAutoConfiguration +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class OfflineRealTest { + + @Autowired + private EventPortalProperties eventPortalProperties; + + @Test + public void applicationStartsInOfflineMode() { + assertTrue(eventPortalProperties.getGateway().getMessaging().isStandalone()); + } + +} \ No newline at end of file diff --git a/service/application/src/test/java/com/solace/maas/ep/event/management/agent/realTests/badClasses/BadCommand.java b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/realTests/badClasses/BadCommand.java new file mode 100644 index 000000000..632d7880b --- /dev/null +++ b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/realTests/badClasses/BadCommand.java @@ -0,0 +1,12 @@ +package com.solace.maas.ep.event.management.agent.realTests.badClasses; + +import com.solace.maas.ep.event.management.agent.plugin.command.model.Command; + +@SuppressWarnings("PMD") +public class BadCommand extends Command { + private CommandTypeBad commandType; + + public void setCommandType(CommandTypeBad commandType) { + this.commandType = commandType; + } +} diff --git a/service/application/src/test/java/com/solace/maas/ep/event/management/agent/realTests/badClasses/CommandTypeBad.java b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/realTests/badClasses/CommandTypeBad.java new file mode 100644 index 000000000..d6d816135 --- /dev/null +++ b/service/application/src/test/java/com/solace/maas/ep/event/management/agent/realTests/badClasses/CommandTypeBad.java @@ -0,0 +1,7 @@ +package com.solace.maas.ep.event.management.agent.realTests.badClasses; + +public enum CommandTypeBad { + terraform, + badEnum +} + diff --git a/service/application/src/test/resources/application-negativetests.yml b/service/application/src/test/resources/application-negativetests.yml new file mode 100644 index 000000000..3985aa8f8 --- /dev/null +++ b/service/application/src/test/resources/application-negativetests.yml @@ -0,0 +1,130 @@ +springdoc: + packages-to-scan: com.solace.maas.ep.event.management.agent.scanManager.rest + api-docs: + path: /docs/event-management-agent + swagger-ui: + path: /event-management-agent/swagger-ui.html +server: + port: 8180 +spring: + main: + allow-bean-definition-overriding: true + servlet: + multipart: + max-request-size: ${MAX_REQUEST_SIZE:5MB} + max-file-size: ${MAX_FILE_SIZE:5MB} + jpa: + database-platform: org.hibernate.dialect.H2Dialect + hibernate: + ddl-auto: create-drop + defer-datasource-initialization: true + datasource: + url: jdbc:h2:file:./data/cache;DB_CLOSE_ON_EXIT=FALSE + username: sa + driver-class-name: org.h2.Driver + password: password + h2: + console: + settings: + web-allow-others: true + enabled: true + path: /h2 +camel: + springboot: + use-mdc-logging: true +kafka: + client: + config: + reconnections: + max-backoff: + unit: milliseconds + value: 1000 + backoff: + unit: milliseconds + value: 50 + connections: + max-idle: + unit: milliseconds + value: 10000 + request-timeout: + unit: milliseconds + value: 5000 + timeout: + unit: milliseconds + value: 60000 +eventPortal: + topicPrefix: ${EP_TOPIC_PREFIX:sc/ep/runtime} + runtimeAgentId: ${EP_RUNTIME_AGENT_ID} + organizationId: ${EP_ORGANIZATION_ID} + gateway: + id: 1n257sln2bl + name: the ep vmr + messaging: + standalone: false + rtoSession: false + enableHeartbeats: true + testHeartbeats: true + connections: + - name: eventPortalGateway + authenticationType: ${EP_GATEWAY_AUTH:basicAuthentication} + msgVpn: ${EP_GATEWAY_MSGVPN} + url: ${EP_GATEWAY_URL} + users: + - clientName: client_7zu3ng4ed37 + username: ${EP_GATEWAY_USERNAME} + password: ${EP_GATEWAY_PASSWORD} + name: messaging1 +plugins: + resources: + - id: 49a23700m80 + type: solace + name: demo2 + connections: + - name: demo2 + url: ${SOLACE_SEMP_URL} + properties: + - name: msgVpn + value: default + - name: sempPageSize + value: 100 + authentication: + - properties: + - name: type + value: basicAuthentication + protocol: semp + credentials: + - properties: + - name: username + value: ${SOLACE_SEMP_USERNAME} + - name: password + value: ${SOLACE_SEMP_PASSWORD} + source: ENVIRONMENT_VARIABLE + operations: + - name: ALL + - id: v0r806w0bmj + type: solace + name: gregSolaceService + connections: + - name: gregSolaceService + url: ${OLD_SOLACE_SEMP_URL} + properties: + - name: msgVpn + value: default + - name: sempPageSize + value: 100 + authentication: + - properties: + - name: type + value: basicAuthentication + protocol: semp + credentials: + - properties: + - name: username + value: ${OLD_SOLACE_SEMP_USERNAME} + - name: password + value: ${OLD_SOLACE_SEMP_PASSWORD} + source: ENVIRONMENT_VARIABLE + operations: + - name: ALL +logging: + config: "classpath:logback-spring-negativetests.xml" diff --git a/service/application/src/test/resources/application-offlinetests.yml b/service/application/src/test/resources/application-offlinetests.yml new file mode 100644 index 000000000..a2f72a7d2 --- /dev/null +++ b/service/application/src/test/resources/application-offlinetests.yml @@ -0,0 +1,130 @@ +springdoc: + packages-to-scan: com.solace.maas.ep.event.management.agent.scanManager.rest + api-docs: + path: /docs/event-management-agent + swagger-ui: + path: /event-management-agent/swagger-ui.html +server: + port: 8180 +spring: + main: + allow-bean-definition-overriding: true + servlet: + multipart: + max-request-size: ${MAX_REQUEST_SIZE:5MB} + max-file-size: ${MAX_FILE_SIZE:5MB} + jpa: + database-platform: org.hibernate.dialect.H2Dialect + hibernate: + ddl-auto: create-drop + defer-datasource-initialization: true + datasource: + url: jdbc:h2:file:./data/cache;DB_CLOSE_ON_EXIT=FALSE + username: sa + driver-class-name: org.h2.Driver + password: password + h2: + console: + settings: + web-allow-others: true + enabled: true + path: /h2 +camel: + springboot: + use-mdc-logging: true +kafka: + client: + config: + reconnections: + max-backoff: + unit: milliseconds + value: 1000 + backoff: + unit: milliseconds + value: 50 + connections: + max-idle: + unit: milliseconds + value: 10000 + request-timeout: + unit: milliseconds + value: 5000 + timeout: + unit: milliseconds + value: 60000 +eventPortal: + topicPrefix: ${EP_TOPIC_PREFIX:sc/ep/runtime} + runtimeAgentId: ${EP_RUNTIME_AGENT_ID} + organizationId: ${EP_ORGANIZATION_ID} + gateway: + id: 1n257sln2bl + name: the ep vmr + messaging: + standalone: true + rtoSession: false + enableHeartbeats: true + testHeartbeats: true + connections: + - name: eventPortalGateway + authenticationType: ${EP_GATEWAY_AUTH:basicAuthentication} + msgVpn: ${EP_GATEWAY_MSGVPN} + url: ${EP_GATEWAY_URL} + users: + - clientName: client_7zu3ng4ed37 + username: ${EP_GATEWAY_USERNAME} + password: ${EP_GATEWAY_PASSWORD} + name: messaging1 +plugins: + resources: + - id: 49a23700m80 + type: solace + name: demo2 + connections: + - name: demo2 + url: ${SOLACE_SEMP_URL} + properties: + - name: msgVpn + value: default + - name: sempPageSize + value: 100 + authentication: + - properties: + - name: type + value: basicAuthentication + protocol: semp + credentials: + - properties: + - name: username + value: ${SOLACE_SEMP_USERNAME} + - name: password + value: ${SOLACE_SEMP_PASSWORD} + source: ENVIRONMENT_VARIABLE + operations: + - name: ALL + - id: v0r806w0bmj + type: solace + name: gregSolaceService + connections: + - name: gregSolaceService + url: ${OLD_SOLACE_SEMP_URL} + properties: + - name: msgVpn + value: default + - name: sempPageSize + value: 100 + authentication: + - properties: + - name: type + value: basicAuthentication + protocol: semp + credentials: + - properties: + - name: username + value: ${OLD_SOLACE_SEMP_USERNAME} + - name: password + value: ${OLD_SOLACE_SEMP_PASSWORD} + source: ENVIRONMENT_VARIABLE + operations: + - name: ALL +logging: + config: "classpath:logback-spring-offlinetests.xml" \ No newline at end of file diff --git a/service/application/src/test/resources/hcl/AddQueueReadOnlyUser.tf b/service/application/src/test/resources/hcl/AddQueueReadOnlyUser.tf new file mode 100644 index 000000000..086fefc62 --- /dev/null +++ b/service/application/src/test/resources/hcl/AddQueueReadOnlyUser.tf @@ -0,0 +1,102 @@ +terraform { + required_providers { + solacebroker = { + source = "registry.terraform.io/solaceproducts/solacebroker" + } + } +} + +provider "solacebroker" { + alias = "fh71c08said" + username = "admin2" + password = "${var.password}" + url = "${var.url}" +} + +data "solacebroker_msg_vpn" "fh71c08said" { + provider = solacebroker.fh71c08said + msg_vpn_name = "default" +} + +resource "solacebroker_msg_vpn_queue" "fh71c08said-Consumer2" { + provider = solacebroker.fh71c08said + msg_vpn_name = data.solacebroker_msg_vpn.fh71c08said.msg_vpn_name + owner = "discovery" + max_ttl = 0 + queue_name = "Consumer2" + access_type = "exclusive" + max_msg_size = 10000000 + permission = "consume" + dead_msg_queue = "#DEAD_MSG_QUEUE" + max_bind_count = 1000 + delivery_delay = 0 + egress_enabled = true + ingress_enabled = true + max_msg_spool_usage = 5000 + redelivery_enabled = true + respect_ttl_enabled = false + max_redelivery_count = 0 + delivery_count_enabled = false + event_bind_count_threshold = { "setPercent" : 80, "clearPercent" : 60 } + reject_low_priority_msg_limit = 0 + respect_msg_priority_enabled = false + event_msg_spool_usage_threshold = { "setPercent" : 25, "clearPercent" : 18 } + reject_low_priority_msg_enabled = false + consumer_ack_propagation_enabled = true + max_delivered_unacked_msgs_per_flow = 10000 + reject_msg_to_sender_on_discard_behavior = "when-queue-enabled" + event_reject_low_priority_msg_limit_threshold = { "setPercent" : 80, "clearPercent" : 60 } +} + +resource "solacebroker_msg_vpn_queue_subscription" "fh71c08said-Consumer2_a_b_c__" { + provider = solacebroker.fh71c08said + msg_vpn_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer2.msg_vpn_name + queue_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer2.queue_name + subscription_topic = "a/b/c/>" +} + +resource "solacebroker_msg_vpn_queue" "fh71c08said-Consumer1" { + provider = solacebroker.fh71c08said + msg_vpn_name = data.solacebroker_msg_vpn.fh71c08said.msg_vpn_name + owner = "discovery" + max_ttl = 0 + queue_name = "Consumer2" + access_type = "exclusive" + max_msg_size = 10000000 + permission = "consume" + dead_msg_queue = "#DEAD_MSG_QUEUE" + max_bind_count = 1000 + delivery_delay = 0 + egress_enabled = true + ingress_enabled = true + max_msg_spool_usage = 5000 + redelivery_enabled = true + respect_ttl_enabled = false + max_redelivery_count = 0 + delivery_count_enabled = false + event_bind_count_threshold = { "setPercent" : 80, "clearPercent" : 60 } + reject_low_priority_msg_limit = 0 + respect_msg_priority_enabled = false + event_msg_spool_usage_threshold = { "setPercent" : 25, "clearPercent" : 18 } + reject_low_priority_msg_enabled = false + consumer_ack_propagation_enabled = true + max_delivered_unacked_msgs_per_flow = 10000 + reject_msg_to_sender_on_discard_behavior = "when-queue-enabled" + event_reject_low_priority_msg_limit_threshold = { "setPercent" : 80, "clearPercent" : 60 } +} + +resource "solacebroker_msg_vpn_queue_subscription" "fh71c08said-Consumer1_a_b_c__" { + provider = solacebroker.fh71c08said + msg_vpn_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.msg_vpn_name + queue_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.queue_name + subscription_topic = "a/b/c/>" +} + +variable username { +} + +variable password { +} + +variable url { +} \ No newline at end of file diff --git a/service/application/src/test/resources/hcl/addQueue.tf b/service/application/src/test/resources/hcl/addQueue.tf new file mode 100644 index 000000000..641ae0266 --- /dev/null +++ b/service/application/src/test/resources/hcl/addQueue.tf @@ -0,0 +1,65 @@ +terraform { + required_providers { + solacebroker = { + source = "registry.terraform.io/solaceproducts/solacebroker" + } + } +} + +provider "solacebroker" { + alias = "fh71c08said" + username = "${var.username}" + password = "${var.password}" + url = "${var.url}" +} + +data "solacebroker_msg_vpn" "fh71c08said" { + provider = solacebroker.fh71c08said + msg_vpn_name = "default" +} + +resource "solacebroker_msg_vpn_queue" "fh71c08said-Consumer1" { + provider = solacebroker.fh71c08said + msg_vpn_name = data.solacebroker_msg_vpn.fh71c08said.msg_vpn_name + owner = "discovery" + max_ttl = 0 + queue_name = "Consumer1" + access_type = "exclusive" + max_msg_size = 10000000 + permission = "consume" + dead_msg_queue = "#DEAD_MSG_QUEUE" + max_bind_count = 1000 + delivery_delay = 0 + egress_enabled = true + ingress_enabled = true + max_msg_spool_usage = 5000 + redelivery_enabled = true + respect_ttl_enabled = false + max_redelivery_count = 0 + delivery_count_enabled = false + event_bind_count_threshold = { "setPercent" : 80, "clearPercent" : 60 } + reject_low_priority_msg_limit = 0 + respect_msg_priority_enabled = false + event_msg_spool_usage_threshold = { "setPercent" : 25, "clearPercent" : 18 } + reject_low_priority_msg_enabled = false + consumer_ack_propagation_enabled = true + max_delivered_unacked_msgs_per_flow = 10000 + reject_msg_to_sender_on_discard_behavior = "when-queue-enabled" + event_reject_low_priority_msg_limit_threshold = { "setPercent" : 80, "clearPercent" : 60 } +} + +resource "solacebroker_msg_vpn_queue_subscription" "fh71c08said-Consumer1_a_b_c__" { + provider = solacebroker.fh71c08said + msg_vpn_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.msg_vpn_name + queue_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.queue_name + subscription_topic = "a/b/c/>" +} + +variable username { +} + +variable password { +} + +variable url { +} \ No newline at end of file diff --git a/service/application/src/test/resources/hcl/addQueue2.tf b/service/application/src/test/resources/hcl/addQueue2.tf new file mode 100644 index 000000000..0371cd991 --- /dev/null +++ b/service/application/src/test/resources/hcl/addQueue2.tf @@ -0,0 +1,65 @@ +terraform { + required_providers { + solacebroker = { + source = "registry.terraform.io/solaceproducts/solacebroker" + } + } +} + +provider "solacebroker" { + alias = "fh71c08saie" + username = "${var.username}" + password = "${var.password}" + url = "${var.url}" +} + +data "solacebroker_msg_vpn" "fh71c08saie" { + provider = solacebroker.fh71c08saie + msg_vpn_name = "default" +} + +resource "solacebroker_msg_vpn_queue" "fh71c08saie-Consumer2" { + provider = solacebroker.fh71c08saie + msg_vpn_name = data.solacebroker_msg_vpn.fh71c08saie.msg_vpn_name + owner = "discovery" + max_ttl = 0 + queue_name = "Consumer2" + access_type = "exclusive" + max_msg_size = 10000000 + permission = "consume" + dead_msg_queue = "#DEAD_MSG_QUEUE" + max_bind_count = 1000 + delivery_delay = 0 + egress_enabled = true + ingress_enabled = true + max_msg_spool_usage = 5000 + redelivery_enabled = true + respect_ttl_enabled = false + max_redelivery_count = 0 + delivery_count_enabled = false + event_bind_count_threshold = { "setPercent" : 80, "clearPercent" : 60 } + reject_low_priority_msg_limit = 0 + respect_msg_priority_enabled = false + event_msg_spool_usage_threshold = { "setPercent" : 25, "clearPercent" : 18 } + reject_low_priority_msg_enabled = false + consumer_ack_propagation_enabled = true + max_delivered_unacked_msgs_per_flow = 10000 + reject_msg_to_sender_on_discard_behavior = "when-queue-enabled" + event_reject_low_priority_msg_limit_threshold = { "setPercent" : 80, "clearPercent" : 60 } +} + +resource "solacebroker_msg_vpn_queue_subscription" "fh71c08saie-Consumer2_a_b_c__" { + provider = solacebroker.fh71c08saie + msg_vpn_name = solacebroker_msg_vpn_queue.fh71c08saie-Consumer2.msg_vpn_name + queue_name = solacebroker_msg_vpn_queue.fh71c08saie-Consumer2.queue_name + subscription_topic = "a/b/c/>" +} + +variable username { +} + +variable password { +} + +variable url { +} \ No newline at end of file diff --git a/service/application/src/test/resources/hcl/addQueueBadCredentials.tf b/service/application/src/test/resources/hcl/addQueueBadCredentials.tf new file mode 100644 index 000000000..b8a1f8dfa --- /dev/null +++ b/service/application/src/test/resources/hcl/addQueueBadCredentials.tf @@ -0,0 +1,65 @@ +terraform { + required_providers { + solacebroker = { + source = "registry.terraform.io/solaceproducts/solacebroker" + } + } +} + +provider "solacebroker" { + alias = "fh71c08said" + username = "${var.username}" + password = "badpassword" + url = "${var.url}" +} + +data "solacebroker_msg_vpn" "fh71c08said" { + provider = solacebroker.fh71c08said + msg_vpn_name = "default" +} + +resource "solacebroker_msg_vpn_queue" "fh71c08said-Consumer1" { + provider = solacebroker.fh71c08said + msg_vpn_name = data.solacebroker_msg_vpn.fh71c08said.msg_vpn_name + owner = "discovery" + max_ttl = 0 + queue_name = "Consumer1" + access_type = "exclusive" + max_msg_size = 10000000 + permission = "consume" + dead_msg_queue = "#DEAD_MSG_QUEUE" + max_bind_count = 1000 + delivery_delay = 0 + egress_enabled = true + ingress_enabled = true + max_msg_spool_usage = 5000 + redelivery_enabled = true + respect_ttl_enabled = false + max_redelivery_count = 0 + delivery_count_enabled = false + event_bind_count_threshold = { "setPercent" : 80, "clearPercent" : 60 } + reject_low_priority_msg_limit = 0 + respect_msg_priority_enabled = false + event_msg_spool_usage_threshold = { "setPercent" : 25, "clearPercent" : 18 } + reject_low_priority_msg_enabled = false + consumer_ack_propagation_enabled = true + max_delivered_unacked_msgs_per_flow = 10000 + reject_msg_to_sender_on_discard_behavior = "when-queue-enabled" + event_reject_low_priority_msg_limit_threshold = { "setPercent" : 80, "clearPercent" : 60 } +} + +resource "solacebroker_msg_vpn_queue_subscription" "fh71c08said-Consumer1_a_b_c__" { + provider = solacebroker.fh71c08said + msg_vpn_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.msg_vpn_name + queue_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.queue_name + subscription_topic = "a/b/c/>" +} + +variable username { +} + +variable password { +} + +variable url { +} \ No newline at end of file diff --git a/service/application/src/test/resources/hcl/addQueueBadHost.tf b/service/application/src/test/resources/hcl/addQueueBadHost.tf new file mode 100644 index 000000000..a6f657a8b --- /dev/null +++ b/service/application/src/test/resources/hcl/addQueueBadHost.tf @@ -0,0 +1,65 @@ +terraform { + required_providers { + solacebroker = { + source = "registry.terraform.io/solaceproducts/solacebroker" + } + } +} + +provider "solacebroker" { + alias = "fh71c08said" + username = "${var.username}" + password = "${var.password}" + url = "http://badurl:43434" +} + +data "solacebroker_msg_vpn" "fh71c08said" { + provider = solacebroker.fh71c08said + msg_vpn_name = "default" +} + +resource "solacebroker_msg_vpn_queue" "fh71c08said-Consumer1" { + provider = solacebroker.fh71c08said + msg_vpn_name = data.solacebroker_msg_vpn.fh71c08said.msg_vpn_name + owner = "discovery" + max_ttl = 0 + queue_name = "Consumer1" + access_type = "exclusive" + max_msg_size = 10000000 + permission = "consume" + dead_msg_queue = "#DEAD_MSG_QUEUE" + max_bind_count = 1000 + delivery_delay = 0 + egress_enabled = true + ingress_enabled = true + max_msg_spool_usage = 5000 + redelivery_enabled = true + respect_ttl_enabled = false + max_redelivery_count = 0 + delivery_count_enabled = false + event_bind_count_threshold = { "setPercent" : 80, "clearPercent" : 60 } + reject_low_priority_msg_limit = 0 + respect_msg_priority_enabled = false + event_msg_spool_usage_threshold = { "setPercent" : 25, "clearPercent" : 18 } + reject_low_priority_msg_enabled = false + consumer_ack_propagation_enabled = true + max_delivered_unacked_msgs_per_flow = 10000 + reject_msg_to_sender_on_discard_behavior = "when-queue-enabled" + event_reject_low_priority_msg_limit_threshold = { "setPercent" : 80, "clearPercent" : 60 } +} + +resource "solacebroker_msg_vpn_queue_subscription" "fh71c08said-Consumer1_a_b_c__" { + provider = solacebroker.fh71c08said + msg_vpn_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.msg_vpn_name + queue_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.queue_name + subscription_topic = "a/b/c/>" +} + +variable username { +} + +variable password { +} + +variable url { +} \ No newline at end of file diff --git a/service/application/src/test/resources/hcl/addQueueBadPort.tf b/service/application/src/test/resources/hcl/addQueueBadPort.tf new file mode 100644 index 000000000..aec54e905 --- /dev/null +++ b/service/application/src/test/resources/hcl/addQueueBadPort.tf @@ -0,0 +1,65 @@ +terraform { + required_providers { + solacebroker = { + source = "registry.terraform.io/solaceproducts/solacebroker" + } + } +} + +provider "solacebroker" { + alias = "fh71c08said" + username = "${var.username}" + password = "${var.password}" + url = "${var.url}33" +} + +data "solacebroker_msg_vpn" "fh71c08said" { + provider = solacebroker.fh71c08said + msg_vpn_name = "default" +} + +resource "solacebroker_msg_vpn_queue" "fh71c08said-Consumer1" { + provider = solacebroker.fh71c08said + msg_vpn_name = data.solacebroker_msg_vpn.fh71c08said.msg_vpn_name + owner = "discovery" + max_ttl = 0 + queue_name = "Consumer1" + access_type = "exclusive" + max_msg_size = 10000000 + permission = "consume" + dead_msg_queue = "#DEAD_MSG_QUEUE" + max_bind_count = 1000 + delivery_delay = 0 + egress_enabled = true + ingress_enabled = true + max_msg_spool_usage = 5000 + redelivery_enabled = true + respect_ttl_enabled = false + max_redelivery_count = 0 + delivery_count_enabled = false + event_bind_count_threshold = { "setPercent" : 80, "clearPercent" : 60 } + reject_low_priority_msg_limit = 0 + respect_msg_priority_enabled = false + event_msg_spool_usage_threshold = { "setPercent" : 25, "clearPercent" : 18 } + reject_low_priority_msg_enabled = false + consumer_ack_propagation_enabled = true + max_delivered_unacked_msgs_per_flow = 10000 + reject_msg_to_sender_on_discard_behavior = "when-queue-enabled" + event_reject_low_priority_msg_limit_threshold = { "setPercent" : 80, "clearPercent" : 60 } +} + +resource "solacebroker_msg_vpn_queue_subscription" "fh71c08said-Consumer1_a_b_c__" { + provider = solacebroker.fh71c08said + msg_vpn_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.msg_vpn_name + queue_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.queue_name + subscription_topic = "a/b/c/>" +} + +variable username { +} + +variable password { +} + +variable url { +} \ No newline at end of file diff --git a/service/application/src/test/resources/hcl/addQueueNewVariableNotInPlugin.tf b/service/application/src/test/resources/hcl/addQueueNewVariableNotInPlugin.tf new file mode 100644 index 000000000..45bcdea78 --- /dev/null +++ b/service/application/src/test/resources/hcl/addQueueNewVariableNotInPlugin.tf @@ -0,0 +1,65 @@ +terraform { + required_providers { + solacebroker = { + source = "registry.terraform.io/solaceproducts/solacebroker" + } + } +} + +provider "solacebroker" { + alias = "fh71c08said" + username = "${var.username}" + password = "${var.passwordd}" + url = "${var.url}" +} + +data "solacebroker_msg_vpn" "fh71c08said" { + provider = solacebroker.fh71c08said + msg_vpn_name = "default" +} + +resource "solacebroker_msg_vpn_queue" "fh71c08said-Consumer1" { + provider = solacebroker.fh71c08said + msg_vpn_name = data.solacebroker_msg_vpn.fh71c08said.msg_vpn_name + owner = "discovery" + max_ttl = 0 + queue_name = "Consumer1" + access_type = "exclusive" + max_msg_size = 10000000 + permission = "consume" + dead_msg_queue = "#DEAD_MSG_QUEUE" + max_bind_count = 1000 + delivery_delay = 0 + egress_enabled = true + ingress_enabled = true + max_msg_spool_usage = 5000 + redelivery_enabled = true + respect_ttl_enabled = false + max_redelivery_count = 0 + delivery_count_enabled = false + event_bind_count_threshold = { "setPercent" : 80, "clearPercent" : 60 } + reject_low_priority_msg_limit = 0 + respect_msg_priority_enabled = false + event_msg_spool_usage_threshold = { "setPercent" : 25, "clearPercent" : 18 } + reject_low_priority_msg_enabled = false + consumer_ack_propagation_enabled = true + max_delivered_unacked_msgs_per_flow = 10000 + reject_msg_to_sender_on_discard_behavior = "when-queue-enabled" + event_reject_low_priority_msg_limit_threshold = { "setPercent" : 80, "clearPercent" : 60 } +} + +resource "solacebroker_msg_vpn_queue_subscription" "fh71c08said-Consumer1_a_b_c__" { + provider = solacebroker.fh71c08said + msg_vpn_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.msg_vpn_name + queue_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.queue_name + subscription_topic = "a/b/c/>" +} + +variable username { +} + +variable password { +} + +variable url { +} \ No newline at end of file diff --git a/service/application/src/test/resources/hcl/badBlockHcl.tf b/service/application/src/test/resources/hcl/badBlockHcl.tf new file mode 100644 index 000000000..2b73c978d --- /dev/null +++ b/service/application/src/test/resources/hcl/badBlockHcl.tf @@ -0,0 +1,65 @@ +terraform { + required_providers { + solacebroker = { + source = "registry.terraform.io/solaceproducts/solacebroker" + } + } +} + +provider "solacebroker" { + alias = "fh71c08said" + username = "${var.username}" + password = "${var.password}" + url = "${var.url}" +} + +datam "solacebroker_msg_vpn" "fh71c08said" { + provider = solacebroker.fh71c08said + msg_vpn_name = "default" +} + +resource "solacebroker_msg_vpn_queue" "fh71c08said-Consumer1" { + provider = solacebroker.fh71c08said + msg_vpn_name = data.solacebroker_msg_vpn.fh71c08said.msg_vpn_name + owner = "discovery" + max_ttl = 0 + queue_name = "Consumer1" + access_type = "exclusive" + max_msg_size = 10000000 + permission = "consume" + dead_msg_queue = "#DEAD_MSG_QUEUE" + max_bind_count = 1000 + delivery_delay = 0 + egress_enabled = true + ingress_enabled = true + max_msg_spool_usage = 5000 + redelivery_enabled = true + respect_ttl_enabled = false + max_redelivery_count = 0 + delivery_count_enabled = false + event_bind_count_threshold = { "setPercent" : 80, "clearPercent" : 60 } + reject_low_priority_msg_limit = 0 + respect_msg_priority_enabled = false + event_msg_spool_usage_threshold = { "setPercent" : 25, "clearPercent" : 18 } + reject_low_priority_msg_enabled = false + consumer_ack_propagation_enabled = true + max_delivered_unacked_msgs_per_flow = 10000 + reject_msg_to_sender_on_discard_behavior = "when-queue-enabled" + event_reject_low_priority_msg_limit_threshold = { "setPercent" : 80, "clearPercent" : 60 } +} + +resource "solacebroker_msg_vpn_queue_subscription" "fh71c08said-Consumer1_a_b_c__" { + provider = solacebroker.fh71c08said + msg_vpn_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.msg_vpn_name + queue_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.queue_name + subscription_topic = "a/b/c/>" +} + +variable username { +} + +variable password { +} + +variable url { +} \ No newline at end of file diff --git a/service/application/src/test/resources/hcl/badFormatHcl.tf b/service/application/src/test/resources/hcl/badFormatHcl.tf new file mode 100644 index 000000000..4120f326f --- /dev/null +++ b/service/application/src/test/resources/hcl/badFormatHcl.tf @@ -0,0 +1,65 @@ +terraform { + required_providers { + solacebroker = { + source = "registry.terraform.io/solaceproducts/solacebroker" + } + } +} + +provider "solacebroker { + alias = "fh71c08said" + username = "${var.username}" + password = "${var.password}" + url = "${var.url}" +} + +datam "solacebroker_msg_vpn" "fh71c08said" { + provider = solacebroker.fh71c08said + msg_vpn_name = "default" +} + +resource "solacebroker_msg_vpn_queue" "fh71c08said-Consumer1" { + provider = solacebroker.fh71c08said + msg_vpn_name = data.solacebroker_msg_vpn.fh71c08said.msg_vpn_name + owner = "discovery" + max_ttl = 0 + queue_name = "Consumer1" + access_type = "exclusive" + max_msg_size = 10000000 + permission = "consume" + dead_msg_queue = "#DEAD_MSG_QUEUE" + max_bind_count = 1000 + delivery_delay = 0 + egress_enabled = true + ingress_enabled = true + max_msg_spool_usage = 5000 + redelivery_enabled = true + respect_ttl_enabled = false + max_redelivery_count = 0 + delivery_count_enabled = false + event_bind_count_threshold = { "setPercent" : 80, "clearPercent" : 60 } + reject_low_priority_msg_limit = 0 + respect_msg_priority_enabled = false + event_msg_spool_usage_threshold = { "setPercent" : 25, "clearPercent" : 18 } + reject_low_priority_msg_enabled = false + consumer_ack_propagation_enabled = true + max_delivered_unacked_msgs_per_flow = 10000 + reject_msg_to_sender_on_discard_behavior = "when-queue-enabled" + event_reject_low_priority_msg_limit_threshold = { "setPercent" : 80, "clearPercent" : 60 } +} + +resource "solacebroker_msg_vpn_queue_subscription" "fh71c08said-Consumer1_a_b_c__" { + provider = solacebroker.fh71c08said + msg_vpn_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.msg_vpn_name + queue_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.queue_name + subscription_topic = "a/b/c/>" +} + +variable username { +} + +variable password { +} + +variable url { +} \ No newline at end of file diff --git a/service/application/src/test/resources/hcl/badProvider.tf b/service/application/src/test/resources/hcl/badProvider.tf new file mode 100644 index 000000000..760657447 --- /dev/null +++ b/service/application/src/test/resources/hcl/badProvider.tf @@ -0,0 +1,65 @@ +terraform { + required_providers { + solacebroker = { + source = "registry.terraform.io/solaceproducts/solacebrokerz" + } + } +} + +provider "solacebroker" { + alias = "fh71c08said" + username = "${var.username}" + password = "${var.password}" + url = "${var.url}" +} + +data "solacebroker_msg_vpn" "fh71c08said" { + provider = solacebroker.fh71c08said + msg_vpn_name = "default" +} + +resource "solacebroker_msg_vpn_queue" "fh71c08said-Consumer1" { + provider = solacebroker.fh71c08said + msg_vpn_name = data.solacebroker_msg_vpn.fh71c08said.msg_vpn_name + owner = "discovery" + max_ttl = 0 + queue_name = "Consumer1" + access_type = "exclusive" + max_msg_size = 10000000 + permission = "consume" + dead_msg_queue = "#DEAD_MSG_QUEUE" + max_bind_count = 1000 + delivery_delay = 0 + egress_enabled = true + ingress_enabled = true + max_msg_spool_usage = 5000 + redelivery_enabled = true + respect_ttl_enabled = false + max_redelivery_count = 0 + delivery_count_enabled = false + event_bind_count_threshold = { "setPercent" : 80, "clearPercent" : 60 } + reject_low_priority_msg_limit = 0 + respect_msg_priority_enabled = false + event_msg_spool_usage_threshold = { "setPercent" : 25, "clearPercent" : 18 } + reject_low_priority_msg_enabled = false + consumer_ack_propagation_enabled = true + max_delivered_unacked_msgs_per_flow = 10000 + reject_msg_to_sender_on_discard_behavior = "when-queue-enabled" + event_reject_low_priority_msg_limit_threshold = { "setPercent" : 80, "clearPercent" : 60 } +} + +resource "solacebroker_msg_vpn_queue_subscription" "fh71c08said-Consumer1_a_b_c__" { + provider = solacebroker.fh71c08said + msg_vpn_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.msg_vpn_name + queue_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.queue_name + subscription_topic = "a/b/c/>" +} + +variable username { +} + +variable password { +} + +variable url { +} \ No newline at end of file diff --git a/service/application/src/test/resources/hcl/deleteQueue.tf b/service/application/src/test/resources/hcl/deleteQueue.tf new file mode 100644 index 000000000..f77bdee2a --- /dev/null +++ b/service/application/src/test/resources/hcl/deleteQueue.tf @@ -0,0 +1,28 @@ +terraform { + required_providers { + solacebroker = { + source = "registry.terraform.io/solaceproducts/solacebroker" + } + } +} + +provider "solacebroker" { + alias = "fh71c08said" + username = "${var.username}" + password = "${var.password}" + url = "${var.url}" +} + +data "solacebroker_msg_vpn" "fh71c08said" { + provider = solacebroker.fh71c08said + msg_vpn_name = "default" +} + +variable username { +} + +variable password { +} + +variable url { +} \ No newline at end of file diff --git a/service/application/src/test/resources/hcl/deleteQueue2.tf b/service/application/src/test/resources/hcl/deleteQueue2.tf new file mode 100644 index 000000000..67b64e5bd --- /dev/null +++ b/service/application/src/test/resources/hcl/deleteQueue2.tf @@ -0,0 +1,28 @@ +terraform { + required_providers { + solacebroker = { + source = "registry.terraform.io/solaceproducts/solacebroker" + } + } +} + +provider "solacebroker" { + alias = "fh71c08saie" + username = "${var.username}" + password = "${var.password}" + url = "${var.url}" +} + +data "solacebroker_msg_vpn" "fh71c08saie" { + provider = solacebroker.fh71c08saie + msg_vpn_name = "default" +} + +variable username { +} + +variable password { +} + +variable url { +} \ No newline at end of file diff --git a/service/application/src/test/resources/hcl/updateQueue.tf b/service/application/src/test/resources/hcl/updateQueue.tf new file mode 100644 index 000000000..4b5f7c75b --- /dev/null +++ b/service/application/src/test/resources/hcl/updateQueue.tf @@ -0,0 +1,65 @@ +terraform { + required_providers { + solacebroker = { + source = "registry.terraform.io/solaceproducts/solacebroker" + } + } +} + +provider "solacebroker" { + alias = "fh71c08said" + username = "${var.username}" + password = "${var.password}" + url = "${var.url}" +} + +data "solacebroker_msg_vpn" "fh71c08said" { + provider = solacebroker.fh71c08said + msg_vpn_name = "default" +} + +resource "solacebroker_msg_vpn_queue" "fh71c08said-Consumer1" { + provider = solacebroker.fh71c08said + msg_vpn_name = data.solacebroker_msg_vpn.fh71c08said.msg_vpn_name + owner = "discovery" + max_ttl = 0 + queue_name = "Consumer1" + access_type = "exclusive" + max_msg_size = 10000000 + permission = "consume" + dead_msg_queue = "#DEAD_MSG_QUEUE" + max_bind_count = 500 + delivery_delay = 0 + egress_enabled = true + ingress_enabled = true + max_msg_spool_usage = 5000 + redelivery_enabled = false + respect_ttl_enabled = false + max_redelivery_count = 0 + delivery_count_enabled = false + event_bind_count_threshold = { "setPercent" : 80, "clearPercent" : 60 } + reject_low_priority_msg_limit = 0 + respect_msg_priority_enabled = false + event_msg_spool_usage_threshold = { "setPercent" : 25, "clearPercent" : 18 } + reject_low_priority_msg_enabled = false + consumer_ack_propagation_enabled = true + max_delivered_unacked_msgs_per_flow = 10000 + reject_msg_to_sender_on_discard_behavior = "when-queue-enabled" + event_reject_low_priority_msg_limit_threshold = { "setPercent" : 80, "clearPercent" : 60 } +} + +resource "solacebroker_msg_vpn_queue_subscription" "fh71c08said-Consumer1_a_b_c__" { + provider = solacebroker.fh71c08said + msg_vpn_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.msg_vpn_name + queue_name = solacebroker_msg_vpn_queue.fh71c08said-Consumer1.queue_name + subscription_topic = "a/b/c/>" +} + +variable username { +} + +variable password { +} + +variable url { +} \ No newline at end of file diff --git a/service/application/src/test/resources/logback-spring-negativetests.xml b/service/application/src/test/resources/logback-spring-negativetests.xml new file mode 100644 index 000000000..6388cdf51 --- /dev/null +++ b/service/application/src/test/resources/logback-spring-negativetests.xml @@ -0,0 +1,75 @@ + + + + + + + + + EMA.log + + %d [%thread] %-5level %-50logger{40} : %msg%n + + + + EMA-%d{yyyy-MM-dd}.%i.log + 1MB + 30 + 10MB + false + + + + + TestOutput.log + + %msg%n + + + + TestOutput-%d{yyyy-MM-dd}.%i.log + 1MB + 30 + 10MB + false + + + + + + SCAN_ID + general-logs + + + + data_collection/logs/${SCAN_ID}.log + + [%X{SCAN_ID}] ------ %date [%level] [%thread] %logger{10} [%file:%line] %msg%n + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/service/application/src/test/resources/logback-spring-offlinetests.xml b/service/application/src/test/resources/logback-spring-offlinetests.xml new file mode 100644 index 000000000..bc30d5668 --- /dev/null +++ b/service/application/src/test/resources/logback-spring-offlinetests.xml @@ -0,0 +1,75 @@ + + + + + + + + + EMA.log + + %d [%thread] %-5level %-50logger{40} : %msg%n + + + + EMA-%d{yyyy-MM-dd}.%i.log + 1MB + 30 + 10MB + false + + + + + TestOutput.log + + %msg%n + + + + TestOutput-%d{yyyy-MM-dd}.%i.log + 1MB + 30 + 10MB + false + + + + + + SCAN_ID + general-logs + + + + data_collection/logs/${SCAN_ID}.log + + [%X{SCAN_ID}] ------ %date [%level] [%thread] %logger{10} [%file:%line] %msg%n + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/service/plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/publisher/SolacePublisher.java b/service/plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/publisher/SolacePublisher.java index ae94c1292..28a121c4c 100644 --- a/service/plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/publisher/SolacePublisher.java +++ b/service/plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/publisher/SolacePublisher.java @@ -2,6 +2,7 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import com.solace.maas.ep.event.management.agent.plugin.config.EnableRtoCondition; import com.solace.maas.ep.event.management.agent.plugin.mop.MOPConstants; import com.solace.maas.ep.event.management.agent.plugin.mop.MOPMessage; @@ -27,6 +28,10 @@ public class SolacePublisher { private final OutboundMessageBuilder outboundMessageBuilder; private final DirectMessagePublisher directMessagePublisher; + static { + mapper.registerModule(new JavaTimeModule()); + } + public SolacePublisher(OutboundMessageBuilder outboundMessageBuilder, DirectMessagePublisher directMessagePublisher) { this.outboundMessageBuilder = outboundMessageBuilder; diff --git a/service/terraform-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/terraform/manager/TerraformLogProcessingService.java b/service/terraform-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/terraform/manager/TerraformLogProcessingService.java index b73141f2c..2805fa177 100644 --- a/service/terraform-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/terraform/manager/TerraformLogProcessingService.java +++ b/service/terraform-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/terraform/manager/TerraformLogProcessingService.java @@ -121,16 +121,13 @@ private Map simplifyApplyErroredLog(Map expanded String.format("This method only handles logs of type %s", VALUE_TYPE_APPLY_ERRORED) ); } - //return expandedLogMessage; return Map.of( "address", extractResourceAddressFromDiagnostic(expandedLogMessage.get(KEY_DIAGNOSTIC)), KEY_DIAGNOSTIC_DETAIL, extractDiagnosticDetailMessage(expandedLogMessage.get(KEY_DIAGNOSTIC)), "message", expandedLogMessage.get(KEY_MESSAGE), "level", expandedLogMessage.get(KEY_LEVEL).toString().toUpperCase(), "timestamp", expandedLogMessage.get(KEY_TIMESTAMP) - ); - } private String extractDiagnosticDetailMessage(Object diagnostic) { diff --git a/service/terraform-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/terraform/manager/TerraformManager.java b/service/terraform-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/terraform/manager/TerraformManager.java index 2729f5643..0a7deaf88 100644 --- a/service/terraform-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/terraform/manager/TerraformManager.java +++ b/service/terraform-plugin/src/main/java/com/solace/maas/ep/event/management/agent/plugin/terraform/manager/TerraformManager.java @@ -34,7 +34,6 @@ public class TerraformManager { private final TerraformLogProcessingService terraformLogProcessingService; private final TerraformProperties terraformProperties; private final TerraformClientFactory terraformClientFactory; - private final static String TF_CONFIG_FILENAME = "config.tf"; public TerraformManager(TerraformLogProcessingService terraformLogProcessingService, @@ -89,8 +88,10 @@ private static String executeTerraformCommand(Command command, Map { writeHclToFile(command, configPath); - terraformClient.plan(envVars).get(); - terraformClient.apply(envVars).get(); + Boolean planSuccessful = terraformClient.plan(envVars).get(); + if (Boolean.TRUE.equals(planSuccessful)) { + terraformClient.apply(envVars).get(); + } } case "write_HCL" -> writeHclToFile(command, configPath); default -> throw new IllegalArgumentException("Unsupported command " + commandVerb); @@ -118,7 +119,7 @@ private void processTerraformResponse(CommandRequest request, Command command, S } } - private void setCommandError(Command command, Exception e) { + public static void setCommandError(Command command, Exception e) { command.setResult(CommandResult.builder() .status(JobStatus.error) .logs(List.of( @@ -152,7 +153,12 @@ private static void writeHclToFile(Command command, Path configPath) throws IOEx // At the moment, we only support base64 decoding Map parameters = command.getParameters(); if (parameters != null && parameters.containsKey("Content-Encoding") && "base64".equals(parameters.get("Content-Encoding"))) { - byte[] decodedBytes = Base64.getDecoder().decode(command.getBody()); + byte[] decodedBytes; + try { + decodedBytes = Base64.getDecoder().decode(command.getBody()); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("Error decoding base64 content", e); + } Files.write(configPath.resolve(TF_CONFIG_FILENAME), decodedBytes); } else { if (parameters == null || !parameters.containsKey("Content-Encoding")) {