From bc6efc5c5103d61c9d13313e41e2344e8baf4b7e Mon Sep 17 00:00:00 2001
From: Georg Pfuetzenreuter
Date: Sat, 7 May 2022 18:37:24 +0200
Subject: Checkpoint: Image deletion interface

Signed-off-by: Georg Pfuetzenreuter <mail@georg-pfuetzenreuter.net>
---
 .../java/net/libertacasa/pubsh/web/Docker.java     | 47 ++++++++++++++++++-
 .../net/libertacasa/pubsh/web/SecurityConfig.java  |  1 -
 .../net/libertacasa/pubsh/web/WebApplication.java  | 52 ++++++++++++++++++----
 3 files changed, 89 insertions(+), 11 deletions(-)

(limited to 'src/main/java/net/libertacasa/pubsh')

diff --git a/src/main/java/net/libertacasa/pubsh/web/Docker.java b/src/main/java/net/libertacasa/pubsh/web/Docker.java
index 1460bb3..6912d1b 100644
--- a/src/main/java/net/libertacasa/pubsh/web/Docker.java
+++ b/src/main/java/net/libertacasa/pubsh/web/Docker.java
@@ -1,17 +1,25 @@
 package net.libertacasa.pubsh.web;
 
 import java.io.File;
+import java.nio.file.Path;
 import java.time.Duration;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
+
+import org.springframework.core.io.ClassPathResource;
+
 import com.github.dockerjava.api.DockerClient;
 import com.github.dockerjava.api.command.BuildImageResultCallback;
+import com.github.dockerjava.api.command.CreateContainerResponse;
 import com.github.dockerjava.api.command.InspectExecResponse.Container;
 import com.github.dockerjava.api.command.ListContainersCmd;
+import com.github.dockerjava.api.command.ListImagesCmd;
+import com.github.dockerjava.api.command.WaitContainerResultCallback;
 import com.github.dockerjava.api.model.Image;
 import com.github.dockerjava.core.DefaultDockerClientConfig;
 import com.github.dockerjava.core.DockerClientConfig;
