From 7cc7d71ccc2ec03aa1f039610d7d7011d6b1e1f2 Mon Sep 17 00:00:00 2001 From: Timofey Kirillov Date: Tue, 29 Mar 2022 13:53:22 +0300 Subject: [PATCH] feat(stapel-to-buildah): implement 'from' stage * New stapel builder method introduced into ContainerRuntime, not fully implemented yet. * pkg/build/stage/from implemented using new stapel builder. * refactored all StageBuilder related implementations and moved to pkg/container_runtime/stage_builder. Signed-off-by: Timofey Kirillov --- cmd/werf/common/conveyor_options.go | 2 +- pkg/build/build_phase.go | 18 +-- pkg/build/builder/ansible.go | 27 ++-- pkg/build/builder/builder.go | 9 +- pkg/build/builder/shell.go | 27 ++-- pkg/build/builder/stage_builder.go | 123 ------------------ pkg/build/conveyor.go | 6 +- pkg/build/stage/base.go | 55 ++++---- pkg/build/stage/before_install.go | 2 +- pkg/build/stage/before_setup.go | 2 +- pkg/build/stage/conveyor.go | 3 + pkg/build/stage/data_test.go | 12 +- pkg/build/stage/dependencies.go | 14 +- pkg/build/stage/dependencies_test.go | 10 +- pkg/build/stage/docker_instructions.go | 10 +- pkg/build/stage/dockerfile.go | 12 +- pkg/build/stage/dockerfile_test.go | 10 +- pkg/build/stage/from.go | 49 ++++--- pkg/build/stage/git.go | 10 +- pkg/build/stage/git_archive.go | 13 +- pkg/build/stage/git_mapping.go | 10 +- pkg/build/stage/git_mapping_test.go | 2 +- pkg/build/stage/git_patch.go | 14 +- pkg/build/stage/install.go | 2 +- pkg/build/stage/setup.go | 2 +- pkg/build/stage/stage_image.go | 12 +- pkg/build/stage/stubs_test.go | 4 + pkg/container_runtime/buildah_runtime.go | 56 +++++++- .../docker_server_runtime.go | 8 +- .../dockerfile_image_builder.go | 93 ------------- pkg/container_runtime/image_interface.go | 5 +- pkg/container_runtime/interface.go | 21 ++- pkg/container_runtime/legacy_interface.go | 5 +- pkg/container_runtime/legacy_stage_image.go | 8 +- .../perf_check_container_runtime.go | 12 +- .../stage_builder/dockerfile_stage_builder.go | 110 ++++++++++++++++ .../legacy_stapel_stage_builder.go | 37 ++++++ .../stage_builder/stage_builder.go | 52 ++++++++ .../stage_builder/stapel_stage_builder.go | 80 ++++++++++++ pkg/container_runtime/utils.go | 2 +- pkg/storage/repo_stages_storage.go | 1 + 41 files changed, 573 insertions(+), 377 deletions(-) delete mode 100644 pkg/build/builder/stage_builder.go delete mode 100644 pkg/container_runtime/dockerfile_image_builder.go create mode 100644 pkg/container_runtime/stage_builder/dockerfile_stage_builder.go create mode 100644 pkg/container_runtime/stage_builder/legacy_stapel_stage_builder.go create mode 100644 pkg/container_runtime/stage_builder/stage_builder.go create mode 100644 pkg/container_runtime/stage_builder/stapel_stage_builder.go diff --git a/cmd/werf/common/conveyor_options.go b/cmd/werf/common/conveyor_options.go index 4d7ef06fc2..7f7cdb1a18 100644 --- a/cmd/werf/common/conveyor_options.go +++ b/cmd/werf/common/conveyor_options.go @@ -66,7 +66,7 @@ func GetBuildOptions(commonCmdData *CmdData, giterminismManager giterminism_mana buildOptions = build.BuildOptions{ SkipImageMetadataPublication: *commonCmdData.Dev, CustomTagFuncList: customTagFuncList, - ImageBuildOptions: container_runtime.LegacyBuildOptions{ + ImageBuildOptions: container_runtime.BuildOptions{ IntrospectAfterError: *commonCmdData.IntrospectAfterError, IntrospectBeforeError: *commonCmdData.IntrospectBeforeError, }, diff --git a/pkg/build/build_phase.go b/pkg/build/build_phase.go index ec27cc2392..451744e666 100644 --- a/pkg/build/build_phase.go +++ b/pkg/build/build_phase.go @@ -36,7 +36,7 @@ type BuildPhaseOptions struct { } type BuildOptions struct { - ImageBuildOptions container_runtime.LegacyBuildOptions + ImageBuildOptions container_runtime.BuildOptions IntrospectOptions ReportPath string @@ -628,10 +628,10 @@ func (phase *BuildPhase) prepareStageInstructions(ctx context.Context, img *Imag for key, value := range serviceLabels { labels = append(labels, fmt.Sprintf("%s=%v", key, value)) } - stageImage.StageBuilderAccessor.NativeDockerfileStageBuilder().AppendLabels(labels...) + stageImage.Builder.DockerfileStageBuilder().AppendLabels(labels...) phase.Conveyor.AppendOnTerminateFunc(func() error { - return stageImage.StageBuilderAccessor.NativeDockerfileStageBuilder().Cleanup(ctx) + return stageImage.Builder.DockerfileStageBuilder().Cleanup(ctx) }) default: @@ -675,7 +675,7 @@ func (phase *BuildPhase) prepareStageInstructions(ctx context.Context, img *Imag } func (phase *BuildPhase) buildStage(ctx context.Context, img *Image, stg stage.Interface) error { - if !img.isDockerfileImage { + if !img.isDockerfileImage && phase.Conveyor.UseLegacyStapelBuilder(phase.Conveyor.ContainerRuntime) { _, err := stapel.GetOrCreateContainer(ctx) if err != nil { return fmt.Errorf("get or create stapel container failed: %s", err) @@ -724,11 +724,13 @@ func (phase *BuildPhase) atomicBuildStageImage(ctx context.Context, img *Image, } if err := logboek.Context(ctx).Streams().DoErrorWithTag(fmt.Sprintf("%s/%s", img.LogName(), stg.Name()), img.LogTagStyle(), func() error { - switch stg.Name() { - case "dockerfile": - return stageImage.StageBuilderAccessor.NativeDockerfileStageBuilder().Build(ctx) + switch { + case stg.Name() == "dockerfile": + return stageImage.Builder.DockerfileStageBuilder().Build(ctx) + case phase.Conveyor.UseLegacyStapelBuilder(phase.Conveyor.ContainerRuntime): + return stageImage.Builder.LegacyStapelStageBuilder().Build(ctx, phase.ImageBuildOptions) default: - return stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Build(ctx, phase.ImageBuildOptions) + return stageImage.Builder.StapelStageBuilder().Build(ctx, phase.ImageBuildOptions) } }); err != nil { return fmt.Errorf("failed to build image for stage %s with digest %s: %s", stg.Name(), stg.GetDigest(), err) diff --git a/pkg/build/builder/ansible.go b/pkg/build/builder/ansible.go index 6cd445a173..a553959d4d 100644 --- a/pkg/build/builder/ansible.go +++ b/pkg/build/builder/ansible.go @@ -17,6 +17,7 @@ import ( "github.com/werf/logboek" "github.com/werf/werf/pkg/config" "github.com/werf/werf/pkg/container_runtime" + "github.com/werf/werf/pkg/container_runtime/stage_builder" "github.com/werf/werf/pkg/stapel" "github.com/werf/werf/pkg/util" ) @@ -44,20 +45,20 @@ func (b *Ansible) IsBeforeSetupEmpty(ctx context.Context) bool { } func (b *Ansible) IsSetupEmpty(ctx context.Context) bool { return b.isEmptyStage(ctx, "Setup") } -func (b *Ansible) BeforeInstall(ctx context.Context, cr container_runtime.ContainerRuntime, stageBuilder StageBuilderAccessorInterface) error { - return b.stage(ctx, cr, stageBuilder, "BeforeInstall") +func (b *Ansible) BeforeInstall(ctx context.Context, cr container_runtime.ContainerRuntime, stageBuilder stage_builder.StageBuilderInterface, useLegacyStapelBuilder bool) error { + return b.stage(ctx, cr, stageBuilder, useLegacyStapelBuilder, "BeforeInstall") } -func (b *Ansible) Install(ctx context.Context, cr container_runtime.ContainerRuntime, stageBuilder StageBuilderAccessorInterface) error { - return b.stage(ctx, cr, stageBuilder, "Install") +func (b *Ansible) Install(ctx context.Context, cr container_runtime.ContainerRuntime, stageBuilder stage_builder.StageBuilderInterface, useLegacyStapelBuilder bool) error { + return b.stage(ctx, cr, stageBuilder, useLegacyStapelBuilder, "Install") } -func (b *Ansible) BeforeSetup(ctx context.Context, cr container_runtime.ContainerRuntime, stageBuilder StageBuilderAccessorInterface) error { - return b.stage(ctx, cr, stageBuilder, "BeforeSetup") +func (b *Ansible) BeforeSetup(ctx context.Context, cr container_runtime.ContainerRuntime, stageBuilder stage_builder.StageBuilderInterface, useLegacyStapelBuilder bool) error { + return b.stage(ctx, cr, stageBuilder, useLegacyStapelBuilder, "BeforeSetup") } -func (b *Ansible) Setup(ctx context.Context, cr container_runtime.ContainerRuntime, stageBuilder StageBuilderAccessorInterface) error { - return b.stage(ctx, cr, stageBuilder, "Setup") +func (b *Ansible) Setup(ctx context.Context, cr container_runtime.ContainerRuntime, stageBuilder stage_builder.StageBuilderInterface, useLegacyStapelBuilder bool) error { + return b.stage(ctx, cr, stageBuilder, useLegacyStapelBuilder, "Setup") } func (b *Ansible) BeforeInstallChecksum(ctx context.Context) string { @@ -73,11 +74,8 @@ func (b *Ansible) isEmptyStage(ctx context.Context, userStageName string) bool { return b.stageChecksum(ctx, userStageName) == "" } -func (b *Ansible) stage(ctx context.Context, cr container_runtime.ContainerRuntime, stageBuilder StageBuilderAccessorInterface, userStageName string) error { - if cr.HasContainerRootMountSupport() { - // TODO(stapel-to-buildah) - panic("not implemented") - } else { +func (b *Ansible) stage(ctx context.Context, cr container_runtime.ContainerRuntime, stageBuilder stage_builder.StageBuilderInterface, useLegacyStapelBuilder bool, userStageName string) error { + if useLegacyStapelBuilder { container := stageBuilder.LegacyStapelStageBuilder().BuilderContainer() if len(b.stageTasks(userStageName)) == 0 { @@ -136,6 +134,9 @@ func (b *Ansible) stage(ctx context.Context, cr container_runtime.ContainerRunti container.AddServiceRunCommands(command) return nil + } else { + // TODO(stapel-to-buildah) + panic("not implemented") } } diff --git a/pkg/build/builder/builder.go b/pkg/build/builder/builder.go index 327634b793..c08754a588 100644 --- a/pkg/build/builder/builder.go +++ b/pkg/build/builder/builder.go @@ -5,6 +5,7 @@ import ( "os" "github.com/werf/werf/pkg/container_runtime" + "github.com/werf/werf/pkg/container_runtime/stage_builder" ) type Builder interface { @@ -12,10 +13,10 @@ type Builder interface { IsInstallEmpty(ctx context.Context) bool IsBeforeSetupEmpty(ctx context.Context) bool IsSetupEmpty(ctx context.Context) bool - BeforeInstall(ctx context.Context, cr container_runtime.ContainerRuntime, stageBuilder StageBuilderAccessorInterface) error - Install(ctx context.Context, cr container_runtime.ContainerRuntime, stageBuilder StageBuilderAccessorInterface) error - BeforeSetup(ctx context.Context, cr container_runtime.ContainerRuntime, stageBuilder StageBuilderAccessorInterface) error - Setup(ctx context.Context, cr container_runtime.ContainerRuntime, stageBuilder StageBuilderAccessorInterface) error + BeforeInstall(ctx context.Context, cr container_runtime.ContainerRuntime, stageBuilder stage_builder.StageBuilderInterface, useLegacyStapelBuilder bool) error + Install(ctx context.Context, cr container_runtime.ContainerRuntime, stageBuilder stage_builder.StageBuilderInterface, useLegacyStapelBuilder bool) error + BeforeSetup(ctx context.Context, cr container_runtime.ContainerRuntime, stageBuilder stage_builder.StageBuilderInterface, useLegacyStapelBuilder bool) error + Setup(ctx context.Context, cr container_runtime.ContainerRuntime, stageBuilder stage_builder.StageBuilderInterface, useLegacyStapelBuilder bool) error BeforeInstallChecksum(ctx context.Context) string InstallChecksum(ctx context.Context) string BeforeSetupChecksum(ctx context.Context) string diff --git a/pkg/build/builder/shell.go b/pkg/build/builder/shell.go index 1712126ca9..f4ff4a0cb5 100644 --- a/pkg/build/builder/shell.go +++ b/pkg/build/builder/shell.go @@ -12,6 +12,7 @@ import ( "github.com/werf/logboek" "github.com/werf/werf/pkg/config" "github.com/werf/werf/pkg/container_runtime" + "github.com/werf/werf/pkg/container_runtime/stage_builder" "github.com/werf/werf/pkg/stapel" "github.com/werf/werf/pkg/util" ) @@ -36,20 +37,20 @@ func (b *Shell) IsBeforeSetupEmpty(ctx context.Context) bool { } func (b *Shell) IsSetupEmpty(ctx context.Context) bool { return b.isEmptyStage(ctx, "Setup") } -func (b *Shell) BeforeInstall(_ context.Context, cr container_runtime.ContainerRuntime, stageBuilder StageBuilderAccessorInterface) error { - return b.stage(cr, stageBuilder, "BeforeInstall") +func (b *Shell) BeforeInstall(_ context.Context, cr container_runtime.ContainerRuntime, stageBuilder stage_builder.StageBuilderInterface, useLegacyStapelBuilder bool) error { + return b.stage(cr, stageBuilder, useLegacyStapelBuilder, "BeforeInstall") } -func (b *Shell) Install(_ context.Context, cr container_runtime.ContainerRuntime, stageBuilder StageBuilderAccessorInterface) error { - return b.stage(cr, stageBuilder, "Install") +func (b *Shell) Install(_ context.Context, cr container_runtime.ContainerRuntime, stageBuilder stage_builder.StageBuilderInterface, useLegacyStapelBuilder bool) error { + return b.stage(cr, stageBuilder, useLegacyStapelBuilder, "Install") } -func (b *Shell) BeforeSetup(_ context.Context, cr container_runtime.ContainerRuntime, stageBuilder StageBuilderAccessorInterface) error { - return b.stage(cr, stageBuilder, "BeforeSetup") +func (b *Shell) BeforeSetup(_ context.Context, cr container_runtime.ContainerRuntime, stageBuilder stage_builder.StageBuilderInterface, useLegacyStapelBuilder bool) error { + return b.stage(cr, stageBuilder, useLegacyStapelBuilder, "BeforeSetup") } -func (b *Shell) Setup(_ context.Context, cr container_runtime.ContainerRuntime, stageBuilder StageBuilderAccessorInterface) error { - return b.stage(cr, stageBuilder, "Setup") +func (b *Shell) Setup(_ context.Context, cr container_runtime.ContainerRuntime, stageBuilder stage_builder.StageBuilderInterface, useLegacyStapelBuilder bool) error { + return b.stage(cr, stageBuilder, useLegacyStapelBuilder, "Setup") } func (b *Shell) BeforeInstallChecksum(ctx context.Context) string { @@ -65,11 +66,8 @@ func (b *Shell) isEmptyStage(ctx context.Context, userStageName string) bool { return b.stageChecksum(ctx, userStageName) == "" } -func (b *Shell) stage(cr container_runtime.ContainerRuntime, stageBuilder StageBuilderAccessorInterface, userStageName string) error { - if cr.HasContainerRootMountSupport() { - // TODO(stapel-to-buildah) - panic("not implemented") - } else { +func (b *Shell) stage(cr container_runtime.ContainerRuntime, stageBuilder stage_builder.StageBuilderInterface, useLegacyStapelBuilder bool, userStageName string) error { + if useLegacyStapelBuilder { container := stageBuilder.LegacyStapelStageBuilder().BuilderContainer() stageHostTmpDir, err := b.stageHostTmpDir(userStageName) @@ -91,6 +89,9 @@ func (b *Shell) stage(cr container_runtime.ContainerRuntime, stageBuilder StageB container.AddServiceRunCommands(containerTmpScriptFilePath) return nil + } else { + // TODO(stapel-to-buildah) + panic("not implemented") } } diff --git a/pkg/build/builder/stage_builder.go b/pkg/build/builder/stage_builder.go deleted file mode 100644 index 8c6c2fa0f0..0000000000 --- a/pkg/build/builder/stage_builder.go +++ /dev/null @@ -1,123 +0,0 @@ -package builder - -import ( - "context" - - "github.com/werf/werf/pkg/container_runtime" -) - -type StageBuilderAccessorInterface interface { - StapelStageBuilder() StapelStageBuilderInterface - NativeDockerfileStageBuilder() NativeDockerfileStageBuilderInterface - LegacyStapelStageBuilder() LegacyStapelStageBuilderInterface -} - -type StageBuilderAccessor struct { - ContainerRuntime container_runtime.ContainerRuntime - Image container_runtime.LegacyImageInterface - DockerfileImageBuilder *container_runtime.DockerfileImageBuilder -} - -func NewStageBuilderAccessor(containerRuntime container_runtime.ContainerRuntime, image container_runtime.LegacyImageInterface) *StageBuilderAccessor { - return &StageBuilderAccessor{ - ContainerRuntime: containerRuntime, - Image: image, - } -} - -func (accessor *StageBuilderAccessor) StapelStageBuilder() StapelStageBuilderInterface { - return NewStapelStageBuilder() -} - -func (accessor *StageBuilderAccessor) LegacyStapelStageBuilder() LegacyStapelStageBuilderInterface { - return NewLegacyStapelStageBuilder(accessor.ContainerRuntime, accessor.Image) -} - -func (accessor *StageBuilderAccessor) NativeDockerfileStageBuilder() NativeDockerfileStageBuilderInterface { - if accessor.DockerfileImageBuilder == nil { - accessor.DockerfileImageBuilder = container_runtime.NewDockerfileImageBuilder(accessor.ContainerRuntime, accessor.Image) - } - return accessor.DockerfileImageBuilder -} - -type StapelStageBuilderInterface interface { - AppendPrepareContainerAction(action PrepareContainerAction) StapelStageBuilderInterface - AddLabels(map[string]string) StapelStageBuilderInterface - AddContainerVolumes(volumes ...string) StapelStageBuilderInterface -} - -type PrepareContainerAction interface { - PrepareContainer(containerRoot string) error -} - -type stapelStageBuilder struct { - ContainerRuntime container_runtime.ContainerRuntime - - labels map[string]string - volumes []string -} - -func NewStapelStageBuilder() *stapelStageBuilder { - return &stapelStageBuilder{} -} - -func (builder *stapelStageBuilder) AddLabels(labels map[string]string) StapelStageBuilderInterface { - for k, v := range labels { - builder.labels[k] = v - } - return builder -} - -func (builder *stapelStageBuilder) AddContainerVolumes(volumes ...string) StapelStageBuilderInterface { - builder.volumes = append(builder.volumes, volumes...) - return builder -} - -func (builder *stapelStageBuilder) AppendPrepareContainerAction(action PrepareContainerAction) StapelStageBuilderInterface { - panic("FIXME") - return builder -} - -type NativeDockerfileStageBuilderInterface interface { - Build(ctx context.Context) error - Cleanup(ctx context.Context) error - SetDockerfile(dockerfile []byte) - SetDockerfileCtxRelPath(dockerfileCtxRelPath string) - SetTarget(target string) - AppendBuildArgs(args ...string) - AppendAddHost(addHost ...string) - SetNetwork(network string) - SetSSH(ssh string) - AppendLabels(labels ...string) - SetContextArchivePath(contextArchivePath string) -} - -type LegacyStapelStageBuilderInterface interface { - Container() container_runtime.LegacyContainer - BuilderContainer() container_runtime.LegacyBuilderContainer - Build(ctx context.Context, opts container_runtime.LegacyBuildOptions) error -} - -type legacyStapelStageBuilder struct { - ContainerRuntime container_runtime.ContainerRuntime - Image container_runtime.LegacyImageInterface -} - -func NewLegacyStapelStageBuilder(containerRuntime container_runtime.ContainerRuntime, image container_runtime.LegacyImageInterface) *legacyStapelStageBuilder { - return &legacyStapelStageBuilder{ - ContainerRuntime: containerRuntime, - Image: image, - } -} - -func (builder *legacyStapelStageBuilder) Container() container_runtime.LegacyContainer { - return builder.Image.Container() -} - -func (builder *legacyStapelStageBuilder) BuilderContainer() container_runtime.LegacyBuilderContainer { - return builder.Image.BuilderContainer() -} - -func (builder *legacyStapelStageBuilder) Build(ctx context.Context, opts container_runtime.LegacyBuildOptions) error { - return builder.Image.Build(ctx, opts) -} diff --git a/pkg/build/conveyor.go b/pkg/build/conveyor.go index ba771c7c8b..ffe8a8a417 100644 --- a/pkg/build/conveyor.go +++ b/pkg/build/conveyor.go @@ -125,6 +125,10 @@ func (c *Conveyor) getServiceRWMutex(service string) *sync.RWMutex { return rwMutex } +func (c *Conveyor) UseLegacyStapelBuilder(cr container_runtime.ContainerRuntime) bool { + return !cr.HasStapelBuildSupport() +} + func (c *Conveyor) IsBaseImagesRepoIdsCacheExist(key string) bool { c.getServiceRWMutex("BaseImagesRepoIdsCache").RLock() defer c.getServiceRWMutex("BaseImagesRepoIdsCache").RUnlock() @@ -688,7 +692,7 @@ func (c *Conveyor) GetOrCreateStageImage(fromImage *container_runtime.LegacyStag } i := container_runtime.NewLegacyStageImage(fromImage, name, c.ContainerRuntime) - img := stage.NewStageImage(c.ContainerRuntime, i) + img := stage.NewStageImage(c.ContainerRuntime, fromImage, i) c.SetStageImage(img) return img diff --git a/pkg/build/stage/base.go b/pkg/build/stage/base.go index 2a62c6af63..6aa6bee880 100644 --- a/pkg/build/stage/base.go +++ b/pkg/build/stage/base.go @@ -244,26 +244,26 @@ func (s *BaseStage) PrepareImage(ctx context.Context, c Conveyor, cr container_r * NOTE: Take into account when adding new base PrepareImage steps. */ - if cr.HasContainerRootMountSupport() { - // TODO(stapel-to-buildah) - panic("not implemented") + addLabels := map[string]string{imagePkg.WerfProjectRepoCommitLabel: c.GiterminismManager().HeadCommit()} + if c.UseLegacyStapelBuilder(cr) { + stageImage.Builder.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions().AddLabel(addLabels) } else { - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions().AddLabel(map[string]string{imagePkg.WerfProjectRepoCommitLabel: c.GiterminismManager().HeadCommit()}) - - serviceMounts := s.getServiceMounts(prevBuiltImage) - s.addServiceMountsLabels(serviceMounts, stageImage) - if err := s.addServiceMountsVolumes(serviceMounts, stageImage); err != nil { - return fmt.Errorf("error adding mounts volumes: %s", err) - } + stageImage.Builder.StapelStageBuilder().AddLabels(addLabels) + } - customMounts := s.getCustomMounts(prevBuiltImage) - s.addCustomMountLabels(customMounts, stageImage) - if err := s.addCustomMountVolumes(customMounts, stageImage); err != nil { - return fmt.Errorf("error adding mounts volumes: %s", err) - } + serviceMounts := s.getServiceMounts(prevBuiltImage) + s.addServiceMountsLabels(serviceMounts, c, cr, stageImage) + if err := s.addServiceMountsVolumes(serviceMounts, stageImage); err != nil { + return fmt.Errorf("error adding mounts volumes: %s", err) + } - return nil + customMounts := s.getCustomMounts(prevBuiltImage) + s.addCustomMountLabels(customMounts, c, cr, stageImage) + if err := s.addCustomMountVolumes(customMounts, stageImage); err != nil { + return fmt.Errorf("error adding mounts volumes: %s", err) } + + return nil } func (s *BaseStage) PreRunHook(_ context.Context, _ Conveyor) error { @@ -333,14 +333,14 @@ func (s *BaseStage) addServiceMountsVolumes(mountpointsByType map[string][]strin return fmt.Errorf("error creating tmp path %s for mount: %s", absoluteFrom, err) } - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().RunOptions().AddVolume(fmt.Sprintf("%s:%s", absoluteFrom, absoluteMountpoint)) + stageImage.Builder.LegacyStapelStageBuilder().Container().RunOptions().AddVolume(fmt.Sprintf("%s:%s", absoluteFrom, absoluteMountpoint)) } } return nil } -func (s *BaseStage) addServiceMountsLabels(mountpointsByType map[string][]string, stageImage *StageImage) { +func (s *BaseStage) addServiceMountsLabels(mountpointsByType map[string][]string, c Conveyor, cr container_runtime.ContainerRuntime, stageImage *StageImage) { for mountType, mountpoints := range mountpointsByType { var labelName string switch mountType { @@ -354,7 +354,12 @@ func (s *BaseStage) addServiceMountsLabels(mountpointsByType map[string][]string labelValue := strings.Join(mountpoints, ";") - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions().AddLabel(map[string]string{labelName: labelValue}) + addLabels := map[string]string{labelName: labelValue} + if c.UseLegacyStapelBuilder(cr) { + stageImage.Builder.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions().AddLabel(addLabels) + } else { + stageImage.Builder.StapelStageBuilder().AddLabels(addLabels) + } } } @@ -419,18 +424,24 @@ func (s *BaseStage) addCustomMountVolumes(mountpointsByFrom map[string][]string, for _, mountpoint := range mountpoints { absoluteMountpoint := path.Join("/", mountpoint) - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().RunOptions().AddVolume(fmt.Sprintf("%s:%s", absoluteFrom, absoluteMountpoint)) + stageImage.Builder.LegacyStapelStageBuilder().Container().RunOptions().AddVolume(fmt.Sprintf("%s:%s", absoluteFrom, absoluteMountpoint)) } } return nil } -func (s *BaseStage) addCustomMountLabels(mountpointsByFrom map[string][]string, stageImage *StageImage) { +func (s *BaseStage) addCustomMountLabels(mountpointsByFrom map[string][]string, c Conveyor, cr container_runtime.ContainerRuntime, stageImage *StageImage) { for from, mountpoints := range mountpointsByFrom { labelName := fmt.Sprintf("%s%s", imagePkg.WerfMountCustomDirLabelPrefix, strings.ReplaceAll(filepath.ToSlash(from), "/", "--")) labelValue := strings.Join(mountpoints, ";") - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions().AddLabel(map[string]string{labelName: labelValue}) + + addLabels := map[string]string{labelName: labelValue} + if c.UseLegacyStapelBuilder(cr) { + stageImage.Builder.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions().AddLabel(addLabels) + } else { + stageImage.Builder.StapelStageBuilder().AddLabels(addLabels) + } } } diff --git a/pkg/build/stage/before_install.go b/pkg/build/stage/before_install.go index ae2bb80513..8aa82004dc 100644 --- a/pkg/build/stage/before_install.go +++ b/pkg/build/stage/before_install.go @@ -36,7 +36,7 @@ func (s *BeforeInstallStage) PrepareImage(ctx context.Context, c Conveyor, cr co return err } - if err := s.builder.BeforeInstall(ctx, cr, stageImage.StageBuilderAccessor); err != nil { + if err := s.builder.BeforeInstall(ctx, cr, stageImage.Builder, c.UseLegacyStapelBuilder(cr)); err != nil { return err } diff --git a/pkg/build/stage/before_setup.go b/pkg/build/stage/before_setup.go index bd74bf0ab9..4475759244 100644 --- a/pkg/build/stage/before_setup.go +++ b/pkg/build/stage/before_setup.go @@ -42,7 +42,7 @@ func (s *BeforeSetupStage) PrepareImage(ctx context.Context, c Conveyor, cr cont return err } - if err := s.builder.BeforeSetup(ctx, cr, stageImage.StageBuilderAccessor); err != nil { + if err := s.builder.BeforeSetup(ctx, cr, stageImage.Builder, c.UseLegacyStapelBuilder(cr)); err != nil { return err } diff --git a/pkg/build/stage/conveyor.go b/pkg/build/stage/conveyor.go index fdd1248f2f..65a39c75ae 100644 --- a/pkg/build/stage/conveyor.go +++ b/pkg/build/stage/conveyor.go @@ -4,6 +4,7 @@ import ( "context" "github.com/werf/werf/pkg/build/import_server" + "github.com/werf/werf/pkg/container_runtime" "github.com/werf/werf/pkg/giterminism_manager" "github.com/werf/werf/pkg/storage" ) @@ -28,6 +29,8 @@ type Conveyor interface { GetLocalGitRepoVirtualMergeOptions() VirtualMergeOptions GiterminismManager() giterminism_manager.Interface + + UseLegacyStapelBuilder(cr container_runtime.ContainerRuntime) bool } type VirtualMergeOptions struct { diff --git a/pkg/build/stage/data_test.go b/pkg/build/stage/data_test.go index 6fb5851086..1d24c4ce9b 100644 --- a/pkg/build/stage/data_test.go +++ b/pkg/build/stage/data_test.go @@ -5,8 +5,8 @@ import ( . "github.com/onsi/gomega" - "github.com/werf/werf/pkg/build/builder" "github.com/werf/werf/pkg/config" + "github.com/werf/werf/pkg/container_runtime/stage_builder" "github.com/werf/werf/pkg/util" ) @@ -101,7 +101,7 @@ func GetConfigDependencies(dependencies []*TestDependency) (res []*config.Depend return } -func CheckImageDependenciesAfterPrepare(img *LegacyImageStub, stageBuilderAccessor *builder.StageBuilderAccessor, dependencies []*TestDependency) { +func CheckImageDependenciesAfterPrepare(img *LegacyImageStub, stageBuilder *stage_builder.StageBuilder, dependencies []*TestDependency) { for _, dep := range dependencies { if dep.TargetEnvImageName != "" { Expect(img._Container._ServiceCommitChangeOptions.Env[dep.TargetEnvImageName]).To(Equal(dep.GetDockerImageName())) @@ -117,16 +117,16 @@ func CheckImageDependenciesAfterPrepare(img *LegacyImageStub, stageBuilderAccess } if dep.TargetBuildArgImageName != "" { - Expect(util.IsStringsContainValue(stageBuilderAccessor.DockerfileImageBuilder.BuildDockerfileOptions.BuildArgs, fmt.Sprintf("%s=%s", dep.TargetBuildArgImageName, dep.GetDockerImageName()))).To(BeTrue()) + Expect(util.IsStringsContainValue(stageBuilder.GetDockerfileStageBuilderImplementation().BuildDockerfileOptions.BuildArgs, fmt.Sprintf("%s=%s", dep.TargetBuildArgImageName, dep.GetDockerImageName()))).To(BeTrue()) } if dep.TargetBuildArgImageRepo != "" { - Expect(util.IsStringsContainValue(stageBuilderAccessor.DockerfileImageBuilder.BuildDockerfileOptions.BuildArgs, fmt.Sprintf("%s=%s", dep.TargetBuildArgImageRepo, dep.DockerImageRepo))).To(BeTrue()) + Expect(util.IsStringsContainValue(stageBuilder.GetDockerfileStageBuilderImplementation().BuildDockerfileOptions.BuildArgs, fmt.Sprintf("%s=%s", dep.TargetBuildArgImageRepo, dep.DockerImageRepo))).To(BeTrue()) } if dep.TargetBuildArgImageTag != "" { - Expect(util.IsStringsContainValue(stageBuilderAccessor.DockerfileImageBuilder.BuildDockerfileOptions.BuildArgs, fmt.Sprintf("%s=%s", dep.TargetBuildArgImageTag, dep.DockerImageTag))).To(BeTrue()) + Expect(util.IsStringsContainValue(stageBuilder.GetDockerfileStageBuilderImplementation().BuildDockerfileOptions.BuildArgs, fmt.Sprintf("%s=%s", dep.TargetBuildArgImageTag, dep.DockerImageTag))).To(BeTrue()) } if dep.TargetBuildArgImageID != "" { - Expect(util.IsStringsContainValue(stageBuilderAccessor.DockerfileImageBuilder.BuildDockerfileOptions.BuildArgs, fmt.Sprintf("%s=%s", dep.TargetBuildArgImageID, dep.DockerImageID))).To(BeTrue()) + Expect(util.IsStringsContainValue(stageBuilder.GetDockerfileStageBuilderImplementation().BuildDockerfileOptions.BuildArgs, fmt.Sprintf("%s=%s", dep.TargetBuildArgImageID, dep.DockerImageID))).To(BeTrue()) } } } diff --git a/pkg/build/stage/dependencies.go b/pkg/build/stage/dependencies.go index 4cc0a20dee..c4cdd2f7a7 100644 --- a/pkg/build/stage/dependencies.go +++ b/pkg/build/stage/dependencies.go @@ -95,7 +95,7 @@ func (s *DependenciesStage) GetDependencies(ctx context.Context, c Conveyor, _, return util.Sha256Hash(args...), nil } -func (s *DependenciesStage) prepareImageWithDockerServer(ctx context.Context, c Conveyor, cr container_runtime.ContainerRuntime, _, stageImage *StageImage) error { +func (s *DependenciesStage) prepareImageWithLegacyStapelBuilder(ctx context.Context, c Conveyor, cr container_runtime.ContainerRuntime, _, stageImage *StageImage) error { for _, elm := range s.imports { sourceImageName := getSourceImageName(elm) srv, err := c.GetImportServer(ctx, sourceImageName, elm.Stage) @@ -104,9 +104,9 @@ func (s *DependenciesStage) prepareImageWithDockerServer(ctx context.Context, c } command := srv.GetCopyCommand(ctx, elm) - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().AddServiceRunCommands(command) + stageImage.Builder.LegacyStapelStageBuilder().Container().AddServiceRunCommands(command) - imageServiceCommitChangeOptions := stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions() + imageServiceCommitChangeOptions := stageImage.Builder.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions() labelKey := imagePkg.WerfImportChecksumLabelPrefix + getImportID(elm) @@ -123,7 +123,7 @@ func (s *DependenciesStage) prepareImageWithDockerServer(ctx context.Context, c } for _, dep := range s.dependencies { - depImageServiceOptions := stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions() + depImageServiceOptions := stageImage.Builder.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions() depImageName := c.GetImageNameForLastImageStage(dep.ImageName) depImageID := c.GetImageIDForLastImageStage(dep.ImageName) @@ -155,11 +155,11 @@ func (s *DependenciesStage) prepareImageWithDockerServer(ctx context.Context, c } func (s *DependenciesStage) PrepareImage(ctx context.Context, c Conveyor, cr container_runtime.ContainerRuntime, prevImage, stageImage *StageImage) error { - if cr.HasContainerRootMountSupport() { + if c.UseLegacyStapelBuilder(cr) { + return s.prepareImageWithLegacyStapelBuilder(ctx, c, cr, prevImage, stageImage) + } else { // TODO(stapel-to-buildah) panic("not implemented") - } else { - return s.prepareImageWithDockerServer(ctx, c, cr, prevImage, stageImage) } } diff --git a/pkg/build/stage/dependencies_test.go b/pkg/build/stage/dependencies_test.go index dff40e4ca4..41db378923 100644 --- a/pkg/build/stage/dependencies_test.go +++ b/pkg/build/stage/dependencies_test.go @@ -6,8 +6,8 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/werf/werf/pkg/build/builder" "github.com/werf/werf/pkg/config" + "github.com/werf/werf/pkg/container_runtime/stage_builder" ) var _ = Describe("DependenciesStage", func() { @@ -24,10 +24,10 @@ var _ = Describe("DependenciesStage", func() { }) img := NewLegacyImageStub() - stageBuilderAccessor := builder.NewStageBuilderAccessor(containerRuntime, img) + stageBuilder := stage_builder.NewStageBuilder(containerRuntime, nil, img) stageImage := &StageImage{ - Image: img, - StageBuilderAccessor: stageBuilderAccessor, + Image: img, + Builder: stageBuilder, } digest, err := stage.GetDependencies(ctx, conveyor, nil, stageImage) @@ -36,7 +36,7 @@ var _ = Describe("DependenciesStage", func() { err = stage.PrepareImage(ctx, conveyor, containerRuntime, nil, stageImage) Expect(err).To(Succeed()) - CheckImageDependenciesAfterPrepare(img, stageBuilderAccessor, data.Dependencies) + CheckImageDependenciesAfterPrepare(img, stageBuilder, data.Dependencies) }, Entry("should calculate basic stage digest when no dependencies are set", diff --git a/pkg/build/stage/docker_instructions.go b/pkg/build/stage/docker_instructions.go index 5f8e237495..2f5f68e52f 100644 --- a/pkg/build/stage/docker_instructions.go +++ b/pkg/build/stage/docker_instructions.go @@ -65,11 +65,8 @@ func (s *DockerInstructionsStage) PrepareImage(ctx context.Context, c Conveyor, return err } - if cr.HasContainerRootMountSupport() { - // TODO(stapel-to-buildah) - panic("not implemented") - } else { - imageCommitChangeOptions := stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().CommitChangeOptions() + if c.UseLegacyStapelBuilder(cr) { + imageCommitChangeOptions := stageImage.Builder.LegacyStapelStageBuilder().Container().CommitChangeOptions() imageCommitChangeOptions.AddVolume(s.instructions.Volume...) imageCommitChangeOptions.AddExpose(s.instructions.Expose...) imageCommitChangeOptions.AddEnv(s.instructions.Env) @@ -81,5 +78,8 @@ func (s *DockerInstructionsStage) PrepareImage(ctx context.Context, c Conveyor, imageCommitChangeOptions.AddHealthCheck(s.instructions.HealthCheck) return nil + } else { + // TODO(stapel-to-buildah) + panic("not implemented") } } diff --git a/pkg/build/stage/dockerfile.go b/pkg/build/stage/dockerfile.go index 77d8089f1c..f528df941a 100644 --- a/pkg/build/stage/dockerfile.go +++ b/pkg/build/stage/dockerfile.go @@ -16,9 +16,9 @@ import ( "github.com/moby/buildkit/frontend/dockerfile/shell" "github.com/werf/logboek" - "github.com/werf/werf/pkg/build/builder" "github.com/werf/werf/pkg/config" "github.com/werf/werf/pkg/container_runtime" + "github.com/werf/werf/pkg/container_runtime/stage_builder" "github.com/werf/werf/pkg/context_manager" "github.com/werf/werf/pkg/docker_registry" "github.com/werf/werf/pkg/git_repo" @@ -688,16 +688,16 @@ func (s *DockerfileStage) PrepareImage(ctx context.Context, c Conveyor, cr conta return err } - if err := s.SetupDockerImageBuilder(stageImage.StageBuilderAccessor.NativeDockerfileStageBuilder(), c); err != nil { + if err := s.SetupDockerImageBuilder(stageImage.Builder.DockerfileStageBuilder(), c); err != nil { return err } - stageImage.StageBuilderAccessor.NativeDockerfileStageBuilder().SetContextArchivePath(archivePath) + stageImage.Builder.DockerfileStageBuilder().SetContextArchivePath(archivePath) - stageImage.StageBuilderAccessor.NativeDockerfileStageBuilder().AppendLabels(fmt.Sprintf("%s=%s", image.WerfProjectRepoCommitLabel, c.GiterminismManager().HeadCommit())) + stageImage.Builder.DockerfileStageBuilder().AppendLabels(fmt.Sprintf("%s=%s", image.WerfProjectRepoCommitLabel, c.GiterminismManager().HeadCommit())) if c.GiterminismManager().Dev() { - stageImage.StageBuilderAccessor.NativeDockerfileStageBuilder().AppendLabels(fmt.Sprintf("%s=true", image.WerfDevLabel)) + stageImage.Builder.DockerfileStageBuilder().AppendLabels(fmt.Sprintf("%s=true", image.WerfDevLabel)) } return nil @@ -738,7 +738,7 @@ func (s *DockerfileStage) prepareContextArchive(ctx context.Context, giterminism return archivePath, nil } -func (s *DockerfileStage) SetupDockerImageBuilder(b builder.NativeDockerfileStageBuilderInterface, c Conveyor) error { +func (s *DockerfileStage) SetupDockerImageBuilder(b stage_builder.DockerfileStageBuilderInterface, c Conveyor) error { b.SetDockerfile(s.dockerfile) b.SetDockerfileCtxRelPath(s.dockerfilePath) diff --git a/pkg/build/stage/dockerfile_test.go b/pkg/build/stage/dockerfile_test.go index 496b73cca0..323a562766 100644 --- a/pkg/build/stage/dockerfile_test.go +++ b/pkg/build/stage/dockerfile_test.go @@ -9,8 +9,8 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - "github.com/werf/werf/pkg/build/builder" "github.com/werf/werf/pkg/build/dockerfile_helpers" + "github.com/werf/werf/pkg/container_runtime/stage_builder" "github.com/werf/werf/pkg/util" ) @@ -72,10 +72,10 @@ var _ = Describe("DockerfileStage", func() { stage := newTestDockerfileStage(data.Dockerfile, data.Target, data.BuildArgs, dockerStages, dockerMetaArgs, data.TestDependencies.Dependencies) img := NewLegacyImageStub() - stageBuilderAccessor := builder.NewStageBuilderAccessor(containerRuntime, img) + stageBuilder := stage_builder.NewStageBuilder(containerRuntime, nil, img) stageImage := &StageImage{ - Image: img, - StageBuilderAccessor: stageBuilderAccessor, + Image: img, + Builder: stageBuilder, } digest, err := stage.GetDependencies(ctx, conveyor, nil, stageImage) @@ -84,7 +84,7 @@ var _ = Describe("DockerfileStage", func() { err = stage.PrepareImage(ctx, conveyor, containerRuntime, nil, stageImage) Expect(err).To(Succeed()) - CheckImageDependenciesAfterPrepare(img, stageBuilderAccessor, data.TestDependencies.Dependencies) + CheckImageDependenciesAfterPrepare(img, stageBuilder, data.TestDependencies.Dependencies) }, Entry("should calculate dockerfile stage digest when no dependencies are set", diff --git a/pkg/build/stage/from.go b/pkg/build/stage/from.go index b218878a05..729448c672 100644 --- a/pkg/build/stage/from.go +++ b/pkg/build/stage/from.go @@ -3,6 +3,7 @@ package stage import ( "context" "fmt" + "os" "path" "path/filepath" "strings" @@ -72,27 +73,41 @@ func (s *FromStage) GetDependencies(_ context.Context, c Conveyor, prevImage, _ } func (s *FromStage) PrepareImage(ctx context.Context, c Conveyor, cr container_runtime.ContainerRuntime, prevBuiltImage, stageImage *StageImage) error { - if cr.HasContainerRootMountSupport() { - // TODO(stapel-to-buildah) - panic("not implemented") + addLabels := map[string]string{imagePkg.WerfProjectRepoCommitLabel: c.GiterminismManager().HeadCommit()} + if c.UseLegacyStapelBuilder(cr) { + stageImage.Builder.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions().AddLabel(addLabels) } else { - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions().AddLabel(map[string]string{imagePkg.WerfProjectRepoCommitLabel: c.GiterminismManager().HeadCommit()}) + stageImage.Builder.StapelStageBuilder().AddLabels(addLabels) + } - serviceMounts := s.getServiceMounts(prevBuiltImage) - s.addServiceMountsLabels(serviceMounts, stageImage) + serviceMounts := s.getServiceMounts(prevBuiltImage) + s.addServiceMountsLabels(serviceMounts, c, cr, stageImage) - customMounts := s.getCustomMounts(prevBuiltImage) - s.addCustomMountLabels(customMounts, stageImage) + customMounts := s.getCustomMounts(prevBuiltImage) + s.addCustomMountLabels(customMounts, c, cr, stageImage) - var mountpoints []string - for _, mountCfg := range s.configMounts { - mountpoints = append(mountpoints, mountCfg.To) - } - if len(mountpoints) != 0 { - mountpointsStr := strings.Join(mountpoints, " ") - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().AddServiceRunCommands(fmt.Sprintf("%s -rf %s", stapel.RmBinPath(), mountpointsStr)) - } + var mountpoints []string + for _, mountCfg := range s.configMounts { + mountpoints = append(mountpoints, mountCfg.To) + } - return nil + if len(mountpoints) != 0 { + mountpointsStr := strings.Join(mountpoints, " ") + + if c.UseLegacyStapelBuilder(cr) { + stageImage.Builder.LegacyStapelStageBuilder().Container().AddServiceRunCommands(fmt.Sprintf("%s -rf %s", stapel.RmBinPath(), mountpointsStr)) + } else { + stageImage.Builder.StapelStageBuilder().AddPrepareContainerActions(container_runtime.PrepareContainerActionWith(func(containerRoot string) error { + for _, mountpoint := range mountpoints { + if err := os.RemoveAll(mountpoint); err != nil { + return fmt.Errorf("unable to remove %q: %s", mountpoint, err) + } + } + + return nil + })) + } } + + return nil } diff --git a/pkg/build/stage/git.go b/pkg/build/stage/git.go index 1b4d502d66..25a3ffb9fa 100644 --- a/pkg/build/stage/git.go +++ b/pkg/build/stage/git.go @@ -30,14 +30,14 @@ func (s *GitStage) PrepareImage(ctx context.Context, c Conveyor, cr container_ru return err } - if cr.HasContainerRootMountSupport() { - // TODO(stapel-to-buildah) - panic("not implemented") - } else { + if c.UseLegacyStapelBuilder(cr) { if c.GiterminismManager().Dev() { - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().BuilderContainer().AddLabel(map[string]string{imagePkg.WerfDevLabel: "true"}) + stageImage.Builder.LegacyStapelStageBuilder().BuilderContainer().AddLabel(map[string]string{imagePkg.WerfDevLabel: "true"}) } return nil + } else { + // TODO(stapel-to-buildah) + panic("not implemented") } } diff --git a/pkg/build/stage/git_archive.go b/pkg/build/stage/git_archive.go index 2179623e5c..d4b604dc00 100644 --- a/pkg/build/stage/git_archive.go +++ b/pkg/build/stage/git_archive.go @@ -73,21 +73,20 @@ func (s *GitArchiveStage) PrepareImage(ctx context.Context, c Conveyor, cr conta return err } - if cr.HasContainerRootMountSupport() { - // TODO(stapel-to-buildah) - panic("not implemented") - } else { - + if c.UseLegacyStapelBuilder(cr) { for _, gitMapping := range s.gitMappings { if err := gitMapping.ApplyArchiveCommand(ctx, c, stageImage); err != nil { return err } } - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().RunOptions().AddVolume(fmt.Sprintf("%s:%s:ro", git_repo.CommonGitDataManager.GetArchivesCacheDir(), s.ContainerArchivesDir)) - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().RunOptions().AddVolume(fmt.Sprintf("%s:%s:ro", s.ScriptsDir, s.ContainerScriptsDir)) + stageImage.Builder.LegacyStapelStageBuilder().Container().RunOptions().AddVolume(fmt.Sprintf("%s:%s:ro", git_repo.CommonGitDataManager.GetArchivesCacheDir(), s.ContainerArchivesDir)) + stageImage.Builder.LegacyStapelStageBuilder().Container().RunOptions().AddVolume(fmt.Sprintf("%s:%s:ro", s.ScriptsDir, s.ContainerScriptsDir)) return nil + } else { + // TODO(stapel-to-buildah) + panic("not implemented") } } diff --git a/pkg/build/stage/git_mapping.go b/pkg/build/stage/git_mapping.go index c51cd6b7d0..fbba1c3607 100644 --- a/pkg/build/stage/git_mapping.go +++ b/pkg/build/stage/git_mapping.go @@ -297,18 +297,18 @@ func (gm *GitMapping) GetLatestCommitInfo(ctx context.Context, c Conveyor) (Imag } func (gm *GitMapping) AddGitCommitToImageLabels(stageImage *StageImage, commitInfo ImageCommitInfo) { - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions().AddLabel(map[string]string{ + stageImage.Builder.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions().AddLabel(map[string]string{ gm.ImageGitCommitLabel(): commitInfo.Commit, }) if commitInfo.VirtualMerge { - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions().AddLabel(map[string]string{ + stageImage.Builder.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions().AddLabel(map[string]string{ gm.VirtualMergeLabel(): "true", gm.VirtualMergeFromCommitLabel(): commitInfo.VirtualMergeFromCommit, gm.VirtualMergeIntoCommitLabel(): commitInfo.VirtualMergeIntoCommit, }) } else { - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions().AddLabel(map[string]string{ + stageImage.Builder.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions().AddLabel(map[string]string{ gm.VirtualMergeLabel(): "false", }) } @@ -595,7 +595,7 @@ func (gm *GitMapping) applyScript(stageImage *StageImage, commands []string) err return err } - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().AddServiceRunCommands(containerTmpScriptFilePath) + stageImage.Builder.LegacyStapelStageBuilder().Container().AddServiceRunCommands(containerTmpScriptFilePath) return nil } @@ -626,7 +626,7 @@ func (gm *GitMapping) baseApplyArchiveCommand(ctx context.Context, commit string return nil, err } - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions().AddLabel(map[string]string{gm.getArchiveTypeLabelName(): string(archiveType)}) + stageImage.Builder.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions().AddLabel(map[string]string{gm.getArchiveTypeLabelName(): string(archiveType)}) return commands, err } diff --git a/pkg/build/stage/git_mapping_test.go b/pkg/build/stage/git_mapping_test.go index 24a3c97ee9..10586babc3 100644 --- a/pkg/build/stage/git_mapping_test.go +++ b/pkg/build/stage/git_mapping_test.go @@ -142,7 +142,7 @@ var _ = Describe("GitMapping", func() { }, }, }) - img := stage.NewStageImage(containerRuntime, prevBuiltImage) + img := stage.NewStageImage(containerRuntime, nil, prevBuiltImage) baseCommit, err := gitMapping.GetBaseCommitForPrevBuiltImage(ctx, c, img) Expect(err).To(Succeed()) diff --git a/pkg/build/stage/git_patch.go b/pkg/build/stage/git_patch.go index ff3f87663b..7e68997fd5 100644 --- a/pkg/build/stage/git_patch.go +++ b/pkg/build/stage/git_patch.go @@ -78,20 +78,20 @@ func (s *GitPatchStage) PrepareImage(ctx context.Context, c Conveyor, cr contain } func (s *GitPatchStage) prepareImage(ctx context.Context, c Conveyor, cr container_runtime.ContainerRuntime, prevBuiltImage, stageImage *StageImage) error { - if cr.HasContainerRootMountSupport() { - // TODO(stapel-to-buildah) - panic("not implemented") - } else { + if c.UseLegacyStapelBuilder(cr) { for _, gitMapping := range s.gitMappings { if err := gitMapping.ApplyPatchCommand(ctx, c, prevBuiltImage, stageImage); err != nil { return err } } - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().RunOptions().AddVolume(fmt.Sprintf("%s:%s:ro", git_repo.CommonGitDataManager.GetPatchesCacheDir(), s.ContainerPatchesDir)) - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().RunOptions().AddVolume(fmt.Sprintf("%s:%s:ro", git_repo.CommonGitDataManager.GetArchivesCacheDir(), s.ContainerArchivesDir)) - stageImage.StageBuilderAccessor.LegacyStapelStageBuilder().Container().RunOptions().AddVolume(fmt.Sprintf("%s:%s:ro", s.ScriptsDir, s.ContainerScriptsDir)) + stageImage.Builder.LegacyStapelStageBuilder().Container().RunOptions().AddVolume(fmt.Sprintf("%s:%s:ro", git_repo.CommonGitDataManager.GetPatchesCacheDir(), s.ContainerPatchesDir)) + stageImage.Builder.LegacyStapelStageBuilder().Container().RunOptions().AddVolume(fmt.Sprintf("%s:%s:ro", git_repo.CommonGitDataManager.GetArchivesCacheDir(), s.ContainerArchivesDir)) + stageImage.Builder.LegacyStapelStageBuilder().Container().RunOptions().AddVolume(fmt.Sprintf("%s:%s:ro", s.ScriptsDir, s.ContainerScriptsDir)) return nil + } else { + // TODO(stapel-to-buildah) + panic("not implemented") } } diff --git a/pkg/build/stage/install.go b/pkg/build/stage/install.go index 3cc3e208ab..7a9af9786b 100644 --- a/pkg/build/stage/install.go +++ b/pkg/build/stage/install.go @@ -42,7 +42,7 @@ func (s *InstallStage) PrepareImage(ctx context.Context, c Conveyor, cr containe return err } - if err := s.builder.Install(ctx, cr, stageImage.StageBuilderAccessor); err != nil { + if err := s.builder.Install(ctx, cr, stageImage.Builder, c.UseLegacyStapelBuilder(cr)); err != nil { return err } diff --git a/pkg/build/stage/setup.go b/pkg/build/stage/setup.go index 6a4d2258ef..fbdd5d646a 100644 --- a/pkg/build/stage/setup.go +++ b/pkg/build/stage/setup.go @@ -42,7 +42,7 @@ func (s *SetupStage) PrepareImage(ctx context.Context, c Conveyor, cr container_ return err } - if err := s.builder.Setup(ctx, cr, stageImage.StageBuilderAccessor); err != nil { + if err := s.builder.Setup(ctx, cr, stageImage.Builder, c.UseLegacyStapelBuilder(cr)); err != nil { return err } diff --git a/pkg/build/stage/stage_image.go b/pkg/build/stage/stage_image.go index 73ab2bbf92..08b9a8105d 100644 --- a/pkg/build/stage/stage_image.go +++ b/pkg/build/stage/stage_image.go @@ -1,18 +1,18 @@ package stage import ( - "github.com/werf/werf/pkg/build/builder" "github.com/werf/werf/pkg/container_runtime" + "github.com/werf/werf/pkg/container_runtime/stage_builder" ) type StageImage struct { - Image container_runtime.LegacyImageInterface - StageBuilderAccessor builder.StageBuilderAccessorInterface + Image container_runtime.LegacyImageInterface + Builder stage_builder.StageBuilderInterface } -func NewStageImage(containerRuntime container_runtime.ContainerRuntime, image container_runtime.LegacyImageInterface) *StageImage { +func NewStageImage(containerRuntime container_runtime.ContainerRuntime, fromImage container_runtime.ImageInterface, image container_runtime.LegacyImageInterface) *StageImage { return &StageImage{ - Image: image, - StageBuilderAccessor: builder.NewStageBuilderAccessor(containerRuntime, image), + Image: image, + Builder: stage_builder.NewStageBuilder(containerRuntime, fromImage, image), } } diff --git a/pkg/build/stage/stubs_test.go b/pkg/build/stage/stubs_test.go index c5d2244a6f..7f1a487218 100644 --- a/pkg/build/stage/stubs_test.go +++ b/pkg/build/stage/stubs_test.go @@ -89,6 +89,10 @@ func NewConveyorStubForDependencies(giterminismManager *GiterminismManagerStub, return NewConveyorStub(giterminismManager, lastStageImageNameByImageName, lastStageImageIDByImageName) } +func (c *ConveyorStub) UseLegacyStapelBuilder(cr container_runtime.ContainerRuntime) bool { + return true +} + func (c *ConveyorStub) GetImageNameForLastImageStage(imageName string) string { return c.lastStageImageNameByImageName[imageName] } diff --git a/pkg/container_runtime/buildah_runtime.go b/pkg/container_runtime/buildah_runtime.go index 9411983b9b..a120fc0638 100644 --- a/pkg/container_runtime/buildah_runtime.go +++ b/pkg/container_runtime/buildah_runtime.go @@ -5,6 +5,8 @@ import ( "fmt" "strings" + "github.com/google/uuid" + "github.com/werf/logboek" "github.com/werf/werf/pkg/buildah" "github.com/werf/werf/pkg/image" @@ -22,10 +24,62 @@ func NewBuildahRuntime(buildah buildah.Buildah) *BuildahRuntime { return &BuildahRuntime{buildah: buildah} } -func (runtime *BuildahRuntime) HasContainerRootMountSupport() bool { +func (runtime *BuildahRuntime) HasStapelBuildSupport() bool { return true } +// FIXME(stapel-to-buildah): proper deep implementation +func (runtime *BuildahRuntime) BuildStapelStage(ctx context.Context, baseImage string, opts BuildStapelStageOpts) (string, error) { + /* + 1. Create new temporary build container using 'from' and remain uniq container name. + 2. Mount container root to host and run all prepare-container-actions, then unmount. + 3. Run user instructions in container, mount volumes when build. + 4. Set specified labels into container. + 5. Save container name as builtID (ideally there is no need to commit an image here, because buildah allows to commit and push directly container, which would happen later). + */ + + containerID := uuid.New().String() + + _, err := runtime.buildah.FromCommand(ctx, containerID, baseImage, buildah.FromCommandOpts{}) + if err != nil { + return "", fmt.Errorf("unable to create container using base image %q: %s", baseImage, err) + } + + if len(opts.PrepareContainerActions) > 0 { + err := func() error { + containerRoot, err := runtime.buildah.Mount(ctx, containerID, buildah.MountOpts{}) + if err != nil { + return fmt.Errorf("unable to mount container %q root dir: %s", containerID, err) + } + defer runtime.buildah.Umount(ctx, containerRoot, buildah.UmountOpts{}) + + for _, action := range opts.PrepareContainerActions { + if err := action.PrepareContainer(containerRoot); err != nil { + return fmt.Errorf("unable to prepare container in %q: %s", containerRoot, err) + } + } + + return nil + }() + if err != nil { + return "", err + } + } + + for _, cmd := range opts.UserCommands { + if err := runtime.buildah.RunCommand(ctx, containerID, strings.Fields(cmd), buildah.RunCommandOpts{}); err != nil { + return "", fmt.Errorf("unable to run %q: %s", cmd, err) + } + } + + // TODO(stapel-to-buildah): use buildah.Change to set labels + fmt.Printf("Setting labels %v for build container %q\n", opts.Labels, containerID) + + fmt.Printf("Committing container %q\n", containerID) + + return "", fmt.Errorf("not implemented yet") +} + // GetImageInfo returns nil, nil if image not found. func (runtime *BuildahRuntime) GetImageInfo(ctx context.Context, ref string, opts GetImageInfoOpts) (*image.Info, error) { inspect, err := runtime.buildah.Inspect(ctx, ref) diff --git a/pkg/container_runtime/docker_server_runtime.go b/pkg/container_runtime/docker_server_runtime.go index c1ea0ba90b..efa1921d93 100644 --- a/pkg/container_runtime/docker_server_runtime.go +++ b/pkg/container_runtime/docker_server_runtime.go @@ -20,10 +20,14 @@ func NewDockerServerRuntime() *DockerServerRuntime { return &DockerServerRuntime{} } -func (runtime *DockerServerRuntime) HasContainerRootMountSupport() bool { +func (runtime *DockerServerRuntime) HasStapelBuildSupport() bool { return false } +func (runtime *DockerServerRuntime) BuildStapelStage(ctx context.Context, baseImage string, opts BuildStapelStageOpts) (string, error) { + panic("BuildStapelStage does not implemented for DockerServerRuntime. Please report the bug if you've received this message.") +} + func (runtime *DockerServerRuntime) BuildDockerfile(ctx context.Context, _ []byte, opts BuildDockerfileOpts) (string, error) { switch { case opts.ContextTar == nil: @@ -63,7 +67,7 @@ func (runtime *DockerServerRuntime) BuildDockerfile(ctx context.Context, _ []byt cliArgs = append(cliArgs, "-") - if debug() { + if Debug() { fmt.Printf("[DOCKER BUILD] docker build %s\n", strings.Join(cliArgs, " ")) } diff --git a/pkg/container_runtime/dockerfile_image_builder.go b/pkg/container_runtime/dockerfile_image_builder.go deleted file mode 100644 index 847e64b057..0000000000 --- a/pkg/container_runtime/dockerfile_image_builder.go +++ /dev/null @@ -1,93 +0,0 @@ -package container_runtime - -import ( - "context" - "fmt" - "os" -) - -type DockerfileImageBuilder struct { - ContainerRuntime ContainerRuntime - Dockerfile []byte - BuildDockerfileOptions BuildDockerfileOpts - ContextArchivePath string - - Image ImageInterface -} - -func NewDockerfileImageBuilder(containerRuntime ContainerRuntime, image ImageInterface) *DockerfileImageBuilder { - return &DockerfileImageBuilder{ContainerRuntime: containerRuntime, Image: image} -} - -// filePathToStdin != "" ?? -func (b *DockerfileImageBuilder) Build(ctx context.Context) error { - if debug() { - fmt.Printf("[DOCKER BUILD] context archive path: %s\n", b.ContextArchivePath) - } - - contextReader, err := os.Open(b.ContextArchivePath) - if err != nil { - return fmt.Errorf("unable to open context archive %q: %s", b.ContextArchivePath, err) - } - defer contextReader.Close() - - opts := b.BuildDockerfileOptions - opts.ContextTar = contextReader - - if debug() { - fmt.Printf("ContextArchivePath=%q\n", b.ContextArchivePath) - fmt.Printf("BiuldDockerfileOptions: %#v\n", opts) - } - - builtID, err := b.ContainerRuntime.BuildDockerfile(ctx, b.Dockerfile, opts) - if err != nil { - return fmt.Errorf("error building dockerfile with %s: %s", b.ContainerRuntime.String(), err) - } - - b.Image.SetBuiltID(builtID) - - return nil -} - -func (b *DockerfileImageBuilder) Cleanup(ctx context.Context) error { - if err := b.ContainerRuntime.Rmi(ctx, b.Image.GetBuiltID(), RmiOpts{}); err != nil { - return fmt.Errorf("unable to remove built dockerfile image %q: %s", b.Image.GetBuiltID(), err) - } - return nil -} - -func (b *DockerfileImageBuilder) SetDockerfile(dockerfile []byte) { - b.Dockerfile = dockerfile -} - -func (b *DockerfileImageBuilder) SetDockerfileCtxRelPath(dockerfileCtxRelPath string) { - b.BuildDockerfileOptions.DockerfileCtxRelPath = dockerfileCtxRelPath -} - -func (b *DockerfileImageBuilder) SetTarget(target string) { - b.BuildDockerfileOptions.Target = target -} - -func (b *DockerfileImageBuilder) AppendBuildArgs(args ...string) { - b.BuildDockerfileOptions.BuildArgs = append(b.BuildDockerfileOptions.BuildArgs, args...) -} - -func (b *DockerfileImageBuilder) AppendAddHost(addHost ...string) { - b.BuildDockerfileOptions.AddHost = append(b.BuildDockerfileOptions.AddHost, addHost...) -} - -func (b *DockerfileImageBuilder) SetNetwork(network string) { - b.BuildDockerfileOptions.Network = network -} - -func (b *DockerfileImageBuilder) SetSSH(ssh string) { - b.BuildDockerfileOptions.SSH = ssh -} - -func (b *DockerfileImageBuilder) AppendLabels(labels ...string) { - b.BuildDockerfileOptions.Labels = append(b.BuildDockerfileOptions.Labels, labels...) -} - -func (b *DockerfileImageBuilder) SetContextArchivePath(contextArchivePath string) { - b.ContextArchivePath = contextArchivePath -} diff --git a/pkg/container_runtime/image_interface.go b/pkg/container_runtime/image_interface.go index 320bbd039d..44ab1bb78e 100644 --- a/pkg/container_runtime/image_interface.go +++ b/pkg/container_runtime/image_interface.go @@ -1,6 +1,9 @@ package container_runtime type ImageInterface interface { + Name() string + SetName(name string) + SetBuiltID(builtID string) - GetBuiltID() string + BuiltID() string } diff --git a/pkg/container_runtime/interface.go b/pkg/container_runtime/interface.go index 78192a56ea..73fdf17ca4 100644 --- a/pkg/container_runtime/interface.go +++ b/pkg/container_runtime/interface.go @@ -53,6 +53,23 @@ type BuildDockerfileOpts struct { // Labels map[string]string // } +type BuildStapelStageOpts struct { + BuildVolumes []string + Labels []string + UserCommands []string + PrepareContainerActions []PrepareContainerAction +} + +type PrepareContainerAction interface { + PrepareContainer(containerRoot string) error +} + +type PrepareContainerActionWith func(containerRoot string) error + +func (f PrepareContainerActionWith) PrepareContainer(containerRoot string) error { + return f(containerRoot) +} + type ContainerRuntime interface { Tag(ctx context.Context, ref, newRef string, opts TagOpts) error Push(ctx context.Context, ref string, opts PushOpts) error @@ -61,9 +78,9 @@ type ContainerRuntime interface { GetImageInfo(ctx context.Context, ref string, opts GetImageInfoOpts) (*image.Info, error) BuildDockerfile(ctx context.Context, dockerfile []byte, opts BuildDockerfileOpts) (string, error) - // StapelBuild(opts StapelBuildOptions) string + BuildStapelStage(ctx context.Context, baseImage string, opts BuildStapelStageOpts) (string, error) - HasContainerRootMountSupport() bool + HasStapelBuildSupport() bool String() string // Legacy diff --git a/pkg/container_runtime/legacy_interface.go b/pkg/container_runtime/legacy_interface.go index 1fb5728d9a..8087190b56 100644 --- a/pkg/container_runtime/legacy_interface.go +++ b/pkg/container_runtime/legacy_interface.go @@ -6,7 +6,7 @@ import ( "github.com/werf/werf/pkg/image" ) -type LegacyBuildOptions struct { +type BuildOptions struct { IntrospectBeforeError bool IntrospectAfterError bool } @@ -23,9 +23,10 @@ type LegacyImageInterface interface { Container() LegacyContainer BuilderContainer() LegacyBuilderContainer - Build(context.Context, LegacyBuildOptions) error + Build(context.Context, BuildOptions) error SetBuiltID(builtID string) GetBuiltID() string + BuiltID() string TagBuiltImage(ctx context.Context) error Introspect(ctx context.Context) error diff --git a/pkg/container_runtime/legacy_stage_image.go b/pkg/container_runtime/legacy_stage_image.go index bfd1e95308..eff3bdcffa 100644 --- a/pkg/container_runtime/legacy_stage_image.go +++ b/pkg/container_runtime/legacy_stage_image.go @@ -45,7 +45,7 @@ func (i *LegacyStageImage) GetID() string { } } -func (i *LegacyStageImage) Build(ctx context.Context, options LegacyBuildOptions) error { +func (i *LegacyStageImage) Build(ctx context.Context, options BuildOptions) error { containerLockName := ContainerLockName(i.container.Name()) if _, lock, err := werf.AcquireHostLock(ctx, containerLockName, lockgate.AcquireOptions{}); err != nil { return fmt.Errorf("failed to lock %s: %s", containerLockName, err) @@ -175,10 +175,14 @@ func (i *LegacyStageImage) SetBuiltID(builtID string) { i.builtID = builtID } -func (i *LegacyStageImage) GetBuiltID() string { +func (i *LegacyStageImage) BuiltID() string { return i.builtID } +func (i *LegacyStageImage) GetBuiltID() string { + return i.BuiltID() +} + func (i *LegacyStageImage) TagBuiltImage(ctx context.Context) error { _ = i.ContainerRuntime.(*DockerServerRuntime) diff --git a/pkg/container_runtime/perf_check_container_runtime.go b/pkg/container_runtime/perf_check_container_runtime.go index bcb23ad2d9..988b1e8d93 100644 --- a/pkg/container_runtime/perf_check_container_runtime.go +++ b/pkg/container_runtime/perf_check_container_runtime.go @@ -15,8 +15,8 @@ func NewPerfCheckContainerRuntime(containerRuntime ContainerRuntime) *PerfCheckC return &PerfCheckContainerRuntime{ContainerRuntime: containerRuntime} } -func (runtime *PerfCheckContainerRuntime) HasContainerRootMountSupport() bool { - return runtime.ContainerRuntime.HasContainerRootMountSupport() +func (runtime *PerfCheckContainerRuntime) HasStapelBuildSupport() bool { + return runtime.ContainerRuntime.HasStapelBuildSupport() } func (runtime *PerfCheckContainerRuntime) GetImageInfo(ctx context.Context, ref string, opts GetImageInfoOpts) (resImg *image.Info, resErr error) { @@ -67,6 +67,14 @@ func (runtime *PerfCheckContainerRuntime) BuildDockerfile(ctx context.Context, d return } +func (runtime *PerfCheckContainerRuntime) BuildStapelStage(ctx context.Context, baseImage string, opts BuildStapelStageOpts) (resID string, resErr error) { + logboek.Context(ctx).Default().LogProcess("ContainerRuntime.BuildDockerfile"). + Do(func() { + resID, resErr = runtime.ContainerRuntime.BuildStapelStage(ctx, baseImage, opts) + }) + return +} + func (runtime *PerfCheckContainerRuntime) RefreshImageObject(ctx context.Context, img LegacyImageInterface) (resErr error) { logboek.Context(ctx).Default().LogProcess("ContainerRuntime.RefreshImageObject %q", img.Name()). Do(func() { diff --git a/pkg/container_runtime/stage_builder/dockerfile_stage_builder.go b/pkg/container_runtime/stage_builder/dockerfile_stage_builder.go new file mode 100644 index 0000000000..75d936d75a --- /dev/null +++ b/pkg/container_runtime/stage_builder/dockerfile_stage_builder.go @@ -0,0 +1,110 @@ +package stage_builder + +import ( + "context" + "fmt" + "os" + + "github.com/werf/werf/pkg/container_runtime" +) + +type DockerfileStageBuilderInterface interface { + Build(ctx context.Context) error + Cleanup(ctx context.Context) error + SetDockerfile(dockerfile []byte) + SetDockerfileCtxRelPath(dockerfileCtxRelPath string) + SetTarget(target string) + AppendBuildArgs(args ...string) + AppendAddHost(addHost ...string) + SetNetwork(network string) + SetSSH(ssh string) + AppendLabels(labels ...string) + SetContextArchivePath(contextArchivePath string) +} + +type DockerfileStageBuilder struct { + ContainerRuntime container_runtime.ContainerRuntime + Dockerfile []byte + BuildDockerfileOptions container_runtime.BuildDockerfileOpts + ContextArchivePath string + + Image container_runtime.ImageInterface +} + +func NewDockerfileStageBuilder(containerRuntime container_runtime.ContainerRuntime, image container_runtime.ImageInterface) *DockerfileStageBuilder { + return &DockerfileStageBuilder{ContainerRuntime: containerRuntime, Image: image} +} + +func (b *DockerfileStageBuilder) Build(ctx context.Context) error { + // filePathToStdin != "" ?? + + if container_runtime.Debug() { + fmt.Printf("[DOCKER BUILD] context archive path: %s\n", b.ContextArchivePath) + } + + contextReader, err := os.Open(b.ContextArchivePath) + if err != nil { + return fmt.Errorf("unable to open context archive %q: %s", b.ContextArchivePath, err) + } + defer contextReader.Close() + + opts := b.BuildDockerfileOptions + opts.ContextTar = contextReader + + if container_runtime.Debug() { + fmt.Printf("ContextArchivePath=%q\n", b.ContextArchivePath) + fmt.Printf("BiuldDockerfileOptions: %#v\n", opts) + } + + builtID, err := b.ContainerRuntime.BuildDockerfile(ctx, b.Dockerfile, opts) + if err != nil { + return fmt.Errorf("error building dockerfile with %s: %s", b.ContainerRuntime.String(), err) + } + + b.Image.SetBuiltID(builtID) + + return nil +} + +func (b *DockerfileStageBuilder) Cleanup(ctx context.Context) error { + if err := b.ContainerRuntime.Rmi(ctx, b.Image.BuiltID(), container_runtime.RmiOpts{}); err != nil { + return fmt.Errorf("unable to remove built dockerfile image %q: %s", b.Image.BuiltID(), err) + } + return nil +} + +func (b *DockerfileStageBuilder) SetDockerfile(dockerfile []byte) { + b.Dockerfile = dockerfile +} + +func (b *DockerfileStageBuilder) SetDockerfileCtxRelPath(dockerfileCtxRelPath string) { + b.BuildDockerfileOptions.DockerfileCtxRelPath = dockerfileCtxRelPath +} + +func (b *DockerfileStageBuilder) SetTarget(target string) { + b.BuildDockerfileOptions.Target = target +} + +func (b *DockerfileStageBuilder) AppendBuildArgs(args ...string) { + b.BuildDockerfileOptions.BuildArgs = append(b.BuildDockerfileOptions.BuildArgs, args...) +} + +func (b *DockerfileStageBuilder) AppendAddHost(addHost ...string) { + b.BuildDockerfileOptions.AddHost = append(b.BuildDockerfileOptions.AddHost, addHost...) +} + +func (b *DockerfileStageBuilder) SetNetwork(network string) { + b.BuildDockerfileOptions.Network = network +} + +func (b *DockerfileStageBuilder) SetSSH(ssh string) { + b.BuildDockerfileOptions.SSH = ssh +} + +func (b *DockerfileStageBuilder) AppendLabels(labels ...string) { + b.BuildDockerfileOptions.Labels = append(b.BuildDockerfileOptions.Labels, labels...) +} + +func (b *DockerfileStageBuilder) SetContextArchivePath(contextArchivePath string) { + b.ContextArchivePath = contextArchivePath +} diff --git a/pkg/container_runtime/stage_builder/legacy_stapel_stage_builder.go b/pkg/container_runtime/stage_builder/legacy_stapel_stage_builder.go new file mode 100644 index 0000000000..0ab4e1776e --- /dev/null +++ b/pkg/container_runtime/stage_builder/legacy_stapel_stage_builder.go @@ -0,0 +1,37 @@ +package stage_builder + +import ( + "context" + + "github.com/werf/werf/pkg/container_runtime" +) + +type LegacyStapelStageBuilderInterface interface { + Container() container_runtime.LegacyContainer + BuilderContainer() container_runtime.LegacyBuilderContainer + Build(ctx context.Context, opts container_runtime.BuildOptions) error +} + +type LegacyStapelStageBuilder struct { + ContainerRuntime container_runtime.ContainerRuntime + Image container_runtime.LegacyImageInterface +} + +func NewLegacyStapelStageBuilder(containerRuntime container_runtime.ContainerRuntime, image container_runtime.LegacyImageInterface) *LegacyStapelStageBuilder { + return &LegacyStapelStageBuilder{ + ContainerRuntime: containerRuntime, + Image: image, + } +} + +func (builder *LegacyStapelStageBuilder) Container() container_runtime.LegacyContainer { + return builder.Image.Container() +} + +func (builder *LegacyStapelStageBuilder) BuilderContainer() container_runtime.LegacyBuilderContainer { + return builder.Image.BuilderContainer() +} + +func (builder *LegacyStapelStageBuilder) Build(ctx context.Context, opts container_runtime.BuildOptions) error { + return builder.Image.Build(ctx, opts) +} diff --git a/pkg/container_runtime/stage_builder/stage_builder.go b/pkg/container_runtime/stage_builder/stage_builder.go new file mode 100644 index 0000000000..eb1e4b7357 --- /dev/null +++ b/pkg/container_runtime/stage_builder/stage_builder.go @@ -0,0 +1,52 @@ +package stage_builder + +import "github.com/werf/werf/pkg/container_runtime" + +type StageBuilderInterface interface { + StapelStageBuilder() StapelStageBuilderInterface + DockerfileStageBuilder() DockerfileStageBuilderInterface + LegacyStapelStageBuilder() LegacyStapelStageBuilderInterface +} + +type StageBuilder struct { + ContainerRuntime container_runtime.ContainerRuntime + FromImage container_runtime.ImageInterface + Image container_runtime.LegacyImageInterface // TODO: use ImageInterface + + dockerfileStageBuilder *DockerfileStageBuilder + stapelStageBuilder *StapelStageBuilder +} + +func (stageBuilder *StageBuilder) GetDockerfileStageBuilderImplementation() *DockerfileStageBuilder { + return stageBuilder.dockerfileStageBuilder +} + +func (stageBuilder *StageBuilder) GetStapelStageBuilderImplementation() *StapelStageBuilder { + return stageBuilder.stapelStageBuilder +} + +func NewStageBuilder(containerRuntime container_runtime.ContainerRuntime, fromImage container_runtime.ImageInterface, image container_runtime.LegacyImageInterface) *StageBuilder { + return &StageBuilder{ + ContainerRuntime: containerRuntime, + FromImage: fromImage, + Image: image, + } +} + +func (stageBuilder *StageBuilder) StapelStageBuilder() StapelStageBuilderInterface { + if stageBuilder.stapelStageBuilder == nil { + stageBuilder.stapelStageBuilder = NewStapelStageBuilder(stageBuilder.ContainerRuntime, stageBuilder.FromImage, stageBuilder.Image) + } + return stageBuilder.stapelStageBuilder +} + +func (stageBuilder *StageBuilder) LegacyStapelStageBuilder() LegacyStapelStageBuilderInterface { + return NewLegacyStapelStageBuilder(stageBuilder.ContainerRuntime, stageBuilder.Image) +} + +func (stageBuilder *StageBuilder) DockerfileStageBuilder() DockerfileStageBuilderInterface { + if stageBuilder.dockerfileStageBuilder == nil { + stageBuilder.dockerfileStageBuilder = NewDockerfileStageBuilder(stageBuilder.ContainerRuntime, stageBuilder.Image) + } + return stageBuilder.dockerfileStageBuilder +} diff --git a/pkg/container_runtime/stage_builder/stapel_stage_builder.go b/pkg/container_runtime/stage_builder/stapel_stage_builder.go new file mode 100644 index 0000000000..719d28abdc --- /dev/null +++ b/pkg/container_runtime/stage_builder/stapel_stage_builder.go @@ -0,0 +1,80 @@ +package stage_builder + +import ( + "context" + "fmt" + + "github.com/werf/werf/pkg/container_runtime" +) + +type StapelStageBuilderInterface interface { + AddLabels(map[string]string) StapelStageBuilderInterface + AddBuildVolumes(volumes ...string) StapelStageBuilderInterface + AddPrepareContainerActions(action ...container_runtime.PrepareContainerAction) StapelStageBuilderInterface + AddUserCommands(commands ...string) StapelStageBuilderInterface + + Build(ctx context.Context, opts container_runtime.BuildOptions) error +} + +type StapelStageBuilder struct { + ContainerRuntime container_runtime.ContainerRuntime + FromImage container_runtime.ImageInterface + Image container_runtime.ImageInterface + + labels []string + buildVolumes []string + prepareContainerActions []container_runtime.PrepareContainerAction + userCommands []string +} + +func NewStapelStageBuilder(containerRuntime container_runtime.ContainerRuntime, fromImage, image container_runtime.ImageInterface) *StapelStageBuilder { + return &StapelStageBuilder{ + ContainerRuntime: containerRuntime, + FromImage: fromImage, + Image: image, + } +} + +func (builder *StapelStageBuilder) Build(ctx context.Context, opts container_runtime.BuildOptions) error { + // TODO: support introspect options + + builtID, err := builder.ContainerRuntime.BuildStapelStage(ctx, builder.FromImage.Name(), container_runtime.BuildStapelStageOpts{ + BuildVolumes: builder.buildVolumes, + Labels: builder.labels, + UserCommands: builder.userCommands, + PrepareContainerActions: builder.prepareContainerActions, + }) + if err != nil { + return fmt.Errorf("error building stapel stage with %s: %s", builder.ContainerRuntime.String(), err) + } + + builder.Image.SetBuiltID(builtID) + + return nil +} + +func (builder *StapelStageBuilder) AddLabels(labels map[string]string) StapelStageBuilderInterface { + for k, v := range labels { + builder.labels = append(builder.labels, fmt.Sprintf("%s=%s", k, v)) + } + + return builder +} + +func (builder *StapelStageBuilder) AddBuildVolumes(volumes ...string) StapelStageBuilderInterface { + builder.buildVolumes = append(builder.buildVolumes, volumes...) + + return builder +} + +func (builder *StapelStageBuilder) AddPrepareContainerActions(actions ...container_runtime.PrepareContainerAction) StapelStageBuilderInterface { + builder.prepareContainerActions = append(builder.prepareContainerActions, actions...) + + return builder +} + +func (builder *StapelStageBuilder) AddUserCommands(commands ...string) StapelStageBuilderInterface { + builder.userCommands = append(builder.userCommands, commands...) + + return builder +} diff --git a/pkg/container_runtime/utils.go b/pkg/container_runtime/utils.go index 602acef706..d5c77c5929 100644 --- a/pkg/container_runtime/utils.go +++ b/pkg/container_runtime/utils.go @@ -15,7 +15,7 @@ var ( logImageInfoFormat = fmt.Sprintf("%%%ds: %%s\n", logImageInfoLeftPartWidth) ) -func debug() bool { +func Debug() bool { return os.Getenv("WERF_CONTAINER_RUNTIME_DEBUG") == "1" } diff --git a/pkg/storage/repo_stages_storage.go b/pkg/storage/repo_stages_storage.go index 4cc81e3b9c..8428ccfa4c 100644 --- a/pkg/storage/repo_stages_storage.go +++ b/pkg/storage/repo_stages_storage.go @@ -478,6 +478,7 @@ func (storage *RepoStagesStorage) FetchImage(ctx context.Context, img container_ } // FIXME(stapel-to-buildah): use ImageInterface instead of LegacyImageInterface +// FIXME(stapel-to-buildah): possible optimization would be to push buildah container directly into registry wihtout committing a local image func (storage *RepoStagesStorage) StoreImage(ctx context.Context, img container_runtime.LegacyImageInterface) error { if img.GetBuiltID() != "" { if err := storage.ContainerRuntime.Tag(ctx, img.GetBuiltID(), img.Name(), container_runtime.TagOpts{}); err != nil {