From d87b0a34dd082d5257afac193c3c03eb885de4dd Mon Sep 17 00:00:00 2001 From: Luca Trubbiani Date: Tue, 9 Jul 2024 11:37:11 +0200 Subject: [PATCH 1/4] Change builder tool and update frameworks with context-sources-map --- core-builder-tool/builder-tool.sh | 62 ++++++++++++++++++- .../k8s/K8sDeploymentFramework.java | 10 ++- .../infrastructure/k8s/K8sJobFramework.java | 10 ++- .../infrastructure/k8s/K8sServeFramework.java | 10 ++- 4 files changed, 84 insertions(+), 8 deletions(-) diff --git a/core-builder-tool/builder-tool.sh b/core-builder-tool/builder-tool.sh index 47c0f45a0..c8ce875a6 100755 --- a/core-builder-tool/builder-tool.sh +++ b/core-builder-tool/builder-tool.sh @@ -95,11 +95,69 @@ handle_error() { exit 1 } + +# Function to synchronize files based on context-sources-map using rsync +sync_files_with_rsync() { + local map_file="$1" + local base64_dir="$2" + local destination_dir="$3" + + # Function to decode base64 filename without padding + decode_base64_no_padding() { + local base64_filename="$1" + # Add padding if necessary for base64 decoding + while [ $((${#base64_filename} % 4)) -ne 0 ]; do + base64_filename="${base64_filename}=" + done + echo "$base64_filename" | base64 --decode + } + + # Check if MAP_FILE exists + if [ ! -f "$map_file" ]; then + log "Error: Context-sources-map file '$map_file' does not exist." + exit 1 + fi + + # Read the context-sources-map file line by line + while IFS=',' read -r base64_filename destination_path; do + # Trim whitespace + base64_filename=$(echo "$base64_filename" | xargs) + destination_path=$(echo "$destination_path" | xargs) + + # Decode the base64 filename + decoded_filename=$(decode_base64_no_padding "$base64_filename") + source_file="$base64_dir/$base64_filename" + + # Check if the source file exists + if [ ! -f "$source_file" ]; then + log "Error: Source file '$source_file' does not exist." + continue + fi + + # Create the destination directory if it does not exist + mkdir -p "$(dirname "$destination_dir/$destination_path")" + + # Use rsync to copy the source file to the destination path + cp "$source_file" "$destination_dir/$destination_path" + + # Check rsync exit status + if [ $? -eq 0 ]; then + log "Successfully copied '$source_file' to '$destination_path'" + else + log "Error: Failed to rsync '$source_file' to '$destination_path'" + fi + done < "$map_file" +} + + # Trap any error or signal and call the error handling function trap 'handle_error $LINENO "$BASH_COMMAND"' ERR -# Copy everything from source directory to destination directory, excluding context-refs.txt -rsync -avL --exclude='context-refs.txt' --exclude='Dockerfile' --exclude='.*/' "$source_dir/" "$destination_dir/" +# Process context-sources.txt +if [ -f "$source_dir/context-sources-map.txt" ]; then + sync_files_with_rsync "$source_dir/context-sources-map.txt" "./" "$destination_dir" +fi + # Process context-refs.txt if [ -f "$source_dir/context-refs.txt" ]; then diff --git a/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sDeploymentFramework.java b/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sDeploymentFramework.java index 725b924e6..df042be6e 100644 --- a/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sDeploymentFramework.java +++ b/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sDeploymentFramework.java @@ -110,7 +110,7 @@ public K8sDeploymentRunnable run(K8sDeploymentRunnable runnable) throws K8sFrame .stream() .collect( Collectors.toMap( - ContextSource::getName, + c -> Base64.getUrlEncoder().withoutPadding().encodeToString(c.getName().getBytes()), c -> new String( Base64.getDecoder().decode(c.getBase64()), @@ -119,7 +119,13 @@ public K8sDeploymentRunnable run(K8sDeploymentRunnable runnable) throws K8sFrame ) ) ) - .orElseGet(Map::of) + .orElseGet(Map::of), + contextSourcesOpt + .map(contextSources -> Map.of("context-sources-map.txt", + contextSources.stream() + .map(c -> Base64.getUrlEncoder().withoutPadding().encodeToString(c.getName().getBytes()) + "," + c.getName() + "\n") + .collect(Collectors.joining("")) + )).orElseGet(Map::of) ) ); diff --git a/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sJobFramework.java b/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sJobFramework.java index b22c34870..c8ceac660 100644 --- a/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sJobFramework.java +++ b/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sJobFramework.java @@ -123,7 +123,7 @@ public K8sJobRunnable run(K8sJobRunnable runnable) throws K8sFrameworkException .stream() .collect( Collectors.toMap( - ContextSource::getName, + c -> Base64.getUrlEncoder().withoutPadding().encodeToString(c.getName().getBytes()), c -> new String( Base64.getDecoder().decode(c.getBase64()), @@ -132,7 +132,13 @@ public K8sJobRunnable run(K8sJobRunnable runnable) throws K8sFrameworkException ) ) ) - .orElseGet(Map::of) + .orElseGet(Map::of), + contextSourcesOpt + .map(contextSources -> Map.of("context-sources-map.txt", + contextSources.stream() + .map(c -> Base64.getUrlEncoder().withoutPadding().encodeToString(c.getName().getBytes()) + "," + c.getName() + "\n") + .collect(Collectors.joining("")) + )).orElseGet(Map::of) ) ); diff --git a/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sServeFramework.java b/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sServeFramework.java index c538f7ef1..6b50446bc 100644 --- a/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sServeFramework.java +++ b/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sServeFramework.java @@ -96,7 +96,7 @@ public K8sServeRunnable run(K8sServeRunnable runnable) throws K8sFrameworkExcept .stream() .collect( Collectors.toMap( - ContextSource::getName, + c -> Base64.getUrlEncoder().withoutPadding().encodeToString(c.getName().getBytes()), c -> new String( Base64.getDecoder().decode(c.getBase64()), @@ -105,7 +105,13 @@ public K8sServeRunnable run(K8sServeRunnable runnable) throws K8sFrameworkExcept ) ) ) - .orElseGet(Map::of) + .orElseGet(Map::of), + contextSourcesOpt + .map(contextSources -> Map.of("context-sources-map.txt", + contextSources.stream() + .map(c -> Base64.getUrlEncoder().withoutPadding().encodeToString(c.getName().getBytes()) + "," + c.getName() + "\n") + .collect(Collectors.joining("")) + )).orElseGet(Map::of) ) ); From 25d90643cfe1627bd473d61f3c2d13c09322e6f3 Mon Sep 17 00:00:00 2001 From: Luca Trubbiani Date: Tue, 9 Jul 2024 11:46:35 +0200 Subject: [PATCH 2/4] add prefix source dir for files --- core-builder-tool/builder-tool.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-builder-tool/builder-tool.sh b/core-builder-tool/builder-tool.sh index c8ce875a6..0b8d95712 100755 --- a/core-builder-tool/builder-tool.sh +++ b/core-builder-tool/builder-tool.sh @@ -155,7 +155,7 @@ trap 'handle_error $LINENO "$BASH_COMMAND"' ERR # Process context-sources.txt if [ -f "$source_dir/context-sources-map.txt" ]; then - sync_files_with_rsync "$source_dir/context-sources-map.txt" "./" "$destination_dir" + sync_files_with_rsync "$source_dir/context-sources-map.txt" "$source_dir/" "$destination_dir" fi From 6dad82d287f7eac806e593df38785d7d7050aae8 Mon Sep 17 00:00:00 2001 From: Luca Trubbiani Date: Tue, 9 Jul 2024 16:50:22 +0200 Subject: [PATCH 3/4] Add base64 file name also on KanikoFramework --- .../k8s/K8sKanikoFramework.java | 182 +++++++++--------- 1 file changed, 95 insertions(+), 87 deletions(-) diff --git a/modules/framework-kaniko/src/main/java/it/smartcommunitylabdhub/framework/kaniko/infrastructure/k8s/K8sKanikoFramework.java b/modules/framework-kaniko/src/main/java/it/smartcommunitylabdhub/framework/kaniko/infrastructure/k8s/K8sKanikoFramework.java index e16e91507..24bc0d4ac 100644 --- a/modules/framework-kaniko/src/main/java/it/smartcommunitylabdhub/framework/kaniko/infrastructure/k8s/K8sKanikoFramework.java +++ b/modules/framework-kaniko/src/main/java/it/smartcommunitylabdhub/framework/kaniko/infrastructure/k8s/K8sKanikoFramework.java @@ -28,6 +28,7 @@ import it.smartcommunitylabdhub.framework.k8s.objects.CoreVolume; import it.smartcommunitylabdhub.framework.kaniko.runnables.K8sKanikoRunnable; import jakarta.validation.constraints.NotNull; + import java.io.Serializable; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -38,6 +39,7 @@ import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; + import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.util.Assert; @@ -50,8 +52,9 @@ public class K8sKanikoFramework extends K8sBaseFramework> typeRef = new TypeReference< - HashMap - >() {}; + HashMap + >() { + }; private final BatchV1Api batchV1Api; @@ -102,44 +105,49 @@ public K8sKanikoRunnable run(K8sKanikoRunnable runnable) throws K8sFrameworkExce Optional> contextRefsOpt = Optional.ofNullable(runnable.getContextRefs()); Optional> contextSourcesOpt = Optional.ofNullable(runnable.getContextSources()); V1ConfigMap configMap = new V1ConfigMap() - .metadata(new V1ObjectMeta().name("init-config-map-" + runnable.getId()).labels(buildLabels(runnable))) - .data( - MapUtils.mergeMultipleMaps( - //dockerfile - Map.of("Dockerfile", runnable.getDockerFile()), - // Generate context-refs.txt if exist - contextRefsOpt - .map(contextRefsList -> - Map.of( - "context-refs.txt", - contextRefsList - .stream() - .map(v -> - v.getProtocol() + "," + v.getDestination() + "," + v.getSource() + "\n" - ) - .collect(Collectors.joining("")) - ) - ) - .orElseGet(Map::of), - // Generate context-sources.txt if exist - contextSourcesOpt - .map(contextSources -> - contextSources - .stream() - .collect( - Collectors.toMap( - ContextSource::getName, - c -> - new String( - Base64.getDecoder().decode(c.getBase64()), - StandardCharsets.UTF_8 - ) - ) - ) + .metadata(new V1ObjectMeta().name("init-config-map-" + runnable.getId()).labels(buildLabels(runnable))) + .data( + MapUtils.mergeMultipleMaps( + //dockerfile + Map.of("Dockerfile", runnable.getDockerFile()), + // Generate context-refs.txt if exist + contextRefsOpt + .map(contextRefsList -> + Map.of( + "context-refs.txt", + contextRefsList + .stream() + .map(v -> + v.getProtocol() + "," + v.getDestination() + "," + v.getSource() + "\n" + ) + .collect(Collectors.joining("")) + ) + ) + .orElseGet(Map::of), + // Generate context-sources.txt if exist + contextSourcesOpt + .map(contextSources -> + contextSources + .stream() + .collect( + Collectors.toMap( + c -> Base64.getUrlEncoder().withoutPadding().encodeToString(c.getName().getBytes()), + c -> new String( + Base64.getDecoder().decode(c.getBase64()), + StandardCharsets.UTF_8 + ) + ) + ) + ) + .orElseGet(Map::of), + contextSourcesOpt + .map(contextSources -> Map.of("context-sources-map.txt", + contextSources.stream() + .map(c -> Base64.getUrlEncoder().withoutPadding().encodeToString(c.getName().getBytes()) + "," + c.getName() + "\n") + .collect(Collectors.joining("")) + )).orElseGet(Map::of) ) - .orElseGet(Map::of) - ) - ); + ); coreV1Api.createNamespacedConfigMap(namespace, configMap, null, null, null, null); } catch (ApiException | NullPointerException e) { @@ -230,17 +238,17 @@ public V1Job build(K8sKanikoRunnable runnable) throws K8sFrameworkException { // Generate jobName and ContainerName String jobName = k8sBuilderHelper.getJobName(runnable.getRuntime(), runnable.getTask(), runnable.getId()); String containerName = k8sBuilderHelper.getContainerName( - runnable.getRuntime(), - runnable.getTask(), - runnable.getId() + runnable.getRuntime(), + runnable.getTask(), + runnable.getId() ); log.debug("build k8s job for {}", jobName); //build destination image name and set to runnable String prefix = - (StringUtils.hasText(imageRegistry) ? imageRegistry + "/" : "") + - (StringUtils.hasText(imagePrefix) ? imagePrefix + "-" : ""); + (StringUtils.hasText(imageRegistry) ? imageRegistry + "/" : "") + + (StringUtils.hasText(imagePrefix) ? imagePrefix + "-" : ""); // workaround: update image name only first time String imageName = runnable.getImage(); if (StringUtils.hasText(prefix) && !runnable.getImage().startsWith(prefix)) { @@ -256,10 +264,10 @@ public V1Job build(K8sKanikoRunnable runnable) throws K8sFrameworkException { // Create sharedVolume CoreVolume sharedVolume = new CoreVolume( - CoreVolume.VolumeType.empty_dir, - "/shared", - "shared-dir", - Map.of("sizeLimit", "100Mi") + CoreVolume.VolumeType.empty_dir, + "/shared", + "shared-dir", + Map.of("sizeLimit", "100Mi") ); List coreVolumes = new ArrayList<>(); @@ -271,20 +279,20 @@ public V1Job build(K8sKanikoRunnable runnable) throws K8sFrameworkException { // Create config map volume CoreVolume configMapVolume = new CoreVolume( - CoreVolume.VolumeType.config_map, - "/init-config-map", - "init-config-map", - Map.of("name", "init-config-map-" + runnable.getId()) + CoreVolume.VolumeType.config_map, + "/init-config-map", + "init-config-map", + Map.of("name", "init-config-map-" + runnable.getId()) ); coreVolumes.add(configMapVolume); // Add secret for kaniko if (StringUtils.hasText(kanikoSecret)) { CoreVolume secretVolume = new CoreVolume( - CoreVolume.VolumeType.secret, - "/kaniko/.docker", - kanikoSecret, - Map.of("items", CoreItems.builder().keyToPath(Map.of(".dockerconfigjson", "config.json")).build()) + CoreVolume.VolumeType.secret, + "/kaniko/.docker", + kanikoSecret, + Map.of("items", CoreItems.builder().keyToPath(Map.of(".dockerconfigjson", "config.json")).build()) ); if (runnableVolumesOpt.stream().noneMatch(v -> kanikoSecret.equals(v.getName()))) { coreVolumes.add(secretVolume); @@ -292,11 +300,11 @@ public V1Job build(K8sKanikoRunnable runnable) throws K8sFrameworkException { } //Add all volumes Optional - .ofNullable(runnable.getVolumes()) - .ifPresentOrElse(coreVolumes::addAll, () -> runnable.setVolumes(coreVolumes)); + .ofNullable(runnable.getVolumes()) + .ifPresentOrElse(coreVolumes::addAll, () -> runnable.setVolumes(coreVolumes)); List kanikoArgsAll = new ArrayList<>( - List.of("--dockerfile=/init-config-map/Dockerfile", "--context=/shared", "--destination=" + imageName) + List.of("--dockerfile=/init-config-map/Dockerfile", "--context=/shared", "--destination=" + imageName) ); // Add Kaniko args kanikoArgsAll.addAll(kanikoArgs); @@ -314,24 +322,24 @@ public V1Job build(K8sKanikoRunnable runnable) throws K8sFrameworkException { // Build Container V1Container container = new V1Container() - .name(containerName) - .image(kanikoImage) - .imagePullPolicy("Always") - .imagePullPolicy("IfNotPresent") - .args(kanikoArgsAll) - .resources(resources) - .volumeMounts(volumeMounts) - .envFrom(envFrom) - .env(env); + .name(containerName) + .image(kanikoImage) + .imagePullPolicy("Always") + .imagePullPolicy("IfNotPresent") + .args(kanikoArgsAll) + .resources(resources) + .volumeMounts(volumeMounts) + .envFrom(envFrom) + .env(env); // Create a PodSpec for the container V1PodSpec podSpec = new V1PodSpec() - .containers(Collections.singletonList(container)) - .nodeSelector(buildNodeSelector(runnable)) - .affinity(runnable.getAffinity()) - .tolerations(buildTolerations(runnable)) - .volumes(volumes) - .restartPolicy("Never"); + .containers(Collections.singletonList(container)) + .nodeSelector(buildNodeSelector(runnable)) + .affinity(runnable.getAffinity()) + .tolerations(buildTolerations(runnable)) + .volumes(volumes) + .restartPolicy("Never"); // Create a PodTemplateSpec with the PodSpec V1PodTemplateSpec podTemplateSpec = new V1PodTemplateSpec().metadata(metadata).spec(podSpec); @@ -339,14 +347,14 @@ public V1Job build(K8sKanikoRunnable runnable) throws K8sFrameworkException { // Add Init container to the PodTemplateSpec // Build the Init Container V1Container initContainer = new V1Container() - .name("init-container-" + runnable.getId()) - .image(initImage) - .volumeMounts(volumeMounts) - .resources(resources) - .env(env) - .envFrom(envFrom) - //TODO below execute a command that is a Go script - .command(List.of("/bin/bash", "-c", "/app/builder-tool.sh")); + .name("init-container-" + runnable.getId()) + .image(initImage) + .volumeMounts(volumeMounts) + .resources(resources) + .env(env) + .envFrom(envFrom) + //TODO below execute a command that is a Go script + .command(List.of("/bin/bash", "-c", "/app/builder-tool.sh")); // Set initContainer as first container in the PodSpec podSpec.setInitContainers(Collections.singletonList(initContainer)); @@ -355,11 +363,11 @@ public V1Job build(K8sKanikoRunnable runnable) throws K8sFrameworkException { // Create the JobSpec with the PodTemplateSpec V1JobSpec jobSpec = new V1JobSpec() - .activeDeadlineSeconds(Long.valueOf(activeDeadlineSeconds)) - .parallelism(1) - .completions(1) - .backoffLimit(backoffLimit) - .template(podTemplateSpec); + .activeDeadlineSeconds(Long.valueOf(activeDeadlineSeconds)) + .parallelism(1) + .completions(1) + .backoffLimit(backoffLimit) + .template(podTemplateSpec); // Return a new job with metadata and jobSpec return new V1Job().metadata(metadata).spec(jobSpec); From 18af0762194fe32eb5593a4b7973163f59b3e04d Mon Sep 17 00:00:00 2001 From: Matteo Saloni Date: Tue, 9 Jul 2024 17:54:56 +0200 Subject: [PATCH 4/4] chore: prettier --- .../k8s/K8sDeploymentFramework.java | 31 ++- .../infrastructure/k8s/K8sJobFramework.java | 29 ++- .../infrastructure/k8s/K8sServeFramework.java | 31 ++- .../k8s/K8sKanikoFramework.java | 205 ++++++++++-------- 4 files changed, 181 insertions(+), 115 deletions(-) diff --git a/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sDeploymentFramework.java b/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sDeploymentFramework.java index df042be6e..72a946532 100644 --- a/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sDeploymentFramework.java +++ b/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sDeploymentFramework.java @@ -110,7 +110,11 @@ public K8sDeploymentRunnable run(K8sDeploymentRunnable runnable) throws K8sFrame .stream() .collect( Collectors.toMap( - c -> Base64.getUrlEncoder().withoutPadding().encodeToString(c.getName().getBytes()), + c -> + Base64 + .getUrlEncoder() + .withoutPadding() + .encodeToString(c.getName().getBytes()), c -> new String( Base64.getDecoder().decode(c.getBase64()), @@ -120,12 +124,25 @@ public K8sDeploymentRunnable run(K8sDeploymentRunnable runnable) throws K8sFrame ) ) .orElseGet(Map::of), - contextSourcesOpt - .map(contextSources -> Map.of("context-sources-map.txt", - contextSources.stream() - .map(c -> Base64.getUrlEncoder().withoutPadding().encodeToString(c.getName().getBytes()) + "," + c.getName() + "\n") - .collect(Collectors.joining("")) - )).orElseGet(Map::of) + contextSourcesOpt + .map(contextSources -> + Map.of( + "context-sources-map.txt", + contextSources + .stream() + .map(c -> + Base64 + .getUrlEncoder() + .withoutPadding() + .encodeToString(c.getName().getBytes()) + + "," + + c.getName() + + "\n" + ) + .collect(Collectors.joining("")) + ) + ) + .orElseGet(Map::of) ) ); diff --git a/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sJobFramework.java b/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sJobFramework.java index c8ceac660..9129147af 100644 --- a/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sJobFramework.java +++ b/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sJobFramework.java @@ -123,7 +123,11 @@ public K8sJobRunnable run(K8sJobRunnable runnable) throws K8sFrameworkException .stream() .collect( Collectors.toMap( - c -> Base64.getUrlEncoder().withoutPadding().encodeToString(c.getName().getBytes()), + c -> + Base64 + .getUrlEncoder() + .withoutPadding() + .encodeToString(c.getName().getBytes()), c -> new String( Base64.getDecoder().decode(c.getBase64()), @@ -134,11 +138,24 @@ public K8sJobRunnable run(K8sJobRunnable runnable) throws K8sFrameworkException ) .orElseGet(Map::of), contextSourcesOpt - .map(contextSources -> Map.of("context-sources-map.txt", - contextSources.stream() - .map(c -> Base64.getUrlEncoder().withoutPadding().encodeToString(c.getName().getBytes()) + "," + c.getName() + "\n") - .collect(Collectors.joining("")) - )).orElseGet(Map::of) + .map(contextSources -> + Map.of( + "context-sources-map.txt", + contextSources + .stream() + .map(c -> + Base64 + .getUrlEncoder() + .withoutPadding() + .encodeToString(c.getName().getBytes()) + + "," + + c.getName() + + "\n" + ) + .collect(Collectors.joining("")) + ) + ) + .orElseGet(Map::of) ) ); diff --git a/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sServeFramework.java b/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sServeFramework.java index 6b50446bc..273c2af1f 100644 --- a/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sServeFramework.java +++ b/modules/framework-k8s/src/main/java/it/smartcommunitylabdhub/framework/k8s/infrastructure/k8s/K8sServeFramework.java @@ -96,7 +96,11 @@ public K8sServeRunnable run(K8sServeRunnable runnable) throws K8sFrameworkExcept .stream() .collect( Collectors.toMap( - c -> Base64.getUrlEncoder().withoutPadding().encodeToString(c.getName().getBytes()), + c -> + Base64 + .getUrlEncoder() + .withoutPadding() + .encodeToString(c.getName().getBytes()), c -> new String( Base64.getDecoder().decode(c.getBase64()), @@ -106,12 +110,25 @@ public K8sServeRunnable run(K8sServeRunnable runnable) throws K8sFrameworkExcept ) ) .orElseGet(Map::of), - contextSourcesOpt - .map(contextSources -> Map.of("context-sources-map.txt", - contextSources.stream() - .map(c -> Base64.getUrlEncoder().withoutPadding().encodeToString(c.getName().getBytes()) + "," + c.getName() + "\n") - .collect(Collectors.joining("")) - )).orElseGet(Map::of) + contextSourcesOpt + .map(contextSources -> + Map.of( + "context-sources-map.txt", + contextSources + .stream() + .map(c -> + Base64 + .getUrlEncoder() + .withoutPadding() + .encodeToString(c.getName().getBytes()) + + "," + + c.getName() + + "\n" + ) + .collect(Collectors.joining("")) + ) + ) + .orElseGet(Map::of) ) ); diff --git a/modules/framework-kaniko/src/main/java/it/smartcommunitylabdhub/framework/kaniko/infrastructure/k8s/K8sKanikoFramework.java b/modules/framework-kaniko/src/main/java/it/smartcommunitylabdhub/framework/kaniko/infrastructure/k8s/K8sKanikoFramework.java index 24bc0d4ac..29fc3e9b1 100644 --- a/modules/framework-kaniko/src/main/java/it/smartcommunitylabdhub/framework/kaniko/infrastructure/k8s/K8sKanikoFramework.java +++ b/modules/framework-kaniko/src/main/java/it/smartcommunitylabdhub/framework/kaniko/infrastructure/k8s/K8sKanikoFramework.java @@ -28,7 +28,6 @@ import it.smartcommunitylabdhub.framework.k8s.objects.CoreVolume; import it.smartcommunitylabdhub.framework.kaniko.runnables.K8sKanikoRunnable; import jakarta.validation.constraints.NotNull; - import java.io.Serializable; import java.nio.charset.StandardCharsets; import java.util.ArrayList; @@ -39,7 +38,6 @@ import java.util.Map; import java.util.Optional; import java.util.stream.Collectors; - import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.util.Assert; @@ -52,9 +50,8 @@ public class K8sKanikoFramework extends K8sBaseFramework> typeRef = new TypeReference< - HashMap - >() { - }; + HashMap + >() {}; private final BatchV1Api batchV1Api; @@ -105,49 +102,67 @@ public K8sKanikoRunnable run(K8sKanikoRunnable runnable) throws K8sFrameworkExce Optional> contextRefsOpt = Optional.ofNullable(runnable.getContextRefs()); Optional> contextSourcesOpt = Optional.ofNullable(runnable.getContextSources()); V1ConfigMap configMap = new V1ConfigMap() - .metadata(new V1ObjectMeta().name("init-config-map-" + runnable.getId()).labels(buildLabels(runnable))) - .data( - MapUtils.mergeMultipleMaps( - //dockerfile - Map.of("Dockerfile", runnable.getDockerFile()), - // Generate context-refs.txt if exist - contextRefsOpt - .map(contextRefsList -> - Map.of( - "context-refs.txt", - contextRefsList - .stream() - .map(v -> - v.getProtocol() + "," + v.getDestination() + "," + v.getSource() + "\n" - ) - .collect(Collectors.joining("")) - ) - ) - .orElseGet(Map::of), - // Generate context-sources.txt if exist - contextSourcesOpt - .map(contextSources -> - contextSources - .stream() - .collect( - Collectors.toMap( - c -> Base64.getUrlEncoder().withoutPadding().encodeToString(c.getName().getBytes()), - c -> new String( - Base64.getDecoder().decode(c.getBase64()), - StandardCharsets.UTF_8 - ) - ) - ) - ) - .orElseGet(Map::of), - contextSourcesOpt - .map(contextSources -> Map.of("context-sources-map.txt", - contextSources.stream() - .map(c -> Base64.getUrlEncoder().withoutPadding().encodeToString(c.getName().getBytes()) + "," + c.getName() + "\n") - .collect(Collectors.joining("")) - )).orElseGet(Map::of) + .metadata(new V1ObjectMeta().name("init-config-map-" + runnable.getId()).labels(buildLabels(runnable))) + .data( + MapUtils.mergeMultipleMaps( + //dockerfile + Map.of("Dockerfile", runnable.getDockerFile()), + // Generate context-refs.txt if exist + contextRefsOpt + .map(contextRefsList -> + Map.of( + "context-refs.txt", + contextRefsList + .stream() + .map(v -> + v.getProtocol() + "," + v.getDestination() + "," + v.getSource() + "\n" + ) + .collect(Collectors.joining("")) + ) + ) + .orElseGet(Map::of), + // Generate context-sources.txt if exist + contextSourcesOpt + .map(contextSources -> + contextSources + .stream() + .collect( + Collectors.toMap( + c -> + Base64 + .getUrlEncoder() + .withoutPadding() + .encodeToString(c.getName().getBytes()), + c -> + new String( + Base64.getDecoder().decode(c.getBase64()), + StandardCharsets.UTF_8 + ) + ) + ) + ) + .orElseGet(Map::of), + contextSourcesOpt + .map(contextSources -> + Map.of( + "context-sources-map.txt", + contextSources + .stream() + .map(c -> + Base64 + .getUrlEncoder() + .withoutPadding() + .encodeToString(c.getName().getBytes()) + + "," + + c.getName() + + "\n" + ) + .collect(Collectors.joining("")) + ) ) - ); + .orElseGet(Map::of) + ) + ); coreV1Api.createNamespacedConfigMap(namespace, configMap, null, null, null, null); } catch (ApiException | NullPointerException e) { @@ -238,17 +253,17 @@ public V1Job build(K8sKanikoRunnable runnable) throws K8sFrameworkException { // Generate jobName and ContainerName String jobName = k8sBuilderHelper.getJobName(runnable.getRuntime(), runnable.getTask(), runnable.getId()); String containerName = k8sBuilderHelper.getContainerName( - runnable.getRuntime(), - runnable.getTask(), - runnable.getId() + runnable.getRuntime(), + runnable.getTask(), + runnable.getId() ); log.debug("build k8s job for {}", jobName); //build destination image name and set to runnable String prefix = - (StringUtils.hasText(imageRegistry) ? imageRegistry + "/" : "") + - (StringUtils.hasText(imagePrefix) ? imagePrefix + "-" : ""); + (StringUtils.hasText(imageRegistry) ? imageRegistry + "/" : "") + + (StringUtils.hasText(imagePrefix) ? imagePrefix + "-" : ""); // workaround: update image name only first time String imageName = runnable.getImage(); if (StringUtils.hasText(prefix) && !runnable.getImage().startsWith(prefix)) { @@ -264,10 +279,10 @@ public V1Job build(K8sKanikoRunnable runnable) throws K8sFrameworkException { // Create sharedVolume CoreVolume sharedVolume = new CoreVolume( - CoreVolume.VolumeType.empty_dir, - "/shared", - "shared-dir", - Map.of("sizeLimit", "100Mi") + CoreVolume.VolumeType.empty_dir, + "/shared", + "shared-dir", + Map.of("sizeLimit", "100Mi") ); List coreVolumes = new ArrayList<>(); @@ -279,20 +294,20 @@ public V1Job build(K8sKanikoRunnable runnable) throws K8sFrameworkException { // Create config map volume CoreVolume configMapVolume = new CoreVolume( - CoreVolume.VolumeType.config_map, - "/init-config-map", - "init-config-map", - Map.of("name", "init-config-map-" + runnable.getId()) + CoreVolume.VolumeType.config_map, + "/init-config-map", + "init-config-map", + Map.of("name", "init-config-map-" + runnable.getId()) ); coreVolumes.add(configMapVolume); // Add secret for kaniko if (StringUtils.hasText(kanikoSecret)) { CoreVolume secretVolume = new CoreVolume( - CoreVolume.VolumeType.secret, - "/kaniko/.docker", - kanikoSecret, - Map.of("items", CoreItems.builder().keyToPath(Map.of(".dockerconfigjson", "config.json")).build()) + CoreVolume.VolumeType.secret, + "/kaniko/.docker", + kanikoSecret, + Map.of("items", CoreItems.builder().keyToPath(Map.of(".dockerconfigjson", "config.json")).build()) ); if (runnableVolumesOpt.stream().noneMatch(v -> kanikoSecret.equals(v.getName()))) { coreVolumes.add(secretVolume); @@ -300,11 +315,11 @@ public V1Job build(K8sKanikoRunnable runnable) throws K8sFrameworkException { } //Add all volumes Optional - .ofNullable(runnable.getVolumes()) - .ifPresentOrElse(coreVolumes::addAll, () -> runnable.setVolumes(coreVolumes)); + .ofNullable(runnable.getVolumes()) + .ifPresentOrElse(coreVolumes::addAll, () -> runnable.setVolumes(coreVolumes)); List kanikoArgsAll = new ArrayList<>( - List.of("--dockerfile=/init-config-map/Dockerfile", "--context=/shared", "--destination=" + imageName) + List.of("--dockerfile=/init-config-map/Dockerfile", "--context=/shared", "--destination=" + imageName) ); // Add Kaniko args kanikoArgsAll.addAll(kanikoArgs); @@ -322,24 +337,24 @@ public V1Job build(K8sKanikoRunnable runnable) throws K8sFrameworkException { // Build Container V1Container container = new V1Container() - .name(containerName) - .image(kanikoImage) - .imagePullPolicy("Always") - .imagePullPolicy("IfNotPresent") - .args(kanikoArgsAll) - .resources(resources) - .volumeMounts(volumeMounts) - .envFrom(envFrom) - .env(env); + .name(containerName) + .image(kanikoImage) + .imagePullPolicy("Always") + .imagePullPolicy("IfNotPresent") + .args(kanikoArgsAll) + .resources(resources) + .volumeMounts(volumeMounts) + .envFrom(envFrom) + .env(env); // Create a PodSpec for the container V1PodSpec podSpec = new V1PodSpec() - .containers(Collections.singletonList(container)) - .nodeSelector(buildNodeSelector(runnable)) - .affinity(runnable.getAffinity()) - .tolerations(buildTolerations(runnable)) - .volumes(volumes) - .restartPolicy("Never"); + .containers(Collections.singletonList(container)) + .nodeSelector(buildNodeSelector(runnable)) + .affinity(runnable.getAffinity()) + .tolerations(buildTolerations(runnable)) + .volumes(volumes) + .restartPolicy("Never"); // Create a PodTemplateSpec with the PodSpec V1PodTemplateSpec podTemplateSpec = new V1PodTemplateSpec().metadata(metadata).spec(podSpec); @@ -347,14 +362,14 @@ public V1Job build(K8sKanikoRunnable runnable) throws K8sFrameworkException { // Add Init container to the PodTemplateSpec // Build the Init Container V1Container initContainer = new V1Container() - .name("init-container-" + runnable.getId()) - .image(initImage) - .volumeMounts(volumeMounts) - .resources(resources) - .env(env) - .envFrom(envFrom) - //TODO below execute a command that is a Go script - .command(List.of("/bin/bash", "-c", "/app/builder-tool.sh")); + .name("init-container-" + runnable.getId()) + .image(initImage) + .volumeMounts(volumeMounts) + .resources(resources) + .env(env) + .envFrom(envFrom) + //TODO below execute a command that is a Go script + .command(List.of("/bin/bash", "-c", "/app/builder-tool.sh")); // Set initContainer as first container in the PodSpec podSpec.setInitContainers(Collections.singletonList(initContainer)); @@ -363,11 +378,11 @@ public V1Job build(K8sKanikoRunnable runnable) throws K8sFrameworkException { // Create the JobSpec with the PodTemplateSpec V1JobSpec jobSpec = new V1JobSpec() - .activeDeadlineSeconds(Long.valueOf(activeDeadlineSeconds)) - .parallelism(1) - .completions(1) - .backoffLimit(backoffLimit) - .template(podTemplateSpec); + .activeDeadlineSeconds(Long.valueOf(activeDeadlineSeconds)) + .parallelism(1) + .completions(1) + .backoffLimit(backoffLimit) + .template(podTemplateSpec); // Return a new job with metadata and jobSpec return new V1Job().metadata(metadata).spec(jobSpec);