vorteil/vorteil

View on GitHub
pkg/cli/vcfg-flags.go

Summary

Maintainability
A
2 hrs
Test Coverage
A
93%
package cli

/**
 * SPDX-License-Identifier: Apache-2.0
 * Copyright 2020 vorteil.io Pty Ltd
 */

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

    "github.com/mattn/go-shellwords"
    "github.com/vorteil/vorteil/pkg/flag"
    "github.com/vorteil/vorteil/pkg/vcfg"
)

var (
    hideFlags        = false
    maxRedirectFlags int
    maxNetworkFlags  int
    maxProgramFlags  int
    maxNFSFlags      int
    maxLoggingFlags  int
)

func init() {
    // fixes a flag parsing issue
    if runtime.GOOS == "windows" {
        for i := range os.Args {
            splitQuote := strings.Split(os.Args[i], "\"")
            _, err := os.Stat(splitQuote[0])
            if err == nil {
                os.Args[i] = filepath.ToSlash(splitQuote[0])
            }
        }
    }

    args, err := shellwords.Parse(strings.Join(os.Args, " "))
    if err != nil {
        // panic(err)
    }

    for _, arg := range args {
        setFlagArgArray(arg)
    }
}

func setFlagArgArray(arg string) {
    if !strings.HasPrefix(arg, "--") {
        return
    }

    elems := strings.Split(arg, "[")
    if len(elems) > 1 {
        elems[1] = strings.Split(elems[1], "]")[0]
        switch elems[0] {
        case "--network":
            tallyRepeatableFlag(&maxNetworkFlags, elems[1])
        case "--program":
            tallyRepeatableFlag(&maxProgramFlags, elems[1])
        case "--nfs":
            tallyRepeatableFlag(&maxNFSFlags, elems[1])
        case "--logging":
            tallyRepeatableFlag(&maxLoggingFlags, elems[1])
        case "--redirect":
            tallyRepeatableFlag(&maxRedirectFlags, elems[1])
        }
    }
}

func tallyRepeatableFlag(v *int, s string) {
    if i, err := strconv.Atoi(s); err == nil && (i+1) > *v {
        *v = i + 1
    }
}

// --sysctl
var sysctlFlag = flag.NewStringSliceFlag("sysctl", "add a sysctl key/value tuple", hideFlags, sysctlFlagValidator)
var sysctlFlagValidator = func(f flag.StringSliceFlag) error {
    for _, s := range f.Value {
        x := strings.Split(s, "=")
        if len(x) < 2 {
            log.Warnf("invalid sysctl tuple '%s'", s)
        }
        if overrideVCFG.Sysctl == nil {
            overrideVCFG.Sysctl = make(map[string]string)
        }
        overrideVCFG.Sysctl[x[0]] = x[1]
    }
    return nil
}

// --info.author
var infoAuthorFlag = flag.NewStringFlag("info.author", "name the author of the app", hideFlags, infoAuthorFlagValidator)
var infoAuthorFlagValidator = func(f flag.StringFlag) error {
    overrideVCFG.Info.Author = f.Value
    return nil
}

// --info.date
var infoDateFlag = flag.NewStringFlag("info.date", "date of app's release (YYYY-MM-DD)", hideFlags, infoDateFlagValidator)
var infoDateFlagValidator = func(f flag.StringFlag) error {
    var err error
    if f.Value == "" {
        return nil
    }
    overrideVCFG.Info.Date, err = vcfg.TimestampFromString(f.Value)
    return err
}

// --info.description
var infoDescriptionFlag = flag.NewStringFlag("info.description", "provide a description for the app", hideFlags, infoDescriptionFlagValidator)
var infoDescriptionFlagValidator = func(f flag.StringFlag) error {
    overrideVCFG.Info.Description = f.Value
    return nil
}

// --info.name
var infoNameFlag = flag.NewStringFlag("info.name", "name of the app", hideFlags, infoNameFlagValidator)
var infoNameFlagValidator = func(f flag.StringFlag) error {
    overrideVCFG.Info.Name = f.Value
    return nil
}

// --info.summary
var infoSummaryFlag = flag.NewStringFlag("info.summary", "provide a short summary for the app", hideFlags, infoSummaryFlagValidator)
var infoSummaryFlagValidator = func(f flag.StringFlag) error {
    overrideVCFG.Info.Summary = f.Value
    return nil
}

