Skip to content

Commit

Permalink
feat(staged-dockerfile): refactor dockerfile, use buidkit instruction…
Browse files Browse the repository at this point in the history
… structs directly

Signed-off-by: Timofey Kirillov <timofey.kirillov@flant.com>
  • Loading branch information
distorhead committed Oct 28, 2022
1 parent eb801bd commit e138887
Show file tree
Hide file tree
Showing 60 changed files with 418 additions and 662 deletions.
9 changes: 7 additions & 2 deletions pkg/build/build_phase.go
Expand Up @@ -14,6 +14,7 @@ import (
"time"

"github.com/google/uuid"
"github.com/moby/buildkit/frontend/dockerfile/instructions"

"github.com/werf/logboek"
"github.com/werf/logboek/pkg/style"
Expand All @@ -23,7 +24,6 @@ import (
"github.com/werf/werf/pkg/container_backend"
backend_instruction "github.com/werf/werf/pkg/container_backend/instruction"
"github.com/werf/werf/pkg/docker_registry"
dockerfile_instruction "github.com/werf/werf/pkg/dockerfile/instruction"
"github.com/werf/werf/pkg/git_repo"
imagePkg "github.com/werf/werf/pkg/image"
"github.com/werf/werf/pkg/stapel"
Expand Down Expand Up @@ -696,7 +696,12 @@ func (phase *BuildPhase) prepareStageInstructions(ctx context.Context, img *imag
})
} else {
stageImage.Builder.DockerfileStageBuilder().SetBuildContextArchive(phase.buildContextArchive)
stageImage.Builder.DockerfileStageBuilder().AppendPostInstruction(backend_instruction.NewLabel(*dockerfile_instruction.NewLabel("", serviceLabels)))

for k, v := range serviceLabels {
stageImage.Builder.DockerfileStageBuilder().AppendPostInstruction(
backend_instruction.NewLabel(instructions.NewLabelCommand(k, v, true)),
)
}
}

err := stg.PrepareImage(ctx, phase.Conveyor, phase.Conveyor.ContainerBackend, phase.StagesIterator.GetPrevBuiltImage(img, stg), stageImage, phase.buildContextArchive)
Expand Down
35 changes: 17 additions & 18 deletions pkg/build/image/dockerfile.go
Expand Up @@ -16,7 +16,6 @@ import (
"github.com/werf/werf/pkg/config"
"github.com/werf/werf/pkg/dockerfile"
"github.com/werf/werf/pkg/dockerfile/frontend"
dockerfile_instruction "github.com/werf/werf/pkg/dockerfile/instruction"
"github.com/werf/werf/pkg/giterminism_manager"
"github.com/werf/werf/pkg/path_matcher"
"github.com/werf/werf/pkg/util"
Expand Down Expand Up @@ -136,40 +135,40 @@ func mapDockerfileToImagesSets(ctx context.Context, cfg *dockerfile.Dockerfile,

var stg stage.Interface
switch typedInstr := any(instr).(type) {
case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Arg]:
case *dockerfile.DockerfileStageInstruction[*instructions.ArgCommand]:
// TODO(staged-dockerfile): support build-args at this level or dockerfile pkg level (?)
continue
case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Add]:
case *dockerfile.DockerfileStageInstruction[*instructions.AddCommand]:
stg = stage_instruction.NewAdd(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions)
case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Cmd]:
case *dockerfile.DockerfileStageInstruction[*instructions.CmdCommand]:
stg = stage_instruction.NewCmd(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions)
case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Copy]:
case *dockerfile.DockerfileStageInstruction[*instructions.CopyCommand]:
stg = stage_instruction.NewCopy(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions)
case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Entrypoint]:
case *dockerfile.DockerfileStageInstruction[*instructions.EntrypointCommand]:
stg = stage_instruction.NewEntrypoint(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions)
case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Env]:
case *dockerfile.DockerfileStageInstruction[*instructions.EnvCommand]:
stg = stage_instruction.NewEnv(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions)
case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Expose]:
case *dockerfile.DockerfileStageInstruction[*instructions.ExposeCommand]:
stg = stage_instruction.NewExpose(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions)
case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Healthcheck]:
case *dockerfile.DockerfileStageInstruction[*instructions.HealthCheckCommand]:
stg = stage_instruction.NewHealthcheck(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions)
case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Label]:
case *dockerfile.DockerfileStageInstruction[*instructions.LabelCommand]:
stg = stage_instruction.NewLabel(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions)
case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Maintainer]:
case *dockerfile.DockerfileStageInstruction[*instructions.MaintainerCommand]:
stg = stage_instruction.NewMaintainer(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions)
case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.OnBuild]:
case *dockerfile.DockerfileStageInstruction[*instructions.OnbuildCommand]:
stg = stage_instruction.NewOnBuild(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions)
case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Run]:
case *dockerfile.DockerfileStageInstruction[*instructions.RunCommand]:
stg = stage_instruction.NewRun(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions)
case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Shell]:
case *dockerfile.DockerfileStageInstruction[*instructions.ShellCommand]:
stg = stage_instruction.NewShell(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions)
case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.StopSignal]:
case *dockerfile.DockerfileStageInstruction[*instructions.StopSignalCommand]:
stg = stage_instruction.NewStopSignal(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions)
case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.User]:
case *dockerfile.DockerfileStageInstruction[*instructions.UserCommand]:
stg = stage_instruction.NewUser(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions)
case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Volume]:
case *dockerfile.DockerfileStageInstruction[*instructions.VolumeCommand]:
stg = stage_instruction.NewVolume(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions)
case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Workdir]:
case *dockerfile.DockerfileStageInstruction[*instructions.WorkdirCommand]:
stg = stage_instruction.NewWorkdir(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions)
default:
panic(fmt.Sprintf("unsupported instruction type %#v", instr))
Expand Down
18 changes: 9 additions & 9 deletions pkg/build/stage/instruction/add.go
Expand Up @@ -5,21 +5,22 @@ import (
"fmt"
"strings"

"github.com/moby/buildkit/frontend/dockerfile/instructions"

"github.com/werf/werf/pkg/build/stage"
"github.com/werf/werf/pkg/config"
"github.com/werf/werf/pkg/container_backend"
backend_instruction "github.com/werf/werf/pkg/container_backend/instruction"
"github.com/werf/werf/pkg/dockerfile"
dockerfile_instruction "github.com/werf/werf/pkg/dockerfile/instruction"
"github.com/werf/werf/pkg/util"
)

