Skip to content

Commit 9b3dbf9

Browse files
committed
fix(docker-instructions): exactOptionValues option to fix docker-server backend options evaluation
Signed-off-by: Timofey Kirillov <timofey.kirillov@flant.com> Signed-off-by: Timofey Kirillov <timofey.kirillov@flant.com>
1 parent 6dcbd3e commit 9b3dbf9

File tree

9 files changed

+291
-33
lines changed

9 files changed

+291
-33
lines changed

pkg/build/stage/docker_instructions.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,15 @@ type DockerInstructionsStage struct {
3030
instructions *config.Docker
3131
}
3232

33-
func (s *DockerInstructionsStage) GetDependencies(_ context.Context, _ Conveyor, _ container_backend.ContainerBackend, _, _ *StageImage) (string, error) {
33+
func (s *DockerInstructionsStage) GetDependencies(_ context.Context, c Conveyor, backend container_backend.ContainerBackend, _, _ *StageImage) (string, error) {
3434
var args []string
3535

36+
// FIXME: add to digest if option set, keep current compatible digest otherwise
37+
38+
if c.UseLegacyStapelBuilder(backend) && s.instructions.ExactValues {
39+
args = append(args, "exact-values:::")
40+
}
41+
3642
args = append(args, s.instructions.Volume...)
3743
args = append(args, s.instructions.Expose...)
3844
args = append(args, mapToSortedArgs(s.instructions.Env)...)
@@ -61,6 +67,10 @@ func mapToSortedArgs(h map[string]string) (result []string) {
6167
}
6268

6369
func (s *DockerInstructionsStage) PrepareImage(ctx context.Context, c Conveyor, cr container_backend.ContainerBackend, prevBuiltImage, stageImage *StageImage) error {
70+
if c.UseLegacyStapelBuilder(cr) {
71+
stageImage.Image.SetCommitChangeOptions(container_backend.LegacyCommitChangeOptions{ExactValues: s.instructions.ExactValues})
72+
}
73+
6474
if err := s.BaseStage.PrepareImage(ctx, c, cr, prevBuiltImage, stageImage); err != nil {
6575
return err
6676
}

pkg/config/docker.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ type Docker struct {
1111
Entrypoint string
1212
HealthCheck string
1313

14+
ExactValues bool
15+
1416
raw *rawDocker
1517
}
1618

pkg/config/raw_docker.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ type rawDocker struct {
1616
Entrypoint interface{} `yaml:"ENTRYPOINT,omitempty"`
1717
HealthCheck string `yaml:"HEALTHCHECK,omitempty"`
1818

19+
ExactValues bool `yaml:"exactValues,omitempty"`
20+
1921
rawStapelImage *rawStapelImage `yaml:"-"` // parent
2022

2123
UnsupportedAttributes map[string]interface{} `yaml:",inline"`
@@ -76,6 +78,7 @@ func (c *rawDocker) toDirective() (docker *Docker, err error) {
7678
}
7779

7880
docker.HealthCheck = c.HealthCheck
81+
docker.ExactValues = c.ExactValues
7982

8083
docker.raw = c
8184

pkg/container_backend/legacy_interface.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ type LegacyImageInterface interface {
3737

3838
SetStageDescription(stage *image.StageDescription)
3939
GetStageDescription() *image.StageDescription
40+
SetCommitChangeOptions(opts LegacyCommitChangeOptions)
4041

4142
GetCopy() LegacyImageInterface
4243
}

pkg/container_backend/legacy_stage_image.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,11 @@ import (
1515

1616
type LegacyStageImage struct {
1717
*legacyBaseImage
18-
fromImage *LegacyStageImage
19-
container *LegacyStageImageContainer
20-
buildImage *legacyBaseImage
21-
builtID string
18+
fromImage *LegacyStageImage
19+
container *LegacyStageImageContainer
20+
buildImage *legacyBaseImage
21+
builtID string
22+
commitChangeOptions LegacyCommitChangeOptions
2223
}
2324

2425
func NewLegacyStageImage(fromImage *LegacyStageImage, name string, containerBackend ContainerBackend) *LegacyStageImage {
@@ -42,6 +43,10 @@ func (i *LegacyStageImage) GetCopy() LegacyImageInterface {
4243
return ni
4344
}
4445

46+
func (i *LegacyStageImage) SetCommitChangeOptions(opts LegacyCommitChangeOptions) {
47+
i.commitChangeOptions = opts
48+
}
49+
4550
func (i *LegacyStageImage) BuilderContainer() LegacyBuilderContainer {
4651
return &LegacyStageImageBuilderContainer{i}
4752
}

pkg/container_backend/legacy_stage_image_container.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func (c *LegacyStageImageContainer) Name() string {
4040
}
4141

4242
func (c *LegacyStageImageContainer) UserCommitChanges() []string {
43-
return c.commitChangeOptions.toCommitChanges()
43+
return c.commitChangeOptions.toCommitChanges(c.image.commitChangeOptions)
4444
}
4545

4646
func (c *LegacyStageImageContainer) UserRunCommands() []string {
@@ -201,13 +201,13 @@ func (c *LegacyStageImageContainer) prepareIntrospectOptions(ctx context.Context
201201
return c.prepareRunOptions(ctx)
202202
}
203203

204-
func (c *LegacyStageImageContainer) prepareCommitChanges(ctx context.Context) ([]string, error) {
204+
func (c *LegacyStageImageContainer) prepareCommitChanges(ctx context.Context, opts LegacyCommitChangeOptions) ([]string, error) {
205205
commitOptions, err := c.prepareCommitOptions(ctx)
206206
if err != nil {
207207
return nil, err
208208
}
209209

210-
commitChanges, err := commitOptions.prepareCommitChanges(ctx)
210+
commitChanges, err := commitOptions.prepareCommitChanges(ctx, opts)
211211
if err != nil {
212212
return nil, err
213213
}
@@ -324,11 +324,13 @@ func IsStartContainerErr(err error) bool {
324324
func (c *LegacyStageImageContainer) commit(ctx context.Context) (string, error) {
325325
_ = c.image.ContainerBackend.(*DockerServerBackend)
326326

327-
commitChanges, err := c.prepareCommitChanges(ctx)
327+
commitChanges, err := c.prepareCommitChanges(ctx, c.image.commitChangeOptions)
328328
if err != nil {
329329
return "", err
330330
}
331331

332+
fmt.Printf("!!! LegacyStageImageContainer.commit Changes:%#v\n", commitChanges)
333+
332334
commitOptions := types.ContainerCommitOptions{Changes: commitChanges}
333335
id, err := docker.ContainerCommit(ctx, c.name, commitOptions)
334336
if err != nil {

pkg/container_backend/legacy_stage_image_container_options.go

Lines changed: 76 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,20 @@ package container_backend
33
import (
44
"context"
55
"fmt"
6+
"sort"
67

78
"github.com/hashicorp/go-version"
89

910
"github.com/werf/werf/pkg/docker"
1011
)
1112

13+
type LegacyCommitChangeOptions struct {
14+
ExactValues bool
15+
}
16+
1217
type LegacyStageImageContainerOptions struct {
18+
dockerServerVersion string
19+
1320
Volume []string
1421
VolumesFrom []string
1522
Expose []string
@@ -132,6 +139,19 @@ func (co *LegacyStageImageContainerOptions) merge(co2 *LegacyStageImageContainer
132139
return mergedCo
133140
}
134141

142+
func getKeys(m map[string]string) []string {
143+
keys := make([]string, 0, len(m))
144+
for k := range m {
145+
keys = append(keys, k)
146+
}
147+
return keys
148+
}
149+
150+
func sortStrings(arr []string) []string {
151+
sort.Strings(arr)
152+
return arr
153+
}
154+
135155
func (co *LegacyStageImageContainerOptions) toRunArgs() ([]string, error) {
136156
var args []string
137157

@@ -143,12 +163,12 @@ func (co *LegacyStageImageContainerOptions) toRunArgs() ([]string, error) {
143163
args = append(args, fmt.Sprintf("--volumes-from=%s", volumesFrom))
144164
}
145165

146-
for key, value := range co.Env {
147-
args = append(args, fmt.Sprintf("--env=%s=%v", key, value))
166+
for _, k := range sortStrings(getKeys(co.Env)) {
167+
args = append(args, fmt.Sprintf("--env=%s=%v", k, co.Env[k]))
148168
}
149169

150-
for key, value := range co.Label {
151-
args = append(args, fmt.Sprintf("--label=%s=%v", key, value))
170+
for _, k := range sortStrings(getKeys(co.Label)) {
171+
args = append(args, fmt.Sprintf("--label=%s=%v", k, co.Label[k]))
152172
}
153173

154174
if co.User != "" {
@@ -166,23 +186,23 @@ func (co *LegacyStageImageContainerOptions) toRunArgs() ([]string, error) {
166186
return args, nil
167187
}
168188

169-
func (co *LegacyStageImageContainerOptions) toCommitChanges() []string {
189+
func (co *LegacyStageImageContainerOptions) toCommitChanges(opts LegacyCommitChangeOptions) []string {
170190
var args []string
171191

172192
for _, volume := range co.Volume {
173-
args = append(args, fmt.Sprintf("VOLUME %s", volume))
193+
args = append(args, fmt.Sprintf("VOLUME %s", escapeVolume(volume, opts.ExactValues)))
174194
}
175195

176196
for _, expose := range co.Expose {
177-
args = append(args, fmt.Sprintf("EXPOSE %s", expose))
197+
args = append(args, fmt.Sprintf("EXPOSE %s", defaultEscape(expose, opts.ExactValues)))
178198
}
179199

180-
for key, value := range co.Env {
181-
args = append(args, fmt.Sprintf("ENV %s=%v", key, value))
200+
for _, k := range sortStrings(getKeys(co.Env)) {
201+
args = append(args, fmt.Sprintf("ENV %s=%s", k, defaultEscape(co.Env[k], opts.ExactValues)))
182202
}
183203

184-
for key, value := range co.Label {
185-
args = append(args, fmt.Sprintf("LABEL %s=%v", key, value))
204+
for _, k := range sortStrings(getKeys(co.Label)) {
205+
args = append(args, fmt.Sprintf("LABEL %s=%s", k, defaultEscape(co.Label[k], opts.ExactValues)))
186206
}
187207

188208
if co.Cmd != "" {
@@ -208,23 +228,25 @@ func (co *LegacyStageImageContainerOptions) toCommitChanges() []string {
208228
return args
209229
}
210230

211-
func (co *LegacyStageImageContainerOptions) prepareCommitChanges(ctx context.Context) ([]string, error) {
231+
func (co *LegacyStageImageContainerOptions) prepareCommitChanges(ctx context.Context, opts LegacyCommitChangeOptions) ([]string, error) {
212232
var args []string
213233

234+
fmt.Printf("-- LegacyStageImageContainerOptions.prepareCommitChanges opts.ExactValues=%v\n", opts.ExactValues)
235+
214236
for _, volume := range co.Volume {
215-
args = append(args, fmt.Sprintf("VOLUME %s", volume))
237+
args = append(args, fmt.Sprintf("VOLUME %s", escapeVolume(volume, opts.ExactValues)))
216238
}
217239

218240
for _, expose := range co.Expose {
219-
args = append(args, fmt.Sprintf("EXPOSE %s", expose))
241+
args = append(args, fmt.Sprintf("EXPOSE %s", defaultEscape(expose, opts.ExactValues)))
220242
}
221243

222-
for key, value := range co.Env {
223-
args = append(args, fmt.Sprintf("ENV %s=%v", key, value))
244+
for _, k := range sortStrings(getKeys(co.Env)) {
245+
args = append(args, fmt.Sprintf("ENV %s=%s", k, defaultEscape(co.Env[k], opts.ExactValues)))
224246
}
225247

226-
for key, value := range co.Label {
227-
args = append(args, fmt.Sprintf("LABEL %s=%v", key, value))
248+
for _, k := range sortStrings(getKeys(co.Label)) {
249+
args = append(args, fmt.Sprintf("LABEL %s=%s", k, defaultEscape(co.Label[k], opts.ExactValues)))
228250
}
229251

230252
if co.Workdir != "" {
@@ -240,7 +262,7 @@ func (co *LegacyStageImageContainerOptions) prepareCommitChanges(ctx context.Con
240262
if co.Entrypoint != "" {
241263
entrypoint = co.Entrypoint
242264
} else {
243-
entrypoint, err = getEmptyEntrypointInstructionValue(ctx)
265+
entrypoint, err = getEmptyEntrypointInstructionValue(ctx, co.dockerServerVersion)
244266
if err != nil {
245267
return nil, fmt.Errorf("container options preparing failed: %w", err)
246268
}
@@ -261,13 +283,20 @@ func (co *LegacyStageImageContainerOptions) prepareCommitChanges(ctx context.Con
261283
return args, nil
262284
}
263285

264-
func getEmptyEntrypointInstructionValue(ctx context.Context) (string, error) {
265-
v, err := docker.ServerVersion(ctx)
266-
if err != nil {
267-
return "", err
286+
func getEmptyEntrypointInstructionValue(ctx context.Context, dockerServerVersion string) (string, error) {
287+
var rawServerVersion string
288+
289+
if dockerServerVersion == "" {
290+
v, err := docker.ServerVersion(ctx)
291+
if err != nil {
292+
return "", fmt.Errorf("unable to query docker server version: %w", err)
293+
}
294+
rawServerVersion = v.Version
295+
} else {
296+
rawServerVersion = dockerServerVersion
268297
}
269298

270-
serverVersion, err := version.NewVersion(v.Version)
299+
serverVersion, err := version.NewVersion(rawServerVersion)
271300
if err != nil {
272301
return "", err
273302
}
@@ -283,3 +312,26 @@ func getEmptyEntrypointInstructionValue(ctx context.Context) (string, error) {
283312

284313
return "[\"\"]", nil
285314
}
315+
316+
// FIXME: remove escaping in 2.0 or 1.3
317+
func escapeVolume(volume string, exactValues bool) string {
318+
if exactValues {
319+
return fmt.Sprintf("[%s]", quoteValue(volume))
320+
}
321+
return volume
322+
}
323+
324+
func defaultEscape(value string, exactValues bool) string {
325+
return doEscape(value, exactValues, quoteValue)
326+
}
327+
328+
func doEscape(value string, exactValues bool, escaper func(string) string) string {
329+
if exactValues {
330+
return escaper(value)
331+
}
332+
return value
333+
}
334+
335+
func quoteValue(value string) string {
336+
return fmt.Sprintf("%q", value)
337+
}

0 commit comments

Comments
 (0)