<commit_before>package peas

import (
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"code.cloudfoundry.org/garden"
	"code.cloudfoundry.org/guardian/gardener"
	spec "code.cloudfoundry.org/guardian/gardener/container-spec"
	"code.cloudfoundry.org/guardian/rundmc/depot"
	"code.cloudfoundry.org/guardian/rundmc/runrunc"
	"code.cloudfoundry.org/lager"
	multierror "github.com/hashicorp/go-multierror"
	uuid "github.com/nu7hatch/gouuid"
	specs "github.com/opencontainers/runtime-spec/specs-go"
	errorwrapper "github.com/pkg/errors"
)

var RootfsPath = filepath.Join(os.TempDir(), "pea-empty-rootfs")

//go:generate counterfeiter . Volumizer
type Volumizer interface {
	Create(log lager.Logger, spec garden.ContainerSpec) (specs.Spec, error)
	Destroy(log lager.Logger, handle string) error
}

//go:generate counterfeiter . PidGetter
type PidGetter interface {
	GetPid(log lager.Logger, handle string) (int, error)
}

//go:generate counterfeiter . PrivilegedGetter
type PrivilegedGetter interface {
	Privileged(bundlePath string) (bool, error)
}

//go:generate counterfeiter . RuncDeleter
type RuncDeleter interface {
	Delete(log lager.Logger, force bool, handle string) error
}

type PeaCreator struct {
	Volumizer              Volumizer
	PidGetter              PidGetter
	PrivilegedGetter       PrivilegedGetter
	BindMountSourceCreator depot.BindMountSourceCreator
	BundleGenerator        depot.BundleGenerator
	BundleSaver            depot.BundleSaver
	ProcessBuilder         runrunc.ProcessBuilder
	ExecRunner             runrunc.ExecRunner
	RuncDeleter            RuncDeleter
	PeaCleaner             gardener.PeaCleaner
}