type Add struct {
*Base[*dockerfile_instruction.Add, *backend_instruction.Add]
*Base[*instructions.AddCommand, *backend_instruction.Add]
}

func NewAdd(name stage.StageName, i *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Add], dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *Add {
return &Add{Base: NewBase(name, i, backend_instruction.NewAdd(*i.Data), dependencies, hasPrevStage, opts)}
func NewAdd(name stage.StageName, i *dockerfile.DockerfileStageInstruction[*instructions.AddCommand], dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *Add {
return &Add{Base: NewBase(name, i, backend_instruction.NewAdd(i.Data), dependencies, hasPrevStage, opts)}
}

func (stg *Add) GetDependencies(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevImage, prevBuiltImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) (string, error) {
Expand All @@ -29,14 +30,13 @@ func (stg *Add) GetDependencies(ctx context.Context, c stage.Conveyor, cb contai
}

args = append(args, "Instruction", stg.instruction.Data.Name())
args = append(args, "Raw", stg.instruction.Data.Raw)
args = append(args, append([]string{"Src"}, stg.instruction.Data.Src...)...)
args = append(args, "Dst", stg.instruction.Data.Dst)
args = append(args, append([]string{"Sources"}, stg.instruction.Data.Sources()...)...)
args = append(args, "Dest", stg.instruction.Data.Dest())
args = append(args, "Chown", stg.instruction.Data.Chown)
args = append(args, "Chmod", stg.instruction.Data.Chmod)

var fileGlobSrc []string
for _, src := range stg.instruction.Data.Src {
for _, src := range stg.instruction.Data.Sources() {
if !strings.HasPrefix(src, "http://") && !strings.HasPrefix(src, "https://") {
fileGlobSrc = append(fileGlobSrc, src)
}
Expand All @@ -46,7 +46,7 @@ func (stg *Add) GetDependencies(ctx context.Context, c stage.Conveyor, cb contai
if srcChecksum, err := buildContextArchive.CalculateGlobsChecksum(ctx, fileGlobSrc, true); err != nil {
return "", fmt.Errorf("unable to calculate build context globs checksum: %w", err)
} else {
args = append(args, "SrcChecksum", srcChecksum)
args = append(args, "SourcesChecksum", srcChecksum)
}
}

Expand Down
56 changes: 37 additions & 19 deletions pkg/build/stage/instruction/add_test.go
Expand Up @@ -4,11 +4,11 @@ import (
"context"
"fmt"

"github.com/moby/buildkit/frontend/dockerfile/instructions"
. "github.com/onsi/gomega"

"github.com/werf/werf/pkg/build/stage"
"github.com/werf/werf/pkg/dockerfile"
dockerfile_instruction "github.com/werf/werf/pkg/dockerfile/instruction"
)

var _ = DescribeTable("ADD digest",
Expand All @@ -25,14 +25,17 @@ var _ = DescribeTable("ADD digest",
},

Entry("ADD basic", NewTestData(
NewAdd("ADD", dockerfile.NewDockerfileStageInstruction(
dockerfile_instruction.NewAdd("", []string{"src"}, "/app", "1000:1000", "")), nil, false,
NewAdd("ADD",
dockerfile.NewDockerfileStageInstruction(
&instructions.AddCommand{SourcesAndDest: []string{"src", "/app"}, Chown: "1000:1000", Chmod: ""},
),
nil, false,
&stage.BaseStageOptions{
ImageName: "example-image",
ProjectName: "example-project",
},
),
"febdd3676850b1b28161dc2a518495ba8e413b1aab3f28c7121c44c9da7d1212",
"88c31da85ac26ae35d29462c6dc309c2a02997c0de92b4ccee7db2e41be17187",
TestDataOptions{
Files: []*FileData{
{Name: "src/main/java/worker/Worker.java", Data: []byte(`package worker;`)},
Expand All @@ -42,14 +45,17 @@ var _ = DescribeTable("ADD digest",
)),

Entry("ADD with changed chown", NewTestData(
NewAdd("ADD", dockerfile.NewDockerfileStageInstruction(
dockerfile_instruction.NewAdd("", []string{"src"}, "/app", "1000:1001", "")), nil, false,
NewAdd("ADD",
dockerfile.NewDockerfileStageInstruction(
&instructions.AddCommand{SourcesAndDest: []string{"src", "/app"}, Chown: "1000:1001", Chmod: ""},
),
nil, false,
&stage.BaseStageOptions{
ImageName: "example-image",
ProjectName: "example-project",
},
),
"7f2ce5be335c61b5117446a3e508af27af1217bab68319a690f0f8d4653bed21",
"846ef29e994224dd84bf0a5de47b0b3255c8681b8178e8da5611b21547cd182b",
TestDataOptions{
Files: []*FileData{
{Name: "src/main/java/worker/Worker.java", Data: []byte(`package worker;`)},
Expand All @@ -60,14 +66,17 @@ var _ = DescribeTable("ADD digest",
)),

Entry("ADD with changed chmod", NewTestData(
NewAdd("ADD", dockerfile.NewDockerfileStageInstruction(
dockerfile_instruction.NewAdd("", []string{"src"}, "/app", "1000:1001", "0777")), nil, false,
NewAdd("ADD",
dockerfile.NewDockerfileStageInstruction(
&instructions.AddCommand{SourcesAndDest: []string{"src", "/app"}, Chown: "1000:1001", Chmod: "0777"},
),
nil, false,
&stage.BaseStageOptions{
ImageName: "example-image",
ProjectName: "example-project",
},
),
"f37bc012a10364919e30f5c6ac1ed9de8d5d32590ecb57564c449d1261439488",
"cef21e87710631a08edeb176a9487f81ae20171c22ec4537a3dc8fbc67aca868",
TestDataOptions{
Files: []*FileData{
{Name: "src/main/java/worker/Worker.java", Data: []byte(`package worker;`)},
Expand All @@ -78,14 +87,17 @@ var _ = DescribeTable("ADD digest",
)),

Entry("ADD with changed sources paths", NewTestData(
NewAdd("ADD", dockerfile.NewDockerfileStageInstruction(
dockerfile_instruction.NewAdd("", []string{"src", "pom.xml"}, "/app", "1000:1000", "0777")), nil, false,
NewAdd("ADD",
dockerfile.NewDockerfileStageInstruction(
&instructions.AddCommand{SourcesAndDest: []string{"src", "pom.xml", "/app"}, Chown: "1000:1001", Chmod: "0777"},
),
nil, false,
&stage.BaseStageOptions{
ImageName: "example-image",
ProjectName: "example-project",
},
),
"4a66595bf3f692d892cc1f5132a21939f681b5e38c59831b0359ba69889f1392",
"97f3f8a240902d73ec9a209f6c8368047b56d9247bdf9da88a40ac5dba925209",
TestDataOptions{
Files: []*FileData{
{Name: "src/main/java/worker/Worker.java", Data: []byte(`package worker;`)},
Expand All @@ -96,14 +108,17 @@ var _ = DescribeTable("ADD digest",
)),

Entry("ADD with changed source files", NewTestData(
NewAdd("ADD", dockerfile.NewDockerfileStageInstruction(
dockerfile_instruction.NewAdd("", []string{"src", "pom.xml"}, "/app", "1000:1000", "0777")), nil, false,
NewAdd("ADD",
dockerfile.NewDockerfileStageInstruction(
&instructions.AddCommand{SourcesAndDest: []string{"src", "pom.xml", "/app"}, Chown: "1000:1001", Chmod: "0777"},
),
nil, false,
&stage.BaseStageOptions{
ImageName: "example-image",
ProjectName: "example-project",
},
),
"c52c2a9ff2aa7054ab1f5c57717775c4e00a3b80d618b8a2aacefeb48b582ac0",
"60178e0b174bd1bce1cd29f8132ea84cc7212773b6fce9fad3ddff842d5cf2e0",
TestDataOptions{
Files: []*FileData{
{Name: "src/main/java/worker/Worker.java", Data: []byte(`package worker2;`)},
Expand All @@ -114,14 +129,17 @@ var _ = DescribeTable("ADD digest",
)),

Entry("ADD with changed destination path", NewTestData(
NewAdd("ADD", dockerfile.NewDockerfileStageInstruction(
dockerfile_instruction.NewAdd("", []string{"src", "pom.xml"}, "/app2", "1000:1000", "0777")), nil, false,
NewAdd("ADD",
dockerfile.NewDockerfileStageInstruction(
&instructions.AddCommand{SourcesAndDest: []string{"src", "pom.xml", "/app2"}, Chown: "1000:1001", Chmod: "0777"},
),
nil, false,
&stage.BaseStageOptions{
ImageName: "example-image",
ProjectName: "example-project",
},
),
"a067cbedb63b837bc9583487b27ad2f5dcc9d744df03414b9b1436e90e8c514e",
"c1f03d5701951fe9c5836957c753c9486f22e14b2d9291780ae70f288e531e1c",
TestDataOptions{
Files: []*FileData{
{Name: "src/main/java/worker/Worker.java", Data: []byte(`package worker2;`)},
Expand Down
11 changes: 6 additions & 5 deletions pkg/build/stage/instruction/cmd.go
Expand Up @@ -4,21 +4,22 @@ import (
"context"
"fmt"

"github.com/moby/buildkit/frontend/dockerfile/instructions"

"github.com/werf/werf/pkg/build/stage"
"github.com/werf/werf/pkg/config"
"github.com/werf/werf/pkg/container_backend"
backend_instruction "github.com/werf/werf/pkg/container_backend/instruction"
"github.com/werf/werf/pkg/dockerfile"
dockerfile_instruction "github.com/werf/werf/pkg/dockerfile/instruction"
"github.com/werf/werf/pkg/util"
)

type Cmd struct {
*Base[*dockerfile_instruction.Cmd, *backend_instruction.Cmd]
*Base[*instructions.CmdCommand, *backend_instruction.Cmd]
}

func NewCmd(name stage.StageName, i *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Cmd], dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *Cmd {
return &Cmd{Base: NewBase(name, i, backend_instruction.NewCmd(*i.Data), dependencies, hasPrevStage, opts)}
func NewCmd(name stage.StageName, i *dockerfile.DockerfileStageInstruction[*instructions.CmdCommand], dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *Cmd {
return &Cmd{Base: NewBase(name, i, backend_instruction.NewCmd(i.Data), dependencies, hasPrevStage, opts)}
}

func (stg *Cmd) GetDependencies(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevImage, prevBuiltImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) (string, error) {
Expand All @@ -28,7 +29,7 @@ func (stg *Cmd) GetDependencies(ctx context.Context, c stage.Conveyor, cb contai
}

args = append(args, "Instruction", stg.instruction.Data.Name())
args = append(args, append([]string{"Cmd"}, stg.instruction.Data.Cmd...)...)
args = append(args, append([]string{"Cmd"}, stg.instruction.Data.CmdLine...)...)
args = append(args, "PrependShell", fmt.Sprintf("%v", stg.instruction.Data.PrependShell))

return util.Sha256Hash(args...), nil
Expand Down

0 comments on commit e138887

Please sign in to comment.