// --info.url
var infoURLFlag = flag.NewStringFlag("info.url", "URL for more information about the app", hideFlags, infoURLFlagValidator)
var infoURLFlagValidator = func(f flag.StringFlag) error {
    var err error
    overrideVCFG.Info.URL, err = vcfg.URLFromString(f.Value)
    return err
}

// --info.version
var infoVersionFlag = flag.NewStringFlag("info.version", "identify the app's version", hideFlags, infoVersionFlagValidator)
var infoVersionFlagValidator = func(f flag.StringFlag) error {
    overrideVCFG.Info.Version = f.Value
    return nil
}

// --logging.config
var loggingConfigFlag = flag.NewNStringSliceFlag("logging[<<N>>].config", "configure app's logging config", &maxLoggingFlags, hideFlags, loggingConfigFlagValidator)
var loggingConfigFlagValidator = func(f flag.NStringSliceFlag) error {
    for i := 0; i < *f.Total; i++ {
        if len(f.Value[i]) == 0 {
            continue
        }
        s := f.Value[i]
        for len(overrideVCFG.Logging) < i+1 {
            overrideVCFG.Logging = append(overrideVCFG.Logging, vcfg.Logging{})
        }
        logging := &overrideVCFG.Logging[i]
        if logging.Config == nil {
            logging.Config = make([]string, 0)
        }
        logging.Config = append(logging.Config, s...)
    }
    return nil
}

// --logging.type
var loggingTypeFlag = flag.NewNStringFlag("logging[<<N>>].type", "configure app's logging type", &maxLoggingFlags, hideFlags, loggingTypeFlagValidator)
var loggingTypeFlagValidator = func(f flag.NStringFlag) error {
    for i := 0; i < *f.Total; i++ {
        if f.Value[i] == "" {
            continue
        }
        s := f.Value[i]
        for len(overrideVCFG.Logging) < i+1 {
            overrideVCFG.Logging = append(overrideVCFG.Logging, vcfg.Logging{})
        }
        logging := &overrideVCFG.Logging[i]
        logging.Type = s
    }
    return nil
}

var initRequiredNFS = func(f flag.NStringFlag, fn func(nfs *vcfg.NFSSettings, s string)) error {
    return initFromNStringFlag(f, func(i int, s string) {
        for len(overrideVCFG.NFS) < i+1 {
            overrideVCFG.NFS = append(overrideVCFG.NFS, vcfg.NFSSettings{})
        }
        fn(&overrideVCFG.NFS[i], s)
    })
}

// --nfs.mount
var nfsMountFlag = flag.NewNStringFlag("nfs[<<N>>].mount", "configure app's nfs mounts", &maxNFSFlags, hideFlags, nfsMountFlagValidator)
var nfsMountFlagValidator = func(f flag.NStringFlag) error {
    return initRequiredNFS(f, func(nfs *vcfg.NFSSettings, s string) { nfs.MountPoint = s })
}

// --nfs.options
var nfsOptionsFlag = flag.NewNStringFlag("nfs[<<N>>].options", "configure app's nfs options", &maxNFSFlags, hideFlags, nfsOptionsFlagValidator)
var nfsOptionsFlagValidator = func(f flag.NStringFlag) error {
    return initRequiredNFS(f, func(nfs *vcfg.NFSSettings, s string) { nfs.Arguments = s })
}

// --nfs.server
var nfsServerFlag = flag.NewNStringFlag("nfs[<<N>>].server", "configure app's nfs servers", &maxNFSFlags, hideFlags, nfsServerFlagValidator)
var nfsServerFlagValidator = func(f flag.NStringFlag) error {
    return initRequiredNFS(f, func(nfs *vcfg.NFSSettings, s string) { nfs.Server = s })
}

func initRequiredNetworks(l, i int) {
    if l == 0 {
        return
    }
    for len(overrideVCFG.Networks) < i+1 {
        overrideVCFG.Networks = append(overrideVCFG.Networks, vcfg.NetworkInterface{IP: "dhcp"})
    }
}

var initRequiredNetworksFromString = func(f flag.NStringFlag, fn func(nic *vcfg.NetworkInterface, s string)) error {
    return initFromNStringFlag(f, func(i int, s string) {
        initRequiredNetworks(len(f.Value), i)
        fn(&overrideVCFG.Networks[i], s)
    })
}

