Skip to content

Commit

Permalink
feat: improve docker compose coverage (#2320)
Browse files Browse the repository at this point in the history
## Description
This PR contains various improvements (and hacks) to docker compose
transpiler to improve it's coverage of docker composes, specifically in
the `awesome-compose` repo.

- support for per service `env_file` key
- better path support, notably turn filepaths referencing upstream or
home path to Persistent Directories
- use container name as service name if set (required for hostname
networking)
- support for volumes mounting files (before only supported directories
due to files artifact expansion limitations)
- converts invalid service names to ones that are RFC 1035

other fixes for compose to enable more docker compose coverage:
- allow uploading entire package contents into a files artifact
- allow compressing empty directories

## Is this change user facing?
NO

## References
#2043

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Ben Gazzard <ben@dartoxia.com>
Co-authored-by: Gyanendra Mishra <anomaly.the@gmail.com>
Co-authored-by: kurtosisbot <89932784+kurtosisbot@users.noreply.github.com>
Co-authored-by: kurtosisbot <kurtosisbot@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Laurent Luce <laurentluce49@yahoo.com>
Co-authored-by: leoporoli <leandroporoli@gmail.com>
Co-authored-by: leovct <l009.vincent@gmail.com>
  • Loading branch information
9 people committed Mar 22, 2024
1 parent 7bfa28f commit 45bd59e
Show file tree
Hide file tree
Showing 15 changed files with 478 additions and 106 deletions.
Expand Up @@ -2,6 +2,8 @@ package user_service_functions

import (
"context"
"fmt"
"strconv"
"strings"
"sync"

Expand Down Expand Up @@ -539,6 +541,7 @@ func createStartServiceOperation(
memoryAllocationMegabytes := serviceConfig.GetMemoryAllocationMegabytes()
privateIPAddrPlaceholder := serviceConfig.GetPrivateIPAddrPlaceholder()
user := serviceConfig.GetUser()
filesToBeMoved := serviceConfig.GetFilesToBeMoved()

// We replace the placeholder value with the actual private IP address
privateIPAddrStr := privateIpAddr.String()
Expand All @@ -552,6 +555,17 @@ func createStartServiceOperation(
envVars[key] = strings.Replace(envVars[key], privateIPAddrPlaceholder, privateIPAddrStr, unlimitedReplacements)
}

// TODO clean this hack up
// this path will only be hit if `files_to_be_moved` is set in Starlark; which is a hidden property
// used by compose transpilation
if len(filesToBeMoved) > 0 {
var err error
cmdArgs, entrypointArgs, err = getUpdatedEntrypointAndCmdFromFilesToBeMoved(ctx, dockerManager, containerImageName, cmdArgs, entrypointArgs, filesToBeMoved)
if err != nil {
return nil, stacktrace.Propagate(err, "an error occurred while handling files for compose")
}
}

volumeMounts := map[string]string{}
shouldDeleteVolumes := true
if filesArtifactsExpansion != nil {
Expand Down Expand Up @@ -753,6 +767,50 @@ func createStartServiceOperation(
}
}

// TODO - clean this up this is super janky, a way to handle compose & volume
func getUpdatedEntrypointAndCmdFromFilesToBeMoved(ctx context.Context, dockerManager *docker_manager.DockerManager, containerImageName string, cmdArgs []string, entrypointArgs []string, filesToBeMoved map[string]string) ([]string, []string, error) {
concatenatedFilesToBeMoved := []string{}
for source, destination := range filesToBeMoved {
// TODO improve this; the first condition handles files the other folders
concatenatedFilesToBeMoved = append(concatenatedFilesToBeMoved, fmt.Sprintf("mv %v %v", source, destination))
}

concatenatedFilesToBeMovedAsStr := strings.Join(concatenatedFilesToBeMoved, " && ")
originalEntrypointArgs, originalCmdArgs, err := dockerManager.GetEntryPointAndCommand(ctx, containerImageName)
if err != nil {
return nil, nil, stacktrace.Propagate(err, "an error occurred fetching data about image '%v'", containerImageName)
}

// we do this replacement as we want to keep the original command args as they are not overwritten
// it might be that none of the two are set
if len(cmdArgs) == 0 && len(originalCmdArgs) > 0 {
cmdArgs = originalCmdArgs
}
if len(entrypointArgs) == 0 && len(originalEntrypointArgs) > 0 {
entrypointArgs = originalEntrypointArgs
}

entryPointArgsAsStr := quoteAndJoinArgs(entrypointArgs)
cmdArgsAsStr := quoteAndJoinArgs(cmdArgs)

if len(cmdArgs) > 0 {
if len(entrypointArgs) > 0 {
cmdArgs = []string{"-c", concatenatedFilesToBeMovedAsStr + " && " + entryPointArgsAsStr + " " + cmdArgsAsStr}
} else {
cmdArgs = []string{"-c", concatenatedFilesToBeMovedAsStr + " && " + cmdArgsAsStr}
}
} else {
if len(entrypointArgs) > 0 {
cmdArgs = []string{"-c", concatenatedFilesToBeMovedAsStr + " && " + entryPointArgsAsStr}
} else {
// no entrypoint and no command; this shouldn't really happen
cmdArgs = []string{"-c", concatenatedFilesToBeMovedAsStr}
}
}
entrypointArgs = []string{"/bin/sh"}
return cmdArgs, entrypointArgs, nil
}

// Ensure that provided [privatePorts] and [publicPorts] are one to one by checking:
// - There is a matching publicPort for every portID in privatePorts
// - There are the same amount of private and public ports
Expand Down Expand Up @@ -845,3 +903,11 @@ func registerUserServices(

return successfulRegistrations, failedRegistrations, nil
}

func quoteAndJoinArgs(args []string) string {
var quotedArgs []string
for _, arg := range args {
quotedArgs = append(quotedArgs, strconv.Quote(arg))
}
return strings.Join(quotedArgs, " ")
}
Expand Up @@ -1660,6 +1660,17 @@ func (manager *DockerManager) getImagePlatform(ctx context.Context, imageName st
return imageInspect.Architecture, nil
}

func (manager *DockerManager) GetEntryPointAndCommand(ctx context.Context, imageName string) ([]string, []string, error) {
imageInspect, _, err := manager.dockerClient.ImageInspectWithRaw(ctx, imageName)
if err != nil {
return nil, nil, stacktrace.Propagate(err, "an error occurred while running image inspect on image '%v'", imageName)
}
if imageInspect.Config == nil {
return nil, nil, stacktrace.NewError("image inspect config was empty, can't geet entrypoint or cmd: %v", imageInspect)
}
return imageInspect.Config.Entrypoint, imageInspect.Config.Cmd, nil
}

/*
Creates a Docker-Container-To-Host Port mapping, defining how a Container's JSON RPC and service-specific ports are
mapped to the host ports.
Expand Down
Expand Up @@ -2,9 +2,8 @@ package service

import (
"encoding/json"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode"

"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_build_spec"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_download_mode"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/image_registry_spec"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/nix_build_spec"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/port_spec"
Expand Down Expand Up @@ -70,6 +69,8 @@ type privateServiceConfig struct {
NodeSelectors map[string]string

ImageDownloadMode image_download_mode.ImageDownloadMode

FilesToBeMoved map[string]string
}

func CreateServiceConfig(
Expand Down Expand Up @@ -123,6 +124,7 @@ func CreateServiceConfig(
Tolerations: tolerations,
NodeSelectors: nodeSelectors,
ImageDownloadMode: imageDownloadMode,
FilesToBeMoved: map[string]string{},
}
return &ServiceConfig{internalServiceConfig}, nil
}
Expand Down Expand Up @@ -217,6 +219,14 @@ func (serviceConfig *ServiceConfig) GetNodeSelectors() map[string]string {
return serviceConfig.privateServiceConfig.NodeSelectors
}

func (serviceConfig *ServiceConfig) SetFilesToBeMoved(filesToBeMoved map[string]string) {
serviceConfig.privateServiceConfig.FilesToBeMoved = filesToBeMoved
}

func (serviceConfig *ServiceConfig) GetFilesToBeMoved() map[string]string {
return serviceConfig.privateServiceConfig.FilesToBeMoved
}

func (serviceConfig *ServiceConfig) UnmarshalJSON(data []byte) error {

// Suppressing exhaustruct requirement because we want an object with zero values
Expand Down

0 comments on commit 45bd59e

Please sign in to comment.