Skip to content

Commit 469a065

Browse files
fix(build, imageSpec): keep essential werf labels
Signed-off-by: Aleksei Igrychev <aleksei.igrychev@palark.com>
1 parent 0793ebb commit 469a065

File tree

4 files changed

+63
-73
lines changed

4 files changed

+63
-73
lines changed

Diff for: pkg/build/stage/image_spec.go

+21-20
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,14 @@ import (
1919
)
2020

2121
const (
22-
labelTemplateImage = "image"
23-
labelTemplateProject = "project"
24-
labelTemplateDelimiter = "%"
25-
werfLabelsGlobalWarning = "Removal of the werf labels requires explicit use of the clearWerfLabels directive. Some labels are purely informational, while others are essential for cleanup operations."
26-
werfLabelsHostCleanupWarning = "Removal of the %s label will affect host auto cleanup. Proper work of auto cleanup is not guaranteed."
22+
labelTemplateImage = "image"
23+
labelTemplateProject = "project"
24+
labelTemplateDelimiter = "%"
25+
werfLabelsGlobalWarning = `The "werf" and "werf-parent-stage-id" labels cannot be removed within the imageSpec stage, as they are essential for the proper operation of host and container registry cleanup.
26+
27+
If you need to remove all werf labels, use the werf export command. By default, this command removes all werf labels and fully detaches images from werf control, transferring host and container registry cleanup entirely to the user.
28+
29+
To disable this warning, explicitly set the "keepEssentialWerfLabels" directive.`
2730
)
2831

