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
}
Example #2
0
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
}
Example #4
0
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
}
Example #5
0
			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"},