Navigation Menu

Skip to content

Commit

Permalink
feat(stapel-to-buildah): run user stages commands in the script using…
Browse files Browse the repository at this point in the history
… sh or bash

Signed-off-by: Timofey Kirillov <timofey.kirillov@flant.com>
  • Loading branch information
distorhead committed May 6, 2022
1 parent 188ec71 commit e9aa1d4
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 20 deletions.
5 changes: 4 additions & 1 deletion cmd/werf/common/container_backend.go
Expand Up @@ -4,13 +4,15 @@ import (
"context"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/werf/werf/pkg/buildah"
"github.com/werf/werf/pkg/buildah/thirdparty"
"github.com/werf/werf/pkg/container_backend"
"github.com/werf/werf/pkg/docker"
"github.com/werf/werf/pkg/util"
"github.com/werf/werf/pkg/werf"
)

func ContainerBackendProcessStartupHook() (bool, error) {
Expand Down Expand Up @@ -110,6 +112,7 @@ func InitProcessContainerBackend(ctx context.Context, cmdData *CmdData) (contain
insecure := *cmdData.InsecureRegistry || *cmdData.SkipTlsVerifyRegistry
b, err := buildah.NewBuildah(resolvedMode, buildah.BuildahOpts{
CommonBuildahOpts: buildah.CommonBuildahOpts{
TmpDir: filepath.Join(werf.GetServiceDir(), "tmp", "buildah"),
Insecure: insecure,
Isolation: buildahIsolation,
StorageDriver: storageDriver,
Expand All @@ -119,7 +122,7 @@ func InitProcessContainerBackend(ctx context.Context, cmdData *CmdData) (contain
return nil, ctx, fmt.Errorf("unable to get buildah client: %w", err)
}

return wrapContainerBackend(container_backend.NewBuildahBackend(b)), ctx, nil
return wrapContainerBackend(container_backend.NewBuildahBackend(b, filepath.Join(werf.GetServiceDir(), "tmp", "buildah"))), ctx, nil
}

newCtx, err := InitProcessDocker(ctx, cmdData)
Expand Down
77 changes: 58 additions & 19 deletions pkg/container_backend/buildah_backend.go
Expand Up @@ -16,7 +16,7 @@ import (
"github.com/google/uuid"
"github.com/opencontainers/runtime-spec/specs-go"

"github.com/werf/copy-recurse"
copyrec "github.com/werf/copy-recurse"
"github.com/werf/logboek"
"github.com/werf/werf/pkg/buildah"
"github.com/werf/werf/pkg/image"
Expand All @@ -25,15 +25,16 @@ import (
)

type BuildahBackend struct {
TmpDir string
buildah buildah.Buildah
}

type BuildahImage struct {
Image LegacyImageInterface
}

func NewBuildahBackend(buildah buildah.Buildah) *BuildahBackend {
return &BuildahBackend{buildah: buildah}
func NewBuildahBackend(buildah buildah.Buildah, tmpDir string) *BuildahBackend {
return &BuildahBackend{buildah: buildah, TmpDir: tmpDir}
}

func (runtime *BuildahBackend) HasStapelBuildSupport() bool {
Expand Down Expand Up @@ -103,24 +104,62 @@ func (runtime *BuildahBackend) unmountContainers(ctx context.Context, containers
return nil
}

func makeScript(commands []string) []byte {
var scriptCommands []string
for _, c := range commands {
scriptCommands = append(scriptCommands, fmt.Sprintf(`printf "$ %%s\n" %q`, c))
scriptCommands = append(scriptCommands, c)
}

return []byte(fmt.Sprintf(`#!/bin/sh
set -e
if [ "x$_IS_REEXEC" = "x" ]; then
if type bash >/dev/null 2>&1 ; then
echo "# Using bash to execute commands"
echo
export _IS_REEXEC="1"
exec bash $0
else
echo "# Using /bin/sh to execute commands"
echo
fi
fi
%s
`, strings.Join(scriptCommands, "\n")))
}

func (runtime *BuildahBackend) applyCommands(ctx context.Context, container *containerDesc, buildVolumes []string, commands []string) error {
for _, cmd := range commands {
var mounts []specs.Mount
mounts, err := makeBuildahMounts(buildVolumes)
if err != nil {
return err
}
hostScriptPath := filepath.Join(runtime.TmpDir, fmt.Sprintf("script-%s.sh", uuid.New().String()))
if err := os.WriteFile(hostScriptPath, makeScript(commands), os.FileMode(0o555)); err != nil {
return fmt.Errorf("unable to write script file %q: %w", hostScriptPath, err)
}
defer os.RemoveAll(hostScriptPath)

// TODO(stapel-to-buildah): Consider support for shell script instead of separate run commands to allow shared
// usage of shell variables and functions between multiple commands.
// Maybe there is no need of such function, instead provide options to select shell in the werf.yaml.
// Is it important to provide compatibility between docker-server-based werf.yaml and buildah-based?
if err := runtime.buildah.RunCommand(ctx, container.Name, []string{"sh", "-c", cmd}, buildah.RunCommandOpts{
CommonOpts: runtime.getBuildahCommonOpts(ctx, false),
Mounts: mounts,
}); err != nil {
return fmt.Errorf("unable to run %q: %w", cmd, err)
}
logboek.Context(ctx).Default().LogF("Executing script %s\n", hostScriptPath)

destScriptPath := "/.werf/script.sh"

var mounts []specs.Mount
mounts = append(mounts, specs.Mount{
Type: "bind",
Source: hostScriptPath,
Destination: destScriptPath,
})

if m, err := makeBuildahMounts(buildVolumes); err != nil {
return err
} else {
mounts = append(mounts, m...)
}

if err := runtime.buildah.RunCommand(ctx, container.Name, []string{"sh", destScriptPath}, buildah.RunCommandOpts{
CommonOpts: runtime.getBuildahCommonOpts(ctx, false),
Mounts: mounts,
}); err != nil {
return fmt.Errorf("unable to run commands script: %w", err)
}

return nil
Expand Down

0 comments on commit e9aa1d4

Please sign in to comment.