// --network.tcpdump
var networkTCPDumpFlag = flag.NewNBoolFlag("network[<<N>>].tcpdump", "configure this network to run with tcpdump", &maxNetworkFlags, hideFlags, networkTCPDumpFlagValidator)
var networkTCPDumpFlagValidator = func(f flag.NBoolFlag) error {
    for i := 0; i < *f.Total; i++ {
        initRequiredNetworks(len(f.Value), i)
        val := f.Value[i]
        overrideVCFG.Networks[i].TCPDUMP = val
    }
    return nil
}

// --network.gateway
var networkGatewayFlag = flag.NewNStringFlag("network[<<N>>].gateway", "configure app's network gateway", &maxNetworkFlags, hideFlags, networkGatewayFlagValidator)
var networkGatewayFlagValidator = func(f flag.NStringFlag) error {
    return initRequiredNetworksFromString(f, func(nic *vcfg.NetworkInterface, s string) { nic.Gateway = s })
}

var networkFlagValidator = func(f flag.NStringSliceFlag, fn func(nic *vcfg.NetworkInterface, s interface{})) error {
    for i := 0; i < *f.Total; i++ {
        // Skip empty values from unassigned flags
        if f.Value[i] == nil {
            continue
        }

        initRequiredNetworks(len(f.Value[i]), i)
        s := f.Value[i]
        nic := &overrideVCFG.Networks[i]
        fn(nic, s)
    }
    return nil
}

// --network.http
var networkHTTPFlag = flag.NewNStringSliceFlag("network[<<N>>].http", "expose http port", &maxNetworkFlags, hideFlags, networkHTTPFlagValidator)
var networkHTTPFlagValidator = func(f flag.NStringSliceFlag) error {
    return networkFlagValidator(f, func(nic *vcfg.NetworkInterface, s interface{}) { nic.HTTP = s.([]string) })
}

// --network.https
var networkHTTPSFlag = flag.NewNStringSliceFlag("network[<<N>>].https", "expose https port", &maxNetworkFlags, hideFlags, networkHTTPSFlagValidator)
var networkHTTPSFlagValidator = func(f flag.NStringSliceFlag) error {
    return networkFlagValidator(f, func(nic *vcfg.NetworkInterface, s interface{}) { nic.HTTPS = s.([]string) })
}

// --network.ip
var networkIPFlag = flag.NewNStringFlag("network[<<N>>].ip", "configure app's network IP address", &maxNetworkFlags, hideFlags, networkIPFlagValidator)
var networkIPFlagValidator = func(f flag.NStringFlag) error {
    return initRequiredNetworksFromString(f, func(nic *vcfg.NetworkInterface, s string) { nic.IP = s })
}

// --network.mtu
var networkMTUFlag = flag.NewNStringFlag("network[<<N>>].mtu", "configure app's network interface MTU", &maxNetworkFlags, hideFlags, networkMTUFlagValidator)
var networkMTUFlagValidator = func(f flag.NStringFlag) error {
    for i := 0; i < *f.Total; i++ {
        initRequiredNetworks(len(f.Value), i)
        s := f.Value[i]
        if s == "" {
            continue
        }
        x, err := strconv.ParseUint(s, 10, 64)
        if err != nil {
            return err
        }
        nic := &overrideVCFG.Networks[i]
        nic.MTU = uint(x)
    }
    return nil
}

// --network.mask
var networkMaskFlag = flag.NewNStringFlag("network[<<N>>].mask", "configure app's subnet mask", &maxNetworkFlags, hideFlags, networkMaskFlagValidator)
var networkMaskFlagValidator = func(f flag.NStringFlag) error {
    return initRequiredNetworksFromString(f, func(nic *vcfg.NetworkInterface, s string) { nic.Mask = s })
}

// --network.tcp
var networkTCPFlag = flag.NewNStringSliceFlag("network[<<N>>].tcp", "expose tcp port", &maxNetworkFlags, hideFlags, networkTCPFlagValidator)
var networkTCPFlagValidator = func(f flag.NStringSliceFlag) error {
    return networkFlagValidator(f, func(nic *vcfg.NetworkInterface, s interface{}) { nic.TCP = s.([]string) })
}

// --network.udp
var networkUDPFlag = flag.NewNStringSliceFlag("network[<<N>>].udp", "expose udp port", &maxNetworkFlags, hideFlags, networkUDPFlagValidator)
var networkUDPFlagValidator = func(f flag.NStringSliceFlag) error {
    return networkFlagValidator(f, func(nic *vcfg.NetworkInterface, s interface{}) { nic.UDP = s.([]string) })
}

