Merge pull request #3256 from dalegaard/master

Enable rkt driver to use address_mode = 'driver'
This commit is contained in:
Michael Schurter
2017-09-26 18:04:37 -05:00
committed by GitHub
88 changed files with 12152 additions and 73 deletions

View File

@@ -1,5 +1,10 @@
## 0.7 (Unreleased)
__BACKWARDS INCOMPATIBILITIES:__
* driver/rkt: Nomad now requires at least rkt version `1.27.0` for the rkt
driver to function. Please update your version of rkt to at least this
version.
IMPROVEMENTS:
* core: Capability based ACL system with authoratative region, providing
federated ACLs.
@@ -8,6 +13,7 @@ IMPROVEMENTS:
objects to be isolated from each other and other users of the cluster.
* api: Metrics endpoint exposes Prometheus formatted metrics [GH-3171]
* discovery: Allow restarting unhealthy tasks with `check_restart` [GH-3105]
* driver/rkt: Enable rkt driver to use address_mode = 'driver' [GH-3256]
* telemetry: Add support for tagged metrics for Nomad clients [GH-3147]
* telemetry: Add basic Prometheus configuration for a Nomad cluster [GH-3186]

View File

@@ -18,6 +18,9 @@ import (
"syscall"
"time"
appcschema "github.com/appc/spec/schema"
rktv1 "github.com/rkt/rkt/api/v1"
"github.com/hashicorp/go-plugin"
"github.com/hashicorp/go-version"
"github.com/hashicorp/nomad/client/allocdir"
@@ -41,7 +44,7 @@ const (
// minRktVersion is the earliest supported version of rkt. rkt added support
// for CPU and memory isolators in 0.14.0. We cannot support an earlier
// version to maintain an uniform interface across all drivers
minRktVersion = "1.0.0"
minRktVersion = "1.27.0"
// The key populated in the Node Attributes to indicate the presence of the
// Rkt driver
@@ -55,8 +58,8 @@ const (
// rktCmd is the command rkt is installed as.
rktCmd = "rkt"
// rktUuidDeadline is how long to wait for the uuid file to be written
rktUuidDeadline = 5 * time.Second
// rktNetworkDeadline is how long to wait for container network to start
rktNetworkDeadline = 5 * time.Second
)
// RktDriver is a driver for running images via Rkt
@@ -112,6 +115,116 @@ type rktPID struct {
MaxKillTimeout time.Duration
}
// Retrieve pod status for the pod with the given UUID.
func rktGetStatus(uuid string) (*rktv1.Pod, error) {
statusArgs := []string{
"status",
"--format=json",
uuid,
}
var outBuf bytes.Buffer
cmd := exec.Command(rktCmd, statusArgs...)
cmd.Stdout = &outBuf
cmd.Stderr = ioutil.Discard
if err := cmd.Run(); err != nil {
return nil, err
}
var status rktv1.Pod
if err := json.Unmarshal(outBuf.Bytes(), &status); err != nil {
return nil, err
}
return &status, nil
}
// Retrieves a pod manifest
func rktGetManifest(uuid string) (*appcschema.PodManifest, error) {
statusArgs := []string{
"cat-manifest",
uuid,
}
var outBuf bytes.Buffer
cmd := exec.Command(rktCmd, statusArgs...)
cmd.Stdout = &outBuf
cmd.Stderr = ioutil.Discard
if err := cmd.Run(); err != nil {
return nil, err
}
var manifest appcschema.PodManifest
if err := json.Unmarshal(outBuf.Bytes(), &manifest); err != nil {
return nil, err
}
return &manifest, nil
}
func rktGetDriverNetwork(uuid string, driverConfigPortMap map[string]string) (*cstructs.DriverNetwork, error) {
deadline := time.Now().Add(rktNetworkDeadline)
var lastErr error
for time.Now().Before(deadline) {
if status, err := rktGetStatus(uuid); err == nil {
for _, net := range status.Networks {
if !net.IP.IsGlobalUnicast() {
continue
}
// Get the pod manifest so we can figure out which ports are exposed
var portmap map[string]int
manifest, err := rktGetManifest(uuid)
if err == nil {
portmap, err = rktManifestMakePortMap(manifest, driverConfigPortMap)
if err != nil {
lastErr = fmt.Errorf("could not create manifest-based portmap: %v", err)
return nil, lastErr
}
} else {
lastErr = fmt.Errorf("could not get pod manifest: %v", err)
return nil, lastErr
}
return &cstructs.DriverNetwork{
PortMap: portmap,
IP: status.Networks[0].IP.String(),
}, nil
}
if len(status.Networks) == 0 {
lastErr = fmt.Errorf("no networks found")
} else {
lastErr = fmt.Errorf("no good driver networks out of %d returned", len(status.Networks))
}
} else {
lastErr = fmt.Errorf("getting status failed: %v", err)
}
time.Sleep(400 * time.Millisecond)
}
return nil, fmt.Errorf("timed out, last error: %v", lastErr)
}
// Given a rkt/appc pod manifest and driver portmap configuration, create
// a driver portmap.
func rktManifestMakePortMap(manifest *appcschema.PodManifest, configPortMap map[string]string) (map[string]int, error) {
if len(manifest.Apps) == 0 {
return nil, fmt.Errorf("manifest has no apps")
}
if len(manifest.Apps) != 1 {
return nil, fmt.Errorf("manifest has multiple apps!")
}
app := manifest.Apps[0]
if app.App == nil {
return nil, fmt.Errorf("specified app has no App object")
}
portMap := make(map[string]int)
for svc, name := range configPortMap {
for _, port := range app.App.Ports {
if port.Name.String() == name {
portMap[svc] = int(port.Port)
}
}
}
return portMap, nil
}
// NewRktDriver is used to create a new exec driver
func NewRktDriver(ctx *DriverContext) Driver {
return &RktDriver{DriverContext: *ctx}
@@ -247,8 +360,8 @@ func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (*StartResponse,
// ACI image
img := driverConfig.ImageName
// Build the command.
cmdArgs := make([]string, 0, 50)
// Global arguments given to both prepare and run-prepared
globalArgs := make([]string, 0, 50)
// Add debug option to rkt command.
debug := driverConfig.Debug
@@ -274,43 +387,44 @@ func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (*StartResponse,
// if we have a selective insecure_options, prefer them
// insecure options are rkt's global argument, so we do this before the actual "run"
if len(driverConfig.InsecureOptions) > 0 {
cmdArgs = append(cmdArgs, fmt.Sprintf("--insecure-options=%s", strings.Join(driverConfig.InsecureOptions, ",")))
globalArgs = append(globalArgs, fmt.Sprintf("--insecure-options=%s", strings.Join(driverConfig.InsecureOptions, ",")))
} else if insecure {
cmdArgs = append(cmdArgs, "--insecure-options=all")
globalArgs = append(globalArgs, "--insecure-options=all")
}
// debug is rkt's global argument, so add it before the actual "run"
cmdArgs = append(cmdArgs, fmt.Sprintf("--debug=%t", debug))
globalArgs = append(globalArgs, fmt.Sprintf("--debug=%t", debug))
cmdArgs = append(cmdArgs, "run")
prepareArgs := make([]string, 0, 50)
runArgs := make([]string, 0, 50)
prepareArgs = append(prepareArgs, globalArgs...)
prepareArgs = append(prepareArgs, "prepare")
runArgs = append(runArgs, globalArgs...)
runArgs = append(runArgs, "run-prepared")
// disable overlayfs
if driverConfig.NoOverlay {
cmdArgs = append(cmdArgs, "--no-overlay=true")
prepareArgs = append(prepareArgs, "--no-overlay=true")
}
// Write the UUID out to a file in the state dir so we can read it back
// in and access the pod by UUID from other commands
uuidPath := filepath.Join(ctx.TaskDir.Dir, "rkt.uuid")
cmdArgs = append(cmdArgs, fmt.Sprintf("--uuid-file-save=%s", uuidPath))
// Convert underscores to dashes in task names for use in volume names #2358
sanitizedName := strings.Replace(task.Name, "_", "-", -1)
// Mount /alloc
allocVolName := fmt.Sprintf("%s-%s-alloc", d.DriverContext.allocID, sanitizedName)
cmdArgs = append(cmdArgs, fmt.Sprintf("--volume=%s,kind=host,source=%s", allocVolName, ctx.TaskDir.SharedAllocDir))
cmdArgs = append(cmdArgs, fmt.Sprintf("--mount=volume=%s,target=%s", allocVolName, allocdir.SharedAllocContainerPath))
prepareArgs = append(prepareArgs, fmt.Sprintf("--volume=%s,kind=host,source=%s", allocVolName, ctx.TaskDir.SharedAllocDir))
prepareArgs = append(prepareArgs, fmt.Sprintf("--mount=volume=%s,target=%s", allocVolName, allocdir.SharedAllocContainerPath))
// Mount /local
localVolName := fmt.Sprintf("%s-%s-local", d.DriverContext.allocID, sanitizedName)
cmdArgs = append(cmdArgs, fmt.Sprintf("--volume=%s,kind=host,source=%s", localVolName, ctx.TaskDir.LocalDir))
cmdArgs = append(cmdArgs, fmt.Sprintf("--mount=volume=%s,target=%s", localVolName, allocdir.TaskLocalContainerPath))
prepareArgs = append(prepareArgs, fmt.Sprintf("--volume=%s,kind=host,source=%s", localVolName, ctx.TaskDir.LocalDir))
prepareArgs = append(prepareArgs, fmt.Sprintf("--mount=volume=%s,target=%s", localVolName, allocdir.TaskLocalContainerPath))
// Mount /secrets
secretsVolName := fmt.Sprintf("%s-%s-secrets", d.DriverContext.allocID, sanitizedName)
cmdArgs = append(cmdArgs, fmt.Sprintf("--volume=%s,kind=host,source=%s", secretsVolName, ctx.TaskDir.SecretsDir))
cmdArgs = append(cmdArgs, fmt.Sprintf("--mount=volume=%s,target=%s", secretsVolName, allocdir.TaskSecretsContainerPath))
prepareArgs = append(prepareArgs, fmt.Sprintf("--volume=%s,kind=host,source=%s", secretsVolName, ctx.TaskDir.SecretsDir))
prepareArgs = append(prepareArgs, fmt.Sprintf("--mount=volume=%s,target=%s", secretsVolName, allocdir.TaskSecretsContainerPath))
// Mount arbitrary volumes if enabled
if len(driverConfig.Volumes) > 0 {
@@ -334,33 +448,34 @@ func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (*StartResponse,
return nil, fmt.Errorf("invalid rkt volume: %q", rawvol)
}
volName := fmt.Sprintf("%s-%s-%d", d.DriverContext.allocID, sanitizedName, i)
cmdArgs = append(cmdArgs, fmt.Sprintf("--volume=%s,kind=host,source=%s,readOnly=%s", volName, parts[0], readOnly))
cmdArgs = append(cmdArgs, fmt.Sprintf("--mount=volume=%s,target=%s", volName, parts[1]))
prepareArgs = append(prepareArgs, fmt.Sprintf("--volume=%s,kind=host,source=%s,readOnly=%s", volName, parts[0], readOnly))
prepareArgs = append(prepareArgs, fmt.Sprintf("--mount=volume=%s,target=%s", volName, parts[1]))
}
}
cmdArgs = append(cmdArgs, img)
// Inject environment variables
for k, v := range ctx.TaskEnv.Map() {
cmdArgs = append(cmdArgs, fmt.Sprintf("--set-env=%s=%s", k, v))
prepareArgs = append(prepareArgs, fmt.Sprintf("--set-env=%s=%s", k, v))
}
// Image is set here, because the commands that follow apply to it
prepareArgs = append(prepareArgs, img)
// Check if the user has overridden the exec command.
if driverConfig.Command != "" {
cmdArgs = append(cmdArgs, fmt.Sprintf("--exec=%v", driverConfig.Command))
prepareArgs = append(prepareArgs, fmt.Sprintf("--exec=%v", driverConfig.Command))
}
// Add memory isolator
cmdArgs = append(cmdArgs, fmt.Sprintf("--memory=%vM", int64(task.Resources.MemoryMB)))
prepareArgs = append(prepareArgs, fmt.Sprintf("--memory=%vM", int64(task.Resources.MemoryMB)))
// Add CPU isolator
cmdArgs = append(cmdArgs, fmt.Sprintf("--cpu=%vm", int64(task.Resources.CPU)))
prepareArgs = append(prepareArgs, fmt.Sprintf("--cpu=%vm", int64(task.Resources.CPU)))
// Add DNS servers
if len(driverConfig.DNSServers) == 1 && (driverConfig.DNSServers[0] == "host" || driverConfig.DNSServers[0] == "none") {
// Special case single item lists with the special values "host" or "none"
cmdArgs = append(cmdArgs, fmt.Sprintf("--dns=%s", driverConfig.DNSServers[0]))
runArgs = append(runArgs, fmt.Sprintf("--dns=%s", driverConfig.DNSServers[0]))
} else {
for _, ip := range driverConfig.DNSServers {
if err := net.ParseIP(ip); err == nil {
@@ -368,20 +483,20 @@ func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (*StartResponse,
d.logger.Printf("[DEBUG] driver.rkt: %v", msg)
return nil, msg
} else {
cmdArgs = append(cmdArgs, fmt.Sprintf("--dns=%s", ip))
runArgs = append(runArgs, fmt.Sprintf("--dns=%s", ip))
}
}
}
// set DNS search domains
for _, domain := range driverConfig.DNSSearchDomains {
cmdArgs = append(cmdArgs, fmt.Sprintf("--dns-search=%s", domain))
runArgs = append(runArgs, fmt.Sprintf("--dns-search=%s", domain))
}
// set network
network := strings.Join(driverConfig.Net, ",")
if network != "" {
cmdArgs = append(cmdArgs, fmt.Sprintf("--net=%s", network))
runArgs = append(runArgs, fmt.Sprintf("--net=%s", network))
}
// Setup port mapping and exposed ports
@@ -407,7 +522,7 @@ func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (*StartResponse,
d.logger.Printf("[DEBUG] driver.rkt: exposed port %s", containerPort)
// Add port option to rkt run arguments. rkt allows multiple port args
cmdArgs = append(cmdArgs, fmt.Sprintf("--port=%s:%s", containerPort, hostPortStr))
prepareArgs = append(prepareArgs, fmt.Sprintf("--port=%s:%s", containerPort, hostPortStr))
}
for _, port := range network.DynamicPorts {
@@ -425,7 +540,7 @@ func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (*StartResponse,
d.logger.Printf("[DEBUG] driver.rkt: exposed port %s", containerPort)
// Add port option to rkt run arguments. rkt allows multiple port args
cmdArgs = append(cmdArgs, fmt.Sprintf("--port=%s:%s", containerPort, hostPortStr))
prepareArgs = append(prepareArgs, fmt.Sprintf("--port=%s:%s", containerPort, hostPortStr))
}
}
@@ -436,11 +551,11 @@ func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (*StartResponse,
// Need to start arguments with "--"
if len(parsed) > 0 {
cmdArgs = append(cmdArgs, "--")
prepareArgs = append(prepareArgs, "--")
}
for _, arg := range parsed {
cmdArgs = append(cmdArgs, fmt.Sprintf("%v", arg))
prepareArgs = append(prepareArgs, fmt.Sprintf("%v", arg))
}
}
@@ -455,6 +570,24 @@ func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (*StartResponse,
return nil, err
}
absPath, err := GetAbsolutePath(rktCmd)
if err != nil {
return nil, err
}
var outBuf, errBuf bytes.Buffer
cmd := exec.Command(rktCmd, prepareArgs...)
cmd.Stdout = &outBuf
cmd.Stderr = &errBuf
d.logger.Printf("[DEBUG] driver.rkt: preparing pod %q for task %q with: %v", img, d.taskName, prepareArgs)
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("Error preparing rkt pod: %s\n\nOutput: %s\n\nError: %s",
err, outBuf.String(), errBuf.String())
}
uuid := strings.TrimSpace(outBuf.String())
d.logger.Printf("[DEBUG] driver.rkt: pod %q for task %q prepared, UUID is: %s", img, d.taskName, uuid)
runArgs = append(runArgs, uuid)
// The task's environment is set via --set-env flags above, but the rkt
// command itself needs an evironment with PATH set to find iptables.
eb := env.NewEmptyBuilder()
@@ -473,14 +606,9 @@ func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (*StartResponse,
return nil, fmt.Errorf("failed to set executor context: %v", err)
}
absPath, err := GetAbsolutePath(rktCmd)
if err != nil {
return nil, err
}
execCmd := &executor.ExecCommand{
Cmd: absPath,
Args: cmdArgs,
Args: runArgs,
User: task.User,
}
ps, err := execIntf.LaunchCmd(execCmd)
@@ -489,25 +617,7 @@ func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (*StartResponse,
return nil, err
}
// Wait for UUID file to get written
uuid := ""
deadline := time.Now().Add(rktUuidDeadline)
var lastErr error
for time.Now().Before(deadline) {
if uuidBytes, err := ioutil.ReadFile(uuidPath); err != nil {
lastErr = err
} else {
uuid = string(uuidBytes)
break
}
time.Sleep(400 * time.Millisecond)
}
if uuid == "" {
d.logger.Printf("[WARN] driver.rkt: reading uuid from %q failed; unable to run script checks for task %q. Last error: %v",
uuidPath, d.taskName, lastErr)
}
d.logger.Printf("[DEBUG] driver.rkt: started ACI %q (UUID: %s) for task %q with: %v", img, uuid, d.taskName, cmdArgs)
d.logger.Printf("[DEBUG] driver.rkt: started ACI %q (UUID: %s) for task %q with: %v", img, uuid, d.taskName, runArgs)
maxKill := d.DriverContext.config.MaxKillTimeout
h := &rktHandle{
uuid: uuid,
@@ -523,8 +633,20 @@ func (d *RktDriver) Start(ctx *ExecContext, task *structs.Task) (*StartResponse,
waitCh: make(chan *dstructs.WaitResult, 1),
}
go h.run()
//TODO Set Network
return &StartResponse{Handle: h}, nil
d.logger.Printf("[DEBUG] driver.rkt: retrieving network information for pod %q (UUID %s) for task %q", img, uuid, d.taskName)
driverNetwork, err := rktGetDriverNetwork(uuid, driverConfig.PortMap)
if err != nil && !pluginClient.Exited() {
d.logger.Printf("[WARN] driver.rkt: network status retrieval for pod %q (UUID %s) for task %q failed. Last error: %v", img, uuid, d.taskName, err)
// If a portmap was given, this turns into a fatal error
if len(driverConfig.PortMap) != 0 {
pluginClient.Kill()
return nil, fmt.Errorf("Trying to map ports but driver could not determine network information")
}
}
return &StartResponse{Handle: h, Network: driverNetwork}, nil
}
func (d *RktDriver) Cleanup(*ExecContext, *CreatedResources) error { return nil }

View File

@@ -449,7 +449,6 @@ func TestRktDriver_PortsMapping(t *testing.T) {
Driver: "rkt",
Config: map[string]interface{}{
"image": "docker://redis:latest",
"args": []string{"--version"},
"port_map": []map[string]string{
{
"main": "6379-tcp",
@@ -484,6 +483,9 @@ func TestRktDriver_PortsMapping(t *testing.T) {
if err != nil {
t.Fatalf("err: %v", err)
}
if resp.Network == nil {
t.Fatalf("Expected driver to set a DriverNetwork, but it did not!")
}
failCh := make(chan error, 1)
go func() {

View File

@@ -2,7 +2,7 @@
set -o errexit
VERSION=1.18.0
VERSION=1.27.0
DOWNLOAD=https://github.com/coreos/rkt/releases/download/v${VERSION}/rkt-v${VERSION}.tar.gz
function install_rkt() {
@@ -19,4 +19,29 @@ function install_rkt() {
mv /tmp/rkt-v${VERSION}/*.aci /usr/local/bin
}
function configure_rkt_networking() {
if [[ -e /etc/rkt/net.d/99-network.conf ]] ; then
return
fi
mkdir -p /etc/rkt/net.d
cat <<EOT > /etc/rkt/net.d/99-network.conf
{
"name": "default",
"type": "ptp",
"ipMasq": false,
"ipam": {
"type": "host-local",
"subnet": "172.16.28.0/24",
"routes": [
{
"dst": "0.0.0.0/0"
}
]
}
}
EOT
}
install_rkt
configure_rkt_networking

View File

@@ -2,7 +2,7 @@
set -o errexit
VERSION=1.18.0
VERSION=1.27.0
DOWNLOAD=https://github.com/coreos/rkt/releases/download/v${VERSION}/rkt-v${VERSION}.tar.gz
function install_rkt() {

202
vendor/github.com/appc/spec/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

40
vendor/github.com/appc/spec/schema/common/common.go generated vendored Normal file
View File

@@ -0,0 +1,40 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package common
import (
"fmt"
"net/url"
"strings"
)
// MakeQueryString takes a comma-separated LABEL=VALUE string and returns an
// "&"-separated string with URL escaped values.
//
// Examples:
// version=1.0.0,label=v1+v2 -> version=1.0.0&label=v1%2Bv2
// name=db,source=/tmp$1 -> name=db&source=%2Ftmp%241
func MakeQueryString(app string) (string, error) {
parts := strings.Split(app, ",")
escapedParts := make([]string, len(parts))
for i, s := range parts {
p := strings.SplitN(s, "=", 2)
if len(p) != 2 {
return "", fmt.Errorf("malformed string %q - has a label without a value: %s", app, p[0])
}
escapedParts[i] = fmt.Sprintf("%s=%s", p[0], url.QueryEscape(p[1]))
}
return strings.Join(escapedParts, "&"), nil
}

25
vendor/github.com/appc/spec/schema/doc.go generated vendored Normal file
View File

@@ -0,0 +1,25 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package schema provides definitions for the JSON schema of the different
// manifests in the App Container Specification. The manifests are canonically
// represented in their respective structs:
// - `ImageManifest`
// - `PodManifest`
//
// Validation is performed through serialization: if a blob of JSON data will
// unmarshal to one of the *Manifests, it is considered a valid implementation
// of the standard. Similarly, if a constructed *Manifest struct marshals
// successfully to JSON, it must be valid.
package schema

103
vendor/github.com/appc/spec/schema/image.go generated vendored Normal file
View File

@@ -0,0 +1,103 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package schema
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"github.com/appc/spec/schema/types"
"go4.org/errorutil"
)
const (
ACIExtension = ".aci"
ImageManifestKind = types.ACKind("ImageManifest")
)
type ImageManifest struct {
ACKind types.ACKind `json:"acKind"`
ACVersion types.SemVer `json:"acVersion"`
Name types.ACIdentifier `json:"name"`
Labels types.Labels `json:"labels,omitempty"`
App *types.App `json:"app,omitempty"`
Annotations types.Annotations `json:"annotations,omitempty"`
Dependencies types.Dependencies `json:"dependencies,omitempty"`
PathWhitelist []string `json:"pathWhitelist,omitempty"`
}
// imageManifest is a model to facilitate extra validation during the
// unmarshalling of the ImageManifest
type imageManifest ImageManifest
func BlankImageManifest() *ImageManifest {
return &ImageManifest{ACKind: ImageManifestKind, ACVersion: AppContainerVersion}
}
func (im *ImageManifest) UnmarshalJSON(data []byte) error {
a := imageManifest(*im)
err := json.Unmarshal(data, &a)
if err != nil {
if serr, ok := err.(*json.SyntaxError); ok {
line, col, highlight := errorutil.HighlightBytePosition(bytes.NewReader(data), serr.Offset)
return fmt.Errorf("\nError at line %d, column %d\n%s%v", line, col, highlight, err)
}
return err
}
nim := ImageManifest(a)
if err := nim.assertValid(); err != nil {
return err
}
*im = nim
return nil
}
func (im ImageManifest) MarshalJSON() ([]byte, error) {
if err := im.assertValid(); err != nil {
return nil, err
}
return json.Marshal(imageManifest(im))
}
var imKindError = types.InvalidACKindError(ImageManifestKind)
// assertValid performs extra assertions on an ImageManifest to ensure that
// fields are set appropriately, etc. It is used exclusively when marshalling
// and unmarshalling an ImageManifest. Most field-specific validation is
// performed through the individual types being marshalled; assertValid()
// should only deal with higher-level validation.
func (im *ImageManifest) assertValid() error {
if im.ACKind != ImageManifestKind {
return imKindError
}
if im.ACVersion.Empty() {
return errors.New(`acVersion must be set`)
}
if im.Name.Empty() {
return errors.New(`name must be set`)
}
return nil
}
func (im *ImageManifest) GetLabel(name string) (val string, ok bool) {
return im.Labels.Get(name)
}
func (im *ImageManifest) GetAnnotation(name string) (val string, ok bool) {
return im.Annotations.Get(name)
}

42
vendor/github.com/appc/spec/schema/kind.go generated vendored Normal file
View File

@@ -0,0 +1,42 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package schema
import (
"encoding/json"
"github.com/appc/spec/schema/types"
)
type Kind struct {
ACVersion types.SemVer `json:"acVersion"`
ACKind types.ACKind `json:"acKind"`
}
type kind Kind
func (k *Kind) UnmarshalJSON(data []byte) error {
nk := kind{}
err := json.Unmarshal(data, &nk)
if err != nil {
return err
}
*k = Kind(nk)
return nil
}
func (k Kind) MarshalJSON() ([]byte, error) {
return json.Marshal(kind(k))
}

182
vendor/github.com/appc/spec/schema/pod.go generated vendored Normal file
View File

@@ -0,0 +1,182 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package schema
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"github.com/appc/spec/schema/types"
"go4.org/errorutil"
)
const PodManifestKind = types.ACKind("PodManifest")
type PodManifest struct {
ACVersion types.SemVer `json:"acVersion"`
ACKind types.ACKind `json:"acKind"`
Apps AppList `json:"apps"`
Volumes []types.Volume `json:"volumes"`
Isolators []types.Isolator `json:"isolators"`
Annotations types.Annotations `json:"annotations"`
Ports []types.ExposedPort `json:"ports"`
UserAnnotations types.UserAnnotations `json:"userAnnotations,omitempty"`
UserLabels types.UserLabels `json:"userLabels,omitempty"`
}
// podManifest is a model to facilitate extra validation during the
// unmarshalling of the PodManifest
type podManifest PodManifest
func BlankPodManifest() *PodManifest {
return &PodManifest{ACKind: PodManifestKind, ACVersion: AppContainerVersion}
}
func (pm *PodManifest) UnmarshalJSON(data []byte) error {
p := podManifest(*pm)
err := json.Unmarshal(data, &p)
if err != nil {
if serr, ok := err.(*json.SyntaxError); ok {
line, col, highlight := errorutil.HighlightBytePosition(bytes.NewReader(data), serr.Offset)
return fmt.Errorf("\nError at line %d, column %d\n%s%v", line, col, highlight, err)
}
return err
}
npm := PodManifest(p)
if err := npm.assertValid(); err != nil {
return err
}
*pm = npm
return nil
}
func (pm PodManifest) MarshalJSON() ([]byte, error) {
if err := pm.assertValid(); err != nil {
return nil, err
}
return json.Marshal(podManifest(pm))
}
var pmKindError = types.InvalidACKindError(PodManifestKind)
// assertValid performs extra assertions on an PodManifest to
// ensure that fields are set appropriately, etc. It is used exclusively when
// marshalling and unmarshalling an PodManifest. Most
// field-specific validation is performed through the individual types being
// marshalled; assertValid() should only deal with higher-level validation.
func (pm *PodManifest) assertValid() error {
if pm.ACKind != PodManifestKind {
return pmKindError
}
// ensure volumes names are unique (unique key)
volNames := make(map[types.ACName]bool, len(pm.Volumes))
for _, vol := range pm.Volumes {
if volNames[vol.Name] {
return fmt.Errorf("duplicate volume name %q", vol.Name)
}
volNames[vol.Name] = true
}
return nil
}
type AppList []RuntimeApp
type appList AppList
func (al *AppList) UnmarshalJSON(data []byte) error {
a := appList{}
err := json.Unmarshal(data, &a)
if err != nil {
return err
}
nal := AppList(a)
if err := nal.assertValid(); err != nil {
return err
}
*al = nal
return nil
}
func (al AppList) MarshalJSON() ([]byte, error) {
if err := al.assertValid(); err != nil {
return nil, err
}
return json.Marshal(appList(al))
}
func (al AppList) assertValid() error {
seen := map[types.ACName]bool{}
for _, a := range al {
if _, ok := seen[a.Name]; ok {
return fmt.Errorf(`duplicate apps of name %q`, a.Name)
}
seen[a.Name] = true
}
return nil
}
// Get retrieves an app by the specified name from the AppList; if there is
// no such app, nil is returned. The returned *RuntimeApp MUST be considered
// read-only.
func (al AppList) Get(name types.ACName) *RuntimeApp {
for _, a := range al {
if name.Equals(a.Name) {
aa := a
return &aa
}
}
return nil
}
// Mount describes the mapping between a volume and the path it is mounted
// inside of an app's filesystem.
// The AppVolume is optional. If missing, the pod-level Volume of the
// same name shall be used.
type Mount struct {
Volume types.ACName `json:"volume"`
Path string `json:"path"`
AppVolume *types.Volume `json:"appVolume,omitempty"`
}
func (r Mount) assertValid() error {
if r.Volume.Empty() {
return errors.New("volume must be set")
}
if r.Path == "" {
return errors.New("path must be set")
}
return nil
}
// RuntimeApp describes an application referenced in a PodManifest
type RuntimeApp struct {
Name types.ACName `json:"name"`
Image RuntimeImage `json:"image"`
App *types.App `json:"app,omitempty"`
ReadOnlyRootFS bool `json:"readOnlyRootFS,omitempty"`
Mounts []Mount `json:"mounts,omitempty"`
Annotations types.Annotations `json:"annotations,omitempty"`
}
// RuntimeImage describes an image referenced in a RuntimeApp
type RuntimeImage struct {
Name *types.ACIdentifier `json:"name,omitempty"`
ID types.Hash `json:"id"`
Labels types.Labels `json:"labels,omitempty"`
}

View File

@@ -0,0 +1,145 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
"errors"
"regexp"
"strings"
)
var (
// ValidACIdentifier is a regular expression that defines a valid ACIdentifier
ValidACIdentifier = regexp.MustCompile("^[a-z0-9]+([-._~/][a-z0-9]+)*$")
invalidACIdentifierChars = regexp.MustCompile("[^a-z0-9-._~/]")
invalidACIdentifierEdges = regexp.MustCompile("(^[-._~/]+)|([-._~/]+$)")
ErrEmptyACIdentifier = ACIdentifierError("ACIdentifier cannot be empty")
ErrInvalidEdgeInACIdentifier = ACIdentifierError("ACIdentifier must start and end with only lower case " +
"alphanumeric characters")
ErrInvalidCharInACIdentifier = ACIdentifierError("ACIdentifier must contain only lower case " +
`alphanumeric characters plus "-._~/"`)
)
// ACIdentifier (an App-Container Identifier) is a format used by keys in image names
// and image labels of the App Container Standard. An ACIdentifier is restricted to numeric
// and lowercase URI unreserved characters defined in URI RFC[1]; all alphabetical characters
// must be lowercase only. Furthermore, the first and last character ("edges") must be
// alphanumeric, and an ACIdentifier cannot be empty. Programmatically, an ACIdentifier must
// conform to the regular expression ValidACIdentifier.
//
// [1] http://tools.ietf.org/html/rfc3986#section-2.3
type ACIdentifier string
func (n ACIdentifier) String() string {
return string(n)
}
// Set sets the ACIdentifier to the given value, if it is valid; if not,
// an error is returned.
func (n *ACIdentifier) Set(s string) error {
nn, err := NewACIdentifier(s)
if err == nil {
*n = *nn
}
return err
}
// Equals checks whether a given ACIdentifier is equal to this one.
func (n ACIdentifier) Equals(o ACIdentifier) bool {
return strings.ToLower(string(n)) == strings.ToLower(string(o))
}
// Empty returns a boolean indicating whether this ACIdentifier is empty.
func (n ACIdentifier) Empty() bool {
return n.String() == ""
}
// NewACIdentifier generates a new ACIdentifier from a string. If the given string is
// not a valid ACIdentifier, nil and an error are returned.
func NewACIdentifier(s string) (*ACIdentifier, error) {
n := ACIdentifier(s)
if err := n.assertValid(); err != nil {
return nil, err
}
return &n, nil
}
// MustACIdentifier generates a new ACIdentifier from a string, If the given string is
// not a valid ACIdentifier, it panics.
func MustACIdentifier(s string) *ACIdentifier {
n, err := NewACIdentifier(s)
if err != nil {
panic(err)
}
return n
}
func (n ACIdentifier) assertValid() error {
s := string(n)
if len(s) == 0 {
return ErrEmptyACIdentifier
}
if invalidACIdentifierChars.MatchString(s) {
return ErrInvalidCharInACIdentifier
}
if invalidACIdentifierEdges.MatchString(s) {
return ErrInvalidEdgeInACIdentifier
}
return nil
}
// UnmarshalJSON implements the json.Unmarshaler interface
func (n *ACIdentifier) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
nn, err := NewACIdentifier(s)
if err != nil {
return err
}
*n = *nn
return nil
}
// MarshalJSON implements the json.Marshaler interface
func (n ACIdentifier) MarshalJSON() ([]byte, error) {
if err := n.assertValid(); err != nil {
return nil, err
}
return json.Marshal(n.String())
}
// SanitizeACIdentifier replaces every invalid ACIdentifier character in s with an underscore
// making it a legal ACIdentifier string. If the character is an upper case letter it
// replaces it with its lower case. It also removes illegal edge characters
// (hyphens, period, underscore, tilde and slash).
//
// This is a helper function and its algorithm is not part of the spec. It
// should not be called without the user explicitly asking for a suggestion.
func SanitizeACIdentifier(s string) (string, error) {
s = strings.ToLower(s)
s = invalidACIdentifierChars.ReplaceAllString(s, "_")
s = invalidACIdentifierEdges.ReplaceAllString(s, "")
if s == "" {
return "", errors.New("must contain at least one valid character")
}
return s, nil
}

67
vendor/github.com/appc/spec/schema/types/ackind.go generated vendored Normal file
View File

@@ -0,0 +1,67 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
"fmt"
)
var (
ErrNoACKind = ACKindError("ACKind must be set")
)
// ACKind wraps a string to define a field which must be set with one of
// several ACKind values. If it is unset, or has an invalid value, the field
// will refuse to marshal/unmarshal.
type ACKind string
func (a ACKind) String() string {
return string(a)
}
func (a ACKind) assertValid() error {
s := a.String()
switch s {
case "ImageManifest", "PodManifest":
return nil
case "":
return ErrNoACKind
default:
msg := fmt.Sprintf("bad ACKind: %s", s)
return ACKindError(msg)
}
}
func (a ACKind) MarshalJSON() ([]byte, error) {
if err := a.assertValid(); err != nil {
return nil, err
}
return json.Marshal(a.String())
}
func (a *ACKind) UnmarshalJSON(data []byte) error {
var s string
err := json.Unmarshal(data, &s)
if err != nil {
return err
}
na := ACKind(s)
if err := na.assertValid(); err != nil {
return err
}
*a = na
return nil
}

145
vendor/github.com/appc/spec/schema/types/acname.go generated vendored Normal file
View File

@@ -0,0 +1,145 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
"errors"
"regexp"
"strings"
)
var (
// ValidACName is a regular expression that defines a valid ACName
ValidACName = regexp.MustCompile("^[a-z0-9]+([-][a-z0-9]+)*$")
invalidACNameChars = regexp.MustCompile("[^a-z0-9-]")
invalidACNameEdges = regexp.MustCompile("(^[-]+)|([-]+$)")
ErrEmptyACName = ACNameError("ACName cannot be empty")
ErrInvalidEdgeInACName = ACNameError("ACName must start and end with only lower case " +
"alphanumeric characters")
ErrInvalidCharInACName = ACNameError("ACName must contain only lower case " +
`alphanumeric characters plus "-"`)
)
// ACName (an App-Container Name) is a format used by keys in different formats
// of the App Container Standard. An ACName is restricted to numeric and lowercase
// characters accepted by the DNS RFC[1] plus "-"; all alphabetical characters must
// be lowercase only. Furthermore, the first and last character ("edges") must be
// alphanumeric, and an ACName cannot be empty. Programmatically, an ACName must
// conform to the regular expression ValidACName.
//
// [1] http://tools.ietf.org/html/rfc1123#page-13
type ACName string
func (n ACName) String() string {
return string(n)
}
// Set sets the ACName to the given value, if it is valid; if not,
// an error is returned.
func (n *ACName) Set(s string) error {
nn, err := NewACName(s)
if err == nil {
*n = *nn
}
return err
}
// Equals checks whether a given ACName is equal to this one.
func (n ACName) Equals(o ACName) bool {
return strings.ToLower(string(n)) == strings.ToLower(string(o))
}
// Empty returns a boolean indicating whether this ACName is empty.
func (n ACName) Empty() bool {
return n.String() == ""
}
// NewACName generates a new ACName from a string. If the given string is
// not a valid ACName, nil and an error are returned.
func NewACName(s string) (*ACName, error) {
n := ACName(s)
if err := n.assertValid(); err != nil {
return nil, err
}
return &n, nil
}
// MustACName generates a new ACName from a string, If the given string is
// not a valid ACName, it panics.
func MustACName(s string) *ACName {
n, err := NewACName(s)
if err != nil {
panic(err)
}
return n
}
func (n ACName) assertValid() error {
s := string(n)
if len(s) == 0 {
return ErrEmptyACName
}
if invalidACNameChars.MatchString(s) {
return ErrInvalidCharInACName
}
if invalidACNameEdges.MatchString(s) {
return ErrInvalidEdgeInACName
}
return nil
}
// UnmarshalJSON implements the json.Unmarshaler interface
func (n *ACName) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
nn, err := NewACName(s)
if err != nil {
return err
}
*n = *nn
return nil
}
// MarshalJSON implements the json.Marshaler interface
func (n ACName) MarshalJSON() ([]byte, error) {
if err := n.assertValid(); err != nil {
return nil, err
}
return json.Marshal(n.String())
}
// SanitizeACName replaces every invalid ACName character in s with a dash
// making it a legal ACName string. If the character is an upper case letter it
// replaces it with its lower case. It also removes illegal edge characters
// (hyphens).
//
// This is a helper function and its algorithm is not part of the spec. It
// should not be called without the user explicitly asking for a suggestion.
func SanitizeACName(s string) (string, error) {
s = strings.ToLower(s)
s = invalidACNameChars.ReplaceAllString(s, "-")
s = invalidACNameEdges.ReplaceAllString(s, "")
if s == "" {
return "", errors.New("must contain at least one valid character")
}
return s, nil
}

106
vendor/github.com/appc/spec/schema/types/annotations.go generated vendored Normal file
View File

@@ -0,0 +1,106 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
"fmt"
)
type Annotations []Annotation
type annotations Annotations
type Annotation struct {
Name ACIdentifier `json:"name"`
Value string `json:"value"`
}
func (a Annotations) assertValid() error {
seen := map[ACIdentifier]string{}
for _, anno := range a {
_, ok := seen[anno.Name]
if ok {
return fmt.Errorf(`duplicate annotations of name %q`, anno.Name)
}
seen[anno.Name] = anno.Value
}
if c, ok := seen["created"]; ok {
if _, err := NewDate(c); err != nil {
return err
}
}
if h, ok := seen["homepage"]; ok {
if _, err := NewURL(h); err != nil {
return err
}
}
if d, ok := seen["documentation"]; ok {
if _, err := NewURL(d); err != nil {
return err
}
}
return nil
}
func (a Annotations) MarshalJSON() ([]byte, error) {
if err := a.assertValid(); err != nil {
return nil, err
}
return json.Marshal(annotations(a))
}
func (a *Annotations) UnmarshalJSON(data []byte) error {
var ja annotations
if err := json.Unmarshal(data, &ja); err != nil {
return err
}
na := Annotations(ja)
if err := na.assertValid(); err != nil {
return err
}
*a = na
return nil
}
// Retrieve the value of an annotation by the given name from Annotations, if
// it exists.
func (a Annotations) Get(name string) (val string, ok bool) {
for _, anno := range a {
if anno.Name.String() == name {
return anno.Value, true
}
}
return "", false
}
// Set sets the value of an annotation by the given name, overwriting if one already exists.
func (a *Annotations) Set(name ACIdentifier, value string) {
for i, anno := range *a {
if anno.Name.Equals(name) {
(*a)[i] = Annotation{
Name: name,
Value: value,
}
return
}
}
anno := Annotation{
Name: name,
Value: value,
}
*a = append(*a, anno)
}

95
vendor/github.com/appc/spec/schema/types/app.go generated vendored Normal file
View File

@@ -0,0 +1,95 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
"errors"
"fmt"
"path"
)
type App struct {
Exec Exec `json:"exec"`
EventHandlers []EventHandler `json:"eventHandlers,omitempty"`
User string `json:"user"`
Group string `json:"group"`
SupplementaryGIDs []int `json:"supplementaryGIDs,omitempty"`
WorkingDirectory string `json:"workingDirectory,omitempty"`
Environment Environment `json:"environment,omitempty"`
MountPoints []MountPoint `json:"mountPoints,omitempty"`
Ports []Port `json:"ports,omitempty"`
Isolators Isolators `json:"isolators,omitempty"`
UserAnnotations UserAnnotations `json:"userAnnotations,omitempty"`
UserLabels UserLabels `json:"userLabels,omitempty"`
}
// app is a model to facilitate extra validation during the
// unmarshalling of the App
type app App
func (a *App) UnmarshalJSON(data []byte) error {
ja := app(*a)
err := json.Unmarshal(data, &ja)
if err != nil {
return err
}
na := App(ja)
if err := na.assertValid(); err != nil {
return err
}
if na.Environment == nil {
na.Environment = make(Environment, 0)
}
*a = na
return nil
}
func (a App) MarshalJSON() ([]byte, error) {
if err := a.assertValid(); err != nil {
return nil, err
}
return json.Marshal(app(a))
}
func (a *App) assertValid() error {
if err := a.Exec.assertValid(); err != nil {
return err
}
if a.User == "" {
return errors.New(`user is required`)
}
if a.Group == "" {
return errors.New(`group is required`)
}
if !path.IsAbs(a.WorkingDirectory) && a.WorkingDirectory != "" {
return errors.New("workingDirectory must be an absolute path")
}
eh := make(map[string]bool)
for _, e := range a.EventHandlers {
name := e.Name
if eh[name] {
return fmt.Errorf("Only one eventHandler of name %q allowed", name)
}
eh[name] = true
}
if err := a.Environment.assertValid(); err != nil {
return err
}
if err := a.Isolators.assertValid(); err != nil {
return err
}
return nil
}

60
vendor/github.com/appc/spec/schema/types/date.go generated vendored Normal file
View File

@@ -0,0 +1,60 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
"fmt"
"time"
)
// Date wraps time.Time to marshal/unmarshal to/from JSON strings in strict
// accordance with RFC3339
// TODO(jonboulle): golang's implementation seems slightly buggy here;
// according to http://tools.ietf.org/html/rfc3339#section-5.6 , applications
// may choose to separate the date and time with a space instead of a T
// character (for example, `date --rfc-3339` on GNU coreutils) - but this is
// considered an error by go's parser. File a bug?
type Date time.Time
func NewDate(s string) (*Date, error) {
t, err := time.Parse(time.RFC3339, s)
if err != nil {
return nil, fmt.Errorf("bad Date: %v", err)
}
d := Date(t)
return &d, nil
}
func (d Date) String() string {
return time.Time(d).Format(time.RFC3339)
}
func (d *Date) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
nd, err := NewDate(s)
if err != nil {
return err
}
*d = *nd
return nil
}
func (d Date) MarshalJSON() ([]byte, error) {
return json.Marshal(d.String())
}

View File

@@ -0,0 +1,58 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
"errors"
)
type Dependencies []Dependency
type Dependency struct {
ImageName ACIdentifier `json:"imageName"`
ImageID *Hash `json:"imageID,omitempty"`
Labels Labels `json:"labels,omitempty"`
Size uint `json:"size,omitempty"`
}
type dependency Dependency
func (d Dependency) assertValid() error {
if len(d.ImageName) < 1 {
return errors.New(`imageName cannot be empty`)
}
return nil
}
func (d Dependency) MarshalJSON() ([]byte, error) {
if err := d.assertValid(); err != nil {
return nil, err
}
return json.Marshal(dependency(d))
}
func (d *Dependency) UnmarshalJSON(data []byte) error {
var jd dependency
if err := json.Unmarshal(data, &jd); err != nil {
return err
}
nd := Dependency(jd)
if err := nd.assertValid(); err != nil {
return err
}
*d = nd
return nil
}

18
vendor/github.com/appc/spec/schema/types/doc.go generated vendored Normal file
View File

@@ -0,0 +1,18 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package types contains structs representing the various types in the app
// container specification. It is used by the [schema manifest types](../)
// to enforce validation.
package types

110
vendor/github.com/appc/spec/schema/types/environment.go generated vendored Normal file
View File

@@ -0,0 +1,110 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
"fmt"
"regexp"
)
var (
envPattern = regexp.MustCompile("^[A-Za-z_][A-Za-z_0-9.-]*$")
)
type Environment []EnvironmentVariable
type environment Environment
type EnvironmentVariable struct {
Name string `json:"name"`
Value string `json:"value"`
}
func (ev EnvironmentVariable) assertValid() error {
if len(ev.Name) == 0 {
return fmt.Errorf(`environment variable name must not be empty`)
}
if !envPattern.MatchString(ev.Name) {
return fmt.Errorf(`environment variable does not have valid identifier %q`, ev.Name)
}
return nil
}
func (e Environment) assertValid() error {
seen := map[string]bool{}
for _, env := range e {
if err := env.assertValid(); err != nil {
return err
}
_, ok := seen[env.Name]
if ok {
return fmt.Errorf(`duplicate environment variable of name %q`, env.Name)
}
seen[env.Name] = true
}
return nil
}
func (e Environment) MarshalJSON() ([]byte, error) {
if err := e.assertValid(); err != nil {
return nil, err
}
return json.Marshal(environment(e))
}
func (e *Environment) UnmarshalJSON(data []byte) error {
var je environment
if err := json.Unmarshal(data, &je); err != nil {
return err
}
ne := Environment(je)
if err := ne.assertValid(); err != nil {
return err
}
*e = ne
return nil
}
// Retrieve the value of an environment variable by the given name from
// Environment, if it exists.
func (e Environment) Get(name string) (value string, ok bool) {
for _, env := range e {
if env.Name == name {
return env.Value, true
}
}
return "", false
}
// Set sets the value of an environment variable by the given name,
// overwriting if one already exists.
func (e *Environment) Set(name string, value string) {
for i, env := range *e {
if env.Name == name {
(*e)[i] = EnvironmentVariable{
Name: name,
Value: value,
}
return
}
}
env := EnvironmentVariable{
Name: name,
Value: value,
}
*e = append(*e, env)
}

49
vendor/github.com/appc/spec/schema/types/errors.go generated vendored Normal file
View File

@@ -0,0 +1,49 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import "fmt"
// An ACKindError is returned when the wrong ACKind is set in a manifest
type ACKindError string
func (e ACKindError) Error() string {
return string(e)
}
func InvalidACKindError(kind ACKind) ACKindError {
return ACKindError(fmt.Sprintf("missing or bad ACKind (must be %#v)", kind))
}
// An ACVersionError is returned when a bad ACVersion is set in a manifest
type ACVersionError string
func (e ACVersionError) Error() string {
return string(e)
}
// An ACIdentifierError is returned when a bad value is used for an ACIdentifier
type ACIdentifierError string
func (e ACIdentifierError) Error() string {
return string(e)
}
// An ACNameError is returned when a bad value is used for an ACName
type ACNameError string
func (e ACNameError) Error() string {
return string(e)
}

View File

@@ -0,0 +1,61 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
"errors"
"fmt"
)
type EventHandler struct {
Name string `json:"name"`
Exec Exec `json:"exec"`
}
type eventHandler EventHandler
func (e EventHandler) assertValid() error {
s := e.Name
switch s {
case "pre-start", "post-stop":
return nil
case "":
return errors.New(`eventHandler "name" cannot be empty`)
default:
return fmt.Errorf(`bad eventHandler "name": %q`, s)
}
}
func (e EventHandler) MarshalJSON() ([]byte, error) {
if err := e.assertValid(); err != nil {
return nil, err
}
return json.Marshal(eventHandler(e))
}
func (e *EventHandler) UnmarshalJSON(data []byte) error {
var je eventHandler
err := json.Unmarshal(data, &je)
if err != nil {
return err
}
ne := EventHandler(je)
if err := ne.assertValid(); err != nil {
return err
}
*e = ne
return nil
}

46
vendor/github.com/appc/spec/schema/types/exec.go generated vendored Normal file
View File

@@ -0,0 +1,46 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import "encoding/json"
type Exec []string
type exec Exec
func (e Exec) assertValid() error {
return nil
}
func (e Exec) MarshalJSON() ([]byte, error) {
if err := e.assertValid(); err != nil {
return nil, err
}
return json.Marshal(exec(e))
}
func (e *Exec) UnmarshalJSON(data []byte) error {
var je exec
err := json.Unmarshal(data, &je)
if err != nil {
return err
}
ne := Exec(je)
if err := ne.assertValid(); err != nil {
return err
}
*e = ne
return nil
}

118
vendor/github.com/appc/spec/schema/types/hash.go generated vendored Normal file
View File

@@ -0,0 +1,118 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"crypto/sha512"
"encoding/json"
"errors"
"fmt"
"reflect"
"strings"
)
const (
maxHashSize = (sha512.Size / 2) + len("sha512-")
)
// Hash encodes a hash specified in a string of the form:
// "<type>-<value>"
// for example
// "sha512-06c733b1838136838e6d2d3e8fa5aea4c7905e92[...]"
// Valid types are currently:
// * sha512
type Hash struct {
typ string
Val string
}
func NewHash(s string) (*Hash, error) {
elems := strings.Split(s, "-")
if len(elems) != 2 {
return nil, errors.New("badly formatted hash string")
}
nh := Hash{
typ: elems[0],
Val: elems[1],
}
if err := nh.assertValid(); err != nil {
return nil, err
}
return &nh, nil
}
func (h Hash) String() string {
return fmt.Sprintf("%s-%s", h.typ, h.Val)
}
func (h *Hash) Set(s string) error {
nh, err := NewHash(s)
if err == nil {
*h = *nh
}
return err
}
func (h Hash) Empty() bool {
return reflect.DeepEqual(h, Hash{})
}
func (h Hash) assertValid() error {
switch h.typ {
case "sha512":
case "":
return fmt.Errorf("unexpected empty hash type")
default:
return fmt.Errorf("unrecognized hash type: %v", h.typ)
}
if h.Val == "" {
return fmt.Errorf("unexpected empty hash value")
}
return nil
}
func (h *Hash) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
nh, err := NewHash(s)
if err != nil {
return err
}
*h = *nh
return nil
}
func (h Hash) MarshalJSON() ([]byte, error) {
if err := h.assertValid(); err != nil {
return nil, err
}
return json.Marshal(h.String())
}
func NewHashSHA512(b []byte) *Hash {
h := sha512.New()
h.Write(b)
nh, _ := NewHash(fmt.Sprintf("sha512-%x", h.Sum(nil)))
return nh
}
func ShortHash(hash string) string {
if len(hash) > maxHashSize {
return hash[:maxHashSize]
}
return hash
}

190
vendor/github.com/appc/spec/schema/types/isolator.go generated vendored Normal file
View File

@@ -0,0 +1,190 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
"errors"
"fmt"
)
var (
isolatorMap map[ACIdentifier]IsolatorValueConstructor
// ErrIncompatibleIsolator is returned whenever an Isolators set contains
// conflicting IsolatorValue instances
ErrIncompatibleIsolator = errors.New("isolators set contains incompatible types")
// ErrInvalidIsolator is returned upon validation failures due to improper
// or partially constructed Isolator instances (eg. from incomplete direct construction)
ErrInvalidIsolator = errors.New("invalid isolator")
)
func init() {
isolatorMap = make(map[ACIdentifier]IsolatorValueConstructor)
}
type IsolatorValueConstructor func() IsolatorValue
func AddIsolatorValueConstructor(n ACIdentifier, i IsolatorValueConstructor) {
isolatorMap[n] = i
}
func AddIsolatorName(n ACIdentifier, ns map[ACIdentifier]struct{}) {
ns[n] = struct{}{}
}
// Isolators encapsulates a list of individual Isolators for the ImageManifest
// and PodManifest schemas.
type Isolators []Isolator
// assertValid checks that every single isolator is valid and that
// the whole set is well built
func (isolators Isolators) assertValid() error {
typesMap := make(map[ACIdentifier]bool)
for _, i := range isolators {
v := i.Value()
if v == nil {
return ErrInvalidIsolator
}
if err := v.AssertValid(); err != nil {
return err
}
if _, ok := typesMap[i.Name]; ok {
if !v.multipleAllowed() {
return fmt.Errorf(`isolators set contains too many instances of type %s"`, i.Name)
}
}
for _, c := range v.Conflicts() {
if _, found := typesMap[c]; found {
return ErrIncompatibleIsolator
}
}
typesMap[i.Name] = true
}
return nil
}
// GetByName returns the last isolator in the list by the given name.
func (is *Isolators) GetByName(name ACIdentifier) *Isolator {
var i Isolator
for j := len(*is) - 1; j >= 0; j-- {
i = []Isolator(*is)[j]
if i.Name == name {
return &i
}
}
return nil
}
// ReplaceIsolatorsByName overrides matching isolator types with a new
// isolator, deleting them all and appending the new one instead
func (is *Isolators) ReplaceIsolatorsByName(newIs Isolator, oldNames []ACIdentifier) {
var i Isolator
for j := len(*is) - 1; j >= 0; j-- {
i = []Isolator(*is)[j]
for _, name := range oldNames {
if i.Name == name {
*is = append((*is)[:j], (*is)[j+1:]...)
}
}
}
*is = append((*is)[:], newIs)
return
}
// Unrecognized returns a set of isolators that are not recognized.
// An isolator is not recognized if it has not had an associated
// constructor registered with AddIsolatorValueConstructor.
func (is *Isolators) Unrecognized() Isolators {
u := Isolators{}
for _, i := range *is {
if i.value == nil {
u = append(u, i)
}
}
return u
}
// IsolatorValue encapsulates the actual value of an Isolator which may be
// serialized as any arbitrary JSON blob. Specific Isolator types should
// implement this interface to facilitate unmarshalling and validation.
type IsolatorValue interface {
// UnmarshalJSON unserialize a JSON-encoded isolator
UnmarshalJSON(b []byte) error
// AssertValid returns a non-nil error value if an IsolatorValue is not valid
// according to appc spec
AssertValid() error
// Conflicts returns a list of conflicting isolators types, which cannot co-exist
// together with this IsolatorValue
Conflicts() []ACIdentifier
// multipleAllowed specifies whether multiple isolator instances are allowed
// for this isolator type
multipleAllowed() bool
}
// Isolator is a model for unmarshalling isolator types from their JSON-encoded
// representation.
type Isolator struct {
// Name is the name of the Isolator type as defined in the specification.
Name ACIdentifier `json:"name"`
// ValueRaw captures the raw JSON value of an Isolator that was
// unmarshalled. This field is used for unmarshalling only. It MUST NOT
// be referenced by external users of the Isolator struct. It is
// exported only to satisfy Go's unfortunate requirement that fields
// must be capitalized to be unmarshalled successfully.
ValueRaw *json.RawMessage `json:"value"`
// value captures the "true" value of the isolator.
value IsolatorValue
}
// isolator is a shadow type used for unmarshalling.
type isolator Isolator
// Value returns the raw Value of this Isolator. Users should perform a type
// switch/assertion on this value to extract the underlying isolator type.
func (i *Isolator) Value() IsolatorValue {
return i.value
}
// UnmarshalJSON populates this Isolator from a JSON-encoded representation. To
// unmarshal the Value of the Isolator, it will use the appropriate constructor
// as registered by AddIsolatorValueConstructor.
func (i *Isolator) UnmarshalJSON(b []byte) error {
var ii isolator
err := json.Unmarshal(b, &ii)
if err != nil {
return err
}
var dst IsolatorValue
con, ok := isolatorMap[ii.Name]
if ok {
dst = con()
err = dst.UnmarshalJSON(*ii.ValueRaw)
if err != nil {
return err
}
err = dst.AssertValid()
if err != nil {
return err
}
}
i.value = dst
i.ValueRaw = ii.ValueRaw
i.Name = ii.Name
return nil
}

View File

@@ -0,0 +1,533 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
"errors"
"fmt"
"strings"
"unicode"
)
const (
LinuxCapabilitiesRetainSetName = "os/linux/capabilities-retain-set"
LinuxCapabilitiesRevokeSetName = "os/linux/capabilities-remove-set"
LinuxNoNewPrivilegesName = "os/linux/no-new-privileges"
LinuxSeccompRemoveSetName = "os/linux/seccomp-remove-set"
LinuxSeccompRetainSetName = "os/linux/seccomp-retain-set"
LinuxOOMScoreAdjName = "os/linux/oom-score-adj"
LinuxCPUSharesName = "os/linux/cpu-shares"
LinuxSELinuxContextName = "os/linux/selinux-context"
)
var LinuxIsolatorNames = make(map[ACIdentifier]struct{})
func init() {
for name, con := range map[ACIdentifier]IsolatorValueConstructor{
LinuxCapabilitiesRevokeSetName: func() IsolatorValue { return &LinuxCapabilitiesRevokeSet{} },
LinuxCapabilitiesRetainSetName: func() IsolatorValue { return &LinuxCapabilitiesRetainSet{} },
LinuxNoNewPrivilegesName: func() IsolatorValue { v := LinuxNoNewPrivileges(false); return &v },
LinuxOOMScoreAdjName: func() IsolatorValue { v := LinuxOOMScoreAdj(0); return &v },
LinuxCPUSharesName: func() IsolatorValue { v := LinuxCPUShares(1024); return &v },
LinuxSeccompRemoveSetName: func() IsolatorValue { return &LinuxSeccompRemoveSet{} },
LinuxSeccompRetainSetName: func() IsolatorValue { return &LinuxSeccompRetainSet{} },
LinuxSELinuxContextName: func() IsolatorValue { return &LinuxSELinuxContext{} },
} {
AddIsolatorName(name, LinuxIsolatorNames)
AddIsolatorValueConstructor(name, con)
}
}
type LinuxNoNewPrivileges bool
func (l LinuxNoNewPrivileges) AssertValid() error {
return nil
}
// TODO(lucab): both need to be clarified in spec,
// see https://github.com/appc/spec/issues/625
func (l LinuxNoNewPrivileges) multipleAllowed() bool {
return true
}
func (l LinuxNoNewPrivileges) Conflicts() []ACIdentifier {
return nil
}
func (l *LinuxNoNewPrivileges) UnmarshalJSON(b []byte) error {
var v bool
err := json.Unmarshal(b, &v)
if err != nil {
return err
}
*l = LinuxNoNewPrivileges(v)
return nil
}
type AsIsolator interface {
AsIsolator() (*Isolator, error)
}
type LinuxCapabilitiesSet interface {
Set() []LinuxCapability
AssertValid() error
}
type LinuxCapability string
type linuxCapabilitiesSetValue struct {
Set []LinuxCapability `json:"set"`
}
type linuxCapabilitiesSetBase struct {
val linuxCapabilitiesSetValue
}
func (l linuxCapabilitiesSetBase) AssertValid() error {
if len(l.val.Set) == 0 {
return errors.New("set must be non-empty")
}
return nil
}
// TODO(lucab): both need to be clarified in spec,
// see https://github.com/appc/spec/issues/625
func (l linuxCapabilitiesSetBase) multipleAllowed() bool {
return true
}
func (l linuxCapabilitiesSetBase) Conflicts() []ACIdentifier {
return nil
}
func (l *linuxCapabilitiesSetBase) UnmarshalJSON(b []byte) error {
var v linuxCapabilitiesSetValue
err := json.Unmarshal(b, &v)
if err != nil {
return err
}
l.val = v
return err
}
func (l linuxCapabilitiesSetBase) Set() []LinuxCapability {
return l.val.Set
}
type LinuxCapabilitiesRetainSet struct {
linuxCapabilitiesSetBase
}
func NewLinuxCapabilitiesRetainSet(caps ...string) (*LinuxCapabilitiesRetainSet, error) {
l := LinuxCapabilitiesRetainSet{
linuxCapabilitiesSetBase{
linuxCapabilitiesSetValue{
make([]LinuxCapability, len(caps)),
},
},
}
for i, c := range caps {
l.linuxCapabilitiesSetBase.val.Set[i] = LinuxCapability(c)
}
if err := l.AssertValid(); err != nil {
return nil, err
}
return &l, nil
}
func (l LinuxCapabilitiesRetainSet) AsIsolator() (*Isolator, error) {
b, err := json.Marshal(l.linuxCapabilitiesSetBase.val)
if err != nil {
return nil, err
}
rm := json.RawMessage(b)
return &Isolator{
Name: LinuxCapabilitiesRetainSetName,
ValueRaw: &rm,
value: &l,
}, nil
}
type LinuxCapabilitiesRevokeSet struct {
linuxCapabilitiesSetBase
}
func NewLinuxCapabilitiesRevokeSet(caps ...string) (*LinuxCapabilitiesRevokeSet, error) {
l := LinuxCapabilitiesRevokeSet{
linuxCapabilitiesSetBase{
linuxCapabilitiesSetValue{
make([]LinuxCapability, len(caps)),
},
},
}
for i, c := range caps {
l.linuxCapabilitiesSetBase.val.Set[i] = LinuxCapability(c)
}
if err := l.AssertValid(); err != nil {
return nil, err
}
return &l, nil
}
func (l LinuxCapabilitiesRevokeSet) AsIsolator() (*Isolator, error) {
b, err := json.Marshal(l.linuxCapabilitiesSetBase.val)
if err != nil {
return nil, err
}
rm := json.RawMessage(b)
return &Isolator{
Name: LinuxCapabilitiesRevokeSetName,
ValueRaw: &rm,
value: &l,
}, nil
}
type LinuxSeccompSet interface {
Set() []LinuxSeccompEntry
Errno() LinuxSeccompErrno
AssertValid() error
}
type LinuxSeccompEntry string
type LinuxSeccompErrno string
type linuxSeccompValue struct {
Set []LinuxSeccompEntry `json:"set"`
Errno LinuxSeccompErrno `json:"errno"`
}
type linuxSeccompBase struct {
val linuxSeccompValue
}
func (l linuxSeccompBase) multipleAllowed() bool {
return false
}
func (l linuxSeccompBase) AssertValid() error {
if len(l.val.Set) == 0 {
return errors.New("set must be non-empty")
}
if l.val.Errno == "" {
return nil
}
for i, c := range l.val.Errno {
if i == 0 && c != 'E' {
s := fmt.Sprintf("errno must start with an 'E' character, got %s", l.val.Errno)
return errors.New(s)
} else if !(unicode.IsUpper(c) || unicode.IsNumber(c)) {
s := fmt.Sprintf("errno can only contain upper case or numeric characters, got %s", l.val.Errno)
return errors.New(s)
}
}
return nil
}
func (l *linuxSeccompBase) UnmarshalJSON(b []byte) error {
var v linuxSeccompValue
err := json.Unmarshal(b, &v)
if err != nil {
return err
}
l.val = v
return nil
}
func (l linuxSeccompBase) Set() []LinuxSeccompEntry {
return l.val.Set
}
func (l linuxSeccompBase) Errno() LinuxSeccompErrno {
return l.val.Errno
}
type LinuxSeccompRetainSet struct {
linuxSeccompBase
}
func (l LinuxSeccompRetainSet) Conflicts() []ACIdentifier {
return []ACIdentifier{LinuxSeccompRemoveSetName}
}
func NewLinuxSeccompRetainSet(errno string, syscall ...string) (*LinuxSeccompRetainSet, error) {
l := LinuxSeccompRetainSet{
linuxSeccompBase{
linuxSeccompValue{
make([]LinuxSeccompEntry, len(syscall)),
LinuxSeccompErrno(errno),
},
},
}
for i, c := range syscall {
l.linuxSeccompBase.val.Set[i] = LinuxSeccompEntry(c)
}
if err := l.AssertValid(); err != nil {
return nil, err
}
return &l, nil
}
func (l LinuxSeccompRetainSet) AsIsolator() (*Isolator, error) {
b, err := json.Marshal(l.linuxSeccompBase.val)
if err != nil {
return nil, err
}
rm := json.RawMessage(b)
return &Isolator{
Name: LinuxSeccompRetainSetName,
ValueRaw: &rm,
value: &l,
}, nil
}
type LinuxSeccompRemoveSet struct {
linuxSeccompBase
}
func (l LinuxSeccompRemoveSet) Conflicts() []ACIdentifier {
return []ACIdentifier{LinuxSeccompRetainSetName}
}
func NewLinuxSeccompRemoveSet(errno string, syscall ...string) (*LinuxSeccompRemoveSet, error) {
l := LinuxSeccompRemoveSet{
linuxSeccompBase{
linuxSeccompValue{
make([]LinuxSeccompEntry, len(syscall)),
LinuxSeccompErrno(errno),
},
},
}
for i, c := range syscall {
l.linuxSeccompBase.val.Set[i] = LinuxSeccompEntry(c)
}
if err := l.AssertValid(); err != nil {
return nil, err
}
return &l, nil
}
func (l LinuxSeccompRemoveSet) AsIsolator() (*Isolator, error) {
b, err := json.Marshal(l.linuxSeccompBase.val)
if err != nil {
return nil, err
}
rm := json.RawMessage(b)
return &Isolator{
Name: LinuxSeccompRemoveSetName,
ValueRaw: &rm,
value: &l,
}, nil
}
// LinuxCPUShares assigns the CPU time share weight to the processes executed.
// See https://www.freedesktop.org/software/systemd/man/systemd.resource-control.html#CPUShares=weight,
// https://www.kernel.org/doc/Documentation/scheduler/sched-design-CFS.txt
type LinuxCPUShares int
func NewLinuxCPUShares(val int) (*LinuxCPUShares, error) {
l := LinuxCPUShares(val)
if err := l.AssertValid(); err != nil {
return nil, err
}
return &l, nil
}
func (l LinuxCPUShares) AssertValid() error {
if l < 2 || l > 262144 {
return fmt.Errorf("%s must be between 2 and 262144, got %d", LinuxCPUSharesName, l)
}
return nil
}
func (l LinuxCPUShares) multipleAllowed() bool {
return false
}
func (l LinuxCPUShares) Conflicts() []ACIdentifier {
return nil
}
func (l *LinuxCPUShares) UnmarshalJSON(b []byte) error {
var v int
err := json.Unmarshal(b, &v)
if err != nil {
return err
}
*l = LinuxCPUShares(v)
return nil
}
func (l LinuxCPUShares) AsIsolator() Isolator {
b, err := json.Marshal(l)
if err != nil {
panic(err)
}
rm := json.RawMessage(b)
return Isolator{
Name: LinuxCPUSharesName,
ValueRaw: &rm,
value: &l,
}
}
// LinuxOOMScoreAdj is equivalent to /proc/[pid]/oom_score_adj
type LinuxOOMScoreAdj int // -1000 to 1000
func NewLinuxOOMScoreAdj(val int) (*LinuxOOMScoreAdj, error) {
l := LinuxOOMScoreAdj(val)
if err := l.AssertValid(); err != nil {
return nil, err
}
return &l, nil
}
func (l LinuxOOMScoreAdj) AssertValid() error {
if l < -1000 || l > 1000 {
return fmt.Errorf("%s must be between -1000 and 1000, got %d", LinuxOOMScoreAdjName, l)
}
return nil
}
func (l LinuxOOMScoreAdj) multipleAllowed() bool {
return false
}
func (l LinuxOOMScoreAdj) Conflicts() []ACIdentifier {
return nil
}
func (l *LinuxOOMScoreAdj) UnmarshalJSON(b []byte) error {
var v int
err := json.Unmarshal(b, &v)
if err != nil {
return err
}
*l = LinuxOOMScoreAdj(v)
return nil
}
func (l LinuxOOMScoreAdj) AsIsolator() Isolator {
b, err := json.Marshal(l)
if err != nil {
panic(err)
}
rm := json.RawMessage(b)
return Isolator{
Name: LinuxOOMScoreAdjName,
ValueRaw: &rm,
value: &l,
}
}
type LinuxSELinuxUser string
type LinuxSELinuxRole string
type LinuxSELinuxType string
type LinuxSELinuxLevel string
type linuxSELinuxValue struct {
User LinuxSELinuxUser `json:"user"`
Role LinuxSELinuxRole `json:"role"`
Type LinuxSELinuxType `json:"type"`
Level LinuxSELinuxLevel `json:"level"`
}
type LinuxSELinuxContext struct {
val linuxSELinuxValue
}
func (l LinuxSELinuxContext) AssertValid() error {
if l.val.User == "" || strings.Contains(string(l.val.User), ":") {
return fmt.Errorf("invalid user value %q", l.val.User)
}
if l.val.Role == "" || strings.Contains(string(l.val.Role), ":") {
return fmt.Errorf("invalid role value %q", l.val.Role)
}
if l.val.Type == "" || strings.Contains(string(l.val.Type), ":") {
return fmt.Errorf("invalid type value %q", l.val.Type)
}
if l.val.Level == "" {
return fmt.Errorf("invalid level value %q", l.val.Level)
}
return nil
}
func (l *LinuxSELinuxContext) UnmarshalJSON(b []byte) error {
var v linuxSELinuxValue
err := json.Unmarshal(b, &v)
if err != nil {
return err
}
l.val = v
return nil
}
func (l LinuxSELinuxContext) User() LinuxSELinuxUser {
return l.val.User
}
func (l LinuxSELinuxContext) Role() LinuxSELinuxRole {
return l.val.Role
}
func (l LinuxSELinuxContext) Type() LinuxSELinuxType {
return l.val.Type
}
func (l LinuxSELinuxContext) Level() LinuxSELinuxLevel {
return l.val.Level
}
func (l LinuxSELinuxContext) multipleAllowed() bool {
return false
}
func (l LinuxSELinuxContext) Conflicts() []ACIdentifier {
return nil
}
func NewLinuxSELinuxContext(selinuxUser, selinuxRole, selinuxType, selinuxLevel string) (*LinuxSELinuxContext, error) {
l := LinuxSELinuxContext{
linuxSELinuxValue{
LinuxSELinuxUser(selinuxUser),
LinuxSELinuxRole(selinuxRole),
LinuxSELinuxType(selinuxType),
LinuxSELinuxLevel(selinuxLevel),
},
}
if err := l.AssertValid(); err != nil {
return nil, err
}
return &l, nil
}
func (l LinuxSELinuxContext) AsIsolator() (*Isolator, error) {
b, err := json.Marshal(l.val)
if err != nil {
return nil, err
}
rm := json.RawMessage(b)
return &Isolator{
Name: LinuxSELinuxContextName,
ValueRaw: &rm,
value: &l,
}, nil
}

View File

@@ -0,0 +1,245 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
"errors"
"fmt"
"github.com/appc/spec/schema/types/resource"
)
var (
ErrDefaultTrue = errors.New("default must be false")
ErrDefaultRequired = errors.New("default must be true")
ErrRequestNonEmpty = errors.New("request not supported by this resource, must be empty")
ResourceIsolatorNames = make(map[ACIdentifier]struct{})
)
const (
ResourceBlockBandwidthName = "resource/block-bandwidth"
ResourceBlockIOPSName = "resource/block-iops"
ResourceCPUName = "resource/cpu"
ResourceMemoryName = "resource/memory"
ResourceNetworkBandwidthName = "resource/network-bandwidth"
)
func init() {
for name, con := range map[ACIdentifier]IsolatorValueConstructor{
ResourceBlockBandwidthName: func() IsolatorValue { return &ResourceBlockBandwidth{} },
ResourceBlockIOPSName: func() IsolatorValue { return &ResourceBlockIOPS{} },
ResourceCPUName: func() IsolatorValue { return &ResourceCPU{} },
ResourceMemoryName: func() IsolatorValue { return &ResourceMemory{} },
ResourceNetworkBandwidthName: func() IsolatorValue { return &ResourceNetworkBandwidth{} },
} {
AddIsolatorName(name, ResourceIsolatorNames)
AddIsolatorValueConstructor(name, con)
}
}
type Resource interface {
Limit() *resource.Quantity
Request() *resource.Quantity
Default() bool
}
type ResourceBase struct {
val resourceValue
}
type resourceValue struct {
Default bool `json:"default"`
Request *resource.Quantity `json:"request"`
Limit *resource.Quantity `json:"limit"`
}
func (r ResourceBase) Limit() *resource.Quantity {
return r.val.Limit
}
func (r ResourceBase) Request() *resource.Quantity {
return r.val.Request
}
func (r ResourceBase) Default() bool {
return r.val.Default
}
func (r *ResourceBase) UnmarshalJSON(b []byte) error {
return json.Unmarshal(b, &r.val)
}
func (r ResourceBase) AssertValid() error {
return nil
}
// TODO(lucab): both need to be clarified in spec,
// see https://github.com/appc/spec/issues/625
func (l ResourceBase) multipleAllowed() bool {
return true
}
func (l ResourceBase) Conflicts() []ACIdentifier {
return nil
}
type ResourceBlockBandwidth struct {
ResourceBase
}
func (r ResourceBlockBandwidth) AssertValid() error {
if r.Default() != true {
return ErrDefaultRequired
}
if r.Request() != nil {
return ErrRequestNonEmpty
}
return nil
}
type ResourceBlockIOPS struct {
ResourceBase
}
func (r ResourceBlockIOPS) AssertValid() error {
if r.Default() != true {
return ErrDefaultRequired
}
if r.Request() != nil {
return ErrRequestNonEmpty
}
return nil
}
type ResourceCPU struct {
ResourceBase
}
func (r ResourceCPU) String() string {
return fmt.Sprintf("ResourceCPU(request=%s, limit=%s)", r.Request(), r.Limit())
}
func (r ResourceCPU) AssertValid() error {
if r.Default() != false {
return ErrDefaultTrue
}
return nil
}
func (r ResourceCPU) AsIsolator() Isolator {
isol := isolatorMap[ResourceCPUName]()
b, err := json.Marshal(r.val)
if err != nil {
panic(err)
}
valRaw := json.RawMessage(b)
return Isolator{
Name: ResourceCPUName,
ValueRaw: &valRaw,
value: isol,
}
}
func NewResourceCPUIsolator(request, limit string) (*ResourceCPU, error) {
req, err := resource.ParseQuantity(request)
if err != nil {
return nil, fmt.Errorf("error parsing request: %v", err)
}
lim, err := resource.ParseQuantity(limit)
if err != nil {
return nil, fmt.Errorf("error parsing limit: %v", err)
}
res := &ResourceCPU{
ResourceBase{
resourceValue{
Request: &req,
Limit: &lim,
},
},
}
if err := res.AssertValid(); err != nil {
// should never happen
return nil, err
}
return res, nil
}
type ResourceMemory struct {
ResourceBase
}
func (r ResourceMemory) String() string {
return fmt.Sprintf("ResourceMemory(request=%s, limit=%s)", r.Request(), r.Limit())
}
func (r ResourceMemory) AssertValid() error {
if r.Default() != false {
return ErrDefaultTrue
}
return nil
}
func (r ResourceMemory) AsIsolator() Isolator {
isol := isolatorMap[ResourceMemoryName]()
b, err := json.Marshal(r.val)
if err != nil {
panic(err)
}
valRaw := json.RawMessage(b)
return Isolator{
Name: ResourceMemoryName,
ValueRaw: &valRaw,
value: isol,
}
}
func NewResourceMemoryIsolator(request, limit string) (*ResourceMemory, error) {
req, err := resource.ParseQuantity(request)
if err != nil {
return nil, fmt.Errorf("error parsing request: %v", err)
}
lim, err := resource.ParseQuantity(limit)
if err != nil {
return nil, fmt.Errorf("error parsing limit: %v", err)
}
res := &ResourceMemory{
ResourceBase{
resourceValue{
Request: &req,
Limit: &lim,
},
},
}
if err := res.AssertValid(); err != nil {
// should never happen
return nil, err
}
return res, nil
}
type ResourceNetworkBandwidth struct {
ResourceBase
}
func (r ResourceNetworkBandwidth) AssertValid() error {
if r.Default() != true {
return ErrDefaultRequired
}
if r.Request() != nil {
return ErrRequestNonEmpty
}
return nil
}

View File

@@ -0,0 +1,83 @@
// Copyright 2016 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
)
var (
UnixIsolatorNames = make(map[ACIdentifier]struct{})
)
const (
//TODO(lucab): add "ulimit" isolators
UnixSysctlName = "os/unix/sysctl"
)
func init() {
for name, con := range map[ACIdentifier]IsolatorValueConstructor{
UnixSysctlName: func() IsolatorValue { return &UnixSysctl{} },
} {
AddIsolatorName(name, UnixIsolatorNames)
AddIsolatorValueConstructor(name, con)
}
}
type UnixSysctl map[string]string
func (s *UnixSysctl) UnmarshalJSON(b []byte) error {
var v map[string]string
err := json.Unmarshal(b, &v)
if err != nil {
return err
}
*s = UnixSysctl(v)
return err
}
func (s UnixSysctl) AssertValid() error {
return nil
}
func (s UnixSysctl) multipleAllowed() bool {
return false
}
func (s UnixSysctl) Conflicts() []ACIdentifier {
return nil
}
func (s UnixSysctl) AsIsolator() Isolator {
isol := isolatorMap[UnixSysctlName]()
b, err := json.Marshal(s)
if err != nil {
panic(err)
}
valRaw := json.RawMessage(b)
return Isolator{
Name: UnixSysctlName,
ValueRaw: &valRaw,
value: isol,
}
}
func NewUnixSysctlIsolator(cfg map[string]string) (*UnixSysctl, error) {
s := UnixSysctl(cfg)
if err := s.AssertValid(); err != nil {
return nil, err
}
return &s, nil
}

211
vendor/github.com/appc/spec/schema/types/labels.go generated vendored Normal file
View File

@@ -0,0 +1,211 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
"fmt"
"sort"
)
var ValidOSArch = map[string][]string{
"linux": {"amd64", "i386", "aarch64", "aarch64_be", "armv6l", "armv7l", "armv7b", "ppc64", "ppc64le", "s390x"},
"freebsd": {"amd64", "i386", "arm"},
"darwin": {"x86_64", "i386"},
}
type Labels []Label
type labelsSlice Labels
func (l labelsSlice) Len() int { return len(l) }
func (l labelsSlice) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
func (l labelsSlice) Less(i, j int) bool { return l[i].Name < l[j].Name }
type Label struct {
Name ACIdentifier `json:"name"`
Value string `json:"value"`
}
// {appc,go}ArchTuple are internal helper types used to translate arch tuple between go and appc
type appcArchTuple struct {
appcOs string
appcArch string
}
type goArchTuple struct {
goOs string
goArch string
goArchFlavor string
}
// IsValidOsArch checks if a OS-architecture combination is valid given a map
// of valid OS-architectures
func IsValidOSArch(labels map[ACIdentifier]string, validOSArch map[string][]string) error {
if os, ok := labels["os"]; ok {
if validArchs, ok := validOSArch[os]; !ok {
// Not a whitelisted OS. TODO: how to warn rather than fail?
validOses := make([]string, 0, len(validOSArch))
for validOs := range validOSArch {
validOses = append(validOses, validOs)
}
sort.Strings(validOses)
return fmt.Errorf(`bad os %#v (must be one of: %v)`, os, validOses)
} else {
// Whitelisted OS. We check arch here, as arch makes sense only
// when os is defined.
if arch, ok := labels["arch"]; ok {
found := false
for _, validArch := range validArchs {
if arch == validArch {
found = true
break
}
}
if !found {
return fmt.Errorf(`bad arch %#v for %v (must be one of: %v)`, arch, os, validArchs)
}
}
}
}
return nil
}
func (l Labels) assertValid() error {
seen := map[ACIdentifier]string{}
for _, lbl := range l {
if lbl.Name == "name" {
return fmt.Errorf(`invalid label name: "name"`)
}
_, ok := seen[lbl.Name]
if ok {
return fmt.Errorf(`duplicate labels of name %q`, lbl.Name)
}
seen[lbl.Name] = lbl.Value
}
return IsValidOSArch(seen, ValidOSArch)
}
func (l Labels) MarshalJSON() ([]byte, error) {
if err := l.assertValid(); err != nil {
return nil, err
}
return json.Marshal(labelsSlice(l))
}
func (l *Labels) UnmarshalJSON(data []byte) error {
var jl labelsSlice
if err := json.Unmarshal(data, &jl); err != nil {
return err
}
nl := Labels(jl)
if err := nl.assertValid(); err != nil {
return err
}
*l = nl
return nil
}
// Get retrieves the value of the label by the given name from Labels, if it exists
func (l Labels) Get(name string) (val string, ok bool) {
for _, lbl := range l {
if lbl.Name.String() == name {
return lbl.Value, true
}
}
return "", false
}
// ToMap creates a map[ACIdentifier]string.
func (l Labels) ToMap() map[ACIdentifier]string {
labelsMap := make(map[ACIdentifier]string)
for _, lbl := range l {
labelsMap[lbl.Name] = lbl.Value
}
return labelsMap
}
// LabelsFromMap creates Labels from a map[ACIdentifier]string
func LabelsFromMap(labelsMap map[ACIdentifier]string) (Labels, error) {
labels := Labels{}
for n, v := range labelsMap {
labels = append(labels, Label{Name: n, Value: v})
}
if err := labels.assertValid(); err != nil {
return nil, err
}
sort.Sort(labelsSlice(labels))
return labels, nil
}
// ToAppcOSArch translates a Golang arch tuple (OS, architecture, flavor) into
// an appc arch tuple (OS, architecture)
func ToAppcOSArch(goOs string, goArch string, goArchFlavor string) (appcOs string, appcArch string, e error) {
tabularAppcToGo := map[goArchTuple]appcArchTuple{
{"linux", "amd64", ""}: {"linux", "amd64"},
{"linux", "386", ""}: {"linux", "i386"},
{"linux", "arm64", ""}: {"linux", "aarch64"},
{"linux", "arm", ""}: {"linux", "armv6l"},
{"linux", "arm", "6"}: {"linux", "armv6l"},
{"linux", "arm", "7"}: {"linux", "armv7l"},
{"linux", "ppc64", ""}: {"linux", "ppc64"},
{"linux", "ppc64le", ""}: {"linux", "ppc64le"},
{"linux", "s390x", ""}: {"linux", "s390x"},
{"freebsd", "amd64", ""}: {"freebsd", "amd64"},
{"freebsd", "386", ""}: {"freebsd", "i386"},
{"freebsd", "arm", ""}: {"freebsd", "arm"},
{"freebsd", "arm", "5"}: {"freebsd", "arm"},
{"freebsd", "arm", "6"}: {"freebsd", "arm"},
{"freebsd", "arm", "7"}: {"freebsd", "arm"},
{"darwin", "amd64", ""}: {"darwin", "x86_64"},
{"darwin", "386", ""}: {"darwin", "i386"},
}
archTuple, ok := tabularAppcToGo[goArchTuple{goOs, goArch, goArchFlavor}]
if !ok {
return "", "", fmt.Errorf("unknown arch tuple: %q - %q - %q", goOs, goArch, goArchFlavor)
}
return archTuple.appcOs, archTuple.appcArch, nil
}
// ToGoOSArch translates an appc arch tuple (OS, architecture) into
// a Golang arch tuple (OS, architecture, flavor)
func ToGoOSArch(appcOs string, appcArch string) (goOs string, goArch string, goArchFlavor string, e error) {
tabularGoToAppc := map[appcArchTuple]goArchTuple{
// {"linux", "aarch64_be"}: nil,
// {"linux", "armv7b"}: nil,
{"linux", "aarch64"}: {"linux", "arm64", ""},
{"linux", "amd64"}: {"linux", "amd64", ""},
{"linux", "armv6l"}: {"linux", "arm", "6"},
{"linux", "armv7l"}: {"linux", "arm", "7"},
{"linux", "i386"}: {"linux", "386", ""},
{"linux", "ppc64"}: {"linux", "ppc64", ""},
{"linux", "ppc64le"}: {"linux", "ppc64le", ""},
{"linux", "s390x"}: {"linux", "s390x", ""},
{"freebsd", "amd64"}: {"freebsd", "amd64", ""},
{"freebsd", "arm"}: {"freebsd", "arm", "6"},
{"freebsd", "386"}: {"freebsd", "i386", ""},
{"darwin", "amd64"}: {"darwin", "x86_64", ""},
{"darwin", "386"}: {"darwin", "i386", ""},
}
archTuple, ok := tabularGoToAppc[appcArchTuple{appcOs, appcArch}]
if !ok {
return "", "", "", fmt.Errorf("unknown arch tuple: %q - %q", appcOs, appcArch)
}
return archTuple.goOs, archTuple.goArch, archTuple.goArchFlavor, nil
}

92
vendor/github.com/appc/spec/schema/types/mountpoint.go generated vendored Normal file
View File

@@ -0,0 +1,92 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"errors"
"fmt"
"net/url"
"strconv"
"github.com/appc/spec/schema/common"
)
// MountPoint is the application-side manifestation of a Volume.
type MountPoint struct {
Name ACName `json:"name"`
Path string `json:"path"`
ReadOnly bool `json:"readOnly,omitempty"`
}
func (mount MountPoint) assertValid() error {
if mount.Name.Empty() {
return errors.New("name must be set")
}
if len(mount.Path) == 0 {
return errors.New("path must be set")
}
return nil
}
// MountPointFromString takes a command line mountpoint parameter and returns a mountpoint
//
// It is useful for actool patch-manifest --mounts
//
// Example mountpoint parameters:
// database,path=/tmp,readOnly=true
func MountPointFromString(mp string) (*MountPoint, error) {
var mount MountPoint
mp = "name=" + mp
mpQuery, err := common.MakeQueryString(mp)
if err != nil {
return nil, err
}
v, err := url.ParseQuery(mpQuery)
if err != nil {
return nil, err
}
for key, val := range v {
if len(val) > 1 {
return nil, fmt.Errorf("label %s with multiple values %q", key, val)
}
switch key {
case "name":
acn, err := NewACName(val[0])
if err != nil {
return nil, err
}
mount.Name = *acn
case "path":
mount.Path = val[0]
case "readOnly":
ro, err := strconv.ParseBool(val[0])
if err != nil {
return nil, err
}
mount.ReadOnly = ro
default:
return nil, fmt.Errorf("unknown mountpoint parameter %q", key)
}
}
err = mount.assertValid()
if err != nil {
return nil, err
}
return &mount, nil
}

147
vendor/github.com/appc/spec/schema/types/port.go generated vendored Normal file
View File

@@ -0,0 +1,147 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
"errors"
"fmt"
"net"
"net/url"
"strconv"
"github.com/appc/spec/schema/common"
)
// Port represents a port as offered by an application *inside*
// the pod.
type Port struct {
Name ACName `json:"name"`
Protocol string `json:"protocol"`
Port uint `json:"port"`
Count uint `json:"count"`
SocketActivated bool `json:"socketActivated"`
}
// ExposedPort represents a port listening on the host side.
// The PodPort is optional -- if missing, then try and find the pod-side
// information by matching names
type ExposedPort struct {
Name ACName `json:"name"`
HostPort uint `json:"hostPort"`
HostIP net.IP `json:"hostIP,omitempty"` // optional
PodPort *Port `json:"podPort,omitempty"` // optional. If missing, try and find a corresponding App's port
}
type port Port
func (p *Port) UnmarshalJSON(data []byte) error {
var pp port
if err := json.Unmarshal(data, &pp); err != nil {
return err
}
np := Port(pp)
if err := np.assertValid(); err != nil {
return err
}
if np.Count == 0 {
np.Count = 1
}
*p = np
return nil
}
func (p Port) MarshalJSON() ([]byte, error) {
if err := p.assertValid(); err != nil {
return nil, err
}
return json.Marshal(port(p))
}
func (p Port) assertValid() error {
// Although there are no guarantees, most (if not all)
// transport protocols use 16 bit ports
if p.Port > 65535 || p.Port < 1 {
return errors.New("port must be in 1-65535 range")
}
if p.Port+p.Count > 65536 {
return errors.New("end of port range must be in 1-65535 range")
}
return nil
}
// PortFromString takes a command line port parameter and returns a port
//
// It is useful for actool patch-manifest --ports
//
// Example port parameters:
// health-check,protocol=udp,port=8000
// query,protocol=tcp,port=8080,count=1,socketActivated=true
func PortFromString(pt string) (*Port, error) {
var port Port
pt = "name=" + pt
ptQuery, err := common.MakeQueryString(pt)
if err != nil {
return nil, err
}
v, err := url.ParseQuery(ptQuery)
if err != nil {
return nil, err
}
for key, val := range v {
if len(val) > 1 {
return nil, fmt.Errorf("label %s with multiple values %q", key, val)
}
switch key {
case "name":
acn, err := NewACName(val[0])
if err != nil {
return nil, err
}
port.Name = *acn
case "protocol":
port.Protocol = val[0]
case "port":
p, err := strconv.ParseUint(val[0], 10, 16)
if err != nil {
return nil, err
}
port.Port = uint(p)
case "count":
cnt, err := strconv.ParseUint(val[0], 10, 16)
if err != nil {
return nil, err
}
port.Count = uint(cnt)
case "socketActivated":
sa, err := strconv.ParseBool(val[0])
if err != nil {
return nil, err
}
port.SocketActivated = sa
default:
return nil, fmt.Errorf("unknown port parameter %q", key)
}
}
err = port.assertValid()
if err != nil {
return nil, err
}
return &port, nil
}

View File

@@ -0,0 +1,4 @@
This package was copied in from the Kubernetes repo to avoid a cyclic
dependency. These files were taken from master from
github.com/kubernetes/kubernetes at commit hash
b0deb2eb8f4037421077f77cb163dbb4c0a2a9f5.

View File

@@ -0,0 +1,298 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resource
import (
"math/big"
"strconv"
inf "gopkg.in/inf.v0"
)
// Scale is used for getting and setting the base-10 scaled value.
// Base-2 scales are omitted for mathematical simplicity.
// See Quantity.ScaledValue for more details.
type Scale int32
// infScale adapts a Scale value to an inf.Scale value.
func (s Scale) infScale() inf.Scale {
return inf.Scale(-s) // inf.Scale is upside-down
}
const (
Nano Scale = -9
Micro Scale = -6
Milli Scale = -3
Kilo Scale = 3
Mega Scale = 6
Giga Scale = 9
Tera Scale = 12
Peta Scale = 15
Exa Scale = 18
)
var (
Zero = int64Amount{}
// Used by quantity strings - treat as read only
zeroBytes = []byte("0")
)
// int64Amount represents a fixed precision numerator and arbitrary scale exponent. It is faster
// than operations on inf.Dec for values that can be represented as int64.
type int64Amount struct {
value int64
scale Scale
}
// Sign returns 0 if the value is zero, -1 if it is less than 0, or 1 if it is greater than 0.
func (a int64Amount) Sign() int {
switch {
case a.value == 0:
return 0
case a.value > 0:
return 1
default:
return -1
}
}
// AsInt64 returns the current amount as an int64 at scale 0, or false if the value cannot be
// represented in an int64 OR would result in a loss of precision. This method is intended as
// an optimization to avoid calling AsDec.
func (a int64Amount) AsInt64() (int64, bool) {
if a.scale == 0 {
return a.value, true
}
if a.scale < 0 {
// TODO: attempt to reduce factors, although it is assumed that factors are reduced prior
// to the int64Amount being created.
return 0, false
}
return positiveScaleInt64(a.value, a.scale)
}
// AsScaledInt64 returns an int64 representing the value of this amount at the specified scale,
// rounding up, or false if that would result in overflow. (1e20).AsScaledInt64(1) would result
// in overflow because 1e19 is not representable as an int64. Note that setting a scale larger
// than the current value may result in loss of precision - i.e. (1e-6).AsScaledInt64(0) would
// return 1, because 0.000001 is rounded up to 1.
func (a int64Amount) AsScaledInt64(scale Scale) (result int64, ok bool) {
if a.scale < scale {
result, _ = negativeScaleInt64(a.value, scale-a.scale)
return result, true
}
return positiveScaleInt64(a.value, a.scale-scale)
}
// AsDec returns an inf.Dec representation of this value.
func (a int64Amount) AsDec() *inf.Dec {
var base inf.Dec
base.SetUnscaled(a.value)
base.SetScale(inf.Scale(-a.scale))
return &base
}
// Cmp returns 0 if a and b are equal, 1 if a is greater than b, or -1 if a is less than b.
func (a int64Amount) Cmp(b int64Amount) int {
switch {
case a.scale == b.scale:
// compare only the unscaled portion
case a.scale > b.scale:
result, remainder, exact := divideByScaleInt64(b.value, a.scale-b.scale)
if !exact {
return a.AsDec().Cmp(b.AsDec())
}
if result == a.value {
switch {
case remainder == 0:
return 0
case remainder > 0:
return -1
default:
return 1
}
}
b.value = result
default:
result, remainder, exact := divideByScaleInt64(a.value, b.scale-a.scale)
if !exact {
return a.AsDec().Cmp(b.AsDec())
}
if result == b.value {
switch {
case remainder == 0:
return 0
case remainder > 0:
return 1
default:
return -1
}
}
a.value = result
}
switch {
case a.value == b.value:
return 0
case a.value < b.value:
return -1
default:
return 1
}
}
// Add adds two int64Amounts together, matching scales. It will return false and not mutate
// a if overflow or underflow would result.
func (a *int64Amount) Add(b int64Amount) bool {
switch {
case b.value == 0:
return true
case a.value == 0:
a.value = b.value
a.scale = b.scale
return true
case a.scale == b.scale:
c, ok := int64Add(a.value, b.value)
if !ok {
return false
}
a.value = c
case a.scale > b.scale:
c, ok := positiveScaleInt64(a.value, a.scale-b.scale)
if !ok {
return false
}
c, ok = int64Add(c, b.value)
if !ok {
return false
}
a.scale = b.scale
a.value = c
default:
c, ok := positiveScaleInt64(b.value, b.scale-a.scale)
if !ok {
return false
}
c, ok = int64Add(a.value, c)
if !ok {
return false
}
a.value = c
}
return true
}
// Sub removes the value of b from the current amount, or returns false if underflow would result.
func (a *int64Amount) Sub(b int64Amount) bool {
return a.Add(int64Amount{value: -b.value, scale: b.scale})
}
// AsScale adjusts this amount to set a minimum scale, rounding up, and returns true iff no precision
// was lost. (1.1e5).AsScale(5) would return 1.1e5, but (1.1e5).AsScale(6) would return 1e6.
func (a int64Amount) AsScale(scale Scale) (int64Amount, bool) {
if a.scale >= scale {
return a, true
}
result, exact := negativeScaleInt64(a.value, scale-a.scale)
return int64Amount{value: result, scale: scale}, exact
}
// AsCanonicalBytes accepts a buffer to write the base-10 string value of this field to, and returns
// either that buffer or a larger buffer and the current exponent of the value. The value is adjusted
// until the exponent is a multiple of 3 - i.e. 1.1e5 would return "110", 3.
func (a int64Amount) AsCanonicalBytes(out []byte) (result []byte, exponent int32) {
mantissa := a.value
exponent = int32(a.scale)
amount, times := removeInt64Factors(mantissa, 10)
exponent += int32(times)
// make sure exponent is a multiple of 3
var ok bool
switch exponent % 3 {
case 1, -2:
amount, ok = int64MultiplyScale10(amount)
if !ok {
return infDecAmount{a.AsDec()}.AsCanonicalBytes(out)
}
exponent = exponent - 1
case 2, -1:
amount, ok = int64MultiplyScale100(amount)
if !ok {
return infDecAmount{a.AsDec()}.AsCanonicalBytes(out)
}
exponent = exponent - 2
}
return strconv.AppendInt(out, amount, 10), exponent
}
// AsCanonicalBase1024Bytes accepts a buffer to write the base-1024 string value of this field to, and returns
// either that buffer or a larger buffer and the current exponent of the value. 2048 is 2 * 1024 ^ 1 and would
// return []byte("2048"), 1.
func (a int64Amount) AsCanonicalBase1024Bytes(out []byte) (result []byte, exponent int32) {
value, ok := a.AsScaledInt64(0)
if !ok {
return infDecAmount{a.AsDec()}.AsCanonicalBase1024Bytes(out)
}
amount, exponent := removeInt64Factors(value, 1024)
return strconv.AppendInt(out, amount, 10), exponent
}
// infDecAmount implements common operations over an inf.Dec that are specific to the quantity
// representation.
type infDecAmount struct {
*inf.Dec
}
// AsScale adjusts this amount to set a minimum scale, rounding up, and returns true iff no precision
// was lost. (1.1e5).AsScale(5) would return 1.1e5, but (1.1e5).AsScale(6) would return 1e6.
func (a infDecAmount) AsScale(scale Scale) (infDecAmount, bool) {
tmp := &inf.Dec{}
tmp.Round(a.Dec, scale.infScale(), inf.RoundUp)
return infDecAmount{tmp}, tmp.Cmp(a.Dec) == 0
}
// AsCanonicalBytes accepts a buffer to write the base-10 string value of this field to, and returns
// either that buffer or a larger buffer and the current exponent of the value. The value is adjusted
// until the exponent is a multiple of 3 - i.e. 1.1e5 would return "110", 3.
func (a infDecAmount) AsCanonicalBytes(out []byte) (result []byte, exponent int32) {
mantissa := a.Dec.UnscaledBig()
exponent = int32(-a.Dec.Scale())
amount := big.NewInt(0).Set(mantissa)
// move all factors of 10 into the exponent for easy reasoning
amount, times := removeBigIntFactors(amount, bigTen)
exponent += times
// make sure exponent is a multiple of 3
for exponent%3 != 0 {
amount.Mul(amount, bigTen)
exponent--
}
return append(out, amount.String()...), exponent
}
// AsCanonicalBase1024Bytes accepts a buffer to write the base-1024 string value of this field to, and returns
// either that buffer or a larger buffer and the current exponent of the value. 2048 is 2 * 1024 ^ 1 and would
// return []byte("2048"), 1.
func (a infDecAmount) AsCanonicalBase1024Bytes(out []byte) (result []byte, exponent int32) {
tmp := &inf.Dec{}
tmp.Round(a.Dec, 0, inf.RoundUp)
amount, exponent := removeBigIntFactors(tmp.UnscaledBig(), big1024)
return append(out, amount.String()...), exponent
}

View File

@@ -0,0 +1,327 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resource
import (
"math/big"
inf "gopkg.in/inf.v0"
)
const (
// maxInt64Factors is the highest value that will be checked when removing factors of 10 from an int64.
// It is also the maximum decimal digits that can be represented with an int64.
maxInt64Factors = 18
)
var (
// Commonly needed big.Int values-- treat as read only!
bigTen = big.NewInt(10)
bigZero = big.NewInt(0)
bigOne = big.NewInt(1)
bigThousand = big.NewInt(1000)
big1024 = big.NewInt(1024)
// Commonly needed inf.Dec values-- treat as read only!
decZero = inf.NewDec(0, 0)
decOne = inf.NewDec(1, 0)
decMinusOne = inf.NewDec(-1, 0)
decThousand = inf.NewDec(1000, 0)
dec1024 = inf.NewDec(1024, 0)
decMinus1024 = inf.NewDec(-1024, 0)
// Largest (in magnitude) number allowed.
maxAllowed = infDecAmount{inf.NewDec((1<<63)-1, 0)} // == max int64
// The maximum value we can represent milli-units for.
// Compare with the return value of Quantity.Value() to
// see if it's safe to use Quantity.MilliValue().
MaxMilliValue = int64(((1 << 63) - 1) / 1000)
)
const mostNegative = -(mostPositive + 1)
const mostPositive = 1<<63 - 1
// int64Add returns a+b, or false if that would overflow int64.
func int64Add(a, b int64) (int64, bool) {
c := a + b
switch {
case a > 0 && b > 0:
if c < 0 {
return 0, false
}
case a < 0 && b < 0:
if c > 0 {
return 0, false
}
if a == mostNegative && b == mostNegative {
return 0, false
}
}
return c, true
}
// int64Multiply returns a*b, or false if that would overflow or underflow int64.
func int64Multiply(a, b int64) (int64, bool) {
if a == 0 || b == 0 || a == 1 || b == 1 {
return a * b, true
}
if a == mostNegative || b == mostNegative {
return 0, false
}
c := a * b
return c, c/b == a
}
// int64MultiplyScale returns a*b, assuming b is greater than one, or false if that would overflow or underflow int64.
// Use when b is known to be greater than one.
func int64MultiplyScale(a int64, b int64) (int64, bool) {
if a == 0 || a == 1 {
return a * b, true
}
if a == mostNegative && b != 1 {
return 0, false
}
c := a * b
return c, c/b == a
}
// int64MultiplyScale10 multiplies a by 10, or returns false if that would overflow. This method is faster than
// int64Multiply(a, 10) because the compiler can optimize constant factor multiplication.
func int64MultiplyScale10(a int64) (int64, bool) {
if a == 0 || a == 1 {
return a * 10, true
}
if a == mostNegative {
return 0, false
}
c := a * 10
return c, c/10 == a
}
// int64MultiplyScale100 multiplies a by 100, or returns false if that would overflow. This method is faster than
// int64Multiply(a, 100) because the compiler can optimize constant factor multiplication.
func int64MultiplyScale100(a int64) (int64, bool) {
if a == 0 || a == 1 {
return a * 100, true
}
if a == mostNegative {
return 0, false
}
c := a * 100
return c, c/100 == a
}
// int64MultiplyScale1000 multiplies a by 1000, or returns false if that would overflow. This method is faster than
// int64Multiply(a, 1000) because the compiler can optimize constant factor multiplication.
func int64MultiplyScale1000(a int64) (int64, bool) {
if a == 0 || a == 1 {
return a * 1000, true
}
if a == mostNegative {
return 0, false
}
c := a * 1000
return c, c/1000 == a
}
// positiveScaleInt64 multiplies base by 10^scale, returning false if the
// value overflows. Passing a negative scale is undefined.
func positiveScaleInt64(base int64, scale Scale) (int64, bool) {
switch scale {
case 0:
return base, true
case 1:
return int64MultiplyScale10(base)
case 2:
return int64MultiplyScale100(base)
case 3:
return int64MultiplyScale1000(base)
case 6:
return int64MultiplyScale(base, 1000000)
case 9:
return int64MultiplyScale(base, 1000000000)
default:
value := base
var ok bool
for i := Scale(0); i < scale; i++ {
if value, ok = int64MultiplyScale(value, 10); !ok {
return 0, false
}
}
return value, true
}
}
// negativeScaleInt64 reduces base by the provided scale, rounding up, until the
// value is zero or the scale is reached. Passing a negative scale is undefined.
// The value returned, if not exact, is rounded away from zero.
func negativeScaleInt64(base int64, scale Scale) (result int64, exact bool) {
if scale == 0 {
return base, true
}
value := base
var fraction bool
for i := Scale(0); i < scale; i++ {
if !fraction && value%10 != 0 {
fraction = true
}
value = value / 10
if value == 0 {
if fraction {
if base > 0 {
return 1, false
}
return -1, false
}
return 0, true
}
}
if fraction {
if base > 0 {
value += 1
} else {
value += -1
}
}
return value, !fraction
}
func pow10Int64(b int64) int64 {
switch b {
case 0:
return 1
case 1:
return 10
case 2:
return 100
case 3:
return 1000
case 4:
return 10000
case 5:
return 100000
case 6:
return 1000000
case 7:
return 10000000
case 8:
return 100000000
case 9:
return 1000000000
case 10:
return 10000000000
case 11:
return 100000000000
case 12:
return 1000000000000
case 13:
return 10000000000000
case 14:
return 100000000000000
case 15:
return 1000000000000000
case 16:
return 10000000000000000
case 17:
return 100000000000000000
case 18:
return 1000000000000000000
default:
return 0
}
}
// powInt64 raises a to the bth power. Is not overflow aware.
func powInt64(a, b int64) int64 {
p := int64(1)
for b > 0 {
if b&1 != 0 {
p *= a
}
b >>= 1
a *= a
}
return p
}
// negativeScaleInt64 returns the result of dividing base by scale * 10 and the remainder, or
// false if no such division is possible. Dividing by negative scales is undefined.
func divideByScaleInt64(base int64, scale Scale) (result, remainder int64, exact bool) {
if scale == 0 {
return base, 0, true
}
// the max scale representable in base 10 in an int64 is 18 decimal places
if scale >= 18 {
return 0, base, false
}
divisor := pow10Int64(int64(scale))
return base / divisor, base % divisor, true
}
// removeInt64Factors divides in a loop; the return values have the property that
// value == result * base ^ scale
func removeInt64Factors(value int64, base int64) (result int64, times int32) {
times = 0
result = value
negative := result < 0
if negative {
result = -result
}
switch base {
// allow the compiler to optimize the common cases
case 10:
for result >= 10 && result%10 == 0 {
times++
result = result / 10
}
// allow the compiler to optimize the common cases
case 1024:
for result >= 1024 && result%1024 == 0 {
times++
result = result / 1024
}
default:
for result >= base && result%base == 0 {
times++
result = result / base
}
}
if negative {
result = -result
}
return result, times
}
// removeBigIntFactors divides in a loop; the return values have the property that
// d == result * factor ^ times
// d may be modified in place.
// If d == 0, then the return values will be (0, 0)
func removeBigIntFactors(d, factor *big.Int) (result *big.Int, times int32) {
q := big.NewInt(0)
m := big.NewInt(0)
for d.Cmp(bigZero) != 0 {
q.DivMod(d, factor, m)
if m.Cmp(bigZero) != 0 {
break
}
times++
d, q = q, d
}
return d, times
}

View File

@@ -0,0 +1,768 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resource
import (
"bytes"
"errors"
"fmt"
"math/big"
"regexp"
"strconv"
"strings"
flag "github.com/spf13/pflag"
inf "gopkg.in/inf.v0"
)
// Quantity is a fixed-point representation of a number.
// It provides convenient marshaling/unmarshaling in JSON and YAML,
// in addition to String() and Int64() accessors.
//
// The serialization format is:
//
// <quantity> ::= <signedNumber><suffix>
// (Note that <suffix> may be empty, from the "" case in <decimalSI>.)
// <digit> ::= 0 | 1 | ... | 9
// <digits> ::= <digit> | <digit><digits>
// <number> ::= <digits> | <digits>.<digits> | <digits>. | .<digits>
// <sign> ::= "+" | "-"
// <signedNumber> ::= <number> | <sign><number>
// <suffix> ::= <binarySI> | <decimalExponent> | <decimalSI>
// <binarySI> ::= Ki | Mi | Gi | Ti | Pi | Ei
// (International System of units; See: http://physics.nist.gov/cuu/Units/binary.html)
// <decimalSI> ::= m | "" | k | M | G | T | P | E
// (Note that 1024 = 1Ki but 1000 = 1k; I didn't choose the capitalization.)
// <decimalExponent> ::= "e" <signedNumber> | "E" <signedNumber>
//
// No matter which of the three exponent forms is used, no quantity may represent
// a number greater than 2^63-1 in magnitude, nor may it have more than 3 decimal
// places. Numbers larger or more precise will be capped or rounded up.
// (E.g.: 0.1m will rounded up to 1m.)
// This may be extended in the future if we require larger or smaller quantities.
//
// When a Quantity is parsed from a string, it will remember the type of suffix
// it had, and will use the same type again when it is serialized.
//
// Before serializing, Quantity will be put in "canonical form".
// This means that Exponent/suffix will be adjusted up or down (with a
// corresponding increase or decrease in Mantissa) such that:
// a. No precision is lost
// b. No fractional digits will be emitted
// c. The exponent (or suffix) is as large as possible.
// The sign will be omitted unless the number is negative.
//
// Examples:
// 1.5 will be serialized as "1500m"
// 1.5Gi will be serialized as "1536Mi"
//
// NOTE: We reserve the right to amend this canonical format, perhaps to
// allow 1.5 to be canonical.
// TODO: Remove above disclaimer after all bikeshedding about format is over,
// or after March 2015.
//
// Note that the quantity will NEVER be internally represented by a
// floating point number. That is the whole point of this exercise.
//
// Non-canonical values will still parse as long as they are well formed,
// but will be re-emitted in their canonical form. (So always use canonical
// form, or don't diff.)
//
// This format is intended to make it difficult to use these numbers without
// writing some sort of special handling code in the hopes that that will
// cause implementors to also use a fixed point implementation.
//
// +gencopy=false
// +protobuf=true
// +protobuf.embed=string
// +protobuf.options.marshal=false
// +protobuf.options.(gogoproto.goproto_stringer)=false
type Quantity struct {
// i is the quantity in int64 scaled form, if d.Dec == nil
i int64Amount
// d is the quantity in inf.Dec form if d.Dec != nil
d infDecAmount
// s is the generated value of this quantity to avoid recalculation
s string
// Change Format at will. See the comment for Canonicalize for
// more details.
Format
}
// CanonicalValue allows a quantity amount to be converted to a string.
type CanonicalValue interface {
// AsCanonicalBytes returns a byte array representing the string representation
// of the value mantissa and an int32 representing its exponent in base-10. Callers may
// pass a byte slice to the method to avoid allocations.
AsCanonicalBytes(out []byte) ([]byte, int32)
// AsCanonicalBase1024Bytes returns a byte array representing the string representation
// of the value mantissa and an int32 representing its exponent in base-1024. Callers
// may pass a byte slice to the method to avoid allocations.
AsCanonicalBase1024Bytes(out []byte) ([]byte, int32)
}
// Format lists the three possible formattings of a quantity.
type Format string
const (
DecimalExponent = Format("DecimalExponent") // e.g., 12e6
BinarySI = Format("BinarySI") // e.g., 12Mi (12 * 2^20)
DecimalSI = Format("DecimalSI") // e.g., 12M (12 * 10^6)
)
// MustParse turns the given string into a quantity or panics; for tests
// or others cases where you know the string is valid.
func MustParse(str string) Quantity {
q, err := ParseQuantity(str)
if err != nil {
panic(fmt.Errorf("cannot parse '%v': %v", str, err))
}
return q
}
const (
// splitREString is used to separate a number from its suffix; as such,
// this is overly permissive, but that's OK-- it will be checked later.
splitREString = "^([+-]?[0-9.]+)([eEinumkKMGTP]*[-+]?[0-9]*)$"
)
var (
// splitRE is used to get the various parts of a number.
splitRE = regexp.MustCompile(splitREString)
// Errors that could happen while parsing a string.
ErrFormatWrong = errors.New("quantities must match the regular expression '" + splitREString + "'")
ErrNumeric = errors.New("unable to parse numeric part of quantity")
ErrSuffix = errors.New("unable to parse quantity's suffix")
)
// parseQuantityString is a fast scanner for quantity values.
func parseQuantityString(str string) (positive bool, value, num, denom, suffix string, err error) {
positive = true
pos := 0
end := len(str)
// handle leading sign
if pos < end {
switch str[0] {
case '-':
positive = false
pos++
case '+':
pos++
}
}
// strip leading zeros
Zeroes:
for i := pos; ; i++ {
if i >= end {
num = "0"
value = num
return
}
switch str[i] {
case '0':
pos++
default:
break Zeroes
}
}
// extract the numerator
Num:
for i := pos; ; i++ {
if i >= end {
num = str[pos:end]
value = str[0:end]
return
}
switch str[i] {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
default:
num = str[pos:i]
pos = i
break Num
}
}
// if we stripped all numerator positions, always return 0
if len(num) == 0 {
num = "0"
}
// handle a denominator
if pos < end && str[pos] == '.' {
pos++
Denom:
for i := pos; ; i++ {
if i >= end {
denom = str[pos:end]
value = str[0:end]
return
}
switch str[i] {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
default:
denom = str[pos:i]
pos = i
break Denom
}
}
// TODO: we currently allow 1.G, but we may not want to in the future.
// if len(denom) == 0 {
// err = ErrFormatWrong
// return
// }
}
value = str[0:pos]
// grab the elements of the suffix
suffixStart := pos
for i := pos; ; i++ {
if i >= end {
suffix = str[suffixStart:end]
return
}
if !strings.ContainsAny(str[i:i+1], "eEinumkKMGTP") {
pos = i
break
}
}
if pos < end {
switch str[pos] {
case '-', '+':
pos++
}
}
Suffix:
for i := pos; ; i++ {
if i >= end {
suffix = str[suffixStart:end]
return
}
switch str[i] {
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
default:
break Suffix
}
}
// we encountered a non decimal in the Suffix loop, but the last character
// was not a valid exponent
err = ErrFormatWrong
return
}
// ParseQuantity turns str into a Quantity, or returns an error.
func ParseQuantity(str string) (Quantity, error) {
if len(str) == 0 {
return Quantity{}, ErrFormatWrong
}
if str == "0" {
return Quantity{Format: DecimalSI, s: str}, nil
}
positive, value, num, denom, suf, err := parseQuantityString(str)
if err != nil {
return Quantity{}, err
}
base, exponent, format, ok := quantitySuffixer.interpret(suffix(suf))
if !ok {
return Quantity{}, ErrSuffix
}
precision := int32(0)
scale := int32(0)
mantissa := int64(1)
switch format {
case DecimalExponent, DecimalSI:
scale = exponent
precision = maxInt64Factors - int32(len(num)+len(denom))
case BinarySI:
scale = 0
switch {
case exponent >= 0 && len(denom) == 0:
// only handle positive binary numbers with the fast path
mantissa = int64(int64(mantissa) << uint64(exponent))
// 1Mi (2^20) has ~6 digits of decimal precision, so exponent*3/10 -1 is roughly the precision
precision = 15 - int32(len(num)) - int32(float32(exponent)*3/10) - 1
default:
precision = -1
}
}
if precision >= 0 {
// if we have a denominator, shift the entire value to the left by the number of places in the
// denominator
scale -= int32(len(denom))
if scale >= int32(Nano) {
shifted := num + denom
var value int64
value, err := strconv.ParseInt(shifted, 10, 64)
if err != nil {
return Quantity{}, ErrNumeric
}
if result, ok := int64Multiply(value, int64(mantissa)); ok {
if !positive {
result = -result
}
// if the number is in canonical form, reuse the string
switch format {
case BinarySI:
if exponent%10 == 0 && (value&0x07 != 0) {
return Quantity{i: int64Amount{value: result, scale: Scale(scale)}, Format: format, s: str}, nil
}
default:
if scale%3 == 0 && !strings.HasSuffix(shifted, "000") && shifted[0] != '0' {
return Quantity{i: int64Amount{value: result, scale: Scale(scale)}, Format: format, s: str}, nil
}
}
return Quantity{i: int64Amount{value: result, scale: Scale(scale)}, Format: format}, nil
}
}
}
amount := new(inf.Dec)
if _, ok := amount.SetString(value); !ok {
return Quantity{}, ErrNumeric
}
// So that no one but us has to think about suffixes, remove it.
if base == 10 {
amount.SetScale(amount.Scale() + Scale(exponent).infScale())
} else if base == 2 {
// numericSuffix = 2 ** exponent
numericSuffix := big.NewInt(1).Lsh(bigOne, uint(exponent))
ub := amount.UnscaledBig()
amount.SetUnscaledBig(ub.Mul(ub, numericSuffix))
}
// Cap at min/max bounds.
sign := amount.Sign()
if sign == -1 {
amount.Neg(amount)
}
// This rounds non-zero values up to the minimum representable value, under the theory that
// if you want some resources, you should get some resources, even if you asked for way too small
// of an amount. Arguably, this should be inf.RoundHalfUp (normal rounding), but that would have
// the side effect of rounding values < .5n to zero.
if v, ok := amount.Unscaled(); v != int64(0) || !ok {
amount.Round(amount, Nano.infScale(), inf.RoundUp)
}
// The max is just a simple cap.
// TODO: this prevents accumulating quantities greater than int64, for instance quota across a cluster
if format == BinarySI && amount.Cmp(maxAllowed.Dec) > 0 {
amount.Set(maxAllowed.Dec)
}
if format == BinarySI && amount.Cmp(decOne) < 0 && amount.Cmp(decZero) > 0 {
// This avoids rounding and hopefully confusion, too.
format = DecimalSI
}
if sign == -1 {
amount.Neg(amount)
}
return Quantity{d: infDecAmount{amount}, Format: format}, nil
}
// CanonicalizeBytes returns the canonical form of q and its suffix (see comment on Quantity).
//
// Note about BinarySI:
// * If q.Format is set to BinarySI and q.Amount represents a non-zero value between
// -1 and +1, it will be emitted as if q.Format were DecimalSI.
// * Otherwise, if q.Format is set to BinarySI, frational parts of q.Amount will be
// rounded up. (1.1i becomes 2i.)
func (q *Quantity) CanonicalizeBytes(out []byte) (result, suffix []byte) {
if q.IsZero() {
return zeroBytes, nil
}
var rounded CanonicalValue
format := q.Format
switch format {
case DecimalExponent, DecimalSI:
case BinarySI:
if q.CmpInt64(-1024) > 0 && q.CmpInt64(1024) < 0 {
// This avoids rounding and hopefully confusion, too.
format = DecimalSI
} else {
var exact bool
if rounded, exact = q.AsScale(0); !exact {
// Don't lose precision-- show as DecimalSI
format = DecimalSI
}
}
default:
format = DecimalExponent
}
// TODO: If BinarySI formatting is requested but would cause rounding, upgrade to
// one of the other formats.
switch format {
case DecimalExponent, DecimalSI:
number, exponent := q.AsCanonicalBytes(out)
suffix, _ := quantitySuffixer.constructBytes(10, exponent, format)
return number, suffix
default:
// format must be BinarySI
number, exponent := rounded.AsCanonicalBase1024Bytes(out)
suffix, _ := quantitySuffixer.constructBytes(2, exponent*10, format)
return number, suffix
}
}
// AsInt64 returns a representation of the current value as an int64 if a fast conversion
// is possible. If false is returned, callers must use the inf.Dec form of this quantity.
func (q *Quantity) AsInt64() (int64, bool) {
if q.d.Dec != nil {
return 0, false
}
return q.i.AsInt64()
}
// ToDec promotes the quantity in place to use an inf.Dec representation and returns itself.
func (q *Quantity) ToDec() *Quantity {
if q.d.Dec == nil {
q.d.Dec = q.i.AsDec()
q.i = int64Amount{}
}
return q
}
// AsDec returns the quantity as represented by a scaled inf.Dec.
func (q *Quantity) AsDec() *inf.Dec {
if q.d.Dec != nil {
return q.d.Dec
}
q.d.Dec = q.i.AsDec()
q.i = int64Amount{}
return q.d.Dec
}
// AsCanonicalBytes returns the canonical byte representation of this quantity as a mantissa
// and base 10 exponent. The out byte slice may be passed to the method to avoid an extra
// allocation.
func (q *Quantity) AsCanonicalBytes(out []byte) (result []byte, exponent int32) {
if q.d.Dec != nil {
return q.d.AsCanonicalBytes(out)
}
return q.i.AsCanonicalBytes(out)
}
// IsZero returns true if the quantity is equal to zero.
func (q *Quantity) IsZero() bool {
if q.d.Dec != nil {
return q.d.Dec.Sign() == 0
}
return q.i.value == 0
}
// Sign returns 0 if the quantity is zero, -1 if the quantity is less than zero, or 1 if the
// quantity is greater than zero.
func (q *Quantity) Sign() int {
if q.d.Dec != nil {
return q.d.Dec.Sign()
}
return q.i.Sign()
}
// AsScaled returns the current value, rounded up to the provided scale, and returns
// false if the scale resulted in a loss of precision.
func (q *Quantity) AsScale(scale Scale) (CanonicalValue, bool) {
if q.d.Dec != nil {
return q.d.AsScale(scale)
}
return q.i.AsScale(scale)
}
// RoundUp updates the quantity to the provided scale, ensuring that the value is at
// least 1. False is returned if the rounding operation resulted in a loss of precision.
// Negative numbers are rounded away from zero (-9 scale 1 rounds to -10).
func (q *Quantity) RoundUp(scale Scale) bool {
if q.d.Dec != nil {
q.s = ""
d, exact := q.d.AsScale(scale)
q.d = d
return exact
}
// avoid clearing the string value if we have already calculated it
if q.i.scale >= scale {
return true
}
q.s = ""
i, exact := q.i.AsScale(scale)
q.i = i
return exact
}
// Add adds the provide y quantity to the current value. If the current value is zero,
// the format of the quantity will be updated to the format of y.
func (q *Quantity) Add(y Quantity) {
q.s = ""
if q.d.Dec == nil && y.d.Dec == nil {
if q.i.value == 0 {
q.Format = y.Format
}
if q.i.Add(y.i) {
return
}
} else if q.IsZero() {
q.Format = y.Format
}
q.ToDec().d.Dec.Add(q.d.Dec, y.AsDec())
}
// Sub subtracts the provided quantity from the current value in place. If the current
// value is zero, the format of the quantity will be updated to the format of y.
func (q *Quantity) Sub(y Quantity) {
q.s = ""
if q.IsZero() {
q.Format = y.Format
}
if q.d.Dec == nil && y.d.Dec == nil && q.i.Sub(y.i) {
return
}
q.ToDec().d.Dec.Sub(q.d.Dec, y.AsDec())
}
// Cmp returns 0 if the quantity is equal to y, -1 if the quantity is less than y, or 1 if the
// quantity is greater than y.
func (q *Quantity) Cmp(y Quantity) int {
if q.d.Dec == nil && y.d.Dec == nil {
return q.i.Cmp(y.i)
}
return q.AsDec().Cmp(y.AsDec())
}
// CmpInt64 returns 0 if the quantity is equal to y, -1 if the quantity is less than y, or 1 if the
// quantity is greater than y.
func (q *Quantity) CmpInt64(y int64) int {
if q.d.Dec != nil {
return q.d.Dec.Cmp(inf.NewDec(y, inf.Scale(0)))
}
return q.i.Cmp(int64Amount{value: y})
}
// Neg sets quantity to be the negative value of itself.
func (q *Quantity) Neg() {
q.s = ""
if q.d.Dec == nil {
q.i.value = -q.i.value
return
}
q.d.Dec.Neg(q.d.Dec)
}
// int64QuantityExpectedBytes is the expected width in bytes of the canonical string representation
// of most Quantity values.
const int64QuantityExpectedBytes = 18
// String formats the Quantity as a string, caching the result if not calculated.
// String is an expensive operation and caching this result significantly reduces the cost of
// normal parse / marshal operations on Quantity.
func (q *Quantity) String() string {
if len(q.s) == 0 {
result := make([]byte, 0, int64QuantityExpectedBytes)
number, suffix := q.CanonicalizeBytes(result)
number = append(number, suffix...)
q.s = string(number)
}
return q.s
}
// MarshalJSON implements the json.Marshaller interface.
func (q Quantity) MarshalJSON() ([]byte, error) {
if len(q.s) > 0 {
out := make([]byte, len(q.s)+2)
out[0], out[len(out)-1] = '"', '"'
copy(out[1:], q.s)
return out, nil
}
result := make([]byte, int64QuantityExpectedBytes, int64QuantityExpectedBytes)
result[0] = '"'
number, suffix := q.CanonicalizeBytes(result[1:1])
// if the same slice was returned to us that we passed in, avoid another allocation by copying number into
// the source slice and returning that
if len(number) > 0 && &number[0] == &result[1] && (len(number)+len(suffix)+2) <= int64QuantityExpectedBytes {
number = append(number, suffix...)
number = append(number, '"')
return result[:1+len(number)], nil
}
// if CanonicalizeBytes needed more space than our slice provided, we may need to allocate again so use
// append
result = result[:1]
result = append(result, number...)
result = append(result, suffix...)
result = append(result, '"')
return result, nil
}
// UnmarshalJSON implements the json.Unmarshaller interface.
// TODO: Remove support for leading/trailing whitespace
func (q *Quantity) UnmarshalJSON(value []byte) error {
l := len(value)
if l == 4 && bytes.Equal(value, []byte("null")) {
q.d.Dec = nil
q.i = int64Amount{}
return nil
}
if l >= 2 && value[0] == '"' && value[l-1] == '"' {
value = value[1 : l-1]
}
parsed, err := ParseQuantity(strings.TrimSpace(string(value)))
if err != nil {
return err
}
// This copy is safe because parsed will not be referred to again.
*q = parsed
return nil
}
// NewQuantity returns a new Quantity representing the given
// value in the given format.
func NewQuantity(value int64, format Format) *Quantity {
return &Quantity{
i: int64Amount{value: value},
Format: format,
}
}
// NewMilliQuantity returns a new Quantity representing the given
// value * 1/1000 in the given format. Note that BinarySI formatting
// will round fractional values, and will be changed to DecimalSI for
// values x where (-1 < x < 1) && (x != 0).
func NewMilliQuantity(value int64, format Format) *Quantity {
return &Quantity{
i: int64Amount{value: value, scale: -3},
Format: format,
}
}
// NewScaledQuantity returns a new Quantity representing the given
// value * 10^scale in DecimalSI format.
func NewScaledQuantity(value int64, scale Scale) *Quantity {
return &Quantity{
i: int64Amount{value: value, scale: scale},
Format: DecimalSI,
}
}
// Value returns the value of q; any fractional part will be lost.
func (q *Quantity) Value() int64 {
return q.ScaledValue(0)
}
// MilliValue returns the value of ceil(q * 1000); this could overflow an int64;
// if that's a concern, call Value() first to verify the number is small enough.
func (q *Quantity) MilliValue() int64 {
return q.ScaledValue(Milli)
}
// ScaledValue returns the value of ceil(q * 10^scale); this could overflow an int64.
// To detect overflow, call Value() first and verify the expected magnitude.
func (q *Quantity) ScaledValue(scale Scale) int64 {
if q.d.Dec == nil {
i, _ := q.i.AsScaledInt64(scale)
return i
}
dec := q.d.Dec
return scaledValue(dec.UnscaledBig(), int(dec.Scale()), int(scale.infScale()))
}
// Set sets q's value to be value.
func (q *Quantity) Set(value int64) {
q.SetScaled(value, 0)
}
// SetMilli sets q's value to be value * 1/1000.
func (q *Quantity) SetMilli(value int64) {
q.SetScaled(value, Milli)
}
// SetScaled sets q's value to be value * 10^scale
func (q *Quantity) SetScaled(value int64, scale Scale) {
q.s = ""
q.d.Dec = nil
q.i = int64Amount{value: value, scale: scale}
}
// Copy is a convenience function that makes a deep copy for you. Non-deep
// copies of quantities share pointers and you will regret that.
func (q *Quantity) Copy() *Quantity {
if q.d.Dec == nil {
return &Quantity{
s: q.s,
i: q.i,
Format: q.Format,
}
}
tmp := &inf.Dec{}
return &Quantity{
s: q.s,
d: infDecAmount{tmp.Set(q.d.Dec)},
Format: q.Format,
}
}
// qFlag is a helper type for the Flag function
type qFlag struct {
dest *Quantity
}
// Sets the value of the internal Quantity. (used by flag & pflag)
func (qf qFlag) Set(val string) error {
q, err := ParseQuantity(val)
if err != nil {
return err
}
// This copy is OK because q will not be referenced again.
*qf.dest = q
return nil
}
// Converts the value of the internal Quantity to a string. (used by flag & pflag)
func (qf qFlag) String() string {
return qf.dest.String()
}
// States the type of flag this is (Quantity). (used by pflag)
func (qf qFlag) Type() string {
return "quantity"
}
// QuantityFlag is a helper that makes a quantity flag (using standard flag package).
// Will panic if defaultValue is not a valid quantity.
func QuantityFlag(flagName, defaultValue, description string) *Quantity {
q := MustParse(defaultValue)
flag.Var(NewQuantityFlagValue(&q), flagName, description)
return &q
}
// NewQuantityFlagValue returns an object that can be used to back a flag,
// pointing at the given Quantity variable.
func NewQuantityFlagValue(q *Quantity) flag.Value {
return qFlag{q}
}

View File

@@ -0,0 +1,95 @@
/*
Copyright 2015 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resource
import (
"math"
"math/big"
"sync"
)
var (
// A sync pool to reduce allocation.
intPool sync.Pool
maxInt64 = big.NewInt(math.MaxInt64)
)
func init() {
intPool.New = func() interface{} {
return &big.Int{}
}
}
// scaledValue scales given unscaled value from scale to new Scale and returns
// an int64. It ALWAYS rounds up the result when scale down. The final result might
// overflow.
//
// scale, newScale represents the scale of the unscaled decimal.
// The mathematical value of the decimal is unscaled * 10**(-scale).
func scaledValue(unscaled *big.Int, scale, newScale int) int64 {
dif := scale - newScale
if dif == 0 {
return unscaled.Int64()
}
// Handle scale up
// This is an easy case, we do not need to care about rounding and overflow.
// If any intermediate operation causes overflow, the result will overflow.
if dif < 0 {
return unscaled.Int64() * int64(math.Pow10(-dif))
}
// Handle scale down
// We have to be careful about the intermediate operations.
// fast path when unscaled < max.Int64 and exp(10,dif) < max.Int64
const log10MaxInt64 = 19
if unscaled.Cmp(maxInt64) < 0 && dif < log10MaxInt64 {
divide := int64(math.Pow10(dif))
result := unscaled.Int64() / divide
mod := unscaled.Int64() % divide
if mod != 0 {
return result + 1
}
return result
}
// We should only convert back to int64 when getting the result.
divisor := intPool.Get().(*big.Int)
exp := intPool.Get().(*big.Int)
result := intPool.Get().(*big.Int)
defer func() {
intPool.Put(divisor)
intPool.Put(exp)
intPool.Put(result)
}()
// divisor = 10^(dif)
// TODO: create loop up table if exp costs too much.
divisor.Exp(bigTen, exp.SetInt64(int64(dif)), nil)
// reuse exp
remainder := exp
// result = unscaled / divisor
// remainder = unscaled % divisor
result.DivMod(unscaled, divisor, remainder)
if remainder.Sign() != 0 {
return result.Int64() + 1
}
return result.Int64()
}

View File

@@ -0,0 +1,198 @@
/*
Copyright 2014 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package resource
import (
"strconv"
)
type suffix string
// suffixer can interpret and construct suffixes.
type suffixer interface {
interpret(suffix) (base, exponent int32, fmt Format, ok bool)
construct(base, exponent int32, fmt Format) (s suffix, ok bool)
constructBytes(base, exponent int32, fmt Format) (s []byte, ok bool)
}
// quantitySuffixer handles suffixes for all three formats that quantity
// can handle.
var quantitySuffixer = newSuffixer()
type bePair struct {
base, exponent int32
}
type listSuffixer struct {
suffixToBE map[suffix]bePair
beToSuffix map[bePair]suffix
beToSuffixBytes map[bePair][]byte
}
func (ls *listSuffixer) addSuffix(s suffix, pair bePair) {
if ls.suffixToBE == nil {
ls.suffixToBE = map[suffix]bePair{}
}
if ls.beToSuffix == nil {
ls.beToSuffix = map[bePair]suffix{}
}
if ls.beToSuffixBytes == nil {
ls.beToSuffixBytes = map[bePair][]byte{}
}
ls.suffixToBE[s] = pair
ls.beToSuffix[pair] = s
ls.beToSuffixBytes[pair] = []byte(s)
}
func (ls *listSuffixer) lookup(s suffix) (base, exponent int32, ok bool) {
pair, ok := ls.suffixToBE[s]
if !ok {
return 0, 0, false
}
return pair.base, pair.exponent, true
}
func (ls *listSuffixer) construct(base, exponent int32) (s suffix, ok bool) {
s, ok = ls.beToSuffix[bePair{base, exponent}]
return
}
func (ls *listSuffixer) constructBytes(base, exponent int32) (s []byte, ok bool) {
s, ok = ls.beToSuffixBytes[bePair{base, exponent}]
return
}
type suffixHandler struct {
decSuffixes listSuffixer
binSuffixes listSuffixer
}
type fastLookup struct {
*suffixHandler
}
func (l fastLookup) interpret(s suffix) (base, exponent int32, format Format, ok bool) {
switch s {
case "":
return 10, 0, DecimalSI, true
case "n":
return 10, -9, DecimalSI, true
case "u":
return 10, -6, DecimalSI, true
case "m":
return 10, -3, DecimalSI, true
case "k":
return 10, 3, DecimalSI, true
case "M":
return 10, 6, DecimalSI, true
case "G":
return 10, 9, DecimalSI, true
}
return l.suffixHandler.interpret(s)
}
func newSuffixer() suffixer {
sh := &suffixHandler{}
// IMPORTANT: if you change this section you must change fastLookup
sh.binSuffixes.addSuffix("Ki", bePair{2, 10})
sh.binSuffixes.addSuffix("Mi", bePair{2, 20})
sh.binSuffixes.addSuffix("Gi", bePair{2, 30})
sh.binSuffixes.addSuffix("Ti", bePair{2, 40})
sh.binSuffixes.addSuffix("Pi", bePair{2, 50})
sh.binSuffixes.addSuffix("Ei", bePair{2, 60})
// Don't emit an error when trying to produce
// a suffix for 2^0.
sh.decSuffixes.addSuffix("", bePair{2, 0})
sh.decSuffixes.addSuffix("n", bePair{10, -9})
sh.decSuffixes.addSuffix("u", bePair{10, -6})
sh.decSuffixes.addSuffix("m", bePair{10, -3})
sh.decSuffixes.addSuffix("", bePair{10, 0})
sh.decSuffixes.addSuffix("k", bePair{10, 3})
sh.decSuffixes.addSuffix("M", bePair{10, 6})
sh.decSuffixes.addSuffix("G", bePair{10, 9})
sh.decSuffixes.addSuffix("T", bePair{10, 12})
sh.decSuffixes.addSuffix("P", bePair{10, 15})
sh.decSuffixes.addSuffix("E", bePair{10, 18})
return fastLookup{sh}
}
func (sh *suffixHandler) construct(base, exponent int32, fmt Format) (s suffix, ok bool) {
switch fmt {
case DecimalSI:
return sh.decSuffixes.construct(base, exponent)
case BinarySI:
return sh.binSuffixes.construct(base, exponent)
case DecimalExponent:
if base != 10 {
return "", false
}
if exponent == 0 {
return "", true
}
return suffix("e" + strconv.FormatInt(int64(exponent), 10)), true
}
return "", false
}
func (sh *suffixHandler) constructBytes(base, exponent int32, format Format) (s []byte, ok bool) {
switch format {
case DecimalSI:
return sh.decSuffixes.constructBytes(base, exponent)
case BinarySI:
return sh.binSuffixes.constructBytes(base, exponent)
case DecimalExponent:
if base != 10 {
return nil, false
}
if exponent == 0 {
return nil, true
}
result := make([]byte, 8, 8)
result[0] = 'e'
number := strconv.AppendInt(result[1:1], int64(exponent), 10)
if &result[1] == &number[0] {
return result[:1+len(number)], true
}
result = append(result[:1], number...)
return result, true
}
return nil, false
}
func (sh *suffixHandler) interpret(suffix suffix) (base, exponent int32, fmt Format, ok bool) {
// Try lookup tables first
if b, e, ok := sh.decSuffixes.lookup(suffix); ok {
return b, e, DecimalSI, true
}
if b, e, ok := sh.binSuffixes.lookup(suffix); ok {
return b, e, BinarySI, true
}
if len(suffix) > 1 && (suffix[0] == 'E' || suffix[0] == 'e') {
parsed, err := strconv.ParseInt(string(suffix[1:]), 10, 64)
if err != nil {
return 0, 0, DecimalExponent, false
}
return 10, int32(parsed), DecimalExponent, true
}
return 0, 0, DecimalExponent, false
}

91
vendor/github.com/appc/spec/schema/types/semver.go generated vendored Normal file
View File

@@ -0,0 +1,91 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
"github.com/coreos/go-semver/semver"
)
var (
ErrNoZeroSemVer = ACVersionError("SemVer cannot be zero")
ErrBadSemVer = ACVersionError("SemVer is bad")
)
// SemVer implements the Unmarshaler interface to define a field that must be
// a semantic version string
// TODO(jonboulle): extend upstream instead of wrapping?
type SemVer semver.Version
// NewSemVer generates a new SemVer from a string. If the given string does
// not represent a valid SemVer, nil and an error are returned.
func NewSemVer(s string) (*SemVer, error) {
nsv, err := semver.NewVersion(s)
if err != nil {
return nil, ErrBadSemVer
}
v := SemVer(*nsv)
if v.Empty() {
return nil, ErrNoZeroSemVer
}
return &v, nil
}
func (sv SemVer) LessThanMajor(versionB SemVer) bool {
majorA := semver.Version(sv).Major
majorB := semver.Version(versionB).Major
if majorA < majorB {
return true
}
return false
}
func (sv SemVer) LessThanExact(versionB SemVer) bool {
vA := semver.Version(sv)
vB := semver.Version(versionB)
return vA.LessThan(vB)
}
func (sv SemVer) String() string {
s := semver.Version(sv)
return s.String()
}
func (sv SemVer) Empty() bool {
return semver.Version(sv) == semver.Version{}
}
// UnmarshalJSON implements the json.Unmarshaler interface
func (sv *SemVer) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
v, err := NewSemVer(s)
if err != nil {
return err
}
*sv = *v
return nil
}
// MarshalJSON implements the json.Marshaler interface
func (sv SemVer) MarshalJSON() ([]byte, error) {
if sv.Empty() {
return nil, ErrNoZeroSemVer
}
return json.Marshal(sv.String())
}

71
vendor/github.com/appc/spec/schema/types/url.go generated vendored Normal file
View File

@@ -0,0 +1,71 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
"fmt"
"net/url"
)
// URL wraps url.URL to marshal/unmarshal to/from JSON strings and enforce
// that the scheme is HTTP/HTTPS only
type URL url.URL
func NewURL(s string) (*URL, error) {
uu, err := url.Parse(s)
if err != nil {
return nil, fmt.Errorf("bad URL: %v", err)
}
nu := URL(*uu)
if err := nu.assertValidScheme(); err != nil {
return nil, err
}
return &nu, nil
}
func (u URL) String() string {
uu := url.URL(u)
return uu.String()
}
func (u URL) assertValidScheme() error {
switch u.Scheme {
case "http", "https":
return nil
default:
return fmt.Errorf("bad URL scheme, must be http/https")
}
}
func (u *URL) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
nu, err := NewURL(s)
if err != nil {
return err
}
*u = *nu
return nil
}
func (u URL) MarshalJSON() ([]byte, error) {
if err := u.assertValidScheme(); err != nil {
return nil, err
}
return json.Marshal(u.String())
}

View File

@@ -0,0 +1,18 @@
// Copyright 2016 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
// UserAnnotations are arbitrary key-value pairs, to be supplied and interpreted by the user
type UserAnnotations map[string]string

View File

@@ -0,0 +1,18 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
// UserLabels are arbitrary key-value pairs, to be supplied and interpreted by the user
type UserLabels map[string]string

92
vendor/github.com/appc/spec/schema/types/uuid.go generated vendored Normal file
View File

@@ -0,0 +1,92 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"reflect"
"strings"
)
var (
ErrNoEmptyUUID = errors.New("UUID cannot be empty")
)
// UUID encodes an RFC4122-compliant UUID, marshaled to/from a string
// TODO(jonboulle): vendor a package for this?
// TODO(jonboulle): consider more flexibility in input string formats.
// Right now, we only accept:
// "6733C088-A507-4694-AABF-EDBE4FC5266F"
// "6733C088A5074694AABFEDBE4FC5266F"
type UUID [16]byte
func (u UUID) String() string {
return fmt.Sprintf("%x-%x-%x-%x-%x", u[0:4], u[4:6], u[6:8], u[8:10], u[10:16])
}
func (u *UUID) Set(s string) error {
nu, err := NewUUID(s)
if err == nil {
*u = *nu
}
return err
}
// NewUUID generates a new UUID from the given string. If the string does not
// represent a valid UUID, nil and an error are returned.
func NewUUID(s string) (*UUID, error) {
s = strings.Replace(s, "-", "", -1)
if len(s) != 32 {
return nil, errors.New("bad UUID length != 32")
}
dec, err := hex.DecodeString(s)
if err != nil {
return nil, err
}
var u UUID
for i, b := range dec {
u[i] = b
}
return &u, nil
}
func (u UUID) Empty() bool {
return reflect.DeepEqual(u, UUID{})
}
func (u *UUID) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
uu, err := NewUUID(s)
if uu.Empty() {
return ErrNoEmptyUUID
}
if err == nil {
*u = *uu
}
return err
}
func (u UUID) MarshalJSON() ([]byte, error) {
if u.Empty() {
return nil, ErrNoEmptyUUID
}
return json.Marshal(u.String())
}

249
vendor/github.com/appc/spec/schema/types/volume.go generated vendored Normal file
View File

@@ -0,0 +1,249 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
"errors"
"fmt"
"net/url"
"path/filepath"
"strconv"
"strings"
"github.com/appc/spec/schema/common"
)
const (
emptyVolumeDefaultMode = "0755"
emptyVolumeDefaultUID = 0
emptyVolumeDefaultGID = 0
)
// Volume encapsulates a volume which should be mounted into the filesystem
// of all apps in a PodManifest
type Volume struct {
Name ACName `json:"name"`
Kind string `json:"kind"`
// currently used only by "host"
// TODO(jonboulle): factor out?
Source string `json:"source,omitempty"`
ReadOnly *bool `json:"readOnly,omitempty"`
Recursive *bool `json:"recursive,omitempty"`
// currently used only by "empty"
Mode *string `json:"mode,omitempty"`
UID *int `json:"uid,omitempty"`
GID *int `json:"gid,omitempty"`
}
type volume Volume
func (v Volume) assertValid() error {
if v.Name.Empty() {
return errors.New("name must be set")
}
switch v.Kind {
case "empty":
if v.Source != "" {
return errors.New("source for empty volume must be empty")
}
if v.Mode == nil {
return errors.New("mode for empty volume must be set")
}
if v.UID == nil {
return errors.New("uid for empty volume must be set")
}
if v.GID == nil {
return errors.New("gid for empty volume must be set")
}
return nil
case "host":
if v.Source == "" {
return errors.New("source for host volume cannot be empty")
}
if v.Mode != nil {
return errors.New("mode for host volume cannot be set")
}
if v.UID != nil {
return errors.New("uid for host volume cannot be set")
}
if v.GID != nil {
return errors.New("gid for host volume cannot be set")
}
if !filepath.IsAbs(v.Source) {
return errors.New("source for host volume must be absolute path")
}
return nil
default:
return errors.New(`unrecognized volume kind: should be one of "empty", "host"`)
}
}
func (v *Volume) UnmarshalJSON(data []byte) error {
var vv volume
if err := json.Unmarshal(data, &vv); err != nil {
return err
}
nv := Volume(vv)
maybeSetDefaults(&nv)
if err := nv.assertValid(); err != nil {
return err
}
*v = nv
return nil
}
func (v Volume) MarshalJSON() ([]byte, error) {
if err := v.assertValid(); err != nil {
return nil, err
}
return json.Marshal(volume(v))
}
func (v Volume) String() string {
s := []string{
v.Name.String(),
",kind=",
v.Kind,
}
if v.Source != "" {
s = append(s, ",source=")
s = append(s, v.Source)
}
if v.ReadOnly != nil {
s = append(s, ",readOnly=")
s = append(s, strconv.FormatBool(*v.ReadOnly))
}
if v.Recursive != nil {
s = append(s, ",recursive=")
s = append(s, strconv.FormatBool(*v.Recursive))
}
switch v.Kind {
case "empty":
if *v.Mode != emptyVolumeDefaultMode {
s = append(s, ",mode=")
s = append(s, *v.Mode)
}
if *v.UID != emptyVolumeDefaultUID {
s = append(s, ",uid=")
s = append(s, strconv.Itoa(*v.UID))
}
if *v.GID != emptyVolumeDefaultGID {
s = append(s, ",gid=")
s = append(s, strconv.Itoa(*v.GID))
}
}
return strings.Join(s, "")
}
// VolumeFromString takes a command line volume parameter and returns a volume
//
// Example volume parameters:
// database,kind=host,source=/tmp,readOnly=true,recursive=true
func VolumeFromString(vp string) (*Volume, error) {
vp = "name=" + vp
vpQuery, err := common.MakeQueryString(vp)
if err != nil {
return nil, err
}
v, err := url.ParseQuery(vpQuery)
if err != nil {
return nil, err
}
return VolumeFromParams(v)
}
func VolumeFromParams(params map[string][]string) (*Volume, error) {
var vol Volume
for key, val := range params {
val := val
if len(val) > 1 {
return nil, fmt.Errorf("label %s with multiple values %q", key, val)
}
switch key {
case "name":
acn, err := NewACName(val[0])
if err != nil {
return nil, err
}
vol.Name = *acn
case "kind":
vol.Kind = val[0]
case "source":
vol.Source = val[0]
case "readOnly":
ro, err := strconv.ParseBool(val[0])
if err != nil {
return nil, err
}
vol.ReadOnly = &ro
case "recursive":
rec, err := strconv.ParseBool(val[0])
if err != nil {
return nil, err
}
vol.Recursive = &rec
case "mode":
vol.Mode = &val[0]
case "uid":
u, err := strconv.Atoi(val[0])
if err != nil {
return nil, err
}
vol.UID = &u
case "gid":
g, err := strconv.Atoi(val[0])
if err != nil {
return nil, err
}
vol.GID = &g
default:
return nil, fmt.Errorf("unknown volume parameter %q", key)
}
}
maybeSetDefaults(&vol)
if err := vol.assertValid(); err != nil {
return nil, err
}
return &vol, nil
}
// maybeSetDefaults sets the correct default values for certain fields on a
// Volume if they are not already been set. These fields are not
// pre-populated on all Volumes as the Volume type is polymorphic.
func maybeSetDefaults(vol *Volume) {
if vol.Kind == "empty" {
if vol.Mode == nil {
m := emptyVolumeDefaultMode
vol.Mode = &m
}
if vol.UID == nil {
u := emptyVolumeDefaultUID
vol.UID = &u
}
if vol.GID == nil {
g := emptyVolumeDefaultGID
vol.GID = &g
}
}
}

39
vendor/github.com/appc/spec/schema/version.go generated vendored Normal file
View File

@@ -0,0 +1,39 @@
// Copyright 2015 The appc Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package schema
import (
"github.com/appc/spec/schema/types"
)
const (
// version represents the canonical version of the appc spec and tooling.
// For now, the schema and tooling is coupled with the spec itself, so
// this must be kept in sync with the VERSION file in the root of the repo.
version string = "0.8.11"
)
var (
// AppContainerVersion is the SemVer representation of version
AppContainerVersion types.SemVer
)
func init() {
v, err := types.NewSemVer(version)
if err != nil {
panic(err)
}
AppContainerVersion = *v
}

202
vendor/github.com/containernetworking/cni/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -0,0 +1,91 @@
// Copyright 2015 CNI authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding"
"fmt"
"reflect"
"strings"
)
// UnmarshallableBool typedef for builtin bool
// because builtin type's methods can't be declared
type UnmarshallableBool bool
// UnmarshalText implements the encoding.TextUnmarshaler interface.
// Returns boolean true if the string is "1" or "[Tt]rue"
// Returns boolean false if the string is "0" or "[Ff]alse"
func (b *UnmarshallableBool) UnmarshalText(data []byte) error {
s := strings.ToLower(string(data))
switch s {
case "1", "true":
*b = true
case "0", "false":
*b = false
default:
return fmt.Errorf("Boolean unmarshal error: invalid input %s", s)
}
return nil
}
// CommonArgs contains the IgnoreUnknown argument
// and must be embedded by all Arg structs
type CommonArgs struct {
IgnoreUnknown UnmarshallableBool `json:"ignoreunknown,omitempty"`
}
// GetKeyField is a helper function to receive Values
// Values that represent a pointer to a struct
func GetKeyField(keyString string, v reflect.Value) reflect.Value {
return v.Elem().FieldByName(keyString)
}
// LoadArgs parses args from a string in the form "K=V;K2=V2;..."
func LoadArgs(args string, container interface{}) error {
if args == "" {
return nil
}
containerValue := reflect.ValueOf(container)
pairs := strings.Split(args, ";")
unknownArgs := []string{}
for _, pair := range pairs {
kv := strings.Split(pair, "=")
if len(kv) != 2 {
return fmt.Errorf("ARGS: invalid pair %q", pair)
}
keyString := kv[0]
valueString := kv[1]
keyField := GetKeyField(keyString, containerValue)
if !keyField.IsValid() {
unknownArgs = append(unknownArgs, pair)
continue
}
u := keyField.Addr().Interface().(encoding.TextUnmarshaler)
err := u.UnmarshalText([]byte(valueString))
if err != nil {
return fmt.Errorf("ARGS: error parsing value of pair %q: %v)", pair, err)
}
}
isIgnoreUnknown := GetKeyField("IgnoreUnknown", containerValue).Bool()
if len(unknownArgs) > 0 && !isIgnoreUnknown {
return fmt.Errorf("ARGS: unknown args %q", unknownArgs)
}
return nil
}

View File

@@ -0,0 +1,191 @@
// Copyright 2015 CNI authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package types
import (
"encoding/json"
"fmt"
"net"
"os"
)
// like net.IPNet but adds JSON marshalling and unmarshalling
type IPNet net.IPNet
// ParseCIDR takes a string like "10.2.3.1/24" and
// return IPNet with "10.2.3.1" and /24 mask
func ParseCIDR(s string) (*net.IPNet, error) {
ip, ipn, err := net.ParseCIDR(s)
if err != nil {
return nil, err
}
ipn.IP = ip
return ipn, nil
}
func (n IPNet) MarshalJSON() ([]byte, error) {
return json.Marshal((*net.IPNet)(&n).String())
}
func (n *IPNet) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
tmp, err := ParseCIDR(s)
if err != nil {
return err
}
*n = IPNet(*tmp)
return nil
}
// NetConf describes a network.
type NetConf struct {
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
IPAM struct {
Type string `json:"type,omitempty"`
} `json:"ipam,omitempty"`
DNS DNS `json:"dns"`
}
// Result is what gets returned from the plugin (via stdout) to the caller
type Result struct {
IP4 *IPConfig `json:"ip4,omitempty"`
IP6 *IPConfig `json:"ip6,omitempty"`
DNS DNS `json:"dns,omitempty"`
}
func (r *Result) Print() error {
return prettyPrint(r)
}
// String returns a formatted string in the form of "[IP4: $1,][ IP6: $2,] DNS: $3" where
// $1 represents the receiver's IPv4, $2 represents the receiver's IPv6 and $3 the
// receiver's DNS. If $1 or $2 are nil, they won't be present in the returned string.
func (r *Result) String() string {
var str string
if r.IP4 != nil {
str = fmt.Sprintf("IP4:%+v, ", *r.IP4)
}
if r.IP6 != nil {
str += fmt.Sprintf("IP6:%+v, ", *r.IP6)
}
return fmt.Sprintf("%sDNS:%+v", str, r.DNS)
}
// IPConfig contains values necessary to configure an interface
type IPConfig struct {
IP net.IPNet
Gateway net.IP
Routes []Route
}
// DNS contains values interesting for DNS resolvers
type DNS struct {
Nameservers []string `json:"nameservers,omitempty"`
Domain string `json:"domain,omitempty"`
Search []string `json:"search,omitempty"`
Options []string `json:"options,omitempty"`
}
type Route struct {
Dst net.IPNet
GW net.IP
}
type Error struct {
Code uint `json:"code"`
Msg string `json:"msg"`
Details string `json:"details,omitempty"`
}
func (e *Error) Error() string {
return e.Msg
}
func (e *Error) Print() error {
return prettyPrint(e)
}
// net.IPNet is not JSON (un)marshallable so this duality is needed
// for our custom IPNet type
// JSON (un)marshallable types
type ipConfig struct {
IP IPNet `json:"ip"`
Gateway net.IP `json:"gateway,omitempty"`
Routes []Route `json:"routes,omitempty"`
}
type route struct {
Dst IPNet `json:"dst"`
GW net.IP `json:"gw,omitempty"`
}
func (c *IPConfig) MarshalJSON() ([]byte, error) {
ipc := ipConfig{
IP: IPNet(c.IP),
Gateway: c.Gateway,
Routes: c.Routes,
}
return json.Marshal(ipc)
}
func (c *IPConfig) UnmarshalJSON(data []byte) error {
ipc := ipConfig{}
if err := json.Unmarshal(data, &ipc); err != nil {
return err
}
c.IP = net.IPNet(ipc.IP)
c.Gateway = ipc.Gateway
c.Routes = ipc.Routes
return nil
}
func (r *Route) UnmarshalJSON(data []byte) error {
rt := route{}
if err := json.Unmarshal(data, &rt); err != nil {
return err
}
r.Dst = net.IPNet(rt.Dst)
r.GW = rt.GW
return nil
}
func (r *Route) MarshalJSON() ([]byte, error) {
rt := route{
Dst: IPNet(r.Dst),
GW: r.GW,
}
return json.Marshal(rt)
}
func prettyPrint(obj interface{}) error {
data, err := json.MarshalIndent(obj, "", " ")
if err != nil {
return err
}
_, err = os.Stdout.Write(data)
return err
}

202
vendor/github.com/coreos/go-semver/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

296
vendor/github.com/coreos/go-semver/semver/semver.go generated vendored Normal file
View File

@@ -0,0 +1,296 @@
// Copyright 2013-2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Semantic Versions http://semver.org
package semver
import (
"bytes"
"errors"
"fmt"
"regexp"
"strconv"
"strings"
)
type Version struct {
Major int64
Minor int64
Patch int64
PreRelease PreRelease
Metadata string
}
type PreRelease string
func splitOff(input *string, delim string) (val string) {
parts := strings.SplitN(*input, delim, 2)
if len(parts) == 2 {
*input = parts[0]
val = parts[1]
}
return val
}
func New(version string) *Version {
return Must(NewVersion(version))
}
func NewVersion(version string) (*Version, error) {
v := Version{}
if err := v.Set(version); err != nil {
return nil, err
}
return &v, nil
}
// Must is a helper for wrapping NewVersion and will panic if err is not nil.
func Must(v *Version, err error) *Version {
if err != nil {
panic(err)
}
return v
}
// Set parses and updates v from the given version string. Implements flag.Value
func (v *Version) Set(version string) error {
metadata := splitOff(&version, "+")
preRelease := PreRelease(splitOff(&version, "-"))
dotParts := strings.SplitN(version, ".", 3)
if len(dotParts) != 3 {
return fmt.Errorf("%s is not in dotted-tri format", version)
}
if err := validateIdentifier(string(preRelease)); err != nil {
return fmt.Errorf("failed to validate pre-release: %v", err)
}
if err := validateIdentifier(metadata); err != nil {
return fmt.Errorf("failed to validate metadata: %v", err)
}
parsed := make([]int64, 3, 3)
for i, v := range dotParts[:3] {
val, err := strconv.ParseInt(v, 10, 64)
parsed[i] = val
if err != nil {
return err
}
}
v.Metadata = metadata
v.PreRelease = preRelease
v.Major = parsed[0]
v.Minor = parsed[1]
v.Patch = parsed[2]
return nil
}
func (v Version) String() string {
var buffer bytes.Buffer
fmt.Fprintf(&buffer, "%d.%d.%d", v.Major, v.Minor, v.Patch)
if v.PreRelease != "" {
fmt.Fprintf(&buffer, "-%s", v.PreRelease)
}
if v.Metadata != "" {
fmt.Fprintf(&buffer, "+%s", v.Metadata)
}
return buffer.String()
}
func (v *Version) UnmarshalYAML(unmarshal func(interface{}) error) error {
var data string
if err := unmarshal(&data); err != nil {
return err
}
return v.Set(data)
}
func (v Version) MarshalJSON() ([]byte, error) {
return []byte(`"` + v.String() + `"`), nil
}
func (v *Version) UnmarshalJSON(data []byte) error {
l := len(data)
if l == 0 || string(data) == `""` {
return nil
}
if l < 2 || data[0] != '"' || data[l-1] != '"' {
return errors.New("invalid semver string")
}
return v.Set(string(data[1 : l-1]))
}
// Compare tests if v is less than, equal to, or greater than versionB,
// returning -1, 0, or +1 respectively.
func (v Version) Compare(versionB Version) int {
if cmp := recursiveCompare(v.Slice(), versionB.Slice()); cmp != 0 {
return cmp
}
return preReleaseCompare(v, versionB)
}
// Equal tests if v is equal to versionB.
func (v Version) Equal(versionB Version) bool {
return v.Compare(versionB) == 0
}
// LessThan tests if v is less than versionB.
func (v Version) LessThan(versionB Version) bool {
return v.Compare(versionB) < 0
}
// Slice converts the comparable parts of the semver into a slice of integers.
func (v Version) Slice() []int64 {
return []int64{v.Major, v.Minor, v.Patch}
}
func (p PreRelease) Slice() []string {
preRelease := string(p)
return strings.Split(preRelease, ".")
}
func preReleaseCompare(versionA Version, versionB Version) int {
a := versionA.PreRelease
b := versionB.PreRelease
/* Handle the case where if two versions are otherwise equal it is the
* one without a PreRelease that is greater */
if len(a) == 0 && (len(b) > 0) {
return 1
} else if len(b) == 0 && (len(a) > 0) {
return -1
}
// If there is a prerelease, check and compare each part.
return recursivePreReleaseCompare(a.Slice(), b.Slice())
}
func recursiveCompare(versionA []int64, versionB []int64) int {
if len(versionA) == 0 {
return 0
}
a := versionA[0]
b := versionB[0]
if a > b {
return 1
} else if a < b {
return -1
}
return recursiveCompare(versionA[1:], versionB[1:])
}
func recursivePreReleaseCompare(versionA []string, versionB []string) int {
// A larger set of pre-release fields has a higher precedence than a smaller set,
// if all of the preceding identifiers are equal.
if len(versionA) == 0 {
if len(versionB) > 0 {
return -1
}
return 0
} else if len(versionB) == 0 {
// We're longer than versionB so return 1.
return 1
}
a := versionA[0]
b := versionB[0]
aInt := false
bInt := false
aI, err := strconv.Atoi(versionA[0])
if err == nil {
aInt = true
}
bI, err := strconv.Atoi(versionB[0])
if err == nil {
bInt = true
}
// Numeric identifiers always have lower precedence than non-numeric identifiers.
if aInt && !bInt {
return -1
} else if !aInt && bInt {
return 1
}
// Handle Integer Comparison
if aInt && bInt {
if aI > bI {
return 1
} else if aI < bI {
return -1
}
}
// Handle String Comparison
if a > b {
return 1
} else if a < b {
return -1
}
return recursivePreReleaseCompare(versionA[1:], versionB[1:])
}
// BumpMajor increments the Major field by 1 and resets all other fields to their default values
func (v *Version) BumpMajor() {
v.Major += 1
v.Minor = 0
v.Patch = 0
v.PreRelease = PreRelease("")
v.Metadata = ""
}
// BumpMinor increments the Minor field by 1 and resets all other fields to their default values
func (v *Version) BumpMinor() {
v.Minor += 1
v.Patch = 0
v.PreRelease = PreRelease("")
v.Metadata = ""
}
// BumpPatch increments the Patch field by 1 and resets all other fields to their default values
func (v *Version) BumpPatch() {
v.Patch += 1
v.PreRelease = PreRelease("")
v.Metadata = ""
}
// validateIdentifier makes sure the provided identifier satisfies semver spec
func validateIdentifier(id string) error {
if id != "" && !reIdentifier.MatchString(id) {
return fmt.Errorf("%s is not a valid semver identifier", id)
}
return nil
}
// reIdentifier is a regular expression used to check that pre-release and metadata
// identifiers satisfy the spec requirements
var reIdentifier = regexp.MustCompile(`^[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*$`)

38
vendor/github.com/coreos/go-semver/semver/sort.go generated vendored Normal file
View File

@@ -0,0 +1,38 @@
// Copyright 2013-2015 CoreOS, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package semver
import (
"sort"
)
type Versions []*Version
func (s Versions) Len() int {
return len(s)
}
func (s Versions) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s Versions) Less(i, j int) bool {
return s[i].LessThan(*s[j])
}
// Sort sorts the given slice of Version
func Sort(versions []*Version) {
sort.Sort(Versions(versions))
}

201
vendor/github.com/rkt/rkt/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

102
vendor/github.com/rkt/rkt/api/v1/json.go generated vendored Normal file
View File

@@ -0,0 +1,102 @@
// Copyright 2016 The rkt Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package v1
import "github.com/rkt/rkt/networking/netinfo"
// AppState defines the state of the app.
type AppState string
const (
AppStateUnknown AppState = "unknown"
AppStateCreated AppState = "created"
AppStateRunning AppState = "running"
AppStateExited AppState = "exited"
)
type (
// Mount defines the mount point.
Mount struct {
// Name of the mount.
Name string `json:"name"`
// Container path of the mount.
ContainerPath string `json:"container_path"`
// Host path of the mount.
HostPath string `json:"host_path"`
// Whether the mount is read-only.
ReadOnly bool `json:"read_only"`
// TODO(yifan): What about 'SelinuxRelabel bool'?
}
// App defines the app object.
App struct {
// Name of the app.
Name string `json:"name"`
// State of the app, can be created, running, exited, or unknown.
State AppState `json:"state"`
// Creation time of the container, nanoseconds since epoch.
CreatedAt *int64 `json:"created_at,omitempty"`
// Start time of the container, nanoseconds since epoch.
StartedAt *int64 `json:"started_at,omitempty"`
// Finish time of the container, nanoseconds since epoch.
FinishedAt *int64 `json:"finished_at,omitempty"`
// Exit code of the container.
ExitCode *int32 `json:"exit_code,omitempty"`
// Image ID of the container.
ImageID string `json:"image_id"`
// Mount points of the container.
Mounts []*Mount `json:"mounts,omitempty"`
// User annotations of the container.
UserAnnotations map[string]string `json:"user_annotations,omitempty"`
// User labels of the container.
UserLabels map[string]string `json:"user_labels,omitempty"`
}
// Pod defines the pod object.
Pod struct {
// UUID of the pod.
UUID string `json:"name"`
// State of the pod, all valid values are defined in pkg/pod/pods.go.
State string `json:"state"`
// Networks are the information of the networks.
Networks []netinfo.NetInfo `json:"networks,omitempty"`
// AppNames are the names of the apps.
// Deprecated: use Apps instead.
AppNames []string `json:"app_names,omitempty"`
// Apps holds current information about each app.
Apps []*App `json:"apps,omitempty"`
// The start time of the pod.
StartedAt *int64 `json:"started_at,omitempty"`
// UserAnnotations are the pod user annotations.
UserAnnotations map[string]string `json:"user_annotations,omitempty"`
// UserLabels are the pod user labels.
UserLabels map[string]string `json:"user_labels,omitempty"`
}
ImageListEntry struct {
// ID is the Image ID for this image
ID string `json:"id"`
// Name is the name of this image, such as example.com/some/image
Name string `json:"name"`
// ImportTime indicates when this image was imported in nanoseconds
// since the unix epoch
ImportTime int64 `json:"import_time"`
// LastUsedTime indicates when was last used in nanoseconds since the
// unix epoch
LastUsedTime int64 `json:"last_used_time"`
// Size is the size of this image in bytes
Size int64 `json:"size"`
}
)

View File

@@ -0,0 +1,80 @@
// Copyright 2015 The rkt Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package netinfo
import (
"encoding/json"
"net"
"os"
"path/filepath"
"syscall"
"github.com/containernetworking/cni/pkg/types"
)
const filename = "net-info.json"
// A type and some structure to represent rkt's view of a *runtime*
// network instance.
//
// Each instance represents a network configuration that has been enabled,
// along with runtime information from the network plugin.
//
// This information is also serialized in the pod's runtime directory so that
// `rkt list` and other stage0 programs can access the runtime state.
type NetInfo struct {
NetName string `json:"netName"`
ConfPath string `json:"netConf"`
PluginPath string `json:"pluginPath"`
IfName string `json:"ifName"`
IP net.IP `json:"ip"`
Args string `json:"args"`
Mask net.IP `json:"mask"` // we used IP instead of IPMask because support for json serialization (we don't need specific functionalities)
HostIP net.IP `json:"-"`
IP4 *types.IPConfig `json:"-"`
DNS types.DNS `json:"-"`
}
func LoadAt(cdirfd int) ([]NetInfo, error) {
fd, err := syscall.Openat(cdirfd, filename, syscall.O_RDONLY, 0)
if err != nil {
return nil, err
}
f := os.NewFile(uintptr(fd), filename)
var info []NetInfo
err = json.NewDecoder(f).Decode(&info)
return info, err
}
func Save(root string, info []NetInfo) error {
f, err := os.Create(filepath.Join(root, filename))
if err != nil {
return err
}
defer f.Close()
return json.NewEncoder(f).Encode(info)
}
// MergeCNIResult will incorporate the result of a CNI plugin's execution
func (ni *NetInfo) MergeCNIResult(result types.Result) {
ni.IP = result.IP4.IP.IP
ni.Mask = net.IP(result.IP4.IP.Mask)
ni.HostIP = result.IP4.Gateway
ni.IP4 = result.IP4
ni.DNS = result.DNS
}

28
vendor/github.com/spf13/pflag/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,28 @@
Copyright (c) 2012 Alex Ogier. All rights reserved.
Copyright (c) 2012 The Go Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

296
vendor/github.com/spf13/pflag/README.md generated vendored Normal file
View File

@@ -0,0 +1,296 @@
[![Build Status](https://travis-ci.org/spf13/pflag.svg?branch=master)](https://travis-ci.org/spf13/pflag)
[![Go Report Card](https://goreportcard.com/badge/github.com/spf13/pflag)](https://goreportcard.com/report/github.com/spf13/pflag)
[![GoDoc](https://godoc.org/github.com/spf13/pflag?status.svg)](https://godoc.org/github.com/spf13/pflag)
## Description
pflag is a drop-in replacement for Go's flag package, implementing
POSIX/GNU-style --flags.
pflag is compatible with the [GNU extensions to the POSIX recommendations
for command-line options][1]. For a more precise description, see the
"Command-line flag syntax" section below.
[1]: http://www.gnu.org/software/libc/manual/html_node/Argument-Syntax.html
pflag is available under the same style of BSD license as the Go language,
which can be found in the LICENSE file.
## Installation
pflag is available using the standard `go get` command.
Install by running:
go get github.com/spf13/pflag
Run tests by running:
go test github.com/spf13/pflag
## Usage
pflag is a drop-in replacement of Go's native flag package. If you import
pflag under the name "flag" then all code should continue to function
with no changes.
``` go
import flag "github.com/spf13/pflag"
```
There is one exception to this: if you directly instantiate the Flag struct
there is one more field "Shorthand" that you will need to set.
Most code never instantiates this struct directly, and instead uses
functions such as String(), BoolVar(), and Var(), and is therefore
unaffected.
Define flags using flag.String(), Bool(), Int(), etc.
This declares an integer flag, -flagname, stored in the pointer ip, with type *int.
``` go
var ip *int = flag.Int("flagname", 1234, "help message for flagname")
```
If you like, you can bind the flag to a variable using the Var() functions.
``` go
var flagvar int
func init() {
flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
}
```
Or you can create custom flags that satisfy the Value interface (with
pointer receivers) and couple them to flag parsing by
``` go
flag.Var(&flagVal, "name", "help message for flagname")
```
For such flags, the default value is just the initial value of the variable.
After all flags are defined, call
``` go
flag.Parse()
```
to parse the command line into the defined flags.
Flags may then be used directly. If you're using the flags themselves,
they are all pointers; if you bind to variables, they're values.
``` go
fmt.Println("ip has value ", *ip)
fmt.Println("flagvar has value ", flagvar)
```
There are helpers function to get values later if you have the FlagSet but
it was difficult to keep up with all of the flag pointers in your code.
If you have a pflag.FlagSet with a flag called 'flagname' of type int you
can use GetInt() to get the int value. But notice that 'flagname' must exist
and it must be an int. GetString("flagname") will fail.
``` go
i, err := flagset.GetInt("flagname")
```
After parsing, the arguments after the flag are available as the
slice flag.Args() or individually as flag.Arg(i).
The arguments are indexed from 0 through flag.NArg()-1.
The pflag package also defines some new functions that are not in flag,
that give one-letter shorthands for flags. You can use these by appending
'P' to the name of any function that defines a flag.
``` go
var ip = flag.IntP("flagname", "f", 1234, "help message")
var flagvar bool
func init() {
flag.BoolVarP(&flagvar, "boolname", "b", true, "help message")
}
flag.VarP(&flagVal, "varname", "v", "help message")
```
Shorthand letters can be used with single dashes on the command line.
Boolean shorthand flags can be combined with other shorthand flags.
The default set of command-line flags is controlled by
top-level functions. The FlagSet type allows one to define
independent sets of flags, such as to implement subcommands
in a command-line interface. The methods of FlagSet are
analogous to the top-level functions for the command-line
flag set.
## Setting no option default values for flags
After you create a flag it is possible to set the pflag.NoOptDefVal for
the given flag. Doing this changes the meaning of the flag slightly. If
a flag has a NoOptDefVal and the flag is set on the command line without
an option the flag will be set to the NoOptDefVal. For example given:
``` go
var ip = flag.IntP("flagname", "f", 1234, "help message")
flag.Lookup("flagname").NoOptDefVal = "4321"
```
Would result in something like
| Parsed Arguments | Resulting Value |
| ------------- | ------------- |
| --flagname=1357 | ip=1357 |
| --flagname | ip=4321 |
| [nothing] | ip=1234 |
## Command line flag syntax
```
--flag // boolean flags, or flags with no option default values
--flag x // only on flags without a default value
--flag=x
```
Unlike the flag package, a single dash before an option means something
different than a double dash. Single dashes signify a series of shorthand
letters for flags. All but the last shorthand letter must be boolean flags
or a flag with a default value
```
// boolean or flags where the 'no option default value' is set
-f
-f=true
-abc
but
-b true is INVALID
// non-boolean and flags without a 'no option default value'
-n 1234
-n=1234
-n1234
// mixed
-abcs "hello"
-absd="hello"
-abcs1234
```
Flag parsing stops after the terminator "--". Unlike the flag package,
flags can be interspersed with arguments anywhere on the command line
before this terminator.
Integer flags accept 1234, 0664, 0x1234 and may be negative.
Boolean flags (in their long form) accept 1, 0, t, f, true, false,
TRUE, FALSE, True, False.
Duration flags accept any input valid for time.ParseDuration.
## Mutating or "Normalizing" Flag names
It is possible to set a custom flag name 'normalization function.' It allows flag names to be mutated both when created in the code and when used on the command line to some 'normalized' form. The 'normalized' form is used for comparison. Two examples of using the custom normalization func follow.
**Example #1**: You want -, _, and . in flags to compare the same. aka --my-flag == --my_flag == --my.flag
``` go
func wordSepNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
from := []string{"-", "_"}
to := "."
for _, sep := range from {
name = strings.Replace(name, sep, to, -1)
}
return pflag.NormalizedName(name)
}
myFlagSet.SetNormalizeFunc(wordSepNormalizeFunc)
```
**Example #2**: You want to alias two flags. aka --old-flag-name == --new-flag-name
``` go
func aliasNormalizeFunc(f *pflag.FlagSet, name string) pflag.NormalizedName {
switch name {
case "old-flag-name":
name = "new-flag-name"
break
}
return pflag.NormalizedName(name)
}
myFlagSet.SetNormalizeFunc(aliasNormalizeFunc)
```
## Deprecating a flag or its shorthand
It is possible to deprecate a flag, or just its shorthand. Deprecating a flag/shorthand hides it from help text and prints a usage message when the deprecated flag/shorthand is used.
**Example #1**: You want to deprecate a flag named "badflag" as well as inform the users what flag they should use instead.
```go
// deprecate a flag by specifying its name and a usage message
flags.MarkDeprecated("badflag", "please use --good-flag instead")
```
This hides "badflag" from help text, and prints `Flag --badflag has been deprecated, please use --good-flag instead` when "badflag" is used.
**Example #2**: You want to keep a flag name "noshorthandflag" but deprecate its shortname "n".
```go
// deprecate a flag shorthand by specifying its flag name and a usage message
flags.MarkShorthandDeprecated("noshorthandflag", "please use --noshorthandflag only")
```
This hides the shortname "n" from help text, and prints `Flag shorthand -n has been deprecated, please use --noshorthandflag only` when the shorthand "n" is used.
Note that usage message is essential here, and it should not be empty.
## Hidden flags
It is possible to mark a flag as hidden, meaning it will still function as normal, however will not show up in usage/help text.
**Example**: You have a flag named "secretFlag" that you need for internal use only and don't want it showing up in help text, or for its usage text to be available.
```go
// hide a flag by specifying its name
flags.MarkHidden("secretFlag")
```
## Disable sorting of flags
`pflag` allows you to disable sorting of flags for help and usage message.
**Example**:
```go
flags.BoolP("verbose", "v", false, "verbose output")
flags.String("coolflag", "yeaah", "it's really cool flag")
flags.Int("usefulflag", 777, "sometimes it's very useful")
flags.SortFlags = false
flags.PrintDefaults()
```
**Output**:
```
-v, --verbose verbose output
--coolflag string it's really cool flag (default "yeaah")
--usefulflag int sometimes it's very useful (default 777)
```
## Supporting Go flags when using pflag
In order to support flags defined using Go's `flag` package, they must be added to the `pflag` flagset. This is usually necessary
to support flags defined by third-party dependencies (e.g. `golang/glog`).
**Example**: You want to add the Go flags to the `CommandLine` flagset
```go
import (
goflag "flag"
flag "github.com/spf13/pflag"
)
var ip *int = flag.Int("flagname", 1234, "help message for flagname")
func main() {
flag.CommandLine.AddGoFlagSet(goflag.CommandLine)
flag.Parse()
}
```
## More info
You can see the full reference documentation of the pflag package
[at godoc.org][3], or through go's standard documentation system by
running `godoc -http=:6060` and browsing to
[http://localhost:6060/pkg/github.com/spf13/pflag][2] after
installation.
[2]: http://localhost:6060/pkg/github.com/spf13/pflag
[3]: http://godoc.org/github.com/spf13/pflag

94
vendor/github.com/spf13/pflag/bool.go generated vendored Normal file
View File

@@ -0,0 +1,94 @@
package pflag
import "strconv"
// optional interface to indicate boolean flags that can be
// supplied without "=value" text
type boolFlag interface {
Value
IsBoolFlag() bool
}
// -- bool Value
type boolValue bool
func newBoolValue(val bool, p *bool) *boolValue {
*p = val
return (*boolValue)(p)
}
func (b *boolValue) Set(s string) error {
v, err := strconv.ParseBool(s)
*b = boolValue(v)
return err
}
func (b *boolValue) Type() string {
return "bool"
}
func (b *boolValue) String() string { return strconv.FormatBool(bool(*b)) }
func (b *boolValue) IsBoolFlag() bool { return true }
func boolConv(sval string) (interface{}, error) {
return strconv.ParseBool(sval)
}
// GetBool return the bool value of a flag with the given name
func (f *FlagSet) GetBool(name string) (bool, error) {
val, err := f.getFlagType(name, "bool", boolConv)
if err != nil {
return false, err
}
return val.(bool), nil
}
// BoolVar defines a bool flag with specified name, default value, and usage string.
// The argument p points to a bool variable in which to store the value of the flag.
func (f *FlagSet) BoolVar(p *bool, name string, value bool, usage string) {
f.BoolVarP(p, name, "", value, usage)
}
// BoolVarP is like BoolVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) BoolVarP(p *bool, name, shorthand string, value bool, usage string) {
flag := f.VarPF(newBoolValue(value, p), name, shorthand, usage)
flag.NoOptDefVal = "true"
}
// BoolVar defines a bool flag with specified name, default value, and usage string.
// The argument p points to a bool variable in which to store the value of the flag.
func BoolVar(p *bool, name string, value bool, usage string) {
BoolVarP(p, name, "", value, usage)
}
// BoolVarP is like BoolVar, but accepts a shorthand letter that can be used after a single dash.
func BoolVarP(p *bool, name, shorthand string, value bool, usage string) {
flag := CommandLine.VarPF(newBoolValue(value, p), name, shorthand, usage)
flag.NoOptDefVal = "true"
}
// Bool defines a bool flag with specified name, default value, and usage string.
// The return value is the address of a bool variable that stores the value of the flag.
func (f *FlagSet) Bool(name string, value bool, usage string) *bool {
return f.BoolP(name, "", value, usage)
}
// BoolP is like Bool, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) BoolP(name, shorthand string, value bool, usage string) *bool {
p := new(bool)
f.BoolVarP(p, name, shorthand, value, usage)
return p
}
// Bool defines a bool flag with specified name, default value, and usage string.
// The return value is the address of a bool variable that stores the value of the flag.
func Bool(name string, value bool, usage string) *bool {
return BoolP(name, "", value, usage)
}
// BoolP is like Bool, but accepts a shorthand letter that can be used after a single dash.
func BoolP(name, shorthand string, value bool, usage string) *bool {
b := CommandLine.BoolP(name, shorthand, value, usage)
return b
}

147
vendor/github.com/spf13/pflag/bool_slice.go generated vendored Normal file
View File

@@ -0,0 +1,147 @@
package pflag
import (
"io"
"strconv"
"strings"
)
// -- boolSlice Value
type boolSliceValue struct {
value *[]bool
changed bool
}
func newBoolSliceValue(val []bool, p *[]bool) *boolSliceValue {
bsv := new(boolSliceValue)
bsv.value = p
*bsv.value = val
return bsv
}
// Set converts, and assigns, the comma-separated boolean argument string representation as the []bool value of this flag.
// If Set is called on a flag that already has a []bool assigned, the newly converted values will be appended.
func (s *boolSliceValue) Set(val string) error {
// remove all quote characters
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
// read flag arguments with CSV parser
boolStrSlice, err := readAsCSV(rmQuote.Replace(val))
if err != nil && err != io.EOF {
return err
}
// parse boolean values into slice
out := make([]bool, 0, len(boolStrSlice))
for _, boolStr := range boolStrSlice {
b, err := strconv.ParseBool(strings.TrimSpace(boolStr))
if err != nil {
return err
}
out = append(out, b)
}
if !s.changed {
*s.value = out
} else {
*s.value = append(*s.value, out...)
}
s.changed = true
return nil
}
// Type returns a string that uniquely represents this flag's type.
func (s *boolSliceValue) Type() string {
return "boolSlice"
}
// String defines a "native" format for this boolean slice flag value.
func (s *boolSliceValue) String() string {
boolStrSlice := make([]string, len(*s.value))
for i, b := range *s.value {
boolStrSlice[i] = strconv.FormatBool(b)
}
out, _ := writeAsCSV(boolStrSlice)
return "[" + out + "]"
}
func boolSliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// Empty string would cause a slice with one (empty) entry
if len(val) == 0 {
return []bool{}, nil
}
ss := strings.Split(val, ",")
out := make([]bool, len(ss))
for i, t := range ss {
var err error
out[i], err = strconv.ParseBool(t)
if err != nil {
return nil, err
}
}
return out, nil
}
// GetBoolSlice returns the []bool value of a flag with the given name.
func (f *FlagSet) GetBoolSlice(name string) ([]bool, error) {
val, err := f.getFlagType(name, "boolSlice", boolSliceConv)
if err != nil {
return []bool{}, err
}
return val.([]bool), nil
}
// BoolSliceVar defines a boolSlice flag with specified name, default value, and usage string.
// The argument p points to a []bool variable in which to store the value of the flag.
func (f *FlagSet) BoolSliceVar(p *[]bool, name string, value []bool, usage string) {
f.VarP(newBoolSliceValue(value, p), name, "", usage)
}
// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) {
f.VarP(newBoolSliceValue(value, p), name, shorthand, usage)
}
// BoolSliceVar defines a []bool flag with specified name, default value, and usage string.
// The argument p points to a []bool variable in which to store the value of the flag.
func BoolSliceVar(p *[]bool, name string, value []bool, usage string) {
CommandLine.VarP(newBoolSliceValue(value, p), name, "", usage)
}
// BoolSliceVarP is like BoolSliceVar, but accepts a shorthand letter that can be used after a single dash.
func BoolSliceVarP(p *[]bool, name, shorthand string, value []bool, usage string) {
CommandLine.VarP(newBoolSliceValue(value, p), name, shorthand, usage)
}
// BoolSlice defines a []bool flag with specified name, default value, and usage string.
// The return value is the address of a []bool variable that stores the value of the flag.
func (f *FlagSet) BoolSlice(name string, value []bool, usage string) *[]bool {
p := []bool{}
f.BoolSliceVarP(&p, name, "", value, usage)
return &p
}
// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool {
p := []bool{}
f.BoolSliceVarP(&p, name, shorthand, value, usage)
return &p
}
// BoolSlice defines a []bool flag with specified name, default value, and usage string.
// The return value is the address of a []bool variable that stores the value of the flag.
func BoolSlice(name string, value []bool, usage string) *[]bool {
return CommandLine.BoolSliceP(name, "", value, usage)
}
// BoolSliceP is like BoolSlice, but accepts a shorthand letter that can be used after a single dash.
func BoolSliceP(name, shorthand string, value []bool, usage string) *[]bool {
return CommandLine.BoolSliceP(name, shorthand, value, usage)
}

96
vendor/github.com/spf13/pflag/count.go generated vendored Normal file
View File

@@ -0,0 +1,96 @@
package pflag
import "strconv"
// -- count Value
type countValue int
func newCountValue(val int, p *int) *countValue {
*p = val
return (*countValue)(p)
}
func (i *countValue) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 64)
// -1 means that no specific value was passed, so increment
if v == -1 {
*i = countValue(*i + 1)
} else {
*i = countValue(v)
}
return err
}
func (i *countValue) Type() string {
return "count"
}
func (i *countValue) String() string { return strconv.Itoa(int(*i)) }
func countConv(sval string) (interface{}, error) {
i, err := strconv.Atoi(sval)
if err != nil {
return nil, err
}
return i, nil
}
// GetCount return the int value of a flag with the given name
func (f *FlagSet) GetCount(name string) (int, error) {
val, err := f.getFlagType(name, "count", countConv)
if err != nil {
return 0, err
}
return val.(int), nil
}
// CountVar defines a count flag with specified name, default value, and usage string.
// The argument p points to an int variable in which to store the value of the flag.
// A count flag will add 1 to its value evey time it is found on the command line
func (f *FlagSet) CountVar(p *int, name string, usage string) {
f.CountVarP(p, name, "", usage)
}
// CountVarP is like CountVar only take a shorthand for the flag name.
func (f *FlagSet) CountVarP(p *int, name, shorthand string, usage string) {
flag := f.VarPF(newCountValue(0, p), name, shorthand, usage)
flag.NoOptDefVal = "-1"
}
// CountVar like CountVar only the flag is placed on the CommandLine instead of a given flag set
func CountVar(p *int, name string, usage string) {
CommandLine.CountVar(p, name, usage)
}
// CountVarP is like CountVar only take a shorthand for the flag name.
func CountVarP(p *int, name, shorthand string, usage string) {
CommandLine.CountVarP(p, name, shorthand, usage)
}
// Count defines a count flag with specified name, default value, and usage string.
// The return value is the address of an int variable that stores the value of the flag.
// A count flag will add 1 to its value evey time it is found on the command line
func (f *FlagSet) Count(name string, usage string) *int {
p := new(int)
f.CountVarP(p, name, "", usage)
return p
}
// CountP is like Count only takes a shorthand for the flag name.
func (f *FlagSet) CountP(name, shorthand string, usage string) *int {
p := new(int)
f.CountVarP(p, name, shorthand, usage)
return p
}
// Count defines a count flag with specified name, default value, and usage string.
// The return value is the address of an int variable that stores the value of the flag.
// A count flag will add 1 to its value evey time it is found on the command line
func Count(name string, usage string) *int {
return CommandLine.CountP(name, "", usage)
}
// CountP is like Count only takes a shorthand for the flag name.
func CountP(name, shorthand string, usage string) *int {
return CommandLine.CountP(name, shorthand, usage)
}

86
vendor/github.com/spf13/pflag/duration.go generated vendored Normal file
View File

@@ -0,0 +1,86 @@
package pflag
import (
"time"
)
// -- time.Duration Value
type durationValue time.Duration
func newDurationValue(val time.Duration, p *time.Duration) *durationValue {
*p = val
return (*durationValue)(p)
}
func (d *durationValue) Set(s string) error {
v, err := time.ParseDuration(s)
*d = durationValue(v)
return err
}
func (d *durationValue) Type() string {
return "duration"
}
func (d *durationValue) String() string { return (*time.Duration)(d).String() }
func durationConv(sval string) (interface{}, error) {
return time.ParseDuration(sval)
}
// GetDuration return the duration value of a flag with the given name
func (f *FlagSet) GetDuration(name string) (time.Duration, error) {
val, err := f.getFlagType(name, "duration", durationConv)
if err != nil {
return 0, err
}
return val.(time.Duration), nil
}
// DurationVar defines a time.Duration flag with specified name, default value, and usage string.
// The argument p points to a time.Duration variable in which to store the value of the flag.
func (f *FlagSet) DurationVar(p *time.Duration, name string, value time.Duration, usage string) {
f.VarP(newDurationValue(value, p), name, "", usage)
}
// DurationVarP is like DurationVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) DurationVarP(p *time.Duration, name, shorthand string, value time.Duration, usage string) {
f.VarP(newDurationValue(value, p), name, shorthand, usage)
}
// DurationVar defines a time.Duration flag with specified name, default value, and usage string.
// The argument p points to a time.Duration variable in which to store the value of the flag.
func DurationVar(p *time.Duration, name string, value time.Duration, usage string) {
CommandLine.VarP(newDurationValue(value, p), name, "", usage)
}
// DurationVarP is like DurationVar, but accepts a shorthand letter that can be used after a single dash.
func DurationVarP(p *time.Duration, name, shorthand string, value time.Duration, usage string) {
CommandLine.VarP(newDurationValue(value, p), name, shorthand, usage)
}
// Duration defines a time.Duration flag with specified name, default value, and usage string.
// The return value is the address of a time.Duration variable that stores the value of the flag.
func (f *FlagSet) Duration(name string, value time.Duration, usage string) *time.Duration {
p := new(time.Duration)
f.DurationVarP(p, name, "", value, usage)
return p
}
// DurationP is like Duration, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) DurationP(name, shorthand string, value time.Duration, usage string) *time.Duration {
p := new(time.Duration)
f.DurationVarP(p, name, shorthand, value, usage)
return p
}
// Duration defines a time.Duration flag with specified name, default value, and usage string.
// The return value is the address of a time.Duration variable that stores the value of the flag.
func Duration(name string, value time.Duration, usage string) *time.Duration {
return CommandLine.DurationP(name, "", value, usage)
}
// DurationP is like Duration, but accepts a shorthand letter that can be used after a single dash.
func DurationP(name, shorthand string, value time.Duration, usage string) *time.Duration {
return CommandLine.DurationP(name, shorthand, value, usage)
}

1132
vendor/github.com/spf13/pflag/flag.go generated vendored Normal file

File diff suppressed because it is too large Load Diff

88
vendor/github.com/spf13/pflag/float32.go generated vendored Normal file
View File

@@ -0,0 +1,88 @@
package pflag
import "strconv"
// -- float32 Value
type float32Value float32
func newFloat32Value(val float32, p *float32) *float32Value {
*p = val
return (*float32Value)(p)
}
func (f *float32Value) Set(s string) error {
v, err := strconv.ParseFloat(s, 32)
*f = float32Value(v)
return err
}
func (f *float32Value) Type() string {
return "float32"
}
func (f *float32Value) String() string { return strconv.FormatFloat(float64(*f), 'g', -1, 32) }
func float32Conv(sval string) (interface{}, error) {
v, err := strconv.ParseFloat(sval, 32)
if err != nil {
return 0, err
}
return float32(v), nil
}
// GetFloat32 return the float32 value of a flag with the given name
func (f *FlagSet) GetFloat32(name string) (float32, error) {
val, err := f.getFlagType(name, "float32", float32Conv)
if err != nil {
return 0, err
}
return val.(float32), nil
}
// Float32Var defines a float32 flag with specified name, default value, and usage string.
// The argument p points to a float32 variable in which to store the value of the flag.
func (f *FlagSet) Float32Var(p *float32, name string, value float32, usage string) {
f.VarP(newFloat32Value(value, p), name, "", usage)
}
// Float32VarP is like Float32Var, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Float32VarP(p *float32, name, shorthand string, value float32, usage string) {
f.VarP(newFloat32Value(value, p), name, shorthand, usage)
}
// Float32Var defines a float32 flag with specified name, default value, and usage string.
// The argument p points to a float32 variable in which to store the value of the flag.
func Float32Var(p *float32, name string, value float32, usage string) {
CommandLine.VarP(newFloat32Value(value, p), name, "", usage)
}
// Float32VarP is like Float32Var, but accepts a shorthand letter that can be used after a single dash.
func Float32VarP(p *float32, name, shorthand string, value float32, usage string) {
CommandLine.VarP(newFloat32Value(value, p), name, shorthand, usage)
}
// Float32 defines a float32 flag with specified name, default value, and usage string.
// The return value is the address of a float32 variable that stores the value of the flag.
func (f *FlagSet) Float32(name string, value float32, usage string) *float32 {
p := new(float32)
f.Float32VarP(p, name, "", value, usage)
return p
}
// Float32P is like Float32, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Float32P(name, shorthand string, value float32, usage string) *float32 {
p := new(float32)
f.Float32VarP(p, name, shorthand, value, usage)
return p
}
// Float32 defines a float32 flag with specified name, default value, and usage string.
// The return value is the address of a float32 variable that stores the value of the flag.
func Float32(name string, value float32, usage string) *float32 {
return CommandLine.Float32P(name, "", value, usage)
}
// Float32P is like Float32, but accepts a shorthand letter that can be used after a single dash.
func Float32P(name, shorthand string, value float32, usage string) *float32 {
return CommandLine.Float32P(name, shorthand, value, usage)
}

84
vendor/github.com/spf13/pflag/float64.go generated vendored Normal file
View File

@@ -0,0 +1,84 @@
package pflag
import "strconv"
// -- float64 Value
type float64Value float64
func newFloat64Value(val float64, p *float64) *float64Value {
*p = val
return (*float64Value)(p)
}
func (f *float64Value) Set(s string) error {
v, err := strconv.ParseFloat(s, 64)
*f = float64Value(v)
return err
}
func (f *float64Value) Type() string {
return "float64"
}
func (f *float64Value) String() string { return strconv.FormatFloat(float64(*f), 'g', -1, 64) }
func float64Conv(sval string) (interface{}, error) {
return strconv.ParseFloat(sval, 64)
}
// GetFloat64 return the float64 value of a flag with the given name
func (f *FlagSet) GetFloat64(name string) (float64, error) {
val, err := f.getFlagType(name, "float64", float64Conv)
if err != nil {
return 0, err
}
return val.(float64), nil
}
// Float64Var defines a float64 flag with specified name, default value, and usage string.
// The argument p points to a float64 variable in which to store the value of the flag.
func (f *FlagSet) Float64Var(p *float64, name string, value float64, usage string) {
f.VarP(newFloat64Value(value, p), name, "", usage)
}
// Float64VarP is like Float64Var, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Float64VarP(p *float64, name, shorthand string, value float64, usage string) {
f.VarP(newFloat64Value(value, p), name, shorthand, usage)
}
// Float64Var defines a float64 flag with specified name, default value, and usage string.
// The argument p points to a float64 variable in which to store the value of the flag.
func Float64Var(p *float64, name string, value float64, usage string) {
CommandLine.VarP(newFloat64Value(value, p), name, "", usage)
}
// Float64VarP is like Float64Var, but accepts a shorthand letter that can be used after a single dash.
func Float64VarP(p *float64, name, shorthand string, value float64, usage string) {
CommandLine.VarP(newFloat64Value(value, p), name, shorthand, usage)
}
// Float64 defines a float64 flag with specified name, default value, and usage string.
// The return value is the address of a float64 variable that stores the value of the flag.
func (f *FlagSet) Float64(name string, value float64, usage string) *float64 {
p := new(float64)
f.Float64VarP(p, name, "", value, usage)
return p
}
// Float64P is like Float64, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Float64P(name, shorthand string, value float64, usage string) *float64 {
p := new(float64)
f.Float64VarP(p, name, shorthand, value, usage)
return p
}
// Float64 defines a float64 flag with specified name, default value, and usage string.
// The return value is the address of a float64 variable that stores the value of the flag.
func Float64(name string, value float64, usage string) *float64 {
return CommandLine.Float64P(name, "", value, usage)
}
// Float64P is like Float64, but accepts a shorthand letter that can be used after a single dash.
func Float64P(name, shorthand string, value float64, usage string) *float64 {
return CommandLine.Float64P(name, shorthand, value, usage)
}

101
vendor/github.com/spf13/pflag/golangflag.go generated vendored Normal file
View File

@@ -0,0 +1,101 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package pflag
import (
goflag "flag"
"reflect"
"strings"
)
// flagValueWrapper implements pflag.Value around a flag.Value. The main
// difference here is the addition of the Type method that returns a string
// name of the type. As this is generally unknown, we approximate that with
// reflection.
type flagValueWrapper struct {
inner goflag.Value
flagType string
}
// We are just copying the boolFlag interface out of goflag as that is what
// they use to decide if a flag should get "true" when no arg is given.
type goBoolFlag interface {
goflag.Value
IsBoolFlag() bool
}
func wrapFlagValue(v goflag.Value) Value {
// If the flag.Value happens to also be a pflag.Value, just use it directly.
if pv, ok := v.(Value); ok {
return pv
}
pv := &flagValueWrapper{
inner: v,
}
t := reflect.TypeOf(v)
if t.Kind() == reflect.Interface || t.Kind() == reflect.Ptr {
t = t.Elem()
}
pv.flagType = strings.TrimSuffix(t.Name(), "Value")
return pv
}
func (v *flagValueWrapper) String() string {
return v.inner.String()
}
func (v *flagValueWrapper) Set(s string) error {
return v.inner.Set(s)
}
func (v *flagValueWrapper) Type() string {
return v.flagType
}
// PFlagFromGoFlag will return a *pflag.Flag given a *flag.Flag
// If the *flag.Flag.Name was a single character (ex: `v`) it will be accessiblei
// with both `-v` and `--v` in flags. If the golang flag was more than a single
// character (ex: `verbose`) it will only be accessible via `--verbose`
func PFlagFromGoFlag(goflag *goflag.Flag) *Flag {
// Remember the default value as a string; it won't change.
flag := &Flag{
Name: goflag.Name,
Usage: goflag.Usage,
Value: wrapFlagValue(goflag.Value),
// Looks like golang flags don't set DefValue correctly :-(
//DefValue: goflag.DefValue,
DefValue: goflag.Value.String(),
}
// Ex: if the golang flag was -v, allow both -v and --v to work
if len(flag.Name) == 1 {
flag.Shorthand = flag.Name
}
if fv, ok := goflag.Value.(goBoolFlag); ok && fv.IsBoolFlag() {
flag.NoOptDefVal = "true"
}
return flag
}
// AddGoFlag will add the given *flag.Flag to the pflag.FlagSet
func (f *FlagSet) AddGoFlag(goflag *goflag.Flag) {
if f.Lookup(goflag.Name) != nil {
return
}
newflag := PFlagFromGoFlag(goflag)
f.AddFlag(newflag)
}
// AddGoFlagSet will add the given *flag.FlagSet to the pflag.FlagSet
func (f *FlagSet) AddGoFlagSet(newSet *goflag.FlagSet) {
if newSet == nil {
return
}
newSet.VisitAll(func(goflag *goflag.Flag) {
f.AddGoFlag(goflag)
})
}

84
vendor/github.com/spf13/pflag/int.go generated vendored Normal file
View File

@@ -0,0 +1,84 @@
package pflag
import "strconv"
// -- int Value
type intValue int
func newIntValue(val int, p *int) *intValue {
*p = val
return (*intValue)(p)
}
func (i *intValue) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 64)
*i = intValue(v)
return err
}
func (i *intValue) Type() string {
return "int"
}
func (i *intValue) String() string { return strconv.Itoa(int(*i)) }
func intConv(sval string) (interface{}, error) {
return strconv.Atoi(sval)
}
// GetInt return the int value of a flag with the given name
func (f *FlagSet) GetInt(name string) (int, error) {
val, err := f.getFlagType(name, "int", intConv)
if err != nil {
return 0, err
}
return val.(int), nil
}
// IntVar defines an int flag with specified name, default value, and usage string.
// The argument p points to an int variable in which to store the value of the flag.
func (f *FlagSet) IntVar(p *int, name string, value int, usage string) {
f.VarP(newIntValue(value, p), name, "", usage)
}
// IntVarP is like IntVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) IntVarP(p *int, name, shorthand string, value int, usage string) {
f.VarP(newIntValue(value, p), name, shorthand, usage)
}
// IntVar defines an int flag with specified name, default value, and usage string.
// The argument p points to an int variable in which to store the value of the flag.
func IntVar(p *int, name string, value int, usage string) {
CommandLine.VarP(newIntValue(value, p), name, "", usage)
}
// IntVarP is like IntVar, but accepts a shorthand letter that can be used after a single dash.
func IntVarP(p *int, name, shorthand string, value int, usage string) {
CommandLine.VarP(newIntValue(value, p), name, shorthand, usage)
}
// Int defines an int flag with specified name, default value, and usage string.
// The return value is the address of an int variable that stores the value of the flag.
func (f *FlagSet) Int(name string, value int, usage string) *int {
p := new(int)
f.IntVarP(p, name, "", value, usage)
return p
}
// IntP is like Int, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) IntP(name, shorthand string, value int, usage string) *int {
p := new(int)
f.IntVarP(p, name, shorthand, value, usage)
return p
}
// Int defines an int flag with specified name, default value, and usage string.
// The return value is the address of an int variable that stores the value of the flag.
func Int(name string, value int, usage string) *int {
return CommandLine.IntP(name, "", value, usage)
}
// IntP is like Int, but accepts a shorthand letter that can be used after a single dash.
func IntP(name, shorthand string, value int, usage string) *int {
return CommandLine.IntP(name, shorthand, value, usage)
}

