@@ -25,7 +25,9 @@ import (
2525 runtimespec "github.com/opencontainers/runtime-spec/specs-go"
2626 "github.com/opencontainers/runtime-tools/validate"
2727 "github.com/pkg/errors"
28+ "github.com/sirupsen/logrus"
2829 "github.com/syndtr/gocapability/capability"
30+ "golang.org/x/sys/windows"
2931 runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
3032
3133 containerstore "github.com/containerd/cri/pkg/store/container"
@@ -39,26 +41,75 @@ func init() {
3941
4042// setOCIProcessArgs sets process args. It returns error if the final arg list
4143// is empty.
42- func setOCIProcessArgs (g * generator , config * runtime.ContainerConfig , imageConfig * imagespec.ImageConfig ) error {
44+ func setOCIProcessArgs (g * generator , config * runtime.ContainerConfig , image * imagespec.Image ) error {
4345 command , args := config .GetCommand (), config .GetArgs ()
4446 // The following logic is migrated from https://github.com/moby/moby/blob/master/daemon/commit.go
4547 // TODO(random-liu): Clearly define the commands overwrite behavior.
4648 if len (command ) == 0 {
4749 // Copy array to avoid data race.
4850 if len (args ) == 0 {
49- args = append ([]string {}, imageConfig .Cmd ... )
51+ args = append ([]string {}, image . Config .Cmd ... )
5052 }
5153 if command == nil {
52- command = append ([]string {}, imageConfig .Entrypoint ... )
54+ command = append ([]string {}, image . Config .Entrypoint ... )
5355 }
5456 }
5557 if len (command ) == 0 && len (args ) == 0 {
5658 return errors .New ("no command specified" )
5759 }
58- g .SetProcessArgs (append (command , args ... ))
60+ var ignoreArgsEscaped bool
61+ if ignoreArgsEscapedAnno , ok := config .Annotations ["microsoft.io/ignore-args-escaped" ]; ok {
62+ ignoreArgsEscaped = ignoreArgsEscapedAnno == "true"
63+ }
64+ setProcessArgs (g , image .OS == "windows" , image .Config .ArgsEscaped && ! ignoreArgsEscaped , append (command , args ... ))
5965 return nil
6066}
6167
68+ // setProcessArgs sets either g.Config.Process.CommandLine or g.Config.Process.Args.
69+ // This is forked from g.SetProcessArgs to add argsEscaped support.
70+ func setProcessArgs (g * generator , isWindows bool , argsEscaped bool , args []string ) {
71+ logrus .WithFields (logrus.Fields {
72+ "isWindows" : isWindows ,
73+ "argsEscaped" : argsEscaped ,
74+ "args" : args ,
75+ }).Info ("Setting process args on OCI spec" )
76+ if g .Config == nil {
77+ g .Config = & runtimespec.Spec {}
78+ }
79+ if g .Config .Process == nil {
80+ g .Config .Process = & runtimespec.Process {}
81+ }
82+
83+ if isWindows && argsEscaped {
84+ // argsEscaped is used for Windows containers to indicate that the command line should be
85+ // used from args[0] without escaping. This case seems to mostly result from use of
86+ // shell-form ENTRYPOINT or CMD in the Dockerfile. argsEscaped is a non-standard OCI
87+ // extension but we are using it here to support Docker images that rely on it. In the
88+ // future we should move to some properly standardized support in upstream OCI.
89+ // This logic is taken from https://github.com/moby/moby/blob/24f173a003727611aa482a55b812e0e39c67be65/daemon/oci_windows.go#L244
90+ //
91+ // Note: The approach taken here causes ArgsEscaped to change how commands passed directly
92+ // via CRI are interpreted as well. However, this actually matches with Docker's behavior
93+ // regarding commands specified at container create time, and seems non-trivial to fix,
94+ // so going to leave this way for now.
95+ g .Config .Process .CommandLine = args [0 ]
96+ if len (args [1 :]) > 0 {
97+ g .Config .Process .CommandLine += " " + escapeArgs (args [1 :])
98+ }
99+ } else {
100+ g .Config .Process .Args = args
101+ }
102+ }
103+
104+ // escapeArgs makes a Windows-style escaped command line from a set of arguments
105+ func escapeArgs (args []string ) string {
106+ escapedArgs := make ([]string , len (args ))
107+ for i , a := range args {
108+ escapedArgs [i ] = windows .EscapeArg (a )
109+ }
110+ return strings .Join (escapedArgs , " " )
111+ }
112+
62113// addImageEnvs adds environment variables from image config. It returns error if
63114// an invalid environment variable is encountered.
64115func addImageEnvs (g * generator , imageEnvs []string ) error {
0 commit comments