// --system.kernel-args
var systemKernelArgsFlag = flag.NewStringFlag("system.kernel-args", "linux kernel args to append", hideFlags, systemKernelArgsFlagValidator)
var systemKernelArgsFlagValidator = func(f flag.StringFlag) error {
    overrideVCFG.System.KernelArgs = f.Value
    return nil
}

// --system.dns
var systemDNSFlag = flag.NewStringSliceFlag("system.dns", "set the DNS server list for the system", hideFlags, systemDNSFlagValidator)
var systemDNSFlagValidator = func(f flag.StringSliceFlag) error {
    overrideVCFG.System.DNS = f.Value
    return nil
}

// --system.hostname
var systemHostnameFlag = flag.NewStringFlag("system.hostname", "set the hostname for the system", hideFlags, systemHostnameFlagValidator)
var systemHostnameFlagValidator = func(f flag.StringFlag) error {
    overrideVCFG.System.Hostname = f.Value
    return nil
}

// --system.filesystem
var systemFilesystemFlag = flag.NewStringFlag("system.filesystem", "set the filesystem format", hideFlags, systemFilesystemFlagValidator)
var systemFilesystemFlagValidator = func(f flag.StringFlag) error {
    overrideVCFG.System.Filesystem = vcfg.Filesystem(f.Value)
    return nil
}

// --system.max-fds
var systemMaxFDsFlag = flag.NewUintFlag("system.max-fds", "maximum file descriptors available to app", hideFlags, systemMaxFDsFlagValidator)
var systemMaxFDsFlagValidator = func(f flag.UintFlag) error {
    overrideVCFG.System.MaxFDs = f.Value
    return nil
}

// --system.output-mode
var systemOutputModeFlag = flag.NewStringFlag("system.output-mode", "specify vm output behaviour mode", hideFlags, systemOutputModeFlagValidator)
var systemOutputModeFlagValidator = func(f flag.StringFlag) error {
    overrideVCFG.System.StdoutMode = vcfg.StdoutModeFromString(f.Value)
    return nil
}

// --system.user
var systemUserFlag = flag.NewStringFlag("system.user", "name of the non-root user (default: vorteil)", hideFlags, systemUserFlagValidator)
var systemUserFlagValidator = func(f flag.StringFlag) error {
    overrideVCFG.System.User = f.Value
    return nil
}

// --system.terminate-wait
var systemTerminateWaitFlag = flag.NewUintFlag("system.terminate-wait", "how many milliseconds to wait for program termination (default: 3000)", hideFlags, systemTerminateWaitFlagValidator)
var systemTerminateWaitFlagValidator = func(f flag.UintFlag) error {
    overrideVCFG.System.TerminateWait = f.Value
    return nil
}

// a key can have multiple destinations
// key = src, vals = dst
var filesMap = make(map[string][]string)

// --files
var filesFlag = flag.NewStringSliceFlag("files", "<src>[@<dst>]   add files from the host filesystem to an existing folder in the virtual machine filesystem (dst defaults to '/')", hideFlags, filesFlagValidator)
var filesFlagValidator = func(f flag.StringSliceFlag) error {
    for _, v := range f.Value {
        // value should have no more than 2 elements when split by '@'
        x := strings.SplitN(v, "@", 2)
        var src = x[0]
        var dst = "/"
        if len(x) > 1 {
            dst = x[1]
        }
        if _, ok := filesMap[src]; !ok {
            filesMap[src] = make([]string, 0)
        }
        filesMap[src] = append(filesMap[src], dst)
    }
    return nil
}

// --vm.cpus
var vmCPUsFlag = flag.NewUintFlag("vm.cpus", "number of cpus to allocate to app", hideFlags, vmCPUsFlagValidator)
var vmCPUsFlagValidator = func(f flag.UintFlag) error {
    overrideVCFG.VM.CPUs = f.Value
    return nil
}

func overwriteSizeFieldFromString(f flag.StringFlag, field *vcfg.Bytes) error {
    var err error
    *field, err = vcfg.ParseBytes(f.Value)
    if err != nil {
        return fmt.Errorf("--%s=%s: %v", f.Key, f.Value, err)
    }
    return nil
}

