From 306ed6c10696a2746cf7b14143a5dd4edf07a0c0 Mon Sep 17 00:00:00 2001 From: Timofey Kirillov Date: Wed, 19 Oct 2022 19:33:02 +0300 Subject: [PATCH] feat(staged-dockerfile): basic support of all dockerfile stages at conveyor level Signed-off-by: Timofey Kirillov --- pkg/build/image/dockerfile.go | 52 ++++++++++++++++++---- pkg/build/stage/instruction/add.go | 35 +++++++++++++++ pkg/build/stage/instruction/base.go | 15 +++++-- pkg/build/stage/instruction/cmd.go | 34 ++++++++++++++ pkg/build/stage/instruction/copy.go | 36 +++++++++++++++ pkg/build/stage/instruction/entrypoint.go | 34 ++++++++++++++ pkg/build/stage/instruction/env.go | 35 +++++++++++++++ pkg/build/stage/instruction/expose.go | 32 +++++++++++++ pkg/build/stage/instruction/healthcheck.go | 38 ++++++++++++++++ pkg/build/stage/instruction/label.go | 35 +++++++++++++++ pkg/build/stage/instruction/maintainer.go | 32 +++++++++++++ pkg/build/stage/instruction/on_build.go | 32 +++++++++++++ pkg/build/stage/instruction/run.go | 4 +- pkg/build/stage/instruction/shell.go | 32 +++++++++++++ pkg/build/stage/instruction/stop_signal.go | 32 +++++++++++++ pkg/build/stage/instruction/user.go | 32 +++++++++++++ pkg/build/stage/instruction/volume.go | 32 +++++++++++++ pkg/build/stage/instruction/workdir.go | 32 +++++++++++++ 18 files changed, 559 insertions(+), 15 deletions(-) create mode 100644 pkg/build/stage/instruction/add.go create mode 100644 pkg/build/stage/instruction/cmd.go create mode 100644 pkg/build/stage/instruction/copy.go create mode 100644 pkg/build/stage/instruction/entrypoint.go create mode 100644 pkg/build/stage/instruction/env.go create mode 100644 pkg/build/stage/instruction/expose.go create mode 100644 pkg/build/stage/instruction/healthcheck.go create mode 100644 pkg/build/stage/instruction/label.go create mode 100644 pkg/build/stage/instruction/maintainer.go create mode 100644 pkg/build/stage/instruction/on_build.go create mode 100644 pkg/build/stage/instruction/shell.go create mode 100644 pkg/build/stage/instruction/stop_signal.go create mode 100644 pkg/build/stage/instruction/user.go create mode 100644 pkg/build/stage/instruction/volume.go create mode 100644 pkg/build/stage/instruction/workdir.go diff --git a/pkg/build/image/dockerfile.go b/pkg/build/image/dockerfile.go index 0ed6484d0e..66c773c22b 100644 --- a/pkg/build/image/dockerfile.go +++ b/pkg/build/image/dockerfile.go @@ -118,21 +118,55 @@ func mapDockerfileToImagesSets(ctx context.Context, cfg *dockerfile.Dockerfile, } for ind, instr := range stg.Instructions { + stageName := stage.StageName(fmt.Sprintf("%d-%s", ind, instr.GetInstructionData().Name())) + isFirstStage := (len(img.stages) == 0) + baseStageOptions := &stage.BaseStageOptions{ + ImageName: img.Name, + ImageTmpDir: img.TmpDir, + ContainerWerfDir: img.ContainerWerfDir, + ProjectName: opts.ProjectName, + } + + var stg stage.Interface switch typedInstr := any(instr).(type) { + case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Add]: + stg = stage_instruction.NewAdd(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions) + case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Cmd]: + stg = stage_instruction.NewCmd(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions) + case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Copy]: + stg = stage_instruction.NewCopy(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions) + case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Entrypoint]: + stg = stage_instruction.NewEntrypoint(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions) + case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Env]: + stg = stage_instruction.NewEnv(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions) + case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Expose]: + stg = stage_instruction.NewExpose(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions) + case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Healthcheck]: + stg = stage_instruction.NewHealthcheck(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions) + case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Label]: + stg = stage_instruction.NewLabel(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions) + case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Maintainer]: + stg = stage_instruction.NewMaintainer(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions) + case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.OnBuild]: + stg = stage_instruction.NewOnBuild(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions) case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Run]: - isFirstStage := (len(img.stages) == 0) - - img.stages = append(img.stages, stage_instruction.NewRun(stage.StageName(fmt.Sprintf("%d-%s", ind, typedInstr.Data.Name())), typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, &stage.BaseStageOptions{ - ImageName: img.Name, - ImageTmpDir: img.TmpDir, - ContainerWerfDir: img.ContainerWerfDir, - ProjectName: opts.ProjectName, - })) - + stg = stage_instruction.NewRun(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions) + case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Shell]: + stg = stage_instruction.NewShell(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions) + case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.StopSignal]: + stg = stage_instruction.NewStopSignal(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions) + case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.User]: + stg = stage_instruction.NewUser(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions) + case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Volume]: + stg = stage_instruction.NewVolume(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions) + case *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Workdir]: + stg = stage_instruction.NewWorkdir(stageName, typedInstr, dockerfileImageConfig.Dependencies, !isFirstStage, baseStageOptions) default: panic(fmt.Sprintf("unsupported instruction type %#v", instr)) } + img.stages = append(img.stages, stg) + for _, dep := range instr.GetDependenciesByStageRef() { appendQueue(dep, item.Level+1) } diff --git a/pkg/build/stage/instruction/add.go b/pkg/build/stage/instruction/add.go new file mode 100644 index 0000000000..9053852fb6 --- /dev/null +++ b/pkg/build/stage/instruction/add.go @@ -0,0 +1,35 @@ +package instruction + +import ( + "context" + + "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] +} + +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, dependencies, hasPrevStage, opts)} +} + +func (stage *Add) GetDependencies(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevImage, prevBuiltImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) (string, error) { + var args []string + args = append(args, stage.instruction.Data.Name()) + args = append(args, stage.instruction.Data.Src...) + args = append(args, stage.instruction.Data.Dst) + args = append(args, stage.instruction.Data.Chown) + args = append(args, stage.instruction.Data.Chmod) + return util.Sha256Hash(args...), nil +} + +func (stage *Add) PrepareImage(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevBuiltImage, stageImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) error { + return stage.Base.prepareInstruction(ctx, stageImage, buildContextArchive, backend_instruction.NewAdd(*stage.instruction.Data)) +} diff --git a/pkg/build/stage/instruction/base.go b/pkg/build/stage/instruction/base.go index 491ef40c5b..2918bf3eb8 100644 --- a/pkg/build/stage/instruction/base.go +++ b/pkg/build/stage/instruction/base.go @@ -1,8 +1,11 @@ package instruction import ( + "context" + "github.com/werf/werf/pkg/build/stage" "github.com/werf/werf/pkg/config" + "github.com/werf/werf/pkg/container_backend" "github.com/werf/werf/pkg/dockerfile" ) @@ -23,10 +26,16 @@ func NewBase[T dockerfile.InstructionDataInterface](name stage.StageName, instru } } -func (stage *Base[T]) HasPrevStage() bool { - return stage.hasPrevStage +func (stg *Base[T]) HasPrevStage() bool { + return stg.hasPrevStage } -func (s *Base[T]) IsStapelStage() bool { +func (stg *Base[T]) IsStapelStage() bool { return false } + +func (stg *Base[T]) prepareInstruction(ctx context.Context, stageImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver, backendInstruction container_backend.InstructionInterface) error { + stageImage.Builder.DockerfileStageBuilder().SetBuildContextArchive(buildContextArchive) // FIXME(staged-dockerfile): set context at build-phase level + stageImage.Builder.DockerfileStageBuilder().AppendInstruction(backendInstruction) + return nil +} diff --git a/pkg/build/stage/instruction/cmd.go b/pkg/build/stage/instruction/cmd.go new file mode 100644 index 0000000000..1ef71c00a9 --- /dev/null +++ b/pkg/build/stage/instruction/cmd.go @@ -0,0 +1,34 @@ +package instruction + +import ( + "context" + "fmt" + + "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] +} + +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, dependencies, hasPrevStage, opts)} +} + +func (stage *Cmd) GetDependencies(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevImage, prevBuiltImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) (string, error) { + var args []string + args = append(args, stage.instruction.Data.Name()) + args = append(args, stage.instruction.Data.Cmd...) + args = append(args, fmt.Sprintf("%v", stage.instruction.Data.PrependShell)) + return util.Sha256Hash(args...), nil +} + +func (stage *Cmd) PrepareImage(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevBuiltImage, stageImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) error { + return stage.Base.prepareInstruction(ctx, stageImage, buildContextArchive, backend_instruction.NewCmd(*stage.instruction.Data)) +} diff --git a/pkg/build/stage/instruction/copy.go b/pkg/build/stage/instruction/copy.go new file mode 100644 index 0000000000..50f3aa9420 --- /dev/null +++ b/pkg/build/stage/instruction/copy.go @@ -0,0 +1,36 @@ +package instruction + +import ( + "context" + + "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 Copy struct { + *Base[*dockerfile_instruction.Copy] +} + +func NewCopy(name stage.StageName, i *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Copy], dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *Copy { + return &Copy{Base: NewBase(name, i, dependencies, hasPrevStage, opts)} +} + +func (stage *Copy) GetDependencies(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevImage, prevBuiltImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) (string, error) { + var args []string + args = append(args, stage.instruction.Data.Name()) + args = append(args, stage.instruction.Data.From) + args = append(args, stage.instruction.Data.Src...) + args = append(args, stage.instruction.Data.Dst) + args = append(args, stage.instruction.Data.Chown) + args = append(args, stage.instruction.Data.Chmod) + return util.Sha256Hash(args...), nil +} + +func (stage *Copy) PrepareImage(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevBuiltImage, stageImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) error { + return stage.Base.prepareInstruction(ctx, stageImage, buildContextArchive, backend_instruction.NewCopy(*stage.instruction.Data)) +} diff --git a/pkg/build/stage/instruction/entrypoint.go b/pkg/build/stage/instruction/entrypoint.go new file mode 100644 index 0000000000..9202cac65c --- /dev/null +++ b/pkg/build/stage/instruction/entrypoint.go @@ -0,0 +1,34 @@ +package instruction + +import ( + "context" + "fmt" + + "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 Entrypoint struct { + *Base[*dockerfile_instruction.Entrypoint] +} + +func NewEntrypoint(name stage.StageName, i *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Entrypoint], dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *Entrypoint { + return &Entrypoint{Base: NewBase(name, i, dependencies, hasPrevStage, opts)} +} + +func (stage *Entrypoint) GetDependencies(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevImage, prevBuiltImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) (string, error) { + var args []string + args = append(args, stage.instruction.Data.Name()) + args = append(args, stage.instruction.Data.Entrypoint...) + args = append(args, fmt.Sprintf("%v", stage.instruction.Data.PrependShell)) + return util.Sha256Hash(args...), nil +} + +func (stage *Entrypoint) PrepareImage(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevBuiltImage, stageImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) error { + return stage.Base.prepareInstruction(ctx, stageImage, buildContextArchive, backend_instruction.NewEntrypoint(*stage.instruction.Data)) +} diff --git a/pkg/build/stage/instruction/env.go b/pkg/build/stage/instruction/env.go new file mode 100644 index 0000000000..08efdecd0b --- /dev/null +++ b/pkg/build/stage/instruction/env.go @@ -0,0 +1,35 @@ +package instruction + +import ( + "context" + + "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 Env struct { + *Base[*dockerfile_instruction.Env] +} + +func NewEnv(name stage.StageName, i *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Env], dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *Env { + return &Env{Base: NewBase(name, i, dependencies, hasPrevStage, opts)} +} + +func (stage *Env) GetDependencies(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevImage, prevBuiltImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) (string, error) { + var args []string + args = append(args, stage.instruction.Data.Name()) + // FIXME(staged-dockerfile): sort envs + for k, v := range stage.instruction.Data.Envs { + args = append(args, k, v) + } + return util.Sha256Hash(args...), nil +} + +func (stage *Env) PrepareImage(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevBuiltImage, stageImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) error { + return stage.Base.prepareInstruction(ctx, stageImage, buildContextArchive, backend_instruction.NewEnv(*stage.instruction.Data)) +} diff --git a/pkg/build/stage/instruction/expose.go b/pkg/build/stage/instruction/expose.go new file mode 100644 index 0000000000..711e096e1c --- /dev/null +++ b/pkg/build/stage/instruction/expose.go @@ -0,0 +1,32 @@ +package instruction + +import ( + "context" + + "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 Expose struct { + *Base[*dockerfile_instruction.Expose] +} + +func NewExpose(name stage.StageName, i *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Expose], dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *Expose { + return &Expose{Base: NewBase(name, i, dependencies, hasPrevStage, opts)} +} + +func (stage *Expose) GetDependencies(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevImage, prevBuiltImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) (string, error) { + var args []string + args = append(args, stage.instruction.Data.Name()) + args = append(args, stage.instruction.Data.Ports...) + return util.Sha256Hash(args...), nil +} + +func (stage *Expose) PrepareImage(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevBuiltImage, stageImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) error { + return stage.Base.prepareInstruction(ctx, stageImage, buildContextArchive, backend_instruction.NewExpose(*stage.instruction.Data)) +} diff --git a/pkg/build/stage/instruction/healthcheck.go b/pkg/build/stage/instruction/healthcheck.go new file mode 100644 index 0000000000..4be6e414d7 --- /dev/null +++ b/pkg/build/stage/instruction/healthcheck.go @@ -0,0 +1,38 @@ +package instruction + +import ( + "context" + "fmt" + + "github.com/werf/werf/pkg/build/stage" + "github.com/werf/werf/pkg/config" + "github.com/werf/werf/pkg/container_backend" + "github.com/werf/werf/pkg/dockerfile" + dockerfile_instruction "github.com/werf/werf/pkg/dockerfile/instruction" + "github.com/werf/werf/pkg/util" +) + +type Healthcheck struct { + *Base[*dockerfile_instruction.Healthcheck] +} + +func NewHealthcheck(name stage.StageName, i *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Healthcheck], dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *Healthcheck { + return &Healthcheck{Base: NewBase(name, i, dependencies, hasPrevStage, opts)} +} + +func (stage *Healthcheck) GetDependencies(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevImage, prevBuiltImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) (string, error) { + var args []string + args = append(args, stage.instruction.Data.Name()) + args = append(args, string(stage.instruction.Data.Type)) + args = append(args, stage.instruction.Data.Config.Test...) + args = append(args, stage.instruction.Data.Config.Interval.String()) + args = append(args, stage.instruction.Data.Config.Timeout.String()) + args = append(args, stage.instruction.Data.Config.StartPeriod.String()) + args = append(args, fmt.Sprintf("%d", stage.instruction.Data.Config.Retries)) + return util.Sha256Hash(args...), nil +} + +func (stage *Healthcheck) PrepareImage(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevBuiltImage, stageImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) error { + // FIXME(staged-dockerfile): construct backend instruction + return stage.Base.prepareInstruction(ctx, stageImage, buildContextArchive, nil) +} diff --git a/pkg/build/stage/instruction/label.go b/pkg/build/stage/instruction/label.go new file mode 100644 index 0000000000..3ed947ef93 --- /dev/null +++ b/pkg/build/stage/instruction/label.go @@ -0,0 +1,35 @@ +package instruction + +import ( + "context" + + "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 Label struct { + *Base[*dockerfile_instruction.Label] +} + +func NewLabel(name stage.StageName, i *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Label], dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *Label { + return &Label{Base: NewBase(name, i, dependencies, hasPrevStage, opts)} +} + +func (stage *Label) GetDependencies(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevImage, prevBuiltImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) (string, error) { + var args []string + args = append(args, stage.instruction.Data.Name()) + // FIXME(staged-dockerfile): sort labels map + for k, v := range stage.instruction.Data.Labels { + args = append(args, k, v) + } + return util.Sha256Hash(args...), nil +} + +func (stage *Label) PrepareImage(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevBuiltImage, stageImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) error { + return stage.Base.prepareInstruction(ctx, stageImage, buildContextArchive, backend_instruction.NewLabel(*stage.instruction.Data)) +} diff --git a/pkg/build/stage/instruction/maintainer.go b/pkg/build/stage/instruction/maintainer.go new file mode 100644 index 0000000000..13e052fe8e --- /dev/null +++ b/pkg/build/stage/instruction/maintainer.go @@ -0,0 +1,32 @@ +package instruction + +import ( + "context" + + "github.com/werf/werf/pkg/build/stage" + "github.com/werf/werf/pkg/config" + "github.com/werf/werf/pkg/container_backend" + "github.com/werf/werf/pkg/dockerfile" + dockerfile_instruction "github.com/werf/werf/pkg/dockerfile/instruction" + "github.com/werf/werf/pkg/util" +) + +type Maintainer struct { + *Base[*dockerfile_instruction.Maintainer] +} + +func NewMaintainer(name stage.StageName, i *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Maintainer], dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *Maintainer { + return &Maintainer{Base: NewBase(name, i, dependencies, hasPrevStage, opts)} +} + +func (stage *Maintainer) GetDependencies(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevImage, prevBuiltImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) (string, error) { + var args []string + args = append(args, stage.instruction.Data.Name()) + args = append(args, stage.instruction.Data.Maintainer) + return util.Sha256Hash(args...), nil +} + +func (stage *Maintainer) PrepareImage(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevBuiltImage, stageImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) error { + // FIXME(staged-dockerfile): no Maintainer instruction + return stage.Base.prepareInstruction(ctx, stageImage, buildContextArchive, nil) +} diff --git a/pkg/build/stage/instruction/on_build.go b/pkg/build/stage/instruction/on_build.go new file mode 100644 index 0000000000..657e2d32c0 --- /dev/null +++ b/pkg/build/stage/instruction/on_build.go @@ -0,0 +1,32 @@ +package instruction + +import ( + "context" + + "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 OnBuild struct { + *Base[*dockerfile_instruction.OnBuild] +} + +func NewOnBuild(name stage.StageName, i *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.OnBuild], dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *OnBuild { + return &OnBuild{Base: NewBase(name, i, dependencies, hasPrevStage, opts)} +} + +func (stage *OnBuild) GetDependencies(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevImage, prevBuiltImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) (string, error) { + var args []string + args = append(args, stage.instruction.Data.Name()) + args = append(args, stage.instruction.Data.Instruction) + return util.Sha256Hash(args...), nil +} + +func (stage *OnBuild) PrepareImage(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevBuiltImage, stageImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) error { + return stage.Base.prepareInstruction(ctx, stageImage, buildContextArchive, backend_instruction.NewOnBuild(*stage.instruction.Data)) +} diff --git a/pkg/build/stage/instruction/run.go b/pkg/build/stage/instruction/run.go index 9b175cd6cb..3b2d5e7ca3 100644 --- a/pkg/build/stage/instruction/run.go +++ b/pkg/build/stage/instruction/run.go @@ -25,7 +25,5 @@ func (stage *Run) GetDependencies(ctx context.Context, c stage.Conveyor, cb cont } func (stage *Run) PrepareImage(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevBuiltImage, stageImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) error { - stageImage.Builder.DockerfileStageBuilder().SetBuildContextArchive(buildContextArchive) - stageImage.Builder.DockerfileStageBuilder().AppendInstruction(backend_instruction.NewRun(*stage.instruction.Data)) - return nil + return stage.prepareInstruction(ctx, stageImage, buildContextArchive, backend_instruction.NewRun(*stage.instruction.Data)) } diff --git a/pkg/build/stage/instruction/shell.go b/pkg/build/stage/instruction/shell.go new file mode 100644 index 0000000000..a56e505362 --- /dev/null +++ b/pkg/build/stage/instruction/shell.go @@ -0,0 +1,32 @@ +package instruction + +import ( + "context" + + "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 Shell struct { + *Base[*dockerfile_instruction.Shell] +} + +func NewShell(name stage.StageName, i *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Shell], dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *Shell { + return &Shell{Base: NewBase(name, i, dependencies, hasPrevStage, opts)} +} + +func (stage *Shell) GetDependencies(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevImage, prevBuiltImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) (string, error) { + var args []string + args = append(args, stage.instruction.Data.Name()) + args = append(args, stage.instruction.Data.Shell...) + return util.Sha256Hash(args...), nil +} + +func (stage *Shell) PrepareImage(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevBuiltImage, stageImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) error { + return stage.Base.prepareInstruction(ctx, stageImage, buildContextArchive, backend_instruction.NewShell(*stage.instruction.Data)) +} diff --git a/pkg/build/stage/instruction/stop_signal.go b/pkg/build/stage/instruction/stop_signal.go new file mode 100644 index 0000000000..7ccc49362e --- /dev/null +++ b/pkg/build/stage/instruction/stop_signal.go @@ -0,0 +1,32 @@ +package instruction + +import ( + "context" + + "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 StopSignal struct { + *Base[*dockerfile_instruction.StopSignal] +} + +func NewStopSignal(name stage.StageName, i *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.StopSignal], dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *StopSignal { + return &StopSignal{Base: NewBase(name, i, dependencies, hasPrevStage, opts)} +} + +func (stage *StopSignal) GetDependencies(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevImage, prevBuiltImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) (string, error) { + var args []string + args = append(args, stage.instruction.Data.Name()) + args = append(args, stage.instruction.Data.Signal) + return util.Sha256Hash(args...), nil +} + +func (stage *StopSignal) PrepareImage(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevBuiltImage, stageImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) error { + return stage.Base.prepareInstruction(ctx, stageImage, buildContextArchive, backend_instruction.NewStopSignal(*stage.instruction.Data)) +} diff --git a/pkg/build/stage/instruction/user.go b/pkg/build/stage/instruction/user.go new file mode 100644 index 0000000000..44da66448c --- /dev/null +++ b/pkg/build/stage/instruction/user.go @@ -0,0 +1,32 @@ +package instruction + +import ( + "context" + + "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 User struct { + *Base[*dockerfile_instruction.User] +} + +func NewUser(name stage.StageName, i *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.User], dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *User { + return &User{Base: NewBase(name, i, dependencies, hasPrevStage, opts)} +} + +func (stage *User) GetDependencies(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevImage, prevBuiltImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) (string, error) { + var args []string + args = append(args, stage.instruction.Data.Name()) + args = append(args, stage.instruction.Data.User) + return util.Sha256Hash(args...), nil +} + +func (stage *User) PrepareImage(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevBuiltImage, stageImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) error { + return stage.Base.prepareInstruction(ctx, stageImage, buildContextArchive, backend_instruction.NewUser(*stage.instruction.Data)) +} diff --git a/pkg/build/stage/instruction/volume.go b/pkg/build/stage/instruction/volume.go new file mode 100644 index 0000000000..76a98379c5 --- /dev/null +++ b/pkg/build/stage/instruction/volume.go @@ -0,0 +1,32 @@ +package instruction + +import ( + "context" + + "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 Volume struct { + *Base[*dockerfile_instruction.Volume] +} + +func NewVolume(name stage.StageName, i *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Volume], dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *Volume { + return &Volume{Base: NewBase(name, i, dependencies, hasPrevStage, opts)} +} + +func (stage *Volume) GetDependencies(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevImage, prevBuiltImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) (string, error) { + var args []string + args = append(args, stage.instruction.Data.Name()) + args = append(args, stage.instruction.Data.Volumes...) + return util.Sha256Hash(args...), nil +} + +func (stage *Volume) PrepareImage(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevBuiltImage, stageImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) error { + return stage.Base.prepareInstruction(ctx, stageImage, buildContextArchive, backend_instruction.NewVolume(*stage.instruction.Data)) +} diff --git a/pkg/build/stage/instruction/workdir.go b/pkg/build/stage/instruction/workdir.go new file mode 100644 index 0000000000..a6215f28d3 --- /dev/null +++ b/pkg/build/stage/instruction/workdir.go @@ -0,0 +1,32 @@ +package instruction + +import ( + "context" + + "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 Workdir struct { + *Base[*dockerfile_instruction.Workdir] +} + +func NewWorkdir(name stage.StageName, i *dockerfile.DockerfileStageInstruction[*dockerfile_instruction.Workdir], dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *Workdir { + return &Workdir{Base: NewBase(name, i, dependencies, hasPrevStage, opts)} +} + +func (stage *Workdir) GetDependencies(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevImage, prevBuiltImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) (string, error) { + var args []string + args = append(args, stage.instruction.Data.Name()) + args = append(args, stage.instruction.Data.Workdir) + return util.Sha256Hash(args...), nil +} + +func (stage *Workdir) PrepareImage(ctx context.Context, c stage.Conveyor, cb container_backend.ContainerBackend, prevBuiltImage, stageImage *stage.StageImage, buildContextArchive container_backend.BuildContextArchiver) error { + return stage.Base.prepareInstruction(ctx, stageImage, buildContextArchive, backend_instruction.NewWorkdir(*stage.instruction.Data)) +}