func (factory *gardenContainerSpecFactory) BuildTaskContainerSpec( spec TaskContainerSpec, gardenSpec garden.ContainerSpec, cancel <-chan os.Signal, delegate ImageFetchingDelegate, id Identifier, metadata Metadata, workerClient Client, ) (garden.ContainerSpec, error) { if spec.ImageResourcePointer == nil { gardenSpec.RootFSPath = spec.Image } gardenSpec.Privileged = spec.Privileged var err error gardenSpec, err = factory.createVolumes(gardenSpec, spec.Inputs) if err != nil { return gardenSpec, err } for _, mount := range spec.Outputs { volume := mount.Volume gardenSpec.BindMounts = append(gardenSpec.BindMounts, garden.BindMount{ SrcPath: volume.Path(), DstPath: mount.MountPath, Mode: garden.BindMountModeRW, }) factory.volumeHandles = append(factory.volumeHandles, volume.Handle()) factory.volumeMounts[volume.Handle()] = mount.MountPath } return gardenSpec, nil }
func (worker *gardenWorker) CreateContainer(id Identifier, spec ContainerSpec) (Container, error) { gardenSpec := garden.ContainerSpec{ Properties: id.gardenProperties(), } dance: switch s := spec.(type) { case ResourceTypeContainerSpec: gardenSpec.Privileged = true if s.Ephemeral { gardenSpec.Properties[ephemeralPropertyName] = "true" } for _, t := range worker.resourceTypes { if t.Type == s.Type { gardenSpec.RootFSPath = t.Image break dance } } return nil, ErrUnsupportedResourceType case TaskContainerSpec: gardenSpec.RootFSPath = s.Image gardenSpec.Privileged = s.Privileged default: return nil, fmt.Errorf("unknown container spec type: %T (%#v)", s, s) } gardenContainer, err := worker.gardenClient.Create(gardenSpec) if err != nil { return nil, err } return newGardenWorkerContainer(gardenContainer, worker.gardenClient, worker.clock), nil }
func (factory *gardenContainerSpecFactory) BuildResourceContainerSpec( spec ResourceTypeContainerSpec, gardenSpec garden.ContainerSpec, resourceTypes []atc.WorkerResourceType, ) (garden.ContainerSpec, error) { if len(spec.Mounts) > 0 && spec.Cache.Volume != nil { return gardenSpec, errors.New("a container may not have mounts and a cache") } gardenSpec.Privileged = true gardenSpec.Env = append(gardenSpec.Env, spec.Env...) if spec.Ephemeral { gardenSpec.Properties[ephemeralPropertyName] = "true" } if spec.Cache.Volume != nil && spec.Cache.MountPath != "" { gardenSpec.BindMounts = []garden.BindMount{ { SrcPath: spec.Cache.Volume.Path(), DstPath: spec.Cache.MountPath, Mode: garden.BindMountModeRW, }, } factory.volumeHandles = append(factory.volumeHandles, spec.Cache.Volume.Handle()) factory.volumeMounts[spec.Cache.Volume.Handle()] = spec.Cache.MountPath } var err error gardenSpec, err = factory.createVolumes(gardenSpec, spec.Mounts) if err != nil { return gardenSpec, err } if spec.ImageResourcePointer == nil { for _, t := range resourceTypes { if t.Type == spec.Type { gardenSpec.RootFSPath = t.Image return gardenSpec, nil } } return gardenSpec, ErrUnsupportedResourceType } return gardenSpec, nil }
func (c *RuncContainerCreator) Create(spec garden.ContainerSpec) (*Container, error) { dir, err := c.Depot.Create() if err != nil { return nil, fmt.Errorf("create depot dir: %s", err) } if len(spec.RootFSPath) == 0 { spec.RootFSPath = c.DefaultRootfs } rootfs, err := url.Parse(spec.RootFSPath) if err != nil { return nil, fmt.Errorf("create: not a valid rootfs path: %s", err) } if _, err := exec.Command("cp", "-r", rootfs.Path, path.Join(dir, "rootfs")).CombinedOutput(); err != nil { return nil, fmt.Errorf("create: copy rootfs: %s", err) } runcSpec := runc.PortableSpec{ Version: "0.1", OS: runtime.GOOS, Arch: runtime.GOARCH, Cpus: 1.1, Memory: 1024, Root: runc.Root{ Path: "rootfs", Readonly: false, }, Namespaces: []runc.Namespace{ { Type: "process", }, { Type: "network", }, { Type: "mount", }, { Type: "ipc", }, { Type: "uts", }, }, Devices: []string{ "null", "random", "full", "tty", "zero", "urandom", }, Mounts: []runc.Mount{ { Type: "proc", Source: "proc", Destination: "/proc", Options: "", }, { Type: "tmpfs", Source: "tmpfs", Destination: "/dev", Options: "nosuid,strictatime,mode=755,size=65536k", }, { Type: "devpts", Source: "devpts", Destination: "/dev/pts", Options: "nosuid,noexec,newinstance,ptmxmode=0666,mode=0620,gid=5", }, { Type: "tmpfs", Source: "shm", Destination: "/dev/shm", Options: "nosuid,noexec,nodev,mode=1777,size=65536k", }, { Type: "mqueue", Source: "mqueue", Destination: "/dev/mqueue", Options: "nosuid,noexec,nodev", }, { Type: "sysfs", Source: "sysfs", Destination: "/sys", Options: "nosuid,noexec,nodev", }, { Type: "bind", Source: c.InitdPath, Destination: "/garden-bin/initd", Options: "bind", }, { Type: "bind", Source: path.Join(dir, "run"), Destination: "/run/garden", Options: "bind", }}, Processes: []*runc.Process{{ // User: "******", // Args: []string{ // "/bin/ls", "-lR", "/garden-bin", // }, // }}, User: "******", Args: []string{ "/garden-bin/initd", "-socket", "/run/garden/initd.sock", "-unmountAfterListening", "/run/garden", }, }}, } data, err := json.MarshalIndent(&runcSpec, "", "\t") if err != nil { return nil, fmt.Errorf("create: marshal runc spec: %s", err) } err = ioutil.WriteFile(path.Join(dir, "container.json"), data, 0700) if err != nil { return nil, fmt.Errorf("create: write runc spec: %s", err) } os.Setenv("CGO_ENABLED", "1") runcBin, err := gexec.Build("github.com/opencontainers/runc") if err != nil { return nil, fmt.Errorf("create: build runc: %s", err) } runcCommand := exec.Command(runcBin) runcCommand.Dir = dir if err := c.CommandRunner.Start(runcCommand); err != nil { return nil, fmt.Errorf("create: start runc container: %s", err) } time.Sleep(2 * time.Second) return &Container{ LimitsHandler: &LimitsHandler{}, StreamHandler: &StreamHandler{}, InfoHandler: &InfoHandler{ Spec: spec, ContainerPath: dir, PropsHandler: &PropsHandler{}, }, NetHandler: &NetHandler{ Chain: c.Chain, PortPool: c.PortPool, }, RunHandler: &RunHandler{ ProcessTracker: process_tracker.New(dir, c.CommandRunner), ContainerCmd: &doshcmd{ Path: filepath.Join(dir, "bin", "dosh"), InitdSock: filepath.Join(dir, "run", "initd.sock"), }, }, }, nil }
Eventually(client).Should(gbytes.Say(`container.start.ended","log_level":0,"data":{"handle":"kumquat"`)) }) It("should not log any environment variables", func() { Consistently(client).ShouldNot(gbytes.Say("PASSWORD")) Consistently(client).ShouldNot(gbytes.Say("MY_SECRET")) }) It("should not log any properties", func() { Consistently(client).ShouldNot(gbytes.Say("super")) Consistently(client).ShouldNot(gbytes.Say("banana")) }) Context("from a docker url", func() { BeforeEach(func() { containerSpec.RootFSPath = "docker:///cloudfoundry/with-volume" }) It("should not log any environment variables", func() { Consistently(client).ShouldNot(gbytes.Say("test-from-dockerfile")) }) }) }) Context("when container spawn a new process", func() { It("should not log any environment variables and command line arguments", func() { process, err := container.Run(garden.ProcessSpec{ User: "******", Path: "echo", Args: []string{"-username", "banana"}, Env: []string{"PASSWORD=MY_SECRET"},