From 3ceb622860d7bffe3e66db7e353faad87b04a6f5 Mon Sep 17 00:00:00 2001 From: Timofey Kirillov Date: Thu, 26 May 2022 22:07:21 +0300 Subject: [PATCH] fix(cache-repo): panic when using cache repo and fromImage directive ``` goroutine 1623 [running]: github.com/werf/werf/pkg/build/stage.(*BaseStage).getServiceMountsFromLabels(0xc0016ed300?, 0xc001b00100) /home/distorhead/werf/pkg/build/stage/base.go:283 +0xc4 github.com/werf/werf/pkg/build/stage.(*BaseStage).getServiceMounts(0xc000e50d80?, 0x3bde920?) /home/distorhead/werf/pkg/build/stage/base.go:274 +0x36 github.com/werf/werf/pkg/build/stage.(*FromStage).PrepareImage(0xc0014c5140, {0xc001508420?, 0x3be22c8?}, {0x3be06b0, 0xc0006ac2c0}, {0x3bde920, 0xc000f622e0}, 0x0?, 0xc001b01640) /home/distorhead/werf/pkg/build/stage/from.go:82 +0x194 github.com/werf/werf/pkg/build.(*BuildPhase).prepareStageInstructions(0xc00188a2d0, {0x3bcc730?, 0xc001858300}, 0xc001508420, {0x3be22c8, 0xc0014c5140}) /home/distorhead/werf/pkg/build/build_phase.go:693 +0xdff ... ``` Refactor the process of copying of stage-image descriptors objects into cache storage. Signed-off-by: Timofey Kirillov --- pkg/build/build_phase.go | 12 ++++++------ pkg/build/image.go | 2 +- pkg/container_backend/buildah_backend.go | 8 +++++--- pkg/container_backend/legacy_interface.go | 2 ++ pkg/container_backend/legacy_stage_image.go | 13 +++++++++++++ pkg/storage/manager/storage_manager.go | 8 +++++--- 6 files changed, 32 insertions(+), 13 deletions(-) diff --git a/pkg/build/build_phase.go b/pkg/build/build_phase.go index aea0a2d5f8..3d5c74b8c3 100644 --- a/pkg/build/build_phase.go +++ b/pkg/build/build_phase.go @@ -800,20 +800,21 @@ func (phase *BuildPhase) atomicBuildStageImage(ctx context.Context, img *Image, // use newly built image newStageImageName, uniqueID := phase.Conveyor.StorageManager.GenerateStageUniqueID(stg.GetDigest(), stages) - stageImageObj := phase.Conveyor.GetStageImage(stageImage.Image.Name()) - phase.Conveyor.UnsetStageImage(stageImageObj.Image.Name()) - stageImageObj.Image.SetName(newStageImageName) - phase.Conveyor.SetStageImage(stageImageObj) + phase.Conveyor.UnsetStageImage(stageImage.Image.Name()) + stageImage.Image.SetName(newStageImageName) + phase.Conveyor.SetStageImage(stageImage) if err := logboek.Context(ctx).Default().LogProcess("Store stage into %s", phase.Conveyor.StorageManager.GetStagesStorage().String()).DoError(func() error { if err := phase.Conveyor.StorageManager.GetStagesStorage().StoreImage(ctx, stageImage.Image); err != nil { return fmt.Errorf("unable to store stage %s digest %s image %s into repo %s: %w", stg.LogDetailedName(), stg.GetDigest(), stageImage.Image.Name(), phase.Conveyor.StorageManager.GetStagesStorage().String(), err) } + if desc, err := phase.Conveyor.StorageManager.GetStagesStorage().GetStageDescription(ctx, phase.Conveyor.projectName(), stg.GetDigest(), uniqueID); err != nil { return fmt.Errorf("unable to get stage %s digest %s image %s description from repo %s after stages has been stored into repo: %w", stg.LogDetailedName(), stg.GetDigest(), stageImage.Image.Name(), phase.Conveyor.StorageManager.GetStagesStorage().String(), err) } else { - stageImageObj.Image.SetStageDescription(desc) + stageImage.Image.SetStageDescription(desc) } + return nil }); err != nil { return err @@ -824,7 +825,6 @@ func (phase *BuildPhase) atomicBuildStageImage(ctx context.Context, img *Image, if err := phase.Conveyor.StorageManager.CopyStageIntoCacheStorages(ctx, stg, phase.Conveyor.ContainerBackend); err != nil { return fmt.Errorf("unable to copy stage %s into cache storages: %w", stageImage.Image.GetStageDescription().StageID.String(), err) } - return nil } } diff --git a/pkg/build/image.go b/pkg/build/image.go index ae37e2eb32..8bbdbac2da 100644 --- a/pkg/build/image.go +++ b/pkg/build/image.go @@ -126,7 +126,7 @@ func (i *Image) SetupBaseImage(c *Conveyor) { if i.baseImageImageName != "" { i.baseImageType = StageAsBaseImage i.stageAsBaseImage = c.GetImage(i.baseImageImageName).GetLastNonEmptyStage() - i.baseImage = c.GetOrCreateStageImage(nil, i.stageAsBaseImage.GetStageImage().Image.Name()) + i.baseImage = i.stageAsBaseImage.GetStageImage() } else { i.baseImageType = ImageFromRegistryAsBaseImage i.baseImage = c.GetOrCreateStageImage(nil, i.baseImageName) diff --git a/pkg/container_backend/buildah_backend.go b/pkg/container_backend/buildah_backend.go index 7ec0fd2426..bdb187c9ed 100644 --- a/pkg/container_backend/buildah_backend.go +++ b/pkg/container_backend/buildah_backend.go @@ -613,9 +613,11 @@ func (runtime *BuildahBackend) RenameImage(ctx context.Context, img LegacyImageI desc := img.GetStageDescription() - repository, tag := image.ParseRepositoryAndTag(newImageName) - desc.Info.Repository = repository - desc.Info.Tag = tag + if desc != nil { + repository, tag := image.ParseRepositoryAndTag(newImageName) + desc.Info.Repository = repository + desc.Info.Tag = tag + } return nil } diff --git a/pkg/container_backend/legacy_interface.go b/pkg/container_backend/legacy_interface.go index 553ad04181..5fd7be8897 100644 --- a/pkg/container_backend/legacy_interface.go +++ b/pkg/container_backend/legacy_interface.go @@ -37,6 +37,8 @@ type LegacyImageInterface interface { SetStageDescription(stage *image.StageDescription) GetStageDescription() *image.StageDescription + + GetCopy() LegacyImageInterface } type LegacyContainer interface { diff --git a/pkg/container_backend/legacy_stage_image.go b/pkg/container_backend/legacy_stage_image.go index db744e3211..0510d04821 100644 --- a/pkg/container_backend/legacy_stage_image.go +++ b/pkg/container_backend/legacy_stage_image.go @@ -29,6 +29,19 @@ func NewLegacyStageImage(fromImage *LegacyStageImage, name string, containerBack return stage } +func (i *LegacyStageImage) GetCopy() LegacyImageInterface { + ni := NewLegacyStageImage(i.fromImage, i.name, i.ContainerBackend) + + if info := i.GetInfo(); info != nil { + ni.SetInfo(info) + } + if desc := i.GetStageDescription(); desc != nil { + ni.SetStageDescription(desc) + } + + return ni +} + func (i *LegacyStageImage) BuilderContainer() LegacyBuilderContainer { return &LegacyStageImageBuilderContainer{i} } diff --git a/pkg/storage/manager/storage_manager.go b/pkg/storage/manager/storage_manager.go index 0c394f2938..2a6257aa8a 100644 --- a/pkg/storage/manager/storage_manager.go +++ b/pkg/storage/manager/storage_manager.go @@ -383,17 +383,19 @@ func doFetchStage(ctx context.Context, projectName string, stagesStorage storage } func copyStageIntoStagesStorage(ctx context.Context, projectName string, stageID image.StageID, img container_backend.LegacyImageInterface, stagesStorage storage.StagesStorage, containerBackend container_backend.ContainerBackend) error { + newImg := img.GetCopy() + targetStagesStorageImageName := stagesStorage.ConstructStageImageName(projectName, stageID.Digest, stageID.UniqueID) - if err := containerBackend.RenameImage(ctx, img, targetStagesStorageImageName, false); err != nil { + if err := containerBackend.RenameImage(ctx, newImg, targetStagesStorageImageName, false); err != nil { return fmt.Errorf("unable to rename image %s to %s: %w", img.Name(), targetStagesStorageImageName, err) } - if err := stagesStorage.StoreImage(ctx, img); err != nil { + if err := stagesStorage.StoreImage(ctx, newImg); err != nil { return fmt.Errorf("unable to store stage %s into the cache stages storage %s: %w", stageID.String(), stagesStorage.String(), err) } - if err := storeStageDescriptionIntoLocalManifestCache(ctx, projectName, stageID, stagesStorage, convertStageDescriptionForStagesStorage(img.GetStageDescription(), stagesStorage)); err != nil { + if err := storeStageDescriptionIntoLocalManifestCache(ctx, projectName, stageID, stagesStorage, convertStageDescriptionForStagesStorage(newImg.GetStageDescription(), stagesStorage)); err != nil { return fmt.Errorf("error storing stage %s description into local manifest cache: %w", targetStagesStorageImageName, err) }