@@ -3,13 +3,20 @@ package container_backend
33import (
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+
1217type 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+
135155func (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