diff --git a/src/main/java/controllers/DockerController.java b/src/main/java/controllers/DockerController.java index 0932be0..0bb3214 100644 --- a/src/main/java/controllers/DockerController.java +++ b/src/main/java/controllers/DockerController.java @@ -54,14 +54,17 @@ public void restartApp(@PathVariable("name") String name) { dockerService.restartContainer(name); } - // **Configure application settings** - @PostMapping("/Config/{id}") - @Operation(summary = "Configure an application", description = "Configures a specific application with the provided parameters.") + @PostMapping("/Config/byName/{name}") + @Operation( + summary = "Configure an application", + description = "Allows adding, updating, or deleting environment variables of a container. The JSON body must contain `add`, `update`, and/or `delete` keys." + ) @Tag(name = "Configuration") - public ResponseEntity configApp(@PathVariable("id") String id, @RequestBody Map config) { - return dockerService.configApp(id, config); + public ResponseEntity configAppByName(@PathVariable("name") String name, @RequestBody Map config) { + return dockerService.configApp(name, config); } + @PutMapping("IsCrash/{name}") @Operation(summary = "Check application crash status", description = "Checks whether a specific application has crashed.") @Tag(name = "Crash Status and Errors") diff --git a/src/main/java/services/DockerService.java b/src/main/java/services/DockerService.java index ca146c3..899b168 100644 --- a/src/main/java/services/DockerService.java +++ b/src/main/java/services/DockerService.java @@ -4,7 +4,6 @@ import com.github.dockerjava.api.command.*; import com.github.dockerjava.api.model.*; import model.ContainerRunParam; -import org.apache.catalina.Host; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -16,6 +15,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.*; @Service public class DockerService { @@ -150,34 +150,55 @@ public List listCrashedContainers() { .toList(); } - // Applique une nouvelle configuration d'environnement (redéploiement) - public ResponseEntity configApp(String id, Map conf) { + public ResponseEntity configApp(String name, Map conf) { + try { + Map envMap = new HashMap<>(); - var inspect = dockerClient.inspectContainerCmd(id).exec(); - ContainerRunParam params = new ContainerRunParam( - inspect.getName(), - inspect.getNetworkSettings().getPorts().toString(), - conf, - inspect.getImageId(), - null, - null - ); + InspectContainerResponse container = dockerClient.inspectContainerCmd(name).exec(); - if ("running".equals(dockerClient.inspectContainerCmd(id).exec().getState().getStatus())) { - dockerClient.stopContainerCmd(id).exec(); - } + String[] oldEnvList = container.getConfig().getEnv(); + if (oldEnvList != null) { + for (String env : oldEnvList) { + String[] parts = env.split("=", 2); + if (parts.length == 2) { + envMap.put(parts[0], parts[1]); + } + } + } + + Map toAdd = (Map) conf.getOrDefault("add", Map.of()); + Map toUpdate = (Map) conf.getOrDefault("update", Map.of()); + Map toDelete = (Map) conf.getOrDefault("delete", Map.of()); + + toAdd.forEach(envMap::put); + toUpdate.forEach(envMap::put); + toDelete.keySet().forEach(envMap::remove); + + ContainerRunParam params = new ContainerRunParam( + container.getName().replace("/", ""), // le nom avec '/' à retirer + container.getNetworkSettings().getPorts().toString(), + envMap, + container.getImageId(), + null, + null + ); + + if ("running".equals(container.getState().getStatus())) { + dockerClient.stopContainerCmd(name).exec(); + } + dockerClient.removeContainerCmd(name).exec(); + + System.out.println("Variables finales envoyées à Docker : " + params.getEnv()); - dockerClient.removeContainerCmd(id).exec(); - try { startImage(params); - return ResponseEntity.ok(id); + return ResponseEntity.ok(name); + } catch (Exception e) { e.printStackTrace(); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Error: " + e.getMessage()); } } - /// Image management public String pullImage(String imageName) throws InterruptedException { diff --git a/src/test/java/org/example/jafeur/ConfigTests.java b/src/test/java/org/example/jafeur/ConfigTests.java new file mode 100644 index 0000000..a72225d --- /dev/null +++ b/src/test/java/org/example/jafeur/ConfigTests.java @@ -0,0 +1,104 @@ +package org.example.jafeur; + +import com.github.dockerjava.api.DockerClient; +import com.github.dockerjava.api.command.CreateContainerResponse; +import com.github.dockerjava.api.command.InspectContainerResponse; +import org.junit.jupiter.api.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import services.DockerService; + +import java.util.*; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class ConfigTests { + + @Autowired + private DockerService dockerService; + + private final DockerClient dockerClient; + + @Autowired + public ConfigTests(DockerClient dockerClient) { + this.dockerClient = dockerClient; + } + + @BeforeAll + static void setUpBeforeAll() { + System.out.println("Starting ConfigTests..."); + } + + @AfterAll + static void tearDownAfterAll() { + System.out.println("Finished ConfigTests."); + } + + @Test + @Order(1) + void testConfigApp_AddUpdateDeleteEnvVars() throws InterruptedException { + String containerName = "config-test-container"; + + // 🔁 Supprimer s'il existe déjà + dockerService.getAllContainers().stream() + .filter(container -> Arrays.asList(container.getNames()).contains("/" + containerName)) + .findFirst() + .ifPresent(existing -> { + try { + dockerClient.removeContainerCmd(existing.getId()).withForce(true).exec(); + System.out.println("Conteneur existant supprimé"); + } catch (Exception e) { + fail("Could not remove existing container: " + e.getMessage()); + } + }); + + // 🚀 1. Créer le conteneur initial + CreateContainerResponse created = dockerClient.createContainerCmd("alpine") + .withName(containerName) + .withEnv("INITIAL_VAR=initial") + .withCmd("sh", "-c", "env && sleep 9999") + .exec(); + dockerClient.startContainerCmd(created.getId()).exec(); + System.out.println("Conteneur initial lancé"); + + Thread.sleep(500); + + // ➕ 2. Ajout des variables + dockerService.configApp(containerName, Map.of( + "add", Map.of("VAR1", "value1", "VAR2", "toremove") + )); + + Thread.sleep(1000); + + InspectContainerResponse afterAdd = dockerClient.inspectContainerCmd(containerName).exec(); + String[] rawEnvsAfterAdd = afterAdd.getConfig().getEnv(); + assertNotNull(rawEnvsAfterAdd, "Env list is null after add"); + + List envsAfterAdd = Arrays.asList(rawEnvsAfterAdd); + System.out.println("Env après ajout : " + envsAfterAdd); + + assertTrue(envsAfterAdd.contains("VAR1=value1"), "VAR1=value1 n'est pas présent"); + assertTrue(envsAfterAdd.contains("VAR2=toremove"), "VAR2=toremove n'est pas présent"); + + // 🔁 3. Update + Delete + dockerService.configApp(containerName, Map.of( + "update", Map.of("VAR1", "updated-value"), + "delete", Map.of("VAR2", "") + )); + + Thread.sleep(1000); + + InspectContainerResponse afterUpdate = dockerClient.inspectContainerCmd(containerName).exec(); + String[] rawEnvsAfterUpdate = afterUpdate.getConfig().getEnv(); + assertNotNull(rawEnvsAfterUpdate, "Env list is null after update"); + + List envsAfterUpdate = Arrays.asList(rawEnvsAfterUpdate); + System.out.println("Env après update : " + envsAfterUpdate); + + assertTrue(envsAfterUpdate.contains("VAR1=updated-value"), "VAR1 n'est pas mis à jour"); + assertFalse(envsAfterUpdate.stream().anyMatch(e -> e.startsWith("VAR2=")), "VAR2 aurait dû être supprimé"); + } + +} \ No newline at end of file diff --git a/src/test/java/org/example/jafeur/ContainerTests.java b/src/test/java/org/example/jafeur/ContainerTests.java index ef47e7b..82fbc4a 100644 --- a/src/test/java/org/example/jafeur/ContainerTests.java +++ b/src/test/java/org/example/jafeur/ContainerTests.java @@ -80,23 +80,6 @@ void testGetAllContainers() { assertNotNull(dockerService.getAllContainers()); } - @Test - @Order(5) - void testConfigApp() { - String containerName = "test-container"; - dockerService.configApp(containerName, Map.of("VAR_TEST", "new_value", "VAR_TEST2", "new_value2")); - - InspectContainerResponse containerInfo = dockerClient.inspectContainerCmd(containerName).exec(); - List envVariables = Arrays.asList(Objects.requireNonNull(containerInfo.getConfig().getEnv())); - - assertTrue(envVariables.contains("VAR_TEST=new_value")); - assertTrue(envVariables.contains("VAR_TEST2=new_value2")); - - // assert that the container is still running - assertTrue(dockerService.getRunningContainers().stream() - .anyMatch(container -> container.getNames()[0].equals("/" + containerName))); - } - @Test @Order(6) void testStopContainer() {