88
vendor/github.com/spf13/pflag/int32.go generated vendored Normal file
View File

@@ -0,0 +1,88 @@
package pflag
import "strconv"
// -- int32 Value
type int32Value int32
func newInt32Value(val int32, p *int32) *int32Value {
*p = val
return (*int32Value)(p)
}
func (i *int32Value) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 32)
*i = int32Value(v)
return err
}
func (i *int32Value) Type() string {
return "int32"
}
func (i *int32Value) String() string { return strconv.FormatInt(int64(*i), 10) }
func int32Conv(sval string) (interface{}, error) {
v, err := strconv.ParseInt(sval, 0, 32)
if err != nil {
return 0, err
}
return int32(v), nil
}
// GetInt32 return the int32 value of a flag with the given name
func (f *FlagSet) GetInt32(name string) (int32, error) {
val, err := f.getFlagType(name, "int32", int32Conv)
if err != nil {
return 0, err
}
return val.(int32), nil
}
// Int32Var defines an int32 flag with specified name, default value, and usage string.
// The argument p points to an int32 variable in which to store the value of the flag.
func (f *FlagSet) Int32Var(p *int32, name string, value int32, usage string) {
f.VarP(newInt32Value(value, p), name, "", usage)
}
// Int32VarP is like Int32Var, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Int32VarP(p *int32, name, shorthand string, value int32, usage string) {
f.VarP(newInt32Value(value, p), name, shorthand, usage)
}
// Int32Var defines an int32 flag with specified name, default value, and usage string.
// The argument p points to an int32 variable in which to store the value of the flag.
func Int32Var(p *int32, name string, value int32, usage string) {
CommandLine.VarP(newInt32Value(value, p), name, "", usage)
}
// Int32VarP is like Int32Var, but accepts a shorthand letter that can be used after a single dash.
func Int32VarP(p *int32, name, shorthand string, value int32, usage string) {
CommandLine.VarP(newInt32Value(value, p), name, shorthand, usage)
}
// Int32 defines an int32 flag with specified name, default value, and usage string.
// The return value is the address of an int32 variable that stores the value of the flag.
func (f *FlagSet) Int32(name string, value int32, usage string) *int32 {
p := new(int32)
f.Int32VarP(p, name, "", value, usage)
return p
}
// Int32P is like Int32, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Int32P(name, shorthand string, value int32, usage string) *int32 {
p := new(int32)
f.Int32VarP(p, name, shorthand, value, usage)
return p
}
// Int32 defines an int32 flag with specified name, default value, and usage string.
// The return value is the address of an int32 variable that stores the value of the flag.
func Int32(name string, value int32, usage string) *int32 {
return CommandLine.Int32P(name, "", value, usage)
}
// Int32P is like Int32, but accepts a shorthand letter that can be used after a single dash.
func Int32P(name, shorthand string, value int32, usage string) *int32 {
return CommandLine.Int32P(name, shorthand, value, usage)
}

