func (g *Generator) DropLinuxResourcesBlockIOThrottleWriteBpsDevice(major int64, minor int64) {
	if g.Config == nil || g.Config.Linux == nil || g.Config.Linux.Resources == nil || g.Config.Linux.Resources.BlockIO == nil {
		return
	}
	throttleDevices := dropBlockIOThrottleDevice(g.Config.Linux.Resources.BlockIO.ThrottleWriteBpsDevice, major, minor)
	g.Config.Linux.Resources.BlockIO.ThrottleWriteBpsDevice = throttleDevices
}
DropLinuxResourcesBlockIOThrottleWriteBpsDevice drops a item from g.Config.Linux.Resources.BlockIO.ThrottleWriteBpsDevice.
package generate
import (
	"encoding/json"
	"fmt"
	"io"
	"os"
	"strings"
	rspec "github.com/opencontainers/runtime-spec/specs-go"
	"github.com/opencontainers/runtime-tools/generate/seccomp"
	"github.com/opencontainers/runtime-tools/validate"
	"github.com/syndtr/gocapability/capability"
)
var (
	Namespaces = []string{"network", "pid", "mount", "ipc", "uts", "user", "cgroup"}
	removeFunc = func(s []string, i int) []string {
		s[i] = s[len(s)-1]
		return s[:len(s)-1]
	}
)
type Generator struct {
	Config       *rspec.Spec
	HostSpecific bool
}
type ExportOptions struct {
	Seccomp bool  
}
func New(os string) (generator Generator, err error) {
	if os != "linux" && os != "solaris" && os != "windows" {
		return generator, fmt.Errorf("no defaults configured for %s", os)
	}
	config := rspec.Spec{
		Version:  rspec.Version,
		Hostname: "mrsdalloway",
	}
	if os == "windows" {
		config.Process = &rspec.Process{
			Args: []string{
				"cmd",
			},
			Cwd: `C:\`,
		}
		config.Windows = &rspec.Windows{}
	} else {
		config.Root = &rspec.Root{
			Path:     "rootfs",
			Readonly: false,
		}
		config.Process = &rspec.Process{
			Terminal: false,
			Args: []string{
				"sh",
			},
		}
	}
	if os == "linux" || os == "solaris" {
		config.Process.User = rspec.User{}
		config.Process.Env = []string{
			"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
			"TERM=xterm",
		}
		config.Process.Cwd = "/"
		config.Process.Rlimits = []rspec.POSIXRlimit{
			{
				Type: "RLIMIT_NOFILE",
				Hard: uint64(1024),
				Soft: uint64(1024),
			},
		}
	}
	if os == "linux" {
		config.Process.Capabilities = &rspec.LinuxCapabilities{
			Bounding: []string{
				"CAP_CHOWN",
				"CAP_DAC_OVERRIDE",
				"CAP_FSETID",
				"CAP_FOWNER",
				"CAP_MKNOD",
				"CAP_NET_RAW",
				"CAP_SETGID",
				"CAP_SETUID",
				"CAP_SETFCAP",
				"CAP_SETPCAP",
				"CAP_NET_BIND_SERVICE",
				"CAP_SYS_CHROOT",
				"CAP_KILL",
				"CAP_AUDIT_WRITE",
			},
			Permitted: []string{
				"CAP_CHOWN",
				"CAP_DAC_OVERRIDE",
				"CAP_FSETID",
				"CAP_FOWNER",
				"CAP_MKNOD",
				"CAP_NET_RAW",
				"CAP_SETGID",
				"CAP_SETUID",
				"CAP_SETFCAP",
				"CAP_SETPCAP",
				"CAP_NET_BIND_SERVICE",
				"CAP_SYS_CHROOT",
				"CAP_KILL",
				"CAP_AUDIT_WRITE",
			},
			Inheritable: []string{
				"CAP_CHOWN",
				"CAP_DAC_OVERRIDE",
				"CAP_FSETID",
				"CAP_FOWNER",
				"CAP_MKNOD",
				"CAP_NET_RAW",
				"CAP_SETGID",
				"CAP_SETUID",
				"CAP_SETFCAP",
				"CAP_SETPCAP",
				"CAP_NET_BIND_SERVICE",
				"CAP_SYS_CHROOT",
				"CAP_KILL",
				"CAP_AUDIT_WRITE",
			},
			Effective: []string{
				"CAP_CHOWN",
				"CAP_DAC_OVERRIDE",
				"CAP_FSETID",
				"CAP_FOWNER",
				"CAP_MKNOD",
				"CAP_NET_RAW",
				"CAP_SETGID",
				"CAP_SETUID",
				"CAP_SETFCAP",
				"CAP_SETPCAP",
				"CAP_NET_BIND_SERVICE",
				"CAP_SYS_CHROOT",
				"CAP_KILL",
				"CAP_AUDIT_WRITE",
			},
			Ambient: []string{
				"CAP_CHOWN",
				"CAP_DAC_OVERRIDE",
				"CAP_FSETID",
				"CAP_FOWNER",
				"CAP_MKNOD",
				"CAP_NET_RAW",
				"CAP_SETGID",
				"CAP_SETUID",
				"CAP_SETFCAP",
				"CAP_SETPCAP",
				"CAP_NET_BIND_SERVICE",
				"CAP_SYS_CHROOT",
				"CAP_KILL",
				"CAP_AUDIT_WRITE",
			},
		}
		config.Mounts = []rspec.Mount{
			{
				Destination: "/proc",
				Type:        "proc",
				Source:      "proc",
				Options:     []string{"nosuid", "noexec", "nodev"},
			},
			{
				Destination: "/dev",
				Type:        "tmpfs",
				Source:      "tmpfs",
				Options:     []string{"nosuid", "strictatime", "mode=755", "size=65536k"},
			},
			{
				Destination: "/dev/pts",
				Type:        "devpts",
				Source:      "devpts",
				Options:     []string{"nosuid", "noexec", "newinstance", "ptmxmode=0666", "mode=0620", "gid=5"},
			},
			{
				Destination: "/dev/shm",
				Type:        "tmpfs",
				Source:      "shm",
				Options:     []string{"nosuid", "noexec", "nodev", "mode=1777", "size=65536k"},
			},
			{
				Destination: "/dev/mqueue",
				Type:        "mqueue",
				Source:      "mqueue",
				Options:     []string{"nosuid", "noexec", "nodev"},
			},
			{
				Destination: "/sys",
				Type:        "sysfs",
				Source:      "sysfs",
				Options:     []string{"nosuid", "noexec", "nodev", "ro"},
			},
		}
		config.Linux = &rspec.Linux{
			Resources: &rspec.LinuxResources{
				Devices: []rspec.LinuxDeviceCgroup{
					{
						Allow:  false,
						Access: "rwm",
					},
				},
			},
			Namespaces: []rspec.LinuxNamespace{
				{
					Type: "pid",
				},
				{
					Type: "network",
				},
				{
					Type: "ipc",
				},
				{
					Type: "uts",
				},
				{
					Type: "mount",
				},
			},
			Seccomp: seccomp.DefaultProfile(&config),
		}
	}
	return Generator{Config: &config}, nil
}
func NewFromSpec(config *rspec.Spec) Generator {
	return Generator{
		Config: config,
	}
}
func NewFromFile(path string) (Generator, error) {
	cf, err := os.Open(path)
	if err != nil {
		if os.IsNotExist(err) {
			return Generator{}, fmt.Errorf("template configuration at %s not found", path)
		}
		return Generator{}, err
	}
	defer cf.Close()
	return NewFromTemplate(cf)
}
func NewFromTemplate(r io.Reader) (Generator, error) {
	var config rspec.Spec
	if err := json.NewDecoder(r).Decode(&config); err != nil {
		return Generator{}, err
	}
	return Generator{
		Config: &config,
	}, nil
}
func (g *Generator) SetSpec(config *rspec.Spec) {
	g.Config = config
}
func (g *Generator) Spec() *rspec.Spec {
	return g.Config
}
func (g *Generator) Save(w io.Writer, exportOpts ExportOptions) (err error) {
	var data []byte
	if g.Config.Linux != nil {
		buf, err := json.Marshal(g.Config.Linux)
		if err != nil {
			return err
		}
		if string(buf) == "{}" {
			g.Config.Linux = nil
		}
	}
	if exportOpts.Seccomp {
		data, err = json.MarshalIndent(g.Config.Linux.Seccomp, "", "\t")
	} else {
		data, err = json.MarshalIndent(g.Config, "", "\t")
	}
	if err != nil {
		return err
	}
	_, err = w.Write(data)
	if err != nil {
		return err
	}
	return nil
}
func (g *Generator) SaveToFile(path string, exportOpts ExportOptions) error {
	f, err := os.Create(path)
	if err != nil {
		return err
	}
	defer f.Close()
	return g.Save(f, exportOpts)
}
func (g *Generator) SetVersion(version string) {
	g.initConfig()
	g.Config.Version = version
}
func (g *Generator) SetRootPath(path string) {
	g.initConfigRoot()
	g.Config.Root.Path = path
}
func (g *Generator) SetRootReadonly(b bool) {
	g.initConfigRoot()
	g.Config.Root.Readonly = b
}
func (g *Generator) SetHostname(s string) {
	g.initConfig()
	g.Config.Hostname = s
}
func (g *Generator) SetOCIVersion(s string) {
	g.initConfig()
	g.Config.Version = s
}
func (g *Generator) ClearAnnotations() {
	if g.Config == nil {
		return
	}
	g.Config.Annotations = make(map[string]string)
}
func (g *Generator) AddAnnotation(key, value string) {
	g.initConfigAnnotations()
	g.Config.Annotations[key] = value
}
func (g *Generator) RemoveAnnotation(key string) {
	if g.Config == nil || g.Config.Annotations == nil {
		return
	}
	delete(g.Config.Annotations, key)
}
func (g *Generator) RemoveHostname() {
	if g.Config == nil {
		return
	}
	g.Config.Hostname = ""
}
func (g *Generator) SetProcessConsoleSize(width, height uint) {
	g.initConfigProcessConsoleSize()
	g.Config.Process.ConsoleSize.Width = width
	g.Config.Process.ConsoleSize.Height = height
}
func (g *Generator) SetProcessUID(uid uint32) {
	g.initConfigProcess()
	g.Config.Process.User.UID = uid
}
func (g *Generator) SetProcessUsername(username string) {
	g.initConfigProcess()
	g.Config.Process.User.Username = username
}
func (g *Generator) SetProcessGID(gid uint32) {
	g.initConfigProcess()
	g.Config.Process.User.GID = gid
}
func (g *Generator) SetProcessCwd(cwd string) {
	g.initConfigProcess()
	g.Config.Process.Cwd = cwd
}
func (g *Generator) SetProcessNoNewPrivileges(b bool) {
	g.initConfigProcess()
	g.Config.Process.NoNewPrivileges = b
}
func (g *Generator) SetProcessTerminal(b bool) {
	g.initConfigProcess()
	g.Config.Process.Terminal = b
}
func (g *Generator) SetProcessApparmorProfile(prof string) {
	g.initConfigProcess()
	g.Config.Process.ApparmorProfile = prof
}
func (g *Generator) SetProcessArgs(args []string) {
	g.initConfigProcess()
	g.Config.Process.Args = args
}
func (g *Generator) ClearProcessEnv() {
	if g.Config == nil || g.Config.Process == nil {
		return
	}
	g.Config.Process.Env = []string{}
}
func (g *Generator) AddProcessEnv(name, value string) {
	g.initConfigProcess()
	env := fmt.Sprintf("%s=%s", name, value)
	for idx := range g.Config.Process.Env {
		if strings.HasPrefix(g.Config.Process.Env[idx], name+"=") {
			g.Config.Process.Env[idx] = env
			return
		}
	}
	g.Config.Process.Env = append(g.Config.Process.Env, env)
}
func (g *Generator) AddProcessRlimits(rType string, rHard uint64, rSoft uint64) {
	g.initConfigProcess()
	for i, rlimit := range g.Config.Process.Rlimits {
		if rlimit.Type == rType {
			g.Config.Process.Rlimits[i].Hard = rHard
			g.Config.Process.Rlimits[i].Soft = rSoft
			return
		}
	}
	newRlimit := rspec.POSIXRlimit{
		Type: rType,
		Hard: rHard,
		Soft: rSoft,
	}
	g.Config.Process.Rlimits = append(g.Config.Process.Rlimits, newRlimit)
}
func (g *Generator) RemoveProcessRlimits(rType string) {
	if g.Config == nil || g.Config.Process == nil {
		return
	}
	for i, rlimit := range g.Config.Process.Rlimits {
		if rlimit.Type == rType {
			g.Config.Process.Rlimits = append(g.Config.Process.Rlimits[:i], g.Config.Process.Rlimits[i+1:]...)
			return
		}
	}
}
func (g *Generator) ClearProcessRlimits() {
	if g.Config == nil || g.Config.Process == nil {
		return
	}
	g.Config.Process.Rlimits = []rspec.POSIXRlimit{}
}
func (g *Generator) ClearProcessAdditionalGids() {
	if g.Config == nil || g.Config.Process == nil {
		return
	}
	g.Config.Process.User.AdditionalGids = []uint32{}
}
func (g *Generator) AddProcessAdditionalGid(gid uint32) {
	g.initConfigProcess()
	for _, group := range g.Config.Process.User.AdditionalGids {
		if group == gid {
			return
		}
	}
	g.Config.Process.User.AdditionalGids = append(g.Config.Process.User.AdditionalGids, gid)
}
func (g *Generator) SetProcessSelinuxLabel(label string) {
	g.initConfigProcess()
	g.Config.Process.SelinuxLabel = label
}
func (g *Generator) SetLinuxCgroupsPath(path string) {
	g.initConfigLinux()
	g.Config.Linux.CgroupsPath = path
}
func (g *Generator) SetLinuxIntelRdtL3CacheSchema(schema string) {
	g.initConfigLinuxIntelRdt()
	g.Config.Linux.IntelRdt.L3CacheSchema = schema
}
func (g *Generator) SetLinuxMountLabel(label string) {
	g.initConfigLinux()
	g.Config.Linux.MountLabel = label
}
func (g *Generator) SetProcessOOMScoreAdj(adj int) {
	g.initConfigProcess()
	g.Config.Process.OOMScoreAdj = &adj
}
func (g *Generator) SetLinuxResourcesBlockIOLeafWeight(weight uint16) {
	g.initConfigLinuxResourcesBlockIO()
	g.Config.Linux.Resources.BlockIO.LeafWeight = &weight
}
func (g *Generator) AddLinuxResourcesBlockIOLeafWeightDevice(major int64, minor int64, weight uint16) {
	g.initConfigLinuxResourcesBlockIO()
	for i, weightDevice := range g.Config.Linux.Resources.BlockIO.WeightDevice {
		if weightDevice.Major == major && weightDevice.Minor == minor {
			g.Config.Linux.Resources.BlockIO.WeightDevice[i].LeafWeight = &weight
			return
		}
	}
	weightDevice := new(rspec.LinuxWeightDevice)
	weightDevice.Major = major
	weightDevice.Minor = minor
	weightDevice.LeafWeight = &weight
	g.Config.Linux.Resources.BlockIO.WeightDevice = append(g.Config.Linux.Resources.BlockIO.WeightDevice, *weightDevice)
}
func (g *Generator) DropLinuxResourcesBlockIOLeafWeightDevice(major int64, minor int64) {
	if g.Config == nil || g.Config.Linux == nil || g.Config.Linux.Resources == nil || g.Config.Linux.Resources.BlockIO == nil {
		return
	}
	for i, weightDevice := range g.Config.Linux.Resources.BlockIO.WeightDevice {
		if weightDevice.Major == major && weightDevice.Minor == minor {
			if weightDevice.Weight != nil {
				newWeightDevice := new(rspec.LinuxWeightDevice)
				newWeightDevice.Major = major
				newWeightDevice.Minor = minor
				newWeightDevice.Weight = weightDevice.Weight
				g.Config.Linux.Resources.BlockIO.WeightDevice[i] = *newWeightDevice
			} else {
				g.Config.Linux.Resources.BlockIO.WeightDevice = append(g.Config.Linux.Resources.BlockIO.WeightDevice[:i], g.Config.Linux.Resources.BlockIO.WeightDevice[i+1:]...)
			}
			return
		}
	}
}
func (g *Generator) SetLinuxResourcesBlockIOWeight(weight uint16) {
	g.initConfigLinuxResourcesBlockIO()
	g.Config.Linux.Resources.BlockIO.Weight = &weight
}
func (g *Generator) AddLinuxResourcesBlockIOWeightDevice(major int64, minor int64, weight uint16) {
	g.initConfigLinuxResourcesBlockIO()
	for i, weightDevice := range g.Config.Linux.Resources.BlockIO.WeightDevice {
		if weightDevice.Major == major && weightDevice.Minor == minor {
			g.Config.Linux.Resources.BlockIO.WeightDevice[i].Weight = &weight
			return
		}
	}
	weightDevice := new(rspec.LinuxWeightDevice)
	weightDevice.Major = major
	weightDevice.Minor = minor
	weightDevice.Weight = &weight
	g.Config.Linux.Resources.BlockIO.WeightDevice = append(g.Config.Linux.Resources.BlockIO.WeightDevice, *weightDevice)
}
func (g *Generator) DropLinuxResourcesBlockIOWeightDevice(major int64, minor int64) {
	if g.Config == nil || g.Config.Linux == nil || g.Config.Linux.Resources == nil || g.Config.Linux.Resources.BlockIO == nil {
		return
	}
	for i, weightDevice := range g.Config.Linux.Resources.BlockIO.WeightDevice {
		if weightDevice.Major == major && weightDevice.Minor == minor {
			if weightDevice.LeafWeight != nil {
				newWeightDevice := new(rspec.LinuxWeightDevice)
				newWeightDevice.Major = major
				newWeightDevice.Minor = minor
				newWeightDevice.LeafWeight = weightDevice.LeafWeight
				g.Config.Linux.Resources.BlockIO.WeightDevice[i] = *newWeightDevice
			} else {
				g.Config.Linux.Resources.BlockIO.WeightDevice = append(g.Config.Linux.Resources.BlockIO.WeightDevice[:i], g.Config.Linux.Resources.BlockIO.WeightDevice[i+1:]...)
			}
			return
		}
	}
}
func (g *Generator) AddLinuxResourcesBlockIOThrottleReadBpsDevice(major int64, minor int64, rate uint64) {
	g.initConfigLinuxResourcesBlockIO()
	throttleDevices := addOrReplaceBlockIOThrottleDevice(g.Config.Linux.Resources.BlockIO.ThrottleReadBpsDevice, major, minor, rate)
	g.Config.Linux.Resources.BlockIO.ThrottleReadBpsDevice = throttleDevices
}
func (g *Generator) DropLinuxResourcesBlockIOThrottleReadBpsDevice(major int64, minor int64) {
	if g.Config == nil || g.Config.Linux == nil || g.Config.Linux.Resources == nil || g.Config.Linux.Resources.BlockIO == nil {
		return
	}
	throttleDevices := dropBlockIOThrottleDevice(g.Config.Linux.Resources.BlockIO.ThrottleReadBpsDevice, major, minor)
	g.Config.Linux.Resources.BlockIO.ThrottleReadBpsDevice = throttleDevices
}
func (g *Generator) AddLinuxResourcesBlockIOThrottleReadIOPSDevice(major int64, minor int64, rate uint64) {
	g.initConfigLinuxResourcesBlockIO()
	throttleDevices := addOrReplaceBlockIOThrottleDevice(g.Config.Linux.Resources.BlockIO.ThrottleReadIOPSDevice, major, minor, rate)
	g.Config.Linux.Resources.BlockIO.ThrottleReadIOPSDevice = throttleDevices
}
func (g *Generator) DropLinuxResourcesBlockIOThrottleReadIOPSDevice(major int64, minor int64) {
	if g.Config == nil || g.Config.Linux == nil || g.Config.Linux.Resources == nil || g.Config.Linux.Resources.BlockIO == nil {
		return
	}
	throttleDevices := dropBlockIOThrottleDevice(g.Config.Linux.Resources.BlockIO.ThrottleReadIOPSDevice, major, minor)
	g.Config.Linux.Resources.BlockIO.ThrottleReadIOPSDevice = throttleDevices
}
func (g *Generator) AddLinuxResourcesBlockIOThrottleWriteBpsDevice(major int64, minor int64, rate uint64) {
	g.initConfigLinuxResourcesBlockIO()
	throttleDevices := addOrReplaceBlockIOThrottleDevice(g.Config.Linux.Resources.BlockIO.ThrottleWriteBpsDevice, major, minor, rate)
	g.Config.Linux.Resources.BlockIO.ThrottleWriteBpsDevice = throttleDevices
}