// --vm.disk-size
var vmDiskSizeFlag = flag.NewStringFlag("vm.disk-size", "disk image capacity to allocate to app", hideFlags, vmDiskSizeFlagValidator)
var vmDiskSizeFlagValidator = func(f flag.StringFlag) error {
    return overwriteSizeFieldFromString(f, &overrideVCFG.VM.DiskSize)
}

// --vm.inodes
var vmInodesFlag = flag.NewUintFlag("vm.inodes", "number of inodes to build on disk image", hideFlags, vmInodesFlagValidator)
var vmInodesFlagValidator = func(f flag.UintFlag) error {
    overrideVCFG.VM.Inodes = vcfg.InodesQuota(f.Value)
    return nil
}

// --vm.kernel
var vmKernelFlag = flag.NewStringFlag("vm.kernel", "kernel to build app on", hideFlags, vmKernelFlagValidator)
var vmKernelFlagValidator = func(f flag.StringFlag) error {
    if f.Value != "" {
        overrideVCFG.VM.Kernel = f.Value
    }
    return nil
}

// --vm.ram
var vmRAMFlag = flag.NewStringFlag("vm.ram", "memory to allocate to app", hideFlags, vmRAMFlagValidator)
var vmRAMFlagValidator = func(f flag.StringFlag) error {
    return overwriteSizeFieldFromString(f, &overrideVCFG.VM.RAM)
}

var initFromNStringFlag = func(f flag.NStringFlag, fn func(i int, s string)) error {
    for i := 0; i < *f.Total; i++ {
        s := f.Value[i]
        if s == "" {
            continue
        }
        fn(i, s)
    }
    return nil
}

var initRequiredProgramsFromString = func(f flag.NStringFlag, fn func(prog *vcfg.Program, s string)) error {
    return initFromNStringFlag(f, func(i int, s string) {
        for len(overrideVCFG.Programs) < i+1 {
            overrideVCFG.Programs = append(overrideVCFG.Programs, vcfg.Program{})
        }
        fn(&overrideVCFG.Programs[i], s)
    })
}

var initRequiredProgramsFromBool = func(f flag.NBoolFlag, fn func(prog *vcfg.Program, s bool)) error {
    for i := 0; i < *f.Total; i++ {
        for len(overrideVCFG.Programs) < i+1 {
            overrideVCFG.Programs = append(overrideVCFG.Programs, vcfg.Program{})
        }
        fn(&overrideVCFG.Programs[i], f.Value[i])
    }
    return nil
}

var initRequiredProgramsFromStringSlice = func(f flag.NStringSliceFlag, fn func(prog *vcfg.Program, s []string)) error {
    for i := 0; i < *f.Total; i++ {
        s := f.Value[i]
        if s == nil {
            continue
        }
        for len(overrideVCFG.Programs) < i+1 {
            overrideVCFG.Programs = append(overrideVCFG.Programs, vcfg.Program{})
        }
        fn(&overrideVCFG.Programs[i], s)
    }
    return nil
}

// --program.binary
var programBinaryFlag = flag.NewNStringFlag("program[<<N>>].binary", "configure a program binary", &maxProgramFlags, hideFlags, programBinaryFlagValidator)
var programBinaryFlagValidator = func(f flag.NStringFlag) error {
    return initRequiredProgramsFromString(f, func(prog *vcfg.Program, s string) { prog.Binary = s })
}

// --program.privileges
var programPrivilegesFlag = flag.NewNStringFlag("program[<<N>>].privilege", "configure program privileges (root, superuser, user)", &maxProgramFlags, hideFlags, programPrivilegesFlagValidator)
var programPrivilegesFlagValidator = func(f flag.NStringFlag) error {
    return initRequiredProgramsFromString(f, func(prog *vcfg.Program, s string) { prog.Privilege = vcfg.Privilege(s) })
}

// --program.env
var programEnvFlag = flag.NewNStringSliceFlag("program[<<N>>].env", "configure the environment variables of a program", &maxProgramFlags, hideFlags, programEnvFlagValidator)
var programEnvFlagValidator = func(f flag.NStringSliceFlag) error {
    return initRequiredProgramsFromStringSlice(f, func(prog *vcfg.Program, s []string) { prog.Env = s })
}

// --program.cwd
var programCWDFlag = flag.NewNStringFlag("program[<<N>>].cwd", "configure the working directory of a program", &maxProgramFlags, hideFlags, programCWDFlagValidator)
var programCWDFlagValidator = func(f flag.NStringFlag) error {
    return initRequiredProgramsFromString(f, func(prog *vcfg.Program, s string) { prog.Cwd = s })
}