84
vendor/github.com/spf13/pflag/int64.go generated vendored Normal file
View File

@@ -0,0 +1,84 @@
package pflag
import "strconv"
// -- int64 Value
type int64Value int64
func newInt64Value(val int64, p *int64) *int64Value {
*p = val
return (*int64Value)(p)
}
func (i *int64Value) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 64)
*i = int64Value(v)
return err
}
func (i *int64Value) Type() string {
return "int64"
}
func (i *int64Value) String() string { return strconv.FormatInt(int64(*i), 10) }
func int64Conv(sval string) (interface{}, error) {
return strconv.ParseInt(sval, 0, 64)
}
// GetInt64 return the int64 value of a flag with the given name
func (f *FlagSet) GetInt64(name string) (int64, error) {
val, err := f.getFlagType(name, "int64", int64Conv)
if err != nil {
return 0, err
}
return val.(int64), nil
}
// Int64Var defines an int64 flag with specified name, default value, and usage string.
// The argument p points to an int64 variable in which to store the value of the flag.
func (f *FlagSet) Int64Var(p *int64, name string, value int64, usage string) {
f.VarP(newInt64Value(value, p), name, "", usage)
}
// Int64VarP is like Int64Var, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Int64VarP(p *int64, name, shorthand string, value int64, usage string) {
f.VarP(newInt64Value(value, p), name, shorthand, usage)
}
// Int64Var defines an int64 flag with specified name, default value, and usage string.
// The argument p points to an int64 variable in which to store the value of the flag.
func Int64Var(p *int64, name string, value int64, usage string) {
CommandLine.VarP(newInt64Value(value, p), name, "", usage)
}
// Int64VarP is like Int64Var, but accepts a shorthand letter that can be used after a single dash.
func Int64VarP(p *int64, name, shorthand string, value int64, usage string) {
CommandLine.VarP(newInt64Value(value, p), name, shorthand, usage)
}
// Int64 defines an int64 flag with specified name, default value, and usage string.
// The return value is the address of an int64 variable that stores the value of the flag.
func (f *FlagSet) Int64(name string, value int64, usage string) *int64 {
p := new(int64)
f.Int64VarP(p, name, "", value, usage)
return p
}
// Int64P is like Int64, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Int64P(name, shorthand string, value int64, usage string) *int64 {
p := new(int64)
f.Int64VarP(p, name, shorthand, value, usage)
return p
}
// Int64 defines an int64 flag with specified name, default value, and usage string.
// The return value is the address of an int64 variable that stores the value of the flag.
func Int64(name string, value int64, usage string) *int64 {
return CommandLine.Int64P(name, "", value, usage)
}
// Int64P is like Int64, but accepts a shorthand letter that can be used after a single dash.
func Int64P(name, shorthand string, value int64, usage string) *int64 {
return CommandLine.Int64P(name, shorthand, value, usage)
}