2932
type ImageSpecStage struct {
@@ -83,7 +86,7 @@ func (s *ImageSpecStage) PrepareImage(ctx context.Context, _ Conveyor, _ contain
8386
newConfig.ClearEntrypoint = newConfig.ClearEntrypoint || s.imageSpec.ClearEntrypoint
8487
}
8588

86-
resultLabels, err := s.modifyLabels(ctx, imageInfo.Labels, s.imageSpec.Labels, s.imageSpec.RemoveLabels, s.imageSpec.ClearWerfLabels)
89+
resultLabels, err := s.modifyLabels(ctx, imageInfo.Labels, s.imageSpec.Labels, s.imageSpec.RemoveLabels, s.imageSpec.KeepEssentialWerfLabels)
8790
if err != nil {
8891
return fmt.Errorf("unable to modify labels: %s", err)
8992
}
@@ -150,7 +153,7 @@ func (s *ImageSpecStage) GetDependencies(_ context.Context, _ Conveyor, _ contai
150153
return util.Sha256Hash(args...), nil
151154
}
152155

153-
func (s *ImageSpecStage) modifyLabels(ctx context.Context, labels, addLabels map[string]string, removeLabels []string, clearWerfLabels bool) (map[string]string, error) {
156+
func (s *ImageSpecStage) modifyLabels(ctx context.Context, labels, addLabels map[string]string, removeLabels []string, keepEssentialWerfLabels bool) (map[string]string, error) {
154157
if labels == nil {
155158
labels = make(map[string]string)
156159
}
@@ -190,7 +193,7 @@ func (s *ImageSpecStage) modifyLabels(ctx context.Context, labels, addLabels map
190193
}
191194
}
192195

193-
shouldRemove := func(key string) bool {
196+
matchFunc := func(key string) bool {
194197
if _, found := exactMatches[key]; found {
195198
return true
196199
}
@@ -199,32 +202,30 @@ func (s *ImageSpecStage) modifyLabels(ctx context.Context, labels, addLabels map
199202
return true
200203
}
201204
}
202-
if clearWerfLabels && strings.HasPrefix(key, "werf") {
203-
return true
204-
}
205205
return false
206206
}
207207

208208
shouldPrintGlobalWarn := false
209-
var cleanupWarnKeys []string
210209
for key := range labels {
211-
if shouldRemove(key) {
212-
if !clearWerfLabels && strings.HasPrefix(key, "werf") {
210+
if !matchFunc(key) {
211+
continue
212+
}
213+
214+
if key == image.WerfLabel || key == image.WerfParentStageID {
215+
if !keepEssentialWerfLabels {
213216
shouldPrintGlobalWarn = true
214-
} else {
215-
delete(labels, key)
216217
}
218+
219+
continue
217220
}
221+
222+
delete(labels, key)
218223
}
219224

220225
if shouldPrintGlobalWarn {
221226
global_warnings.GlobalWarningLn(ctx, werfLabelsGlobalWarning)
222227
}
223228

224-
if len(cleanupWarnKeys) > 0 {
225-
global_warnings.GlobalWarningLn(ctx, fmt.Sprintf(werfLabelsHostCleanupWarning, strings.Join(cleanupWarnKeys, "','")))
226-
}
227-
228229
return labels, nil
229230
}
230231

Diff for: pkg/build/stage/image_spec_test.go

+4-25
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ func TestModifyLabels(t *testing.T) {
8484
labels map[string]string
8585
addLabels map[string]string
8686
removeLabels []string
87-
clearWerfLabels bool
8887
expectedLabels map[string]string
8988
expectedWarnings []string
9089
}{
@@ -94,8 +93,7 @@ func TestModifyLabels(t *testing.T) {
9493
"test-label": "bar",
9594
"werf": "should-stay",
9695
},
97-
removeLabels: []string{"test-label"},
98-
clearWerfLabels: false,
96+
removeLabels: []string{"test-label"},
9997
expectedLabels: map[string]string{
10098
"werf": "should-stay",
10199
"stub": "true",
@@ -107,29 +105,12 @@ func TestModifyLabels(t *testing.T) {
107105
"test-label": "bar",
108106
"test123": "should-remove",
109107
},
110-
removeLabels: []string{"/test[0-9]+/"},
111-
clearWerfLabels: false,
108+
removeLabels: []string{"/test[0-9]+/"},
112109
expectedLabels: map[string]string{
113110
"test-label": "bar",
114111
"stub": "true",
115112
},
116113
},
117-
{
118-
name: "clear werf labels",
119-
labels: map[string]string{
120-
"test-label": "bar",
121-
"werf.test": "should-remove",
122-
"werf.other": "should-remove",
123-
"not-werf": "keep",
124-
"werf-random": "should-remove",
125-
},
126-
clearWerfLabels: true,
127-
expectedLabels: map[string]string{
128-
"test-label": "bar",
129-
"not-werf": "keep",
130-
"stub": "true",
131-
},
132-
},
133114
{
134115
name: "add new labels",
135116
labels: map[string]string{
@@ -152,10 +133,8 @@ func TestModifyLabels(t *testing.T) {
152133
"test-label": "bar",
153134
"remove": "this",
154135
"keep": "me",
155-
"werf.me": "delete",
156136
},
157-
removeLabels: []string{"remove"},
158-
clearWerfLabels: true,
137+
removeLabels: []string{"remove"},
159138
addLabels: map[string]string{
160139
"new": "added",
161140
"project-%project%-id": "image-%image%-name",
@@ -187,7 +166,7 @@ func TestModifyLabels(t *testing.T) {
187166
},
188167
}
189168

190-
modifiedLabels, err := s.modifyLabels(ctx, labelsCopy, tt.addLabels, tt.removeLabels, tt.clearWerfLabels)
169+
modifiedLabels, err := s.modifyLabels(ctx, labelsCopy, tt.addLabels, tt.removeLabels, false)
191170
assert.NoError(t, err)
192171
assert.Equal(t, tt.expectedLabels, modifiedLabels)
193172
})

Diff for: pkg/config/image_spec.go

+25-19
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,29 @@
11
package config
22

3-
import "slices"
3+
import (
4+
"slices"
5+
)
46

57
type ImageSpec struct {
6-
Author string `yaml:"author,omitempty"`
7-
ClearHistory bool `yaml:"clearHistory,omitempty"`
8-
ClearWerfLabels bool `yaml:"clearWerfLabels,omitempty"`
9-
RemoveLabels []string `yaml:"removeLabels,omitempty"`
10-
RemoveVolumes []string `yaml:"removeVolumes,omitempty"`
11-
RemoveEnv []string `yaml:"removeEnv,omitempty"`
12-
ClearCmd bool `yaml:"clearCmd,omitempty"`
13-
ClearEntrypoint bool `yaml:"clearEntrypoint,omitempty"`
14-
Volumes []string `yaml:"volumes,omitempty"`
15-
Labels map[string]string `yaml:"labels,omitempty"`
16-
Env map[string]string `yaml:"env,omitempty"`
17-
User string `yaml:"user,omitempty"`
18-
Cmd []string `yaml:"cmd,omitempty"`
19-
Entrypoint []string `yaml:"entrypoint,omitempty"`
20-
WorkingDir string `yaml:"workingDir,omitempty"`
21-
StopSignal string `yaml:"stopSignal,omitempty"`
22-
Expose []string `yaml:"expose,omitempty"`
23-
Healthcheck *healthConfig `yaml:"healthcheck,omitempty"`
8+
Author string `yaml:"author,omitempty"`
9+
ClearHistory bool `yaml:"clearHistory,omitempty"`
10+
KeepEssentialWerfLabels bool `yaml:"keepEssentialWerfLabels,omitempty"`
11+
ClearWerfLabels bool `yaml:"clearWerfLabels,omitempty"` // TODO: remove in v3.
12+
RemoveLabels []string `yaml:"removeLabels,omitempty"`
13+
RemoveVolumes []string `yaml:"removeVolumes,omitempty"`
14+
RemoveEnv []string `yaml:"removeEnv,omitempty"`
15+
ClearCmd bool `yaml:"clearCmd,omitempty"`
16+
ClearEntrypoint bool `yaml:"clearEntrypoint,omitempty"`
17+
Volumes []string `yaml:"volumes,omitempty"`
18+
Labels map[string]string `yaml:"labels,omitempty"`
19+
Env map[string]string `yaml:"env,omitempty"`
20+
User string `yaml:"user,omitempty"`
21+
Cmd []string `yaml:"cmd,omitempty"`
22+
Entrypoint []string `yaml:"entrypoint,omitempty"`
23+
WorkingDir string `yaml:"workingDir,omitempty"`
24+
StopSignal string `yaml:"stopSignal,omitempty"`
25+
Expose []string `yaml:"expose,omitempty"`
26+
Healthcheck *healthConfig `yaml:"healthcheck,omitempty"`
2427

2528
raw *rawImageSpec
2629
rawGlobal *rawImageSpecGlobal
@@ -47,6 +50,9 @@ func mergeImageSpec(priority, fallback *ImageSpec) ImageSpec {
4750
if priority.ClearWerfLabels {
4851
merged.ClearWerfLabels = priority.ClearWerfLabels
4952
}
53+
if priority.KeepEssentialWerfLabels {
54+
merged.KeepEssentialWerfLabels = priority.KeepEssentialWerfLabels
55+
}
5056

5157
merged.RemoveLabels = mergeSlices(fallback.RemoveLabels, priority.RemoveLabels)
5258
merged.RemoveVolumes = mergeSlices(fallback.RemoveVolumes, priority.RemoveVolumes)

Diff for: pkg/config/raw_image_spec.go

+13-9
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@ type rawImageSpec struct {
1212
}
1313

1414
type rawImageSpecConfig struct {
15-
ClearWerfLabels bool `yaml:"clearWerfLabels,omitempty"`
16-
RemoveLabels []string `yaml:"removeLabels,omitempty"`
17-
RemoveVolumes []string `yaml:"removeVolumes,omitempty"`
18-
RemoveEnv []string `yaml:"removeEnv,omitempty"`
19-
ClearCmd bool `yaml:"clearCmd,omitempty"`
20-
ClearEntrypoint bool `yaml:"clearEntrypoint,omitempty"`
15+
KeepEssentialWerfLabels bool `yaml:"keepEssentialWerfLabels,omitempty"`
16+
ClearWerfLabels bool `yaml:"clearWerfLabels,omitempty"`
17+
RemoveLabels []string `yaml:"removeLabels,omitempty"`
18+
RemoveVolumes []string `yaml:"removeVolumes,omitempty"`
19+
RemoveEnv []string `yaml:"removeEnv,omitempty"`
20+
ClearCmd bool `yaml:"clearCmd,omitempty"`
21+
ClearEntrypoint bool `yaml:"clearEntrypoint,omitempty"`
2122

2223
Volumes []string `yaml:"volumes,omitempty"`
2324
Labels map[string]string `yaml:"labels,omitempty"`
@@ -103,6 +104,7 @@ func (s *rawImageSpec) toDirective() *ImageSpec {
103104
imageSpec.ClearHistory = s.ClearHistory
104105

105106
if s.Config != nil {
107+
imageSpec.KeepEssentialWerfLabels = s.Config.KeepEssentialWerfLabels
106108
imageSpec.ClearWerfLabels = s.Config.ClearWerfLabels
107109
imageSpec.RemoveLabels = s.Config.RemoveLabels
108110
imageSpec.RemoveVolumes = s.Config.RemoveVolumes
@@ -137,9 +139,10 @@ type rawImageSpecGlobal struct {
137139
}
138140

139141
type rawImageSpecGlobalConfig struct {
140-
ClearWerfLabels bool `yaml:"clearWerfLabels,omitempty"`
141-
RemoveLabels []string `yaml:"removeLabels,omitempty"`
142-
Labels map[string]string `yaml:"labels,omitempty"`
142+
KeepEssentialWerfLabels bool `yaml:"keepEssentialWerfLabels,omitempty"`
143+
ClearWerfLabels bool `yaml:"clearWerfLabels,omitempty"`
144+
RemoveLabels []string `yaml:"removeLabels,omitempty"`
145+
Labels map[string]string `yaml:"labels,omitempty"`
143146

144147
rawImageSpecGlobal *rawImageSpecGlobal `yaml:"-"` // parent
145148

@@ -192,6 +195,7 @@ func (s *rawImageSpecGlobal) toDirective() *ImageSpec {
192195
imageSpec.ClearHistory = s.ClearHistory
193196

194197
if s.Config != nil {
198+
imageSpec.KeepEssentialWerfLabels = s.Config.KeepEssentialWerfLabels
195199
imageSpec.ClearWerfLabels = s.Config.ClearWerfLabels
196200
imageSpec.RemoveLabels = s.Config.RemoveLabels
197201
imageSpec.Labels = s.Config.Labels

0 commit comments

Comments
 (0)