@@ -23,16 +23,15 @@ import (
2323 "os"
2424 "time"
2525
26+ "github.com/containerd/containerd/api/services/execution"
27+ rootfsapi "github.com/containerd/containerd/api/services/rootfs"
28+ "github.com/containerd/containerd/api/types/container"
2629 prototypes "github.com/gogo/protobuf/types"
2730 "github.com/golang/glog"
31+ imagespec "github.com/opencontainers/image-spec/specs-go/v1"
2832 runtimespec "github.com/opencontainers/runtime-spec/specs-go"
2933 "github.com/opencontainers/runtime-tools/generate"
3034 "golang.org/x/net/context"
31-
32- "github.com/containerd/containerd/api/services/execution"
33- "github.com/containerd/containerd/api/types/container"
34- "github.com/containerd/containerd/api/types/mount"
35-
3635 runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1"
3736
3837 "github.com/kubernetes-incubator/cri-containerd/pkg/metadata"
@@ -114,12 +113,11 @@ func (c *criContainerdService) startContainer(ctx context.Context, id string, me
114113 glog .V (2 ).Infof ("Sandbox container %q is running with pid %d" , sandboxID , sandboxPid )
115114
116115 // Generate containerd container create options.
117- // TODO(random-liu): [P0] Create container rootfs with image ref.
118- // TODO(random-liu): [P0] Apply default image config.
119- // Use fixed rootfs path for now.
120- const rootPath = "/"
121-
122- spec , err := c .generateContainerSpec (id , sandboxPid , config , sandboxConfig )
116+ imageMeta , err := c .imageMetadataStore .Get (meta .ImageRef )
117+ if err != nil {
118+ return fmt .Errorf ("failed to get container image %q: %v" , meta .ImageRef , err )
119+ }
120+ spec , err := c .generateContainerSpec (id , sandboxPid , config , sandboxConfig , imageMeta .Config )
123121 if err != nil {
124122 return fmt .Errorf ("failed to generate container %q spec: %v" , id , err )
125123 }
@@ -169,31 +167,27 @@ func (c *criContainerdService) startContainer(ctx context.Context, id string, me
169167 }(stderrPipe )
170168 }
171169
170+ // Get rootfs mounts.
171+ mountsResp , err := c .rootfsService .Mounts (ctx , & rootfsapi.MountsRequest {Name : id })
172+ if err != nil {
173+ return fmt .Errorf ("failed to get rootfs mounts %q: %v" , id , err )
174+ }
175+
172176 // Create containerd container.
173177 createOpts := & execution.CreateRequest {
174178 ID : id ,
175179 Spec : & prototypes.Any {
176180 TypeUrl : runtimespec .Version ,
177181 Value : rawSpec ,
178182 },
179- // TODO(random-liu): [P0] Get rootfs mount from containerd.
180- Rootfs : []* mount.Mount {
181- {
182- Type : "bind" ,
183- Source : rootPath ,
184- Options : []string {
185- "rw" ,
186- "rbind" ,
187- },
188- },
189- },
183+ Rootfs : mountsResp .Mounts ,
190184 Runtime : defaultRuntime ,
191185 Stdin : stdin ,
192186 Stdout : stdout ,
193187 Stderr : stderr ,
194188 Terminal : config .GetTty (),
195189 }
196- glog .V (2 ).Infof ("Create containerd container (id=%q, name=%q) with options %+v." ,
190+ glog .V (5 ).Infof ("Create containerd container (id=%q, name=%q) with options %+v." ,
197191 id , meta .Name , createOpts )
198192 createResp , err := c .containerService .Create (ctx , createOpts )
199193 if err != nil {
@@ -219,7 +213,8 @@ func (c *criContainerdService) startContainer(ctx context.Context, id string, me
219213 return nil
220214}
221215
222- func (c * criContainerdService ) generateContainerSpec (id string , sandboxPid uint32 , config * runtime.ContainerConfig , sandboxConfig * runtime.PodSandboxConfig ) (* runtimespec.Spec , error ) {
216+ func (c * criContainerdService ) generateContainerSpec (id string , sandboxPid uint32 , config * runtime.ContainerConfig ,
217+ sandboxConfig * runtime.PodSandboxConfig , imageConfig * imagespec.ImageConfig ) (* runtimespec.Spec , error ) {
223218 // Creates a spec Generator with the default spec.
224219 // TODO(random-liu): [P2] Move container runtime spec generation into a helper function.
225220 g := generate .New ()
@@ -228,14 +223,21 @@ func (c *criContainerdService) generateContainerSpec(id string, sandboxPid uint3
228223 // pre-defined directory.
229224 g .SetRootPath (relativeRootfsPath )
230225
231- if len ( config . GetCommand ()) != 0 || len ( config . GetArgs ()) != 0 {
232- g . SetProcessArgs ( append ( config . GetCommand (), config . GetArgs () ... ))
226+ if err := setOCIProcessArgs ( & g , config , imageConfig ); err != nil {
227+ return nil , err
233228 }
234229
235230 if config .GetWorkingDir () != "" {
236231 g .SetProcessCwd (config .GetWorkingDir ())
232+ } else if imageConfig .WorkingDir != "" {
233+ g .SetProcessCwd (imageConfig .WorkingDir )
237234 }
238235
236+ // Apply envs from image config first, so that envs from container config
237+ // can override them.
238+ if err := addImageEnvs (& g , imageConfig .Env ); err != nil {
239+ return nil , err
240+ }
239241 for _ , e := range config .GetEnvs () {
240242 g .AddProcessEnv (e .GetKey (), e .GetValue ())
241243 }
@@ -288,6 +290,27 @@ func (c *criContainerdService) generateContainerSpec(id string, sandboxPid uint3
288290 return g .Spec (), nil
289291}
290292
293+ // setOCIProcessArgs sets process args. It returns error if the final arg list
294+ // is empty.
295+ func setOCIProcessArgs (g * generate.Generator , config * runtime.ContainerConfig , imageConfig * imagespec.ImageConfig ) error {
296+ command , args := config .GetCommand (), config .GetArgs ()
297+ // The following logic is migrated from https://github.com/moby/moby/blob/master/daemon/commit.go
298+ // TODO(random-liu): Figure out whether the following logic is
299+ if len (command ) == 0 {
300+ if len (args ) == 0 {
301+ args = imageConfig .Cmd
302+ }
303+ if command == nil {
304+ command = imageConfig .Entrypoint
305+ }
306+ }
307+ if len (command ) == 0 && len (args ) == 0 {
308+ return fmt .Errorf ("no command specified" )
309+ }
310+ g .SetProcessArgs (append (command , args ... ))
311+ return nil
312+ }
313+
291314// addOCIBindMounts adds bind mounts.
292315func addOCIBindMounts (g * generate.Generator , mounts []* runtime.Mount ) {
293316 for _ , mount := range mounts {
0 commit comments