preparation for docker containers handling
This commit is contained in:
parent
e290b9314c
commit
27332ff809
@ -1,6 +1,9 @@
|
||||
package fr.la_banquise.backend.data.model;
|
||||
|
||||
import com.github.dockerjava.api.model.Container;
|
||||
import java.util.Set;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
@ -9,6 +12,7 @@ import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.SequenceGenerator;
|
||||
import jakarta.persistence.Table;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
@ -16,6 +20,7 @@ import lombok.NoArgsConstructor;
|
||||
*/
|
||||
@Entity
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Table(name = "instance")
|
||||
public class Instance {
|
||||
@Id
|
||||
@ -23,23 +28,26 @@ public class Instance {
|
||||
@SequenceGenerator(name = "InstanceSeq", sequenceName = "instance_id_seq",
|
||||
allocationSize = 1, initialValue = 1)
|
||||
public Long id;
|
||||
|
||||
@Column(unique = true, nullable = false)
|
||||
public String name;
|
||||
public Long port;
|
||||
public Container container;
|
||||
// So people cant have more than one
|
||||
// container per JI because name will be login-jiId
|
||||
|
||||
public int port;
|
||||
|
||||
//@JsonBackReference
|
||||
@JsonIgnore
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "user_id", nullable = false)
|
||||
public User owner;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "practical_id", nullable = false)
|
||||
public Sujet sujet;
|
||||
//@ManyToOne @JoinColumn(name = "ji_id", nullable = false) public Ji ji;
|
||||
|
||||
public Instance(String name, Long port, User user, Sujet sujet) {
|
||||
public Instance(String name, int port, User user ) {//, Ji ji) {
|
||||
this.name = name;
|
||||
this.port = port;
|
||||
this.owner = user;
|
||||
this.sujet = sujet;
|
||||
//this.ji = ji;
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.JoinTable;
|
||||
import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.SequenceGenerator;
|
||||
import jakarta.persistence.Table;
|
||||
import java.util.List;
|
||||
@ -28,16 +29,19 @@ public class Ji {
|
||||
public String name;
|
||||
public String description;
|
||||
|
||||
@JsonIgnore
|
||||
@ManyToMany
|
||||
@JoinTable(
|
||||
name = "ji_user", // Table de liaison
|
||||
@JoinTable(name = "ji_respos", // Table de liaison
|
||||
joinColumns = @JoinColumn(name = "ji_id"),
|
||||
inverseJoinColumns = @JoinColumn(name = "user_id")
|
||||
)
|
||||
inverseJoinColumns = @JoinColumn(name = "user_id"))
|
||||
public List<User> respos;
|
||||
public String date;
|
||||
|
||||
@ManyToOne @JoinColumn(name = "site_id") @JsonIgnore public Site site;
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "site_id") //@JsonIgnore
|
||||
public Site site;
|
||||
|
||||
@OneToMany @JoinColumn(name = "instance_id") public List<Instance> instances;
|
||||
|
||||
public Ji(String name, String description, List<User> respos, String date,
|
||||
Site site) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package fr.la_banquise.backend.data.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import jakarta.persistence.CascadeType;
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
@ -31,6 +32,9 @@ public class Site {
|
||||
public String description;
|
||||
public String address;
|
||||
|
||||
/*@OneToMany(mappedBy = "ji", cascade = CascadeType.ALL)
|
||||
public List<Instance> instances;*/
|
||||
|
||||
@OneToMany(mappedBy = "site") @JsonIgnore public List<Ji> jiInSite;
|
||||
|
||||
public Site(String name, String description, String address) {
|
||||
|
@ -19,6 +19,7 @@ import jakarta.persistence.ManyToMany;
|
||||
import jakarta.persistence.OneToMany;
|
||||
import jakarta.persistence.SequenceGenerator;
|
||||
import jakarta.persistence.Table;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@ -73,14 +74,13 @@ public class User {
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
public User(String name, String password, RolesAsso role,
|
||||
List<Instance> instances) {
|
||||
public User(String name, String password, RolesAsso role) {
|
||||
this.name = name;
|
||||
this.password = password;
|
||||
if (role == RolesAsso.NONE)
|
||||
this.role = new HashSet<>();
|
||||
else
|
||||
this.role = new HashSet<>(Arrays.asList(role));
|
||||
this.instances = instances;
|
||||
this.instances = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ public class Endpoints {
|
||||
DashboardResponse dashboard = new DashboardResponse();
|
||||
dashboard.tps =
|
||||
sujetService.getAllSujetsRespo(identity.getPrincipal().getName());
|
||||
dashboard.instances = instanceService.getAllInstances(username);
|
||||
//dashboard.instances = instanceService.getAllInstances(username);
|
||||
return Response.ok(dashboard).build();
|
||||
}
|
||||
}
|
||||
|
@ -1,38 +1,57 @@
|
||||
package fr.la_banquise.backend.rest;
|
||||
|
||||
import fr.la_banquise.backend.rest.request.InstanceRequest;
|
||||
import fr.la_banquise.backend.services.InstanceService;
|
||||
import fr.la_banquise.backend.services.JiService;
|
||||
import io.quarkus.security.identity.SecurityIdentity;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
|
||||
/**
|
||||
* InstanceEndpoints
|
||||
*/
|
||||
@Path("/api/instances")
|
||||
@Path("/api/ji/")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public class InstanceEndpoints {
|
||||
|
||||
@Inject
|
||||
SecurityIdentity identity;
|
||||
@Inject SecurityIdentity identity;
|
||||
|
||||
@Inject
|
||||
InstanceService instanceService;
|
||||
@Inject JiService jiService;
|
||||
@Inject InstanceService instanceService;
|
||||
|
||||
@GET
|
||||
@RolesAllowed("ROOT")
|
||||
@Path("/instances")
|
||||
public Response getAllInstances() {
|
||||
String username = identity.getPrincipal().getName();
|
||||
return Response.ok(instanceService.getAllInstances(username)).build();
|
||||
return Response.ok(instanceService.getAllInstances()).build();
|
||||
}
|
||||
|
||||
@POST
|
||||
public Response createInstance(InstanceRequest request) {
|
||||
instanceService.createInstance(request.name, request.ssh, request.pwd, request.port, request.username, request.tpId);
|
||||
@Path("/{id}/instance")
|
||||
public Response createInstance(@PathParam("id") Long jiId,
|
||||
@QueryParam("username") String username) {
|
||||
jiService.createInstance(jiId, username);
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/{id}/instance/container")
|
||||
public Response createContainer(@PathParam("id") Long jiId,
|
||||
@QueryParam("username") String username) {
|
||||
return Response.ok(jiService.createContainer(jiId, username)).build();
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/{id}/instance/container")
|
||||
public Response getStatusContainer(@PathParam("id") Long jiId,
|
||||
@QueryParam("username") String username) {
|
||||
return Response.ok(jiService.getStatusContainer(jiId, username)).build();
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ import java.util.Map;
|
||||
import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
|
||||
import org.eclipse.microprofile.openapi.annotations.responses.APIResponses;
|
||||
|
||||
@Path("/ji")
|
||||
@Path("/api/ji")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public class JiResource {
|
||||
@ -25,7 +25,7 @@ public class JiResource {
|
||||
@GET
|
||||
@Path("/listall")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@RolesAllowed("root")
|
||||
@RolesAllowed("ROOT")
|
||||
public Response listall() {
|
||||
try {
|
||||
List<Ji> ji = jiService.getAllJiAdmin();
|
||||
@ -39,9 +39,10 @@ public class JiResource {
|
||||
|
||||
@POST
|
||||
@Path("/create")
|
||||
@RolesAllowed("root")
|
||||
@RolesAllowed("ROOT")
|
||||
public Response createJi(@QueryParam("name") String name,
|
||||
@QueryParam("desc") String desc,
|
||||
@QueryParam("desc") String desc, // TODO : change
|
||||
// desc to date
|
||||
@QueryParam("address") String address,
|
||||
@QueryParam("respo") String respo,
|
||||
@QueryParam("site") String name_site) {
|
||||
|
@ -26,7 +26,7 @@ public class SiteEndpoints {
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@RolesAllowed("root")
|
||||
@RolesAllowed("ROOT")
|
||||
@Operation(summary = "Lists all existing sites",
|
||||
description = "Lists all sites. Root role required.")
|
||||
@APIResponses({
|
||||
@ -47,7 +47,7 @@ public class SiteEndpoints {
|
||||
}
|
||||
|
||||
@POST
|
||||
@RolesAllowed("root")
|
||||
@RolesAllowed("ROOT")
|
||||
@Operation(summary = "Creates a site",
|
||||
description = "Creates a site if no name is not a duplicate.")
|
||||
@APIResponses({
|
||||
|
@ -43,7 +43,7 @@ public class SujetEndpoints {
|
||||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@RolesAllowed("root")
|
||||
@RolesAllowed("ROOT")
|
||||
public Response createSujet(SujetRequest sujet) {
|
||||
return Response.ok(sujetService.createSujet(sujet)).build();
|
||||
}
|
||||
@ -51,7 +51,7 @@ public class SujetEndpoints {
|
||||
@POST
|
||||
@Path("/respo")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@RolesAllowed("root")
|
||||
@RolesAllowed("ROOT")
|
||||
public Response addRespoSujet(@QueryParam("name_sujet") String name_sujet,
|
||||
@QueryParam("name_user") String name_user) {
|
||||
try {
|
||||
|
@ -1,16 +1,9 @@
|
||||
package fr.la_banquise.backend.rest.request;
|
||||
|
||||
import io.smallrye.common.constraint.Nullable;
|
||||
|
||||
/**
|
||||
* InstanceRequest
|
||||
*/
|
||||
public class InstanceRequest {
|
||||
public String name;
|
||||
public String ssh;
|
||||
public String pwd;
|
||||
public String username;
|
||||
public Long port;
|
||||
@Nullable
|
||||
public Long tpId;
|
||||
public Long jiId;
|
||||
}
|
||||
|
@ -1,15 +1,27 @@
|
||||
package fr.la_banquise.backend.services;
|
||||
|
||||
import com.github.dockerjava.api.DockerClient;
|
||||
import com.github.dockerjava.api.command.CreateContainerResponse;
|
||||
import com.github.dockerjava.api.command.InspectContainerResponse;
|
||||
import com.github.dockerjava.api.model.ExposedPort;
|
||||
import com.github.dockerjava.api.model.HostConfig;
|
||||
import com.github.dockerjava.api.model.Ports;
|
||||
|
||||
import fr.la_banquise.backend.data.model.Instance;
|
||||
import fr.la_banquise.backend.data.model.Sujet;
|
||||
import fr.la_banquise.backend.data.model.Ji;
|
||||
import fr.la_banquise.backend.data.model.User;
|
||||
import fr.la_banquise.backend.data.repository.InstanceRepository;
|
||||
import fr.la_banquise.backend.data.repository.SujetRepository;
|
||||
import fr.la_banquise.backend.data.repository.JiRepository;
|
||||
import fr.la_banquise.backend.data.repository.UserRepository;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.transaction.Transactional;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* InstanceService
|
||||
@ -21,7 +33,9 @@ public class InstanceService {
|
||||
|
||||
@Inject UserRepository userRepository;
|
||||
|
||||
@Inject SujetRepository sujetRepository;
|
||||
@Inject JiRepository jiRepository;
|
||||
|
||||
@Inject DockerClient dockerClient;
|
||||
|
||||
public List<Instance> getAllInstances() {
|
||||
return instanceRepository.findAll().list();
|
||||
@ -36,44 +50,100 @@ public class InstanceService {
|
||||
return instanceRepository.findById(id);
|
||||
}
|
||||
|
||||
public InspectContainerResponse.ContainerState getStatusContainer(Long id) {
|
||||
Instance instance = instanceRepository.findById(id);
|
||||
InspectContainerResponse container =
|
||||
dockerClient.inspectContainerCmd(instance.name).exec();
|
||||
return container.getState();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Instance createInstance(String name, Long port, String username,
|
||||
Long sujetId) {
|
||||
public Instance createInstance(String username, Ji ji) {
|
||||
User user = userRepository.findByName(username);
|
||||
Sujet sujet = sujetRepository.findById(sujetId);
|
||||
Instance instance = new Instance(name, port, user, sujet);
|
||||
String name = username + "-" + ji.id;
|
||||
int port = getFreePort(1).iterator().next();
|
||||
Instance instance = new Instance(name, port, user);
|
||||
instanceRepository.persist(instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Instance createInstance(String name, String ssh, String pwd,
|
||||
Long port, User user, Long sujetId) {
|
||||
Sujet sujet = sujetRepository.findById(sujetId);
|
||||
Instance instance = new Instance(name, port, user, sujet);
|
||||
instanceRepository.persist(instance);
|
||||
return instance;
|
||||
public String createContainer(Long instanceId) {
|
||||
Instance instance = instanceRepository.findById(instanceId);
|
||||
|
||||
ExposedPort tcpSsh = ExposedPort.tcp(22);
|
||||
|
||||
Ports portBindings = new Ports();
|
||||
portBindings.bind(tcpSsh, Ports.Binding.bindPort(instance.port));
|
||||
|
||||
HostConfig hostConfig =
|
||||
HostConfig.newHostConfig().withPortBindings(portBindings);
|
||||
Map<String, String> labels = new HashMap<>();
|
||||
labels.put("test", "banquise");
|
||||
labels.put("environment", "development");
|
||||
labels.put("version", "1.0");
|
||||
labels.put("created-by", "java-docker-api");
|
||||
|
||||
CreateContainerResponse container =
|
||||
dockerClient.createContainerCmd("nginx:latest")
|
||||
.withName(instance.name)
|
||||
.withLabels(labels)
|
||||
.withExposedPorts(tcpSsh)
|
||||
.withHostConfig(hostConfig)
|
||||
.exec();
|
||||
|
||||
return container.getId();
|
||||
}
|
||||
|
||||
public boolean deleteContainer(String containerName) {
|
||||
try {
|
||||
dockerClient.removeContainerCmd(containerName).exec();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public boolean deleteInstance(Long id) {
|
||||
return instanceRepository.deleteById(id);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public boolean deleteAllInstances() {
|
||||
instanceRepository.deleteAll();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteJDMIInstances() {
|
||||
instanceRepository.deleteAll();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Instance updateInstance(Long id) {
|
||||
Instance instance = instanceRepository.findById(id);
|
||||
return instance;
|
||||
if (!containerExists(instance.name))
|
||||
return instanceRepository.deleteById(id);
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean containerExists(String containerName) {
|
||||
try {
|
||||
dockerClient.inspectContainerCmd(containerName).exec();
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Set<Integer> getUsedPorts() {
|
||||
Set<Integer> retour = new HashSet<>();
|
||||
List<Instance> allInstances = getAllInstances();
|
||||
for (Instance instance : allInstances) {
|
||||
retour.add(instance.port);
|
||||
}
|
||||
|
||||
return retour;
|
||||
}
|
||||
|
||||
public Set<Integer> getFreePort(int nbPortsNeeded) {
|
||||
Set<Integer> used = getUsedPorts();
|
||||
Set<Integer> retour = new HashSet<>();
|
||||
|
||||
int port = 40000;
|
||||
|
||||
// max 1000 ports used at a same time
|
||||
while (retour.size() < nbPortsNeeded && port < 41000) {
|
||||
if (!used.contains(port)) {
|
||||
retour.add(port);
|
||||
}
|
||||
port++;
|
||||
}
|
||||
|
||||
return retour;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package fr.la_banquise.backend.services;
|
||||
|
||||
import fr.la_banquise.backend.data.model.Instance;
|
||||
import fr.la_banquise.backend.data.model.Ji;
|
||||
import fr.la_banquise.backend.data.model.Site;
|
||||
import fr.la_banquise.backend.data.model.User;
|
||||
@ -9,7 +10,6 @@ import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.transaction.Transactional;
|
||||
import jakarta.ws.rs.core.SecurityContext;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ApplicationScoped
|
||||
@ -18,6 +18,7 @@ public class JiService {
|
||||
@Inject JiRepository jiRepository;
|
||||
@Inject UserRepository userRepository;
|
||||
@Inject SiteService siteService;
|
||||
@Inject InstanceService instanceService;
|
||||
@Inject SecurityContext security;
|
||||
|
||||
@Transactional
|
||||
@ -58,4 +59,44 @@ public class JiService {
|
||||
siteService.removeJi(ji.site, ji);
|
||||
jiRepository.delete(ji);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Instance createInstance(Long id, String username) {
|
||||
Ji ji = jiRepository.findById(id);
|
||||
Instance instance = instanceService.createInstance(username, ji);
|
||||
ji.instances.add(instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public String createContainer(Long id, String username) {
|
||||
Ji ji = jiRepository.findById(id);
|
||||
String retour = "";
|
||||
for (Instance instance : ji.instances) {
|
||||
|
||||
if (instance.name.equals(username + "-" + id)) {
|
||||
retour = instanceService.createContainer(instance.id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (retour == "")
|
||||
throw new Error("instance or container not found");
|
||||
|
||||
return retour;
|
||||
}
|
||||
|
||||
public String getStatusContainer(Long id, String username) {
|
||||
Ji ji = jiRepository.findById(id);
|
||||
String retour = "";
|
||||
for (Instance instance : ji.instances) {
|
||||
if (instance.name.equals(username + "-" + id)) {
|
||||
retour =
|
||||
instanceService.getStatusContainer(instance.id).toString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (retour == "")
|
||||
throw new Error("instance or container not found");
|
||||
return retour;
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ public class UserService {
|
||||
public User createUser(UserRequest request) {
|
||||
User user =
|
||||
new User(request.name, BcryptUtil.bcryptHash(request.password),
|
||||
RolesAsso.NONE, new ArrayList<>());
|
||||
RolesAsso.NONE);
|
||||
userRepository.persist(user);
|
||||
return user;
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ quarkus.hibernate-orm.database.generation=drop-and-create
|
||||
quarkus.quinoa.dev-server.port=5173
|
||||
quarkus.quinoa.enable-spa-routing=true
|
||||
|
||||
quarkus.docker.docker-host=unix:///run/user/1000/docker.sock
|
||||
quarkus.docker.docker-host=unix:///run/user/1001/docker.sock
|
||||
#quarkus.security.auth.enabled-in-dev-mode=false
|
||||
|
||||
quarkus.hibernate-orm.sql-load-script=import-dev.sql
|
||||
|
@ -1,3 +1,6 @@
|
||||
-- Ce fichier est exécuté automatiquement en mode dev
|
||||
INSERT INTO penguin (name, password) VALUES ('root', '$2a$10$lzKAv4aj6s0jtneg0Ikx/eEBb6p.6N6yo7ZF.myqYxEA9MWbMwvNu');
|
||||
INSERT INTO user_roles (User_id, role) VALUES (1, 'ROOT');
|
||||
INSERT INTO site (name, description, address) VALUES ('test', 'test', 'test');
|
||||
INSERT INTO ji (name, description, date, site_id) VALUES ('ji', 'test', 'date', 1);
|
||||
INSERT INTO ji_respos (ji_id, User_id) VALUES (1, 1);
|
||||
|
Loading…
x
Reference in New Issue
Block a user