88
vendor/github.com/spf13/pflag/int8.go generated vendored Normal file
View File

@@ -0,0 +1,88 @@
package pflag
import "strconv"
// -- int8 Value
type int8Value int8
func newInt8Value(val int8, p *int8) *int8Value {
*p = val
return (*int8Value)(p)
}
func (i *int8Value) Set(s string) error {
v, err := strconv.ParseInt(s, 0, 8)
*i = int8Value(v)
return err
}
func (i *int8Value) Type() string {
return "int8"
}
func (i *int8Value) String() string { return strconv.FormatInt(int64(*i), 10) }
func int8Conv(sval string) (interface{}, error) {
v, err := strconv.ParseInt(sval, 0, 8)
if err != nil {
return 0, err
}
return int8(v), nil
}
// GetInt8 return the int8 value of a flag with the given name
func (f *FlagSet) GetInt8(name string) (int8, error) {
val, err := f.getFlagType(name, "int8", int8Conv)
if err != nil {
return 0, err
}
return val.(int8), nil
}
// Int8Var defines an int8 flag with specified name, default value, and usage string.
// The argument p points to an int8 variable in which to store the value of the flag.
func (f *FlagSet) Int8Var(p *int8, name string, value int8, usage string) {
f.VarP(newInt8Value(value, p), name, "", usage)
}
// Int8VarP is like Int8Var, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Int8VarP(p *int8, name, shorthand string, value int8, usage string) {
f.VarP(newInt8Value(value, p), name, shorthand, usage)
}
// Int8Var defines an int8 flag with specified name, default value, and usage string.
// The argument p points to an int8 variable in which to store the value of the flag.
func Int8Var(p *int8, name string, value int8, usage string) {
CommandLine.VarP(newInt8Value(value, p), name, "", usage)
}
// Int8VarP is like Int8Var, but accepts a shorthand letter that can be used after a single dash.
func Int8VarP(p *int8, name, shorthand string, value int8, usage string) {
CommandLine.VarP(newInt8Value(value, p), name, shorthand, usage)
}
// Int8 defines an int8 flag with specified name, default value, and usage string.
// The return value is the address of an int8 variable that stores the value of the flag.
func (f *FlagSet) Int8(name string, value int8, usage string) *int8 {
p := new(int8)
f.Int8VarP(p, name, "", value, usage)
return p
}
// Int8P is like Int8, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Int8P(name, shorthand string, value int8, usage string) *int8 {
p := new(int8)
f.Int8VarP(p, name, shorthand, value, usage)
return p
}
// Int8 defines an int8 flag with specified name, default value, and usage string.
// The return value is the address of an int8 variable that stores the value of the flag.
func Int8(name string, value int8, usage string) *int8 {
return CommandLine.Int8P(name, "", value, usage)
}
// Int8P is like Int8, but accepts a shorthand letter that can be used after a single dash.
func Int8P(name, shorthand string, value int8, usage string) *int8 {
return CommandLine.Int8P(name, shorthand, value, usage)
}

