Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: build nix image #2132

Merged
merged 16 commits into from
Feb 9, 2024
10 changes: 6 additions & 4 deletions cli/cli/commands/import/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ package _import
import (
"context"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"

"github.com/compose-spec/compose-go/loader"
"github.com/compose-spec/compose-go/types"
"github.com/joho/godotenv"
Expand All @@ -25,10 +30,6 @@ import (
"github.com/kurtosis-tech/kurtosis/name_generator"
"github.com/kurtosis-tech/stacktrace"
"github.com/sirupsen/logrus"
"os"
"path/filepath"
"strconv"
"strings"
)

const (
Expand Down Expand Up @@ -175,6 +176,7 @@ func run(

func convertComposeFileToStarlark(path string, dotEnvMap map[string]string) (string, map[string]string, error) {
project, err := loader.Load(types.ConfigDetails{ //nolint:exhaustruct
// nolint: exhaustruct
ConfigFiles: []types.ConfigFile{{Filename: path}},
Environment: dotEnvMap,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package docker_kurtosis_backend

import (
"context"
"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_registry_spec"
"io"
"sync"

"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_registry_spec"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/nix_build_spec"

"github.com/sirupsen/logrus"

"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/docker/docker_kurtosis_backend/engine_functions"
Expand Down Expand Up @@ -544,6 +546,10 @@ func (backend *DockerKurtosisBackend) BuildImage(ctx context.Context, imageName
return backend.dockerManager.BuildImage(ctx, imageName, imageBuildSpec)
}

func (backend *DockerKurtosisBackend) NixBuild(ctx context.Context, nixBuildSpec *nix_build_spec.NixBuildSpec) (string, error) {
return backend.dockerManager.NixBuild(ctx, nixBuildSpec)
}

// ====================================================================================================
//
// Private helper functions shared by multiple subfunctions files
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,28 @@ import (
"bufio"
"bytes"
"context"
"crypto/md5"
"encoding/json"
"fmt"
"github.com/docker/docker/api/types/registry"
"github.com/docker/go-units"
"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_registry_spec"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/uuid_generator"
"github.com/kurtosis-tech/kurtosis/utils"
"io"
"math"
"net"
"os"
"os/exec"
"regexp"
"strings"
"sync"
"time"

"github.com/docker/docker/api/types/registry"
"github.com/docker/go-units"
"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_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/image_utils"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/uuid_generator"
"github.com/kurtosis-tech/kurtosis/utils"

"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/filters"
Expand Down Expand Up @@ -152,6 +158,8 @@ const (

// Per https://github.com/hashicorp/waypoint/pull/1937/files
buildkitSessionSharedKey = ""

nixCmdPath = "/nix/var/nix/profiles/default/bin/nix"
)

type RestartPolicy string
Expand Down Expand Up @@ -1313,6 +1321,58 @@ func (manager *DockerManager) FetchImage(ctx context.Context, image string, regi
return pulledFromRemote, imageArchitecture, nil
}

func (manager *DockerManager) NixBuild(ctx context.Context, nixBuildSpec *nix_build_spec.NixBuildSpec) (string, error) {
flakeReference := nixBuildSpec.GetFullFlakeReference()

// Flake generates a link to the nix store containing the image result, to avoid collision with a possible existing one from the
// build context (from the user env) and which would result when trying to overwrite it, we create a unique one
hasher := md5.New()
hasher.Write([]byte(flakeReference))
resultLink := fmt.Sprintf("nix-result-%x", hasher.Sum(nil))

cmd := exec.Command(
nixCmdPath, "build", flakeReference,
"--print-out-paths",
"--extra-experimental-features", "flakes nix-command",
"--out-link", resultLink)

var errBuffer strings.Builder
cmd.Stderr = &errBuffer
imageFileRaw, err := cmd.Output()
if err != nil {
errMsg := errBuffer.String()
logrus.WithError(err).Error(errMsg)
return "", stacktrace.Propagate(err, "Failed to build nix image with Nix.")
}
imageFile := strings.TrimSpace(string(imageFileRaw))
logrus.Debugf("Nix flake image on attribute %s, result on image file %s", flakeReference, imageFile)

imageTags, err := image_utils.GetRepoTags(imageFile)
if err != nil {
return "", stacktrace.Propagate(err, "Failed to get image tags from Nix image %s", imageFile)
}

if len(imageTags) == 0 {
return "", stacktrace.NewError("Generated image %s did not have any tags", imageFile)
} else if len(imageTags) > 1 {
logrus.Warnf("Generated image %s had multiple tags: %v. We'll select the first.", imageFile, imageTags)
}
imageTag := imageTags[0]

image, err := os.Open(imageFile)
if err != nil {
return "", stacktrace.Propagate(err, "Failed to open generated Nix image on %s", imageFile)
}

_, err = manager.dockerClient.ImageLoad(ctx, image, false)
if err != nil {
return "", stacktrace.Propagate(err, "Failed to load Nix image %s in docker", imageFile)
}
logrus.Debugf("Nix generated image file %s is loaded into docker", imageFile)

return imageTag, nil
}

func (manager *DockerManager) BuildImage(ctx context.Context, imageName string, imageBuildSpec *image_build_spec.ImageBuildSpec) (string, error) {
buildContextDirPath := imageBuildSpec.GetBuildContextDir()
buildContextTarReader, err := getBuildContextReader(buildContextDirPath)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ func createEngineClusterRole(
}
clusterRoleName := clusterRolesAttributes.GetName().GetString()
clusterRoleLabels := shared_helpers.GetStringMapFromLabelMap(clusterRolesAttributes.GetLabels())
// nolint: exhaustruct
clusterRolePolicyRules := []rbacv1.PolicyRule{
{
Verbs: []string{
Expand Down Expand Up @@ -388,6 +389,7 @@ func createEngineClusterRoleBindings(
}
clusterRoleBindingsName := clusterRoleBindingsAttributes.GetName().GetString()
clusterRoleBindingsLabels := shared_helpers.GetStringMapFromLabelMap(clusterRoleBindingsAttributes.GetLabels())
// nolint: exhaustruct
clusterRoleBindingsSubjects := []rbacv1.Subject{
{
Kind: rbacv1.ServiceAccountKind,
Expand Down Expand Up @@ -452,6 +454,7 @@ func createEnginePod(
}
engineContainerEnvVars = append(engineContainerEnvVars, envVar)
}
// nolint: exhaustruct
engineContainers := []apiv1.Container{
{
Name: kurtosisEngineContainerName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package kubernetes_kurtosis_backend

import (
"context"
"io"

"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_registry_spec"
"io"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/nix_build_spec"
apiv1 "k8s.io/api/core/v1"

"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/kubernetes/kubernetes_kurtosis_backend/engine_functions"
Expand Down Expand Up @@ -487,6 +489,11 @@ func (backend *KubernetesKurtosisBackend) BuildImage(ctx context.Context, imageN
return "", stacktrace.NewError("Building images isn't yet implemented in Kubernetes.")
}

func (backend *KubernetesKurtosisBackend) NixBuild(ctx context.Context, nixBuildSpec *nix_build_spec.NixBuildSpec) (string, error) {
lostbean marked this conversation as resolved.
Show resolved Hide resolved
// TODO IMPLEMENT
return "", stacktrace.NewError("Nix image building isn't yet implemented in Kubernetes.")
}

// ====================================================================================================
//
// Private Helper Functions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package kubernetes_kurtosis_backend
import (
"context"
"fmt"
"net"
"time"

"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/kubernetes/kubernetes_kurtosis_backend/consts"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/kubernetes/kubernetes_kurtosis_backend/shared_helpers"
kubernetes_manager_consts "github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/kubernetes/kubernetes_manager/consts"
Expand All @@ -17,8 +20,6 @@ import (
apiv1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
applyconfigurationsv1 "k8s.io/client-go/applyconfigurations/core/v1"
"net"
"time"
)

const (
Expand Down Expand Up @@ -233,6 +234,7 @@ func (backend *KubernetesKurtosisBackend) CreateAPIContainer(

clusterRoleName := clusterRolesAttributes.GetName().GetString()
clusterRoleLabels := shared_helpers.GetStringMapFromLabelMap(clusterRolesAttributes.GetLabels())
// nolint: exhaustruct
clusterRolePolicyRules := []rbacv1.PolicyRule{
{
Verbs: []string{
Expand Down Expand Up @@ -292,6 +294,7 @@ func (backend *KubernetesKurtosisBackend) CreateAPIContainer(

clusterRoleBindingName := clusterRoleBindingsAttributes.GetName().GetString()
clusterRoleBindingsLabels := shared_helpers.GetStringMapFromLabelMap(clusterRoleBindingsAttributes.GetLabels())
// nolint: exhaustruct
clusterRoleBindingsSubjects := []rbacv1.Subject{
{
Kind: rbacv1.ServiceAccountKind,
Expand Down Expand Up @@ -335,6 +338,7 @@ func (backend *KubernetesKurtosisBackend) CreateAPIContainer(

roleName := rolesAttributes.GetName().GetString()
roleLabels := shared_helpers.GetStringMapFromLabelMap(rolesAttributes.GetLabels())
// nolint: exhaustruct
rolePolicyRules := []rbacv1.PolicyRule{
{
Verbs: []string{
Expand Down Expand Up @@ -394,6 +398,7 @@ func (backend *KubernetesKurtosisBackend) CreateAPIContainer(

roleBindingName := roleBindingsAttributes.GetName().GetString()
roleBindingsLabels := shared_helpers.GetStringMapFromLabelMap(roleBindingsAttributes.GetLabels())
// nolint: exhaustruct
roleBindingsSubjects := []rbacv1.Subject{
{
Kind: rbacv1.ServiceAccountKind,
Expand Down Expand Up @@ -1085,6 +1090,7 @@ func getApiContainerContainersAndVolumes(
}
containerEnvVars = append(containerEnvVars, ownNamespaceEnvVar)

// nolint: exhaustruct
containers := []apiv1.Container{
{
Name: kurtosisApiContainerContainerName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@ package user_services_functions
import (
"context"
"fmt"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service_user"
"strings"

"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/service_user"

"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/kubernetes/kubernetes_kurtosis_backend/consts"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/kubernetes/kubernetes_kurtosis_backend/shared_helpers"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_impls/kubernetes/kubernetes_manager"
Expand Down Expand Up @@ -681,7 +682,7 @@ func getUserServicePodContainerSpecs(
Limits: resourceLimitsList,
Requests: resourceRequestsList,
}

// nolint: exhaustruct
containers := []apiv1.Container{
{
Name: userServiceContainerName,
Expand Down Expand Up @@ -871,6 +872,7 @@ func createRegisterUserServiceOperation(

// Kubernetes doesn't allow us to create services without any ports, so we need to set this to a notional value
// until the user calls StartService
// nolint: exhaustruct
notionalServicePorts := []apiv1.ServicePort{
{
Name: unboundPortName,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package metrics_reporting

import (
"context"
"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_registry_spec"
"io"
"time"

"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_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"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/api_container"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/compute_resources"
Expand Down Expand Up @@ -470,3 +472,7 @@ func (backend *MetricsReportingKurtosisBackend) GetAvailableCPUAndMemory(ctx con
func (backend *MetricsReportingKurtosisBackend) BuildImage(ctx context.Context, imageName string, imageBuildSpec *image_build_spec.ImageBuildSpec) (string, error) {
return backend.underlying.BuildImage(ctx, imageName, imageBuildSpec)
}

func (backend *MetricsReportingKurtosisBackend) NixBuild(ctx context.Context, nixBuildSpec *nix_build_spec.NixBuildSpec) (string, error) {
return backend.underlying.NixBuild(ctx, nixBuildSpec)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ package backend_interface

import (
"context"
"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_registry_spec"
"io"
"time"

"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_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/api_container"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/compute_resources"
"github.com/kurtosis-tech/kurtosis/container-engine-lib/lib/backend_interface/objects/enclave"
Expand Down Expand Up @@ -356,4 +358,6 @@ type KurtosisBackend interface {
// BuildImage builds a container image based on the [imageBuildSpec] with [imageName]
// Returns image architecture and if error occurred
BuildImage(ctx context.Context, imageName string, imageBuildSpec *image_build_spec.ImageBuildSpec) (string, error)

NixBuild(ctx context.Context, nixBuildSpec *nix_build_spec.NixBuildSpec) (string, error)
}
Loading
Loading