From 62b2181cf86e730de5996651c3e7d402dfb6ddc9 Mon Sep 17 00:00:00 2001 From: Timofey Kirillov Date: Mon, 10 Oct 2022 16:11:41 +0300 Subject: [PATCH] feat(staged-dockerfile): refactored conveyor, debug container backend staged dockerfile builder * Implemented test instruction building using new staged-dockerfile building method of container backend. * Refactored conveyor so that new builder now correctly coupled to the existing building mechanics. refs https://github.com/werf/werf/issues/2215 Signed-off-by: Timofey Kirillov --- pkg/build/build_phase.go | 54 +++----- pkg/build/conveyor.go | 32 ++++- pkg/build/image/common.go | 15 --- pkg/build/image/conveyor.go | 3 +- pkg/build/image/dockerfile.go | 16 ++- pkg/build/image/image.go | 125 +++++++++++------- pkg/build/image/stapel.go | 20 ++- pkg/build/stage/dependencies_test.go | 2 +- .../dockerfile_instruction.go | 22 ++- pkg/build/stage/dockerfile_instruction/run.go | 7 +- pkg/build/stage/full_dockerfile_test.go | 4 +- pkg/build/stage/git_mapping_test.go | 2 +- pkg/build/stage/stage_image.go | 4 +- pkg/build/stages_iterator.go | 14 +- .../build_stapel_stage_options.go | 9 -- pkg/container_backend/buildah_backend.go | 71 ++++++---- .../docker_server_backend.go | 5 +- .../dockerfile_instructions.go} | 6 +- pkg/container_backend/interface.go | 6 +- .../perf_check_container_backend.go | 9 +- .../stage_builder/dockerfile_stage_builder.go | 16 +-- .../stage_builder/stage_builder.go | 10 +- .../stage_builder/stapel_stage_builder.go | 10 +- 23 files changed, 257 insertions(+), 205 deletions(-) delete mode 100644 pkg/build/image/common.go rename pkg/{dockerfile/instructions.go => container_backend/dockerfile_instructions.go} (94%) diff --git a/pkg/build/build_phase.go b/pkg/build/build_phase.go index 2b5d15f277..176e89befd 100644 --- a/pkg/build/build_phase.go +++ b/pkg/build/build_phase.go @@ -451,7 +451,7 @@ func (phase *BuildPhase) onImageStage(ctx context.Context, img *image.Image, stg } // Will build a new stage - i := phase.Conveyor.GetOrCreateStageImage(extractLegacyStageImage(phase.StagesIterator.GetPrevImage(img, stg)), uuid.New().String()) + i := phase.Conveyor.GetOrCreateStageImage(uuid.New().String(), phase.StagesIterator.GetPrevImage(img, stg), stg, img) stg.SetStageImage(i) if err := phase.fetchBaseImageForStage(ctx, img, stg); err != nil { @@ -502,7 +502,7 @@ func (phase *BuildPhase) findAndFetchStageFromSecondaryStagesStorage(ctx context if copiedStageDesc, err := storageManager.CopySuitableByDigestStage(ctx, secondaryStageDesc, secondaryStagesStorage, storageManager.GetStagesStorage(), phase.Conveyor.ContainerBackend); err != nil { return fmt.Errorf("unable to copy suitable stage %s from %s to %s: %w", secondaryStageDesc.StageID.String(), secondaryStagesStorage.String(), storageManager.GetStagesStorage().String(), err) } else { - i := phase.Conveyor.GetOrCreateStageImage(extractLegacyStageImage(phase.StagesIterator.GetPrevImage(img, stg)), copiedStageDesc.Info.Name) + i := phase.Conveyor.GetOrCreateStageImage(copiedStageDesc.Info.Name, phase.StagesIterator.GetPrevImage(img, stg), stg, img) i.Image.SetStageDescription(copiedStageDesc) stg.SetStageImage(i) @@ -547,27 +547,16 @@ ScanSecondaryStagesStorageList: } func (phase *BuildPhase) fetchBaseImageForStage(ctx context.Context, img *image.Image, stg stage.Interface) error { - switch { - case stg.Name() == "from": + if stg.HasPrevStage() { + return phase.Conveyor.StorageManager.FetchStage(ctx, phase.Conveyor.ContainerBackend, phase.StagesIterator.PrevBuiltStage) + } else { if err := img.FetchBaseImage(ctx); err != nil { - return fmt.Errorf("unable to fetch base image %s for stage %s: %w", img.GetBaseImage().Image.Name(), stg.LogDetailedName(), err) + return fmt.Errorf("unable to fetch base image %s for stage %s: %w", img.GetBaseStageImage().Image.Name(), stg.LogDetailedName(), err) } - case stg.Name() == "dockerfile": - return nil - case stg.HasPrevStage(): - return phase.Conveyor.StorageManager.FetchStage(ctx, phase.Conveyor.ContainerBackend, phase.StagesIterator.PrevBuiltStage) } - return nil } -func extractLegacyStageImage(stageImage *stage.StageImage) *container_backend.LegacyStageImage { - if stageImage == nil || stageImage.Image == nil { - return nil - } - return stageImage.Image.(*container_backend.LegacyStageImage) -} - func (phase *BuildPhase) calculateStage(ctx context.Context, img *image.Image, stg stage.Interface) (bool, func(), error) { // FIXME(stapel-to-buildah): store StageImage-s everywhere in stage and build pkgs stageDependencies, err := stg.GetDependencies(ctx, phase.Conveyor, phase.Conveyor.ContainerBackend, phase.StagesIterator.GetPrevImage(img, stg), phase.StagesIterator.GetPrevBuiltImage(img, stg)) @@ -597,7 +586,7 @@ func (phase *BuildPhase) calculateStage(ctx context.Context, img *image.Image, s if stageDesc, err := storageManager.SelectSuitableStage(ctx, phase.Conveyor, stg, stages); err != nil { return false, phase.Conveyor.GetStageDigestMutex(stg.GetDigest()).Unlock, err } else if stageDesc != nil { - i := phase.Conveyor.GetOrCreateStageImage(extractLegacyStageImage(phase.StagesIterator.GetPrevImage(img, stg)), stageDesc.Info.Name) + i := phase.Conveyor.GetOrCreateStageImage(stageDesc.Info.Name, phase.StagesIterator.GetPrevImage(img, stg), stg, img) i.Image.SetStageDescription(stageDesc) stg.SetStageImage(i) foundSuitableStage = true @@ -630,19 +619,7 @@ func (phase *BuildPhase) prepareStageInstructions(ctx context.Context, img *imag imagePkg.WerfStageContentDigestLabel: stg.GetContentDigest(), } - switch stg.(type) { - case *stage.FullDockerfileStage: - var labels []string - for key, value := range serviceLabels { - labels = append(labels, fmt.Sprintf("%s=%v", key, value)) - } - stageImage.Builder.DockerfileBuilder().AppendLabels(labels...) - - phase.Conveyor.AppendOnTerminateFunc(func() error { - return stageImage.Builder.DockerfileBuilder().Cleanup(ctx) - }) - - default: + if stg.IsStapelStage() { if phase.Conveyor.UseLegacyStapelBuilder(phase.Conveyor.ContainerBackend) { stageImage.Builder.LegacyStapelStageBuilder().Container().ServiceCommitChangeOptions().AddLabel(serviceLabels) } else { @@ -688,6 +665,19 @@ func (phase *BuildPhase) prepareStageInstructions(ctx context.Context, img *imag } else { stageImage.Builder.StapelStageBuilder().AddEnvs(commitEnvs) } + } else if _, ok := stg.(*stage.FullDockerfileStage); ok { + var labels []string + for key, value := range serviceLabels { + labels = append(labels, fmt.Sprintf("%s=%v", key, value)) + } + stageImage.Builder.DockerfileBuilder().AppendLabels(labels...) + + phase.Conveyor.AppendOnTerminateFunc(func() error { + return stageImage.Builder.DockerfileBuilder().Cleanup(ctx) + }) + } else { + stageImage.Builder.DockerfileStageBuilder().AppendPostCommands(&container_backend.InstructionLabel{Labels: serviceLabels}) + // staged dockerfile } err := stg.PrepareImage(ctx, phase.Conveyor, phase.Conveyor.ContainerBackend, phase.StagesIterator.GetPrevBuiltImage(img, stg), stageImage) @@ -789,7 +779,7 @@ func (phase *BuildPhase) atomicBuildStageImage(ctx context.Context, img *image.I stg.LogDetailedName(), stg.GetDigest(), stageDesc.Info.Name, ) - i := phase.Conveyor.GetOrCreateStageImage(extractLegacyStageImage(phase.StagesIterator.GetPrevImage(img, stg)), stageDesc.Info.Name) + i := phase.Conveyor.GetOrCreateStageImage(stageDesc.Info.Name, phase.StagesIterator.GetPrevImage(img, stg), stg, img) i.Image.SetStageDescription(stageDesc) stg.SetStageImage(i) diff --git a/pkg/build/conveyor.go b/pkg/build/conveyor.go index 86b89ca75e..40be142b9c 100644 --- a/pkg/build/conveyor.go +++ b/pkg/build/conveyor.go @@ -632,16 +632,34 @@ func (c *Conveyor) SetStageImage(stageImage *stage.StageImage) { c.stageImages[stageImage.Image.Name()] = stageImage } -func (c *Conveyor) GetOrCreateStageImage(fromImage *container_backend.LegacyStageImage, name string) *stage.StageImage { - if img := c.GetStageImage(name); img != nil { - return img +func extractLegacyStageImage(stageImage *stage.StageImage) *container_backend.LegacyStageImage { + if stageImage == nil || stageImage.Image == nil { + return nil + } + return stageImage.Image.(*container_backend.LegacyStageImage) +} + +func (c *Conveyor) GetOrCreateStageImage(name string, prevStageImage *stage.StageImage, stg stage.Interface, img *image.Image) *stage.StageImage { + if stageImage := c.GetStageImage(name); stageImage != nil { + return stageImage } - i := container_backend.NewLegacyStageImage(fromImage, name, c.ContainerBackend) - img := stage.NewStageImage(c.ContainerBackend, fromImage, i) + i := container_backend.NewLegacyStageImage(extractLegacyStageImage(prevStageImage), name, c.ContainerBackend) + + var baseImage string + if stg != nil { + if stg.HasPrevStage() { + baseImage = prevStageImage.Image.Name() + } else if stg.IsStapelStage() && stg.Name() == "from" { + baseImage = prevStageImage.Image.Name() + } else { + baseImage = img.GetBaseImageReference() + } + } - c.SetStageImage(img) - return img + stageImage := stage.NewStageImage(c.ContainerBackend, baseImage, i) + c.SetStageImage(stageImage) + return stageImage } func (c *Conveyor) GetImage(name string) *image.Image { diff --git a/pkg/build/image/common.go b/pkg/build/image/common.go deleted file mode 100644 index 65489886ef..0000000000 --- a/pkg/build/image/common.go +++ /dev/null @@ -1,15 +0,0 @@ -package image - -import "context" - -func handleImageFromName(ctx context.Context, from string, fromLatest bool, image *Image) error { - image.baseImageName = from - - if fromLatest { - if _, err := image.getFromBaseImageIdFromRegistry(ctx, image.baseImageName); err != nil { - return err - } - } - - return nil -} diff --git a/pkg/build/image/conveyor.go b/pkg/build/image/conveyor.go index ee13411cc5..cbe278926f 100644 --- a/pkg/build/image/conveyor.go +++ b/pkg/build/image/conveyor.go @@ -4,7 +4,6 @@ import ( "sync" "github.com/werf/werf/pkg/build/stage" - "github.com/werf/werf/pkg/container_backend" "github.com/werf/werf/pkg/git_repo" ) @@ -12,7 +11,7 @@ type Conveyor interface { stage.Conveyor GetImage(name string) *Image - GetOrCreateStageImage(fromImage *container_backend.LegacyStageImage, name string) *stage.StageImage + GetOrCreateStageImage(name string, prevStageImage *stage.StageImage, stg stage.Interface, img *Image) *stage.StageImage IsBaseImagesRepoIdsCacheExist(key string) bool GetBaseImagesRepoIdsCache(key string) string diff --git a/pkg/build/image/dockerfile.go b/pkg/build/image/dockerfile.go index b3b1d77154..9e7de86312 100644 --- a/pkg/build/image/dockerfile.go +++ b/pkg/build/image/dockerfile.go @@ -14,6 +14,7 @@ import ( "github.com/werf/werf/pkg/build/stage" "github.com/werf/werf/pkg/build/stage/dockerfile_instruction" "github.com/werf/werf/pkg/config" + "github.com/werf/werf/pkg/container_backend" "github.com/werf/werf/pkg/dockerfile" "github.com/werf/werf/pkg/path_matcher" "github.com/werf/werf/pkg/util" @@ -70,12 +71,18 @@ func mapDockerfileToImagesSets(ctx context.Context, cfg *dockerfile.Dockerfile, } { - img := NewImage("test", ImageOptions{ + // TODO parse FROM instruction properly, set correct BaseImageReference here + + img, err := NewImage(ctx, "test", ImageFromRegistryAsBaseImage, ImageOptions{ IsDockerfileImage: true, CommonImageOptions: opts, + BaseImageReference: "ubuntu:22.04", }) + if err != nil { + return nil, fmt.Errorf("unable to create image %q: %w", "test", err) + } - img.stages = append(img.stages, dockerfile_instruction.NewRun(&dockerfile.InstructionRun{Command: []string{"ls", "/"}}, nil, false, &stage.BaseStageOptions{ + img.stages = append(img.stages, dockerfile_instruction.NewRun(&container_backend.InstructionRun{Command: []string{"ls", "/"}}, nil, false, &stage.BaseStageOptions{ ImageName: img.Name, ImageTmpDir: img.TmpDir, ContainerWerfDir: img.ContainerWerfDir, @@ -89,10 +96,13 @@ func mapDockerfileToImagesSets(ctx context.Context, cfg *dockerfile.Dockerfile, } func mapLegacyDockerfileToImage(ctx context.Context, dockerfileImageConfig *config.ImageFromDockerfile, opts CommonImageOptions) (*Image, error) { - img := NewImage(dockerfileImageConfig.Name, ImageOptions{ + img, err := NewImage(ctx, dockerfileImageConfig.Name, NoBaseImage, ImageOptions{ CommonImageOptions: opts, IsDockerfileImage: true, }) + if err != nil { + return nil, fmt.Errorf("unable to create image %q: %w", dockerfileImageConfig.Name, err) + } for _, contextAddFile := range dockerfileImageConfig.ContextAddFiles { relContextAddFile := filepath.Join(dockerfileImageConfig.Context, contextAddFile) diff --git a/pkg/build/image/image.go b/pkg/build/image/image.go index 085b187fc4..997d1034bf 100644 --- a/pkg/build/image/image.go +++ b/pkg/build/image/image.go @@ -23,6 +23,7 @@ type BaseImageType string const ( ImageFromRegistryAsBaseImage BaseImageType = "ImageFromRegistryBaseImage" StageAsBaseImage BaseImageType = "StageBaseImage" + NoBaseImage BaseImageType = "NoBaseImage" ) type CommonImageOptions struct { @@ -39,15 +40,37 @@ type CommonImageOptions struct { type ImageOptions struct { CommonImageOptions IsArtifact, IsDockerfileImage bool + + BaseImageReference string + BaseImageName string + FetchLatestBaseImage bool } -func NewImage(name string, opts ImageOptions) *Image { - return &Image{ +func NewImage(ctx context.Context, name string, baseImageType BaseImageType, opts ImageOptions) (*Image, error) { + switch baseImageType { + case NoBaseImage, ImageFromRegistryAsBaseImage, StageAsBaseImage: + default: + panic(fmt.Sprintf("unknown opts.BaseImageType %q", baseImageType)) + } + + i := &Image{ Name: name, CommonImageOptions: opts.CommonImageOptions, IsArtifact: opts.IsArtifact, IsDockerfileImage: opts.IsDockerfileImage, + + baseImageType: baseImageType, + baseImageReference: opts.BaseImageReference, + baseImageName: opts.BaseImageName, + } + + if opts.FetchLatestBaseImage { + if _, err := i.getFromBaseImageIdFromRegistry(ctx, i.baseImageReference); err != nil { + return nil, fmt.Errorf("error fetching base image id from registry: %w", err) + } } + + return i, nil } type Image struct { @@ -57,18 +80,18 @@ type Image struct { IsDockerfileImage bool Name string - baseImageName string - baseImageImageName string - baseImageRepoId string - stages []stage.Interface lastNonEmptyStage stage.Interface contentDigest string rebuilt bool - baseImageType BaseImageType + baseImageType BaseImageType + baseImageReference string + baseImageName string + + baseImageRepoId string + baseStageImage *stage.StageImage stageAsBaseImage stage.Interface - baseImage *stage.StageImage } func (i *Image) LogName() string { @@ -161,37 +184,45 @@ func (i *Image) GetRebuilt() bool { } func (i *Image) SetupBaseImage() { - if i.baseImageImageName != "" { - i.baseImageType = StageAsBaseImage - i.stageAsBaseImage = i.Conveyor.GetImage(i.baseImageImageName).GetLastNonEmptyStage() - i.baseImage = i.stageAsBaseImage.GetStageImage() - } else { - i.baseImageType = ImageFromRegistryAsBaseImage - i.baseImage = i.Conveyor.GetOrCreateStageImage(nil, i.baseImageName) + switch i.baseImageType { + case StageAsBaseImage: + i.stageAsBaseImage = i.Conveyor.GetImage(i.baseImageName).GetLastNonEmptyStage() + i.baseImageReference = i.stageAsBaseImage.GetStageImage().Image.Name() + i.baseStageImage = i.stageAsBaseImage.GetStageImage() + case ImageFromRegistryAsBaseImage: + i.baseStageImage = i.Conveyor.GetOrCreateStageImage(i.baseImageReference, nil, nil, i) + case NoBaseImage: + default: + panic(fmt.Sprintf("unknown base image type %q", i.baseImageType)) } } -func (i *Image) GetBaseImage() *stage.StageImage { - return i.baseImage +// TODO(staged-dockerfile): this is only for compatibility with stapel-builder logic, and this should be unified with new staged-dockerfile logic +func (i *Image) GetBaseStageImage() *stage.StageImage { + return i.baseStageImage +} + +func (i *Image) GetBaseImageReference() string { + return i.baseImageReference } func (i *Image) FetchBaseImage(ctx context.Context) error { switch i.baseImageType { case ImageFromRegistryAsBaseImage: - if info, err := i.ContainerBackend.GetImageInfo(ctx, i.baseImage.Image.Name(), container_backend.GetImageInfoOpts{}); err != nil { - return fmt.Errorf("unable to inspect local image %s: %w", i.baseImage.Image.Name(), err) + if info, err := i.ContainerBackend.GetImageInfo(ctx, i.baseStageImage.Image.Name(), container_backend.GetImageInfoOpts{}); err != nil { + return fmt.Errorf("unable to inspect local image %s: %w", i.baseStageImage.Image.Name(), err) } else if info != nil { // TODO: do not use container_backend.LegacyStageImage for base image - i.baseImage.Image.SetStageDescription(&image.StageDescription{ + i.baseStageImage.Image.SetStageDescription(&image.StageDescription{ StageID: nil, // this is not a stage actually, TODO Info: info, }) - baseImageRepoId, err := i.getFromBaseImageIdFromRegistry(ctx, i.baseImage.Image.Name()) + baseImageRepoId, err := i.getFromBaseImageIdFromRegistry(ctx, i.baseStageImage.Image.Name()) if baseImageRepoId == info.ID || err != nil { if err != nil { - logboek.Context(ctx).Warn().LogF("WARNING: cannot get base image id (%s): %s\n", i.baseImage.Image.Name(), err) - logboek.Context(ctx).Warn().LogF("WARNING: using existing image %s without pull\n", i.baseImage.Image.Name()) + logboek.Context(ctx).Warn().LogF("WARNING: cannot get base image id (%s): %s\n", i.baseStageImage.Image.Name(), err) + logboek.Context(ctx).Warn().LogF("WARNING: using existing image %s without pull\n", i.baseStageImage.Image.Name()) logboek.Context(ctx).Warn().LogOptionalLn() } @@ -199,62 +230,64 @@ func (i *Image) FetchBaseImage(ctx context.Context) error { } } - if err := logboek.Context(ctx).Default().LogProcess("Pulling base image %s", i.baseImage.Image.Name()). + if err := logboek.Context(ctx).Default().LogProcess("Pulling base image %s", i.baseStageImage.Image.Name()). Options(func(options types.LogProcessOptionsInterface) { options.Style(style.Highlight()) }). DoError(func() error { - return i.ContainerBackend.PullImageFromRegistry(ctx, i.baseImage.Image) + return i.ContainerBackend.PullImageFromRegistry(ctx, i.baseStageImage.Image) }); err != nil { return err } - info, err := i.ContainerBackend.GetImageInfo(ctx, i.baseImage.Image.Name(), container_backend.GetImageInfoOpts{}) + info, err := i.ContainerBackend.GetImageInfo(ctx, i.baseStageImage.Image.Name(), container_backend.GetImageInfoOpts{}) if err != nil { - return fmt.Errorf("unable to inspect local image %s: %w", i.baseImage.Image.Name(), err) + return fmt.Errorf("unable to inspect local image %s: %w", i.baseStageImage.Image.Name(), err) } if info == nil { - return fmt.Errorf("unable to inspect local image %s after successful pull: image is not exists", i.baseImage.Image.Name()) + return fmt.Errorf("unable to inspect local image %s after successful pull: image is not exists", i.baseStageImage.Image.Name()) } - i.baseImage.Image.SetStageDescription(&image.StageDescription{ + i.baseStageImage.Image.SetStageDescription(&image.StageDescription{ StageID: nil, // this is not a stage actually, TODO Info: info, }) + + return nil case StageAsBaseImage: - if err := i.StorageManager.FetchStage(ctx, i.ContainerBackend, i.stageAsBaseImage); err != nil { - return err - } + return i.StorageManager.FetchStage(ctx, i.ContainerBackend, i.stageAsBaseImage) + + case NoBaseImage: + return nil + default: panic(fmt.Sprintf("unknown base image type %q", i.baseImageType)) } - - return nil } -func (i *Image) getFromBaseImageIdFromRegistry(ctx context.Context, baseImageName string) (string, error) { - i.Conveyor.GetServiceRWMutex("baseImagesRepoIdsCache" + baseImageName).Lock() - defer i.Conveyor.GetServiceRWMutex("baseImagesRepoIdsCache" + baseImageName).Unlock() +func (i *Image) getFromBaseImageIdFromRegistry(ctx context.Context, reference string) (string, error) { + i.Conveyor.GetServiceRWMutex("baseImagesRepoIdsCache" + reference).Lock() + defer i.Conveyor.GetServiceRWMutex("baseImagesRepoIdsCache" + reference).Unlock() switch { case i.baseImageRepoId != "": return i.baseImageRepoId, nil - case i.Conveyor.IsBaseImagesRepoIdsCacheExist(baseImageName): - i.baseImageRepoId = i.Conveyor.GetBaseImagesRepoIdsCache(baseImageName) + case i.Conveyor.IsBaseImagesRepoIdsCacheExist(reference): + i.baseImageRepoId = i.Conveyor.GetBaseImagesRepoIdsCache(reference) return i.baseImageRepoId, nil - case i.Conveyor.IsBaseImagesRepoErrCacheExist(baseImageName): - return "", i.Conveyor.GetBaseImagesRepoErrCache(baseImageName) + case i.Conveyor.IsBaseImagesRepoErrCacheExist(reference): + return "", i.Conveyor.GetBaseImagesRepoErrCache(reference) } var fetchedBaseRepoImage *image.Info - processMsg := fmt.Sprintf("Trying to get from base image id from registry (%s)", baseImageName) + processMsg := fmt.Sprintf("Trying to get from base image id from registry (%s)", reference) if err := logboek.Context(ctx).Info().LogProcessInline(processMsg).DoError(func() error { var fetchImageIdErr error - fetchedBaseRepoImage, fetchImageIdErr = docker_registry.API().GetRepoImage(ctx, baseImageName) + fetchedBaseRepoImage, fetchImageIdErr = docker_registry.API().GetRepoImage(ctx, reference) if fetchImageIdErr != nil { - i.Conveyor.SetBaseImagesRepoErrCache(baseImageName, fetchImageIdErr) - return fmt.Errorf("can not get base image id from registry (%s): %w", baseImageName, fetchImageIdErr) + i.Conveyor.SetBaseImagesRepoErrCache(reference, fetchImageIdErr) + return fmt.Errorf("can not get base image id from registry (%s): %w", reference, fetchImageIdErr) } return nil @@ -263,7 +296,7 @@ func (i *Image) getFromBaseImageIdFromRegistry(ctx context.Context, baseImageNam } i.baseImageRepoId = fetchedBaseRepoImage.ID - i.Conveyor.SetBaseImagesRepoIdsCache(baseImageName, i.baseImageRepoId) + i.Conveyor.SetBaseImagesRepoIdsCache(reference, i.baseImageRepoId) return i.baseImageRepoId, nil } diff --git a/pkg/build/image/stapel.go b/pkg/build/image/stapel.go index 8b576099ab..3a2c9ec1bc 100644 --- a/pkg/build/image/stapel.go +++ b/pkg/build/image/stapel.go @@ -31,21 +31,27 @@ func mapStapelConfigToImage(ctx context.Context, metaConfig *config.Meta, stapel imageArtifact := stapelImageConfig.IsArtifact() from, fromImageName, fromLatest := getFromFields(imageBaseConfig) - image := NewImage(imageName, ImageOptions{ + imageOpts := ImageOptions{ CommonImageOptions: opts, IsArtifact: imageArtifact, - }) + } + var baseImageType BaseImageType if from != "" { - if err := handleImageFromName(ctx, from, fromLatest, image); err != nil { - return nil, err - } + baseImageType = ImageFromRegistryAsBaseImage + imageOpts.BaseImageReference = from + imageOpts.FetchLatestBaseImage = fromLatest } else { - image.baseImageImageName = fromImageName + baseImageType = StageAsBaseImage + imageOpts.BaseImageName = fromImageName } - err := initStages(ctx, image, metaConfig, stapelImageConfig, opts) + image, err := NewImage(ctx, imageName, baseImageType, imageOpts) if err != nil { + return nil, fmt.Errorf("unable to create image %q: %w", imageName, err) + } + + if err := initStages(ctx, image, metaConfig, stapelImageConfig, opts); err != nil { return nil, err } diff --git a/pkg/build/stage/dependencies_test.go b/pkg/build/stage/dependencies_test.go index 22cf191f25..45bc821683 100644 --- a/pkg/build/stage/dependencies_test.go +++ b/pkg/build/stage/dependencies_test.go @@ -24,7 +24,7 @@ var _ = Describe("DependenciesStage", func() { }) img := NewLegacyImageStub() - stageBuilder := stage_builder.NewStageBuilder(containerBackend, nil, img) + stageBuilder := stage_builder.NewStageBuilder(containerBackend, "", img) stageImage := &StageImage{ Image: img, Builder: stageBuilder, diff --git a/pkg/build/stage/dockerfile_instruction/dockerfile_instruction.go b/pkg/build/stage/dockerfile_instruction/dockerfile_instruction.go index 5bc8ec64b4..a0428d09db 100644 --- a/pkg/build/stage/dockerfile_instruction/dockerfile_instruction.go +++ b/pkg/build/stage/dockerfile_instruction/dockerfile_instruction.go @@ -1,5 +1,21 @@ package dockerfile_instruction -type DockerfileInstruction interface { - Name() string -} +import "github.com/werf/werf/pkg/build/stage" + +const ( + InstructionEnv stage.StageName = "ENV" + InstructionCopy stage.StageName = "COPY" + InstructionAdd stage.StageName = "ADD" + InstructionRun stage.StageName = "RUN" + InstructionEntrypoint stage.StageName = "ENTRYPOINT" + InstructionCmd stage.StageName = "CMD" + InstructionUser stage.StageName = "USER" + InstructionWorkdir stage.StageName = "WORKDIR" + InstructionExpose stage.StageName = "EXPOSE" + InstructionVolume stage.StageName = "VOLUME" + InstructionOnBuild stage.StageName = "ONBUILD" + InstructionStopSignal stage.StageName = "STOPSIGNAL" + InstructionShell stage.StageName = "SHELL" + InstructionHealthcheck stage.StageName = "HEALTHCHECK" + InstructionLabel stage.StageName = "LABEL" +) diff --git a/pkg/build/stage/dockerfile_instruction/run.go b/pkg/build/stage/dockerfile_instruction/run.go index b0c761252a..6149c5d050 100644 --- a/pkg/build/stage/dockerfile_instruction/run.go +++ b/pkg/build/stage/dockerfile_instruction/run.go @@ -6,18 +6,17 @@ import ( "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" "github.com/werf/werf/pkg/util" ) type Run struct { *Base - instruction *dockerfile.InstructionRun + instruction *container_backend.InstructionRun } -func NewRun(instruction *dockerfile.InstructionRun, dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *Run { +func NewRun(instruction *container_backend.InstructionRun, dependencies []*config.Dependency, hasPrevStage bool, opts *stage.BaseStageOptions) *Run { return &Run{ - Base: NewBase(stage.StageName(instruction.Name()), dependencies, hasPrevStage, opts), + Base: NewBase("RUN", dependencies, hasPrevStage, opts), instruction: instruction, } } diff --git a/pkg/build/stage/full_dockerfile_test.go b/pkg/build/stage/full_dockerfile_test.go index ab8363b964..6b62e0ba13 100644 --- a/pkg/build/stage/full_dockerfile_test.go +++ b/pkg/build/stage/full_dockerfile_test.go @@ -72,7 +72,7 @@ var _ = Describe("FullDockerfileStage", func() { stage := newTestFullDockerfileStage(data.DockerfileData, data.Target, data.BuildArgs, dockerStages, dockerMetaArgs, data.TestDependencies.Dependencies) img := NewLegacyImageStub() - stageBuilder := stage_builder.NewStageBuilder(containerBackend, nil, img) + stageBuilder := stage_builder.NewStageBuilder(containerBackend, "", img) stageImage := &StageImage{ Image: img, Builder: stageBuilder, @@ -331,7 +331,7 @@ RUN --mount=type=bind,from=build,source=/usr/local/test_project/dist,target=/usr containerBackend := NewContainerBackendMock() img := NewLegacyImageStub() - stageBuilder := stage_builder.NewStageBuilder(containerBackend, nil, img) + stageBuilder := stage_builder.NewStageBuilder(containerBackend, "", img) stageImage := &StageImage{ Image: img, Builder: stageBuilder, diff --git a/pkg/build/stage/git_mapping_test.go b/pkg/build/stage/git_mapping_test.go index d57592de36..1842d6d2f7 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(containerBackend, nil, prevBuiltImage) + img := stage.NewStageImage(containerBackend, "", prevBuiltImage) baseCommit, err := gitMapping.GetBaseCommitForPrevBuiltImage(ctx, c, img) Expect(err).To(Succeed()) diff --git a/pkg/build/stage/stage_image.go b/pkg/build/stage/stage_image.go index 7f0ddfb4f7..b91c27c100 100644 --- a/pkg/build/stage/stage_image.go +++ b/pkg/build/stage/stage_image.go @@ -10,9 +10,9 @@ type StageImage struct { Builder stage_builder.StageBuilderInterface } -func NewStageImage(containerBackend container_backend.ContainerBackend, fromImage container_backend.ImageInterface, image container_backend.LegacyImageInterface) *StageImage { +func NewStageImage(containerBackend container_backend.ContainerBackend, baseImage string, image container_backend.LegacyImageInterface) *StageImage { return &StageImage{ Image: image, - Builder: stage_builder.NewStageBuilder(containerBackend, fromImage, image), + Builder: stage_builder.NewStageBuilder(containerBackend, baseImage, image), } } diff --git a/pkg/build/stages_iterator.go b/pkg/build/stages_iterator.go index 7c9f4bf102..241363a15f 100644 --- a/pkg/build/stages_iterator.go +++ b/pkg/build/stages_iterator.go @@ -23,19 +23,21 @@ func NewStagesIterator(conveyor *Conveyor) *StagesIterator { } func (iterator *StagesIterator) GetPrevImage(img *build_image.Image, stg stage.Interface) *stage.StageImage { - if stg.Name() == "from" { - return img.GetBaseImage() - } else if iterator.PrevNonEmptyStage != nil { + if stg.HasPrevStage() { return iterator.PrevNonEmptyStage.GetStageImage() + } else if stg.IsStapelStage() && stg.Name() == "from" { + // TODO(staged-dockerfile): this is only for compatibility with stapel-builder logic, and this should be unified with new staged-dockerfile logic + return img.GetBaseStageImage() } return nil } func (iterator *StagesIterator) GetPrevBuiltImage(img *build_image.Image, stg stage.Interface) *stage.StageImage { - if stg.Name() == "from" { - return img.GetBaseImage() - } else if iterator.PrevBuiltStage != nil { + if stg.HasPrevStage() { return iterator.PrevBuiltStage.GetStageImage() + } else if stg.IsStapelStage() && stg.Name() == "from" { + // TODO(staged-dockerfile): this is only for compatibility with stapel-builder logic, and this should be unified with new staged-dockerfile logic + return img.GetBaseStageImage() } return nil } diff --git a/pkg/container_backend/build_stapel_stage_options.go b/pkg/container_backend/build_stapel_stage_options.go index 2cd4da0944..58686d5eda 100644 --- a/pkg/container_backend/build_stapel_stage_options.go +++ b/pkg/container_backend/build_stapel_stage_options.go @@ -10,8 +10,6 @@ type AddDataArchiveOptions struct { } type BuildStapelStageOptionsInterface interface { - SetBaseImage(baseImage string) BuildStapelStageOptionsInterface - AddLabels(labels map[string]string) BuildStapelStageOptionsInterface AddVolumes(volumes []string) BuildStapelStageOptionsInterface AddExpose(expose []string) BuildStapelStageOptionsInterface @@ -31,8 +29,6 @@ type BuildStapelStageOptionsInterface interface { } type BuildStapelStageOptions struct { - BaseImage string - Labels []string Volumes []string Expose []string @@ -91,11 +87,6 @@ type DependencyImportSpec struct { Group string } -func (opts *BuildStapelStageOptions) SetBaseImage(baseImage string) BuildStapelStageOptionsInterface { - opts.BaseImage = baseImage - return opts -} - func (opts *BuildStapelStageOptions) AddLabels(labels map[string]string) BuildStapelStageOptionsInterface { for k, v := range labels { opts.Labels = append(opts.Labels, fmt.Sprintf("%s=%s", k, v)) diff --git a/pkg/container_backend/buildah_backend.go b/pkg/container_backend/buildah_backend.go index 3c54060e7c..cf0c010e07 100644 --- a/pkg/container_backend/buildah_backend.go +++ b/pkg/container_backend/buildah_backend.go @@ -20,7 +20,6 @@ import ( copyrec "github.com/werf/copy-recurse" "github.com/werf/logboek" "github.com/werf/werf/pkg/buildah" - "github.com/werf/werf/pkg/dockerfile" "github.com/werf/werf/pkg/image" "github.com/werf/werf/pkg/path_matcher" "github.com/werf/werf/pkg/util" @@ -63,11 +62,16 @@ func (runtime *BuildahBackend) createContainers(ctx context.Context, images []st for _, img := range images { containerID := fmt.Sprintf("werf-%s", uuid.New().String()) + if img == "" { + panic("cannot start container for an empty image param") + } + _, err := runtime.buildah.FromCommand(ctx, containerID, img, buildah.FromCommandOpts(runtime.getBuildahCommonOpts(ctx, true))) if err != nil { return nil, fmt.Errorf("unable to create container using base image %q: %w", img, err) } + logboek.Context(ctx).Debug().LogF("Started container %q for image %q\n", containerID, img) res = append(res, &containerDesc{ImageName: img, Name: containerID}) } @@ -418,13 +422,14 @@ func (runtime *BuildahBackend) applyDependenciesImports(ctx context.Context, con return nil } -func (runtime *BuildahBackend) BuildDockerfileStage(ctx context.Context, image ImageInterface, contextTar io.ReadCloser, opts BuildDockerfileStageOptions, instructions ...any) (string, error) { +func (runtime *BuildahBackend) BuildDockerfileStage(ctx context.Context, baseImage string, opts BuildDockerfileStageOptions, instructions ...any) (string, error) { var container *containerDesc - if c, err := runtime.createContainers(ctx, []string{image.Name()}); err != nil { + if c, err := runtime.createContainers(ctx, []string{baseImage}); err != nil { return "", err } else { container = c[0] } + defer func() { if err := runtime.removeContainers(ctx, []*containerDesc{container}); err != nil { logboek.Context(ctx).Error().LogF("ERROR: unable to remove temporary build container: %s\n", err) @@ -443,111 +448,119 @@ func (runtime *BuildahBackend) BuildDockerfileStage(ctx context.Context, image I } }() - contextTmpDir, err := runtime.ExtractContext(contextTar) - if err != nil { - return "", fmt.Errorf("error extracting context: %w", err) - } - defer func() { - if err := os.RemoveAll(contextTmpDir); err != nil { - logboek.Context(ctx).Error().LogF("ERROR: unable to remove temporary context dir %s: %s\n", contextTmpDir, err) + var contextTmpDir string + if opts.ContextTar != nil { + var err error + + // TODO(staged-dockerfile): build-context object param + contextTmpDir, err = runtime.ExtractContext(opts.ContextTar) + if err != nil { + return "", fmt.Errorf("error extracting context: %w", err) } - }() - logboek.Context(ctx).Debug().LogF("Executing commands for build container %s\n", container.Name) + defer func() { + if err := os.RemoveAll(contextTmpDir); err != nil { + logboek.Context(ctx).Error().LogF("ERROR: unable to remove temporary context dir %s: %s\n", contextTmpDir, err) + } + }() + } + + logboek.Context(ctx).Debug().LogF("Executing commands for build container %s: %#v\n", container.Name, instructions) + for _, i := range instructions { switch instruction := i.(type) { - case dockerfile.InstructionLabel: + case *InstructionLabel: if err := runtime.buildah.Config(ctx, container.Name, buildah.ConfigOpts{ CommonOpts: runtime.getBuildahCommonOpts(ctx, true), Labels: instruction.LabelsAsList(), }); err != nil { return "", fmt.Errorf("error setting labels %v for container %s: %w", instruction.LabelsAsList(), container.Name, err) } - case dockerfile.InstructionExpose: + case *InstructionExpose: if err := runtime.buildah.Config(ctx, container.Name, buildah.ConfigOpts{ CommonOpts: runtime.getBuildahCommonOpts(ctx, true), Expose: instruction.Ports, }); err != nil { return "", fmt.Errorf("error setting exposed ports %v for container %s: %w", instruction.Ports, container.Name, err) } - case dockerfile.InstructionVolume: + case *InstructionVolume: if err := runtime.buildah.Config(ctx, container.Name, buildah.ConfigOpts{ CommonOpts: runtime.getBuildahCommonOpts(ctx, true), Volumes: instruction.Volumes, }); err != nil { return "", fmt.Errorf("error setting volumes %v for container %s: %w", instruction.Volumes, container.Name, err) } - case dockerfile.InstructionOnBuild: + case *InstructionOnBuild: if err := runtime.buildah.Config(ctx, container.Name, buildah.ConfigOpts{ CommonOpts: runtime.getBuildahCommonOpts(ctx, true), OnBuild: instruction.Instruction, }); err != nil { return "", fmt.Errorf("error setting onbuild %v for container %s: %w", instruction.Instruction, container.Name, err) } - case dockerfile.InstructionStopSignal: + case *InstructionStopSignal: if err := runtime.buildah.Config(ctx, container.Name, buildah.ConfigOpts{ CommonOpts: runtime.getBuildahCommonOpts(ctx, true), StopSignal: instruction.Signal, }); err != nil { return "", fmt.Errorf("error setting stop signal %v for container %s: %w", instruction.Signal, container.Name, err) } - case dockerfile.InstructionShell: + case *InstructionShell: if err := runtime.buildah.Config(ctx, container.Name, buildah.ConfigOpts{ CommonOpts: runtime.getBuildahCommonOpts(ctx, true), Shell: instruction.Shell, }); err != nil { return "", fmt.Errorf("error setting shell %v for container %s: %w", instruction.Shell, container.Name, err) } - case dockerfile.InstructionEnv: + case *InstructionEnv: if err := runtime.buildah.Config(ctx, container.Name, buildah.ConfigOpts{ CommonOpts: runtime.getBuildahCommonOpts(ctx, true), Envs: instruction.Envs, }); err != nil { return "", fmt.Errorf("error setting envs %v for container %s: %w", instruction.Envs, container.Name, err) } - case dockerfile.InstructionRun: + case *InstructionRun: if err := runtime.buildah.RunCommand(ctx, container.Name, instruction.Command, buildah.RunCommandOpts{ // FIXME(ilya-lesikov): should we suppress or not? CommonOpts: runtime.getBuildahCommonOpts(ctx, true), }); err != nil { return "", fmt.Errorf("error running command %v for container %s: %w", instruction.Command, container.Name, err) } - case dockerfile.InstructionCopy: + case *InstructionCopy: if err := runtime.buildah.Copy(ctx, container.Name, contextTmpDir, instruction.Src, instruction.Dst, buildah.CopyOpts{ CommonOpts: runtime.getBuildahCommonOpts(ctx, true), From: instruction.From, }); err != nil { return "", fmt.Errorf("error copying %v to %s for container %s: %w", instruction.Src, instruction.Dst, container.Name, err) } - case dockerfile.InstructionAdd: + case *InstructionAdd: if err := runtime.buildah.Add(ctx, container.Name, instruction.Src, instruction.Dst, buildah.AddOpts{ CommonOpts: runtime.getBuildahCommonOpts(ctx, true), ContextDir: contextTmpDir, }); err != nil { return "", fmt.Errorf("error adding %v to %s for container %s: %w", instruction.Src, instruction.Dst, container.Name, err) } - case dockerfile.InstructionUser: + case *InstructionUser: if err := runtime.buildah.Config(ctx, container.Name, buildah.ConfigOpts{ CommonOpts: runtime.getBuildahCommonOpts(ctx, true), User: instruction.User, }); err != nil { return "", fmt.Errorf("error setting user %s for container %s: %w", instruction.User, container.Name, err) } - case dockerfile.InstructionWorkdir: + case *InstructionWorkdir: if err := runtime.buildah.Config(ctx, container.Name, buildah.ConfigOpts{ CommonOpts: runtime.getBuildahCommonOpts(ctx, true), Workdir: instruction.Workdir, }); err != nil { return "", fmt.Errorf("error setting workdir %s for container %s: %w", instruction.Workdir, container.Name, err) } - case dockerfile.InstructionEntrypoint: + case *InstructionEntrypoint: if err := runtime.buildah.Config(ctx, container.Name, buildah.ConfigOpts{ CommonOpts: runtime.getBuildahCommonOpts(ctx, true), Entrypoint: instruction.Entrypoint, }); err != nil { return "", fmt.Errorf("error setting entrypoint %v for container %s: %w", instruction.Entrypoint, container.Name, err) } - case dockerfile.InstructionCmd: + case *InstructionCmd: if err := runtime.buildah.Config(ctx, container.Name, buildah.ConfigOpts{ CommonOpts: runtime.getBuildahCommonOpts(ctx, true), Cmd: instruction.Cmd, @@ -555,7 +568,7 @@ func (runtime *BuildahBackend) BuildDockerfileStage(ctx context.Context, image I return "", fmt.Errorf("error setting cmd %v for container %s: %w", instruction.Cmd, container.Name, err) } default: - return "", fmt.Errorf("invalid command type: %T", i) + panic(fmt.Sprintf("invalid command type: %T", i)) } } @@ -570,9 +583,9 @@ func (runtime *BuildahBackend) BuildDockerfileStage(ctx context.Context, image I return imageID, nil } -func (runtime *BuildahBackend) BuildStapelStage(ctx context.Context, opts BuildStapelStageOptions) (string, error) { +func (runtime *BuildahBackend) BuildStapelStage(ctx context.Context, baseImage string, opts BuildStapelStageOptions) (string, error) { var container *containerDesc - if c, err := runtime.createContainers(ctx, []string{opts.BaseImage}); err != nil { + if c, err := runtime.createContainers(ctx, []string{baseImage}); err != nil { return "", err } else { container = c[0] diff --git a/pkg/container_backend/docker_server_backend.go b/pkg/container_backend/docker_server_backend.go index f582ce0021..0b8afef5f0 100644 --- a/pkg/container_backend/docker_server_backend.go +++ b/pkg/container_backend/docker_server_backend.go @@ -3,7 +3,6 @@ package container_backend import ( "context" "fmt" - "io" "strings" "github.com/docker/docker/api/types" @@ -26,7 +25,7 @@ func (runtime *DockerServerBackend) HasStapelBuildSupport() bool { return false } -func (runtime *DockerServerBackend) BuildStapelStage(ctx context.Context, opts BuildStapelStageOptions) (string, error) { +func (runtime *DockerServerBackend) BuildStapelStage(ctx context.Context, baseImage string, opts BuildStapelStageOptions) (string, error) { panic("BuildStapelStage does not implemented for DockerServerBackend. Please report the bug if you've received this message.") } @@ -80,7 +79,7 @@ func (runtime *DockerServerBackend) BuildDockerfile(ctx context.Context, _ []byt return tempID, docker.CliBuild_LiveOutputWithCustomIn(ctx, opts.ContextTar, cliArgs...) } -func (runtime *DockerServerBackend) BuildDockerfileStage(ctx context.Context, image ImageInterface, contextTar io.ReadCloser, opts BuildDockerfileStageOptions, commands ...any) (string, error) { +func (runtime *DockerServerBackend) BuildDockerfileStage(ctx context.Context, baseImage string, opts BuildDockerfileStageOptions, instructions ...any) (string, error) { panic("not implemented") } diff --git a/pkg/dockerfile/instructions.go b/pkg/container_backend/dockerfile_instructions.go similarity index 94% rename from pkg/dockerfile/instructions.go rename to pkg/container_backend/dockerfile_instructions.go index 23ef654dc0..01a6449cd1 100644 --- a/pkg/dockerfile/instructions.go +++ b/pkg/container_backend/dockerfile_instructions.go @@ -1,4 +1,4 @@ -package dockerfile +package container_backend import "fmt" @@ -21,10 +21,6 @@ type InstructionRun struct { Command []string } -func (i *InstructionRun) Name() string { - return "RUN" -} - type InstructionEntrypoint struct { Entrypoint []string } diff --git a/pkg/container_backend/interface.go b/pkg/container_backend/interface.go index 701ee88261..d8dfd4c5e2 100644 --- a/pkg/container_backend/interface.go +++ b/pkg/container_backend/interface.go @@ -45,6 +45,8 @@ type BuildDockerfileOpts struct { type BuildDockerfileStageOptions struct { CommonOpts + + ContextTar io.ReadCloser } type ContainerBackend interface { @@ -55,8 +57,8 @@ type ContainerBackend interface { GetImageInfo(ctx context.Context, ref string, opts GetImageInfoOpts) (*image.Info, error) BuildDockerfile(ctx context.Context, dockerfile []byte, opts BuildDockerfileOpts) (string, error) - BuildDockerfileStage(ctx context.Context, image ImageInterface, contextTar io.ReadCloser, opts BuildDockerfileStageOptions, commands ...any) (string, error) - BuildStapelStage(ctx context.Context, opts BuildStapelStageOptions) (string, error) + BuildDockerfileStage(ctx context.Context, baseImage string, opts BuildDockerfileStageOptions, commands ...any) (string, error) + BuildStapelStage(ctx context.Context, baseImage string, opts BuildStapelStageOptions) (string, error) CalculateDependencyImportChecksum(ctx context.Context, dependencyImport DependencyImportSpec) (string, error) HasStapelBuildSupport() bool diff --git a/pkg/container_backend/perf_check_container_backend.go b/pkg/container_backend/perf_check_container_backend.go index 976f726426..70998944e8 100644 --- a/pkg/container_backend/perf_check_container_backend.go +++ b/pkg/container_backend/perf_check_container_backend.go @@ -2,7 +2,6 @@ package container_backend import ( "context" - "io" "github.com/werf/logboek" "github.com/werf/werf/pkg/image" @@ -72,18 +71,18 @@ func (runtime *PerfCheckContainerBackend) BuildDockerfile(ctx context.Context, d return } -func (runtime *PerfCheckContainerBackend) BuildDockerfileStage(ctx context.Context, image ImageInterface, contextTar io.ReadCloser, opts BuildDockerfileStageOptions, commands ...any) (resID string, resErr error) { +func (runtime *PerfCheckContainerBackend) BuildDockerfileStage(ctx context.Context, baseImage string, opts BuildDockerfileStageOptions, instructions ...any) (resID string, resErr error) { logboek.Context(ctx).Default().LogProcess("ContainerBackend.BuildDockerfile"). Do(func() { - resID, resErr = runtime.ContainerBackend.BuildDockerfileStage(ctx, image, contextTar, opts, commands) + resID, resErr = runtime.ContainerBackend.BuildDockerfileStage(ctx, baseImage, opts, instructions...) }) return } -func (runtime *PerfCheckContainerBackend) BuildStapelStage(ctx context.Context, opts BuildStapelStageOptions) (resID string, resErr error) { +func (runtime *PerfCheckContainerBackend) BuildStapelStage(ctx context.Context, baseImage string, opts BuildStapelStageOptions) (resID string, resErr error) { logboek.Context(ctx).Default().LogProcess("ContainerBackend.BuildDockerfile"). Do(func() { - resID, resErr = runtime.ContainerBackend.BuildStapelStage(ctx, opts) + resID, resErr = runtime.ContainerBackend.BuildStapelStage(ctx, baseImage, opts) }) return } diff --git a/pkg/container_backend/stage_builder/dockerfile_stage_builder.go b/pkg/container_backend/stage_builder/dockerfile_stage_builder.go index 4d0e41e603..c04a719d41 100644 --- a/pkg/container_backend/stage_builder/dockerfile_stage_builder.go +++ b/pkg/container_backend/stage_builder/dockerfile_stage_builder.go @@ -22,15 +22,15 @@ type DockerfileStageBuilder struct { postCommands []any contextTar io.ReadCloser - fromImage container_backend.ImageInterface + baseImage string resultImage container_backend.ImageInterface containerBackend container_backend.ContainerBackend } -func NewDockerfileStageBuilder(containerBackend container_backend.ContainerBackend, fromImage, resultImage container_backend.ImageInterface) *DockerfileStageBuilder { +func NewDockerfileStageBuilder(containerBackend container_backend.ContainerBackend, baseImage string, resultImage container_backend.ImageInterface) *DockerfileStageBuilder { return &DockerfileStageBuilder{ containerBackend: containerBackend, - fromImage: fromImage, + baseImage: baseImage, resultImage: resultImage, } } @@ -56,14 +56,10 @@ func (b *DockerfileStageBuilder) SetContext(contextTar io.ReadCloser) Dockerfile } func (b *DockerfileStageBuilder) Build(ctx context.Context, opts container_backend.BuildOptions) error { - commands := append(append(b.preCommands, b.mainCommands...), b.postCommands) - if len(commands) == 0 { - b.resultImage.SetName(b.fromImage.Name()) - b.resultImage.SetBuiltID(b.fromImage.BuiltID()) - return nil - } + commands := append(append(b.preCommands, b.mainCommands...), b.postCommands...) + backendOpts := container_backend.BuildDockerfileStageOptions{ContextTar: b.contextTar} - if builtID, err := b.containerBackend.BuildDockerfileStage(ctx, b.resultImage, b.contextTar, container_backend.BuildDockerfileStageOptions{}, commands...); err != nil { + if builtID, err := b.containerBackend.BuildDockerfileStage(ctx, b.baseImage, backendOpts, commands...); err != nil { return fmt.Errorf("error building dockerfile stage: %w", err) } else { b.resultImage.SetBuiltID(builtID) diff --git a/pkg/container_backend/stage_builder/stage_builder.go b/pkg/container_backend/stage_builder/stage_builder.go index a7c9021ade..1724ce7385 100644 --- a/pkg/container_backend/stage_builder/stage_builder.go +++ b/pkg/container_backend/stage_builder/stage_builder.go @@ -15,17 +15,17 @@ type StageBuilderInterface interface { Build(ctx context.Context, opts container_backend.BuildOptions) error } -func NewStageBuilder(containerBackend container_backend.ContainerBackend, fromImage container_backend.ImageInterface, image container_backend.LegacyImageInterface) *StageBuilder { +func NewStageBuilder(containerBackend container_backend.ContainerBackend, baseImage string, image container_backend.LegacyImageInterface) *StageBuilder { return &StageBuilder{ ContainerBackend: containerBackend, - FromImage: fromImage, + BaseImage: baseImage, Image: image, } } type StageBuilder struct { ContainerBackend container_backend.ContainerBackend - FromImage container_backend.ImageInterface + BaseImage string Image container_backend.LegacyImageInterface // TODO: use ImageInterface dockerfileBuilder *DockerfileBuilder @@ -52,7 +52,7 @@ func (stageBuilder *StageBuilder) GetLegacyStapelStageBuilderImplmentation() *Le func (stageBuilder *StageBuilder) StapelStageBuilder() StapelStageBuilderInterface { if stageBuilder.stapelStageBuilder == nil { - stageBuilder.stapelStageBuilder = NewStapelStageBuilder(stageBuilder.ContainerBackend, stageBuilder.FromImage, stageBuilder.Image) + stageBuilder.stapelStageBuilder = NewStapelStageBuilder(stageBuilder.ContainerBackend, stageBuilder.BaseImage, stageBuilder.Image) } return stageBuilder.stapelStageBuilder } @@ -73,7 +73,7 @@ func (stageBuilder *StageBuilder) DockerfileBuilder() DockerfileBuilderInterface func (stageBuilder *StageBuilder) DockerfileStageBuilder() DockerfileStageBuilderInterface { if stageBuilder.dockerfileStageBuilder == nil { - stageBuilder.dockerfileStageBuilder = NewDockerfileStageBuilder(stageBuilder.ContainerBackend, stageBuilder.FromImage, stageBuilder.Image) + stageBuilder.dockerfileStageBuilder = NewDockerfileStageBuilder(stageBuilder.ContainerBackend, stageBuilder.BaseImage, stageBuilder.Image) } return stageBuilder.dockerfileStageBuilder } diff --git a/pkg/container_backend/stage_builder/stapel_stage_builder.go b/pkg/container_backend/stage_builder/stapel_stage_builder.go index 7995268652..cb7180c6a5 100644 --- a/pkg/container_backend/stage_builder/stapel_stage_builder.go +++ b/pkg/container_backend/stage_builder/stapel_stage_builder.go @@ -16,14 +16,14 @@ type StapelStageBuilder struct { container_backend.BuildStapelStageOptions ContainerBackend container_backend.ContainerBackend - FromImage container_backend.ImageInterface + BaseImage string Image container_backend.ImageInterface } -func NewStapelStageBuilder(containerBackend container_backend.ContainerBackend, fromImage, image container_backend.ImageInterface) *StapelStageBuilder { +func NewStapelStageBuilder(containerBackend container_backend.ContainerBackend, baseImage string, image container_backend.ImageInterface) *StapelStageBuilder { return &StapelStageBuilder{ ContainerBackend: containerBackend, - FromImage: fromImage, + BaseImage: baseImage, Image: image, } } @@ -31,9 +31,7 @@ func NewStapelStageBuilder(containerBackend container_backend.ContainerBackend, func (builder *StapelStageBuilder) Build(ctx context.Context, opts container_backend.BuildOptions) error { // TODO: support introspect options - builder.SetBaseImage(builder.FromImage.Name()) - - builtID, err := builder.ContainerBackend.BuildStapelStage(ctx, builder.BuildStapelStageOptions) + builtID, err := builder.ContainerBackend.BuildStapelStage(ctx, builder.BaseImage, builder.BuildStapelStageOptions) if err != nil { return fmt.Errorf("error building stapel stage with %s: %w", builder.ContainerBackend.String(), err) }