128
vendor/github.com/spf13/pflag/int_slice.go generated vendored Normal file
View File

@@ -0,0 +1,128 @@
package pflag
import (
"fmt"
"strconv"
"strings"
)
// -- intSlice Value
type intSliceValue struct {
value *[]int
changed bool
}
func newIntSliceValue(val []int, p *[]int) *intSliceValue {
isv := new(intSliceValue)
isv.value = p
*isv.value = val
return isv
}
func (s *intSliceValue) Set(val string) error {
ss := strings.Split(val, ",")
out := make([]int, len(ss))
for i, d := range ss {
var err error
out[i], err = strconv.Atoi(d)
if err != nil {
return err
}
}
if !s.changed {
*s.value = out
} else {
*s.value = append(*s.value, out...)
}
s.changed = true
return nil
}
func (s *intSliceValue) Type() string {
return "intSlice"
}
func (s *intSliceValue) String() string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = fmt.Sprintf("%d", d)
}
return "[" + strings.Join(out, ",") + "]"
}
func intSliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// Empty string would cause a slice with one (empty) entry
if len(val) == 0 {
return []int{}, nil
}
ss := strings.Split(val, ",")
out := make([]int, len(ss))
for i, d := range ss {
var err error
out[i], err = strconv.Atoi(d)
if err != nil {
return nil, err
}
}
return out, nil
}
// GetIntSlice return the []int value of a flag with the given name
func (f *FlagSet) GetIntSlice(name string) ([]int, error) {
val, err := f.getFlagType(name, "intSlice", intSliceConv)
if err != nil {
return []int{}, err
}
return val.([]int), nil
}
// IntSliceVar defines a intSlice flag with specified name, default value, and usage string.
// The argument p points to a []int variable in which to store the value of the flag.
func (f *FlagSet) IntSliceVar(p *[]int, name string, value []int, usage string) {
f.VarP(newIntSliceValue(value, p), name, "", usage)
}
// IntSliceVarP is like IntSliceVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) IntSliceVarP(p *[]int, name, shorthand string, value []int, usage string) {
f.VarP(newIntSliceValue(value, p), name, shorthand, usage)
}
// IntSliceVar defines a int[] flag with specified name, default value, and usage string.
// The argument p points to a int[] variable in which to store the value of the flag.
func IntSliceVar(p *[]int, name string, value []int, usage string) {
CommandLine.VarP(newIntSliceValue(value, p), name, "", usage)
}
// IntSliceVarP is like IntSliceVar, but accepts a shorthand letter that can be used after a single dash.
func IntSliceVarP(p *[]int, name, shorthand string, value []int, usage string) {
CommandLine.VarP(newIntSliceValue(value, p), name, shorthand, usage)
}
// IntSlice defines a []int flag with specified name, default value, and usage string.
// The return value is the address of a []int variable that stores the value of the flag.
func (f *FlagSet) IntSlice(name string, value []int, usage string) *[]int {
p := []int{}
f.IntSliceVarP(&p, name, "", value, usage)
return &p
}
// IntSliceP is like IntSlice, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) IntSliceP(name, shorthand string, value []int, usage string) *[]int {
p := []int{}
f.IntSliceVarP(&p, name, shorthand, value, usage)
return &p
}
// IntSlice defines a []int flag with specified name, default value, and usage string.
// The return value is the address of a []int variable that stores the value of the flag.
func IntSlice(name string, value []int, usage string) *[]int {
return CommandLine.IntSliceP(name, "", value, usage)
}
// IntSliceP is like IntSlice, but accepts a shorthand letter that can be used after a single dash.
func IntSliceP(name, shorthand string, value []int, usage string) *[]int {
return CommandLine.IntSliceP(name, shorthand, value, usage)
}

