Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
name: CI

on:
push:
branches:
- '**'
pull_request:
branches:
- main

jobs:
test:
name: Test Code
runs-on: ubuntu-latest
steps:
- name: Clone repo
uses: actions/checkout@v4

- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
cache: 'maven'

- name: Set up Docker
uses: docker/setup-buildx-action@v2

- name: Start services with Docker Compose
run: |
docker compose up -d --build

- name: Run tests
run: |
mvn clean test

- name: Stop and clean up Docker Compose
if: always()
run: |
docker compose down
9 changes: 0 additions & 9 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,6 @@
<version>2.5.0</version>
</dependency>

<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/config/DockerConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ public class DockerConfig {

@Bean
public DockerClient dockerClient() {
// Configure la connexion au démon Docker local via le socket Unix
var config = DefaultDockerClientConfig.createDefaultConfigBuilder()
.withDockerHost("unix:///var/run/docker.sock")
.build();

// Crée un client HTTP pour communiquer avec l’API Docker
var httpClient = new OkDockerHttpClient.Builder()
.dockerHost(config.getDockerHost())
.sslConfig(config.getSSLConfig())
Expand Down
3 changes: 1 addition & 2 deletions src/main/java/controllers/DockerController.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ public DockerController(DockerService dockerService) {
this.dockerService = dockerService;
}

// **Change application status (start, stop, restart)**
@PutMapping("/Start/{name}")
@Operation(summary = "Start a specific application", description = "Starts a specific application by its name.")
@Tag(name = "Change Status")
Expand Down Expand Up @@ -63,7 +62,6 @@ public ResponseEntity<String> configApp(@PathVariable("id") String id, @RequestB
return dockerService.configApp(id, config);
}

// **Check crash status**
@PutMapping("IsCrash/{name}")
@Operation(summary = "Check application crash status", description = "Checks whether a specific application has crashed.")
@Tag(name = "Crash Status and Errors")
Expand Down Expand Up @@ -131,6 +129,7 @@ public ResponseEntity<String> startImage(@RequestBody ContainerRunParam params)
@Tag(name = "Retrieve Information")
public ResponseEntity<List<Container>> getContainers(@PathVariable Boolean showAll) {
try {
// Renvoie soit tous les conteneurs, soit uniquement ceux en cours d'exécution
List<Container> containers;
if (showAll) {
containers = dockerService.getAllContainers();
Expand Down
4 changes: 1 addition & 3 deletions src/main/java/org/example/jafeur/JaFeurApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,10 @@
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@SpringBootApplication
@ComponentScan(basePackages = {"org.example.jafeur", "controllers", "repositories", "services", "config"})
@ComponentScan(basePackages = {"org.example.jafeur", "controllers", "services", "config"})
@EntityScan(basePackages = {"model"})
@EnableJpaRepositories(basePackages = {"repositories"})
public class JaFeurApplication {

public static void main(String[] args) {
Expand Down
44 changes: 11 additions & 33 deletions src/main/java/services/DockerService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
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;
Expand Down Expand Up @@ -149,16 +150,19 @@ public List<String> listCrashedContainers() {
.toList();
}

// Applique une nouvelle configuration d'environnement (redéploiement)
public ResponseEntity<String> configApp(String id, Map<String, String> conf) {

var inspect = dockerClient.inspectContainerCmd(id).exec();
ContainerRunParam params = new ContainerRunParam(
dockerClient.inspectContainerCmd(id).exec().getName(),
dockerClient.inspectContainerCmd(id).exec().getNetworkSettings().getPorts().toString(),
inspect.getName(),
inspect.getNetworkSettings().getPorts().toString(),
conf,
dockerClient.inspectContainerCmd(id).exec().getImageId(),
inspect.getImageId(),
null,
null
);

if ("running".equals(dockerClient.inspectContainerCmd(id).exec().getState().getStatus())) {
dockerClient.stopContainerCmd(id).exec();
}
Expand Down Expand Up @@ -198,35 +202,17 @@ public String buildDockerfile(String tag, Path path) {
.awaitImageId();
}

// Lance un conteneur avec les paramètres nécessaires (env, volume, traefik)
public String startImage(ContainerRunParam params) {
CreateContainerCmd containerBuilder = dockerClient.createContainerCmd(params.getImage());

// Définir le nom du conteneur
if (params.getName() != null) {
containerBuilder.withName(params.getName());
}

// Générer un port basé sur l'ID (évite conflits)
// int defaultPort = 80; // Port interne de l'app
// int hostPort = generatePortFromName(params.getName()); // Port unique basé sur le nom
//
// // Exposer le port
// ExposedPort exposedPort = ExposedPort.tcp(defaultPort);
// HostConfig hostConfig = new HostConfig()
// .withPortBindings(new PortBinding(Ports.Binding.bindPort(hostPort), exposedPort));
//
//// Appliquer d'abord l'exposition des ports, puis le HostConfig
// containerBuilder
// .withExposedPorts(exposedPort)
// .withHostConfig(hostConfig); // Appliquer la config après

containerBuilder
.withExposedPorts(ExposedPort.tcp(80));
// .withHostConfig(new HostConfig().withNetworkMode("web")); // <-- le réseau Docker partagé avec Traefik // enlevé car bugs pour les tests



// Ajouter les variables d'environnement
if (params.getEnv() != null) {
List<String> env = new ArrayList<>();
for (Map.Entry<String, String> entry : params.getEnv().entrySet()) {
Expand All @@ -235,38 +221,30 @@ public String startImage(ContainerRunParam params) {
containerBuilder.withEnv(env);
}

// Ajouter le volume si défini
if (params.getVolume() != null) {
containerBuilder.withVolumes(new Volume(params.getVolume()));
}

// Ajouter une commande spécifique si définie
if (params.getCommand() != null) {
containerBuilder.withCmd(params.getCommand());
}

// Ajouter les labels pour Traefik/Nginx
containerBuilder.withLabels(Map.of(
// Configuration des labels pour exposer l'app via Traefik
containerBuilder.withHostConfig(new HostConfig().withNetworkMode("traefik-network"))
.withLabels(Map.of(
"traefik.enable", "true",
"traefik.http.routers." + params.getName() + ".rule", "Host(`jafeur-" + params.getName() + ".localhost`)",
"traefik.http.routers." + params.getName() + ".entrypoints", "web",
"traefik.http.services." + params.getName() + ".loadbalancer.server.port", "80"
));


// Exécuter la création du conteneur
CreateContainerResponse container = containerBuilder.exec();
dockerClient.startContainerCmd(container.getId()).exec();

return "Container " + params.getName() + " started! Accessible at http://jafeur-" + params.getName() + ".localhost";
}

private int generatePortFromName(String name) {
int hash = name.hashCode();
int basePort = 10000; // Évite conflits avec ports système
return basePort + (Math.abs(hash) % 50000); // Ports entre 10000 et 60000
}

public void removeImage(String imageId) {
dockerClient.removeImageCmd(imageId).exec();
}
Expand Down
4 changes: 0 additions & 4 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,2 @@
spring.application.name=JaFeur
springdoc.swagger-ui.path=/swagger

spring.datasource.url=jdbc:postgresql://162.38.112.137:5432/
spring.datasource.username=postgres
spring.datasource.password=feur