func (p *PeaCreator) CreatePea(log lager.Logger, processSpec garden.ProcessSpec, procIO garden.ProcessIO, sandboxHandle, sandboxBundlePath string) (_ garden.Process, theErr error) {
	errs := func(action string, err error) (garden.Process, error) {
		wrappedErr := errorwrapper.Wrap(err, action)
		log.Error(action, wrappedErr)
		return nil, wrappedErr
	}

	log = log.Session("create-pea", lager.Data{})

	processID, err := generateProcessID(processSpec.ID)
	if err != nil {
		return nil, err
	}

	log.Info("creating", lager.Data{"process_id": processID})
	defer log.Info("done")

	privileged, err := p.PrivilegedGetter.Privileged(sandboxBundlePath)
	if err != nil {
		return errs("determining-privileged", err)
	}

	defaultBindMounts, err := p.BindMountSourceCreator.Create(sandboxBundlePath, !privileged)
	if err != nil {
		return errs("creating-bind-mount-sources", err)
	}

	if processSpec.Dir == "" {
		processSpec.Dir = "/"
	}
	userUID, userGID, err := parseUser(processSpec.User)
	if err != nil {
		return errs("parse-user", err)
	}

	linuxNamespaces, err := p.linuxNamespaces(log, sandboxHandle, privileged)
	if err != nil {
		return errs("determining-namespaces", err)
	}

	runtimeSpec, err := p.Volumizer.Create(log, garden.ContainerSpec{
		Handle:     processID,
		Image:      processSpec.Image,
		Privileged: privileged,
	})
	if err != nil {
		return errs("creating-volume", err)
	}

	if runtimeSpec.Windows == nil {
		runtimeSpec.Windows = new(specs.Windows)
	}

	runtimeSpec.Windows.Network = &specs.WindowsNetwork{
		NetworkSharedContainerName: sandboxHandle,
	}

	cgroupPath := sandboxHandle
	limits := garden.Limits{}
	if processSpec.OverrideContainerLimits != nil {
		cgroupPath = processID
		limits = garden.Limits{
			CPU:    processSpec.OverrideContainerLimits.CPU,
			Memory: processSpec.OverrideContainerLimits.Memory,
		}
	}

	bndl, genErr := p.BundleGenerator.Generate(spec.DesiredContainerSpec{
		Handle:     processID,
		BaseConfig: runtimeSpec,
		CgroupPath: cgroupPath,
		Limits:     limits,
		Namespaces: linuxNamespaces,
		BindMounts: append(processSpec.BindMounts, defaultBindMounts...),
		Privileged: privileged,
	}, sandboxBundlePath)
	if genErr != nil {
		destroyErr := p.Volumizer.Destroy(log, processID)
		return errs("generating-bundle", multierror.Append(genErr, destroyErr))
	}

	peaBundlePath := filepath.Join(sandboxBundlePath, "processes", processID)
	if mkdirErr := os.MkdirAll(peaBundlePath, 0700); mkdirErr != nil {
		return nil, err
	}
	defer func() {
		if theErr != nil {
			err := os.RemoveAll(peaBundlePath)
			if err != nil {
				log.Info("failed-to-remove-pea-process-dir: "+err.Error(), lager.Data{"process_id": processID})
			}
		}
	}()

	preparedProcess := p.ProcessBuilder.BuildProcess(bndl, processSpec, userUID, userGID)

	bndl = bndl.WithProcess(*preparedProcess)
	if saveErr := p.BundleSaver.Save(bndl, peaBundlePath); saveErr != nil {
		destroyErr := p.Volumizer.Destroy(log, processID)
		return errs("saving-bundle", multierror.Append(saveErr, destroyErr))
	}

	extraCleanup := func() error {
		return p.PeaCleaner.Clean(log, processID)
	}

	proc, runErr := p.ExecRunner.Run(
		log, processID, peaBundlePath, sandboxHandle, sandboxBundlePath,<commit_msg>Clean up PeaCreator.CreatePea a bit<commit_after>package peas

import (
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"code.cloudfoundry.org/garden"
	"code.cloudfoundry.org/guardian/gardener"
	spec "code.cloudfoundry.org/guardian/gardener/container-spec"
	"code.cloudfoundry.org/guardian/rundmc/depot"
	"code.cloudfoundry.org/guardian/rundmc/runrunc"
	"code.cloudfoundry.org/lager"
	multierror "github.com/hashicorp/go-multierror"
	uuid "github.com/nu7hatch/gouuid"
	specs "github.com/opencontainers/runtime-spec/specs-go"
	errorwrapper "github.com/pkg/errors"
)

var RootfsPath = filepath.Join(os.TempDir(), "pea-empty-rootfs")

//go:generate counterfeiter . Volumizer
type Volumizer interface {
	Create(log lager.Logger, spec garden.ContainerSpec) (specs.Spec, error)
	Destroy(log lager.Logger, handle string) error
}

//go:generate counterfeiter . PidGetter
type PidGetter interface {
	GetPid(log lager.Logger, handle string) (int, error)
}

//go:generate counterfeiter . PrivilegedGetter
type PrivilegedGetter interface {
	Privileged(bundlePath string) (bool, error)
}

//go:generate counterfeiter . RuncDeleter
type RuncDeleter interface {
	Delete(log lager.Logger, force bool, handle string) error
}

type PeaCreator struct {
	Volumizer              Volumizer
	PidGetter              PidGetter
	PrivilegedGetter       PrivilegedGetter
	BindMountSourceCreator depot.BindMountSourceCreator
	BundleGenerator        depot.BundleGenerator
	BundleSaver            depot.BundleSaver
	ProcessBuilder         runrunc.ProcessBuilder
	ExecRunner             runrunc.ExecRunner
	RuncDeleter            RuncDeleter
	PeaCleaner             gardener.PeaCleaner
}

func (p *PeaCreator) CreatePea(log lager.Logger, processSpec garden.ProcessSpec, procIO garden.ProcessIO, sandboxHandle, sandboxBundlePath string) (_ garden.Process, theErr error) {
	errs := func(action string, err error) (garden.Process, error) {
		wrappedErr := errorwrapper.Wrap(err, action)
		log.Error(action, wrappedErr)
		return nil, wrappedErr
	}

	log = log.Session("create-pea", lager.Data{})

	processID, err := generateProcessID(processSpec.ID)
	if err != nil {
		return nil, err
	}

	log.Info("creating", lager.Data{"process_id": processID})
	defer log.Info("done")

	privileged, err := p.PrivilegedGetter.Privileged(sandboxBundlePath)
	if err != nil {
		return errs("determining-privileged", err)
	}

	defaultBindMounts, err := p.BindMountSourceCreator.Create(sandboxBundlePath, !privileged)
	if err != nil {
		return errs("creating-bind-mount-sources", err)
	}

	if processSpec.Dir == "" {
		processSpec.Dir = "/"
	}
	userUID, userGID, err := parseUser(processSpec.User)
	if err != nil {
		return errs("parse-user", err)
	}

	linuxNamespaces, err := p.linuxNamespaces(log, sandboxHandle, privileged)
	if err != nil {
		return errs("determining-namespaces", err)
	}

	runtimeSpec, err := p.Volumizer.Create(log, garden.ContainerSpec{
		Handle:     processID,
		Image:      processSpec.Image,
		Privileged: privileged,
	})
	if err != nil {
		return errs("creating-volume", err)
	}

	if runtimeSpec.Windows == nil {
		runtimeSpec.Windows = new(specs.Windows)
	}

	runtimeSpec.Windows.Network = &specs.WindowsNetwork{
		NetworkSharedContainerName: sandboxHandle,
	}

	cgroupPath := sandboxHandle
	limits := garden.Limits{}
	if processSpec.OverrideContainerLimits != nil {
		cgroupPath = processID
		limits = garden.Limits{
			CPU:    processSpec.OverrideContainerLimits.CPU,
			Memory: processSpec.OverrideContainerLimits.Memory,
		}
	}

	bndl, genErr := p.BundleGenerator.Generate(spec.DesiredContainerSpec{
		Handle:     processID,
		BaseConfig: runtimeSpec,
		CgroupPath: cgroupPath,
		Limits:     limits,
		Namespaces: linuxNamespaces,
		BindMounts: append(processSpec.BindMounts, defaultBindMounts...),
		Privileged: privileged,
	}, sandboxBundlePath)
	if genErr != nil {
		destroyErr := p.Volumizer.Destroy(log, processID)
		return errs("generating-bundle", multierror.Append(genErr, destroyErr))
	}

	peaBundlePath := filepath.Join(sandboxBundlePath, "processes", processID)
	if mkdirErr := os.MkdirAll(peaBundlePath, 0700); mkdirErr != nil {
		return nil, err
	}
	defer func() {
		if theErr == nil {
			return
		}

		if err := os.RemoveAll(peaBundlePath); err != nil {
			log.Info("failed-to-remove-pea-process-dir: "+err.Error(), lager.Data{"process_id": processID})
		}
	}()

	preparedProcess := p.ProcessBuilder.BuildProcess(bndl, processSpec, userUID, userGID)

	bndl = bndl.WithProcess(*preparedProcess)
	if saveErr := p.BundleSaver.Save(bndl, peaBundlePath); saveErr != nil {
		destroyErr := p.Volumizer.Destroy(log, processID)
		return errs("saving-bundle", multierror.Append(saveErr, destroyErr))
	}

	extraCleanup := func() error {
		return p.PeaCleaner.Clean(log, processID)
	}

	proc, runErr := p.ExecRunner.Run(
		log, processID, peaBundlePath, sandboxHandle, sandboxBundlePath,
{'fraction_non_alphanumeric': 0.11692054343351173, 'fraction_numerical': 0.0010292301358583778, 'mean_word_length': 4.505382436260623, 'pattern_counts': {'":': 4, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '633890', 'n_tokens_mistral': 3475, 'n_tokens_neox': 3342, 'n_words': 648}