94
vendor/github.com/spf13/pflag/ip.go generated vendored Normal file
View File

@@ -0,0 +1,94 @@
package pflag
import (
"fmt"
"net"
"strings"
)
// -- net.IP value
type ipValue net.IP
func newIPValue(val net.IP, p *net.IP) *ipValue {
*p = val
return (*ipValue)(p)
}
func (i *ipValue) String() string { return net.IP(*i).String() }
func (i *ipValue) Set(s string) error {
ip := net.ParseIP(strings.TrimSpace(s))
if ip == nil {
return fmt.Errorf("failed to parse IP: %q", s)
}
*i = ipValue(ip)
return nil
}
func (i *ipValue) Type() string {
return "ip"
}
func ipConv(sval string) (interface{}, error) {
ip := net.ParseIP(sval)
if ip != nil {
return ip, nil
}
return nil, fmt.Errorf("invalid string being converted to IP address: %s", sval)
}
// GetIP return the net.IP value of a flag with the given name
func (f *FlagSet) GetIP(name string) (net.IP, error) {
val, err := f.getFlagType(name, "ip", ipConv)
if err != nil {
return nil, err
}
return val.(net.IP), nil
}
// IPVar defines an net.IP flag with specified name, default value, and usage string.
// The argument p points to an net.IP variable in which to store the value of the flag.
func (f *FlagSet) IPVar(p *net.IP, name string, value net.IP, usage string) {
f.VarP(newIPValue(value, p), name, "", usage)
}
// IPVarP is like IPVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) IPVarP(p *net.IP, name, shorthand string, value net.IP, usage string) {
f.VarP(newIPValue(value, p), name, shorthand, usage)
}
// IPVar defines an net.IP flag with specified name, default value, and usage string.
// The argument p points to an net.IP variable in which to store the value of the flag.
func IPVar(p *net.IP, name string, value net.IP, usage string) {
CommandLine.VarP(newIPValue(value, p), name, "", usage)
}
// IPVarP is like IPVar, but accepts a shorthand letter that can be used after a single dash.
func IPVarP(p *net.IP, name, shorthand string, value net.IP, usage string) {
CommandLine.VarP(newIPValue(value, p), name, shorthand, usage)
}
// IP defines an net.IP flag with specified name, default value, and usage string.
// The return value is the address of an net.IP variable that stores the value of the flag.
func (f *FlagSet) IP(name string, value net.IP, usage string) *net.IP {
p := new(net.IP)
f.IPVarP(p, name, "", value, usage)
return p
}
// IPP is like IP, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) IPP(name, shorthand string, value net.IP, usage string) *net.IP {
p := new(net.IP)
f.IPVarP(p, name, shorthand, value, usage)
return p
}
// IP defines an net.IP flag with specified name, default value, and usage string.
// The return value is the address of an net.IP variable that stores the value of the flag.
func IP(name string, value net.IP, usage string) *net.IP {
return CommandLine.IPP(name, "", value, usage)
}
// IPP is like IP, but accepts a shorthand letter that can be used after a single dash.
func IPP(name, shorthand string, value net.IP, usage string) *net.IP {
return CommandLine.IPP(name, shorthand, value, usage)
}

148
vendor/github.com/spf13/pflag/ip_slice.go generated vendored Normal file
View File

