/
export_phase.go
136 lines (116 loc) · 3.92 KB
/
export_phase.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
package build
import (
"context"
"fmt"
v1 "github.com/google/go-containerregistry/pkg/v1"
"k8s.io/utils/strings/slices"
"github.com/werf/logboek"
"github.com/werf/logboek/pkg/style"
"github.com/werf/logboek/pkg/types"
build_image "github.com/werf/werf/pkg/build/image"
"github.com/werf/werf/pkg/image"
"github.com/werf/werf/pkg/storage"
"github.com/werf/werf/pkg/util"
)
type ExportPhase struct {
BasePhase
ExportPhaseOptions
}
type ExportPhaseOptions struct {
ExportImageNameList []string
ExportTagFuncList []image.ExportTagFunc
MutateConfigFunc func(config v1.Config) (v1.Config, error)
}
func NewExportPhase(c *Conveyor, opts ExportPhaseOptions) *ExportPhase {
return &ExportPhase{
BasePhase: BasePhase{c},
ExportPhaseOptions: opts,
}
}
func (phase *ExportPhase) Name() string {
return "export"
}
func (phase *ExportPhase) AfterImages(ctx context.Context) error {
if len(phase.ExportTagFuncList) == 0 {
return nil
}
for _, desc := range phase.Conveyor.imagesTree.GetImagesByName(true) {
name, images := desc.Unpair()
if !slices.Contains(phase.ExportImageNameList, name) {
continue
}
targetPlatforms := util.MapFuncToSlice(images, func(img *build_image.Image) string { return img.TargetPlatform })
if len(targetPlatforms) == 1 {
img := images[0]
if err := phase.exportImage(ctx, img); err != nil {
return fmt.Errorf("unable to export image %q: %w", img.Name, err)
}
} else {
// FIXME(multiarch): Support multiplatform manifest by pushing local images to repo first, then create manifest list.
// FIXME(multiarch): Also support multiplatform manifest in werf build command in local mode with enabled final-repo.
if _, isLocal := phase.Conveyor.StorageManager.GetStagesStorage().(*storage.LocalStagesStorage); isLocal {
return fmt.Errorf("export command is not supported in multiplatform mode")
}
// multiplatform mode
img := phase.Conveyor.imagesTree.GetMultiplatformImage(name)
if err := phase.exportMultiplatformImage(ctx, img); err != nil {
return fmt.Errorf("unable to export multiplatform image %q: %w", img.Name, err)
}
}
}
return nil
}
func (phase *ExportPhase) exportMultiplatformImage(ctx context.Context, img *build_image.MultiplatformImage) error {
return logboek.Context(ctx).Default().LogProcess("Exporting image...").
Options(func(options types.LogProcessOptionsInterface) {
options.Style(style.Highlight())
}).
DoError(func() error {
for _, tagFunc := range phase.ExportTagFuncList {
tag := tagFunc(img.Name, img.GetStageID().String())
if err := logboek.Context(ctx).Default().LogProcess("tag %s", tag).
DoError(func() error {
desc := img.GetStageDescription()
if err := phase.Conveyor.StorageManager.GetStagesStorage().ExportStage(ctx, desc, tag, phase.MutateConfigFunc); err != nil {
return err
}
return nil
}); err != nil {
return err
}
}
return nil
})
}
func (phase *ExportPhase) exportImage(ctx context.Context, img *build_image.Image) error {
if !slices.Contains(phase.ExportImageNameList, img.Name) {
return nil
}
if len(phase.ExportTagFuncList) == 0 {
return nil
}
return logboek.Context(ctx).Default().LogProcess("Exporting image...").
Options(func(options types.LogProcessOptionsInterface) {
options.Style(style.Highlight())
}).
DoError(func() error {
for _, tagFunc := range phase.ExportTagFuncList {
tag := tagFunc(img.GetName(), img.GetStageID())
if err := logboek.Context(ctx).Default().LogProcess("tag %s", tag).
DoError(func() error {
stageDesc := img.GetLastNonEmptyStage().GetStageImage().Image.GetStageDescription()
if err := phase.Conveyor.StorageManager.GetStagesStorage().ExportStage(ctx, stageDesc, tag, phase.MutateConfigFunc); err != nil {
return err
}
return nil
}); err != nil {
return err
}
}
return nil
})
}
func (phase *ExportPhase) Clone() Phase {
u := *phase
return &u
}