// --program.terminate
var programTerminateFlag = flag.NewNStringFlag("program[<<N>>].terminate", "configure the signal to send program on termination (default: SIGTERM)", &maxProgramFlags, hideFlags, programTerminateFlagValidator)
var programTerminateFlagValidator = func(f flag.NStringFlag) error {
    return initRequiredProgramsFromString(f, func(prog *vcfg.Program, s string) { prog.Terminate = vcfg.TerminateSignal(s) })
}

// --program.logfiles
var programLogFilesFlag = flag.NewNStringSliceFlag("program[<<N>>].logfiles", "gure the logfiles of a program", &maxProgramFlags, hideFlags, programLogFilesFlagValidator)
var programLogFilesFlagValidator = func(f flag.NStringSliceFlag) error {
    return initRequiredProgramsFromStringSlice(f, func(prog *vcfg.Program, s []string) { prog.LogFiles = s })
}

// --program.bootstrap
var programBootstrapFlag = flag.NewNStringSliceFlag("program[<<N>>].bootstrap", "configure the bootstrap parameters of a program", &maxProgramFlags, hideFlags, programBootstrapFlagValidator)
var programBootstrapFlagValidator = func(f flag.NStringSliceFlag) error {
    return initRequiredProgramsFromStringSlice(f, func(prog *vcfg.Program, s []string) { prog.Bootstrap = s })
}

// --program.stdout
var programStdoutFlag = flag.NewNStringFlag("program[<<N>>].stdout", "configure programs stdout", &maxProgramFlags, hideFlags, programStdoutFlagValidator)
var programStdoutFlagValidator = func(f flag.NStringFlag) error {
    return initRequiredProgramsFromString(f, func(prog *vcfg.Program, s string) { prog.Stdout = s })
}

// --program.stderr
var programStderrFlag = flag.NewNStringFlag("program[<<N>>].stderr", "configure programs stderr", &maxProgramFlags, hideFlags, programStderrFlagValidator)
var programStderrFlagValidator = func(f flag.NStringFlag) error {
    return initRequiredProgramsFromString(f, func(prog *vcfg.Program, s string) { prog.Stderr = s })
}

// --program.strace
var programStraceFlag = flag.NewNBoolFlag("program[<<N>>].strace", "configure the program to run with strace", &maxProgramFlags, hideFlags, programStraceFlagValidator)
var programStraceFlagValidator = func(f flag.NBoolFlag) error {
    return initRequiredProgramsFromBool(f, func(prog *vcfg.Program, s bool) { prog.Strace = s })
}

// --program.args
var programArgsFlag = flag.NewNStringFlag("program[<<N>>].args", "configure programs args", &maxProgramFlags, hideFlags, programArgsFlagValidator)
var programArgsFlagValidator = func(f flag.NStringFlag) error {
    return initRequiredProgramsFromString(f, func(prog *vcfg.Program, s string) { prog.Args = s })
}

var vcfgFlags = flag.FlagsList{
    &vmCPUsFlag, &vmDiskSizeFlag, &vmInodesFlag, &vmKernelFlag, &vmRAMFlag,
    &filesFlag, &infoAuthorFlag, &infoDateFlag, &infoDescriptionFlag,
    &infoNameFlag, &infoSummaryFlag, &infoURLFlag, &infoVersionFlag,
    &networkIPFlag, &networkMaskFlag, &networkGatewayFlag, &networkUDPFlag,
    &networkTCPFlag, &networkHTTPFlag, &networkHTTPSFlag, &networkMTUFlag,
    &networkTCPDumpFlag, &loggingConfigFlag, &loggingTypeFlag, &nfsMountFlag,
    &nfsServerFlag, &nfsOptionsFlag, &systemKernelArgsFlag, &systemDNSFlag,
    &systemHostnameFlag, &systemFilesystemFlag, &systemMaxFDsFlag,
    &systemOutputModeFlag, &systemUserFlag, &programBinaryFlag,
    &programPrivilegesFlag, &programArgsFlag, &programStdoutFlag,
    &programStderrFlag, &programLogFilesFlag, &programBootstrapFlag,
    &programEnvFlag, &programCWDFlag, &programStraceFlag, &sysctlFlag,
    &programTerminateFlag, &systemTerminateWaitFlag,
}