@@ -0,0 +1,148 @@
package pflag
import (
"fmt"
"io"
"net"
"strings"
)
// -- ipSlice Value
type ipSliceValue struct {
value *[]net.IP
changed bool
}
func newIPSliceValue(val []net.IP, p *[]net.IP) *ipSliceValue {
ipsv := new(ipSliceValue)
ipsv.value = p
*ipsv.value = val
return ipsv
}
// Set converts, and assigns, the comma-separated IP argument string representation as the []net.IP value of this flag.
// If Set is called on a flag that already has a []net.IP assigned, the newly converted values will be appended.
func (s *ipSliceValue) Set(val string) error {
// remove all quote characters
rmQuote := strings.NewReplacer(`"`, "", `'`, "", "`", "")
// read flag arguments with CSV parser
ipStrSlice, err := readAsCSV(rmQuote.Replace(val))
if err != nil && err != io.EOF {
return err
}
// parse ip values into slice
out := make([]net.IP, 0, len(ipStrSlice))
for _, ipStr := range ipStrSlice {
ip := net.ParseIP(strings.TrimSpace(ipStr))
if ip == nil {
return fmt.Errorf("invalid string being converted to IP address: %s", ipStr)
}
out = append(out, ip)
}
if !s.changed {
*s.value = out
} else {
*s.value = append(*s.value, out...)
}
s.changed = true
return nil
}
// Type returns a string that uniquely represents this flag's type.
func (s *ipSliceValue) Type() string {
return "ipSlice"
}
// String defines a "native" format for this net.IP slice flag value.
func (s *ipSliceValue) String() string {
ipStrSlice := make([]string, len(*s.value))
for i, ip := range *s.value {
ipStrSlice[i] = ip.String()
}
out, _ := writeAsCSV(ipStrSlice)
return "[" + out + "]"
}
func ipSliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// Emtpy string would cause a slice with one (empty) entry
if len(val) == 0 {
return []net.IP{}, nil
}
ss := strings.Split(val, ",")
out := make([]net.IP, len(ss))
for i, sval := range ss {
ip := net.ParseIP(strings.TrimSpace(sval))
if ip == nil {
return nil, fmt.Errorf("invalid string being converted to IP address: %s", sval)
}
out[i] = ip
}
return out, nil
}
// GetIPSlice returns the []net.IP value of a flag with the given name
func (f *FlagSet) GetIPSlice(name string) ([]net.IP, error) {
val, err := f.getFlagType(name, "ipSlice", ipSliceConv)
if err != nil {
return []net.IP{}, err
}
return val.([]net.IP), nil
}
// IPSliceVar defines a ipSlice flag with specified name, default value, and usage string.
// The argument p points to a []net.IP variable in which to store the value of the flag.
func (f *FlagSet) IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) {
f.VarP(newIPSliceValue(value, p), name, "", usage)
}
// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) {
f.VarP(newIPSliceValue(value, p), name, shorthand, usage)
}
// IPSliceVar defines a []net.IP flag with specified name, default value, and usage string.
// The argument p points to a []net.IP variable in which to store the value of the flag.
func IPSliceVar(p *[]net.IP, name string, value []net.IP, usage string) {
CommandLine.VarP(newIPSliceValue(value, p), name, "", usage)
}
// IPSliceVarP is like IPSliceVar, but accepts a shorthand letter that can be used after a single dash.
func IPSliceVarP(p *[]net.IP, name, shorthand string, value []net.IP, usage string) {
CommandLine.VarP(newIPSliceValue(value, p), name, shorthand, usage)
}
// IPSlice defines a []net.IP flag with specified name, default value, and usage string.
// The return value is the address of a []net.IP variable that stores the value of that flag.
func (f *FlagSet) IPSlice(name string, value []net.IP, usage string) *[]net.IP {
p := []net.IP{}
f.IPSliceVarP(&p, name, "", value, usage)
return &p
}
// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP {
p := []net.IP{}
f.IPSliceVarP(&p, name, shorthand, value, usage)
return &p
}
// IPSlice defines a []net.IP flag with specified name, default value, and usage string.
// The return value is the address of a []net.IP variable that stores the value of the flag.
func IPSlice(name string, value []net.IP, usage string) *[]net.IP {
return CommandLine.IPSliceP(name, "", value, usage)
}
// IPSliceP is like IPSlice, but accepts a shorthand letter that can be used after a single dash.
func IPSliceP(name, shorthand string, value []net.IP, usage string) *[]net.IP {
return CommandLine.IPSliceP(name, shorthand, value, usage)
}

122
vendor/github.com/spf13/pflag/ipmask.go generated vendored Normal file
View File

@@ -0,0 +1,122 @@
package pflag
import (
"fmt"
"net"
"strconv"
)
// -- net.IPMask value
type ipMaskValue net.IPMask
func newIPMaskValue(val net.IPMask, p *net.IPMask) *ipMaskValue {
*p = val
return (*ipMaskValue)(p)
}
func (i *ipMaskValue) String() string { return net.IPMask(*i).String() }
func (i *ipMaskValue) Set(s string) error {
ip := ParseIPv4Mask(s)
if ip == nil {
return fmt.Errorf("failed to parse IP mask: %q", s)
}
*i = ipMaskValue(ip)
return nil
}
func (i *ipMaskValue) Type() string {
return "ipMask"
}
// ParseIPv4Mask written in IP form (e.g. 255.255.255.0).
// This function should really belong to the net package.
func ParseIPv4Mask(s string) net.IPMask {
mask := net.ParseIP(s)
if mask == nil {
if len(s) != 8 {
return nil
}
// net.IPMask.String() actually outputs things like ffffff00
// so write a horrible parser for that as well :-(
m := []int{}
for i := 0; i < 4; i++ {
b := "0x" + s[2*i:2*i+2]
d, err := strconv.ParseInt(b, 0, 0)
if err != nil {
return nil
}
m = append(m, int(d))
}
s := fmt.Sprintf("%d.%d.%d.%d", m[0], m[1], m[2], m[3])
mask = net.ParseIP(s)
if mask == nil {
return nil
}
}
return net.IPv4Mask(mask[12], mask[13], mask[14], mask[15])
}
func parseIPv4Mask(sval string) (interface{}, error) {
mask := ParseIPv4Mask(sval)
if mask == nil {
return nil, fmt.Errorf("unable to parse %s as net.IPMask", sval)
}
return mask, nil
}
// GetIPv4Mask return the net.IPv4Mask value of a flag with the given name
func (f *FlagSet) GetIPv4Mask(name string) (net.IPMask, error) {
val, err := f.getFlagType(name, "ipMask", parseIPv4Mask)
if err != nil {
return nil, err
}
return val.(net.IPMask), nil
}
// IPMaskVar defines an net.IPMask flag with specified name, default value, and usage string.
// The argument p points to an net.IPMask variable in which to store the value of the flag.
func (f *FlagSet) IPMaskVar(p *net.IPMask, name string, value net.IPMask, usage string) {
f.VarP(newIPMaskValue(value, p), name, "", usage)
}
// IPMaskVarP is like IPMaskVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) IPMaskVarP(p *net.IPMask, name, shorthand string, value net.IPMask, usage string) {
f.VarP(newIPMaskValue(value, p), name, shorthand, usage)
}
// IPMaskVar defines an net.IPMask flag with specified name, default value, and usage string.
// The argument p points to an net.IPMask variable in which to store the value of the flag.
func IPMaskVar(p *net.IPMask, name string, value net.IPMask, usage string) {
CommandLine.VarP(newIPMaskValue(value, p), name, "", usage)
}
// IPMaskVarP is like IPMaskVar, but accepts a shorthand letter that can be used after a single dash.
func IPMaskVarP(p *net.IPMask, name, shorthand string, value net.IPMask, usage string) {
CommandLine.VarP(newIPMaskValue(value, p), name, shorthand, usage)
}
// IPMask defines an net.IPMask flag with specified name, default value, and usage string.
// The return value is the address of an net.IPMask variable that stores the value of the flag.
func (f *FlagSet) IPMask(name string, value net.IPMask, usage string) *net.IPMask {
p := new(net.IPMask)
f.IPMaskVarP(p, name, "", value, usage)
return p
}
// IPMaskP is like IPMask, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) IPMaskP(name, shorthand string, value net.IPMask, usage string) *net.IPMask {
p := new(net.IPMask)
f.IPMaskVarP(p, name, shorthand, value, usage)
return p
}
// IPMask defines an net.IPMask flag with specified name, default value, and usage string.
// The return value is the address of an net.IPMask variable that stores the value of the flag.
func IPMask(name string, value net.IPMask, usage string) *net.IPMask {
return CommandLine.IPMaskP(name, "", value, usage)
}
// IPMaskP is like IP, but accepts a shorthand letter that can be used after a single dash.
func IPMaskP(name, shorthand string, value net.IPMask, usage string) *net.IPMask {
return CommandLine.IPMaskP(name, shorthand, value, usage)
}

98
vendor/github.com/spf13/pflag/ipnet.go generated vendored Normal file
View File

@@ -0,0 +1,98 @@
package pflag
import (
"fmt"
"net"
"strings"
)
// IPNet adapts net.IPNet for use as a flag.
type ipNetValue net.IPNet
func (ipnet ipNetValue) String() string {
n := net.IPNet(ipnet)
return n.String()
}
func (ipnet *ipNetValue) Set(value string) error {
_, n, err := net.ParseCIDR(strings.TrimSpace(value))
if err != nil {
return err
}
*ipnet = ipNetValue(*n)
return nil
}
func (*ipNetValue) Type() string {
return "ipNet"
}
func newIPNetValue(val net.IPNet, p *net.IPNet) *ipNetValue {
*p = val
return (*ipNetValue)(p)
}
func ipNetConv(sval string) (interface{}, error) {
_, n, err := net.ParseCIDR(strings.TrimSpace(sval))
if err == nil {
return *n, nil
}
return nil, fmt.Errorf("invalid string being converted to IPNet: %s", sval)
}
// GetIPNet return the net.IPNet value of a flag with the given name
func (f *FlagSet) GetIPNet(name string) (net.IPNet, error) {
val, err := f.getFlagType(name, "ipNet", ipNetConv)
if err != nil {
return net.IPNet{}, err
}
return val.(net.IPNet), nil
}
// IPNetVar defines an net.IPNet flag with specified name, default value, and usage string.
// The argument p points to an net.IPNet variable in which to store the value of the flag.
func (f *FlagSet) IPNetVar(p *net.IPNet, name string, value net.IPNet, usage string) {
f.VarP(newIPNetValue(value, p), name, "", usage)
}
// IPNetVarP is like IPNetVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) IPNetVarP(p *net.IPNet, name, shorthand string, value net.IPNet, usage string) {
f.VarP(newIPNetValue(value, p), name, shorthand, usage)
}
// IPNetVar defines an net.IPNet flag with specified name, default value, and usage string.
// The argument p points to an net.IPNet variable in which to store the value of the flag.
func IPNetVar(p *net.IPNet, name string, value net.IPNet, usage string) {
CommandLine.VarP(newIPNetValue(value, p), name, "", usage)
}
// IPNetVarP is like IPNetVar, but accepts a shorthand letter that can be used after a single dash.
func IPNetVarP(p *net.IPNet, name, shorthand string, value net.IPNet, usage string) {
CommandLine.VarP(newIPNetValue(value, p), name, shorthand, usage)
}
// IPNet defines an net.IPNet flag with specified name, default value, and usage string.
// The return value is the address of an net.IPNet variable that stores the value of the flag.
func (f *FlagSet) IPNet(name string, value net.IPNet, usage string) *net.IPNet {
p := new(net.IPNet)
f.IPNetVarP(p, name, "", value, usage)
return p
}
// IPNetP is like IPNet, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) IPNetP(name, shorthand string, value net.IPNet, usage string) *net.IPNet {
p := new(net.IPNet)
f.IPNetVarP(p, name, shorthand, value, usage)
return p
}
// IPNet defines an net.IPNet flag with specified name, default value, and usage string.
// The return value is the address of an net.IPNet variable that stores the value of the flag.
func IPNet(name string, value net.IPNet, usage string) *net.IPNet {
return CommandLine.IPNetP(name, "", value, usage)
}
// IPNetP is like IPNet, but accepts a shorthand letter that can be used after a single dash.
func IPNetP(name, shorthand string, value net.IPNet, usage string) *net.IPNet {
return CommandLine.IPNetP(name, shorthand, value, usage)
}

80
vendor/github.com/spf13/pflag/string.go generated vendored Normal file
View File

@@ -0,0 +1,80 @@
package pflag
// -- string Value
type stringValue string
func newStringValue(val string, p *string) *stringValue {
*p = val
return (*stringValue)(p)
}
func (s *stringValue) Set(val string) error {
*s = stringValue(val)
return nil
}
func (s *stringValue) Type() string {
return "string"
}
func (s *stringValue) String() string { return string(*s) }
func stringConv(sval string) (interface{}, error) {
return sval, nil
}
// GetString return the string value of a flag with the given name
func (f *FlagSet) GetString(name string) (string, error) {
val, err := f.getFlagType(name, "string", stringConv)
if err != nil {
return "", err
}
return val.(string), nil
}
// StringVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a string variable in which to store the value of the flag.
func (f *FlagSet) StringVar(p *string, name string, value string, usage string) {
f.VarP(newStringValue(value, p), name, "", usage)
}
// StringVarP is like StringVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) StringVarP(p *string, name, shorthand string, value string, usage string) {
f.VarP(newStringValue(value, p), name, shorthand, usage)
}
// StringVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a string variable in which to store the value of the flag.
func StringVar(p *string, name string, value string, usage string) {
CommandLine.VarP(newStringValue(value, p), name, "", usage)
}
// StringVarP is like StringVar, but accepts a shorthand letter that can be used after a single dash.
func StringVarP(p *string, name, shorthand string, value string, usage string) {
CommandLine.VarP(newStringValue(value, p), name, shorthand, usage)
}
// String defines a string flag with specified name, default value, and usage string.
// The return value is the address of a string variable that stores the value of the flag.
func (f *FlagSet) String(name string, value string, usage string) *string {
p := new(string)
f.StringVarP(p, name, "", value, usage)
return p
}
// StringP is like String, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) StringP(name, shorthand string, value string, usage string) *string {
p := new(string)
f.StringVarP(p, name, shorthand, value, usage)
return p
}
// String defines a string flag with specified name, default value, and usage string.
// The return value is the address of a string variable that stores the value of the flag.
func String(name string, value string, usage string) *string {
return CommandLine.StringP(name, "", value, usage)
}
// StringP is like String, but accepts a shorthand letter that can be used after a single dash.
func StringP(name, shorthand string, value string, usage string) *string {
return CommandLine.StringP(name, shorthand, value, usage)
}

103
vendor/github.com/spf13/pflag/string_array.go generated vendored Normal file
View File

@@ -0,0 +1,103 @@
package pflag
// -- stringArray Value
type stringArrayValue struct {
value *[]string
changed bool
}
func newStringArrayValue(val []string, p *[]string) *stringArrayValue {
ssv := new(stringArrayValue)
ssv.value = p
*ssv.value = val
return ssv
}
func (s *stringArrayValue) Set(val string) error {
if !s.changed {
*s.value = []string{val}
s.changed = true
} else {
*s.value = append(*s.value, val)
}
return nil
}
func (s *stringArrayValue) Type() string {
return "stringArray"
}
func (s *stringArrayValue) String() string {
str, _ := writeAsCSV(*s.value)
return "[" + str + "]"
}
func stringArrayConv(sval string) (interface{}, error) {
sval = sval[1 : len(sval)-1]
// An empty string would cause a array with one (empty) string
if len(sval) == 0 {
return []string{}, nil
}
return readAsCSV(sval)
}
// GetStringArray return the []string value of a flag with the given name
func (f *FlagSet) GetStringArray(name string) ([]string, error) {
val, err := f.getFlagType(name, "stringArray", stringArrayConv)
if err != nil {
return []string{}, err
}
return val.([]string), nil
}
// StringArrayVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a []string variable in which to store the values of the multiple flags.
// The value of each argument will not try to be separated by comma
func (f *FlagSet) StringArrayVar(p *[]string, name string, value []string, usage string) {
f.VarP(newStringArrayValue(value, p), name, "", usage)
}
// StringArrayVarP is like StringArrayVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) StringArrayVarP(p *[]string, name, shorthand string, value []string, usage string) {
f.VarP(newStringArrayValue(value, p), name, shorthand, usage)
}
// StringArrayVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a []string variable in which to store the value of the flag.
// The value of each argument will not try to be separated by comma
func StringArrayVar(p *[]string, name string, value []string, usage string) {
CommandLine.VarP(newStringArrayValue(value, p), name, "", usage)
}
// StringArrayVarP is like StringArrayVar, but accepts a shorthand letter that can be used after a single dash.
func StringArrayVarP(p *[]string, name, shorthand string, value []string, usage string) {
CommandLine.VarP(newStringArrayValue(value, p), name, shorthand, usage)
}
// StringArray defines a string flag with specified name, default value, and usage string.
// The return value is the address of a []string variable that stores the value of the flag.
// The value of each argument will not try to be separated by comma
func (f *FlagSet) StringArray(name string, value []string, usage string) *[]string {
p := []string{}
f.StringArrayVarP(&p, name, "", value, usage)
return &p
}
// StringArrayP is like StringArray, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) StringArrayP(name, shorthand string, value []string, usage string) *[]string {
p := []string{}
f.StringArrayVarP(&p, name, shorthand, value, usage)
return &p
}
// StringArray defines a string flag with specified name, default value, and usage string.
// The return value is the address of a []string variable that stores the value of the flag.
// The value of each argument will not try to be separated by comma
func StringArray(name string, value []string, usage string) *[]string {
return CommandLine.StringArrayP(name, "", value, usage)
}
// StringArrayP is like StringArray, but accepts a shorthand letter that can be used after a single dash.
func StringArrayP(name, shorthand string, value []string, usage string) *[]string {
return CommandLine.StringArrayP(name, shorthand, value, usage)
}

129
vendor/github.com/spf13/pflag/string_slice.go generated vendored Normal file
View File

@@ -0,0 +1,129 @@
package pflag
import (
"bytes"
"encoding/csv"
"strings"
)
// -- stringSlice Value
type stringSliceValue struct {
value *[]string
changed bool
}
func newStringSliceValue(val []string, p *[]string) *stringSliceValue {
ssv := new(stringSliceValue)
ssv.value = p
*ssv.value = val
return ssv
}
func readAsCSV(val string) ([]string, error) {
if val == "" {
return []string{}, nil
}
stringReader := strings.NewReader(val)
csvReader := csv.NewReader(stringReader)
return csvReader.Read()
}
func writeAsCSV(vals []string) (string, error) {
b := &bytes.Buffer{}
w := csv.NewWriter(b)
err := w.Write(vals)
if err != nil {
return "", err
}
w.Flush()
return strings.TrimSuffix(b.String(), "\n"), nil
}
func (s *stringSliceValue) Set(val string) error {
v, err := readAsCSV(val)
if err != nil {
return err
}
if !s.changed {
*s.value = v
} else {
*s.value = append(*s.value, v...)
}
s.changed = true
return nil
}
func (s *stringSliceValue) Type() string {
return "stringSlice"
}
func (s *stringSliceValue) String() string {
str, _ := writeAsCSV(*s.value)
return "[" + str + "]"
}
func stringSliceConv(sval string) (interface{}, error) {
sval = sval[1 : len(sval)-1]
// An empty string would cause a slice with one (empty) string
if len(sval) == 0 {
return []string{}, nil
}
return readAsCSV(sval)
}
// GetStringSlice return the []string value of a flag with the given name
func (f *FlagSet) GetStringSlice(name string) ([]string, error) {
val, err := f.getFlagType(name, "stringSlice", stringSliceConv)
if err != nil {
return []string{}, err
}
return val.([]string), nil
}
// StringSliceVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a []string variable in which to store the value of the flag.
func (f *FlagSet) StringSliceVar(p *[]string, name string, value []string, usage string) {
f.VarP(newStringSliceValue(value, p), name, "", usage)
}
// StringSliceVarP is like StringSliceVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) StringSliceVarP(p *[]string, name, shorthand string, value []string, usage string) {
f.VarP(newStringSliceValue(value, p), name, shorthand, usage)
}
// StringSliceVar defines a string flag with specified name, default value, and usage string.
// The argument p points to a []string variable in which to store the value of the flag.
func StringSliceVar(p *[]string, name string, value []string, usage string) {
CommandLine.VarP(newStringSliceValue(value, p), name, "", usage)
}
// StringSliceVarP is like StringSliceVar, but accepts a shorthand letter that can be used after a single dash.
func StringSliceVarP(p *[]string, name, shorthand string, value []string, usage string) {
CommandLine.VarP(newStringSliceValue(value, p), name, shorthand, usage)
}
// StringSlice defines a string flag with specified name, default value, and usage string.
// The return value is the address of a []string variable that stores the value of the flag.
func (f *FlagSet) StringSlice(name string, value []string, usage string) *[]string {
p := []string{}
f.StringSliceVarP(&p, name, "", value, usage)
return &p
}
// StringSliceP is like StringSlice, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) StringSliceP(name, shorthand string, value []string, usage string) *[]string {
p := []string{}
f.StringSliceVarP(&p, name, shorthand, value, usage)
return &p
}
// StringSlice defines a string flag with specified name, default value, and usage string.
// The return value is the address of a []string variable that stores the value of the flag.
func StringSlice(name string, value []string, usage string) *[]string {
return CommandLine.StringSliceP(name, "", value, usage)
}
// StringSliceP is like StringSlice, but accepts a shorthand letter that can be used after a single dash.
func StringSliceP(name, shorthand string, value []string, usage string) *[]string {
return CommandLine.StringSliceP(name, shorthand, value, usage)
}

88
vendor/github.com/spf13/pflag/uint.go generated vendored Normal file
View File

@@ -0,0 +1,88 @@
package pflag
import "strconv"
// -- uint Value
type uintValue uint
func newUintValue(val uint, p *uint) *uintValue {
*p = val
return (*uintValue)(p)
}
func (i *uintValue) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 64)
*i = uintValue(v)
return err
}
func (i *uintValue) Type() string {
return "uint"
}
func (i *uintValue) String() string { return strconv.FormatUint(uint64(*i), 10) }
func uintConv(sval string) (interface{}, error) {
v, err := strconv.ParseUint(sval, 0, 0)
if err != nil {
return 0, err
}
return uint(v), nil
}
// GetUint return the uint value of a flag with the given name
func (f *FlagSet) GetUint(name string) (uint, error) {
val, err := f.getFlagType(name, "uint", uintConv)
if err != nil {
return 0, err
}
return val.(uint), nil
}
// UintVar defines a uint flag with specified name, default value, and usage string.
// The argument p points to a uint variable in which to store the value of the flag.
func (f *FlagSet) UintVar(p *uint, name string, value uint, usage string) {
f.VarP(newUintValue(value, p), name, "", usage)
}
// UintVarP is like UintVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) UintVarP(p *uint, name, shorthand string, value uint, usage string) {
f.VarP(newUintValue(value, p), name, shorthand, usage)
}
// UintVar defines a uint flag with specified name, default value, and usage string.
// The argument p points to a uint variable in which to store the value of the flag.
func UintVar(p *uint, name string, value uint, usage string) {
CommandLine.VarP(newUintValue(value, p), name, "", usage)
}
// UintVarP is like UintVar, but accepts a shorthand letter that can be used after a single dash.
func UintVarP(p *uint, name, shorthand string, value uint, usage string) {
CommandLine.VarP(newUintValue(value, p), name, shorthand, usage)
}
// Uint defines a uint flag with specified name, default value, and usage string.
// The return value is the address of a uint variable that stores the value of the flag.
func (f *FlagSet) Uint(name string, value uint, usage string) *uint {
p := new(uint)
f.UintVarP(p, name, "", value, usage)
return p
}
// UintP is like Uint, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) UintP(name, shorthand string, value uint, usage string) *uint {
p := new(uint)
f.UintVarP(p, name, shorthand, value, usage)
return p
}
// Uint defines a uint flag with specified name, default value, and usage string.
// The return value is the address of a uint variable that stores the value of the flag.
func Uint(name string, value uint, usage string) *uint {
return CommandLine.UintP(name, "", value, usage)
}
// UintP is like Uint, but accepts a shorthand letter that can be used after a single dash.
func UintP(name, shorthand string, value uint, usage string) *uint {
return CommandLine.UintP(name, shorthand, value, usage)
}

88
vendor/github.com/spf13/pflag/uint16.go generated vendored Normal file
View File

@@ -0,0 +1,88 @@
package pflag
import "strconv"
// -- uint16 value
type uint16Value uint16
func newUint16Value(val uint16, p *uint16) *uint16Value {
*p = val
return (*uint16Value)(p)
}
func (i *uint16Value) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 16)
*i = uint16Value(v)
return err
}
func (i *uint16Value) Type() string {
return "uint16"
}
func (i *uint16Value) String() string { return strconv.FormatUint(uint64(*i), 10) }
func uint16Conv(sval string) (interface{}, error) {
v, err := strconv.ParseUint(sval, 0, 16)
if err != nil {
return 0, err
}
return uint16(v), nil
}
// GetUint16 return the uint16 value of a flag with the given name
func (f *FlagSet) GetUint16(name string) (uint16, error) {
val, err := f.getFlagType(name, "uint16", uint16Conv)
if err != nil {
return 0, err
}
return val.(uint16), nil
}
// Uint16Var defines a uint flag with specified name, default value, and usage string.
// The argument p points to a uint variable in which to store the value of the flag.
func (f *FlagSet) Uint16Var(p *uint16, name string, value uint16, usage string) {
f.VarP(newUint16Value(value, p), name, "", usage)
}
// Uint16VarP is like Uint16Var, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Uint16VarP(p *uint16, name, shorthand string, value uint16, usage string) {
f.VarP(newUint16Value(value, p), name, shorthand, usage)
}
// Uint16Var defines a uint flag with specified name, default value, and usage string.
// The argument p points to a uint variable in which to store the value of the flag.
func Uint16Var(p *uint16, name string, value uint16, usage string) {
CommandLine.VarP(newUint16Value(value, p), name, "", usage)
}
// Uint16VarP is like Uint16Var, but accepts a shorthand letter that can be used after a single dash.
func Uint16VarP(p *uint16, name, shorthand string, value uint16, usage string) {
CommandLine.VarP(newUint16Value(value, p), name, shorthand, usage)
}
// Uint16 defines a uint flag with specified name, default value, and usage string.
// The return value is the address of a uint variable that stores the value of the flag.
func (f *FlagSet) Uint16(name string, value uint16, usage string) *uint16 {
p := new(uint16)
f.Uint16VarP(p, name, "", value, usage)
return p
}
// Uint16P is like Uint16, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Uint16P(name, shorthand string, value uint16, usage string) *uint16 {
p := new(uint16)
f.Uint16VarP(p, name, shorthand, value, usage)
return p
}
// Uint16 defines a uint flag with specified name, default value, and usage string.
// The return value is the address of a uint variable that stores the value of the flag.
func Uint16(name string, value uint16, usage string) *uint16 {
return CommandLine.Uint16P(name, "", value, usage)
}
// Uint16P is like Uint16, but accepts a shorthand letter that can be used after a single dash.
func Uint16P(name, shorthand string, value uint16, usage string) *uint16 {
return CommandLine.Uint16P(name, shorthand, value, usage)
}

88
vendor/github.com/spf13/pflag/uint32.go generated vendored Normal file
View File

@@ -0,0 +1,88 @@
package pflag
import "strconv"
// -- uint32 value
type uint32Value uint32
func newUint32Value(val uint32, p *uint32) *uint32Value {
*p = val
return (*uint32Value)(p)
}
func (i *uint32Value) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 32)
*i = uint32Value(v)
return err
}
func (i *uint32Value) Type() string {
return "uint32"
}
func (i *uint32Value) String() string { return strconv.FormatUint(uint64(*i), 10) }
func uint32Conv(sval string) (interface{}, error) {
v, err := strconv.ParseUint(sval, 0, 32)
if err != nil {
return 0, err
}
return uint32(v), nil
}
// GetUint32 return the uint32 value of a flag with the given name
func (f *FlagSet) GetUint32(name string) (uint32, error) {
val, err := f.getFlagType(name, "uint32", uint32Conv)
if err != nil {
return 0, err
}
return val.(uint32), nil
}
// Uint32Var defines a uint32 flag with specified name, default value, and usage string.
// The argument p points to a uint32 variable in which to store the value of the flag.
func (f *FlagSet) Uint32Var(p *uint32, name string, value uint32, usage string) {
f.VarP(newUint32Value(value, p), name, "", usage)
}
// Uint32VarP is like Uint32Var, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Uint32VarP(p *uint32, name, shorthand string, value uint32, usage string) {
f.VarP(newUint32Value(value, p), name, shorthand, usage)
}
// Uint32Var defines a uint32 flag with specified name, default value, and usage string.
// The argument p points to a uint32 variable in which to store the value of the flag.
func Uint32Var(p *uint32, name string, value uint32, usage string) {
CommandLine.VarP(newUint32Value(value, p), name, "", usage)
}
// Uint32VarP is like Uint32Var, but accepts a shorthand letter that can be used after a single dash.
func Uint32VarP(p *uint32, name, shorthand string, value uint32, usage string) {
CommandLine.VarP(newUint32Value(value, p), name, shorthand, usage)
}
// Uint32 defines a uint32 flag with specified name, default value, and usage string.
// The return value is the address of a uint32 variable that stores the value of the flag.
func (f *FlagSet) Uint32(name string, value uint32, usage string) *uint32 {
p := new(uint32)
f.Uint32VarP(p, name, "", value, usage)
return p
}
// Uint32P is like Uint32, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Uint32P(name, shorthand string, value uint32, usage string) *uint32 {
p := new(uint32)
f.Uint32VarP(p, name, shorthand, value, usage)
return p
}
// Uint32 defines a uint32 flag with specified name, default value, and usage string.
// The return value is the address of a uint32 variable that stores the value of the flag.
func Uint32(name string, value uint32, usage string) *uint32 {
return CommandLine.Uint32P(name, "", value, usage)
}
// Uint32P is like Uint32, but accepts a shorthand letter that can be used after a single dash.
func Uint32P(name, shorthand string, value uint32, usage string) *uint32 {
return CommandLine.Uint32P(name, shorthand, value, usage)
}

88
vendor/github.com/spf13/pflag/uint64.go generated vendored Normal file
View File

@@ -0,0 +1,88 @@
package pflag
import "strconv"
// -- uint64 Value
type uint64Value uint64
func newUint64Value(val uint64, p *uint64) *uint64Value {
*p = val
return (*uint64Value)(p)
}
func (i *uint64Value) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 64)
*i = uint64Value(v)
return err
}
func (i *uint64Value) Type() string {
return "uint64"
}
func (i *uint64Value) String() string { return strconv.FormatUint(uint64(*i), 10) }
func uint64Conv(sval string) (interface{}, error) {
v, err := strconv.ParseUint(sval, 0, 64)
if err != nil {
return 0, err
}
return uint64(v), nil
}
// GetUint64 return the uint64 value of a flag with the given name
func (f *FlagSet) GetUint64(name string) (uint64, error) {
val, err := f.getFlagType(name, "uint64", uint64Conv)
if err != nil {
return 0, err
}
return val.(uint64), nil
}
// Uint64Var defines a uint64 flag with specified name, default value, and usage string.
// The argument p points to a uint64 variable in which to store the value of the flag.
func (f *FlagSet) Uint64Var(p *uint64, name string, value uint64, usage string) {
f.VarP(newUint64Value(value, p), name, "", usage)
}
// Uint64VarP is like Uint64Var, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Uint64VarP(p *uint64, name, shorthand string, value uint64, usage string) {
f.VarP(newUint64Value(value, p), name, shorthand, usage)
}
// Uint64Var defines a uint64 flag with specified name, default value, and usage string.
// The argument p points to a uint64 variable in which to store the value of the flag.
func Uint64Var(p *uint64, name string, value uint64, usage string) {
CommandLine.VarP(newUint64Value(value, p), name, "", usage)
}
// Uint64VarP is like Uint64Var, but accepts a shorthand letter that can be used after a single dash.
func Uint64VarP(p *uint64, name, shorthand string, value uint64, usage string) {
CommandLine.VarP(newUint64Value(value, p), name, shorthand, usage)
}
// Uint64 defines a uint64 flag with specified name, default value, and usage string.
// The return value is the address of a uint64 variable that stores the value of the flag.
func (f *FlagSet) Uint64(name string, value uint64, usage string) *uint64 {
p := new(uint64)
f.Uint64VarP(p, name, "", value, usage)
return p
}
// Uint64P is like Uint64, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Uint64P(name, shorthand string, value uint64, usage string) *uint64 {
p := new(uint64)
f.Uint64VarP(p, name, shorthand, value, usage)
return p
}
// Uint64 defines a uint64 flag with specified name, default value, and usage string.
// The return value is the address of a uint64 variable that stores the value of the flag.
func Uint64(name string, value uint64, usage string) *uint64 {
return CommandLine.Uint64P(name, "", value, usage)
}
// Uint64P is like Uint64, but accepts a shorthand letter that can be used after a single dash.
func Uint64P(name, shorthand string, value uint64, usage string) *uint64 {
return CommandLine.Uint64P(name, shorthand, value, usage)
}

88
vendor/github.com/spf13/pflag/uint8.go generated vendored Normal file
View File

@@ -0,0 +1,88 @@
package pflag
import "strconv"
// -- uint8 Value
type uint8Value uint8
func newUint8Value(val uint8, p *uint8) *uint8Value {
*p = val
return (*uint8Value)(p)
}
func (i *uint8Value) Set(s string) error {
v, err := strconv.ParseUint(s, 0, 8)
*i = uint8Value(v)
return err
}
func (i *uint8Value) Type() string {
return "uint8"
}
func (i *uint8Value) String() string { return strconv.FormatUint(uint64(*i), 10) }
func uint8Conv(sval string) (interface{}, error) {
v, err := strconv.ParseUint(sval, 0, 8)
if err != nil {
return 0, err
}
return uint8(v), nil
}
// GetUint8 return the uint8 value of a flag with the given name
func (f *FlagSet) GetUint8(name string) (uint8, error) {
val, err := f.getFlagType(name, "uint8", uint8Conv)
if err != nil {
return 0, err
}
return val.(uint8), nil
}
// Uint8Var defines a uint8 flag with specified name, default value, and usage string.
// The argument p points to a uint8 variable in which to store the value of the flag.
func (f *FlagSet) Uint8Var(p *uint8, name string, value uint8, usage string) {
f.VarP(newUint8Value(value, p), name, "", usage)
}
// Uint8VarP is like Uint8Var, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Uint8VarP(p *uint8, name, shorthand string, value uint8, usage string) {
f.VarP(newUint8Value(value, p), name, shorthand, usage)
}
// Uint8Var defines a uint8 flag with specified name, default value, and usage string.
// The argument p points to a uint8 variable in which to store the value of the flag.
func Uint8Var(p *uint8, name string, value uint8, usage string) {
CommandLine.VarP(newUint8Value(value, p), name, "", usage)
}
// Uint8VarP is like Uint8Var, but accepts a shorthand letter that can be used after a single dash.
func Uint8VarP(p *uint8, name, shorthand string, value uint8, usage string) {
CommandLine.VarP(newUint8Value(value, p), name, shorthand, usage)
}
// Uint8 defines a uint8 flag with specified name, default value, and usage string.
// The return value is the address of a uint8 variable that stores the value of the flag.
func (f *FlagSet) Uint8(name string, value uint8, usage string) *uint8 {
p := new(uint8)
f.Uint8VarP(p, name, "", value, usage)
return p
}
// Uint8P is like Uint8, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) Uint8P(name, shorthand string, value uint8, usage string) *uint8 {
p := new(uint8)
f.Uint8VarP(p, name, shorthand, value, usage)
return p
}
// Uint8 defines a uint8 flag with specified name, default value, and usage string.
// The return value is the address of a uint8 variable that stores the value of the flag.
func Uint8(name string, value uint8, usage string) *uint8 {
return CommandLine.Uint8P(name, "", value, usage)
}
// Uint8P is like Uint8, but accepts a shorthand letter that can be used after a single dash.
func Uint8P(name, shorthand string, value uint8, usage string) *uint8 {
return CommandLine.Uint8P(name, shorthand, value, usage)
}

