mirror of
https://github.com/lxc/crio-lxc.git
synced 2026-02-05 09:45:04 +01:00
Initial commit of crio-lxc
Use an init wrapper to bind in the syncfifo over which we will then inform cri-o that we are ready. This way we don't need any coordination from liblxc at all to emulate the desired protocol. Signed-off-by: Michael McCracken <mikmccra@cisco.com> Signed-off-by: Tycho Andersen <tycho@tycho.ws> Signed-off-by: Serge Hallyn <shallyn@cisco.com>
This commit is contained in:
committed by
Serge Hallyn
parent
77276bea1c
commit
19cd17cd88
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*~
|
||||
26
LICENSE
26
LICENSE
@@ -1,3 +1,4 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
@@ -174,28 +175,3 @@
|
||||
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.
|
||||
|
||||
22
Makefile
Normal file
22
Makefile
Normal file
@@ -0,0 +1,22 @@
|
||||
GO_SRC=$(shell find . -name \*.go)
|
||||
COMMIT_HASH=$(shell git rev-parse HEAD)
|
||||
COMMIT=$(if $(shell git status --porcelain --untracked-files=no),$(COMMIT_HASH)-dirty,$(COMMIT_HASH))
|
||||
TEST?=$(patsubst test/%.bats,%,$(wildcard test/*.bats))
|
||||
|
||||
crio-lxc: $(GO_SRC)
|
||||
go build -ldflags "-X main.version=$(COMMIT)" -o crio-lxc ./cmd
|
||||
|
||||
# make test TEST=basic will run only the basic test.
|
||||
.PHONY: check
|
||||
check: crio-lxc
|
||||
go fmt ./... && ([ -z $(TRAVIS) ] || git diff --quiet)
|
||||
go test ./...
|
||||
sudo -E "PATH=$$PATH" bats -t $(patsubst %,test/%.bats,$(TEST))
|
||||
|
||||
.PHONY: vendorup
|
||||
vendorup:
|
||||
go get -u
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
-rm -r crio-lxc
|
||||
14
README.md
Normal file
14
README.md
Normal file
@@ -0,0 +1,14 @@
|
||||
# crio-lxc
|
||||
|
||||
This is a wrapper around [LXC](https://github.com/lxc/lxc) which can be used as
|
||||
a drop-in container runtime replacement for use by
|
||||
[CRI-O](https://github.com/kubernetes-sigs/cri-o).
|
||||
|
||||
To use this, simply build it:
|
||||
|
||||
```
|
||||
make
|
||||
```
|
||||
|
||||
Then specify the `crio-lxc` binary you just built as the value for
|
||||
`default_runtime` in the `crio.runtime` section of `/etc/crio/crio.conf`.
|
||||
212
cmd/create.go
Normal file
212
cmd/create.go
Normal file
@@ -0,0 +1,212 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
lxc "gopkg.in/lxc/go-lxc.v2"
|
||||
)
|
||||
|
||||
var createCmd = cli.Command{
|
||||
Name: "create",
|
||||
Usage: "create a container from a bundle directory",
|
||||
ArgsUsage: "<containerID>",
|
||||
Action: doCreate,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "bundle",
|
||||
Usage: "set bundle directory",
|
||||
Value: ".",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "console-socket",
|
||||
Usage: "pty master FD", // TODO not handled yet
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "pid-file",
|
||||
Usage: "path to write container PID", // TODO not handled yet
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func emitFifoWaiter(file string) error {
|
||||
fifoWaiter := fmt.Sprintf(`#!/bin/sh
|
||||
stat /syncfifo
|
||||
echo "%s" | tee /syncfifo
|
||||
exec $@
|
||||
`, SYNC_FIFO_CONTENT)
|
||||
|
||||
return ioutil.WriteFile(file, []byte(fifoWaiter), 0755)
|
||||
}
|
||||
|
||||
func doCreate(ctx *cli.Context) error {
|
||||
containerID := ctx.Args().Get(0)
|
||||
if len(containerID) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "missing container ID\n")
|
||||
cli.ShowCommandHelpAndExit(ctx, "create", 1)
|
||||
}
|
||||
log.Infof("creating container %s", containerID)
|
||||
|
||||
exists, err := containerExists(containerID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to check if container exists")
|
||||
}
|
||||
if exists {
|
||||
return fmt.Errorf("container '%s' already exists", containerID)
|
||||
}
|
||||
|
||||
c, err := lxc.NewContainer(containerID, LXC_PATH)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to create new container")
|
||||
}
|
||||
defer c.Release()
|
||||
|
||||
spec, err := readBundleSpec(filepath.Join(ctx.String("bundle"), "config.json"))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "couldn't load bundle spec")
|
||||
}
|
||||
|
||||
if err := os.MkdirAll(filepath.Join(LXC_PATH, containerID), 0770); err != nil {
|
||||
return errors.Wrap(err, "failed to create container dir")
|
||||
}
|
||||
|
||||
if err := makeSyncFifo(filepath.Join(LXC_PATH, containerID)); err != nil {
|
||||
return errors.Wrap(err, "failed to make sync fifo")
|
||||
}
|
||||
|
||||
if err := configureContainer(ctx, c, spec); err != nil {
|
||||
return errors.Wrap(err, "failed to configure container")
|
||||
}
|
||||
|
||||
log.Infof("created syncfifo, executing %#v", spec.Process.Args)
|
||||
|
||||
if err := startContainer(c, spec); err != nil {
|
||||
return errors.Wrap(err, "failed to start the container init")
|
||||
}
|
||||
|
||||
log.Infof("created container %s in lxcdir %s", containerID, LXC_PATH)
|
||||
return nil
|
||||
}
|
||||
|
||||
func configureContainer(ctx *cli.Context, c *lxc.Container, spec *specs.Spec) error {
|
||||
if ctx.Bool("debug") {
|
||||
c.SetVerbosity(lxc.Verbose)
|
||||
}
|
||||
|
||||
if err := configureLogging(ctx, c); err != nil {
|
||||
return errors.Wrap(err, "failed to configure logging")
|
||||
}
|
||||
|
||||
// rootfs
|
||||
// todo Root.Readonly? - use lxc.rootfs.options
|
||||
if err := c.SetConfigItem("lxc.rootfs.path", spec.Root.Path); err != nil {
|
||||
return errors.Wrapf(err, "failed to set rootfs: '%s'", spec.Root.Path)
|
||||
}
|
||||
if err := c.SetConfigItem("lxc.rootfs.managed", "0"); err != nil {
|
||||
return errors.Wrap(err, "failed to set rootfs.managed to 0")
|
||||
}
|
||||
|
||||
for _, envVar := range spec.Process.Env {
|
||||
if err := c.SetConfigItem("lxc.environment", envVar); err != nil {
|
||||
return fmt.Errorf("error setting environment variable '%s': %v", envVar, err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, ms := range spec.Mounts {
|
||||
opts := strings.Join(ms.Options, ",")
|
||||
mnt := fmt.Sprintf("%s %s %s %s", ms.Source, ms.Destination, ms.Type, opts)
|
||||
if err := c.SetConfigItem("lxc.mount.entry", mnt); err != nil {
|
||||
return errors.Wrap(err, "failed to set mount config")
|
||||
}
|
||||
}
|
||||
|
||||
mnt := fmt.Sprintf("%s %s none ro,bind,create=file", path.Join(LXC_PATH, c.Name(), SYNC_FIFO_PATH), strings.Trim(SYNC_FIFO_PATH, "/"))
|
||||
if err := c.SetConfigItem("lxc.mount.entry", mnt); err != nil {
|
||||
return errors.Wrap(err, "failed to set syncfifo mount config entry")
|
||||
}
|
||||
|
||||
err := emitFifoWaiter(path.Join(spec.Root.Path, "fifo-wait"))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "couldn't write wrapper init")
|
||||
}
|
||||
|
||||
if err := c.SetConfigItem("lxc.init.cwd", spec.Process.Cwd); err != nil {
|
||||
return errors.Wrap(err, "failed to set CWD")
|
||||
}
|
||||
|
||||
if err := c.SetConfigItem("lxc.uts.name", spec.Hostname); err != nil {
|
||||
return errors.Wrap(err, "failed to set hostname")
|
||||
}
|
||||
|
||||
argsString := "/fifo-wait " + strings.Join(spec.Process.Args, " ")
|
||||
if err := c.SetConfigItem("lxc.execute.cmd", argsString); err != nil {
|
||||
return errors.Wrap(err, "failed to set lxc.execute.cmd")
|
||||
|
||||
}
|
||||
if err := c.SetConfigItem("lxc.hook.version", "1"); err != nil {
|
||||
return errors.Wrap(err, "failed to set hook version")
|
||||
}
|
||||
|
||||
// capabilities?
|
||||
|
||||
// if !spec.Process.Terminal {
|
||||
// passFdsToContainer()
|
||||
// }
|
||||
|
||||
// Write out final config file for debugging and use with lxc-attach:
|
||||
// Do not edit config after this.
|
||||
savedConfigFile := filepath.Join(LXC_PATH, c.Name(), "config")
|
||||
if err := c.SaveConfigFile(savedConfigFile); err != nil {
|
||||
return errors.Wrapf(err, "failed to save config file to '%s'", savedConfigFile)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func makeSyncFifo(dir string) error {
|
||||
fifoFilename := filepath.Join(dir, "syncfifo")
|
||||
prevMask := unix.Umask(0000)
|
||||
defer unix.Umask(prevMask)
|
||||
if err := unix.Mkfifo(fifoFilename, 0622); err != nil {
|
||||
return errors.Wrapf(err, "failed to make fifo '%s'", fifoFilename)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func startContainer(c *lxc.Container, spec *specs.Spec) error {
|
||||
binary, err := os.Readlink("/proc/self/exe")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cmd := exec.Command(
|
||||
binary,
|
||||
"internal",
|
||||
c.Name(),
|
||||
spec.Root.Path,
|
||||
filepath.Join(LXC_PATH, c.Name(), "config"),
|
||||
)
|
||||
|
||||
if !spec.Process.Terminal {
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
}
|
||||
|
||||
cmdErr := cmd.Start()
|
||||
|
||||
return cmdErr
|
||||
|
||||
}
|
||||
7
cmd/defs.go
Normal file
7
cmd/defs.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package main
|
||||
|
||||
var (
|
||||
CURRENT_OCI_VERSION = "0.2.1"
|
||||
// controlled by --lxc-path arg to main
|
||||
LXC_PATH = ""
|
||||
)
|
||||
75
cmd/delete.go
Normal file
75
cmd/delete.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
lxc "gopkg.in/lxc/go-lxc.v2"
|
||||
)
|
||||
|
||||
var deleteCmd = cli.Command{
|
||||
Name: "delete",
|
||||
Usage: "deletes a container",
|
||||
Action: doDelete,
|
||||
ArgsUsage: `[containerID]
|
||||
|
||||
<containerID> is the ID of the container to delete
|
||||
`,
|
||||
Flags: []cli.Flag{},
|
||||
}
|
||||
|
||||
func doDelete(ctx *cli.Context) error {
|
||||
containerID := ctx.Args().Get(0)
|
||||
if len(containerID) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "missing container ID\n")
|
||||
cli.ShowCommandHelpAndExit(ctx, "state", 1)
|
||||
}
|
||||
|
||||
exists, err := containerExists(containerID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to check if container exists")
|
||||
}
|
||||
if !exists {
|
||||
return fmt.Errorf("container '%s' not found", containerID)
|
||||
}
|
||||
|
||||
c, err := lxc.NewContainer(containerID, LXC_PATH)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to load container")
|
||||
}
|
||||
defer c.Release()
|
||||
|
||||
if err := configureLogging(ctx, c); err != nil {
|
||||
return errors.Wrap(err, "failed to configure logging")
|
||||
|
||||
}
|
||||
|
||||
if c.Running() {
|
||||
return fmt.Errorf("container '%s' is running, cannot delete.", containerID)
|
||||
}
|
||||
|
||||
// TODO: lxc-destroy deletes the rootfs.
|
||||
// this appears to contradict the runtime spec:
|
||||
|
||||
// "Note that resources associated with the container,
|
||||
// but not created by this container, MUST NOT be deleted.Note
|
||||
// that resources associated with the container, but not
|
||||
// created by this container, MUST NOT be deleted.
|
||||
|
||||
if err := c.Destroy(); err != nil {
|
||||
return errors.Wrap(err, "failed to delete container.")
|
||||
}
|
||||
|
||||
// TODO - because we set rootfs.managed=0, Destroy() doesn't
|
||||
// delete the /var/lib/lxc/$containerID/config file:
|
||||
configDir := filepath.Join(LXC_PATH, containerID)
|
||||
if err := os.RemoveAll(configDir); err != nil {
|
||||
return errors.Wrapf(err, "failed to remove %s", configDir)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
48
cmd/fifo-wait.go
Normal file
48
cmd/fifo-wait.go
Normal file
@@ -0,0 +1,48 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
const (
|
||||
SYNC_FIFO_PATH = "/syncfifo"
|
||||
SYNC_FIFO_CONTENT = "meshuggah rocks"
|
||||
)
|
||||
|
||||
var fifoWaitCmd = cli.Command{
|
||||
Name: "fifo-wait",
|
||||
Action: doFifoWait,
|
||||
Hidden: true,
|
||||
}
|
||||
|
||||
func doFifoWait(ctx *cli.Context) error {
|
||||
syncPipe, err := os.Open(SYNC_FIFO_PATH)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "couldn't open %s", SYNC_FIFO_PATH)
|
||||
}
|
||||
defer syncPipe.Close()
|
||||
|
||||
fi, err := syncPipe.Stat()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "couldn't stat %s", SYNC_FIFO_PATH)
|
||||
}
|
||||
|
||||
if fi.Mode()&os.ModeNamedPipe == 0 {
|
||||
return errors.Errorf("%s exists and is not a named pipe", SYNC_FIFO_PATH)
|
||||
}
|
||||
|
||||
_, err = syncPipe.WriteString(SYNC_FIFO_CONTENT)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "could write to fifo")
|
||||
}
|
||||
|
||||
cmd := exec.Command(ctx.Args().Get(0), ctx.Args().Tail()...)
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
return cmd.Run()
|
||||
}
|
||||
117
cmd/internal.go
Normal file
117
cmd/internal.go
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* This file is a little bit strange. The problem is that we want to do
|
||||
* daemonized containers with liblxc, but we can't spawn containers in threaded
|
||||
* environments (i.e. golang), with go-lxc. So instead, we embed some C into
|
||||
* our program that catches execution before golang starts. This way, we can do
|
||||
* a tiny C program to actually spawn the container.
|
||||
*
|
||||
*/
|
||||
package main
|
||||
|
||||
// #cgo LDFLAGS: -llxc
|
||||
/*
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <lxc/lxccontainer.h>
|
||||
|
||||
static int spawn_container(char *name, char *lxcpath, char *config)
|
||||
{
|
||||
struct lxc_container *c;
|
||||
|
||||
c = lxc_container_new(name, lxcpath);
|
||||
if (!c) {
|
||||
fprintf(stderr, "failed to create container %s\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
c->clear_config(c);
|
||||
if (!c->load_config(c, config)) {
|
||||
fprintf(stderr, "failed to load container config at %s\n", config);
|
||||
return -1;
|
||||
}
|
||||
|
||||
c->daemonize = false;
|
||||
if (!c->start(c, 1, NULL)) {
|
||||
fprintf(stderr, "failed to start container %s\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return c->error_num;
|
||||
}
|
||||
|
||||
// main function for the "internal" command. Right now, arguments look like:
|
||||
// argv[0] internal <container_name> <lxcpath> <config_path>
|
||||
__attribute__((constructor)) void internal(void)
|
||||
{
|
||||
int ret, status;
|
||||
char buf[4096];
|
||||
ssize_t size;
|
||||
char *cur, *name, *lxcpath, *config_path;
|
||||
|
||||
ret = open("/proc/self/cmdline", O_RDONLY);
|
||||
if (ret < 0) {
|
||||
perror("error: open");
|
||||
exit(96);
|
||||
}
|
||||
|
||||
if ((size = read(ret, buf, sizeof(buf)-1)) < 0) {
|
||||
close(ret);
|
||||
perror("error: read");
|
||||
exit(96);
|
||||
}
|
||||
close(ret);
|
||||
|
||||
// /proc/self/cmdline is null separated, but let's be real safe
|
||||
buf[size] = 0;
|
||||
cur = buf;
|
||||
|
||||
#define ADVANCE_ARG \
|
||||
do { \
|
||||
while (*cur) { \
|
||||
cur++; \
|
||||
} \
|
||||
cur++; \
|
||||
} while (0)
|
||||
|
||||
// skip argv[0]
|
||||
ADVANCE_ARG;
|
||||
|
||||
// is this really the internal command, if not, continue normal execution
|
||||
if (strcmp(cur, "internal"))
|
||||
return;
|
||||
|
||||
ADVANCE_ARG;
|
||||
name = cur;
|
||||
ADVANCE_ARG;
|
||||
lxcpath = cur;
|
||||
ADVANCE_ARG;
|
||||
config_path = cur;
|
||||
|
||||
ret = isatty(STDIN_FILENO);
|
||||
if (ret < 0) {
|
||||
perror("isatty");
|
||||
exit(96);
|
||||
}
|
||||
|
||||
// If this is non interactive, get rid of our controlling terminal,
|
||||
// since we don't want lxc's setting of ISIG to ignore user's ^Cs.
|
||||
if (!ret)
|
||||
setsid();
|
||||
|
||||
status = spawn_container(name, lxcpath, config_path);
|
||||
|
||||
// Try and propagate the container's exit code.
|
||||
if (WIFEXITED(status)) {
|
||||
exit(WEXITSTATUS(status));
|
||||
} else {
|
||||
kill(0, WTERMSIG(status));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
106
cmd/kill.go
Normal file
106
cmd/kill.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
"golang.org/x/sys/unix"
|
||||
|
||||
//"github.com/apex/log"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
lxc "gopkg.in/lxc/go-lxc.v2"
|
||||
)
|
||||
|
||||
var killCmd = cli.Command{
|
||||
Name: "kill",
|
||||
Usage: "sends a signal to a container",
|
||||
Action: doKill,
|
||||
ArgsUsage: `[containerID]
|
||||
|
||||
<containerID> is the ID of the container to send a signal to
|
||||
`,
|
||||
Flags: []cli.Flag{
|
||||
cli.StringFlag{
|
||||
Name: "signal",
|
||||
Usage: "the signal to send, as a string",
|
||||
Value: "TERM",
|
||||
},
|
||||
},
|
||||
}
|
||||
var signalMap = map[string]syscall.Signal{
|
||||
"ABRT": unix.SIGABRT,
|
||||
"ALRM": unix.SIGALRM,
|
||||
"BUS": unix.SIGBUS,
|
||||
"CHLD": unix.SIGCHLD,
|
||||
"CLD": unix.SIGCLD,
|
||||
"CONT": unix.SIGCONT,
|
||||
"FPE": unix.SIGFPE,
|
||||
"HUP": unix.SIGHUP,
|
||||
"ILL": unix.SIGILL,
|
||||
"INT": unix.SIGINT,
|
||||
"IO": unix.SIGIO,
|
||||
"IOT": unix.SIGIOT,
|
||||
"KILL": unix.SIGKILL,
|
||||
"PIPE": unix.SIGPIPE,
|
||||
"POLL": unix.SIGPOLL,
|
||||
"PROF": unix.SIGPROF,
|
||||
"PWR": unix.SIGPWR,
|
||||
"QUIT": unix.SIGQUIT,
|
||||
"SEGV": unix.SIGSEGV,
|
||||
"STKFLT": unix.SIGSTKFLT,
|
||||
"STOP": unix.SIGSTOP,
|
||||
"SYS": unix.SIGSYS,
|
||||
"TERM": unix.SIGTERM,
|
||||
"TRAP": unix.SIGTRAP,
|
||||
"TSTP": unix.SIGTSTP,
|
||||
"TTIN": unix.SIGTTIN,
|
||||
"TTOU": unix.SIGTTOU,
|
||||
"URG": unix.SIGURG,
|
||||
"USR1": unix.SIGUSR1,
|
||||
"USR2": unix.SIGUSR2,
|
||||
"VTALRM": unix.SIGVTALRM,
|
||||
"WINCH": unix.SIGWINCH,
|
||||
"XCPU": unix.SIGXCPU,
|
||||
"XFSZ": unix.SIGXFSZ,
|
||||
}
|
||||
|
||||
func doKill(ctx *cli.Context) error {
|
||||
containerID := ctx.Args().Get(0)
|
||||
if len(containerID) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "missing container ID\n")
|
||||
cli.ShowCommandHelpAndExit(ctx, "state", 1)
|
||||
}
|
||||
|
||||
exists, err := containerExists(containerID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to check if container exists")
|
||||
}
|
||||
if !exists {
|
||||
return fmt.Errorf("container '%s' not found", containerID)
|
||||
}
|
||||
|
||||
c, err := lxc.NewContainer(containerID, LXC_PATH)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to load container")
|
||||
}
|
||||
defer c.Release()
|
||||
|
||||
if err := configureLogging(ctx, c); err != nil {
|
||||
return errors.Wrap(err, "failed to configure logging")
|
||||
|
||||
}
|
||||
|
||||
if !c.Running() {
|
||||
return fmt.Errorf("container '%s' is not running", containerID)
|
||||
}
|
||||
|
||||
pid := c.InitPid()
|
||||
|
||||
if err := unix.Kill(pid, signalMap[ctx.String("signal")]); err != nil {
|
||||
return errors.Wrap(err, "failed to send signal")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
67
cmd/main.go
Normal file
67
cmd/main.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/apex/log"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
var (
|
||||
version = ""
|
||||
debug = false
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "crio-lxc"
|
||||
app.Usage = "crio-lxc is a CRI compliant runtime wrapper for lxc"
|
||||
app.Version = version
|
||||
app.Commands = []cli.Command{
|
||||
stateCmd,
|
||||
createCmd,
|
||||
startCmd,
|
||||
killCmd,
|
||||
deleteCmd,
|
||||
}
|
||||
|
||||
app.Flags = []cli.Flag{
|
||||
cli.BoolFlag{
|
||||
Name: "debug",
|
||||
Usage: "enable debug mode",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "log-level",
|
||||
Usage: "set log level for LXC",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "log-file",
|
||||
Usage: "log file for LXC",
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "lxc-path, root",
|
||||
Usage: "set the lxc path to use",
|
||||
Value: "/var/lib/lxc",
|
||||
},
|
||||
}
|
||||
|
||||
app.Before = func(ctx *cli.Context) error {
|
||||
LXC_PATH = ctx.String("lxc-path")
|
||||
|
||||
debug = ctx.Bool("debug")
|
||||
return nil
|
||||
}
|
||||
|
||||
log.SetLevel(log.InfoLevel)
|
||||
|
||||
if err := app.Run(os.Args); err != nil {
|
||||
format := "error: %v\n"
|
||||
if debug {
|
||||
format = "error: %+v\n"
|
||||
}
|
||||
|
||||
fmt.Fprintf(os.Stderr, format, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
63
cmd/start.go
Normal file
63
cmd/start.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/apex/log"
|
||||
// "github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
lxc "gopkg.in/lxc/go-lxc.v2"
|
||||
)
|
||||
|
||||
var startCmd = cli.Command{
|
||||
Name: "start",
|
||||
Usage: "starts a container",
|
||||
Action: doStart,
|
||||
ArgsUsage: `[containerID]
|
||||
|
||||
starts <containerID>
|
||||
`,
|
||||
}
|
||||
|
||||
func doStart(ctx *cli.Context) error {
|
||||
containerID := ctx.Args().Get(0)
|
||||
if len(containerID) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "missing container ID\n")
|
||||
cli.ShowCommandHelpAndExit(ctx, "state", 1)
|
||||
}
|
||||
|
||||
log.Infof("about to create container")
|
||||
c, err := lxc.NewContainer(containerID, LXC_PATH)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to load container")
|
||||
}
|
||||
defer c.Release()
|
||||
log.Infof("checking if running")
|
||||
if c.Running() {
|
||||
return fmt.Errorf("'%s' is already running", containerID)
|
||||
}
|
||||
log.Infof("not running, can start")
|
||||
fifoPath := filepath.Join(LXC_PATH, containerID, "syncfifo")
|
||||
log.Infof("opening fifo '%s'", fifoPath)
|
||||
f, err := os.OpenFile(fifoPath, os.O_RDWR, 0)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to open sync fifo")
|
||||
}
|
||||
|
||||
log.Infof("opened fifo, reading")
|
||||
data := make([]byte, len(SYNC_FIFO_CONTENT))
|
||||
n, err := f.Read(data)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "problem reading from fifo")
|
||||
}
|
||||
if n != len(SYNC_FIFO_CONTENT) || string(data) != SYNC_FIFO_CONTENT {
|
||||
return errors.Errorf("bad fifo content: %s", string(data))
|
||||
}
|
||||
|
||||
log.Infof("read '%s' from fifo, done", data)
|
||||
return nil
|
||||
}
|
||||
82
cmd/state.go
Normal file
82
cmd/state.go
Normal file
@@ -0,0 +1,82 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
// "github.com/apex/log"
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
lxc "gopkg.in/lxc/go-lxc.v2"
|
||||
)
|
||||
|
||||
var stateCmd = cli.Command{
|
||||
Name: "state",
|
||||
Usage: "returns state of a container",
|
||||
Action: doState,
|
||||
ArgsUsage: `[containerID]
|
||||
|
||||
<containerID> is the ID of the container you want to know about.
|
||||
`,
|
||||
Flags: []cli.Flag{},
|
||||
}
|
||||
|
||||
func doState(ctx *cli.Context) error {
|
||||
containerID := ctx.Args().Get(0)
|
||||
if len(containerID) == 0 {
|
||||
fmt.Fprintf(os.Stderr, "missing container ID\n")
|
||||
cli.ShowCommandHelpAndExit(ctx, "state", 1)
|
||||
}
|
||||
|
||||
exists, err := containerExists(containerID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to check if container exists")
|
||||
}
|
||||
if !exists {
|
||||
return fmt.Errorf("container '%s' not found", containerID)
|
||||
}
|
||||
|
||||
c, err := lxc.NewContainer(containerID, LXC_PATH)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to load container")
|
||||
}
|
||||
defer c.Release()
|
||||
|
||||
if err := configureLogging(ctx, c); err != nil {
|
||||
return errors.Wrap(err, "failed to configure logging")
|
||||
|
||||
}
|
||||
|
||||
// TODO need to detect 'created' per
|
||||
// https://github.com/opencontainers/runtime-spec/blob/v1.0.0-rc4/runtime.md#state
|
||||
// it means "the container process has neither exited nor executed the user-specified program"
|
||||
status := "stopped"
|
||||
if c.Running() {
|
||||
status = "running"
|
||||
}
|
||||
pid := 0
|
||||
// bundlePath is the enclosing directory of the rootfs:
|
||||
// https://github.com/opencontainers/runtime-spec/blob/v1.0.0-rc4/bundle.md
|
||||
bundlePath := filepath.Dir(c.ConfigItem("lxc.rootfs.path")[0])
|
||||
annotations := map[string]string{}
|
||||
s := specs.State{
|
||||
Version: CURRENT_OCI_VERSION,
|
||||
ID: containerID,
|
||||
Status: status,
|
||||
Pid: pid,
|
||||
Bundle: bundlePath,
|
||||
Annotations: annotations,
|
||||
}
|
||||
|
||||
stateJson, err := json.Marshal(s)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to marshal json")
|
||||
}
|
||||
fmt.Fprintf(os.Stdout, string(stateJson))
|
||||
|
||||
return nil
|
||||
}
|
||||
77
cmd/utils.go
Normal file
77
cmd/utils.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/opencontainers/runtime-spec/specs-go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/urfave/cli"
|
||||
|
||||
lxc "gopkg.in/lxc/go-lxc.v2"
|
||||
)
|
||||
|
||||
func readBundleSpec(specFilePath string) (spec *specs.Spec, err error) {
|
||||
specFile, err := os.Open(specFilePath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to open spec file '%s'", specFilePath)
|
||||
}
|
||||
defer specFile.Close()
|
||||
err = json.NewDecoder(specFile).Decode(&spec)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to decode spec file")
|
||||
}
|
||||
|
||||
return spec, nil
|
||||
}
|
||||
|
||||
func configureLogging(ctx *cli.Context, c *lxc.Container) error {
|
||||
if ctx.GlobalIsSet("log-level") {
|
||||
logLevel := lxc.TRACE
|
||||
switch ctx.GlobalString("log-level") {
|
||||
case "trace":
|
||||
logLevel = lxc.TRACE
|
||||
case "debug":
|
||||
logLevel = lxc.DEBUG
|
||||
case "info":
|
||||
logLevel = lxc.INFO
|
||||
case "warn":
|
||||
logLevel = lxc.WARN
|
||||
case "", "error":
|
||||
logLevel = lxc.ERROR
|
||||
default:
|
||||
return fmt.Errorf("lxc driver config 'log_level' can only be trace, debug, info, warn or error")
|
||||
}
|
||||
c.SetLogLevel(logLevel)
|
||||
}
|
||||
|
||||
if ctx.GlobalIsSet("log-file") {
|
||||
c.SetLogFile(ctx.GlobalString("log-file"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func pathExists(path string) (bool, error) {
|
||||
_, err := os.Stat(path)
|
||||
if err == nil {
|
||||
return true, nil
|
||||
}
|
||||
if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
}
|
||||
return true, err
|
||||
}
|
||||
|
||||
func containerExists(containerID string) (bool, error) {
|
||||
// check for container existence by looking for config file.
|
||||
// otherwise NewContainer will return an empty container
|
||||
// struct and we'll report wrong info
|
||||
configExists, err := pathExists(filepath.Join(LXC_PATH, containerID, "config"))
|
||||
if err != nil {
|
||||
return false, errors.Wrap(err, "failed to check path existence of config")
|
||||
}
|
||||
|
||||
return configExists, nil
|
||||
}
|
||||
28
go.mod
Normal file
28
go.mod
Normal file
@@ -0,0 +1,28 @@
|
||||
module github.com/lxc/crio-lxc
|
||||
|
||||
require (
|
||||
github.com/anuvu/stacker v0.4.0
|
||||
github.com/apex/log v1.1.0
|
||||
github.com/gorilla/websocket v1.4.0 // indirect
|
||||
github.com/juju/loggo v0.0.0-20190212223446-d976af380377 // indirect
|
||||
github.com/lxc/lxd v0.0.0-20190404234020-f51c28a37443
|
||||
github.com/openSUSE/umoci v0.4.4
|
||||
github.com/opencontainers/runtime-spec v1.0.1
|
||||
github.com/opencontainers/selinux v1.2.1 // indirect
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/rogpeppe/godef v1.1.1 // indirect
|
||||
github.com/sirupsen/logrus v1.4.1 // indirect
|
||||
github.com/urfave/cli v1.20.0
|
||||
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5 // indirect
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 // indirect
|
||||
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67
|
||||
golang.org/x/tools v0.0.0-20190405180640-052fc3cfdbc2 // indirect
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
|
||||
gopkg.in/lxc/go-lxc.v2 v2.0.0-20190324192716-2f350e4a2980
|
||||
gopkg.in/yaml.v2 v2.2.2
|
||||
k8s.io/client-go v11.0.0+incompatible // indirect
|
||||
)
|
||||
|
||||
replace github.com/vbatts/go-mtree v0.4.4 => github.com/vbatts/go-mtree v0.4.5-0.20190122034725-8b6de6073c1a
|
||||
|
||||
replace github.com/openSUSE/umoci v0.4.4 => github.com/tych0/umoci v0.1.1-0.20190402232331-556620754fb1
|
||||
223
go.sum
Normal file
223
go.sum
Normal file
@@ -0,0 +1,223 @@
|
||||
9fans.net/go v0.0.0-20181112161441-237454027057 h1:OcHlKWkAMJEF1ndWLGxp5dnJQkYM/YImUOvsBoz6h5E=
|
||||
9fans.net/go v0.0.0-20181112161441-237454027057/go.mod h1:diCsxrliIURU9xsYtjCp5AbpQKqdhKmf0ujWDUSkfoY=
|
||||
code.cloudfoundry.org/systemcerts v0.0.0-20180917154049-ca00b2f806f2/go.mod h1:EXawaFLz9fhxAjRCeaqP+Wr5t5+h75UzbHEA7ybrr1o=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/Microsoft/go-winio v0.0.0-20190117211522-75bf6ca3d7cb/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/anuvu/stacker v0.4.0 h1:+r8MQr8RVlFuVe9W7mxZ/pF/SBtX5XIvaBOcmkPqlI0=
|
||||
github.com/anuvu/stacker v0.4.0/go.mod h1:RGdZIvdQLCxFPND+8jXVppAUPbRS/dkDWe65qt274Gg=
|
||||
github.com/apex/log v1.1.0 h1:J5rld6WVFi6NxA6m8GJ1LJqu3+GiTFIt3mYv27gdQWI=
|
||||
github.com/apex/log v1.1.0/go.mod h1:yA770aXIDQrhVOIGurT/pVdfCpSq1GQV/auzMN5fzvY=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/boltdb/bolt v0.0.0-20180302180052-fd01fc79c553 h1:yvSJ8qbaWLeS7COhu2KJ0epn4mmc+aGeBP7Dpg7xQTY=
|
||||
github.com/boltdb/bolt v0.0.0-20180302180052-fd01fc79c553/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
|
||||
github.com/cheggaaa/pb v1.0.27 h1:wIkZHkNfC7R6GI5w7l/PdAdzXzlrbcI3p8OAlnkTsnc=
|
||||
github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
|
||||
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 h1:4BX8f882bXEDKfWIf0wa8HRvpnBoPszJJXL+TVbBw4M=
|
||||
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
|
||||
github.com/containers/image v0.0.0-20190208010805-4629bcc4825f h1:Z7kajYzNuO4jIjGfQSgF88QQZL8uBlGggRcukmldxow=
|
||||
github.com/containers/image v0.0.0-20190208010805-4629bcc4825f/go.mod h1:8Vtij257IWSanUQKe1tAeNOm2sRVkSqQTVQ1IlwI3+M=
|
||||
github.com/containers/storage v0.0.0-20190207215558-06b6c2e4cf25/go.mod h1:+RirK6VQAqskQlaTBrOG6ulDvn4si2QjFE1NZCn06MM=
|
||||
github.com/cyphar/filepath-securejoin v0.2.2 h1:jCwT2GTP+PY5nBz3c/YL5PAIbusElVrPujOBSCj8xRg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/docker/distribution v0.0.0-20190205005809-0d3efadf0154 h1:C8WBRZDiZn3IZnBlbHVeTWF32XhVGK69Li4GC/3jL9Q=
|
||||
github.com/docker/distribution v0.0.0-20190205005809-0d3efadf0154/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v0.0.0-20190207111444-e6fe7f8f2936 h1:eRJM2oxktfS3HP/ziIJuvn9QXxq1rP/2mNJj04uXklQ=
|
||||
github.com/docker/docker v0.0.0-20190207111444-e6fe7f8f2936/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.0.0-20180925085122-123ba1b7cd64 h1:imB4LnBHHEccRIBjH4lY4X3TC8FPRPue/nkCiJtLERM=
|
||||
github.com/docker/docker-credential-helpers v0.0.0-20180925085122-123ba1b7cd64/go.mod h1:WRaJzqw3CTB9bk10avuGsjVBZsD05qeibJ1/TYlvc0Y=
|
||||
github.com/docker/go-connections v0.0.0-20180821093606-97c2040d34df h1:ADMjlaDGEn0OOQIieyxanhAt41jcngf8rf78X2eKNLw=
|
||||
github.com/docker/go-connections v0.0.0-20180821093606-97c2040d34df/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-metrics v0.0.0-20181218153428-b84716841b82 h1:X0fj836zx99zFu83v/M79DuBn84IL/Syx1SY6Y5ZEMA=
|
||||
github.com/docker/go-metrics v0.0.0-20181218153428-b84716841b82/go.mod h1:/u0gXw0Gay3ceNrsHubL3BtdOL2fHf93USgMTe0W5dI=
|
||||
github.com/docker/go-units v0.3.3 h1:Xk8S3Xj5sLGlG5g67hJmYMmUgXv5N4PhkjJHHqrwnTk=
|
||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4=
|
||||
github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/flosch/pongo2 v0.0.0-20181225140029-79872a7b2769 h1:XToLChWPMXLomJ2InnkrmUkddaXfevrmomMTFL+MaKU=
|
||||
github.com/flosch/pongo2 v0.0.0-20181225140029-79872a7b2769/go.mod h1:tbAXHifHQWNSpWbiJHpJTZH5fi3XHhDMdP//vuz9WS4=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/freddierice/go-losetup v0.0.0-20170407175016-fc9adea44124 h1:TVfi5xMshZAXzVXozESk8bi0JSTPwHkx7qtLOkkcu/c=
|
||||
github.com/freddierice/go-losetup v0.0.0-20170407175016-fc9adea44124/go.mod h1:zAk7fcFx45euzK9Az14j6Hd9n8Cwhnjp/NBfhSIAmFg=
|
||||
github.com/ghodss/yaml v0.0.0-20190206175653-d4115522f0fe h1:X2U2232O/PUczwdCr6+ScoThLvdBKg5yIu6hLcHFR88=
|
||||
github.com/ghodss/yaml v0.0.0-20190206175653-d4115522f0fe/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-check/check v1.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/gorilla/mux v1.7.0 h1:tOSd0UKHQd6urX6ApfOn4XdBMY6Sh1MfxV3kmaazO+U=
|
||||
github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v0.0.0-20190205004414-7c8e298727d1/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/juju/errors v0.0.0-20181118221551-089d3ea4e4d5/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
|
||||
github.com/juju/errors v0.0.0-20190207033735-e65537c515d7 h1:dMIPRDg6gi7CUp0Kj2+HxqJ5kTr1iAdzsXYIrLCNSmU=
|
||||
github.com/juju/errors v0.0.0-20190207033735-e65537c515d7/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
|
||||
github.com/juju/loggo v0.0.0-20180524022052-584905176618/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
|
||||
github.com/juju/loggo v0.0.0-20190212223446-d976af380377/go.mod h1:vgyd7OREkbtVEN/8IXZe5Ooef3LQePvuBm9UWj6ZL8U=
|
||||
github.com/juju/testing v0.0.0-20180920084828-472a3e8b2073/go.mod h1:63prj8cnj0tU0S9OHjGJn+b1h0ZghCndfnbQolrYTwA=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.4.1 h1:8VMb5+0wMgdBykOV96DwNwKFQ+WTI4pzYURP99CcB9E=
|
||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/cpuid v1.2.0 h1:NMpwD2G9JSFOE1/TJjGSo5zG7Yb2bTe7eq1jH+irmeE=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/crc32 v1.2.0/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg=
|
||||
github.com/klauspost/pgzip v1.2.1 h1:oIPZROsWuPHpOdMVWLuJZXwgjhrW8r1yEX8UqMyeNHM=
|
||||
github.com/klauspost/pgzip v1.2.1/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/lxc/lxd v0.0.0-20190208124523-fe0844d45b32/go.mod h1:2BaZflfwsv8a3uy3/Vw+de4Avn4DSrAiqaHJjCIXMV4=
|
||||
github.com/lxc/lxd v0.0.0-20190404234020-f51c28a37443 h1:8VLxh92A974SkZlwBlj38PJprNFwNu3J7CRoTjOjsq4=
|
||||
github.com/lxc/lxd v0.0.0-20190404234020-f51c28a37443/go.mod h1:2BaZflfwsv8a3uy3/Vw+de4Avn4DSrAiqaHJjCIXMV4=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-runewidth v0.0.0-20181218000649-703b5e6b11ae h1:84Sj4V9L4dE13ryw5Vn/sxmxg5ebqhpIfTHflC5Gqrg=
|
||||
github.com/mattn/go-runewidth v0.0.0-20181218000649-703b5e6b11ae/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/hashstructure v1.0.0 h1:ZkRJX1CyOoTkar7p/mLS5TZU4nJ1Rn/F8u9dGS02Q3Y=
|
||||
github.com/mitchellh/hashstructure v1.0.0/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ=
|
||||
github.com/mohae/deepcopy v0.0.0-20170603005431-491d3605edfb/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||
github.com/mtrmac/gpgme v0.0.0-20170102180018-b2432428689c h1:xa+eQWKuJ9MbB9FBL/eoNvDFvveAkz2LQoz8PzX7Q/4=
|
||||
github.com/mtrmac/gpgme v0.0.0-20170102180018-b2432428689c/go.mod h1:GhAqVMEWnTcW2dxoD/SO3n2enrgWl3y6Dnx4m59GvcA=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
|
||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||
github.com/opencontainers/image-spec v1.0.0/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVojFA6h/TRcI=
|
||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||
github.com/opencontainers/runc v0.0.0-20190208075259-dd023c457d84 h1:fDcjHkdDVppN5Fk3yoNtK13eYg8UWLVSzlr4Z8O8MQA=
|
||||
github.com/opencontainers/runc v0.0.0-20190208075259-dd023c457d84/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||
github.com/opencontainers/runtime-spec v1.0.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.0.1 h1:wY4pOY8fBdSIvs9+IDHC55thBuEulhzfSgKeC1yFvzQ=
|
||||
github.com/opencontainers/runtime-spec v1.0.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-tools v0.7.0 h1:MIjqgwi4ZC+eVNGiYotCUYuTfs/oWDEcigK9Ra5ruHU=
|
||||
github.com/opencontainers/runtime-tools v0.7.0/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs=
|
||||
github.com/opencontainers/selinux v1.0.0/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs=
|
||||
github.com/opencontainers/selinux v1.2.1/go.mod h1:+BLncwf63G4dgOzykXAxcmnFlUaOlkDdmw/CqsW6pjs=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.9.1 h1:K47Rk0v/fkEfwfQet2KWhscE0cJzjgCCDBG2KHZoVno=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.2.0 h1:kUZDBDTdBVBYBj5Tmh2NZLlF60mfjA27rM34b+cVwNU=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190208162519-de1b801bf34b h1:SSKVZGyOykopyi4bOAsGmbuEHPExRa+PEI2knZCALcU=
|
||||
github.com/prometheus/procfs v0.0.0-20190208162519-de1b801bf34b/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/rogpeppe/godef v1.1.1 h1:NujOtt9q9vIClRTB3sCZpavac+NMRaIayzrcz1h4fSE=
|
||||
github.com/rogpeppe/godef v1.1.1/go.mod h1:oEo1eMy1VUEHUzUIX4F7IqvMJRiz9UId44mvnR8oPlQ=
|
||||
github.com/rootless-containers/proto v0.1.0 h1:gS1JOMEtk1YDYHCzBAf/url+olMJbac7MTrgSeP6zh4=
|
||||
github.com/rootless-containers/proto v0.1.0/go.mod h1:vgkUFZbQd0gcE/K/ZwtE4MYjZPu0UNHLXIQxhyqAFh8=
|
||||
github.com/sergi/go-diff v0.0.0-20180205163309-da645544ed44 h1:UoZTeCJuGZpwXXqamtSHypwjqpyGdR9smB5iMleBDJ8=
|
||||
github.com/sergi/go-diff v0.0.0-20180205163309-da645544ed44/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sirupsen/logrus v1.4.1 h1:GL2rEmy6nsikmW0r8opw9JIRScdMF5hA8cOYLH7In1k=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2 h1:b6uOv7YOFK0TYG7HtkIgExQo+2RdLuwRft63jn2HWj8=
|
||||
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/tych0/umoci v0.1.1-0.20190402232331-556620754fb1 h1:o4wA23uJTjELWzDPI9c5fWshoXr5iMY8gbt0Vz2bM9Y=
|
||||
github.com/tych0/umoci v0.1.1-0.20190402232331-556620754fb1/go.mod h1:r5Md+fkaQUURwsULEptlOz0Vv2QlzbdbfHi+eBkk2uU=
|
||||
github.com/udhos/equalfile v0.3.0 h1:KhG4xhhkittrgIV/ekHtpEPh7MLxtbjm6kLEwp5Dlbg=
|
||||
github.com/udhos/equalfile v0.3.0/go.mod h1:1LOX9HjdFMke7ryP3IPby09FkswyY5KzhhsT37wLz/Y=
|
||||
github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
|
||||
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
|
||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
github.com/vbatts/go-mtree v0.4.5-0.20190122034725-8b6de6073c1a h1:nuTbu0QJphHUZMSgXx0U5a9+lhM9Mz6eLt/0gGEPgs4=
|
||||
github.com/vbatts/go-mtree v0.4.5-0.20190122034725-8b6de6073c1a/go.mod h1:3sazBqLG4bZYmgRTgdh9X3iKTzwBpp5CrREJDzrNSXY=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||
github.com/xeipuuv/gojsonschema v0.0.0-20180719132039-b84684d0e066/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
|
||||
github.com/xeipuuv/gojsonschema v1.1.0 h1:ngVtJC9TY/lg0AA/1k48FYhBrhRoFlEmWzsehpNAaZg=
|
||||
github.com/xeipuuv/gojsonschema v1.1.0/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190131182504-b8fe1690c613/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5 h1:bselrhR0Or1vomJZC8ZIjWtbDmn9OYFLX5Ik9alpJpE=
|
||||
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4 h1:YUO/7uOKsKeq9UokNS62b8FYywz3ker1l1vDZRCRefw=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67 h1:1Fzlr8kkDLQwqMP8GxrhptBLqZG/EDpiATneiZHY998=
|
||||
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20181130195746-895048a75ecf/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181221001348-537d06c36207/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190405180640-052fc3cfdbc2 h1:rlaAa9eBBj6AI2C90gKs2Q/XF6YFbBDpGSX+npdfPlk=
|
||||
golang.org/x/tools v0.0.0-20190405180640-052fc3cfdbc2/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.27 h1:kJdccidYzt3CaHD1crCFTS1hxyhSi059NhOFUf03YFo=
|
||||
gopkg.in/cheggaaa/pb.v1 v1.0.27/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||
gopkg.in/lxc/go-lxc.v2 v2.0.0-20181227225324-7c910f8a5edc/go.mod h1:4K0lbUXeslpmjwJZyW1lI6s5j97mrsj4+kpYwwvuLXo=
|
||||
gopkg.in/lxc/go-lxc.v2 v2.0.0-20190324192716-2f350e4a2980 h1:JH0hbXFbkeENYCUaso0BKGGuw5RyisZwJKYG4KuzzC4=
|
||||
gopkg.in/lxc/go-lxc.v2 v2.0.0-20190324192716-2f350e4a2980/go.mod h1:4K0lbUXeslpmjwJZyW1lI6s5j97mrsj4+kpYwwvuLXo=
|
||||
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||
gopkg.in/robfig/cron.v2 v2.0.0-20150107220207-be2e0b0deed5 h1:E846t8CnR+lv5nE+VuiKTDG/v1U2stad0QzddfJC7kY=
|
||||
gopkg.in/robfig/cron.v2 v2.0.0-20150107220207-be2e0b0deed5/go.mod h1:hiOFpYm0ZJbusNj2ywpbrXowU3G8U6GIQzqn2mw1UIE=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||
k8s.io/client-go v10.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
|
||||
k8s.io/client-go v11.0.0+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
|
||||
Reference in New Issue
Block a user