@@ -82,8 +90,11 @@ public class Docker {
 	}
 	
 	public static String buildImage(String targetUser, String osChoice, Integer count) {
-		String dockerfile = "classpath:docker/Dockerfile-" + osChoice;
-		String tag = targetUser + ":sh" + count; 
+		String dockerfile = "/home/georg/tmp/docker/Dockerfile_" + osChoice;
+		String tag = targetUser + ":sh" + count;
+		if (! new File(dockerfile).exists()) {
+			System.out.printf("\nInvalid Dockerfile: %s\n", dockerfile);
+		}
 		Set<String> tags = new HashSet<String>();
 		tags.add(tag);
 		String imgid = dockerClient.buildImageCmd()
@@ -91,7 +102,39 @@ public class Docker {
 				.withPull(false).withNoCache(false).withTags(tags)
 				.exec(new BuildImageResultCallback()).awaitImageId();
 		
+		System.out.printf("\nBuilt image with ID %s", imgid);
 		return(imgid);
 	}
+	
+	public static void deleteImage(String username, String id) {
+		List<Image> imagequery = Docker.getImages();
+
+		if (imagequery.toString().contains(id)) {
+			System.out.printf("\nFound image ID %s, deleting ...", id);
+			dockerClient.removeImageCmd(id).withImageId(id).exec();
+		}
+		if (! imagequery.toString().contains(id)) {
+			System.out.printf("\nImage ID %s not found.", id);
+		}
+		
+	}
+	
+	public static String createContainer(String imgid) {
+		//String containerid = dockerClient.createContainerCmd(imgid).exec();
+		WaitContainerResultCallback resultCallback = new WaitContainerResultCallback();
+		CreateContainerResponse createContainerResponse = dockerClient.createContainerCmd(imgid).exec();
+		dockerClient.waitContainerCmd(createContainerResponse.getId()).exec(resultCallback);
+		try {
+			resultCallback.awaitCompletion();
+		} catch (InterruptedException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+		String containerid = createContainerResponse.getId();
+		//System.out.println(dockerClient.infoCmd().exec());
+			
+		System.out.printf("\nCreated container with ID %s from image ID %s", containerid, imgid);
+		return(containerid);
+	}
 
 }
diff --git a/src/main/java/net/libertacasa/pubsh/web/SecurityConfig.java b/src/main/java/net/libertacasa/pubsh/web/SecurityConfig.java
index 630acf4..53f83ab 100644
--- a/src/main/java/net/libertacasa/pubsh/web/SecurityConfig.java
+++ b/src/main/java/net/libertacasa/pubsh/web/SecurityConfig.java
@@ -32,7 +32,6 @@ public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
     @Override
     protected void configure(HttpSecurity http) throws Exception
     {
-    	http.csrf().disable();
         super.configure(http); //.anonymous().disable()
         http
                 .authorizeRequests()
diff --git a/src/main/java/net/libertacasa/pubsh/web/WebApplication.java b/src/main/java/net/libertacasa/pubsh/web/WebApplication.java
index e7b3cd2..bfdeb59 100644
--- a/src/main/java/net/libertacasa/pubsh/web/WebApplication.java
+++ b/src/main/java/net/libertacasa/pubsh/web/WebApplication.java
@@ -21,6 +21,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.util.MultiValueMap;
+import org.springframework.validation.BindingResult;
 import org.springframework.web.bind.annotation.DeleteMapping;
 //import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -36,7 +37,6 @@ import com.github.dockerjava.api.model.Container;
 import com.github.dockerjava.api.model.Image;
 import java.util.Random;
 
-//@SessionAttributes("osChoice")
 @SpringBootApplication
 @Controller
 public class WebApplication {
@@ -87,7 +87,7 @@ public class WebApplication {
       //System.out.println(images);     
       List<Container> containers = Docker.getContainers();
       //System.out.println(containers);
-      
+           
       model.addAttribute("docker_images", images);
       model.addAttribute("docker_containers", containers);
       
@@ -113,30 +113,66 @@ public class WebApplication {
 	     username = String.valueOf(customClaims.get("username"));
  	 // [End]
 	        
-		System.out.printf("Deletion triggered for ID %s by %s (%s)", id, userid, username);
+		System.out.printf("\nDeletion triggered for ID %s by %s (%s)", id, userid, username);
 		
 		Docker.deleteContainer(id);
 			
 		return("redirect:/portal");
 	}
 	
-	@PostMapping(path="/frontend/container/add",consumes=MediaType.APPLICATION_FORM_URLENCODED_VALUE)
-	public static String addContainer(@RequestBody MultiValueMap<String, String> body, HttpServletRequest request) {
+	@DeleteMapping("/frontend/image/delete/{id}")
+	public static String deleteImage(@PathVariable String id, HttpServletRequest request, RedirectAttributes redirectAttributes) {
+	// [Start] This block should move to a logging method. It's only job is to print user details to the console.
 	     KeycloakAuthenticationToken principal = (KeycloakAuthenticationToken) request.getUserPrincipal();
 	     String username= null;
 	     String userid = principal.getName();
 	     IDToken token = principal.getAccount().getKeycloakSecurityContext().getIdToken();		
 	     Map<String, Object> customClaims = token.getOtherClaims();
 	     username = String.valueOf(customClaims.get("username"));
-	     String osChoice = (String) body.getFirst("osChoice");
+	 // [End]
+	     
+	     System.out.printf("\nImage deletion triggered for ID %s by %s (%s)", id, userid, username);
+	     
+	     try {
+	    	 Docker.deleteImage(username, id);
+	    	 String returnmessage =  "Success - removed image with ID " + id + "!";
+	    	 redirectAttributes.addFlashAttribute("message", returnmessage);
+	     } catch (com.github.dockerjava.api.exception.ConflictException exception) {
+	    	 String returnmessage = "Error - Image is still being used by a container.";
+	    	 redirectAttributes.addFlashAttribute("message", returnmessage);
+	     }
+	     		
+	     return("redirect:/portal");
+	}
+	
+	@PostMapping(path="/frontend/container/add",consumes=MediaType.APPLICATION_FORM_URLENCODED_VALUE)
+	public static String addContainer(@RequestBody MultiValueMap<String, String> body, HttpServletRequest request, RedirectAttributes redirectAttributes) {
+	     KeycloakAuthenticationToken principal = (KeycloakAuthenticationToken) request.getUserPrincipal();
+	     String username = null;
+	     String userid = principal.getName();
+	     IDToken token = principal.getAccount().getKeycloakSecurityContext().getIdToken();		
+	     Map<String, Object> customClaims = token.getOtherClaims();
+	     username = String.valueOf(customClaims.get("username"));
+	     String os = (String) body.getFirst("osChoice");
 	     
-	     System.out.printf("New container with OS %s requested by %s (%s)", osChoice, userid, username);
+	     System.out.printf("\nNew container with OS %s requested by %s (%s)\n", os, userid, username);
 	     
 	     Random rand = new Random();
 	     Integer randomInt = rand.nextInt(9999999-1111);
 	     Integer count = randomInt;
 	     
-	     //Docker.buildImage(username, osChoice, count);
+	     try {
+	    	 String imageid = Docker.buildImage(username, os, count);
+	    	 String returnmessage =  "Success - built image with ID " + imageid + " and tag sh" + count + "!";
+	    	 redirectAttributes.addFlashAttribute("message", returnmessage);
+	     } catch (Exception exception) {
+	    	 redirectAttributes.addFlashAttribute("message", "Success!");
+	    	 String returnmessage =  "Error - failed to build image :-(";
+	    	 redirectAttributes.addFlashAttribute("message", returnmessage);
+	    	 System.out.println(exception);
+	     }
+	     
+	     //Docker.createContainer(imageid);
 	     
 	     return("redirect:/portal");
 	}
-- 
cgit v1.2.3