126
vendor/github.com/spf13/pflag/uint_slice.go generated vendored Normal file
View File

@@ -0,0 +1,126 @@
package pflag
import (
"fmt"
"strconv"
"strings"
)
// -- uintSlice Value
type uintSliceValue struct {
value *[]uint
changed bool
}
func newUintSliceValue(val []uint, p *[]uint) *uintSliceValue {
uisv := new(uintSliceValue)
uisv.value = p
*uisv.value = val
return uisv
}
func (s *uintSliceValue) Set(val string) error {
ss := strings.Split(val, ",")
out := make([]uint, len(ss))
for i, d := range ss {
u, err := strconv.ParseUint(d, 10, 0)
if err != nil {
return err
}
out[i] = uint(u)
}
if !s.changed {
*s.value = out
} else {
*s.value = append(*s.value, out...)
}
s.changed = true
return nil
}
func (s *uintSliceValue) Type() string {
return "uintSlice"
}
func (s *uintSliceValue) String() string {
out := make([]string, len(*s.value))
for i, d := range *s.value {
out[i] = fmt.Sprintf("%d", d)
}
return "[" + strings.Join(out, ",") + "]"
}
func uintSliceConv(val string) (interface{}, error) {
val = strings.Trim(val, "[]")
// Empty string would cause a slice with one (empty) entry
if len(val) == 0 {
return []uint{}, nil
}
ss := strings.Split(val, ",")
out := make([]uint, len(ss))
for i, d := range ss {
u, err := strconv.ParseUint(d, 10, 0)
if err != nil {
return nil, err
}
out[i] = uint(u)
}
return out, nil
}
// GetUintSlice returns the []uint value of a flag with the given name.
func (f *FlagSet) GetUintSlice(name string) ([]uint, error) {
val, err := f.getFlagType(name, "uintSlice", uintSliceConv)
if err != nil {
return []uint{}, err
}
return val.([]uint), nil
}
// UintSliceVar defines a uintSlice flag with specified name, default value, and usage string.
// The argument p points to a []uint variable in which to store the value of the flag.
func (f *FlagSet) UintSliceVar(p *[]uint, name string, value []uint, usage string) {
f.VarP(newUintSliceValue(value, p), name, "", usage)
}
// UintSliceVarP is like UintSliceVar, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) {
f.VarP(newUintSliceValue(value, p), name, shorthand, usage)
}
// UintSliceVar defines a uint[] flag with specified name, default value, and usage string.
// The argument p points to a uint[] variable in which to store the value of the flag.
func UintSliceVar(p *[]uint, name string, value []uint, usage string) {
CommandLine.VarP(newUintSliceValue(value, p), name, "", usage)
}
// UintSliceVarP is like the UintSliceVar, but accepts a shorthand letter that can be used after a single dash.
func UintSliceVarP(p *[]uint, name, shorthand string, value []uint, usage string) {
CommandLine.VarP(newUintSliceValue(value, p), name, shorthand, usage)
}
// UintSlice defines a []uint flag with specified name, default value, and usage string.
// The return value is the address of a []uint variable that stores the value of the flag.
func (f *FlagSet) UintSlice(name string, value []uint, usage string) *[]uint {
p := []uint{}
f.UintSliceVarP(&p, name, "", value, usage)
return &p
}
// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash.
func (f *FlagSet) UintSliceP(name, shorthand string, value []uint, usage string) *[]uint {
p := []uint{}
f.UintSliceVarP(&p, name, shorthand, value, usage)
return &p
}
// UintSlice defines a []uint flag with specified name, default value, and usage string.
// The return value is the address of a []uint variable that stores the value of the flag.
func UintSlice(name string, value []uint, usage string) *[]uint {
return CommandLine.UintSliceP(name, "", value, usage)
}
// UintSliceP is like UintSlice, but accepts a shorthand letter that can be used after a single dash.
func UintSliceP(name, shorthand string, value []uint, usage string) *[]uint {
return CommandLine.UintSliceP(name, shorthand, value, usage)
}

202
vendor/go4.org/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright {yyyy} {name of copyright owner}
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

58
vendor/go4.org/errorutil/highlight.go generated vendored Normal file
View File

@@ -0,0 +1,58 @@
/*
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Package errorutil helps make better error messages.
package errorutil // import "go4.org/errorutil"
import (
"bufio"
"bytes"
"fmt"
"io"
"strings"
)
// HighlightBytePosition takes a reader and the location in bytes of a parse
// error (for instance, from json.SyntaxError.Offset) and returns the line, column,
// and pretty-printed context around the error with an arrow indicating the exact
// position of the syntax error.
func HighlightBytePosition(f io.Reader, pos int64) (line, col int, highlight string) {
line = 1
br := bufio.NewReader(f)
lastLine := ""
thisLine := new(bytes.Buffer)
for n := int64(0); n < pos; n++ {
b, err := br.ReadByte()
if err != nil {
break
}
if b == '\n' {
lastLine = thisLine.String()
thisLine.Reset()
line++
col = 1
} else {
col++
thisLine.WriteByte(b)
}
}
if line > 1 {
highlight += fmt.Sprintf("%5d: %s\n", line-1, lastLine)
}
highlight += fmt.Sprintf("%5d: %s\n", line, thisLine.String())
highlight += fmt.Sprintf("%s^\n", strings.Repeat(" ", col+5))
return
}

28
vendor/gopkg.in/inf.v0/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,28 @@
Copyright (c) 2012 Péter Surányi. Portions Copyright (c) 2009 The Go
Authors. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

615
vendor/gopkg.in/inf.v0/dec.go generated vendored Normal file
View File

@@ -0,0 +1,615 @@
// Package inf (type inf.Dec) implements "infinite-precision" decimal
// arithmetic.
// "Infinite precision" describes two characteristics: practically unlimited
// precision for decimal number representation and no support for calculating
// with any specific fixed precision.
// (Although there is no practical limit on precision, inf.Dec can only
// represent finite decimals.)
//
// This package is currently in experimental stage and the API may change.
//
// This package does NOT support:
// - rounding to specific precisions (as opposed to specific decimal positions)
// - the notion of context (each rounding must be explicit)
// - NaN and Inf values, and distinguishing between positive and negative zero
// - conversions to and from float32/64 types
//
// Features considered for possible addition:
// + formatting options
// + Exp method
// + combined operations such as AddRound/MulAdd etc
// + exchanging data in decimal32/64/128 formats
//
package inf // import "gopkg.in/inf.v0"
// TODO:
// - avoid excessive deep copying (quo and rounders)
import (
"fmt"
"io"
"math/big"
"strings"
)
// A Dec represents a signed arbitrary-precision decimal.
// It is a combination of a sign, an arbitrary-precision integer coefficient
// value, and a signed fixed-precision exponent value.
// The sign and the coefficient value are handled together as a signed value
// and referred to as the unscaled value.
// (Positive and negative zero values are not distinguished.)
// Since the exponent is most commonly non-positive, it is handled in negated
// form and referred to as scale.
//
// The mathematical value of a Dec equals:
//
// unscaled * 10**(-scale)
//
// Note that different Dec representations may have equal mathematical values.
//
// unscaled scale String()
// -------------------------
// 0 0 "0"
// 0 2 "0.00"
// 0 -2 "0"
// 1 0 "1"
// 100 2 "1.00"
// 10 0 "10"
// 1 -1 "10"
//
// The zero value for a Dec represents the value 0 with scale 0.
//
// Operations are typically performed through the *Dec type.
// The semantics of the assignment operation "=" for "bare" Dec values is
// undefined and should not be relied on.
//
// Methods are typically of the form:
//
// func (z *Dec) Op(x, y *Dec) *Dec
//
// and implement operations z = x Op y with the result as receiver; if it
// is one of the operands it may be overwritten (and its memory reused).
// To enable chaining of operations, the result is also returned. Methods
// returning a result other than *Dec take one of the operands as the receiver.
//
// A "bare" Quo method (quotient / division operation) is not provided, as the
// result is not always a finite decimal and thus in general cannot be
// represented as a Dec.
// Instead, in the common case when rounding is (potentially) necessary,
// QuoRound should be used with a Scale and a Rounder.
// QuoExact or QuoRound with RoundExact can be used in the special cases when it
// is known that the result is always a finite decimal.
//
type Dec struct {
unscaled big.Int
scale Scale
}
// Scale represents the type used for the scale of a Dec.
type Scale int32
const scaleSize = 4 // bytes in a Scale value
// Scaler represents a method for obtaining the scale to use for the result of
// an operation on x and y.
type scaler interface {
Scale(x *Dec, y *Dec) Scale
}
var bigInt = [...]*big.Int{
big.NewInt(0), big.NewInt(1), big.NewInt(2), big.NewInt(3), big.NewInt(4),
big.NewInt(5), big.NewInt(6), big.NewInt(7), big.NewInt(8), big.NewInt(9),
big.NewInt(10),
}
var exp10cache [64]big.Int = func() [64]big.Int {
e10, e10i := [64]big.Int{}, bigInt[1]
for i, _ := range e10 {
e10[i].Set(e10i)
e10i = new(big.Int).Mul(e10i, bigInt[10])
}
return e10
}()
// NewDec allocates and returns a new Dec set to the given int64 unscaled value
// and scale.
func NewDec(unscaled int64, scale Scale) *Dec {
return new(Dec).SetUnscaled(unscaled).SetScale(scale)
}
// NewDecBig allocates and returns a new Dec set to the given *big.Int unscaled
// value and scale.
func NewDecBig(unscaled *big.Int, scale Scale) *Dec {
return new(Dec).SetUnscaledBig(unscaled).SetScale(scale)
}
// Scale returns the scale of x.
func (x *Dec) Scale() Scale {
return x.scale
}
// Unscaled returns the unscaled value of x for u and true for ok when the
// unscaled value can be represented as int64; otherwise it returns an undefined
// int64 value for u and false for ok. Use x.UnscaledBig().Int64() to avoid
// checking the validity of the value when the check is known to be redundant.
func (x *Dec) Unscaled() (u int64, ok bool) {
u = x.unscaled.Int64()
var i big.Int
ok = i.SetInt64(u).Cmp(&x.unscaled) == 0
return
}
// UnscaledBig returns the unscaled value of x as *big.Int.
func (x *Dec) UnscaledBig() *big.Int {
return &x.unscaled
}
// SetScale sets the scale of z, with the unscaled value unchanged, and returns
// z.
// The mathematical value of the Dec changes as if it was multiplied by
// 10**(oldscale-scale).
func (z *Dec) SetScale(scale Scale) *Dec {
z.scale = scale
return z
}
// SetUnscaled sets the unscaled value of z, with the scale unchanged, and
// returns z.
func (z *Dec) SetUnscaled(unscaled int64) *Dec {
z.unscaled.SetInt64(unscaled)
return z
}
// SetUnscaledBig sets the unscaled value of z, with the scale unchanged, and
// returns z.
func (z *Dec) SetUnscaledBig(unscaled *big.Int) *Dec {
z.unscaled.Set(unscaled)
return z
}
// Set sets z to the value of x and returns z.
// It does nothing if z == x.
func (z *Dec) Set(x *Dec) *Dec {
if z != x {
z.SetUnscaledBig(x.UnscaledBig())
z.SetScale(x.Scale())
}
return z
}
// Sign returns:
//
// -1 if x < 0
// 0 if x == 0
// +1 if x > 0
//
func (x *Dec) Sign() int {
return x.UnscaledBig().Sign()
}
// Neg sets z to -x and returns z.
func (z *Dec) Neg(x *Dec) *Dec {
z.SetScale(x.Scale())
z.UnscaledBig().Neg(x.UnscaledBig())
return z
}
// Cmp compares x and y and returns:
//
// -1 if x < y
// 0 if x == y
// +1 if x > y
//
func (x *Dec) Cmp(y *Dec) int {
xx, yy := upscale(x, y)
return xx.UnscaledBig().Cmp(yy.UnscaledBig())
}
// Abs sets z to |x| (the absolute value of x) and returns z.
func (z *Dec) Abs(x *Dec) *Dec {
z.SetScale(x.Scale())
z.UnscaledBig().Abs(x.UnscaledBig())
return z
}
// Add sets z to the sum x+y and returns z.
// The scale of z is the greater of the scales of x and y.
func (z *Dec) Add(x, y *Dec) *Dec {
xx, yy := upscale(x, y)
z.SetScale(xx.Scale())
z.UnscaledBig().Add(xx.UnscaledBig(), yy.UnscaledBig())
return z
}
// Sub sets z to the difference x-y and returns z.
// The scale of z is the greater of the scales of x and y.
func (z *Dec) Sub(x, y *Dec) *Dec {
xx, yy := upscale(x, y)
z.SetScale(xx.Scale())
z.UnscaledBig().Sub(xx.UnscaledBig(), yy.UnscaledBig())
return z
}
// Mul sets z to the product x*y and returns z.
// The scale of z is the sum of the scales of x and y.
func (z *Dec) Mul(x, y *Dec) *Dec {
z.SetScale(x.Scale() + y.Scale())
z.UnscaledBig().Mul(x.UnscaledBig(), y.UnscaledBig())
return z
}
// Round sets z to the value of x rounded to Scale s using Rounder r, and
// returns z.
func (z *Dec) Round(x *Dec, s Scale, r Rounder) *Dec {
return z.QuoRound(x, NewDec(1, 0), s, r)
}
// QuoRound sets z to the quotient x/y, rounded using the given Rounder to the
// specified scale.
//
// If the rounder is RoundExact but the result can not be expressed exactly at
// the specified scale, QuoRound returns nil, and the value of z is undefined.
//
// There is no corresponding Div method; the equivalent can be achieved through
// the choice of Rounder used.
//
func (z *Dec) QuoRound(x, y *Dec, s Scale, r Rounder) *Dec {
return z.quo(x, y, sclr{s}, r)
}
func (z *Dec) quo(x, y *Dec, s scaler, r Rounder) *Dec {
scl := s.Scale(x, y)
var zzz *Dec
if r.UseRemainder() {
zz, rA, rB := new(Dec).quoRem(x, y, scl, true, new(big.Int), new(big.Int))
zzz = r.Round(new(Dec), zz, rA, rB)
} else {
zz, _, _ := new(Dec).quoRem(x, y, scl, false, nil, nil)
zzz = r.Round(new(Dec), zz, nil, nil)
}
if zzz == nil {
return nil
}
return z.Set(zzz)
}
// QuoExact sets z to the quotient x/y and returns z when x/y is a finite
// decimal. Otherwise it returns nil and the value of z is undefined.
//
// The scale of a non-nil result is "x.Scale() - y.Scale()" or greater; it is
// calculated so that the remainder will be zero whenever x/y is a finite
// decimal.
func (z *Dec) QuoExact(x, y *Dec) *Dec {
return z.quo(x, y, scaleQuoExact{}, RoundExact)
}
// quoRem sets z to the quotient x/y with the scale s, and if useRem is true,
// it sets remNum and remDen to the numerator and denominator of the remainder.
// It returns z, remNum and remDen.
//
// The remainder is normalized to the range -1 < r < 1 to simplify rounding;
// that is, the results satisfy the following equation:
//
// x / y = z + (remNum/remDen) * 10**(-z.Scale())
//
// See Rounder for more details about rounding.
//
func (z *Dec) quoRem(x, y *Dec, s Scale, useRem bool,
remNum, remDen *big.Int) (*Dec, *big.Int, *big.Int) {
// difference (required adjustment) compared to "canonical" result scale
shift := s - (x.Scale() - y.Scale())
// pointers to adjusted unscaled dividend and divisor
var ix, iy *big.Int
switch {
case shift > 0:
// increased scale: decimal-shift dividend left
ix = new(big.Int).Mul(x.UnscaledBig(), exp10(shift))
iy = y.UnscaledBig()
case shift < 0:
// decreased scale: decimal-shift divisor left
ix = x.UnscaledBig()
iy = new(big.Int).Mul(y.UnscaledBig(), exp10(-shift))
default:
ix = x.UnscaledBig()
iy = y.UnscaledBig()
}
// save a copy of iy in case it to be overwritten with the result
iy2 := iy
if iy == z.UnscaledBig() {
iy2 = new(big.Int).Set(iy)
}
// set scale
z.SetScale(s)
// set unscaled
if useRem {
// Int division
_, intr := z.UnscaledBig().QuoRem(ix, iy, new(big.Int))
// set remainder
remNum.Set(intr)
remDen.Set(iy2)
} else {
z.UnscaledBig().Quo(ix, iy)
}
return z, remNum, remDen
}
type sclr struct{ s Scale }
func (s sclr) Scale(x, y *Dec) Scale {
return s.s
}
type scaleQuoExact struct{}
func (sqe scaleQuoExact) Scale(x, y *Dec) Scale {
rem := new(big.Rat).SetFrac(x.UnscaledBig(), y.UnscaledBig())
f2, f5 := factor2(rem.Denom()), factor(rem.Denom(), bigInt[5])
var f10 Scale
if f2 > f5 {
f10 = Scale(f2)
} else {
f10 = Scale(f5)
}
return x.Scale() - y.Scale() + f10
}
func factor(n *big.Int, p *big.Int) int {
// could be improved for large factors
d, f := n, 0
for {
dd, dm := new(big.Int).DivMod(d, p, new(big.Int))
if dm.Sign() == 0 {
f++
d = dd
} else {
break
}
}
return f
}
func factor2(n *big.Int) int {
// could be improved for large factors
f := 0
for ; n.Bit(f) == 0; f++ {
}
return f
}
func upscale(a, b *Dec) (*Dec, *Dec) {
if a.Scale() == b.Scale() {
return a, b
}
if a.Scale() > b.Scale() {
bb := b.rescale(a.Scale())
return a, bb
}
aa := a.rescale(b.Scale())
return aa, b
}
func exp10(x Scale) *big.Int {
if int(x) < len(exp10cache) {
return &exp10cache[int(x)]
}
return new(big.Int).Exp(bigInt[10], big.NewInt(int64(x)), nil)
}
func (x *Dec) rescale(newScale Scale) *Dec {
shift := newScale - x.Scale()
switch {
case shift < 0:
e := exp10(-shift)
return NewDecBig(new(big.Int).Quo(x.UnscaledBig(), e), newScale)
case shift > 0:
e := exp10(shift)
return NewDecBig(new(big.Int).Mul(x.UnscaledBig(), e), newScale)
}
return x
}
var zeros = []byte("00000000000000000000000000000000" +
"00000000000000000000000000000000")
var lzeros = Scale(len(zeros))
func appendZeros(s []byte, n Scale) []byte {
for i := Scale(0); i < n; i += lzeros {
if n > i+lzeros {
s = append(s, zeros...)
} else {
s = append(s, zeros[0:n-i]...)
}
}
return s
}
func (x *Dec) String() string {
if x == nil {
return "<nil>"
}
scale := x.Scale()
s := []byte(x.UnscaledBig().String())
if scale <= 0 {
if scale != 0 && x.unscaled.Sign() != 0 {
s = appendZeros(s, -scale)
}
return string(s)
}
negbit := Scale(-((x.Sign() - 1) / 2))
// scale > 0
lens := Scale(len(s))
if lens-negbit <= scale {
ss := make([]byte, 0, scale+2)
if negbit == 1 {
ss = append(ss, '-')
}
ss = append(ss, '0', '.')
ss = appendZeros(ss, scale-lens+negbit)
ss = append(ss, s[negbit:]...)
return string(ss)
}
// lens > scale
ss := make([]byte, 0, lens+1)
ss = append(ss, s[:lens-scale]...)
ss = append(ss, '.')
ss = append(ss, s[lens-scale:]...)
return string(ss)
}
// Format is a support routine for fmt.Formatter. It accepts the decimal
// formats 'd' and 'f', and handles both equivalently.
// Width, precision, flags and bases 2, 8, 16 are not supported.
func (x *Dec) Format(s fmt.State, ch rune) {
if ch != 'd' && ch != 'f' && ch != 'v' && ch != 's' {
fmt.Fprintf(s, "%%!%c(dec.Dec=%s)", ch, x.String())
return
}
fmt.Fprintf(s, x.String())
}
func (z *Dec) scan(r io.RuneScanner) (*Dec, error) {
unscaled := make([]byte, 0, 256) // collects chars of unscaled as bytes
dp, dg := -1, -1 // indexes of decimal point, first digit
loop:
for {
ch, _, err := r.ReadRune()
if err == io.EOF {
break loop
}
if err != nil {
return nil, err
}
switch {
case ch == '+' || ch == '-':
if len(unscaled) > 0 || dp >= 0 { // must be first character
r.UnreadRune()
break loop
}
case ch == '.':
if dp >= 0 {
r.UnreadRune()
break loop
}
dp = len(unscaled)
continue // don't add to unscaled
case ch >= '0' && ch <= '9':
if dg == -1 {
dg = len(unscaled)
}
default:
r.UnreadRune()
break loop
}
unscaled = append(unscaled, byte(ch))
}
if dg == -1 {
return nil, fmt.Errorf("no digits read")
}
if dp >= 0 {
z.SetScale(Scale(len(unscaled) - dp))
} else {
z.SetScale(0)
}
_, ok := z.UnscaledBig().SetString(string(unscaled), 10)
if !ok {
return nil, fmt.Errorf("invalid decimal: %s", string(unscaled))
}
return z, nil
}
// SetString sets z to the value of s, interpreted as a decimal (base 10),
// and returns z and a boolean indicating success. The scale of z is the
// number of digits after the decimal point (including any trailing 0s),
// or 0 if there is no decimal point. If SetString fails, the value of z
// is undefined but the returned value is nil.
func (z *Dec) SetString(s string) (*Dec, bool) {
r := strings.NewReader(s)
_, err := z.scan(r)
if err != nil {
return nil, false
}
_, _, err = r.ReadRune()
if err != io.EOF {
return nil, false
}
// err == io.EOF => scan consumed all of s
return z, true
}
// Scan is a support routine for fmt.Scanner; it sets z to the value of
// the scanned number. It accepts the decimal formats 'd' and 'f', and
// handles both equivalently. Bases 2, 8, 16 are not supported.
// The scale of z is the number of digits after the decimal point
// (including any trailing 0s), or 0 if there is no decimal point.
func (z *Dec) Scan(s fmt.ScanState, ch rune) error {
if ch != 'd' && ch != 'f' && ch != 's' && ch != 'v' {
return fmt.Errorf("Dec.Scan: invalid verb '%c'", ch)
}
s.SkipSpace()
_, err := z.scan(s)
return err
}
// Gob encoding version
const decGobVersion byte = 1
func scaleBytes(s Scale) []byte {
buf := make([]byte, scaleSize)
i := scaleSize
for j := 0; j < scaleSize; j++ {
i--
buf[i] = byte(s)
s >>= 8
}
return buf
}
func scale(b []byte) (s Scale) {
for j := 0; j < scaleSize; j++ {
s <<= 8
s |= Scale(b[j])
}
return
}
// GobEncode implements the gob.GobEncoder interface.
func (x *Dec) GobEncode() ([]byte, error) {
buf, err := x.UnscaledBig().GobEncode()
if err != nil {
return nil, err
}
buf = append(append(buf, scaleBytes(x.Scale())...), decGobVersion)
return buf, nil
}
// GobDecode implements the gob.GobDecoder interface.
func (z *Dec) GobDecode(buf []byte) error {
if len(buf) == 0 {
return fmt.Errorf("Dec.GobDecode: no data")
}
b := buf[len(buf)-1]
if b != decGobVersion {
return fmt.Errorf("Dec.GobDecode: encoding version %d not supported", b)
}
l := len(buf) - scaleSize - 1
err := z.UnscaledBig().GobDecode(buf[:l])
if err != nil {
return err
}
z.SetScale(scale(buf[l : l+scaleSize]))
return nil
}
// MarshalText implements the encoding.TextMarshaler interface.
func (x *Dec) MarshalText() ([]byte, error) {
return []byte(x.String()), nil
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (z *Dec) UnmarshalText(data []byte) error {
_, ok := z.SetString(string(data))
if !ok {
return fmt.Errorf("invalid inf.Dec")
}
return nil
}

145
vendor/gopkg.in/inf.v0/rounder.go generated vendored Normal file
View File

@@ -0,0 +1,145 @@
package inf
import (
"math/big"
)
// Rounder represents a method for rounding the (possibly infinite decimal)
// result of a division to a finite Dec. It is used by Dec.Round() and
// Dec.Quo().
//
// See the Example for results of using each Rounder with some sample values.
//
type Rounder rounder
// See http://speleotrove.com/decimal/damodel.html#refround for more detailed
// definitions of these rounding modes.
var (
RoundDown Rounder // towards 0
RoundUp Rounder // away from 0
RoundFloor Rounder // towards -infinity
RoundCeil Rounder // towards +infinity
RoundHalfDown Rounder // to nearest; towards 0 if same distance
RoundHalfUp Rounder // to nearest; away from 0 if same distance
RoundHalfEven Rounder // to nearest; even last digit if same distance
)
// RoundExact is to be used in the case when rounding is not necessary.
// When used with Quo or Round, it returns the result verbatim when it can be
// expressed exactly with the given precision, and it returns nil otherwise.
// QuoExact is a shorthand for using Quo with RoundExact.
var RoundExact Rounder
type rounder interface {
// When UseRemainder() returns true, the Round() method is passed the
// remainder of the division, expressed as the numerator and denominator of
// a rational.
UseRemainder() bool
// Round sets the rounded value of a quotient to z, and returns z.
// quo is rounded down (truncated towards zero) to the scale obtained from
// the Scaler in Quo().
//
// When the remainder is not used, remNum and remDen are nil.
// When used, the remainder is normalized between -1 and 1; that is:
//
// -|remDen| < remNum < |remDen|
//
// remDen has the same sign as y, and remNum is zero or has the same sign
// as x.
Round(z, quo *Dec, remNum, remDen *big.Int) *Dec
}
type rndr struct {
useRem bool
round func(z, quo *Dec, remNum, remDen *big.Int) *Dec
}
func (r rndr) UseRemainder() bool {
return r.useRem
}
func (r rndr) Round(z, quo *Dec, remNum, remDen *big.Int) *Dec {
return r.round(z, quo, remNum, remDen)
}
var intSign = []*big.Int{big.NewInt(-1), big.NewInt(0), big.NewInt(1)}
func roundHalf(f func(c int, odd uint) (roundUp bool)) func(z, q *Dec, rA, rB *big.Int) *Dec {
return func(z, q *Dec, rA, rB *big.Int) *Dec {
z.Set(q)
brA, brB := rA.BitLen(), rB.BitLen()
if brA < brB-1 {
// brA < brB-1 => |rA| < |rB/2|
return z
}
roundUp := false
srA, srB := rA.Sign(), rB.Sign()
s := srA * srB
if brA == brB-1 {
rA2 := new(big.Int).Lsh(rA, 1)
if s < 0 {
rA2.Neg(rA2)
}
roundUp = f(rA2.Cmp(rB)*srB, z.UnscaledBig().Bit(0))
} else {
// brA > brB-1 => |rA| > |rB/2|
roundUp = true
}
if roundUp {
z.UnscaledBig().Add(z.UnscaledBig(), intSign[s+1])
}
return z
}
}
func init() {
RoundExact = rndr{true,
func(z, q *Dec, rA, rB *big.Int) *Dec {
if rA.Sign() != 0 {
return nil
}
return z.Set(q)
}}
RoundDown = rndr{false,
func(z, q *Dec, rA, rB *big.Int) *Dec {
return z.Set(q)
}}
RoundUp = rndr{true,
func(z, q *Dec, rA, rB *big.Int) *Dec {
z.Set(q)
if rA.Sign() != 0 {
z.UnscaledBig().Add(z.UnscaledBig(), intSign[rA.Sign()*rB.Sign()+1])
}
return z
}}
RoundFloor = rndr{true,
func(z, q *Dec, rA, rB *big.Int) *Dec {
z.Set(q)
if rA.Sign()*rB.Sign() < 0 {
z.UnscaledBig().Add(z.UnscaledBig(), intSign[0])
}
return z
}}
RoundCeil = rndr{true,
func(z, q *Dec, rA, rB *big.Int) *Dec {
z.Set(q)
if rA.Sign()*rB.Sign() > 0 {
z.UnscaledBig().Add(z.UnscaledBig(), intSign[2])
}
return z
}}
RoundHalfDown = rndr{true, roundHalf(
func(c int, odd uint) bool {
return c > 0
})}
RoundHalfUp = rndr{true, roundHalf(
func(c int, odd uint) bool {
return c >= 0
})}
RoundHalfEven = rndr{true, roundHalf(
func(c int, odd uint) bool {
return c > 0 || c == 0 && odd == 1
})}
}

76
vendor/vendor.json vendored
View File

@@ -59,6 +59,30 @@
"revision": "ea383cf3ba6ec950874b8486cd72356d007c768f",
"revisionTime": "2017-04-10T19:29:09Z"
},
{
"checksumSHA1": "uWJDTv0R/NJVYv51LVy6vKP1CZw=",
"path": "github.com/appc/spec/schema",
"revision": "cbe99b7160b1397bf89f9c8bb1418f69c9424049",
"revisionTime": "2017-09-19T09:55:19Z"
},
{
"checksumSHA1": "Q47G6996hbfQaNp/8CFkGWTVQpw=",
"path": "github.com/appc/spec/schema/common",
"revision": "cbe99b7160b1397bf89f9c8bb1418f69c9424049",
"revisionTime": "2017-09-19T09:55:19Z"
},
{
"checksumSHA1": "kYXCle7Ikc8WqiMs7NXz99bUWqo=",
"path": "github.com/appc/spec/schema/types",
"revision": "cbe99b7160b1397bf89f9c8bb1418f69c9424049",
"revisionTime": "2017-09-19T09:55:19Z"
},
{
"checksumSHA1": "VgPsPj5PH7LKXMa3ZLe5/+Avydo=",
"path": "github.com/appc/spec/schema/types/resource",
"revision": "cbe99b7160b1397bf89f9c8bb1418f69c9424049",
"revisionTime": "2017-09-19T09:55:19Z"
},
{
"path": "github.com/armon/circbuf",
"revision": "bbbad097214e2918d8543d5201d12bfd7bca254d"
@@ -274,6 +298,18 @@
"revision": "7d649b46cdc2cd2ed102d350688a75a4fd7778c6",
"revisionTime": "2016-11-21T13:51:53Z"
},
{
"checksumSHA1": "NeAp/3+Hedu9tnMai+LihERPj84=",
"path": "github.com/containernetworking/cni/pkg/types",
"revision": "5c3c17164270150467498a32c71436c7cd5501be",
"revisionTime": "2016-06-02T16:00:07Z"
},
{
"checksumSHA1": "97BsbXOiZ8+Kr+LIuZkQFtSj7H4=",
"path": "github.com/coreos/go-semver/semver",
"revision": "1817cd4bea52af76542157eeabd74b057d1a199e",
"revisionTime": "2017-06-13T09:22:38Z"
},
{
"checksumSHA1": "/5cvgU+J4l7EhMXTK76KaCAfOuU=",
"path": "github.com/davecgh/go-spew/spew",
@@ -427,14 +463,14 @@
{
"checksumSHA1": "rArZ5mYIe9I1L5PRQOJu8BwafFw=",
"path": "github.com/docker/docker/pkg/pools",
"revision": "52debcd58ac91bf68503ce60561536911b74ff05",
"revisionTime": "2016-05-20T15:17:10Z"
"revision": "da39e9a4f920a15683dd0f23923c302d4db6eed5",
"revisionTime": "2016-05-28T08:11:04Z"
},
{
"checksumSHA1": "rArZ5mYIe9I1L5PRQOJu8BwafFw=",
"path": "github.com/docker/docker/pkg/pools",
"revision": "da39e9a4f920a15683dd0f23923c302d4db6eed5",
"revisionTime": "2016-05-28T08:11:04Z"
"revision": "52debcd58ac91bf68503ce60561536911b74ff05",
"revisionTime": "2016-05-20T15:17:10Z"
},
{
"checksumSHA1": "txf3EORYff4hO6PEvwBm2lyh1MU=",
@@ -1246,6 +1282,20 @@
"revision": "e645f4e5aaa8506fc71d6edbc5c4ff02c04c46f2",
"revisionTime": "2017-07-03T10:12:42Z"
},
{
"checksumSHA1": "ge4Z0w3QJJYTBqJaK3S+a6MCxzQ=",
"path": "github.com/rkt/rkt/api/v1",
"revision": "3abde24bc284b7ded5784c56b4e8184c28999641",
"revisionTime": "2017-08-01T12:18:56Z",
"version": "v1.28.1",
"versionExact": "v1.28.1"
},
{
"checksumSHA1": "4QqLbh9MmajcN6gCx8Er1voiQys=",
"path": "github.com/rkt/rkt/networking/netinfo",
"revision": "5e83d91aafef5f7a38fef62c045e8b57eeeb8bce",
"revisionTime": "2017-09-20T12:17:54Z"
},
{
"checksumSHA1": "M57Rrfc8Z966p+IBtQ91QOcUtcg=",
"comment": "v2.0.1-8-g983d3a5",
@@ -1319,6 +1369,12 @@
"revision": "bb4de0191aa41b5507caa14b0650cdbddcd9280b",
"revisionTime": "2016-09-30T03:27:40Z"
},
{
"checksumSHA1": "Q52Y7t0lEtk/wcDn5q7tS7B+jqs=",
"path": "github.com/spf13/pflag",
"revision": "7aff26db30c1be810f9de5038ec5ef96ac41fd7c",
"revisionTime": "2017-08-24T17:57:12Z"
},
{
"checksumSHA1": "K0crHygPTP42i1nLKWphSlvOQJw=",
"path": "github.com/stretchr/objx",
@@ -1367,6 +1423,12 @@
"revision": "0c6b41e72360850ca4f98dc341fd999726ea007f",
"revisionTime": "2017-06-05T21:53:11Z"
},
{
"checksumSHA1": "PMr/a5kcnC4toJtVwWhlU5E4tJY=",
"path": "go4.org/errorutil",
"revision": "034d17a462f7b2dcd1a4a73553ec5357ff6e6c6e",
"revisionTime": "2017-05-24T23:16:39Z"
},
{
"checksumSHA1": "5TlXhxVMqfHQKpCKucmXNeE6/kc=",
"path": "golang.org/x/crypto/blake2b",
@@ -1613,6 +1675,12 @@
"revision": "a8a77c9133d2d6fd8334f3260d06f60e8d80a5fb",
"revisionTime": "2016-06-29T01:11:04Z"
},
{
"checksumSHA1": "6f8MEU31llHM1sLM/GGH4/Qxu0A=",
"path": "gopkg.in/inf.v0",
"revision": "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4",
"revisionTime": "2015-09-11T12:57:57Z"
},
{
"checksumSHA1": "i97goLq3AIfUNB8l1hxGGMSW0+s=",
"path": "gopkg.in/lxc/go-lxc.v2",

View File

@@ -180,8 +180,8 @@ The `rkt` driver will set the following client attributes:
* `driver.rkt` - Set to `1` if rkt is found on the host node. Nomad determines
this by executing `rkt version` on the host and parsing the output
* `driver.rkt.version` - Version of `rkt` e.g.: `1.1.0`. Note that the minimum required
version is `1.0.0`
* `driver.rkt.version` - Version of `rkt` e.g.: `1.27.0`. Note that the minimum required
version is `1.27.0`
* `driver.rkt.appc.version` - Version of `appc` that `rkt` is using e.g.: `1.1.0`
Here is an example of using these properties in a job file: