Merge pull request #1170 from Random-Liu/remove-ctr-cri-load
Remove ctr cri load
This commit is contained in:
commit
bb020275cb
27
Makefile
27
Makefile
@ -39,10 +39,8 @@ help:
|
|||||||
@echo "Usage: make <target>"
|
@echo "Usage: make <target>"
|
||||||
@echo
|
@echo
|
||||||
@echo " * 'install' - Install binaries to system locations"
|
@echo " * 'install' - Install binaries to system locations"
|
||||||
@echo " * 'binaries' - Build containerd and ctr"
|
@echo " * 'binaries' - Build containerd"
|
||||||
@echo " * 'static-binaries - Build static containerd and ctr"
|
@echo " * 'static-binaries - Build static containerd"
|
||||||
@echo " * 'ctr' - Build ctr"
|
|
||||||
@echo " * 'install-ctr' - Install ctr"
|
|
||||||
@echo " * 'containerd' - Build a customized containerd with CRI plugin for testing"
|
@echo " * 'containerd' - Build a customized containerd with CRI plugin for testing"
|
||||||
@echo " * 'install-containerd' - Install customized containerd to system location"
|
@echo " * 'install-containerd' - Install customized containerd to system location"
|
||||||
@echo " * 'release' - Build release tarball"
|
@echo " * 'release' - Build release tarball"
|
||||||
@ -93,13 +91,6 @@ sync-vendor:
|
|||||||
|
|
||||||
update-vendor: sync-vendor sort-vendor
|
update-vendor: sync-vendor sort-vendor
|
||||||
|
|
||||||
$(BUILD_DIR)/ctr: $(SOURCES)
|
|
||||||
$(GO) build -o $@ \
|
|
||||||
-tags '$(BUILD_TAGS)' \
|
|
||||||
-ldflags '$(GO_LDFLAGS)' \
|
|
||||||
-gcflags '$(GO_GCFLAGS)' \
|
|
||||||
$(PROJECT)/cmd/ctr
|
|
||||||
|
|
||||||
$(BUILD_DIR)/containerd: $(SOURCES) $(PLUGIN_SOURCES)
|
$(BUILD_DIR)/containerd: $(SOURCES) $(PLUGIN_SOURCES)
|
||||||
$(GO) build -o $@ \
|
$(GO) build -o $@ \
|
||||||
-tags '$(BUILD_TAGS)' \
|
-tags '$(BUILD_TAGS)' \
|
||||||
@ -128,26 +119,20 @@ test-e2e-node: binaries
|
|||||||
clean:
|
clean:
|
||||||
rm -rf $(BUILD_DIR)/*
|
rm -rf $(BUILD_DIR)/*
|
||||||
|
|
||||||
binaries: $(BUILD_DIR)/containerd $(BUILD_DIR)/ctr
|
binaries: $(BUILD_DIR)/containerd
|
||||||
|
|
||||||
static-binaries: GO_LDFLAGS += -extldflags "-fno-PIC -static"
|
static-binaries: GO_LDFLAGS += -extldflags "-fno-PIC -static"
|
||||||
static-binaries: $(BUILD_DIR)/containerd $(BUILD_DIR)/ctr
|
static-binaries: $(BUILD_DIR)/containerd
|
||||||
|
|
||||||
ctr: $(BUILD_DIR)/ctr
|
|
||||||
|
|
||||||
install-ctr: ctr
|
|
||||||
install -D -m 755 $(BUILD_DIR)/ctr $(BINDIR)/ctr
|
|
||||||
|
|
||||||
containerd: $(BUILD_DIR)/containerd
|
containerd: $(BUILD_DIR)/containerd
|
||||||
|
|
||||||
install-containerd: containerd
|
install-containerd: containerd
|
||||||
install -D -m 755 $(BUILD_DIR)/containerd $(BINDIR)/containerd
|
install -D -m 755 $(BUILD_DIR)/containerd $(BINDIR)/containerd
|
||||||
|
|
||||||
install: install-ctr install-containerd
|
install: install-containerd
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
rm -f $(BINDIR)/containerd
|
rm -f $(BINDIR)/containerd
|
||||||
rm -f $(BINDIR)/ctr
|
|
||||||
|
|
||||||
$(BUILD_DIR)/$(TARBALL): static-binaries vendor.conf
|
$(BUILD_DIR)/$(TARBALL): static-binaries vendor.conf
|
||||||
@BUILD_DIR=$(BUILD_DIR) TARBALL=$(TARBALL) VERSION=$(VERSION) ./hack/release.sh
|
@BUILD_DIR=$(BUILD_DIR) TARBALL=$(TARBALL) VERSION=$(VERSION) ./hack/release.sh
|
||||||
@ -193,8 +178,6 @@ install.tools: .install.gitvalidation .install.gometalinter .install.vndr
|
|||||||
.PHONY: \
|
.PHONY: \
|
||||||
binaries \
|
binaries \
|
||||||
static-binaries \
|
static-binaries \
|
||||||
ctr \
|
|
||||||
install-ctr \
|
|
||||||
containerd \
|
containerd \
|
||||||
install-containerd \
|
install-containerd \
|
||||||
release \
|
release \
|
||||||
|
78
cli/cli.go
78
cli/cli.go
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 The containerd 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 cli
|
|
||||||
|
|
||||||
import (
|
|
||||||
gocontext "context"
|
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
api "github.com/containerd/cri/pkg/api/v1"
|
|
||||||
"github.com/containerd/cri/pkg/client"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Command is the cli command for cri plugin.
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "cri",
|
|
||||||
Usage: "interact with cri plugin",
|
|
||||||
Subcommands: cli.Commands{
|
|
||||||
loadCommand,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var loadCommand = cli.Command{
|
|
||||||
Name: "load",
|
|
||||||
Usage: "load one or more images from tar archives.",
|
|
||||||
ArgsUsage: "[flags] TAR [TAR, ...]",
|
|
||||||
Description: "load one or more images from tar archives.",
|
|
||||||
Flags: []cli.Flag{},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
ctx = gocontext.Background()
|
|
||||||
address = context.GlobalString("address")
|
|
||||||
timeout = context.GlobalDuration("timeout")
|
|
||||||
cancel gocontext.CancelFunc
|
|
||||||
)
|
|
||||||
if timeout > 0 {
|
|
||||||
ctx, cancel = gocontext.WithTimeout(gocontext.Background(), timeout)
|
|
||||||
} else {
|
|
||||||
ctx, cancel = gocontext.WithCancel(ctx)
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
cl, err := client.NewCRIPluginClient(ctx, address)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "failed to create grpc client")
|
|
||||||
}
|
|
||||||
for _, path := range context.Args() {
|
|
||||||
absPath, err := filepath.Abs(path)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "failed to get absolute path")
|
|
||||||
}
|
|
||||||
res, err := cl.LoadImage(ctx, &api.LoadImageRequest{FilePath: absPath})
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "failed to load image")
|
|
||||||
}
|
|
||||||
images := res.GetImages()
|
|
||||||
for _, image := range images {
|
|
||||||
fmt.Println("Loaded image:", image)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2018 The containerd 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 main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"math/rand"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
ctrapp "github.com/containerd/containerd/cmd/ctr/app"
|
|
||||||
|
|
||||||
cricli "github.com/containerd/cri/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
rand.Seed(time.Now().UnixNano())
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
app := ctrapp.New()
|
|
||||||
app.Commands = append(app.Commands, cricli.Command)
|
|
||||||
if err := app.Run(os.Args); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "ctr: %s\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
@ -27,7 +27,7 @@ REPORT_DIR=${REPORT_DIR:-"/tmp/test-integration"}
|
|||||||
# RUNTIME is the runtime handler to use in the test.
|
# RUNTIME is the runtime handler to use in the test.
|
||||||
RUNTIME=${RUNTIME:-""}
|
RUNTIME=${RUNTIME:-""}
|
||||||
|
|
||||||
CRI_ROOT="/var/lib/containerd/io.containerd.grpc.v1.cri"
|
CRI_ROOT="${CONTAINERD_ROOT}/io.containerd.grpc.v1.cri"
|
||||||
|
|
||||||
mkdir -p ${REPORT_DIR}
|
mkdir -p ${REPORT_DIR}
|
||||||
test_setup ${REPORT_DIR}
|
test_setup ${REPORT_DIR}
|
||||||
|
@ -23,13 +23,23 @@ CONTAINERD_FLAGS="--log-level=debug "
|
|||||||
|
|
||||||
# Use a configuration file for containerd.
|
# Use a configuration file for containerd.
|
||||||
CONTAINERD_CONFIG_FILE=${CONTAINERD_CONFIG_FILE:-""}
|
CONTAINERD_CONFIG_FILE=${CONTAINERD_CONFIG_FILE:-""}
|
||||||
|
# CONTAINERD_TEST_SUFFIX is the suffix appended to the root/state directory used
|
||||||
|
# by test containerd.
|
||||||
|
CONTAINERD_TEST_SUFFIX=${CONTAINERD_TEST_SUFFIX:-"-test"}
|
||||||
|
# The containerd root directory.
|
||||||
|
CONTAINERD_ROOT=${CONTAINERD_ROOT:-"/var/lib/containerd${CONTAINERD_TEST_SUFFIX}"}
|
||||||
|
# The containerd state directory.
|
||||||
|
CONTAINERD_STATE=${CONTAINERD_STATE:-"/run/containerd${CONTAINERD_TEST_SUFFIX}"}
|
||||||
|
# The containerd socket address.
|
||||||
|
CONTAINERD_SOCK=${CONTAINERD_SOCK:-unix://${CONTAINERD_STATE}/containerd.sock}
|
||||||
if [ -f "${CONTAINERD_CONFIG_FILE}" ]; then
|
if [ -f "${CONTAINERD_CONFIG_FILE}" ]; then
|
||||||
CONTAINERD_FLAGS+="--config ${CONTAINERD_CONFIG_FILE} "
|
CONTAINERD_FLAGS+="--config ${CONTAINERD_CONFIG_FILE} "
|
||||||
fi
|
fi
|
||||||
|
CONTAINERD_FLAGS+="--address ${CONTAINERD_SOCK#"unix://"} \
|
||||||
|
--state ${CONTAINERD_STATE} \
|
||||||
|
--root ${CONTAINERD_ROOT}"
|
||||||
|
|
||||||
CONTAINERD_SOCK=unix:///run/containerd/containerd.sock
|
containerd_groupid=
|
||||||
|
|
||||||
containerd_pid=
|
|
||||||
|
|
||||||
# test_setup starts containerd.
|
# test_setup starts containerd.
|
||||||
test_setup() {
|
test_setup() {
|
||||||
@ -39,10 +49,14 @@ test_setup() {
|
|||||||
echo "containerd is not built"
|
echo "containerd is not built"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
sudo pkill -x containerd
|
set -m
|
||||||
|
# Create containerd in a different process group
|
||||||
|
# so that we can easily clean them up.
|
||||||
keepalive "sudo PATH=${PATH} ${ROOT}/_output/containerd ${CONTAINERD_FLAGS}" \
|
keepalive "sudo PATH=${PATH} ${ROOT}/_output/containerd ${CONTAINERD_FLAGS}" \
|
||||||
${RESTART_WAIT_PERIOD} &> ${report_dir}/containerd.log &
|
${RESTART_WAIT_PERIOD} &> ${report_dir}/containerd.log &
|
||||||
containerd_pid=$!
|
pid=$!
|
||||||
|
set +m
|
||||||
|
containerd_groupid=$(ps -o pgid= -p ${pid})
|
||||||
# Wait for containerd to be running by using the containerd client ctr to check the version
|
# Wait for containerd to be running by using the containerd client ctr to check the version
|
||||||
# of the containerd server. Wait an increasing amount of time after each of five attempts
|
# of the containerd server. Wait an increasing amount of time after each of five attempts
|
||||||
local -r ctr_path=$(which ctr)
|
local -r ctr_path=$(which ctr)
|
||||||
@ -61,10 +75,9 @@ test_setup() {
|
|||||||
|
|
||||||
# test_teardown kills containerd.
|
# test_teardown kills containerd.
|
||||||
test_teardown() {
|
test_teardown() {
|
||||||
if [ -n "${containerd_pid}" ]; then
|
if [ -n "${containerd_groupid}" ]; then
|
||||||
kill ${containerd_pid}
|
sudo pkill -g ${containerd_groupid}
|
||||||
fi
|
fi
|
||||||
sudo pkill -x containerd
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# keepalive runs a command and keeps it alive.
|
# keepalive runs a command and keeps it alive.
|
||||||
|
@ -17,17 +17,15 @@ limitations under the License.
|
|||||||
package integration
|
package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"golang.org/x/net/context"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
||||||
|
|
||||||
api "github.com/containerd/cri/pkg/api/v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Test to load an image from tarball.
|
// Test to load an image from tarball.
|
||||||
@ -58,14 +56,22 @@ func TestImageLoad(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Logf("load image in cri")
|
t.Logf("load image in cri")
|
||||||
res, err := criPluginClient.LoadImage(context.Background(), &api.LoadImageRequest{FilePath: tar})
|
ctr, err := exec.LookPath("ctr")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err, "ctr should be installed, make sure you've run `make install.deps`")
|
||||||
require.Equal(t, []string{loadedImage}, res.GetImages())
|
output, err = exec.Command(ctr, "-address="+containerdEndpoint,
|
||||||
|
"-n=k8s.io", "images", "import", tar).CombinedOutput()
|
||||||
|
require.NoError(t, err, "output: %q", output)
|
||||||
|
|
||||||
t.Logf("make sure image is loaded")
|
t.Logf("make sure image is loaded")
|
||||||
img, err = imageService.ImageStatus(&runtime.ImageSpec{Image: testImage})
|
// Use Eventually because the cri plugin needs a short period of time
|
||||||
require.NoError(t, err)
|
// to pick up images imported into containerd directly.
|
||||||
require.NotNil(t, img)
|
require.NoError(t, Eventually(func() (bool, error) {
|
||||||
|
img, err = imageService.ImageStatus(&runtime.ImageSpec{Image: testImage})
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
return img != nil, nil
|
||||||
|
}, 100*time.Millisecond, 10*time.Second))
|
||||||
require.Equal(t, []string{loadedImage}, img.RepoTags)
|
require.Equal(t, []string{loadedImage}, img.RepoTags)
|
||||||
|
|
||||||
t.Logf("create a container with the loaded image")
|
t.Logf("create a container with the loaded image")
|
||||||
|
@ -38,8 +38,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/kubelet/remote"
|
"k8s.io/kubernetes/pkg/kubelet/remote"
|
||||||
kubeletutil "k8s.io/kubernetes/pkg/kubelet/util"
|
kubeletutil "k8s.io/kubernetes/pkg/kubelet/util"
|
||||||
|
|
||||||
api "github.com/containerd/cri/pkg/api/v1"
|
|
||||||
"github.com/containerd/cri/pkg/client"
|
|
||||||
criconfig "github.com/containerd/cri/pkg/config"
|
criconfig "github.com/containerd/cri/pkg/config"
|
||||||
"github.com/containerd/cri/pkg/constants"
|
"github.com/containerd/cri/pkg/constants"
|
||||||
"github.com/containerd/cri/pkg/server"
|
"github.com/containerd/cri/pkg/server"
|
||||||
@ -47,17 +45,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
timeout = 1 * time.Minute
|
timeout = 1 * time.Minute
|
||||||
pauseImage = "k8s.gcr.io/pause:3.1" // This is the same with default sandbox image.
|
pauseImage = "k8s.gcr.io/pause:3.1" // This is the same with default sandbox image.
|
||||||
k8sNamespace = constants.K8sContainerdNamespace
|
k8sNamespace = constants.K8sContainerdNamespace
|
||||||
containerdEndpoint = "/run/containerd/containerd.sock"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
runtimeService cri.RuntimeService
|
runtimeService cri.RuntimeService
|
||||||
imageService cri.ImageManagerService
|
imageService cri.ImageManagerService
|
||||||
containerdClient *containerd.Client
|
containerdClient *containerd.Client
|
||||||
criPluginClient api.CRIPluginServiceClient
|
containerdEndpoint string
|
||||||
)
|
)
|
||||||
|
|
||||||
var criEndpoint = flag.String("cri-endpoint", "unix:///run/containerd/containerd.sock", "The endpoint of cri plugin.")
|
var criEndpoint = flag.String("cri-endpoint", "unix:///run/containerd/containerd.sock", "The endpoint of cri plugin.")
|
||||||
@ -93,16 +90,12 @@ func ConnectDaemons() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to list images")
|
return errors.Wrap(err, "failed to list images")
|
||||||
}
|
}
|
||||||
|
// containerdEndpoint is the same with criEndpoint now
|
||||||
|
containerdEndpoint = strings.TrimPrefix(*criEndpoint, "unix://")
|
||||||
containerdClient, err = containerd.New(containerdEndpoint, containerd.WithDefaultNamespace(k8sNamespace))
|
containerdClient, err = containerd.New(containerdEndpoint, containerd.WithDefaultNamespace(k8sNamespace))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "failed to connect containerd")
|
return errors.Wrap(err, "failed to connect containerd")
|
||||||
}
|
}
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), timeout)
|
|
||||||
defer cancel()
|
|
||||||
criPluginClient, err = client.NewCRIPluginClient(ctx, *criEndpoint)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "failed to connect cri plugin")
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,578 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2019 The containerd 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.
|
|
||||||
*/
|
|
||||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
|
||||||
// source: api.proto
|
|
||||||
|
|
||||||
/*
|
|
||||||
Package api_v1 is a generated protocol buffer package.
|
|
||||||
|
|
||||||
It is generated from these files:
|
|
||||||
api.proto
|
|
||||||
|
|
||||||
It has these top-level messages:
|
|
||||||
LoadImageRequest
|
|
||||||
LoadImageResponse
|
|
||||||
*/
|
|
||||||
package api_v1
|
|
||||||
|
|
||||||
import proto "github.com/gogo/protobuf/proto"
|
|
||||||
import fmt "fmt"
|
|
||||||
import math "math"
|
|
||||||
import _ "github.com/gogo/protobuf/gogoproto"
|
|
||||||
|
|
||||||
import (
|
|
||||||
context "golang.org/x/net/context"
|
|
||||||
grpc "google.golang.org/grpc"
|
|
||||||
)
|
|
||||||
|
|
||||||
import strings "strings"
|
|
||||||
import reflect "reflect"
|
|
||||||
|
|
||||||
import io "io"
|
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
|
||||||
var _ = proto.Marshal
|
|
||||||
var _ = fmt.Errorf
|
|
||||||
var _ = math.Inf
|
|
||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
|
||||||
// is compatible with the proto package it is being compiled against.
|
|
||||||
// A compilation error at this line likely means your copy of the
|
|
||||||
// proto package needs to be updated.
|
|
||||||
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
|
|
||||||
|
|
||||||
type LoadImageRequest struct {
|
|
||||||
// FilePath is the absolute path of docker image tarball.
|
|
||||||
FilePath string `protobuf:"bytes,1,opt,name=FilePath,proto3" json:"FilePath,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *LoadImageRequest) Reset() { *m = LoadImageRequest{} }
|
|
||||||
func (*LoadImageRequest) ProtoMessage() {}
|
|
||||||
func (*LoadImageRequest) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{0} }
|
|
||||||
|
|
||||||
func (m *LoadImageRequest) GetFilePath() string {
|
|
||||||
if m != nil {
|
|
||||||
return m.FilePath
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
type LoadImageResponse struct {
|
|
||||||
// Images have been loaded.
|
|
||||||
Images []string `protobuf:"bytes,1,rep,name=Images" json:"Images,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *LoadImageResponse) Reset() { *m = LoadImageResponse{} }
|
|
||||||
func (*LoadImageResponse) ProtoMessage() {}
|
|
||||||
func (*LoadImageResponse) Descriptor() ([]byte, []int) { return fileDescriptorApi, []int{1} }
|
|
||||||
|
|
||||||
func (m *LoadImageResponse) GetImages() []string {
|
|
||||||
if m != nil {
|
|
||||||
return m.Images
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
proto.RegisterType((*LoadImageRequest)(nil), "api.v1.LoadImageRequest")
|
|
||||||
proto.RegisterType((*LoadImageResponse)(nil), "api.v1.LoadImageResponse")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
|
||||||
var _ context.Context
|
|
||||||
var _ grpc.ClientConn
|
|
||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
|
||||||
// is compatible with the grpc package it is being compiled against.
|
|
||||||
const _ = grpc.SupportPackageIsVersion4
|
|
||||||
|
|
||||||
// Client API for CRIPluginService service
|
|
||||||
|
|
||||||
type CRIPluginServiceClient interface {
|
|
||||||
// LoadImage loads a image into containerd.
|
|
||||||
LoadImage(ctx context.Context, in *LoadImageRequest, opts ...grpc.CallOption) (*LoadImageResponse, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type cRIPluginServiceClient struct {
|
|
||||||
cc *grpc.ClientConn
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewCRIPluginServiceClient(cc *grpc.ClientConn) CRIPluginServiceClient {
|
|
||||||
return &cRIPluginServiceClient{cc}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *cRIPluginServiceClient) LoadImage(ctx context.Context, in *LoadImageRequest, opts ...grpc.CallOption) (*LoadImageResponse, error) {
|
|
||||||
out := new(LoadImageResponse)
|
|
||||||
err := grpc.Invoke(ctx, "/api.v1.CRIPluginService/LoadImage", in, out, c.cc, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return out, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Server API for CRIPluginService service
|
|
||||||
|
|
||||||
type CRIPluginServiceServer interface {
|
|
||||||
// LoadImage loads a image into containerd.
|
|
||||||
LoadImage(context.Context, *LoadImageRequest) (*LoadImageResponse, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
func RegisterCRIPluginServiceServer(s *grpc.Server, srv CRIPluginServiceServer) {
|
|
||||||
s.RegisterService(&_CRIPluginService_serviceDesc, srv)
|
|
||||||
}
|
|
||||||
|
|
||||||
func _CRIPluginService_LoadImage_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
|
||||||
in := new(LoadImageRequest)
|
|
||||||
if err := dec(in); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if interceptor == nil {
|
|
||||||
return srv.(CRIPluginServiceServer).LoadImage(ctx, in)
|
|
||||||
}
|
|
||||||
info := &grpc.UnaryServerInfo{
|
|
||||||
Server: srv,
|
|
||||||
FullMethod: "/api.v1.CRIPluginService/LoadImage",
|
|
||||||
}
|
|
||||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
|
||||||
return srv.(CRIPluginServiceServer).LoadImage(ctx, req.(*LoadImageRequest))
|
|
||||||
}
|
|
||||||
return interceptor(ctx, in, info, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
var _CRIPluginService_serviceDesc = grpc.ServiceDesc{
|
|
||||||
ServiceName: "api.v1.CRIPluginService",
|
|
||||||
HandlerType: (*CRIPluginServiceServer)(nil),
|
|
||||||
Methods: []grpc.MethodDesc{
|
|
||||||
{
|
|
||||||
MethodName: "LoadImage",
|
|
||||||
Handler: _CRIPluginService_LoadImage_Handler,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Streams: []grpc.StreamDesc{},
|
|
||||||
Metadata: "api.proto",
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *LoadImageRequest) Marshal() (dAtA []byte, err error) {
|
|
||||||
size := m.Size()
|
|
||||||
dAtA = make([]byte, size)
|
|
||||||
n, err := m.MarshalTo(dAtA)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return dAtA[:n], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *LoadImageRequest) MarshalTo(dAtA []byte) (int, error) {
|
|
||||||
var i int
|
|
||||||
_ = i
|
|
||||||
var l int
|
|
||||||
_ = l
|
|
||||||
if len(m.FilePath) > 0 {
|
|
||||||
dAtA[i] = 0xa
|
|
||||||
i++
|
|
||||||
i = encodeVarintApi(dAtA, i, uint64(len(m.FilePath)))
|
|
||||||
i += copy(dAtA[i:], m.FilePath)
|
|
||||||
}
|
|
||||||
return i, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *LoadImageResponse) Marshal() (dAtA []byte, err error) {
|
|
||||||
size := m.Size()
|
|
||||||
dAtA = make([]byte, size)
|
|
||||||
n, err := m.MarshalTo(dAtA)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return dAtA[:n], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *LoadImageResponse) MarshalTo(dAtA []byte) (int, error) {
|
|
||||||
var i int
|
|
||||||
_ = i
|
|
||||||
var l int
|
|
||||||
_ = l
|
|
||||||
if len(m.Images) > 0 {
|
|
||||||
for _, s := range m.Images {
|
|
||||||
dAtA[i] = 0xa
|
|
||||||
i++
|
|
||||||
l = len(s)
|
|
||||||
for l >= 1<<7 {
|
|
||||||
dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
|
|
||||||
l >>= 7
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
dAtA[i] = uint8(l)
|
|
||||||
i++
|
|
||||||
i += copy(dAtA[i:], s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return i, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeVarintApi(dAtA []byte, offset int, v uint64) int {
|
|
||||||
for v >= 1<<7 {
|
|
||||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
|
||||||
v >>= 7
|
|
||||||
offset++
|
|
||||||
}
|
|
||||||
dAtA[offset] = uint8(v)
|
|
||||||
return offset + 1
|
|
||||||
}
|
|
||||||
func (m *LoadImageRequest) Size() (n int) {
|
|
||||||
var l int
|
|
||||||
_ = l
|
|
||||||
l = len(m.FilePath)
|
|
||||||
if l > 0 {
|
|
||||||
n += 1 + l + sovApi(uint64(l))
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *LoadImageResponse) Size() (n int) {
|
|
||||||
var l int
|
|
||||||
_ = l
|
|
||||||
if len(m.Images) > 0 {
|
|
||||||
for _, s := range m.Images {
|
|
||||||
l = len(s)
|
|
||||||
n += 1 + l + sovApi(uint64(l))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func sovApi(x uint64) (n int) {
|
|
||||||
for {
|
|
||||||
n++
|
|
||||||
x >>= 7
|
|
||||||
if x == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
func sozApi(x uint64) (n int) {
|
|
||||||
return sovApi(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
|
||||||
}
|
|
||||||
func (this *LoadImageRequest) String() string {
|
|
||||||
if this == nil {
|
|
||||||
return "nil"
|
|
||||||
}
|
|
||||||
s := strings.Join([]string{`&LoadImageRequest{`,
|
|
||||||
`FilePath:` + fmt.Sprintf("%v", this.FilePath) + `,`,
|
|
||||||
`}`,
|
|
||||||
}, "")
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
func (this *LoadImageResponse) String() string {
|
|
||||||
if this == nil {
|
|
||||||
return "nil"
|
|
||||||
}
|
|
||||||
s := strings.Join([]string{`&LoadImageResponse{`,
|
|
||||||
`Images:` + fmt.Sprintf("%v", this.Images) + `,`,
|
|
||||||
`}`,
|
|
||||||
}, "")
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
func valueToStringApi(v interface{}) string {
|
|
||||||
rv := reflect.ValueOf(v)
|
|
||||||
if rv.IsNil() {
|
|
||||||
return "nil"
|
|
||||||
}
|
|
||||||
pv := reflect.Indirect(rv).Interface()
|
|
||||||
return fmt.Sprintf("*%v", pv)
|
|
||||||
}
|
|
||||||
func (m *LoadImageRequest) Unmarshal(dAtA []byte) error {
|
|
||||||
l := len(dAtA)
|
|
||||||
iNdEx := 0
|
|
||||||
for iNdEx < l {
|
|
||||||
preIndex := iNdEx
|
|
||||||
var wire uint64
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowApi
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
wire |= (uint64(b) & 0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fieldNum := int32(wire >> 3)
|
|
||||||
wireType := int(wire & 0x7)
|
|
||||||
if wireType == 4 {
|
|
||||||
return fmt.Errorf("proto: LoadImageRequest: wiretype end group for non-group")
|
|
||||||
}
|
|
||||||
if fieldNum <= 0 {
|
|
||||||
return fmt.Errorf("proto: LoadImageRequest: illegal tag %d (wire type %d)", fieldNum, wire)
|
|
||||||
}
|
|
||||||
switch fieldNum {
|
|
||||||
case 1:
|
|
||||||
if wireType != 2 {
|
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field FilePath", wireType)
|
|
||||||
}
|
|
||||||
var stringLen uint64
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowApi
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
stringLen |= (uint64(b) & 0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
intStringLen := int(stringLen)
|
|
||||||
if intStringLen < 0 {
|
|
||||||
return ErrInvalidLengthApi
|
|
||||||
}
|
|
||||||
postIndex := iNdEx + intStringLen
|
|
||||||
if postIndex > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
m.FilePath = string(dAtA[iNdEx:postIndex])
|
|
||||||
iNdEx = postIndex
|
|
||||||
default:
|
|
||||||
iNdEx = preIndex
|
|
||||||
skippy, err := skipApi(dAtA[iNdEx:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if skippy < 0 {
|
|
||||||
return ErrInvalidLengthApi
|
|
||||||
}
|
|
||||||
if (iNdEx + skippy) > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
iNdEx += skippy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if iNdEx > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func (m *LoadImageResponse) Unmarshal(dAtA []byte) error {
|
|
||||||
l := len(dAtA)
|
|
||||||
iNdEx := 0
|
|
||||||
for iNdEx < l {
|
|
||||||
preIndex := iNdEx
|
|
||||||
var wire uint64
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowApi
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
wire |= (uint64(b) & 0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fieldNum := int32(wire >> 3)
|
|
||||||
wireType := int(wire & 0x7)
|
|
||||||
if wireType == 4 {
|
|
||||||
return fmt.Errorf("proto: LoadImageResponse: wiretype end group for non-group")
|
|
||||||
}
|
|
||||||
if fieldNum <= 0 {
|
|
||||||
return fmt.Errorf("proto: LoadImageResponse: illegal tag %d (wire type %d)", fieldNum, wire)
|
|
||||||
}
|
|
||||||
switch fieldNum {
|
|
||||||
case 1:
|
|
||||||
if wireType != 2 {
|
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field Images", wireType)
|
|
||||||
}
|
|
||||||
var stringLen uint64
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowApi
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
stringLen |= (uint64(b) & 0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
intStringLen := int(stringLen)
|
|
||||||
if intStringLen < 0 {
|
|
||||||
return ErrInvalidLengthApi
|
|
||||||
}
|
|
||||||
postIndex := iNdEx + intStringLen
|
|
||||||
if postIndex > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
m.Images = append(m.Images, string(dAtA[iNdEx:postIndex]))
|
|
||||||
iNdEx = postIndex
|
|
||||||
default:
|
|
||||||
iNdEx = preIndex
|
|
||||||
skippy, err := skipApi(dAtA[iNdEx:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if skippy < 0 {
|
|
||||||
return ErrInvalidLengthApi
|
|
||||||
}
|
|
||||||
if (iNdEx + skippy) > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
iNdEx += skippy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if iNdEx > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func skipApi(dAtA []byte) (n int, err error) {
|
|
||||||
l := len(dAtA)
|
|
||||||
iNdEx := 0
|
|
||||||
for iNdEx < l {
|
|
||||||
var wire uint64
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return 0, ErrIntOverflowApi
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return 0, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
wire |= (uint64(b) & 0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wireType := int(wire & 0x7)
|
|
||||||
switch wireType {
|
|
||||||
case 0:
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return 0, ErrIntOverflowApi
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return 0, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
iNdEx++
|
|
||||||
if dAtA[iNdEx-1] < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return iNdEx, nil
|
|
||||||
case 1:
|
|
||||||
iNdEx += 8
|
|
||||||
return iNdEx, nil
|
|
||||||
case 2:
|
|
||||||
var length int
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return 0, ErrIntOverflowApi
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return 0, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
length |= (int(b) & 0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iNdEx += length
|
|
||||||
if length < 0 {
|
|
||||||
return 0, ErrInvalidLengthApi
|
|
||||||
}
|
|
||||||
return iNdEx, nil
|
|
||||||
case 3:
|
|
||||||
for {
|
|
||||||
var innerWire uint64
|
|
||||||
var start int = iNdEx
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return 0, ErrIntOverflowApi
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return 0, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
innerWire |= (uint64(b) & 0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
innerWireType := int(innerWire & 0x7)
|
|
||||||
if innerWireType == 4 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
next, err := skipApi(dAtA[start:])
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
iNdEx = start + next
|
|
||||||
}
|
|
||||||
return iNdEx, nil
|
|
||||||
case 4:
|
|
||||||
return iNdEx, nil
|
|
||||||
case 5:
|
|
||||||
iNdEx += 4
|
|
||||||
return iNdEx, nil
|
|
||||||
default:
|
|
||||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrInvalidLengthApi = fmt.Errorf("proto: negative length found during unmarshaling")
|
|
||||||
ErrIntOverflowApi = fmt.Errorf("proto: integer overflow")
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() { proto.RegisterFile("api.proto", fileDescriptorApi) }
|
|
||||||
|
|
||||||
var fileDescriptorApi = []byte{
|
|
||||||
// 219 bytes of a gzipped FileDescriptorProto
|
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4c, 0x2c, 0xc8, 0xd4,
|
|
||||||
0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x62, 0x03, 0x31, 0xcb, 0x0c, 0xa5, 0x74, 0xd3, 0x33, 0x4b,
|
|
||||||
0x32, 0x4a, 0x93, 0xf4, 0x92, 0xf3, 0x73, 0xf5, 0xd3, 0xf3, 0xd3, 0xf3, 0xf5, 0xc1, 0xd2, 0x49,
|
|
||||||
0xa5, 0x69, 0x60, 0x1e, 0x98, 0x03, 0x66, 0x41, 0xb4, 0x29, 0xe9, 0x71, 0x09, 0xf8, 0xe4, 0x27,
|
|
||||||
0xa6, 0x78, 0xe6, 0x26, 0xa6, 0xa7, 0x06, 0xa5, 0x16, 0x96, 0xa6, 0x16, 0x97, 0x08, 0x49, 0x71,
|
|
||||||
0x71, 0xb8, 0x65, 0xe6, 0xa4, 0x06, 0x24, 0x96, 0x64, 0x48, 0x30, 0x2a, 0x30, 0x6a, 0x70, 0x06,
|
|
||||||
0xc1, 0xf9, 0x4a, 0xda, 0x5c, 0x82, 0x48, 0xea, 0x8b, 0x0b, 0xf2, 0xf3, 0x8a, 0x53, 0x85, 0xc4,
|
|
||||||
0xb8, 0xd8, 0xc0, 0x02, 0xc5, 0x12, 0x8c, 0x0a, 0xcc, 0x1a, 0x9c, 0x41, 0x50, 0x9e, 0x51, 0x18,
|
|
||||||
0x97, 0x80, 0x73, 0x90, 0x67, 0x40, 0x4e, 0x69, 0x7a, 0x66, 0x5e, 0x70, 0x6a, 0x51, 0x59, 0x66,
|
|
||||||
0x72, 0xaa, 0x90, 0x13, 0x17, 0x27, 0xdc, 0x00, 0x21, 0x09, 0x3d, 0x88, 0xab, 0xf5, 0xd0, 0xdd,
|
|
||||||
0x20, 0x25, 0x89, 0x45, 0x06, 0x62, 0x9b, 0x12, 0x83, 0x93, 0xcc, 0x89, 0x87, 0x72, 0x8c, 0x37,
|
|
||||||
0x1e, 0xca, 0x31, 0x34, 0x3c, 0x92, 0x63, 0x3c, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6,
|
|
||||||
0x07, 0x8f, 0xe4, 0x18, 0x27, 0x3c, 0x96, 0x63, 0x48, 0x62, 0x03, 0xfb, 0xcc, 0x18, 0x10, 0x00,
|
|
||||||
0x00, 0xff, 0xff, 0xfc, 0x6f, 0xec, 0xf4, 0x1d, 0x01, 0x00, 0x00,
|
|
||||||
}
|
|
@ -1,30 +0,0 @@
|
|||||||
// To regenerate api.pb.go run `make proto`
|
|
||||||
syntax = 'proto3';
|
|
||||||
|
|
||||||
package api.v1;
|
|
||||||
|
|
||||||
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
|
|
||||||
|
|
||||||
option (gogoproto.goproto_stringer_all) = false;
|
|
||||||
option (gogoproto.stringer_all) = true;
|
|
||||||
option (gogoproto.goproto_getters_all) = true;
|
|
||||||
option (gogoproto.marshaler_all) = true;
|
|
||||||
option (gogoproto.sizer_all) = true;
|
|
||||||
option (gogoproto.unmarshaler_all) = true;
|
|
||||||
option (gogoproto.goproto_unrecognized_all) = false;
|
|
||||||
|
|
||||||
// CRIPluginService defines non-CRI APIs for cri plugin.
|
|
||||||
service CRIPluginService{
|
|
||||||
// LoadImage loads a image into containerd.
|
|
||||||
rpc LoadImage(LoadImageRequest) returns (LoadImageResponse) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
message LoadImageRequest {
|
|
||||||
// FilePath is the absolute path of docker image tarball.
|
|
||||||
string FilePath = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message LoadImageResponse {
|
|
||||||
// Images have been loaded.
|
|
||||||
repeated string Images = 1;
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2017 The Kubernetes 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 client
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"net"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"google.golang.org/grpc"
|
|
||||||
"k8s.io/kubernetes/pkg/kubelet/util"
|
|
||||||
|
|
||||||
api "github.com/containerd/cri/pkg/api/v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewCRIPluginClient creates grpc client of cri plugin
|
|
||||||
// TODO(random-liu): Wrap grpc functions.
|
|
||||||
func NewCRIPluginClient(ctx context.Context, endpoint string) (api.CRIPluginServiceClient, error) {
|
|
||||||
addr, dialer, err := util.GetAddressAndDialer(endpoint)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to get dialer")
|
|
||||||
}
|
|
||||||
conn, err := grpc.DialContext(ctx, addr,
|
|
||||||
grpc.WithBlock(),
|
|
||||||
grpc.WithInsecure(),
|
|
||||||
grpc.WithContextDialer(
|
|
||||||
func(ctx context.Context, addr string) (net.Conn, error) {
|
|
||||||
if deadline, ok := ctx.Deadline(); ok {
|
|
||||||
return dialer(addr, time.Until(deadline))
|
|
||||||
}
|
|
||||||
return dialer(addr, 0)
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to dial")
|
|
||||||
}
|
|
||||||
return api.NewCRIPluginServiceClient(conn), nil
|
|
||||||
}
|
|
@ -1,356 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2017 The Kubernetes 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 importer
|
|
||||||
|
|
||||||
import (
|
|
||||||
"archive/tar"
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/content"
|
|
||||||
"github.com/containerd/containerd/errdefs"
|
|
||||||
"github.com/containerd/containerd/images"
|
|
||||||
"github.com/containerd/containerd/leases"
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
"github.com/docker/distribution/reference"
|
|
||||||
"github.com/opencontainers/go-digest"
|
|
||||||
"github.com/opencontainers/image-spec/specs-go"
|
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
|
|
||||||
ctrdutil "github.com/containerd/cri/pkg/containerd/util"
|
|
||||||
)
|
|
||||||
|
|
||||||
// This code reuses the docker import code from containerd/containerd#1602.
|
|
||||||
// It has been simplified a bit and garbage collection support was added.
|
|
||||||
// If a library/helper is added to containerd in the future, we should switch to it.
|
|
||||||
|
|
||||||
// manifestDotJSON is an entry in manifest.json.
|
|
||||||
type manifestDotJSON struct {
|
|
||||||
Config string
|
|
||||||
RepoTags []string
|
|
||||||
Layers []string
|
|
||||||
// Parent is unsupported
|
|
||||||
Parent string
|
|
||||||
}
|
|
||||||
|
|
||||||
// isLayerTar returns true if name is like "foobar/layer.tar"
|
|
||||||
func isLayerTar(name string) bool {
|
|
||||||
slashes := len(strings.Split(name, "/"))
|
|
||||||
return slashes == 2 && strings.HasSuffix(name, "/layer.tar")
|
|
||||||
}
|
|
||||||
|
|
||||||
// followSymlinkLayer returns actual layer name of the symlink layer.
|
|
||||||
// It returns "foobar/layer.tar" if the name is like
|
|
||||||
// "../foobar/layer.tar", and returns error if the name
|
|
||||||
// is not in "../foobar/layer.tar" format.
|
|
||||||
func followSymlinkLayer(name string) (string, error) {
|
|
||||||
parts := strings.Split(name, "/")
|
|
||||||
if len(parts) != 3 || parts[0] != ".." {
|
|
||||||
return "", errors.New("invalid symlink layer")
|
|
||||||
}
|
|
||||||
name = strings.TrimPrefix(name, "../")
|
|
||||||
if !isLayerTar(name) {
|
|
||||||
return "", errors.New("invalid layer tar")
|
|
||||||
}
|
|
||||||
return name, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// isDotJSON returns true if name is like "foobar.json"
|
|
||||||
func isDotJSON(name string) bool {
|
|
||||||
slashes := len(strings.Split(name, "/"))
|
|
||||||
return slashes == 1 && strings.HasSuffix(name, ".json")
|
|
||||||
}
|
|
||||||
|
|
||||||
type imageConfig struct {
|
|
||||||
desc ocispec.Descriptor
|
|
||||||
img ocispec.Image
|
|
||||||
}
|
|
||||||
|
|
||||||
type importConfig struct {
|
|
||||||
unpack bool
|
|
||||||
snapshotter string
|
|
||||||
}
|
|
||||||
|
|
||||||
// ImportOption configures import behavior.
|
|
||||||
type ImportOption func(*importConfig)
|
|
||||||
|
|
||||||
// WithUnpack is used to unpack image after import.
|
|
||||||
func WithUnpack(snapshotter string) ImportOption {
|
|
||||||
return func(c *importConfig) {
|
|
||||||
c.unpack = true
|
|
||||||
c.snapshotter = snapshotter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Import implements Docker Image Spec v1.1.
|
|
||||||
// An image MUST have `manifest.json`.
|
|
||||||
// `repositories` file in Docker Image Spec v1.0 is not supported (yet).
|
|
||||||
// Also, the current implementation assumes the implicit file name convention,
|
|
||||||
// which is not explicitly documented in the spec. (e.g. foobar/layer.tar)
|
|
||||||
// It returns a group of image references successfully loaded.
|
|
||||||
func Import(ctx context.Context, client *containerd.Client, reader io.Reader, opts ...ImportOption) (_ []string, retErr error) {
|
|
||||||
c := &importConfig{}
|
|
||||||
for _, o := range opts {
|
|
||||||
o(c)
|
|
||||||
}
|
|
||||||
ctx, done, err := client.WithLease(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
deferCtx, deferCancel := ctrdutil.DeferContext()
|
|
||||||
defer deferCancel()
|
|
||||||
if err := done(deferCtx); err != nil {
|
|
||||||
// Get lease id from context still works after context is done.
|
|
||||||
leaseID, _ := leases.FromContext(ctx)
|
|
||||||
log.G(ctx).WithError(err).Errorf("Failed to release lease %q", leaseID)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
cs := client.ContentStore()
|
|
||||||
is := client.ImageService()
|
|
||||||
|
|
||||||
tr := tar.NewReader(reader)
|
|
||||||
var (
|
|
||||||
mfsts []manifestDotJSON
|
|
||||||
symlinkLayers = make(map[string]string) // key: filename (foobar/layer.tar), value: linkname (targetlayerid/layer.tar)
|
|
||||||
layers = make(map[string]ocispec.Descriptor) // key: filename (foobar/layer.tar)
|
|
||||||
configs = make(map[string]imageConfig) // key: filename (foobar.json)
|
|
||||||
)
|
|
||||||
for {
|
|
||||||
hdr, err := tr.Next()
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "get next file")
|
|
||||||
}
|
|
||||||
if hdr.Typeflag == tar.TypeSymlink && isLayerTar(hdr.Name) {
|
|
||||||
linkname, err := followSymlinkLayer(hdr.Linkname)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "follow symlink layer from %q to %q", hdr.Name, hdr.Linkname)
|
|
||||||
}
|
|
||||||
symlinkLayers[hdr.Name] = linkname
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if hdr.Typeflag != tar.TypeReg && hdr.Typeflag != tar.TypeRegA {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if hdr.Name == "manifest.json" {
|
|
||||||
mfsts, err = onUntarManifestJSON(tr)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "untar manifest %q", hdr.Name)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if isLayerTar(hdr.Name) {
|
|
||||||
desc, err := onUntarLayerTar(ctx, tr, cs, hdr.Name, hdr.Size)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "untar layer %q", hdr.Name)
|
|
||||||
}
|
|
||||||
layers[hdr.Name] = *desc
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if isDotJSON(hdr.Name) {
|
|
||||||
c, err := onUntarDotJSON(ctx, tr, cs, hdr.Name, hdr.Size)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "untar config %q", hdr.Name)
|
|
||||||
}
|
|
||||||
configs[hdr.Name] = *c
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for name, linkname := range symlinkLayers {
|
|
||||||
desc, ok := layers[linkname]
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.Errorf("no target for symlink layer from %q to %q", name, linkname)
|
|
||||||
}
|
|
||||||
layers[name] = desc
|
|
||||||
}
|
|
||||||
var refs []string
|
|
||||||
defer func() {
|
|
||||||
if retErr == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// TODO(random-liu): Consider whether we should keep images already imported
|
|
||||||
// even when there is an error.
|
|
||||||
for _, ref := range refs {
|
|
||||||
func() {
|
|
||||||
deferCtx, deferCancel := ctrdutil.DeferContext()
|
|
||||||
defer deferCancel()
|
|
||||||
if err := is.Delete(deferCtx, ref); err != nil {
|
|
||||||
log.G(ctx).WithError(err).Errorf("Failed to remove image %q", ref)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
for _, mfst := range mfsts {
|
|
||||||
config, ok := configs[mfst.Config]
|
|
||||||
if !ok {
|
|
||||||
return refs, errors.Errorf("image config %q not found", mfst.Config)
|
|
||||||
}
|
|
||||||
schema2Manifest, err := makeDockerSchema2Manifest(mfst, config, layers)
|
|
||||||
if err != nil {
|
|
||||||
return refs, errors.Wrap(err, "create docker manifest")
|
|
||||||
}
|
|
||||||
desc, err := writeDockerSchema2Manifest(ctx, cs, *schema2Manifest, config.img.Architecture, config.img.OS)
|
|
||||||
if err != nil {
|
|
||||||
return refs, errors.Wrap(err, "write docker manifest")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ref := range mfst.RepoTags {
|
|
||||||
normalized, err := reference.ParseDockerRef(ref)
|
|
||||||
if err != nil {
|
|
||||||
return refs, errors.Wrapf(err, "normalize image ref %q", ref)
|
|
||||||
}
|
|
||||||
ref = normalized.String()
|
|
||||||
imgrec := images.Image{
|
|
||||||
Name: ref,
|
|
||||||
Target: *desc,
|
|
||||||
}
|
|
||||||
if c.unpack {
|
|
||||||
img := containerd.NewImage(client, imgrec)
|
|
||||||
if err := img.Unpack(ctx, c.snapshotter); err != nil {
|
|
||||||
return refs, errors.Wrapf(err, "unpack image %q", ref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if _, err := is.Create(ctx, imgrec); err != nil {
|
|
||||||
if !errdefs.IsAlreadyExists(err) {
|
|
||||||
return refs, errors.Wrapf(err, "create image ref %+v", imgrec)
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := is.Update(ctx, imgrec)
|
|
||||||
if err != nil {
|
|
||||||
return refs, errors.Wrapf(err, "update image ref %+v", imgrec)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
refs = append(refs, ref)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return refs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeDockerSchema2Manifest(mfst manifestDotJSON, config imageConfig, layers map[string]ocispec.Descriptor) (*ocispec.Manifest, error) {
|
|
||||||
manifest := ocispec.Manifest{
|
|
||||||
Versioned: specs.Versioned{
|
|
||||||
SchemaVersion: 2,
|
|
||||||
},
|
|
||||||
Config: config.desc,
|
|
||||||
}
|
|
||||||
for _, f := range mfst.Layers {
|
|
||||||
desc, ok := layers[f]
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.Errorf("layer %q not found", f)
|
|
||||||
}
|
|
||||||
manifest.Layers = append(manifest.Layers, desc)
|
|
||||||
}
|
|
||||||
return &manifest, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func writeDockerSchema2Manifest(ctx context.Context, cs content.Ingester, manifest ocispec.Manifest, arch, os string) (*ocispec.Descriptor, error) {
|
|
||||||
manifestBytes, err := json.Marshal(manifest)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
manifestBytesR := bytes.NewReader(manifestBytes)
|
|
||||||
manifestDigest := digest.FromBytes(manifestBytes)
|
|
||||||
labels := map[string]string{}
|
|
||||||
labels["containerd.io/gc.ref.content.0"] = manifest.Config.Digest.String()
|
|
||||||
for i, ch := range manifest.Layers {
|
|
||||||
labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i+1)] = ch.Digest.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
desc := ocispec.Descriptor{
|
|
||||||
MediaType: images.MediaTypeDockerSchema2Manifest,
|
|
||||||
Digest: manifestDigest,
|
|
||||||
Size: int64(len(manifestBytes)),
|
|
||||||
}
|
|
||||||
if err := content.WriteBlob(ctx, cs, "manifest-"+manifestDigest.String(), manifestBytesR,
|
|
||||||
desc, content.WithLabels(labels)); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if arch != "" || os != "" {
|
|
||||||
desc.Platform = &ocispec.Platform{
|
|
||||||
Architecture: arch,
|
|
||||||
OS: os,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &desc, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func onUntarManifestJSON(r io.Reader) ([]manifestDotJSON, error) {
|
|
||||||
// name: "manifest.json"
|
|
||||||
b, err := ioutil.ReadAll(r)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
var mfsts []manifestDotJSON
|
|
||||||
if err := json.Unmarshal(b, &mfsts); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return mfsts, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func onUntarLayerTar(ctx context.Context, r io.Reader, cs content.Ingester, name string, size int64) (*ocispec.Descriptor, error) {
|
|
||||||
// name is like "foobar/layer.tar" ( guaranteed by isLayerTar() )
|
|
||||||
split := strings.Split(name, "/")
|
|
||||||
// note: split[0] is not expected digest here
|
|
||||||
cw, err := cs.Writer(ctx, content.WithRef("layer-"+split[0]), content.WithDescriptor(ocispec.Descriptor{Size: size}))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer cw.Close()
|
|
||||||
if err := content.Copy(ctx, cw, r, size, ""); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &ocispec.Descriptor{
|
|
||||||
MediaType: images.MediaTypeDockerSchema2Layer,
|
|
||||||
Size: size,
|
|
||||||
Digest: cw.Digest(),
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func onUntarDotJSON(ctx context.Context, r io.Reader, cs content.Ingester, name string, size int64) (*imageConfig, error) {
|
|
||||||
config := imageConfig{}
|
|
||||||
config.desc.MediaType = images.MediaTypeDockerSchema2Config
|
|
||||||
config.desc.Size = size
|
|
||||||
// name is like "foobar.json" ( guaranteed by is DotJSON() )
|
|
||||||
split := strings.Split(name, ".")
|
|
||||||
cw, err := cs.Writer(ctx, content.WithRef("config-"+split[0]), content.WithDescriptor(ocispec.Descriptor{Size: size}))
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer cw.Close()
|
|
||||||
var buf bytes.Buffer
|
|
||||||
tr := io.TeeReader(r, &buf)
|
|
||||||
if err := content.Copy(ctx, cw, tr, size, ""); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
config.desc.Digest = cw.Digest()
|
|
||||||
if err := json.Unmarshal(buf.Bytes(), &config.img); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &config, nil
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2017 The Kubernetes 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 server
|
|
||||||
|
|
||||||
import (
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"golang.org/x/net/context"
|
|
||||||
|
|
||||||
api "github.com/containerd/cri/pkg/api/v1"
|
|
||||||
"github.com/containerd/cri/pkg/containerd/importer"
|
|
||||||
)
|
|
||||||
|
|
||||||
// LoadImage loads a image into containerd.
|
|
||||||
func (c *criService) LoadImage(ctx context.Context, r *api.LoadImageRequest) (*api.LoadImageResponse, error) {
|
|
||||||
path := r.GetFilePath()
|
|
||||||
if !filepath.IsAbs(path) {
|
|
||||||
return nil, errors.Errorf("path %q is not an absolute path", path)
|
|
||||||
}
|
|
||||||
f, err := os.Open(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to open file")
|
|
||||||
}
|
|
||||||
repoTags, err := importer.Import(ctx, c.client, f, importer.WithUnpack(c.config.ContainerdConfig.Snapshotter))
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "failed to import image")
|
|
||||||
}
|
|
||||||
for _, repoTag := range repoTags {
|
|
||||||
// Update image store to reflect the newest state in containerd.
|
|
||||||
// Image imported by importer.Import is not treated as managed
|
|
||||||
// by the cri plugin, call `updateImage` to make it managed.
|
|
||||||
// TODO(random-liu): Replace this with the containerd library (issue #909).
|
|
||||||
if err := c.updateImage(ctx, repoTag); err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "update image store %q", repoTag)
|
|
||||||
}
|
|
||||||
logrus.Debugf("Imported image %q", repoTag)
|
|
||||||
}
|
|
||||||
return &api.LoadImageResponse{Images: repoTags}, nil
|
|
||||||
}
|
|
@ -23,7 +23,6 @@ import (
|
|||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
||||||
|
|
||||||
api "github.com/containerd/cri/pkg/api/v1"
|
|
||||||
ctrdutil "github.com/containerd/cri/pkg/containerd/util"
|
ctrdutil "github.com/containerd/cri/pkg/containerd/util"
|
||||||
"github.com/containerd/cri/pkg/log"
|
"github.com/containerd/cri/pkg/log"
|
||||||
)
|
)
|
||||||
@ -448,21 +447,6 @@ func (in *instrumentedService) UpdateRuntimeConfig(ctx context.Context, r *runti
|
|||||||
return in.c.UpdateRuntimeConfig(ctrdutil.WithNamespace(ctx), r)
|
return in.c.UpdateRuntimeConfig(ctrdutil.WithNamespace(ctx), r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (in *instrumentedService) LoadImage(ctx context.Context, r *api.LoadImageRequest) (res *api.LoadImageResponse, err error) {
|
|
||||||
if err := in.checkInitialized(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
logrus.Debugf("LoadImage from file %q", r.GetFilePath())
|
|
||||||
defer func() {
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithError(err).Error("LoadImage failed")
|
|
||||||
} else {
|
|
||||||
logrus.Debugf("LoadImage returns images %+v", res.GetImages())
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return in.c.LoadImage(ctrdutil.WithNamespace(ctx), r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (in *instrumentedService) ReopenContainerLog(ctx context.Context, r *runtime.ReopenContainerLogRequest) (res *runtime.ReopenContainerLogResponse, err error) {
|
func (in *instrumentedService) ReopenContainerLog(ctx context.Context, r *runtime.ReopenContainerLogRequest) (res *runtime.ReopenContainerLogResponse, err error) {
|
||||||
if err := in.checkInitialized(); err != nil {
|
if err := in.checkInitialized(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -36,7 +36,6 @@ import (
|
|||||||
runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/server/streaming"
|
"k8s.io/kubernetes/pkg/kubelet/server/streaming"
|
||||||
|
|
||||||
api "github.com/containerd/cri/pkg/api/v1"
|
|
||||||
"github.com/containerd/cri/pkg/atomic"
|
"github.com/containerd/cri/pkg/atomic"
|
||||||
criconfig "github.com/containerd/cri/pkg/config"
|
criconfig "github.com/containerd/cri/pkg/config"
|
||||||
ctrdutil "github.com/containerd/cri/pkg/containerd/util"
|
ctrdutil "github.com/containerd/cri/pkg/containerd/util"
|
||||||
@ -52,7 +51,6 @@ import (
|
|||||||
type grpcServices interface {
|
type grpcServices interface {
|
||||||
runtime.RuntimeServiceServer
|
runtime.RuntimeServiceServer
|
||||||
runtime.ImageServiceServer
|
runtime.ImageServiceServer
|
||||||
api.CRIPluginServiceServer
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CRIService is the interface implement CRI remote service server.
|
// CRIService is the interface implement CRI remote service server.
|
||||||
@ -176,7 +174,6 @@ func (c *criService) Register(s *grpc.Server) error {
|
|||||||
instrumented := newInstrumentedService(c)
|
instrumented := newInstrumentedService(c)
|
||||||
runtime.RegisterRuntimeServiceServer(s, instrumented)
|
runtime.RegisterRuntimeServiceServer(s, instrumented)
|
||||||
runtime.RegisterImageServiceServer(s, instrumented)
|
runtime.RegisterImageServiceServer(s, instrumented)
|
||||||
api.RegisterCRIPluginServiceServer(s, instrumented)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
116
vendor/github.com/containerd/containerd/cmd/ctr/app/main.go
generated
vendored
116
vendor/github.com/containerd/containerd/cmd/ctr/app/main.go
generated
vendored
@ -1,116 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 app
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands/containers"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands/content"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands/events"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands/images"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands/install"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands/leases"
|
|
||||||
namespacesCmd "github.com/containerd/containerd/cmd/ctr/commands/namespaces"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands/plugins"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands/pprof"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands/run"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands/snapshots"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands/tasks"
|
|
||||||
versionCmd "github.com/containerd/containerd/cmd/ctr/commands/version"
|
|
||||||
"github.com/containerd/containerd/defaults"
|
|
||||||
"github.com/containerd/containerd/namespaces"
|
|
||||||
"github.com/containerd/containerd/version"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
"google.golang.org/grpc/grpclog"
|
|
||||||
)
|
|
||||||
|
|
||||||
var extraCmds = []cli.Command{}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Discard grpc logs so that they don't mess with our stdio
|
|
||||||
grpclog.SetLoggerV2(grpclog.NewLoggerV2(ioutil.Discard, ioutil.Discard, ioutil.Discard))
|
|
||||||
|
|
||||||
cli.VersionPrinter = func(c *cli.Context) {
|
|
||||||
fmt.Println(c.App.Name, version.Package, c.App.Version)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// New returns a *cli.App instance.
|
|
||||||
func New() *cli.App {
|
|
||||||
app := cli.NewApp()
|
|
||||||
app.Name = "ctr"
|
|
||||||
app.Version = version.Version
|
|
||||||
app.Usage = `
|
|
||||||
__
|
|
||||||
_____/ /______
|
|
||||||
/ ___/ __/ ___/
|
|
||||||
/ /__/ /_/ /
|
|
||||||
\___/\__/_/
|
|
||||||
|
|
||||||
containerd CLI
|
|
||||||
`
|
|
||||||
app.Flags = []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "debug",
|
|
||||||
Usage: "enable debug output in logs",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "address, a",
|
|
||||||
Usage: "address for containerd's GRPC server",
|
|
||||||
Value: defaults.DefaultAddress,
|
|
||||||
},
|
|
||||||
cli.DurationFlag{
|
|
||||||
Name: "timeout",
|
|
||||||
Usage: "total timeout for ctr commands",
|
|
||||||
},
|
|
||||||
cli.DurationFlag{
|
|
||||||
Name: "connect-timeout",
|
|
||||||
Usage: "timeout for connecting to containerd",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "namespace, n",
|
|
||||||
Usage: "namespace to use with commands",
|
|
||||||
Value: namespaces.Default,
|
|
||||||
EnvVar: namespaces.NamespaceEnvVar,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
app.Commands = append([]cli.Command{
|
|
||||||
plugins.Command,
|
|
||||||
versionCmd.Command,
|
|
||||||
containers.Command,
|
|
||||||
content.Command,
|
|
||||||
events.Command,
|
|
||||||
images.Command,
|
|
||||||
leases.Command,
|
|
||||||
namespacesCmd.Command,
|
|
||||||
pprof.Command,
|
|
||||||
run.Command,
|
|
||||||
snapshots.Command,
|
|
||||||
tasks.Command,
|
|
||||||
install.Command,
|
|
||||||
}, extraCmds...)
|
|
||||||
app.Before = func(context *cli.Context) error {
|
|
||||||
if context.GlobalBool("debug") {
|
|
||||||
logrus.SetLevel(logrus.DebugLevel)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return app
|
|
||||||
}
|
|
25
vendor/github.com/containerd/containerd/cmd/ctr/app/main_unix.go
generated
vendored
25
vendor/github.com/containerd/containerd/cmd/ctr/app/main_unix.go
generated
vendored
@ -1,25 +0,0 @@
|
|||||||
// +build !windows
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright The containerd 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 app
|
|
||||||
|
|
||||||
import "github.com/containerd/containerd/cmd/ctr/commands/shim"
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
extraCmds = append(extraCmds, shim.Command)
|
|
||||||
}
|
|
56
vendor/github.com/containerd/containerd/cmd/ctr/commands/client.go
generated
vendored
56
vendor/github.com/containerd/containerd/cmd/ctr/commands/client.go
generated
vendored
@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 commands
|
|
||||||
|
|
||||||
import (
|
|
||||||
gocontext "context"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/namespaces"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AppContext returns the context for a command. Should only be called once per
|
|
||||||
// command, near the start.
|
|
||||||
//
|
|
||||||
// This will ensure the namespace is picked up and set the timeout, if one is
|
|
||||||
// defined.
|
|
||||||
func AppContext(context *cli.Context) (gocontext.Context, gocontext.CancelFunc) {
|
|
||||||
var (
|
|
||||||
ctx = gocontext.Background()
|
|
||||||
timeout = context.GlobalDuration("timeout")
|
|
||||||
namespace = context.GlobalString("namespace")
|
|
||||||
cancel gocontext.CancelFunc
|
|
||||||
)
|
|
||||||
ctx = namespaces.WithNamespace(ctx, namespace)
|
|
||||||
if timeout > 0 {
|
|
||||||
ctx, cancel = gocontext.WithTimeout(ctx, timeout)
|
|
||||||
} else {
|
|
||||||
ctx, cancel = gocontext.WithCancel(ctx)
|
|
||||||
}
|
|
||||||
return ctx, cancel
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClient returns a new containerd client
|
|
||||||
func NewClient(context *cli.Context, opts ...containerd.ClientOpt) (*containerd.Client, gocontext.Context, gocontext.CancelFunc, error) {
|
|
||||||
client, err := containerd.New(context.GlobalString("address"), opts...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, nil, err
|
|
||||||
}
|
|
||||||
ctx, cancel := AppContext(context)
|
|
||||||
return client, ctx, cancel, nil
|
|
||||||
}
|
|
187
vendor/github.com/containerd/containerd/cmd/ctr/commands/commands.go
generated
vendored
187
vendor/github.com/containerd/containerd/cmd/ctr/commands/commands.go
generated
vendored
@ -1,187 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 commands
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// SnapshotterFlags are cli flags specifying snapshotter names
|
|
||||||
SnapshotterFlags = []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "snapshotter",
|
|
||||||
Usage: "snapshotter name. Empty value stands for the default value.",
|
|
||||||
Value: containerd.DefaultSnapshotter,
|
|
||||||
EnvVar: "CONTAINERD_SNAPSHOTTER",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// LabelFlag is a cli flag specifying labels
|
|
||||||
LabelFlag = cli.StringSliceFlag{
|
|
||||||
Name: "label",
|
|
||||||
Usage: "labels to attach to the image",
|
|
||||||
}
|
|
||||||
|
|
||||||
// RegistryFlags are cli flags specifying registry options
|
|
||||||
RegistryFlags = []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "skip-verify,k",
|
|
||||||
Usage: "skip SSL certificate validation",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "plain-http",
|
|
||||||
Usage: "allow connections using plain HTTP",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "user,u",
|
|
||||||
Usage: "user[:password] Registry user and password",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "refresh",
|
|
||||||
Usage: "refresh token for authorization server",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContainerFlags are cli flags specifying container options
|
|
||||||
ContainerFlags = []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "config,c",
|
|
||||||
Usage: "path to the runtime-specific spec config file",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "cwd",
|
|
||||||
Usage: "specify the working directory of the process",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "env",
|
|
||||||
Usage: "specify additional container environment variables (i.e. FOO=bar)",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "label",
|
|
||||||
Usage: "specify additional labels (i.e. foo=bar)",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "mount",
|
|
||||||
Usage: "specify additional container mount (ex: type=bind,src=/tmp,dst=/host,options=rbind:ro)",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "net-host",
|
|
||||||
Usage: "enable host networking for the container",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "privileged",
|
|
||||||
Usage: "run privileged container",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "read-only",
|
|
||||||
Usage: "set the containers filesystem as readonly",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "runtime",
|
|
||||||
Usage: "runtime name",
|
|
||||||
Value: fmt.Sprintf("io.containerd.runtime.v1.%s", runtime.GOOS),
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "tty,t",
|
|
||||||
Usage: "allocate a TTY for the container",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "with-ns",
|
|
||||||
Usage: "specify existing Linux namespaces to join at container runtime (format '<nstype>:<path>')",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "pid-file",
|
|
||||||
Usage: "file path to write the task's pid",
|
|
||||||
},
|
|
||||||
cli.IntFlag{
|
|
||||||
Name: "gpus",
|
|
||||||
Usage: "add gpus to the container",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "allow-new-privs",
|
|
||||||
Usage: "turn off OCI spec's NoNewPrivileges feature flag",
|
|
||||||
},
|
|
||||||
cli.Uint64Flag{
|
|
||||||
Name: "memory-limit",
|
|
||||||
Usage: "memory limit (in bytes) for the container",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
// ObjectWithLabelArgs returns the first arg and a LabelArgs object
|
|
||||||
func ObjectWithLabelArgs(clicontext *cli.Context) (string, map[string]string) {
|
|
||||||
var (
|
|
||||||
first = clicontext.Args().First()
|
|
||||||
labelStrings = clicontext.Args().Tail()
|
|
||||||
)
|
|
||||||
|
|
||||||
return first, LabelArgs(labelStrings)
|
|
||||||
}
|
|
||||||
|
|
||||||
// LabelArgs returns a map of label key,value pairs
|
|
||||||
func LabelArgs(labelStrings []string) map[string]string {
|
|
||||||
labels := make(map[string]string, len(labelStrings))
|
|
||||||
for _, label := range labelStrings {
|
|
||||||
parts := strings.SplitN(label, "=", 2)
|
|
||||||
key := parts[0]
|
|
||||||
value := "true"
|
|
||||||
if len(parts) > 1 {
|
|
||||||
value = parts[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
labels[key] = value
|
|
||||||
}
|
|
||||||
|
|
||||||
return labels
|
|
||||||
}
|
|
||||||
|
|
||||||
// PrintAsJSON prints input in JSON format
|
|
||||||
func PrintAsJSON(x interface{}) {
|
|
||||||
b, err := json.MarshalIndent(x, "", " ")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "can't marshal %+v as a JSON string: %v\n", x, err)
|
|
||||||
}
|
|
||||||
fmt.Println(string(b))
|
|
||||||
}
|
|
||||||
|
|
||||||
// WritePidFile writes the pid atomically to a file
|
|
||||||
func WritePidFile(path string, pid int) error {
|
|
||||||
path, err := filepath.Abs(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
tempPath := filepath.Join(filepath.Dir(path), fmt.Sprintf(".%s", filepath.Base(path)))
|
|
||||||
f, err := os.OpenFile(tempPath, os.O_RDWR|os.O_CREATE|os.O_EXCL|os.O_SYNC, 0666)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = fmt.Fprintf(f, "%d", pid)
|
|
||||||
f.Close()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return os.Rename(tempPath, path)
|
|
||||||
}
|
|
33
vendor/github.com/containerd/containerd/cmd/ctr/commands/commands_unix.go
generated
vendored
33
vendor/github.com/containerd/containerd/cmd/ctr/commands/commands_unix.go
generated
vendored
@ -1,33 +0,0 @@
|
|||||||
// +build !windows
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright The containerd 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 commands
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ContainerFlags = append(ContainerFlags, cli.BoolFlag{
|
|
||||||
Name: "rootfs",
|
|
||||||
Usage: "use custom rootfs that is not managed by containerd snapshotter",
|
|
||||||
}, cli.BoolFlag{
|
|
||||||
Name: "no-pivot",
|
|
||||||
Usage: "disable use of pivot-root (linux only)",
|
|
||||||
})
|
|
||||||
}
|
|
30
vendor/github.com/containerd/containerd/cmd/ctr/commands/commands_windows.go
generated
vendored
30
vendor/github.com/containerd/containerd/cmd/ctr/commands/commands_windows.go
generated
vendored
@ -1,30 +0,0 @@
|
|||||||
// +build windows
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright The containerd 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 commands
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
ContainerFlags = append(ContainerFlags, cli.Uint64Flag{
|
|
||||||
Name: "cpu-count",
|
|
||||||
Usage: "number of CPUs available to the container",
|
|
||||||
})
|
|
||||||
}
|
|
102
vendor/github.com/containerd/containerd/cmd/ctr/commands/containers/checkpoint.go
generated
vendored
102
vendor/github.com/containerd/containerd/cmd/ctr/commands/containers/checkpoint.go
generated
vendored
@ -1,102 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 containers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/errdefs"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var checkpointCommand = cli.Command{
|
|
||||||
Name: "checkpoint",
|
|
||||||
Usage: "checkpoint a container",
|
|
||||||
ArgsUsage: "CONTAINER REF",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "rw",
|
|
||||||
Usage: "include the rw layer in the checkpoint",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "image",
|
|
||||||
Usage: "include the image in the checkpoint",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "task",
|
|
||||||
Usage: "checkpoint container task",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
id := context.Args().First()
|
|
||||||
if id == "" {
|
|
||||||
return errors.New("container id must be provided")
|
|
||||||
}
|
|
||||||
ref := context.Args().Get(1)
|
|
||||||
if ref == "" {
|
|
||||||
return errors.New("ref must be provided")
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
opts := []containerd.CheckpointOpts{
|
|
||||||
containerd.WithCheckpointRuntime,
|
|
||||||
}
|
|
||||||
|
|
||||||
if context.Bool("image") {
|
|
||||||
opts = append(opts, containerd.WithCheckpointImage)
|
|
||||||
}
|
|
||||||
if context.Bool("rw") {
|
|
||||||
opts = append(opts, containerd.WithCheckpointRW)
|
|
||||||
}
|
|
||||||
if context.Bool("task") {
|
|
||||||
opts = append(opts, containerd.WithCheckpointTask)
|
|
||||||
}
|
|
||||||
container, err := client.LoadContainer(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
task, err := container.Task(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
if !errdefs.IsNotFound(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// pause if running
|
|
||||||
if task != nil {
|
|
||||||
if err := task.Pause(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if err := task.Resume(ctx); err != nil {
|
|
||||||
fmt.Println(errors.Wrap(err, "error resuming task"))
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := container.Checkpoint(ctx, ref, opts...); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
286
vendor/github.com/containerd/containerd/cmd/ctr/commands/containers/containers.go
generated
vendored
286
vendor/github.com/containerd/containerd/cmd/ctr/commands/containers/containers.go
generated
vendored
@ -1,286 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 containers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"text/tabwriter"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/cio"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands/run"
|
|
||||||
"github.com/containerd/containerd/containers"
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
"github.com/containerd/typeurl"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Command is the cli command for managing containers
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "containers",
|
|
||||||
Usage: "manage containers",
|
|
||||||
Aliases: []string{"c", "container"},
|
|
||||||
Subcommands: []cli.Command{
|
|
||||||
createCommand,
|
|
||||||
deleteCommand,
|
|
||||||
infoCommand,
|
|
||||||
listCommand,
|
|
||||||
setLabelsCommand,
|
|
||||||
checkpointCommand,
|
|
||||||
restoreCommand,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var createCommand = cli.Command{
|
|
||||||
Name: "create",
|
|
||||||
Usage: "create container",
|
|
||||||
ArgsUsage: "[flags] Image|RootFS CONTAINER [COMMAND] [ARG...]",
|
|
||||||
Flags: append(commands.SnapshotterFlags, commands.ContainerFlags...),
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
id string
|
|
||||||
ref string
|
|
||||||
config = context.IsSet("config")
|
|
||||||
)
|
|
||||||
|
|
||||||
if config {
|
|
||||||
id = context.Args().First()
|
|
||||||
if context.NArg() > 1 {
|
|
||||||
return errors.New("with spec config file, only container id should be provided")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
id = context.Args().Get(1)
|
|
||||||
ref = context.Args().First()
|
|
||||||
if ref == "" {
|
|
||||||
return errors.New("image ref must be provided")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if id == "" {
|
|
||||||
return errors.New("container id must be provided")
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
_, err = run.NewContainer(ctx, client, context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var listCommand = cli.Command{
|
|
||||||
Name: "list",
|
|
||||||
Aliases: []string{"ls"},
|
|
||||||
Usage: "list containers",
|
|
||||||
ArgsUsage: "[flags] [<filter>, ...]",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "quiet, q",
|
|
||||||
Usage: "print only the container id",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
filters = context.Args()
|
|
||||||
quiet = context.Bool("quiet")
|
|
||||||
)
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
containers, err := client.Containers(ctx, filters...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if quiet {
|
|
||||||
for _, c := range containers {
|
|
||||||
fmt.Printf("%s\n", c.ID())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
w := tabwriter.NewWriter(os.Stdout, 4, 8, 4, ' ', 0)
|
|
||||||
fmt.Fprintln(w, "CONTAINER\tIMAGE\tRUNTIME\t")
|
|
||||||
for _, c := range containers {
|
|
||||||
info, err := c.Info(ctx, containerd.WithoutRefreshedMetadata)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
imageName := info.Image
|
|
||||||
if imageName == "" {
|
|
||||||
imageName = "-"
|
|
||||||
}
|
|
||||||
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t\n",
|
|
||||||
c.ID(),
|
|
||||||
imageName,
|
|
||||||
info.Runtime.Name,
|
|
||||||
); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return w.Flush()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var deleteCommand = cli.Command{
|
|
||||||
Name: "delete",
|
|
||||||
Usage: "delete one or more existing containers",
|
|
||||||
ArgsUsage: "[flags] CONTAINER [CONTAINER, ...]",
|
|
||||||
Aliases: []string{"del", "rm"},
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "keep-snapshot",
|
|
||||||
Usage: "do not clean up snapshot with container",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var exitErr error
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
deleteOpts := []containerd.DeleteOpts{}
|
|
||||||
if !context.Bool("keep-snapshot") {
|
|
||||||
deleteOpts = append(deleteOpts, containerd.WithSnapshotCleanup)
|
|
||||||
}
|
|
||||||
|
|
||||||
if context.NArg() == 0 {
|
|
||||||
return errors.New("must specify at least one container to delete")
|
|
||||||
}
|
|
||||||
for _, arg := range context.Args() {
|
|
||||||
if err := deleteContainer(ctx, client, arg, deleteOpts...); err != nil {
|
|
||||||
if exitErr == nil {
|
|
||||||
exitErr = err
|
|
||||||
}
|
|
||||||
log.G(ctx).WithError(err).Errorf("failed to delete container %q", arg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return exitErr
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func deleteContainer(ctx context.Context, client *containerd.Client, id string, opts ...containerd.DeleteOpts) error {
|
|
||||||
container, err := client.LoadContainer(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
task, err := container.Task(ctx, cio.Load)
|
|
||||||
if err != nil {
|
|
||||||
return container.Delete(ctx, opts...)
|
|
||||||
}
|
|
||||||
status, err := task.Status(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if status.Status == containerd.Stopped || status.Status == containerd.Created {
|
|
||||||
if _, err := task.Delete(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return container.Delete(ctx, opts...)
|
|
||||||
}
|
|
||||||
return fmt.Errorf("cannot delete a non stopped container: %v", status)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
var setLabelsCommand = cli.Command{
|
|
||||||
Name: "label",
|
|
||||||
Usage: "set and clear labels for a container",
|
|
||||||
ArgsUsage: "[flags] CONTAINER [<key>=<value>, ...]",
|
|
||||||
Description: "set and clear labels for a container",
|
|
||||||
Flags: []cli.Flag{},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
containerID, labels := commands.ObjectWithLabelArgs(context)
|
|
||||||
if containerID == "" {
|
|
||||||
return errors.New("container id must be provided")
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
container, err := client.LoadContainer(ctx, containerID)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
setlabels, err := container.SetLabels(ctx, labels)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var labelStrings []string
|
|
||||||
for k, v := range setlabels {
|
|
||||||
labelStrings = append(labelStrings, fmt.Sprintf("%s=%s", k, v))
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(strings.Join(labelStrings, ","))
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var infoCommand = cli.Command{
|
|
||||||
Name: "info",
|
|
||||||
Usage: "get info about a container",
|
|
||||||
ArgsUsage: "CONTAINER",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
id := context.Args().First()
|
|
||||||
if id == "" {
|
|
||||||
return errors.New("container id must be provided")
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
container, err := client.LoadContainer(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
info, err := container.Info(ctx, containerd.WithoutRefreshedMetadata)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if info.Spec != nil && info.Spec.Value != nil {
|
|
||||||
v, err := typeurl.UnmarshalAny(info.Spec)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
commands.PrintAsJSON(struct {
|
|
||||||
containers.Container
|
|
||||||
Spec interface{} `json:"Spec,omitempty"`
|
|
||||||
}{
|
|
||||||
Container: info,
|
|
||||||
Spec: v,
|
|
||||||
})
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
commands.PrintAsJSON(info)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
96
vendor/github.com/containerd/containerd/cmd/ctr/commands/containers/restore.go
generated
vendored
96
vendor/github.com/containerd/containerd/cmd/ctr/commands/containers/restore.go
generated
vendored
@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 containers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/cio"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/errdefs"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var restoreCommand = cli.Command{
|
|
||||||
Name: "restore",
|
|
||||||
Usage: "restore a container from checkpoint",
|
|
||||||
ArgsUsage: "CONTAINER REF",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "rw",
|
|
||||||
Usage: "restore the rw layer from the checkpoint",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "live",
|
|
||||||
Usage: "restore the runtime and memory data from the checkpoint",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
id := context.Args().First()
|
|
||||||
if id == "" {
|
|
||||||
return errors.New("container id must be provided")
|
|
||||||
}
|
|
||||||
ref := context.Args().Get(1)
|
|
||||||
if ref == "" {
|
|
||||||
return errors.New("ref must be provided")
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
checkpoint, err := client.GetImage(ctx, ref)
|
|
||||||
if err != nil {
|
|
||||||
if !errdefs.IsNotFound(err) {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// TODO (ehazlett): consider other options (always/never fetch)
|
|
||||||
ck, err := client.Fetch(ctx, ref)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
checkpoint = containerd.NewImage(client, ck)
|
|
||||||
}
|
|
||||||
|
|
||||||
opts := []containerd.RestoreOpts{
|
|
||||||
containerd.WithRestoreImage,
|
|
||||||
containerd.WithRestoreSpec,
|
|
||||||
containerd.WithRestoreRuntime,
|
|
||||||
}
|
|
||||||
if context.Bool("rw") {
|
|
||||||
opts = append(opts, containerd.WithRestoreRW)
|
|
||||||
}
|
|
||||||
|
|
||||||
ctr, err := client.Restore(ctx, id, checkpoint, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
topts := []containerd.NewTaskOpts{}
|
|
||||||
if context.Bool("live") {
|
|
||||||
topts = append(topts, containerd.WithTaskCheckpoint(checkpoint))
|
|
||||||
}
|
|
||||||
|
|
||||||
task, err := ctr.NewTask(ctx, cio.NewCreator(cio.WithStdio), topts...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return task.Start(ctx)
|
|
||||||
},
|
|
||||||
}
|
|
570
vendor/github.com/containerd/containerd/cmd/ctr/commands/content/content.go
generated
vendored
570
vendor/github.com/containerd/containerd/cmd/ctr/commands/content/content.go
generated
vendored
@ -1,570 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 content
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strings"
|
|
||||||
"text/tabwriter"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/content"
|
|
||||||
"github.com/containerd/containerd/errdefs"
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
units "github.com/docker/go-units"
|
|
||||||
digest "github.com/opencontainers/go-digest"
|
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
// Command is the cli command for managing content
|
|
||||||
Command = cli.Command{
|
|
||||||
Name: "content",
|
|
||||||
Usage: "manage content",
|
|
||||||
Subcommands: cli.Commands{
|
|
||||||
activeIngestCommand,
|
|
||||||
deleteCommand,
|
|
||||||
editCommand,
|
|
||||||
fetchCommand,
|
|
||||||
fetchObjectCommand,
|
|
||||||
getCommand,
|
|
||||||
ingestCommand,
|
|
||||||
listCommand,
|
|
||||||
pushObjectCommand,
|
|
||||||
setLabelsCommand,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
getCommand = cli.Command{
|
|
||||||
Name: "get",
|
|
||||||
Usage: "get the data for an object",
|
|
||||||
ArgsUsage: "[<digest>, ...]",
|
|
||||||
Description: "display the image object",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
dgst, err := digest.Parse(context.Args().First())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
cs := client.ContentStore()
|
|
||||||
ra, err := cs.ReaderAt(ctx, ocispec.Descriptor{Digest: dgst})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer ra.Close()
|
|
||||||
|
|
||||||
_, err = io.Copy(os.Stdout, content.NewReader(ra))
|
|
||||||
return err
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
ingestCommand = cli.Command{
|
|
||||||
Name: "ingest",
|
|
||||||
Usage: "accept content into the store",
|
|
||||||
ArgsUsage: "[flags] <key>",
|
|
||||||
Description: "ingest objects into the local content store",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.Int64Flag{
|
|
||||||
Name: "expected-size",
|
|
||||||
Usage: "validate against provided size",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "expected-digest",
|
|
||||||
Usage: "verify content against expected digest",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
ref = context.Args().First()
|
|
||||||
expectedSize = context.Int64("expected-size")
|
|
||||||
expectedDigest = digest.Digest(context.String("expected-digest"))
|
|
||||||
)
|
|
||||||
if err := expectedDigest.Validate(); expectedDigest != "" && err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if ref == "" {
|
|
||||||
return errors.New("must specify a transaction reference")
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
cs := client.ContentStore()
|
|
||||||
|
|
||||||
// TODO(stevvooe): Allow ingest to be reentrant. Currently, we expect
|
|
||||||
// all data to be written in a single invocation. Allow multiple writes
|
|
||||||
// to the same transaction key followed by a commit.
|
|
||||||
return content.WriteBlob(ctx, cs, ref, os.Stdin, ocispec.Descriptor{Size: expectedSize, Digest: expectedDigest})
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
activeIngestCommand = cli.Command{
|
|
||||||
Name: "active",
|
|
||||||
Usage: "display active transfers",
|
|
||||||
ArgsUsage: "[flags] [<regexp>]",
|
|
||||||
Description: "display the ongoing transfers",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.DurationFlag{
|
|
||||||
Name: "timeout, t",
|
|
||||||
Usage: "total timeout for fetch",
|
|
||||||
EnvVar: "CONTAINERD_FETCH_TIMEOUT",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "root",
|
|
||||||
Usage: "path to content store root",
|
|
||||||
Value: "/tmp/content", // TODO(stevvooe): for now, just use the PWD/.content
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
match := context.Args().First()
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
cs := client.ContentStore()
|
|
||||||
active, err := cs.ListStatuses(ctx, match)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
tw := tabwriter.NewWriter(os.Stdout, 1, 8, 1, '\t', 0)
|
|
||||||
fmt.Fprintln(tw, "REF\tSIZE\tAGE\t")
|
|
||||||
for _, active := range active {
|
|
||||||
fmt.Fprintf(tw, "%s\t%s\t%s\t\n",
|
|
||||||
active.Ref,
|
|
||||||
units.HumanSize(float64(active.Offset)),
|
|
||||||
units.HumanDuration(time.Since(active.StartedAt)))
|
|
||||||
}
|
|
||||||
|
|
||||||
return tw.Flush()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
listCommand = cli.Command{
|
|
||||||
Name: "list",
|
|
||||||
Aliases: []string{"ls"},
|
|
||||||
Usage: "list all blobs in the store",
|
|
||||||
ArgsUsage: "[flags]",
|
|
||||||
Description: "list blobs in the content store",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "quiet, q",
|
|
||||||
Usage: "print only the blob digest",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
quiet = context.Bool("quiet")
|
|
||||||
args = []string(context.Args())
|
|
||||||
)
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
cs := client.ContentStore()
|
|
||||||
|
|
||||||
var walkFn content.WalkFunc
|
|
||||||
if quiet {
|
|
||||||
walkFn = func(info content.Info) error {
|
|
||||||
fmt.Println(info.Digest)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tw := tabwriter.NewWriter(os.Stdout, 1, 8, 1, '\t', 0)
|
|
||||||
defer tw.Flush()
|
|
||||||
|
|
||||||
fmt.Fprintln(tw, "DIGEST\tSIZE\tAGE\tLABELS")
|
|
||||||
walkFn = func(info content.Info) error {
|
|
||||||
var labelStrings []string
|
|
||||||
for k, v := range info.Labels {
|
|
||||||
labelStrings = append(labelStrings, strings.Join([]string{k, v}, "="))
|
|
||||||
}
|
|
||||||
labels := strings.Join(labelStrings, ",")
|
|
||||||
if labels == "" {
|
|
||||||
labels = "-"
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n",
|
|
||||||
info.Digest,
|
|
||||||
units.HumanSize(float64(info.Size)),
|
|
||||||
units.HumanDuration(time.Since(info.CreatedAt)),
|
|
||||||
labels)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return cs.Walk(ctx, walkFn, args...)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
setLabelsCommand = cli.Command{
|
|
||||||
Name: "label",
|
|
||||||
Usage: "add labels to content",
|
|
||||||
ArgsUsage: "<digest> [<label>=<value> ...]",
|
|
||||||
Description: "labels blobs in the content store",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
object, labels := commands.ObjectWithLabelArgs(context)
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
cs := client.ContentStore()
|
|
||||||
|
|
||||||
dgst, err := digest.Parse(object)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
info := content.Info{
|
|
||||||
Digest: dgst,
|
|
||||||
Labels: map[string]string{},
|
|
||||||
}
|
|
||||||
|
|
||||||
var paths []string
|
|
||||||
for k, v := range labels {
|
|
||||||
paths = append(paths, fmt.Sprintf("labels.%s", k))
|
|
||||||
if v != "" {
|
|
||||||
info.Labels[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nothing updated, do no clear
|
|
||||||
if len(paths) == 0 {
|
|
||||||
info, err = cs.Info(ctx, info.Digest)
|
|
||||||
} else {
|
|
||||||
info, err = cs.Update(ctx, info, paths...)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var labelStrings []string
|
|
||||||
for k, v := range info.Labels {
|
|
||||||
labelStrings = append(labelStrings, fmt.Sprintf("%s=%s", k, v))
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(strings.Join(labelStrings, ","))
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
editCommand = cli.Command{
|
|
||||||
Name: "edit",
|
|
||||||
Usage: "edit a blob and return a new digest",
|
|
||||||
ArgsUsage: "[flags] <digest>",
|
|
||||||
Description: "edit a blob and return a new digest",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "validate",
|
|
||||||
Usage: "validate the result against a format (json, mediatype, etc.)",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "editor",
|
|
||||||
Usage: "select editor (vim, emacs, etc.)",
|
|
||||||
EnvVar: "EDITOR",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
validate = context.String("validate")
|
|
||||||
object = context.Args().First()
|
|
||||||
)
|
|
||||||
|
|
||||||
if validate != "" {
|
|
||||||
return errors.New("validating the edit result not supported")
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(stevvooe): Support looking up objects by a reference through
|
|
||||||
// the image metadata storage.
|
|
||||||
|
|
||||||
dgst, err := digest.Parse(object)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
cs := client.ContentStore()
|
|
||||||
ra, err := cs.ReaderAt(ctx, ocispec.Descriptor{Digest: dgst})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer ra.Close()
|
|
||||||
|
|
||||||
nrc, err := edit(context, content.NewReader(ra))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer nrc.Close()
|
|
||||||
|
|
||||||
wr, err := cs.Writer(ctx, content.WithRef("edit-"+object)) // TODO(stevvooe): Choose a better key?
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := io.Copy(wr, nrc); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := wr.Commit(ctx, 0, wr.Digest()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(wr.Digest())
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteCommand = cli.Command{
|
|
||||||
Name: "delete",
|
|
||||||
Aliases: []string{"del", "remove", "rm"},
|
|
||||||
Usage: "permanently delete one or more blobs",
|
|
||||||
ArgsUsage: "[<digest>, ...]",
|
|
||||||
Description: `Delete one or more blobs permanently. Successfully deleted
|
|
||||||
blobs are printed to stdout.`,
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
args = []string(context.Args())
|
|
||||||
exitError error
|
|
||||||
)
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
cs := client.ContentStore()
|
|
||||||
|
|
||||||
for _, arg := range args {
|
|
||||||
dgst, err := digest.Parse(arg)
|
|
||||||
if err != nil {
|
|
||||||
if exitError == nil {
|
|
||||||
exitError = err
|
|
||||||
}
|
|
||||||
log.G(ctx).WithError(err).Errorf("could not delete %v", dgst)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := cs.Delete(ctx, dgst); err != nil {
|
|
||||||
if !errdefs.IsNotFound(err) {
|
|
||||||
if exitError == nil {
|
|
||||||
exitError = err
|
|
||||||
}
|
|
||||||
log.G(ctx).WithError(err).Errorf("could not delete %v", dgst)
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(dgst)
|
|
||||||
}
|
|
||||||
|
|
||||||
return exitError
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(stevvooe): Create "multi-fetch" mode that just takes a remote
|
|
||||||
// then receives object/hint lines on stdin, returning content as
|
|
||||||
// needed.
|
|
||||||
fetchObjectCommand = cli.Command{
|
|
||||||
Name: "fetch-object",
|
|
||||||
Usage: "retrieve objects from a remote",
|
|
||||||
ArgsUsage: "[flags] <remote> <object> [<hint>, ...]",
|
|
||||||
Description: `Fetch objects by identifier from a remote.`,
|
|
||||||
Flags: commands.RegistryFlags,
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
ref = context.Args().First()
|
|
||||||
)
|
|
||||||
ctx, cancel := commands.AppContext(context)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
resolver, err := commands.GetResolver(ctx, context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = log.WithLogger(ctx, log.G(ctx).WithField("ref", ref))
|
|
||||||
|
|
||||||
log.G(ctx).Debugf("resolving")
|
|
||||||
name, desc, err := resolver.Resolve(ctx, ref)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fetcher, err := resolver.Fetcher(ctx, name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.G(ctx).Debugf("fetching")
|
|
||||||
rc, err := fetcher.Fetch(ctx, desc)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer rc.Close()
|
|
||||||
|
|
||||||
_, err = io.Copy(os.Stdout, rc)
|
|
||||||
return err
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
pushObjectCommand = cli.Command{
|
|
||||||
Name: "push-object",
|
|
||||||
Usage: "push an object to a remote",
|
|
||||||
ArgsUsage: "[flags] <remote> <object> <type>",
|
|
||||||
Description: `Push objects by identifier to a remote.`,
|
|
||||||
Flags: commands.RegistryFlags,
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
ref = context.Args().Get(0)
|
|
||||||
object = context.Args().Get(1)
|
|
||||||
media = context.Args().Get(2)
|
|
||||||
)
|
|
||||||
dgst, err := digest.Parse(object)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
resolver, err := commands.GetResolver(ctx, context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx = log.WithLogger(ctx, log.G(ctx).WithField("ref", ref))
|
|
||||||
|
|
||||||
log.G(ctx).Debugf("resolving")
|
|
||||||
pusher, err := resolver.Pusher(ctx, ref)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
cs := client.ContentStore()
|
|
||||||
|
|
||||||
info, err := cs.Info(ctx, dgst)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
desc := ocispec.Descriptor{
|
|
||||||
MediaType: media,
|
|
||||||
Digest: dgst,
|
|
||||||
Size: info.Size,
|
|
||||||
}
|
|
||||||
|
|
||||||
ra, err := cs.ReaderAt(ctx, desc)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer ra.Close()
|
|
||||||
|
|
||||||
cw, err := pusher.Push(ctx, desc)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Progress reader
|
|
||||||
if err := content.Copy(ctx, cw, content.NewReader(ra), desc.Size, desc.Digest); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Pushed %s %s\n", desc.Digest, desc.MediaType)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func edit(context *cli.Context, rd io.Reader) (io.ReadCloser, error) {
|
|
||||||
editor := context.String("editor")
|
|
||||||
if editor == "" {
|
|
||||||
return nil, fmt.Errorf("editor is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp, err := ioutil.TempFile(os.Getenv("XDG_RUNTIME_DIR"), "edit-")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := io.Copy(tmp, rd); err != nil {
|
|
||||||
tmp.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd := exec.Command("sh", "-c", fmt.Sprintf("%s %s", editor, tmp.Name()))
|
|
||||||
|
|
||||||
cmd.Stdin = os.Stdin
|
|
||||||
cmd.Stdout = os.Stdout
|
|
||||||
cmd.Stderr = os.Stderr
|
|
||||||
cmd.Env = os.Environ()
|
|
||||||
|
|
||||||
if err := cmd.Run(); err != nil {
|
|
||||||
tmp.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, err := tmp.Seek(0, io.SeekStart); err != nil {
|
|
||||||
tmp.Close()
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return onCloser{ReadCloser: tmp, onClose: func() error {
|
|
||||||
return os.RemoveAll(tmp.Name())
|
|
||||||
}}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type onCloser struct {
|
|
||||||
io.ReadCloser
|
|
||||||
onClose func() error
|
|
||||||
}
|
|
||||||
|
|
||||||
func (oc onCloser) Close() error {
|
|
||||||
var err error
|
|
||||||
if err1 := oc.ReadCloser.Close(); err1 != nil {
|
|
||||||
err = err1
|
|
||||||
}
|
|
||||||
|
|
||||||
if oc.onClose != nil {
|
|
||||||
err1 := oc.onClose()
|
|
||||||
if err == nil {
|
|
||||||
err = err1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
382
vendor/github.com/containerd/containerd/cmd/ctr/commands/content/fetch.go
generated
vendored
382
vendor/github.com/containerd/containerd/cmd/ctr/commands/content/fetch.go
generated
vendored
@ -1,382 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 content
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"sync"
|
|
||||||
"text/tabwriter"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/content"
|
|
||||||
"github.com/containerd/containerd/errdefs"
|
|
||||||
"github.com/containerd/containerd/images"
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
"github.com/containerd/containerd/pkg/progress"
|
|
||||||
"github.com/containerd/containerd/platforms"
|
|
||||||
"github.com/containerd/containerd/remotes"
|
|
||||||
digest "github.com/opencontainers/go-digest"
|
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var fetchCommand = cli.Command{
|
|
||||||
Name: "fetch",
|
|
||||||
Usage: "fetch all content for an image into containerd",
|
|
||||||
ArgsUsage: "[flags] <remote> <object>",
|
|
||||||
Description: `Fetch an image into containerd.
|
|
||||||
|
|
||||||
This command ensures that containerd has all the necessary resources to build
|
|
||||||
an image's rootfs and convert the configuration to a runtime format supported
|
|
||||||
by containerd.
|
|
||||||
|
|
||||||
This command uses the same syntax, of remote and object, as 'ctr fetch-object'.
|
|
||||||
We may want to make this nicer, but agnostism is preferred for the moment.
|
|
||||||
|
|
||||||
Right now, the responsibility of the daemon and the cli aren't quite clear. Do
|
|
||||||
not use this implementation as a guide. The end goal should be having metadata,
|
|
||||||
content and snapshots ready for a direct use via the 'ctr run'.
|
|
||||||
|
|
||||||
Most of this is experimental and there are few leaps to make this work.`,
|
|
||||||
Flags: append(commands.RegistryFlags, commands.LabelFlag,
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "platform",
|
|
||||||
Usage: "Pull content from a specific platform",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "all-platforms",
|
|
||||||
Usage: "pull content from all platforms",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Action: func(clicontext *cli.Context) error {
|
|
||||||
var (
|
|
||||||
ref = clicontext.Args().First()
|
|
||||||
)
|
|
||||||
client, ctx, cancel, err := commands.NewClient(clicontext)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
config, err := NewFetchConfig(ctx, clicontext)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = Fetch(ctx, client, ref, config)
|
|
||||||
return err
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// FetchConfig for content fetch
|
|
||||||
type FetchConfig struct {
|
|
||||||
// Resolver
|
|
||||||
Resolver remotes.Resolver
|
|
||||||
// ProgressOutput to display progress
|
|
||||||
ProgressOutput io.Writer
|
|
||||||
// Labels to set on the content
|
|
||||||
Labels []string
|
|
||||||
// Platforms to fetch
|
|
||||||
Platforms []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewFetchConfig returns the default FetchConfig from cli flags
|
|
||||||
func NewFetchConfig(ctx context.Context, clicontext *cli.Context) (*FetchConfig, error) {
|
|
||||||
resolver, err := commands.GetResolver(ctx, clicontext)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
config := &FetchConfig{
|
|
||||||
Resolver: resolver,
|
|
||||||
Labels: clicontext.StringSlice("label"),
|
|
||||||
}
|
|
||||||
if !clicontext.GlobalBool("debug") {
|
|
||||||
config.ProgressOutput = os.Stdout
|
|
||||||
}
|
|
||||||
if !clicontext.Bool("all-platforms") {
|
|
||||||
p := clicontext.StringSlice("platform")
|
|
||||||
if len(p) == 0 {
|
|
||||||
p = append(p, platforms.DefaultString())
|
|
||||||
}
|
|
||||||
config.Platforms = p
|
|
||||||
}
|
|
||||||
return config, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fetch loads all resources into the content store and returns the image
|
|
||||||
func Fetch(ctx context.Context, client *containerd.Client, ref string, config *FetchConfig) (images.Image, error) {
|
|
||||||
ongoing := newJobs(ref)
|
|
||||||
|
|
||||||
pctx, stopProgress := context.WithCancel(ctx)
|
|
||||||
progress := make(chan struct{})
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
if config.ProgressOutput != nil {
|
|
||||||
// no progress bar, because it hides some debug logs
|
|
||||||
showProgress(pctx, ongoing, client.ContentStore(), config.ProgressOutput)
|
|
||||||
}
|
|
||||||
close(progress)
|
|
||||||
}()
|
|
||||||
|
|
||||||
h := images.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
|
|
||||||
if desc.MediaType != images.MediaTypeDockerSchema1Manifest {
|
|
||||||
ongoing.add(desc)
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
})
|
|
||||||
|
|
||||||
log.G(pctx).WithField("image", ref).Debug("fetching")
|
|
||||||
labels := commands.LabelArgs(config.Labels)
|
|
||||||
opts := []containerd.RemoteOpt{
|
|
||||||
containerd.WithPullLabels(labels),
|
|
||||||
containerd.WithResolver(config.Resolver),
|
|
||||||
containerd.WithImageHandler(h),
|
|
||||||
containerd.WithSchema1Conversion,
|
|
||||||
containerd.WithAppendDistributionSourceLabel(),
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, platform := range config.Platforms {
|
|
||||||
opts = append(opts, containerd.WithPlatform(platform))
|
|
||||||
}
|
|
||||||
|
|
||||||
img, err := client.Fetch(pctx, ref, opts...)
|
|
||||||
stopProgress()
|
|
||||||
if err != nil {
|
|
||||||
return images.Image{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
<-progress
|
|
||||||
return img, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func showProgress(ctx context.Context, ongoing *jobs, cs content.Store, out io.Writer) {
|
|
||||||
var (
|
|
||||||
ticker = time.NewTicker(100 * time.Millisecond)
|
|
||||||
fw = progress.NewWriter(out)
|
|
||||||
start = time.Now()
|
|
||||||
statuses = map[string]StatusInfo{}
|
|
||||||
done bool
|
|
||||||
)
|
|
||||||
defer ticker.Stop()
|
|
||||||
|
|
||||||
outer:
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ticker.C:
|
|
||||||
fw.Flush()
|
|
||||||
|
|
||||||
tw := tabwriter.NewWriter(fw, 1, 8, 1, ' ', 0)
|
|
||||||
|
|
||||||
resolved := "resolved"
|
|
||||||
if !ongoing.isResolved() {
|
|
||||||
resolved = "resolving"
|
|
||||||
}
|
|
||||||
statuses[ongoing.name] = StatusInfo{
|
|
||||||
Ref: ongoing.name,
|
|
||||||
Status: resolved,
|
|
||||||
}
|
|
||||||
keys := []string{ongoing.name}
|
|
||||||
|
|
||||||
activeSeen := map[string]struct{}{}
|
|
||||||
if !done {
|
|
||||||
active, err := cs.ListStatuses(ctx, "")
|
|
||||||
if err != nil {
|
|
||||||
log.G(ctx).WithError(err).Error("active check failed")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// update status of active entries!
|
|
||||||
for _, active := range active {
|
|
||||||
statuses[active.Ref] = StatusInfo{
|
|
||||||
Ref: active.Ref,
|
|
||||||
Status: "downloading",
|
|
||||||
Offset: active.Offset,
|
|
||||||
Total: active.Total,
|
|
||||||
StartedAt: active.StartedAt,
|
|
||||||
UpdatedAt: active.UpdatedAt,
|
|
||||||
}
|
|
||||||
activeSeen[active.Ref] = struct{}{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// now, update the items in jobs that are not in active
|
|
||||||
for _, j := range ongoing.jobs() {
|
|
||||||
key := remotes.MakeRefKey(ctx, j)
|
|
||||||
keys = append(keys, key)
|
|
||||||
if _, ok := activeSeen[key]; ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
status, ok := statuses[key]
|
|
||||||
if !done && (!ok || status.Status == "downloading") {
|
|
||||||
info, err := cs.Info(ctx, j.Digest)
|
|
||||||
if err != nil {
|
|
||||||
if !errdefs.IsNotFound(err) {
|
|
||||||
log.G(ctx).WithError(err).Errorf("failed to get content info")
|
|
||||||
continue outer
|
|
||||||
} else {
|
|
||||||
statuses[key] = StatusInfo{
|
|
||||||
Ref: key,
|
|
||||||
Status: "waiting",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if info.CreatedAt.After(start) {
|
|
||||||
statuses[key] = StatusInfo{
|
|
||||||
Ref: key,
|
|
||||||
Status: "done",
|
|
||||||
Offset: info.Size,
|
|
||||||
Total: info.Size,
|
|
||||||
UpdatedAt: info.CreatedAt,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
statuses[key] = StatusInfo{
|
|
||||||
Ref: key,
|
|
||||||
Status: "exists",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if done {
|
|
||||||
if ok {
|
|
||||||
if status.Status != "done" && status.Status != "exists" {
|
|
||||||
status.Status = "done"
|
|
||||||
statuses[key] = status
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
statuses[key] = StatusInfo{
|
|
||||||
Ref: key,
|
|
||||||
Status: "done",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var ordered []StatusInfo
|
|
||||||
for _, key := range keys {
|
|
||||||
ordered = append(ordered, statuses[key])
|
|
||||||
}
|
|
||||||
|
|
||||||
Display(tw, ordered, start)
|
|
||||||
tw.Flush()
|
|
||||||
|
|
||||||
if done {
|
|
||||||
fw.Flush()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case <-ctx.Done():
|
|
||||||
done = true // allow ui to update once more
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// jobs provides a way of identifying the download keys for a particular task
|
|
||||||
// encountering during the pull walk.
|
|
||||||
//
|
|
||||||
// This is very minimal and will probably be replaced with something more
|
|
||||||
// featured.
|
|
||||||
type jobs struct {
|
|
||||||
name string
|
|
||||||
added map[digest.Digest]struct{}
|
|
||||||
descs []ocispec.Descriptor
|
|
||||||
mu sync.Mutex
|
|
||||||
resolved bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func newJobs(name string) *jobs {
|
|
||||||
return &jobs{
|
|
||||||
name: name,
|
|
||||||
added: map[digest.Digest]struct{}{},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j *jobs) add(desc ocispec.Descriptor) {
|
|
||||||
j.mu.Lock()
|
|
||||||
defer j.mu.Unlock()
|
|
||||||
j.resolved = true
|
|
||||||
|
|
||||||
if _, ok := j.added[desc.Digest]; ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
j.descs = append(j.descs, desc)
|
|
||||||
j.added[desc.Digest] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j *jobs) jobs() []ocispec.Descriptor {
|
|
||||||
j.mu.Lock()
|
|
||||||
defer j.mu.Unlock()
|
|
||||||
|
|
||||||
var descs []ocispec.Descriptor
|
|
||||||
return append(descs, j.descs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j *jobs) isResolved() bool {
|
|
||||||
j.mu.Lock()
|
|
||||||
defer j.mu.Unlock()
|
|
||||||
return j.resolved
|
|
||||||
}
|
|
||||||
|
|
||||||
// StatusInfo holds the status info for an upload or download
|
|
||||||
type StatusInfo struct {
|
|
||||||
Ref string
|
|
||||||
Status string
|
|
||||||
Offset int64
|
|
||||||
Total int64
|
|
||||||
StartedAt time.Time
|
|
||||||
UpdatedAt time.Time
|
|
||||||
}
|
|
||||||
|
|
||||||
// Display pretty prints out the download or upload progress
|
|
||||||
func Display(w io.Writer, statuses []StatusInfo, start time.Time) {
|
|
||||||
var total int64
|
|
||||||
for _, status := range statuses {
|
|
||||||
total += status.Offset
|
|
||||||
switch status.Status {
|
|
||||||
case "downloading", "uploading":
|
|
||||||
var bar progress.Bar
|
|
||||||
if status.Total > 0.0 {
|
|
||||||
bar = progress.Bar(float64(status.Offset) / float64(status.Total))
|
|
||||||
}
|
|
||||||
fmt.Fprintf(w, "%s:\t%s\t%40r\t%8.8s/%s\t\n",
|
|
||||||
status.Ref,
|
|
||||||
status.Status,
|
|
||||||
bar,
|
|
||||||
progress.Bytes(status.Offset), progress.Bytes(status.Total))
|
|
||||||
case "resolving", "waiting":
|
|
||||||
bar := progress.Bar(0.0)
|
|
||||||
fmt.Fprintf(w, "%s:\t%s\t%40r\t\n",
|
|
||||||
status.Ref,
|
|
||||||
status.Status,
|
|
||||||
bar)
|
|
||||||
default:
|
|
||||||
bar := progress.Bar(1.0)
|
|
||||||
fmt.Fprintf(w, "%s:\t%s\t%40r\t\n",
|
|
||||||
status.Ref,
|
|
||||||
status.Status,
|
|
||||||
bar)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(w, "elapsed: %-4.1fs\ttotal: %7.6v\t(%v)\t\n",
|
|
||||||
time.Since(start).Seconds(),
|
|
||||||
// TODO(stevvooe): These calculations are actually way off.
|
|
||||||
// Need to account for previously downloaded data. These
|
|
||||||
// will basically be right for a download the first time
|
|
||||||
// but will be skewed if restarting, as it includes the
|
|
||||||
// data into the start time before.
|
|
||||||
progress.Bytes(total),
|
|
||||||
progress.NewBytesPerSecond(total, time.Since(start)))
|
|
||||||
}
|
|
77
vendor/github.com/containerd/containerd/cmd/ctr/commands/events/events.go
generated
vendored
77
vendor/github.com/containerd/containerd/cmd/ctr/commands/events/events.go
generated
vendored
@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 events
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/events"
|
|
||||||
"github.com/containerd/typeurl"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
|
|
||||||
// Register grpc event types
|
|
||||||
_ "github.com/containerd/containerd/api/events"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Command is the cli command for displaying containerd events
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "events",
|
|
||||||
Aliases: []string{"event"},
|
|
||||||
Usage: "display containerd events",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
eventsClient := client.EventService()
|
|
||||||
eventsCh, errCh := eventsClient.Subscribe(ctx, context.Args()...)
|
|
||||||
open := true
|
|
||||||
for open {
|
|
||||||
var e *events.Envelope
|
|
||||||
select {
|
|
||||||
case e = <-eventsCh:
|
|
||||||
case err, open = <-errCh:
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if e != nil {
|
|
||||||
var out []byte
|
|
||||||
if e.Event != nil {
|
|
||||||
v, err := typeurl.UnmarshalAny(e.Event)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
out, err = json.Marshal(v)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if _, err := fmt.Println(
|
|
||||||
e.Timestamp,
|
|
||||||
e.Namespace,
|
|
||||||
e.Topic,
|
|
||||||
string(out),
|
|
||||||
); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
113
vendor/github.com/containerd/containerd/cmd/ctr/commands/images/export.go
generated
vendored
113
vendor/github.com/containerd/containerd/cmd/ctr/commands/images/export.go
generated
vendored
@ -1,113 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 images
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/images/archive"
|
|
||||||
"github.com/containerd/containerd/platforms"
|
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var exportCommand = cli.Command{
|
|
||||||
Name: "export",
|
|
||||||
Usage: "export images",
|
|
||||||
ArgsUsage: "[flags] <out> <image> ...",
|
|
||||||
Description: `Export images to an OCI tar archive.
|
|
||||||
|
|
||||||
Tar output is formatted as an OCI archive, a Docker manifest is provided for the platform.
|
|
||||||
Use '--skip-manifest-json' to avoid including the Docker manifest.json file.
|
|
||||||
Use '--platform' to define the output platform.
|
|
||||||
When '--all-platforms' is given all images in a manifest list must be available.
|
|
||||||
`,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "skip-manifest-json",
|
|
||||||
Usage: "do not add Docker compatible manifest.json to archive",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "platform",
|
|
||||||
Usage: "Pull content from a specific platform",
|
|
||||||
Value: &cli.StringSlice{},
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "all-platforms",
|
|
||||||
Usage: "exports content from all platforms",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
out = context.Args().First()
|
|
||||||
images = context.Args().Tail()
|
|
||||||
exportOpts = []archive.ExportOpt{}
|
|
||||||
)
|
|
||||||
if out == "" || len(images) == 0 {
|
|
||||||
return errors.New("please provide both an output filename and an image reference to export")
|
|
||||||
}
|
|
||||||
|
|
||||||
if pss := context.StringSlice("platform"); len(pss) > 0 {
|
|
||||||
var all []ocispec.Platform
|
|
||||||
for _, ps := range pss {
|
|
||||||
p, err := platforms.Parse(ps)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "invalid platform %q", ps)
|
|
||||||
}
|
|
||||||
all = append(all, p)
|
|
||||||
}
|
|
||||||
exportOpts = append(exportOpts, archive.WithPlatform(platforms.Ordered(all...)))
|
|
||||||
} else {
|
|
||||||
exportOpts = append(exportOpts, archive.WithPlatform(platforms.Default()))
|
|
||||||
}
|
|
||||||
|
|
||||||
if context.Bool("all-platforms") {
|
|
||||||
exportOpts = append(exportOpts, archive.WithAllPlatforms())
|
|
||||||
}
|
|
||||||
|
|
||||||
if context.Bool("skip-manifest-json") {
|
|
||||||
exportOpts = append(exportOpts, archive.WithSkipDockerManifest())
|
|
||||||
}
|
|
||||||
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
is := client.ImageService()
|
|
||||||
for _, img := range images {
|
|
||||||
exportOpts = append(exportOpts, archive.WithImage(is, img))
|
|
||||||
}
|
|
||||||
|
|
||||||
var w io.WriteCloser
|
|
||||||
if out == "-" {
|
|
||||||
w = os.Stdout
|
|
||||||
} else {
|
|
||||||
w, err = os.Create(out)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer w.Close()
|
|
||||||
|
|
||||||
return client.Export(ctx, w, exportOpts...)
|
|
||||||
},
|
|
||||||
}
|
|
330
vendor/github.com/containerd/containerd/cmd/ctr/commands/images/images.go
generated
vendored
330
vendor/github.com/containerd/containerd/cmd/ctr/commands/images/images.go
generated
vendored
@ -1,330 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 images
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
"text/tabwriter"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/errdefs"
|
|
||||||
"github.com/containerd/containerd/images"
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
"github.com/containerd/containerd/pkg/progress"
|
|
||||||
"github.com/containerd/containerd/platforms"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Command is the cli command for managing images
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "images",
|
|
||||||
Aliases: []string{"image", "i"},
|
|
||||||
Usage: "manage images",
|
|
||||||
Subcommands: cli.Commands{
|
|
||||||
checkCommand,
|
|
||||||
exportCommand,
|
|
||||||
importCommand,
|
|
||||||
listCommand,
|
|
||||||
pullCommand,
|
|
||||||
pushCommand,
|
|
||||||
removeCommand,
|
|
||||||
setLabelsCommand,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var listCommand = cli.Command{
|
|
||||||
Name: "list",
|
|
||||||
Aliases: []string{"ls"},
|
|
||||||
Usage: "list images known to containerd",
|
|
||||||
ArgsUsage: "[flags] [<filter>, ...]",
|
|
||||||
Description: "list images registered with containerd",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "quiet, q",
|
|
||||||
Usage: "print only the image refs",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
filters = context.Args()
|
|
||||||
quiet = context.Bool("quiet")
|
|
||||||
)
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
var (
|
|
||||||
imageStore = client.ImageService()
|
|
||||||
cs = client.ContentStore()
|
|
||||||
)
|
|
||||||
imageList, err := imageStore.List(ctx, filters...)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "failed to list images")
|
|
||||||
}
|
|
||||||
if quiet {
|
|
||||||
for _, image := range imageList {
|
|
||||||
fmt.Println(image.Name)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
tw := tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0)
|
|
||||||
fmt.Fprintln(tw, "REF\tTYPE\tDIGEST\tSIZE\tPLATFORMS\tLABELS\t")
|
|
||||||
for _, image := range imageList {
|
|
||||||
size, err := image.Size(ctx, cs, platforms.Default())
|
|
||||||
if err != nil {
|
|
||||||
log.G(ctx).WithError(err).Errorf("failed calculating size for image %s", image.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
platformColumn := "-"
|
|
||||||
specs, err := images.Platforms(ctx, cs, image.Target)
|
|
||||||
if err != nil {
|
|
||||||
log.G(ctx).WithError(err).Errorf("failed resolving platform for image %s", image.Name)
|
|
||||||
} else if len(specs) > 0 {
|
|
||||||
psm := map[string]struct{}{}
|
|
||||||
for _, p := range specs {
|
|
||||||
psm[platforms.Format(p)] = struct{}{}
|
|
||||||
}
|
|
||||||
var ps []string
|
|
||||||
for p := range psm {
|
|
||||||
ps = append(ps, p)
|
|
||||||
}
|
|
||||||
sort.Stable(sort.StringSlice(ps))
|
|
||||||
platformColumn = strings.Join(ps, ",")
|
|
||||||
}
|
|
||||||
|
|
||||||
labels := "-"
|
|
||||||
if len(image.Labels) > 0 {
|
|
||||||
var pairs []string
|
|
||||||
for k, v := range image.Labels {
|
|
||||||
pairs = append(pairs, fmt.Sprintf("%v=%v", k, v))
|
|
||||||
}
|
|
||||||
sort.Strings(pairs)
|
|
||||||
labels = strings.Join(pairs, ",")
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(tw, "%v\t%v\t%v\t%v\t%v\t%s\t\n",
|
|
||||||
image.Name,
|
|
||||||
image.Target.MediaType,
|
|
||||||
image.Target.Digest,
|
|
||||||
progress.Bytes(size),
|
|
||||||
platformColumn,
|
|
||||||
labels)
|
|
||||||
}
|
|
||||||
|
|
||||||
return tw.Flush()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var setLabelsCommand = cli.Command{
|
|
||||||
Name: "label",
|
|
||||||
Usage: "set and clear labels for an image",
|
|
||||||
ArgsUsage: "[flags] <name> [<key>=<value>, ...]",
|
|
||||||
Description: "set and clear labels for an image",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "replace-all, r",
|
|
||||||
Usage: "replace all labels",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
replaceAll = context.Bool("replace-all")
|
|
||||||
name, labels = commands.ObjectWithLabelArgs(context)
|
|
||||||
)
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
if name == "" {
|
|
||||||
return errors.New("please specify an image")
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
is = client.ImageService()
|
|
||||||
fieldpaths []string
|
|
||||||
)
|
|
||||||
|
|
||||||
for k := range labels {
|
|
||||||
if replaceAll {
|
|
||||||
fieldpaths = append(fieldpaths, "labels")
|
|
||||||
} else {
|
|
||||||
fieldpaths = append(fieldpaths, strings.Join([]string{"labels", k}, "."))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
image := images.Image{
|
|
||||||
Name: name,
|
|
||||||
Labels: labels,
|
|
||||||
}
|
|
||||||
|
|
||||||
updated, err := is.Update(ctx, image, fieldpaths...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var labelStrings []string
|
|
||||||
for k, v := range updated.Labels {
|
|
||||||
labelStrings = append(labelStrings, fmt.Sprintf("%s=%s", k, v))
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(strings.Join(labelStrings, ","))
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var checkCommand = cli.Command{
|
|
||||||
Name: "check",
|
|
||||||
Usage: "check that an image has all content available locally",
|
|
||||||
ArgsUsage: "[flags] [<filter>, ...]",
|
|
||||||
Description: "check that an image has all content available locally",
|
|
||||||
Flags: commands.SnapshotterFlags,
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
exitErr error
|
|
||||||
)
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
var (
|
|
||||||
contentStore = client.ContentStore()
|
|
||||||
tw = tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0)
|
|
||||||
)
|
|
||||||
fmt.Fprintln(tw, "REF\tTYPE\tDIGEST\tSTATUS\tSIZE\tUNPACKED\t")
|
|
||||||
|
|
||||||
args := []string(context.Args())
|
|
||||||
imageList, err := client.ListImages(ctx, args...)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "failed listing images")
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, image := range imageList {
|
|
||||||
var (
|
|
||||||
status string = "complete"
|
|
||||||
size string
|
|
||||||
requiredSize int64
|
|
||||||
presentSize int64
|
|
||||||
)
|
|
||||||
|
|
||||||
available, required, present, missing, err := images.Check(ctx, contentStore, image.Target(), platforms.Default())
|
|
||||||
if err != nil {
|
|
||||||
if exitErr == nil {
|
|
||||||
exitErr = errors.Wrapf(err, "unable to check %v", image.Name())
|
|
||||||
}
|
|
||||||
log.G(ctx).WithError(err).Errorf("unable to check %v", image.Name())
|
|
||||||
status = "error"
|
|
||||||
}
|
|
||||||
|
|
||||||
if status != "error" {
|
|
||||||
for _, d := range required {
|
|
||||||
requiredSize += d.Size
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, d := range present {
|
|
||||||
presentSize += d.Size
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(missing) > 0 {
|
|
||||||
status = "incomplete"
|
|
||||||
}
|
|
||||||
|
|
||||||
if available {
|
|
||||||
status += fmt.Sprintf(" (%v/%v)", len(present), len(required))
|
|
||||||
size = fmt.Sprintf("%v/%v", progress.Bytes(presentSize), progress.Bytes(requiredSize))
|
|
||||||
} else {
|
|
||||||
status = fmt.Sprintf("unavailable (%v/?)", len(present))
|
|
||||||
size = fmt.Sprintf("%v/?", progress.Bytes(presentSize))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
size = "-"
|
|
||||||
}
|
|
||||||
|
|
||||||
unpacked, err := image.IsUnpacked(ctx, context.String("snapshotter"))
|
|
||||||
if err != nil {
|
|
||||||
if exitErr == nil {
|
|
||||||
exitErr = errors.Wrapf(err, "unable to check unpack for %v", image.Name())
|
|
||||||
}
|
|
||||||
log.G(ctx).WithError(err).Errorf("unable to check unpack for %v", image.Name())
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(tw, "%v\t%v\t%v\t%v\t%v\t%t\n",
|
|
||||||
image.Name(),
|
|
||||||
image.Target().MediaType,
|
|
||||||
image.Target().Digest,
|
|
||||||
status,
|
|
||||||
size,
|
|
||||||
unpacked)
|
|
||||||
}
|
|
||||||
tw.Flush()
|
|
||||||
|
|
||||||
return exitErr
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var removeCommand = cli.Command{
|
|
||||||
Name: "remove",
|
|
||||||
Aliases: []string{"rm"},
|
|
||||||
Usage: "remove one or more images by reference",
|
|
||||||
ArgsUsage: "[flags] <ref> [<ref>, ...]",
|
|
||||||
Description: "remove one or more images by reference",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "sync",
|
|
||||||
Usage: "Synchronously remove image and all associated resources",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
var (
|
|
||||||
exitErr error
|
|
||||||
imageStore = client.ImageService()
|
|
||||||
)
|
|
||||||
for i, target := range context.Args() {
|
|
||||||
var opts []images.DeleteOpt
|
|
||||||
if context.Bool("sync") && i == context.NArg()-1 {
|
|
||||||
opts = append(opts, images.SynchronousDelete())
|
|
||||||
}
|
|
||||||
if err := imageStore.Delete(ctx, target, opts...); err != nil {
|
|
||||||
if !errdefs.IsNotFound(err) {
|
|
||||||
if exitErr == nil {
|
|
||||||
exitErr = errors.Wrapf(err, "unable to delete %v", target)
|
|
||||||
}
|
|
||||||
log.G(ctx).WithError(err).Errorf("unable to delete %v", target)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// image ref not found in metadata store; log not found condition
|
|
||||||
log.G(ctx).Warnf("%v: image not found", target)
|
|
||||||
} else {
|
|
||||||
fmt.Println(target)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return exitErr
|
|
||||||
},
|
|
||||||
}
|
|
144
vendor/github.com/containerd/containerd/cmd/ctr/commands/images/import.go
generated
vendored
144
vendor/github.com/containerd/containerd/cmd/ctr/commands/images/import.go
generated
vendored
@ -1,144 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 images
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/images/archive"
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var importCommand = cli.Command{
|
|
||||||
Name: "import",
|
|
||||||
Usage: "import images",
|
|
||||||
ArgsUsage: "[flags] <in>",
|
|
||||||
Description: `Import images from a tar stream.
|
|
||||||
Implemented formats:
|
|
||||||
- oci.v1
|
|
||||||
- docker.v1.1
|
|
||||||
- docker.v1.2
|
|
||||||
|
|
||||||
|
|
||||||
For OCI v1, you may need to specify --base-name because an OCI archive may
|
|
||||||
contain only partial image references (tags without the base image name).
|
|
||||||
If no base image name is provided, a name will be generated as "import-%{yyyy-MM-dd}".
|
|
||||||
|
|
||||||
e.g.
|
|
||||||
$ ctr images import --base-name foo/bar foobar.tar
|
|
||||||
|
|
||||||
If foobar.tar contains an OCI ref named "latest" and anonymous ref "sha256:deadbeef", the command will create
|
|
||||||
"foo/bar:latest" and "foo/bar@sha256:deadbeef" images in the containerd store.
|
|
||||||
`,
|
|
||||||
Flags: append([]cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "base-name",
|
|
||||||
Value: "",
|
|
||||||
Usage: "base image name for added images, when provided only images with this name prefix are imported",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "digests",
|
|
||||||
Usage: "whether to create digest images (default: false)",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "index-name",
|
|
||||||
Usage: "image name to keep index as, by default index is discarded",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "all-platforms",
|
|
||||||
Usage: "imports content for all platforms, false by default",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "no-unpack",
|
|
||||||
Usage: "skip unpacking the images, false by default",
|
|
||||||
},
|
|
||||||
}, commands.SnapshotterFlags...),
|
|
||||||
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
in = context.Args().First()
|
|
||||||
opts []containerd.ImportOpt
|
|
||||||
)
|
|
||||||
|
|
||||||
prefix := context.String("base-name")
|
|
||||||
if prefix == "" {
|
|
||||||
prefix = fmt.Sprintf("import-%s", time.Now().Format("2006-01-02"))
|
|
||||||
opts = append(opts, containerd.WithImageRefTranslator(archive.AddRefPrefix(prefix)))
|
|
||||||
} else {
|
|
||||||
// When provided, filter out references which do not match
|
|
||||||
opts = append(opts, containerd.WithImageRefTranslator(archive.FilterRefPrefix(prefix)))
|
|
||||||
}
|
|
||||||
|
|
||||||
if context.Bool("digests") {
|
|
||||||
opts = append(opts, containerd.WithDigestRef(archive.DigestTranslator(prefix)))
|
|
||||||
}
|
|
||||||
|
|
||||||
if idxName := context.String("index-name"); idxName != "" {
|
|
||||||
opts = append(opts, containerd.WithIndexName(idxName))
|
|
||||||
}
|
|
||||||
|
|
||||||
opts = append(opts, containerd.WithAllPlatforms(context.Bool("all-platforms")))
|
|
||||||
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
var r io.ReadCloser
|
|
||||||
if in == "-" {
|
|
||||||
r = os.Stdin
|
|
||||||
} else {
|
|
||||||
r, err = os.Open(in)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
imgs, err := client.Import(ctx, r, opts...)
|
|
||||||
closeErr := r.Close()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if closeErr != nil {
|
|
||||||
return closeErr
|
|
||||||
}
|
|
||||||
|
|
||||||
if !context.Bool("no-unpack") {
|
|
||||||
log.G(ctx).Debugf("unpacking %d images", len(imgs))
|
|
||||||
|
|
||||||
for _, img := range imgs {
|
|
||||||
// TODO: Allow configuration of the platform
|
|
||||||
image := containerd.NewImage(client, img)
|
|
||||||
|
|
||||||
// TODO: Show unpack status
|
|
||||||
fmt.Printf("unpacking %s (%s)...", img.Name, img.Target.Digest)
|
|
||||||
err = image.Unpack(ctx, context.String("snapshotter"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Println("done")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
121
vendor/github.com/containerd/containerd/cmd/ctr/commands/images/pull.go
generated
vendored
121
vendor/github.com/containerd/containerd/cmd/ctr/commands/images/pull.go
generated
vendored
@ -1,121 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 images
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands/content"
|
|
||||||
"github.com/containerd/containerd/images"
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
"github.com/containerd/containerd/platforms"
|
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var pullCommand = cli.Command{
|
|
||||||
Name: "pull",
|
|
||||||
Usage: "pull an image from a remote",
|
|
||||||
ArgsUsage: "[flags] <ref>",
|
|
||||||
Description: `Fetch and prepare an image for use in containerd.
|
|
||||||
|
|
||||||
After pulling an image, it should be ready to use the same reference in a run
|
|
||||||
command. As part of this process, we do the following:
|
|
||||||
|
|
||||||
1. Fetch all resources into containerd.
|
|
||||||
2. Prepare the snapshot filesystem with the pulled resources.
|
|
||||||
3. Register metadata for the image.
|
|
||||||
`,
|
|
||||||
Flags: append(append(commands.RegistryFlags, append(commands.SnapshotterFlags, commands.LabelFlag)...),
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "platform",
|
|
||||||
Usage: "Pull content from a specific platform",
|
|
||||||
Value: &cli.StringSlice{},
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "all-platforms",
|
|
||||||
Usage: "pull content from all platforms",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
ref = context.Args().First()
|
|
||||||
)
|
|
||||||
if ref == "" {
|
|
||||||
return fmt.Errorf("please provide an image reference to pull")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
ctx, done, err := client.WithLease(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer done(ctx)
|
|
||||||
|
|
||||||
config, err := content.NewFetchConfig(ctx, context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
img, err := content.Fetch(ctx, client, ref, config)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
log.G(ctx).WithField("image", ref).Debug("unpacking")
|
|
||||||
|
|
||||||
// TODO: Show unpack status
|
|
||||||
|
|
||||||
var p []ocispec.Platform
|
|
||||||
if context.Bool("all-platforms") {
|
|
||||||
p, err = images.Platforms(ctx, client.ContentStore(), img.Target)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "unable to resolve image platforms")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, s := range context.StringSlice("platform") {
|
|
||||||
ps, err := platforms.Parse(s)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "unable to parse platform %s", s)
|
|
||||||
}
|
|
||||||
p = append(p, ps)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(p) == 0 {
|
|
||||||
p = append(p, platforms.DefaultSpec())
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, platform := range p {
|
|
||||||
fmt.Printf("unpacking %s %s...\n", platforms.Format(platform), img.Target.Digest)
|
|
||||||
i := containerd.NewImageWithPlatform(client, img, platforms.Only(platform))
|
|
||||||
err = i.Unpack(ctx, context.String("snapshotter"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println("done")
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
218
vendor/github.com/containerd/containerd/cmd/ctr/commands/images/push.go
generated
vendored
218
vendor/github.com/containerd/containerd/cmd/ctr/commands/images/push.go
generated
vendored
@ -1,218 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 images
|
|
||||||
|
|
||||||
import (
|
|
||||||
gocontext "context"
|
|
||||||
"os"
|
|
||||||
"sync"
|
|
||||||
"text/tabwriter"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands/content"
|
|
||||||
"github.com/containerd/containerd/images"
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
"github.com/containerd/containerd/pkg/progress"
|
|
||||||
"github.com/containerd/containerd/remotes"
|
|
||||||
"github.com/containerd/containerd/remotes/docker"
|
|
||||||
digest "github.com/opencontainers/go-digest"
|
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
"golang.org/x/sync/errgroup"
|
|
||||||
)
|
|
||||||
|
|
||||||
var pushCommand = cli.Command{
|
|
||||||
Name: "push",
|
|
||||||
Usage: "push an image to a remote",
|
|
||||||
ArgsUsage: "[flags] <remote> [<local>]",
|
|
||||||
Description: `Pushes an image reference from containerd.
|
|
||||||
|
|
||||||
All resources associated with the manifest reference will be pushed.
|
|
||||||
The ref is used to resolve to a locally existing image manifest.
|
|
||||||
The image manifest must exist before push. Creating a new image
|
|
||||||
manifest can be done through calculating the diff for layers,
|
|
||||||
creating the associated configuration, and creating the manifest
|
|
||||||
which references those resources.
|
|
||||||
`,
|
|
||||||
Flags: append(commands.RegistryFlags, cli.StringFlag{
|
|
||||||
Name: "manifest",
|
|
||||||
Usage: "digest of manifest",
|
|
||||||
}, cli.StringFlag{
|
|
||||||
Name: "manifest-type",
|
|
||||||
Usage: "media type of manifest digest",
|
|
||||||
Value: ocispec.MediaTypeImageManifest,
|
|
||||||
}),
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
ref = context.Args().First()
|
|
||||||
local = context.Args().Get(1)
|
|
||||||
debug = context.GlobalBool("debug")
|
|
||||||
desc ocispec.Descriptor
|
|
||||||
)
|
|
||||||
if ref == "" {
|
|
||||||
return errors.New("please provide a remote image reference to push")
|
|
||||||
}
|
|
||||||
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
if manifest := context.String("manifest"); manifest != "" {
|
|
||||||
desc.Digest, err = digest.Parse(manifest)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "invalid manifest digest")
|
|
||||||
}
|
|
||||||
desc.MediaType = context.String("manifest-type")
|
|
||||||
} else {
|
|
||||||
if local == "" {
|
|
||||||
local = ref
|
|
||||||
}
|
|
||||||
img, err := client.ImageService().Get(ctx, local)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "unable to resolve image to manifest")
|
|
||||||
}
|
|
||||||
desc = img.Target
|
|
||||||
}
|
|
||||||
|
|
||||||
resolver, err := commands.GetResolver(ctx, context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
ongoing := newPushJobs(commands.PushTracker)
|
|
||||||
|
|
||||||
eg, ctx := errgroup.WithContext(ctx)
|
|
||||||
|
|
||||||
// used to notify the progress writer
|
|
||||||
doneCh := make(chan struct{})
|
|
||||||
|
|
||||||
eg.Go(func() error {
|
|
||||||
defer close(doneCh)
|
|
||||||
|
|
||||||
log.G(ctx).WithField("image", ref).WithField("digest", desc.Digest).Debug("pushing")
|
|
||||||
|
|
||||||
jobHandler := images.HandlerFunc(func(ctx gocontext.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) {
|
|
||||||
ongoing.add(remotes.MakeRefKey(ctx, desc))
|
|
||||||
return nil, nil
|
|
||||||
})
|
|
||||||
|
|
||||||
return client.Push(ctx, ref, desc,
|
|
||||||
containerd.WithResolver(resolver),
|
|
||||||
containerd.WithImageHandler(jobHandler),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
// don't show progress if debug mode is set
|
|
||||||
if !debug {
|
|
||||||
eg.Go(func() error {
|
|
||||||
var (
|
|
||||||
ticker = time.NewTicker(100 * time.Millisecond)
|
|
||||||
fw = progress.NewWriter(os.Stdout)
|
|
||||||
start = time.Now()
|
|
||||||
done bool
|
|
||||||
)
|
|
||||||
|
|
||||||
defer ticker.Stop()
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ticker.C:
|
|
||||||
fw.Flush()
|
|
||||||
|
|
||||||
tw := tabwriter.NewWriter(fw, 1, 8, 1, ' ', 0)
|
|
||||||
|
|
||||||
content.Display(tw, ongoing.status(), start)
|
|
||||||
tw.Flush()
|
|
||||||
|
|
||||||
if done {
|
|
||||||
fw.Flush()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
case <-doneCh:
|
|
||||||
done = true
|
|
||||||
case <-ctx.Done():
|
|
||||||
done = true // allow ui to update once more
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return eg.Wait()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
type pushjobs struct {
|
|
||||||
jobs map[string]struct{}
|
|
||||||
ordered []string
|
|
||||||
tracker docker.StatusTracker
|
|
||||||
mu sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func newPushJobs(tracker docker.StatusTracker) *pushjobs {
|
|
||||||
return &pushjobs{
|
|
||||||
jobs: make(map[string]struct{}),
|
|
||||||
tracker: tracker,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j *pushjobs) add(ref string) {
|
|
||||||
j.mu.Lock()
|
|
||||||
defer j.mu.Unlock()
|
|
||||||
|
|
||||||
if _, ok := j.jobs[ref]; ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
j.ordered = append(j.ordered, ref)
|
|
||||||
j.jobs[ref] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j *pushjobs) status() []content.StatusInfo {
|
|
||||||
j.mu.Lock()
|
|
||||||
defer j.mu.Unlock()
|
|
||||||
|
|
||||||
statuses := make([]content.StatusInfo, 0, len(j.jobs))
|
|
||||||
for _, name := range j.ordered {
|
|
||||||
si := content.StatusInfo{
|
|
||||||
Ref: name,
|
|
||||||
}
|
|
||||||
|
|
||||||
status, err := j.tracker.GetStatus(name)
|
|
||||||
if err != nil {
|
|
||||||
si.Status = "waiting"
|
|
||||||
} else {
|
|
||||||
si.Offset = status.Offset
|
|
||||||
si.Total = status.Total
|
|
||||||
si.StartedAt = status.StartedAt
|
|
||||||
si.UpdatedAt = status.UpdatedAt
|
|
||||||
if status.Offset >= status.Total {
|
|
||||||
if status.UploadUUID == "" {
|
|
||||||
si.Status = "done"
|
|
||||||
} else {
|
|
||||||
si.Status = "committing"
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
si.Status = "uploading"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
statuses = append(statuses, si)
|
|
||||||
}
|
|
||||||
|
|
||||||
return statuses
|
|
||||||
}
|
|
68
vendor/github.com/containerd/containerd/cmd/ctr/commands/install/install.go
generated
vendored
68
vendor/github.com/containerd/containerd/cmd/ctr/commands/install/install.go
generated
vendored
@ -1,68 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 install
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Command to install binary packages
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "install",
|
|
||||||
Usage: "install a new package",
|
|
||||||
ArgsUsage: "<ref>",
|
|
||||||
Description: "install a new package",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "libs,l",
|
|
||||||
Usage: "install libs from the image",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "replace,r",
|
|
||||||
Usage: "replace any binaries or libs in the opt directory",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "path",
|
|
||||||
Usage: "set an optional install path other than the managed opt directory",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
ref := context.Args().First()
|
|
||||||
image, err := client.GetImage(ctx, ref)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var opts []containerd.InstallOpts
|
|
||||||
if context.Bool("libs") {
|
|
||||||
opts = append(opts, containerd.WithInstallLibs)
|
|
||||||
}
|
|
||||||
if context.Bool("replace") {
|
|
||||||
opts = append(opts, containerd.WithInstallReplace)
|
|
||||||
}
|
|
||||||
if path := context.String("path"); path != "" {
|
|
||||||
opts = append(opts, containerd.WithInstallPath(path))
|
|
||||||
}
|
|
||||||
return client.Install(ctx, image, opts...)
|
|
||||||
},
|
|
||||||
}
|
|
202
vendor/github.com/containerd/containerd/cmd/ctr/commands/leases/leases.go
generated
vendored
202
vendor/github.com/containerd/containerd/cmd/ctr/commands/leases/leases.go
generated
vendored
@ -1,202 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 leases
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
"text/tabwriter"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/leases"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Command is the cli command for managing content
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "leases",
|
|
||||||
Usage: "manage leases",
|
|
||||||
Subcommands: cli.Commands{
|
|
||||||
listCommand,
|
|
||||||
createCommand,
|
|
||||||
deleteCommand,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var listCommand = cli.Command{
|
|
||||||
|
|
||||||
Name: "list",
|
|
||||||
Aliases: []string{"ls"},
|
|
||||||
Usage: "list all active leases",
|
|
||||||
ArgsUsage: "[flags] <filter>",
|
|
||||||
Description: "list active leases by containerd",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "quiet, q",
|
|
||||||
Usage: "print only the blob digest",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
filters = context.Args()
|
|
||||||
quiet = context.Bool("quiet")
|
|
||||||
)
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
ls := client.LeasesService()
|
|
||||||
|
|
||||||
leaseList, err := ls.List(ctx, filters...)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "failed to list leases")
|
|
||||||
}
|
|
||||||
if quiet {
|
|
||||||
for _, l := range leaseList {
|
|
||||||
fmt.Println(l.ID)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
tw := tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0)
|
|
||||||
fmt.Fprintln(tw, "ID\tCREATED AT\tLABELS\t")
|
|
||||||
for _, l := range leaseList {
|
|
||||||
labels := "-"
|
|
||||||
if len(l.Labels) > 0 {
|
|
||||||
var pairs []string
|
|
||||||
for k, v := range l.Labels {
|
|
||||||
pairs = append(pairs, fmt.Sprintf("%v=%v", k, v))
|
|
||||||
}
|
|
||||||
sort.Strings(pairs)
|
|
||||||
labels = strings.Join(pairs, ",")
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintf(tw, "%v\t%v\t%s\t\n",
|
|
||||||
l.ID,
|
|
||||||
l.CreatedAt.Local().Format(time.RFC3339),
|
|
||||||
labels)
|
|
||||||
}
|
|
||||||
|
|
||||||
return tw.Flush()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var createCommand = cli.Command{
|
|
||||||
Name: "create",
|
|
||||||
Usage: "create lease",
|
|
||||||
ArgsUsage: "[flags] <label>=<value> ...",
|
|
||||||
Description: "create a new lease",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "id",
|
|
||||||
Usage: "set the id for the lease, will be generated by default",
|
|
||||||
},
|
|
||||||
cli.DurationFlag{
|
|
||||||
Name: "expires, x",
|
|
||||||
Usage: "expiration of lease (0 value will not expire)",
|
|
||||||
Value: 24 * time.Hour,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var labelstr = context.Args()
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
ls := client.LeasesService()
|
|
||||||
opts := []leases.Opt{}
|
|
||||||
if len(labelstr) > 0 {
|
|
||||||
labels := map[string]string{}
|
|
||||||
for _, lstr := range labelstr {
|
|
||||||
l := strings.SplitN(lstr, "=", 2)
|
|
||||||
if len(l) == 1 {
|
|
||||||
labels[l[0]] = ""
|
|
||||||
} else {
|
|
||||||
labels[l[0]] = l[1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
opts = append(opts, leases.WithLabels(labels))
|
|
||||||
}
|
|
||||||
|
|
||||||
if id := context.String("id"); id != "" {
|
|
||||||
opts = append(opts, leases.WithID(id))
|
|
||||||
}
|
|
||||||
if exp := context.Duration("expires"); exp > 0 {
|
|
||||||
opts = append(opts, leases.WithExpiration(exp))
|
|
||||||
}
|
|
||||||
|
|
||||||
l, err := ls.Create(ctx, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(l.ID)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var deleteCommand = cli.Command{
|
|
||||||
Name: "delete",
|
|
||||||
Aliases: []string{"rm"},
|
|
||||||
Usage: "delete a lease",
|
|
||||||
ArgsUsage: "[flags] <lease id> ...",
|
|
||||||
Description: "delete a lease",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "sync",
|
|
||||||
Usage: "Synchronously remove leases and all unreferenced resources",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var lids = context.Args()
|
|
||||||
if len(lids) == 0 {
|
|
||||||
return cli.ShowSubcommandHelp(context)
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
ls := client.LeasesService()
|
|
||||||
sync := context.Bool("sync")
|
|
||||||
for i, lid := range lids {
|
|
||||||
var opts []leases.DeleteOpt
|
|
||||||
if sync && i == len(lids)-1 {
|
|
||||||
opts = append(opts, leases.SynchronousDelete)
|
|
||||||
}
|
|
||||||
|
|
||||||
lease := leases.Lease{
|
|
||||||
ID: lid,
|
|
||||||
}
|
|
||||||
if err := ls.Delete(ctx, lease, opts...); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Println(lid)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
173
vendor/github.com/containerd/containerd/cmd/ctr/commands/namespaces/namespaces.go
generated
vendored
173
vendor/github.com/containerd/containerd/cmd/ctr/commands/namespaces/namespaces.go
generated
vendored
@ -1,173 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 namespaces
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
"text/tabwriter"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/errdefs"
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Command is the cli command for managing namespaces
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "namespaces",
|
|
||||||
Aliases: []string{"namespace"},
|
|
||||||
Usage: "manage namespaces",
|
|
||||||
Subcommands: cli.Commands{
|
|
||||||
createCommand,
|
|
||||||
listCommand,
|
|
||||||
removeCommand,
|
|
||||||
setLabelsCommand,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var createCommand = cli.Command{
|
|
||||||
Name: "create",
|
|
||||||
Usage: "create a new namespace",
|
|
||||||
ArgsUsage: "<name> [<key>=<value]",
|
|
||||||
Description: "create a new namespace. it must be unique",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
namespace, labels := commands.ObjectWithLabelArgs(context)
|
|
||||||
if namespace == "" {
|
|
||||||
return errors.New("please specify a namespace")
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
namespaces := client.NamespaceService()
|
|
||||||
return namespaces.Create(ctx, namespace, labels)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var setLabelsCommand = cli.Command{
|
|
||||||
Name: "label",
|
|
||||||
Usage: "set and clear labels for a namespace",
|
|
||||||
ArgsUsage: "<name> [<key>=<value>, ...]",
|
|
||||||
Description: "set and clear labels for a namespace",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
namespace, labels := commands.ObjectWithLabelArgs(context)
|
|
||||||
if namespace == "" {
|
|
||||||
return errors.New("please specify a namespace")
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
namespaces := client.NamespaceService()
|
|
||||||
for k, v := range labels {
|
|
||||||
if err := namespaces.SetLabel(ctx, namespace, k, v); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var listCommand = cli.Command{
|
|
||||||
Name: "list",
|
|
||||||
Aliases: []string{"ls"},
|
|
||||||
Usage: "list namespaces",
|
|
||||||
ArgsUsage: "[flags]",
|
|
||||||
Description: "list namespaces",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "quiet, q",
|
|
||||||
Usage: "print only the namespace name",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
quiet := context.Bool("quiet")
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
namespaces := client.NamespaceService()
|
|
||||||
nss, err := namespaces.List(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if quiet {
|
|
||||||
for _, ns := range nss {
|
|
||||||
fmt.Println(ns)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
tw := tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0)
|
|
||||||
fmt.Fprintln(tw, "NAME\tLABELS\t")
|
|
||||||
for _, ns := range nss {
|
|
||||||
labels, err := namespaces.Labels(ctx, ns)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var labelStrings []string
|
|
||||||
for k, v := range labels {
|
|
||||||
labelStrings = append(labelStrings, strings.Join([]string{k, v}, "="))
|
|
||||||
}
|
|
||||||
sort.Strings(labelStrings)
|
|
||||||
|
|
||||||
fmt.Fprintf(tw, "%v\t%v\t\n", ns, strings.Join(labelStrings, ","))
|
|
||||||
}
|
|
||||||
return tw.Flush()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var removeCommand = cli.Command{
|
|
||||||
Name: "remove",
|
|
||||||
Aliases: []string{"rm"},
|
|
||||||
Usage: "remove one or more namespaces",
|
|
||||||
ArgsUsage: "<name> [<name>, ...]",
|
|
||||||
Description: "remove one or more namespaces. for now, the namespace must be empty",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var exitErr error
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
namespaces := client.NamespaceService()
|
|
||||||
for _, target := range context.Args() {
|
|
||||||
if err := namespaces.Delete(ctx, target); err != nil {
|
|
||||||
if !errdefs.IsNotFound(err) {
|
|
||||||
if exitErr == nil {
|
|
||||||
exitErr = errors.Wrapf(err, "unable to delete %v", target)
|
|
||||||
}
|
|
||||||
log.G(ctx).WithError(err).Errorf("unable to delete %v", target)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(target)
|
|
||||||
}
|
|
||||||
return exitErr
|
|
||||||
},
|
|
||||||
}
|
|
162
vendor/github.com/containerd/containerd/cmd/ctr/commands/plugins/plugins.go
generated
vendored
162
vendor/github.com/containerd/containerd/cmd/ctr/commands/plugins/plugins.go
generated
vendored
@ -1,162 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 plugins
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
"text/tabwriter"
|
|
||||||
|
|
||||||
introspection "github.com/containerd/containerd/api/services/introspection/v1"
|
|
||||||
"github.com/containerd/containerd/api/types"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/platforms"
|
|
||||||
"github.com/opencontainers/image-spec/specs-go/v1"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
"google.golang.org/grpc/codes"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Command is a cli command that outputs plugin information
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "plugins",
|
|
||||||
Aliases: []string{"plugin"},
|
|
||||||
Usage: "provides information about containerd plugins",
|
|
||||||
Subcommands: []cli.Command{
|
|
||||||
listCommand,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var listCommand = cli.Command{
|
|
||||||
Name: "list",
|
|
||||||
Aliases: []string{"ls"},
|
|
||||||
Usage: "lists containerd plugins",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "quiet,q",
|
|
||||||
Usage: "print only the plugin ids",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "detailed,d",
|
|
||||||
Usage: "print detailed information about each plugin",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
quiet = context.Bool("quiet")
|
|
||||||
detailed = context.Bool("detailed")
|
|
||||||
)
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
ps := client.IntrospectionService()
|
|
||||||
response, err := ps.Plugins(ctx, &introspection.PluginsRequest{
|
|
||||||
Filters: context.Args(),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if quiet {
|
|
||||||
for _, plugin := range response.Plugins {
|
|
||||||
fmt.Println(plugin.ID)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
w := tabwriter.NewWriter(os.Stdout, 4, 8, 4, ' ', 0)
|
|
||||||
if detailed {
|
|
||||||
first := true
|
|
||||||
for _, plugin := range response.Plugins {
|
|
||||||
if !first {
|
|
||||||
fmt.Fprintln(w, "\t\t\t")
|
|
||||||
}
|
|
||||||
first = false
|
|
||||||
fmt.Fprintln(w, "Type:\t", plugin.Type)
|
|
||||||
fmt.Fprintln(w, "ID:\t", plugin.ID)
|
|
||||||
if len(plugin.Requires) > 0 {
|
|
||||||
fmt.Fprintln(w, "Requires:\t")
|
|
||||||
for _, r := range plugin.Requires {
|
|
||||||
fmt.Fprintln(w, "\t", r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(plugin.Platforms) > 0 {
|
|
||||||
fmt.Fprintln(w, "Platforms:\t", prettyPlatforms(plugin.Platforms))
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(plugin.Exports) > 0 {
|
|
||||||
fmt.Fprintln(w, "Exports:\t")
|
|
||||||
for k, v := range plugin.Exports {
|
|
||||||
fmt.Fprintln(w, "\t", k, "\t", v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(plugin.Capabilities) > 0 {
|
|
||||||
fmt.Fprintln(w, "Capabilities:\t", strings.Join(plugin.Capabilities, ","))
|
|
||||||
}
|
|
||||||
|
|
||||||
if plugin.InitErr != nil {
|
|
||||||
fmt.Fprintln(w, "Error:\t")
|
|
||||||
fmt.Fprintln(w, "\t Code:\t", codes.Code(plugin.InitErr.Code))
|
|
||||||
fmt.Fprintln(w, "\t Message:\t", plugin.InitErr.Message)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return w.Flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Fprintln(w, "TYPE\tID\tPLATFORMS\tSTATUS\t")
|
|
||||||
for _, plugin := range response.Plugins {
|
|
||||||
status := "ok"
|
|
||||||
|
|
||||||
if plugin.InitErr != nil {
|
|
||||||
status = "error"
|
|
||||||
}
|
|
||||||
|
|
||||||
var platformColumn = "-"
|
|
||||||
if len(plugin.Platforms) > 0 {
|
|
||||||
platformColumn = prettyPlatforms(plugin.Platforms)
|
|
||||||
}
|
|
||||||
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t\n",
|
|
||||||
plugin.Type,
|
|
||||||
plugin.ID,
|
|
||||||
platformColumn,
|
|
||||||
status,
|
|
||||||
); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return w.Flush()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func prettyPlatforms(pspb []types.Platform) string {
|
|
||||||
psm := map[string]struct{}{}
|
|
||||||
for _, p := range pspb {
|
|
||||||
psm[platforms.Format(v1.Platform{
|
|
||||||
OS: p.OS,
|
|
||||||
Architecture: p.Architecture,
|
|
||||||
Variant: p.Variant,
|
|
||||||
})] = struct{}{}
|
|
||||||
}
|
|
||||||
var ps []string
|
|
||||||
for p := range psm {
|
|
||||||
ps = append(ps, p)
|
|
||||||
}
|
|
||||||
sort.Stable(sort.StringSlice(ps))
|
|
||||||
return strings.Join(ps, ",")
|
|
||||||
}
|
|
189
vendor/github.com/containerd/containerd/cmd/ctr/commands/pprof/pprof.go
generated
vendored
189
vendor/github.com/containerd/containerd/cmd/ctr/commands/pprof/pprof.go
generated
vendored
@ -1,189 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 pprof
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/defaults"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
type pprofDialer struct {
|
|
||||||
proto string
|
|
||||||
addr string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command is the cli command for providing golang pprof outputs for containerd
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "pprof",
|
|
||||||
Usage: "provide golang pprof outputs for containerd",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "debug-socket, d",
|
|
||||||
Usage: "socket path for containerd's debug server",
|
|
||||||
Value: defaults.DefaultDebugAddress,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Subcommands: []cli.Command{
|
|
||||||
pprofBlockCommand,
|
|
||||||
pprofGoroutinesCommand,
|
|
||||||
pprofHeapCommand,
|
|
||||||
pprofProfileCommand,
|
|
||||||
pprofThreadcreateCommand,
|
|
||||||
pprofTraceCommand,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var pprofGoroutinesCommand = cli.Command{
|
|
||||||
Name: "goroutines",
|
|
||||||
Usage: "dump goroutine stack dump",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
client := getPProfClient(context)
|
|
||||||
|
|
||||||
output, err := httpGetRequest(client, "/debug/pprof/goroutine?debug=2")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer output.Close()
|
|
||||||
_, err = io.Copy(os.Stdout, output)
|
|
||||||
return err
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var pprofHeapCommand = cli.Command{
|
|
||||||
Name: "heap",
|
|
||||||
Usage: "dump heap profile",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
client := getPProfClient(context)
|
|
||||||
|
|
||||||
output, err := httpGetRequest(client, "/debug/pprof/heap")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer output.Close()
|
|
||||||
_, err = io.Copy(os.Stdout, output)
|
|
||||||
return err
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var pprofProfileCommand = cli.Command{
|
|
||||||
Name: "profile",
|
|
||||||
Usage: "CPU profile",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.DurationFlag{
|
|
||||||
Name: "seconds,s",
|
|
||||||
Usage: "duration for collection (seconds)",
|
|
||||||
Value: 30 * time.Second,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
client := getPProfClient(context)
|
|
||||||
|
|
||||||
seconds := context.Duration("seconds").Seconds()
|
|
||||||
output, err := httpGetRequest(client, fmt.Sprintf("/debug/pprof/profile?seconds=%v", seconds))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer output.Close()
|
|
||||||
_, err = io.Copy(os.Stdout, output)
|
|
||||||
return err
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var pprofTraceCommand = cli.Command{
|
|
||||||
Name: "trace",
|
|
||||||
Usage: "collect execution trace",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.DurationFlag{
|
|
||||||
Name: "seconds,s",
|
|
||||||
Usage: "trace time (seconds)",
|
|
||||||
Value: 5 * time.Second,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
client := getPProfClient(context)
|
|
||||||
|
|
||||||
seconds := context.Duration("seconds").Seconds()
|
|
||||||
uri := fmt.Sprintf("/debug/pprof/trace?seconds=%v", seconds)
|
|
||||||
output, err := httpGetRequest(client, uri)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer output.Close()
|
|
||||||
_, err = io.Copy(os.Stdout, output)
|
|
||||||
return err
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var pprofBlockCommand = cli.Command{
|
|
||||||
Name: "block",
|
|
||||||
Usage: "goroutine blocking profile",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
client := getPProfClient(context)
|
|
||||||
|
|
||||||
output, err := httpGetRequest(client, "/debug/pprof/block")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer output.Close()
|
|
||||||
_, err = io.Copy(os.Stdout, output)
|
|
||||||
return err
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var pprofThreadcreateCommand = cli.Command{
|
|
||||||
Name: "threadcreate",
|
|
||||||
Usage: "goroutine thread creating profile",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
client := getPProfClient(context)
|
|
||||||
|
|
||||||
output, err := httpGetRequest(client, "/debug/pprof/threadcreate")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer output.Close()
|
|
||||||
_, err = io.Copy(os.Stdout, output)
|
|
||||||
return err
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPProfClient(context *cli.Context) *http.Client {
|
|
||||||
dialer := getPProfDialer(context.GlobalString("debug-socket"))
|
|
||||||
|
|
||||||
tr := &http.Transport{
|
|
||||||
Dial: dialer.pprofDial,
|
|
||||||
}
|
|
||||||
client := &http.Client{Transport: tr}
|
|
||||||
return client
|
|
||||||
}
|
|
||||||
|
|
||||||
func httpGetRequest(client *http.Client, request string) (io.ReadCloser, error) {
|
|
||||||
resp, err := client.Get("http://." + request)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if resp.StatusCode != 200 {
|
|
||||||
return nil, errors.Errorf("http get failed with status: %s", resp.Status)
|
|
||||||
}
|
|
||||||
return resp.Body, nil
|
|
||||||
}
|
|
29
vendor/github.com/containerd/containerd/cmd/ctr/commands/pprof/pprof_unix.go
generated
vendored
29
vendor/github.com/containerd/containerd/cmd/ctr/commands/pprof/pprof_unix.go
generated
vendored
@ -1,29 +0,0 @@
|
|||||||
// +build !windows
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright The containerd 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 pprof
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
func (d *pprofDialer) pprofDial(proto, addr string) (conn net.Conn, err error) {
|
|
||||||
return net.Dial(d.proto, d.addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPProfDialer(addr string) *pprofDialer {
|
|
||||||
return &pprofDialer{"unix", addr}
|
|
||||||
}
|
|
31
vendor/github.com/containerd/containerd/cmd/ctr/commands/pprof/pprof_windows.go
generated
vendored
31
vendor/github.com/containerd/containerd/cmd/ctr/commands/pprof/pprof_windows.go
generated
vendored
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 pprof
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
|
|
||||||
winio "github.com/Microsoft/go-winio"
|
|
||||||
)
|
|
||||||
|
|
||||||
func (d *pprofDialer) pprofDial(proto, addr string) (conn net.Conn, err error) {
|
|
||||||
return winio.DialPipe(d.addr, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPProfDialer(addr string) *pprofDialer {
|
|
||||||
return &pprofDialer{"winpipe", addr}
|
|
||||||
}
|
|
109
vendor/github.com/containerd/containerd/cmd/ctr/commands/resolver.go
generated
vendored
109
vendor/github.com/containerd/containerd/cmd/ctr/commands/resolver.go
generated
vendored
@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 commands
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
gocontext "context"
|
|
||||||
"crypto/tls"
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/containerd/console"
|
|
||||||
"github.com/containerd/containerd/remotes"
|
|
||||||
"github.com/containerd/containerd/remotes/docker"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
// PushTracker returns a new InMemoryTracker which tracks the ref status
|
|
||||||
var PushTracker = docker.NewInMemoryTracker()
|
|
||||||
|
|
||||||
func passwordPrompt() (string, error) {
|
|
||||||
c := console.Current()
|
|
||||||
defer c.Reset()
|
|
||||||
|
|
||||||
if err := c.DisableEcho(); err != nil {
|
|
||||||
return "", errors.Wrap(err, "failed to disable echo")
|
|
||||||
}
|
|
||||||
|
|
||||||
line, _, err := bufio.NewReader(c).ReadLine()
|
|
||||||
if err != nil {
|
|
||||||
return "", errors.Wrap(err, "failed to read line")
|
|
||||||
}
|
|
||||||
return string(line), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetResolver prepares the resolver from the environment and options
|
|
||||||
func GetResolver(ctx gocontext.Context, clicontext *cli.Context) (remotes.Resolver, error) {
|
|
||||||
username := clicontext.String("user")
|
|
||||||
var secret string
|
|
||||||
if i := strings.IndexByte(username, ':'); i > 0 {
|
|
||||||
secret = username[i+1:]
|
|
||||||
username = username[0:i]
|
|
||||||
}
|
|
||||||
options := docker.ResolverOptions{
|
|
||||||
PlainHTTP: clicontext.Bool("plain-http"),
|
|
||||||
Tracker: PushTracker,
|
|
||||||
}
|
|
||||||
if username != "" {
|
|
||||||
if secret == "" {
|
|
||||||
fmt.Printf("Password: ")
|
|
||||||
|
|
||||||
var err error
|
|
||||||
secret, err = passwordPrompt()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Print("\n")
|
|
||||||
}
|
|
||||||
} else if rt := clicontext.String("refresh"); rt != "" {
|
|
||||||
secret = rt
|
|
||||||
}
|
|
||||||
|
|
||||||
tr := &http.Transport{
|
|
||||||
Proxy: http.ProxyFromEnvironment,
|
|
||||||
DialContext: (&net.Dialer{
|
|
||||||
Timeout: 30 * time.Second,
|
|
||||||
KeepAlive: 30 * time.Second,
|
|
||||||
DualStack: true,
|
|
||||||
}).DialContext,
|
|
||||||
MaxIdleConns: 10,
|
|
||||||
IdleConnTimeout: 30 * time.Second,
|
|
||||||
TLSHandshakeTimeout: 10 * time.Second,
|
|
||||||
TLSClientConfig: &tls.Config{
|
|
||||||
InsecureSkipVerify: clicontext.Bool("skip-verify"),
|
|
||||||
},
|
|
||||||
ExpectContinueTimeout: 5 * time.Second,
|
|
||||||
}
|
|
||||||
|
|
||||||
options.Client = &http.Client{
|
|
||||||
Transport: tr,
|
|
||||||
}
|
|
||||||
|
|
||||||
credentials := func(host string) (string, string, error) {
|
|
||||||
// Only one host
|
|
||||||
return username, secret, nil
|
|
||||||
}
|
|
||||||
options.Authorizer = docker.NewAuthorizer(options.Client, credentials)
|
|
||||||
|
|
||||||
return docker.NewResolver(options), nil
|
|
||||||
}
|
|
215
vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run.go
generated
vendored
215
vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run.go
generated
vendored
@ -1,215 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 run
|
|
||||||
|
|
||||||
import (
|
|
||||||
gocontext "context"
|
|
||||||
"encoding/csv"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containerd/console"
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/cio"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands/tasks"
|
|
||||||
"github.com/containerd/containerd/containers"
|
|
||||||
"github.com/containerd/containerd/oci"
|
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
func withMounts(context *cli.Context) oci.SpecOpts {
|
|
||||||
return func(ctx gocontext.Context, client oci.Client, container *containers.Container, s *specs.Spec) error {
|
|
||||||
mounts := make([]specs.Mount, 0)
|
|
||||||
for _, mount := range context.StringSlice("mount") {
|
|
||||||
m, err := parseMountFlag(mount)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
mounts = append(mounts, m)
|
|
||||||
}
|
|
||||||
return oci.WithMounts(mounts)(ctx, client, container, s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseMountFlag parses a mount string in the form "type=foo,source=/path,destination=/target,options=rbind:rw"
|
|
||||||
func parseMountFlag(m string) (specs.Mount, error) {
|
|
||||||
mount := specs.Mount{}
|
|
||||||
r := csv.NewReader(strings.NewReader(m))
|
|
||||||
|
|
||||||
fields, err := r.Read()
|
|
||||||
if err != nil {
|
|
||||||
return mount, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, field := range fields {
|
|
||||||
v := strings.Split(field, "=")
|
|
||||||
if len(v) != 2 {
|
|
||||||
return mount, fmt.Errorf("invalid mount specification: expected key=val")
|
|
||||||
}
|
|
||||||
|
|
||||||
key := v[0]
|
|
||||||
val := v[1]
|
|
||||||
switch key {
|
|
||||||
case "type":
|
|
||||||
mount.Type = val
|
|
||||||
case "source", "src":
|
|
||||||
mount.Source = val
|
|
||||||
case "destination", "dst":
|
|
||||||
mount.Destination = val
|
|
||||||
case "options":
|
|
||||||
mount.Options = strings.Split(val, ":")
|
|
||||||
default:
|
|
||||||
return mount, fmt.Errorf("mount option %q not supported", key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mount, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command runs a container
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "run",
|
|
||||||
Usage: "run a container",
|
|
||||||
ArgsUsage: "[flags] Image|RootFS ID [COMMAND] [ARG...]",
|
|
||||||
SkipArgReorder: true,
|
|
||||||
Flags: append([]cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "rm",
|
|
||||||
Usage: "remove the container after running",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "null-io",
|
|
||||||
Usage: "send all IO to /dev/null",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "log-uri",
|
|
||||||
Usage: "log uri",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "detach,d",
|
|
||||||
Usage: "detach from the task after it has started execution",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "fifo-dir",
|
|
||||||
Usage: "directory used for storing IO FIFOs",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "cgroup",
|
|
||||||
Usage: "cgroup path (To disable use of cgroup, set to \"\" explicitly)",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "platform",
|
|
||||||
Usage: "run image for specific platform",
|
|
||||||
},
|
|
||||||
}, append(platformRunFlags, append(commands.SnapshotterFlags, commands.ContainerFlags...)...)...),
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
id string
|
|
||||||
ref string
|
|
||||||
|
|
||||||
tty = context.Bool("tty")
|
|
||||||
detach = context.Bool("detach")
|
|
||||||
config = context.IsSet("config")
|
|
||||||
)
|
|
||||||
|
|
||||||
if config {
|
|
||||||
id = context.Args().First()
|
|
||||||
if context.NArg() > 1 {
|
|
||||||
return errors.New("with spec config file, only container id should be provided")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
id = context.Args().Get(1)
|
|
||||||
ref = context.Args().First()
|
|
||||||
|
|
||||||
if ref == "" {
|
|
||||||
return errors.New("image ref must be provided")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if id == "" {
|
|
||||||
return errors.New("container id must be provided")
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
container, err := NewContainer(ctx, client, context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if context.Bool("rm") && !detach {
|
|
||||||
defer container.Delete(ctx, containerd.WithSnapshotCleanup)
|
|
||||||
}
|
|
||||||
var con console.Console
|
|
||||||
if tty {
|
|
||||||
con = console.Current()
|
|
||||||
defer con.Reset()
|
|
||||||
if err := con.SetRaw(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
opts := getNewTaskOpts(context)
|
|
||||||
ioOpts := []cio.Opt{cio.WithFIFODir(context.String("fifo-dir"))}
|
|
||||||
task, err := tasks.NewTask(ctx, client, container, context.String("checkpoint"), con, context.Bool("null-io"), context.String("log-uri"), ioOpts, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var statusC <-chan containerd.ExitStatus
|
|
||||||
if !detach {
|
|
||||||
defer task.Delete(ctx)
|
|
||||||
if statusC, err = task.Wait(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if context.IsSet("pid-file") {
|
|
||||||
if err := commands.WritePidFile(context.String("pid-file"), int(task.Pid())); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := task.Start(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if detach {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if tty {
|
|
||||||
if err := tasks.HandleConsoleResize(ctx, task, con); err != nil {
|
|
||||||
logrus.WithError(err).Error("console resize")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sigc := commands.ForwardAllSignals(ctx, task)
|
|
||||||
defer commands.StopCatch(sigc)
|
|
||||||
}
|
|
||||||
status := <-statusC
|
|
||||||
code, _, err := status.Result()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := task.Delete(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if code != 0 {
|
|
||||||
return cli.NewExitError("", int(code))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
194
vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run_unix.go
generated
vendored
194
vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run_unix.go
generated
vendored
@ -1,194 +0,0 @@
|
|||||||
// +build !windows
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright The containerd 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 run
|
|
||||||
|
|
||||||
import (
|
|
||||||
gocontext "context"
|
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/contrib/nvidia"
|
|
||||||
"github.com/containerd/containerd/oci"
|
|
||||||
"github.com/containerd/containerd/platforms"
|
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var platformRunFlags []cli.Flag
|
|
||||||
|
|
||||||
// NewContainer creates a new container
|
|
||||||
func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli.Context) (containerd.Container, error) {
|
|
||||||
var (
|
|
||||||
id string
|
|
||||||
config = context.IsSet("config")
|
|
||||||
)
|
|
||||||
if config {
|
|
||||||
id = context.Args().First()
|
|
||||||
} else {
|
|
||||||
id = context.Args().Get(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
opts []oci.SpecOpts
|
|
||||||
cOpts []containerd.NewContainerOpts
|
|
||||||
spec containerd.NewContainerOpts
|
|
||||||
)
|
|
||||||
|
|
||||||
cOpts = append(cOpts, containerd.WithContainerLabels(commands.LabelArgs(context.StringSlice("label"))))
|
|
||||||
if config {
|
|
||||||
opts = append(opts, oci.WithSpecFromFile(context.String("config")))
|
|
||||||
} else {
|
|
||||||
var (
|
|
||||||
ref = context.Args().First()
|
|
||||||
//for container's id is Args[1]
|
|
||||||
args = context.Args()[2:]
|
|
||||||
)
|
|
||||||
opts = append(opts, oci.WithDefaultSpec(), oci.WithDefaultUnixDevices)
|
|
||||||
opts = append(opts, oci.WithEnv(context.StringSlice("env")))
|
|
||||||
opts = append(opts, withMounts(context))
|
|
||||||
|
|
||||||
if context.Bool("rootfs") {
|
|
||||||
rootfs, err := filepath.Abs(ref)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
opts = append(opts, oci.WithRootFSPath(rootfs))
|
|
||||||
} else {
|
|
||||||
snapshotter := context.String("snapshotter")
|
|
||||||
var image containerd.Image
|
|
||||||
i, err := client.ImageService().Get(ctx, ref)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if ps := context.String("platform"); ps != "" {
|
|
||||||
platform, err := platforms.Parse(ps)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
image = containerd.NewImageWithPlatform(client, i, platforms.Only(platform))
|
|
||||||
} else {
|
|
||||||
image = containerd.NewImage(client, i)
|
|
||||||
}
|
|
||||||
|
|
||||||
unpacked, err := image.IsUnpacked(ctx, snapshotter)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if !unpacked {
|
|
||||||
if err := image.Unpack(ctx, snapshotter); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
opts = append(opts, oci.WithImageConfig(image))
|
|
||||||
cOpts = append(cOpts,
|
|
||||||
containerd.WithImage(image),
|
|
||||||
containerd.WithSnapshotter(snapshotter),
|
|
||||||
// Even when "readonly" is set, we don't use KindView snapshot here. (#1495)
|
|
||||||
// We pass writable snapshot to the OCI runtime, and the runtime remounts it as read-only,
|
|
||||||
// after creating some mount points on demand.
|
|
||||||
containerd.WithNewSnapshot(id, image),
|
|
||||||
containerd.WithImageStopSignal(image, "SIGTERM"))
|
|
||||||
}
|
|
||||||
if context.Bool("readonly") {
|
|
||||||
opts = append(opts, oci.WithRootFSReadonly())
|
|
||||||
}
|
|
||||||
if len(args) > 0 {
|
|
||||||
opts = append(opts, oci.WithProcessArgs(args...))
|
|
||||||
}
|
|
||||||
if cwd := context.String("cwd"); cwd != "" {
|
|
||||||
opts = append(opts, oci.WithProcessCwd(cwd))
|
|
||||||
}
|
|
||||||
if context.Bool("tty") {
|
|
||||||
opts = append(opts, oci.WithTTY)
|
|
||||||
}
|
|
||||||
if context.Bool("privileged") {
|
|
||||||
opts = append(opts, oci.WithPrivileged)
|
|
||||||
}
|
|
||||||
if context.Bool("net-host") {
|
|
||||||
opts = append(opts, oci.WithHostNamespace(specs.NetworkNamespace), oci.WithHostHostsFile, oci.WithHostResolvconf)
|
|
||||||
}
|
|
||||||
|
|
||||||
joinNs := context.StringSlice("with-ns")
|
|
||||||
for _, ns := range joinNs {
|
|
||||||
parts := strings.Split(ns, ":")
|
|
||||||
if len(parts) != 2 {
|
|
||||||
return nil, errors.New("joining a Linux namespace using --with-ns requires the format 'nstype:path'")
|
|
||||||
}
|
|
||||||
if !validNamespace(parts[0]) {
|
|
||||||
return nil, errors.New("the Linux namespace type specified in --with-ns is not valid: " + parts[0])
|
|
||||||
}
|
|
||||||
opts = append(opts, oci.WithLinuxNamespace(specs.LinuxNamespace{
|
|
||||||
Type: specs.LinuxNamespaceType(parts[0]),
|
|
||||||
Path: parts[1],
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
if context.IsSet("gpus") {
|
|
||||||
opts = append(opts, nvidia.WithGPUs(nvidia.WithDevices(context.Int("gpus")), nvidia.WithAllCapabilities))
|
|
||||||
}
|
|
||||||
if context.IsSet("allow-new-privs") {
|
|
||||||
opts = append(opts, oci.WithNewPrivileges)
|
|
||||||
}
|
|
||||||
if context.IsSet("cgroup") {
|
|
||||||
// NOTE: can be set to "" explicitly for disabling cgroup.
|
|
||||||
opts = append(opts, oci.WithCgroup(context.String("cgroup")))
|
|
||||||
}
|
|
||||||
limit := context.Uint64("memory-limit")
|
|
||||||
if limit != 0 {
|
|
||||||
opts = append(opts, oci.WithMemoryLimit(limit))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cOpts = append(cOpts, containerd.WithRuntime(context.String("runtime"), nil))
|
|
||||||
|
|
||||||
opts = append(opts, oci.WithAnnotations(commands.LabelArgs(context.StringSlice("label"))))
|
|
||||||
var s specs.Spec
|
|
||||||
spec = containerd.WithSpec(&s, opts...)
|
|
||||||
|
|
||||||
cOpts = append(cOpts, spec)
|
|
||||||
|
|
||||||
// oci.WithImageConfig (WithUsername, WithUserID) depends on access to rootfs for resolving via
|
|
||||||
// the /etc/{passwd,group} files. So cOpts needs to have precedence over opts.
|
|
||||||
return client.NewContainer(ctx, id, cOpts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getNewTaskOpts(context *cli.Context) []containerd.NewTaskOpts {
|
|
||||||
if context.Bool("no-pivot") {
|
|
||||||
return []containerd.NewTaskOpts{containerd.WithNoPivotRoot}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func validNamespace(ns string) bool {
|
|
||||||
linuxNs := specs.LinuxNamespaceType(ns)
|
|
||||||
switch linuxNs {
|
|
||||||
case specs.PIDNamespace,
|
|
||||||
specs.NetworkNamespace,
|
|
||||||
specs.UTSNamespace,
|
|
||||||
specs.MountNamespace,
|
|
||||||
specs.UserNamespace,
|
|
||||||
specs.IPCNamespace,
|
|
||||||
specs.CgroupNamespace:
|
|
||||||
return true
|
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
140
vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run_windows.go
generated
vendored
140
vendor/github.com/containerd/containerd/cmd/ctr/commands/run/run_windows.go
generated
vendored
@ -1,140 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 run
|
|
||||||
|
|
||||||
import (
|
|
||||||
gocontext "context"
|
|
||||||
|
|
||||||
"github.com/containerd/console"
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/oci"
|
|
||||||
"github.com/containerd/containerd/runtime/v2/runhcs/options"
|
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var platformRunFlags = []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "isolated",
|
|
||||||
Usage: "run the container with vm isolation",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewContainer creates a new container
|
|
||||||
func NewContainer(ctx gocontext.Context, client *containerd.Client, context *cli.Context) (containerd.Container, error) {
|
|
||||||
var (
|
|
||||||
id string
|
|
||||||
opts []oci.SpecOpts
|
|
||||||
cOpts []containerd.NewContainerOpts
|
|
||||||
spec containerd.NewContainerOpts
|
|
||||||
|
|
||||||
config = context.IsSet("config")
|
|
||||||
)
|
|
||||||
|
|
||||||
if config {
|
|
||||||
id = context.Args().First()
|
|
||||||
opts = append(opts, oci.WithSpecFromFile(context.String("config")))
|
|
||||||
} else {
|
|
||||||
var (
|
|
||||||
ref = context.Args().First()
|
|
||||||
args = context.Args()[2:]
|
|
||||||
)
|
|
||||||
|
|
||||||
id = context.Args().Get(1)
|
|
||||||
snapshotter := context.String("snapshotter")
|
|
||||||
if snapshotter == "windows-lcow" {
|
|
||||||
opts = append(opts, oci.WithDefaultSpecForPlatform("linux/amd64"))
|
|
||||||
// Clear the rootfs section.
|
|
||||||
opts = append(opts, oci.WithRootFSPath(""))
|
|
||||||
} else {
|
|
||||||
opts = append(opts, oci.WithDefaultSpec())
|
|
||||||
opts = append(opts, oci.WithWindowNetworksAllowUnqualifiedDNSQuery())
|
|
||||||
opts = append(opts, oci.WithWindowsIgnoreFlushesDuringBoot())
|
|
||||||
}
|
|
||||||
opts = append(opts, oci.WithEnv(context.StringSlice("env")))
|
|
||||||
opts = append(opts, withMounts(context))
|
|
||||||
|
|
||||||
image, err := client.GetImage(ctx, ref)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
unpacked, err := image.IsUnpacked(ctx, snapshotter)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if !unpacked {
|
|
||||||
if err := image.Unpack(ctx, snapshotter); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
opts = append(opts, oci.WithImageConfig(image))
|
|
||||||
cOpts = append(cOpts, containerd.WithImage(image))
|
|
||||||
cOpts = append(cOpts, containerd.WithSnapshotter(snapshotter))
|
|
||||||
cOpts = append(cOpts, containerd.WithNewSnapshot(id, image))
|
|
||||||
|
|
||||||
if len(args) > 0 {
|
|
||||||
opts = append(opts, oci.WithProcessArgs(args...))
|
|
||||||
}
|
|
||||||
if cwd := context.String("cwd"); cwd != "" {
|
|
||||||
opts = append(opts, oci.WithProcessCwd(cwd))
|
|
||||||
}
|
|
||||||
if context.Bool("tty") {
|
|
||||||
opts = append(opts, oci.WithTTY)
|
|
||||||
|
|
||||||
con := console.Current()
|
|
||||||
size, err := con.Size()
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithError(err).Error("console size")
|
|
||||||
}
|
|
||||||
opts = append(opts, oci.WithTTYSize(int(size.Width), int(size.Height)))
|
|
||||||
}
|
|
||||||
if context.Bool("isolated") {
|
|
||||||
opts = append(opts, oci.WithWindowsHyperV)
|
|
||||||
}
|
|
||||||
limit := context.Uint64("memory-limit")
|
|
||||||
if limit != 0 {
|
|
||||||
opts = append(opts, oci.WithMemoryLimit(limit))
|
|
||||||
}
|
|
||||||
ccount := context.Uint64("cpu-count")
|
|
||||||
if ccount != 0 {
|
|
||||||
opts = append(opts, oci.WithWindowsCPUCount(ccount))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
cOpts = append(cOpts, containerd.WithContainerLabels(commands.LabelArgs(context.StringSlice("label"))))
|
|
||||||
runtime := context.String("runtime")
|
|
||||||
var runtimeOpts interface{}
|
|
||||||
if runtime == "io.containerd.runhcs.v1" {
|
|
||||||
runtimeOpts = &options.Options{
|
|
||||||
Debug: context.GlobalBool("debug"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cOpts = append(cOpts, containerd.WithRuntime(runtime, runtimeOpts))
|
|
||||||
|
|
||||||
var s specs.Spec
|
|
||||||
spec = containerd.WithSpec(&s, opts...)
|
|
||||||
|
|
||||||
cOpts = append(cOpts, spec)
|
|
||||||
|
|
||||||
return client.NewContainer(ctx, id, cOpts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getNewTaskOpts(_ *cli.Context) []containerd.NewTaskOpts {
|
|
||||||
return nil
|
|
||||||
}
|
|
93
vendor/github.com/containerd/containerd/cmd/ctr/commands/shim/io_unix.go
generated
vendored
93
vendor/github.com/containerd/containerd/cmd/ctr/commands/shim/io_unix.go
generated
vendored
@ -1,93 +0,0 @@
|
|||||||
// +build !windows
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright The containerd 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 shim
|
|
||||||
|
|
||||||
import (
|
|
||||||
gocontext "context"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/containerd/fifo"
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
|
||||||
|
|
||||||
var bufPool = sync.Pool{
|
|
||||||
New: func() interface{} {
|
|
||||||
buffer := make([]byte, 32<<10)
|
|
||||||
return &buffer
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func prepareStdio(stdin, stdout, stderr string, console bool) (wg *sync.WaitGroup, err error) {
|
|
||||||
wg = &sync.WaitGroup{}
|
|
||||||
ctx := gocontext.Background()
|
|
||||||
|
|
||||||
f, err := fifo.OpenFifo(ctx, stdin, unix.O_WRONLY|unix.O_CREAT|unix.O_NONBLOCK, 0700)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer func(c io.Closer) {
|
|
||||||
if err != nil {
|
|
||||||
c.Close()
|
|
||||||
}
|
|
||||||
}(f)
|
|
||||||
go func(w io.WriteCloser) {
|
|
||||||
p := bufPool.Get().(*[]byte)
|
|
||||||
defer bufPool.Put(p)
|
|
||||||
io.CopyBuffer(w, os.Stdin, *p)
|
|
||||||
w.Close()
|
|
||||||
}(f)
|
|
||||||
|
|
||||||
f, err = fifo.OpenFifo(ctx, stdout, unix.O_RDONLY|unix.O_CREAT|unix.O_NONBLOCK, 0700)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer func(c io.Closer) {
|
|
||||||
if err != nil {
|
|
||||||
c.Close()
|
|
||||||
}
|
|
||||||
}(f)
|
|
||||||
wg.Add(1)
|
|
||||||
go func(r io.ReadCloser) {
|
|
||||||
io.Copy(os.Stdout, r)
|
|
||||||
r.Close()
|
|
||||||
wg.Done()
|
|
||||||
}(f)
|
|
||||||
|
|
||||||
f, err = fifo.OpenFifo(ctx, stderr, unix.O_RDONLY|unix.O_CREAT|unix.O_NONBLOCK, 0700)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer func(c io.Closer) {
|
|
||||||
if err != nil {
|
|
||||||
c.Close()
|
|
||||||
}
|
|
||||||
}(f)
|
|
||||||
if !console {
|
|
||||||
wg.Add(1)
|
|
||||||
go func(r io.ReadCloser) {
|
|
||||||
io.Copy(os.Stderr, r)
|
|
||||||
r.Close()
|
|
||||||
wg.Done()
|
|
||||||
}(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
return wg, nil
|
|
||||||
}
|
|
258
vendor/github.com/containerd/containerd/cmd/ctr/commands/shim/shim.go
generated
vendored
258
vendor/github.com/containerd/containerd/cmd/ctr/commands/shim/shim.go
generated
vendored
@ -1,258 +0,0 @@
|
|||||||
// +build !windows
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright The containerd 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 shim
|
|
||||||
|
|
||||||
import (
|
|
||||||
gocontext "context"
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
|
||||||
"path/filepath"
|
|
||||||
|
|
||||||
"github.com/containerd/console"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/namespaces"
|
|
||||||
"github.com/containerd/containerd/runtime/v2/shim"
|
|
||||||
"github.com/containerd/containerd/runtime/v2/task"
|
|
||||||
"github.com/containerd/ttrpc"
|
|
||||||
"github.com/containerd/typeurl"
|
|
||||||
ptypes "github.com/gogo/protobuf/types"
|
|
||||||
"github.com/opencontainers/runtime-spec/specs-go"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var fifoFlags = []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "stdin",
|
|
||||||
Usage: "specify the path to the stdin fifo",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "stdout",
|
|
||||||
Usage: "specify the path to the stdout fifo",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "stderr",
|
|
||||||
Usage: "specify the path to the stderr fifo",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "tty,t",
|
|
||||||
Usage: "enable tty support",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command is the cli command for interacting with a task
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "shim",
|
|
||||||
Usage: "interact with a shim directly",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "id",
|
|
||||||
Usage: "container id",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Subcommands: []cli.Command{
|
|
||||||
deleteCommand,
|
|
||||||
execCommand,
|
|
||||||
startCommand,
|
|
||||||
stateCommand,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var startCommand = cli.Command{
|
|
||||||
Name: "start",
|
|
||||||
Usage: "start a container with a task",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
service, err := getTaskService(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = service.Start(gocontext.Background(), &task.StartRequest{
|
|
||||||
ID: context.Args().First(),
|
|
||||||
})
|
|
||||||
return err
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var deleteCommand = cli.Command{
|
|
||||||
Name: "delete",
|
|
||||||
Usage: "delete a container with a task",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
service, err := getTaskService(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
r, err := service.Delete(gocontext.Background(), &task.DeleteRequest{
|
|
||||||
ID: context.Args().First(),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Printf("container deleted and returned exit status %d\n", r.ExitStatus)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var stateCommand = cli.Command{
|
|
||||||
Name: "state",
|
|
||||||
Usage: "get the state of all the processes of the task",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
service, err := getTaskService(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
r, err := service.State(gocontext.Background(), &task.StateRequest{
|
|
||||||
ID: context.GlobalString("id"),
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
commands.PrintAsJSON(r)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var execCommand = cli.Command{
|
|
||||||
Name: "exec",
|
|
||||||
Usage: "exec a new process in the task's container",
|
|
||||||
Flags: append(fifoFlags,
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "attach,a",
|
|
||||||
Usage: "stay attached to the container and open the fifos",
|
|
||||||
},
|
|
||||||
cli.StringSliceFlag{
|
|
||||||
Name: "env,e",
|
|
||||||
Usage: "add environment vars",
|
|
||||||
Value: &cli.StringSlice{},
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "cwd",
|
|
||||||
Usage: "current working directory",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "spec",
|
|
||||||
Usage: "runtime spec",
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
service, err := getTaskService(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
id = context.Args().First()
|
|
||||||
ctx = gocontext.Background()
|
|
||||||
)
|
|
||||||
|
|
||||||
if id == "" {
|
|
||||||
return errors.New("exec id must be provided")
|
|
||||||
}
|
|
||||||
|
|
||||||
tty := context.Bool("tty")
|
|
||||||
wg, err := prepareStdio(context.String("stdin"), context.String("stdout"), context.String("stderr"), tty)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// read spec file and extract Any object
|
|
||||||
spec, err := ioutil.ReadFile(context.String("spec"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
url, err := typeurl.TypeURL(specs.Process{})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
rq := &task.ExecProcessRequest{
|
|
||||||
ID: id,
|
|
||||||
Spec: &ptypes.Any{
|
|
||||||
TypeUrl: url,
|
|
||||||
Value: spec,
|
|
||||||
},
|
|
||||||
Stdin: context.String("stdin"),
|
|
||||||
Stdout: context.String("stdout"),
|
|
||||||
Stderr: context.String("stderr"),
|
|
||||||
Terminal: tty,
|
|
||||||
}
|
|
||||||
if _, err := service.Exec(ctx, rq); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
r, err := service.Start(ctx, &task.StartRequest{
|
|
||||||
ID: id,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Printf("exec running with pid %d\n", r.Pid)
|
|
||||||
if context.Bool("attach") {
|
|
||||||
logrus.Info("attaching")
|
|
||||||
if tty {
|
|
||||||
current := console.Current()
|
|
||||||
defer current.Reset()
|
|
||||||
if err := current.SetRaw(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
size, err := current.Size()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := service.ResizePty(ctx, &task.ResizePtyRequest{
|
|
||||||
ID: id,
|
|
||||||
Width: uint32(size.Width),
|
|
||||||
Height: uint32(size.Height),
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wg.Wait()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func getTaskService(context *cli.Context) (task.TaskService, error) {
|
|
||||||
id := context.GlobalString("id")
|
|
||||||
if id == "" {
|
|
||||||
return nil, fmt.Errorf("container id must be specified")
|
|
||||||
}
|
|
||||||
ns := context.GlobalString("namespace")
|
|
||||||
|
|
||||||
// /containerd-shim/ns/id/shim.sock is the old way to generate shim socket,
|
|
||||||
// compatible it
|
|
||||||
s1 := filepath.Join(string(filepath.Separator), "containerd-shim", ns, id, "shim.sock")
|
|
||||||
// this should not error, ctr always get a default ns
|
|
||||||
ctx := namespaces.WithNamespace(gocontext.Background(), ns)
|
|
||||||
s2, _ := shim.SocketAddress(ctx, id)
|
|
||||||
|
|
||||||
for _, socket := range []string{s1, s2} {
|
|
||||||
conn, err := net.Dial("unix", "\x00"+socket)
|
|
||||||
if err == nil {
|
|
||||||
client := ttrpc.NewClient(conn)
|
|
||||||
|
|
||||||
// TODO(stevvooe): This actually leaks the connection. We were leaking it
|
|
||||||
// before, so may not be a huge deal.
|
|
||||||
|
|
||||||
return task.NewTaskClient(client), nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, fmt.Errorf("fail to connect to container %s's shim", id)
|
|
||||||
}
|
|
52
vendor/github.com/containerd/containerd/cmd/ctr/commands/signals.go
generated
vendored
52
vendor/github.com/containerd/containerd/cmd/ctr/commands/signals.go
generated
vendored
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 commands
|
|
||||||
|
|
||||||
import (
|
|
||||||
gocontext "context"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
type killer interface {
|
|
||||||
Kill(gocontext.Context, syscall.Signal, ...containerd.KillOpts) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// ForwardAllSignals forwards signals
|
|
||||||
func ForwardAllSignals(ctx gocontext.Context, task killer) chan os.Signal {
|
|
||||||
sigc := make(chan os.Signal, 128)
|
|
||||||
signal.Notify(sigc)
|
|
||||||
go func() {
|
|
||||||
for s := range sigc {
|
|
||||||
logrus.Debug("forwarding signal ", s)
|
|
||||||
if err := task.Kill(ctx, s.(syscall.Signal)); err != nil {
|
|
||||||
logrus.WithError(err).Errorf("forward signal %s", s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return sigc
|
|
||||||
}
|
|
||||||
|
|
||||||
// StopCatch stops and closes a channel
|
|
||||||
func StopCatch(sigc chan os.Signal) {
|
|
||||||
signal.Stop(sigc)
|
|
||||||
close(sigc)
|
|
||||||
}
|
|
636
vendor/github.com/containerd/containerd/cmd/ctr/commands/snapshots/snapshots.go
generated
vendored
636
vendor/github.com/containerd/containerd/cmd/ctr/commands/snapshots/snapshots.go
generated
vendored
@ -1,636 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 snapshots
|
|
||||||
|
|
||||||
import (
|
|
||||||
gocontext "context"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"text/tabwriter"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/content"
|
|
||||||
"github.com/containerd/containerd/diff"
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
"github.com/containerd/containerd/mount"
|
|
||||||
"github.com/containerd/containerd/pkg/progress"
|
|
||||||
"github.com/containerd/containerd/rootfs"
|
|
||||||
"github.com/containerd/containerd/snapshots"
|
|
||||||
digest "github.com/opencontainers/go-digest"
|
|
||||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Command is the cli command for managing snapshots
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "snapshots",
|
|
||||||
Aliases: []string{"snapshot"},
|
|
||||||
Usage: "manage snapshots",
|
|
||||||
Flags: commands.SnapshotterFlags,
|
|
||||||
Subcommands: cli.Commands{
|
|
||||||
commitCommand,
|
|
||||||
diffCommand,
|
|
||||||
infoCommand,
|
|
||||||
listCommand,
|
|
||||||
mountCommand,
|
|
||||||
prepareCommand,
|
|
||||||
removeCommand,
|
|
||||||
setLabelCommand,
|
|
||||||
treeCommand,
|
|
||||||
unpackCommand,
|
|
||||||
usageCommand,
|
|
||||||
viewCommand,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var listCommand = cli.Command{
|
|
||||||
Name: "list",
|
|
||||||
Aliases: []string{"ls"},
|
|
||||||
Usage: "list snapshots",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
var (
|
|
||||||
snapshotter = client.SnapshotService(context.GlobalString("snapshotter"))
|
|
||||||
tw = tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0)
|
|
||||||
)
|
|
||||||
fmt.Fprintln(tw, "KEY\tPARENT\tKIND\t")
|
|
||||||
if err := snapshotter.Walk(ctx, func(ctx gocontext.Context, info snapshots.Info) error {
|
|
||||||
fmt.Fprintf(tw, "%v\t%v\t%v\t\n",
|
|
||||||
info.Name,
|
|
||||||
info.Parent,
|
|
||||||
info.Kind)
|
|
||||||
return nil
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return tw.Flush()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var diffCommand = cli.Command{
|
|
||||||
Name: "diff",
|
|
||||||
Usage: "get the diff of two snapshots. the default second snapshot is the first snapshot's parent.",
|
|
||||||
ArgsUsage: "[flags] <idA> [<idB>]",
|
|
||||||
Flags: append([]cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "media-type",
|
|
||||||
Usage: "media type to use for creating diff",
|
|
||||||
Value: ocispec.MediaTypeImageLayerGzip,
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "ref",
|
|
||||||
Usage: "content upload reference to use",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "keep",
|
|
||||||
Usage: "keep diff content. up to creator to delete it.",
|
|
||||||
},
|
|
||||||
}, commands.LabelFlag),
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
idA = context.Args().First()
|
|
||||||
idB = context.Args().Get(1)
|
|
||||||
)
|
|
||||||
if idA == "" {
|
|
||||||
return errors.New("snapshot id must be provided")
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
ctx, done, err := client.WithLease(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer done(ctx)
|
|
||||||
|
|
||||||
var desc ocispec.Descriptor
|
|
||||||
labels := commands.LabelArgs(context.StringSlice("label"))
|
|
||||||
snapshotter := client.SnapshotService(context.GlobalString("snapshotter"))
|
|
||||||
|
|
||||||
fmt.Println(context.String("media-type"))
|
|
||||||
|
|
||||||
if context.Bool("keep") {
|
|
||||||
labels["containerd.io/gc.root"] = time.Now().UTC().Format(time.RFC3339)
|
|
||||||
}
|
|
||||||
opts := []diff.Opt{
|
|
||||||
diff.WithMediaType(context.String("media-type")),
|
|
||||||
diff.WithReference(context.String("ref")),
|
|
||||||
diff.WithLabels(labels),
|
|
||||||
}
|
|
||||||
|
|
||||||
if idB == "" {
|
|
||||||
desc, err = rootfs.CreateDiff(ctx, idA, snapshotter, client.DiffService(), opts...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
var a, b []mount.Mount
|
|
||||||
ds := client.DiffService()
|
|
||||||
|
|
||||||
a, err = getMounts(ctx, idA, snapshotter)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
b, err = getMounts(ctx, idB, snapshotter)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
desc, err = ds.Compare(ctx, a, b, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ra, err := client.ContentStore().ReaderAt(ctx, desc)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = io.Copy(os.Stdout, content.NewReader(ra))
|
|
||||||
|
|
||||||
return err
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func getMounts(ctx gocontext.Context, id string, sn snapshots.Snapshotter) ([]mount.Mount, error) {
|
|
||||||
var mounts []mount.Mount
|
|
||||||
info, err := sn.Stat(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if info.Kind == snapshots.KindActive {
|
|
||||||
mounts, err = sn.Mounts(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
key := fmt.Sprintf("%s-view-key", id)
|
|
||||||
mounts, err = sn.View(ctx, key, id)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer sn.Remove(ctx, key)
|
|
||||||
}
|
|
||||||
return mounts, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var usageCommand = cli.Command{
|
|
||||||
Name: "usage",
|
|
||||||
Usage: "usage snapshots",
|
|
||||||
ArgsUsage: "[flags] [<key>, ...]",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "b",
|
|
||||||
Usage: "display size in bytes",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var displaySize func(int64) string
|
|
||||||
if context.Bool("b") {
|
|
||||||
displaySize = func(s int64) string {
|
|
||||||
return fmt.Sprintf("%d", s)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
displaySize = func(s int64) string {
|
|
||||||
return progress.Bytes(s).String()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
var (
|
|
||||||
snapshotter = client.SnapshotService(context.GlobalString("snapshotter"))
|
|
||||||
tw = tabwriter.NewWriter(os.Stdout, 1, 8, 1, ' ', 0)
|
|
||||||
)
|
|
||||||
fmt.Fprintln(tw, "KEY\tSIZE\tINODES\t")
|
|
||||||
if context.NArg() == 0 {
|
|
||||||
if err := snapshotter.Walk(ctx, func(ctx gocontext.Context, info snapshots.Info) error {
|
|
||||||
usage, err := snapshotter.Usage(ctx, info.Name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Fprintf(tw, "%v\t%s\t%d\t\n", info.Name, displaySize(usage.Size), usage.Inodes)
|
|
||||||
return nil
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, id := range context.Args() {
|
|
||||||
usage, err := snapshotter.Usage(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Fprintf(tw, "%v\t%s\t%d\t\n", id, displaySize(usage.Size), usage.Inodes)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return tw.Flush()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var removeCommand = cli.Command{
|
|
||||||
Name: "remove",
|
|
||||||
Aliases: []string{"rm"},
|
|
||||||
ArgsUsage: "<key> [<key>, ...]",
|
|
||||||
Usage: "remove snapshots",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
snapshotter := client.SnapshotService(context.GlobalString("snapshotter"))
|
|
||||||
for _, key := range context.Args() {
|
|
||||||
err = snapshotter.Remove(ctx, key)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrapf(err, "failed to remove %q", key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var prepareCommand = cli.Command{
|
|
||||||
Name: "prepare",
|
|
||||||
Usage: "prepare a snapshot from a committed snapshot",
|
|
||||||
ArgsUsage: "[flags] <key> [<parent>]",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "target, t",
|
|
||||||
Usage: "mount target path, will print mount, if provided",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
if narg := context.NArg(); narg < 1 || narg > 2 {
|
|
||||||
return cli.ShowSubcommandHelp(context)
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
target = context.String("target")
|
|
||||||
key = context.Args().Get(0)
|
|
||||||
parent = context.Args().Get(1)
|
|
||||||
)
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
snapshotter := client.SnapshotService(context.GlobalString("snapshotter"))
|
|
||||||
labels := map[string]string{
|
|
||||||
"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339),
|
|
||||||
}
|
|
||||||
|
|
||||||
mounts, err := snapshotter.Prepare(ctx, key, parent, snapshots.WithLabels(labels))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if target != "" {
|
|
||||||
printMounts(target, mounts)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var viewCommand = cli.Command{
|
|
||||||
Name: "view",
|
|
||||||
Usage: "create a read-only snapshot from a committed snapshot",
|
|
||||||
ArgsUsage: "[flags] <key> [<parent>]",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "target, t",
|
|
||||||
Usage: "mount target path, will print mount, if provided",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
if narg := context.NArg(); narg < 1 || narg > 2 {
|
|
||||||
return cli.ShowSubcommandHelp(context)
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
target = context.String("target")
|
|
||||||
key = context.Args().Get(0)
|
|
||||||
parent = context.Args().Get(1)
|
|
||||||
)
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
snapshotter := client.SnapshotService(context.GlobalString("snapshotter"))
|
|
||||||
mounts, err := snapshotter.View(ctx, key, parent)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if target != "" {
|
|
||||||
printMounts(target, mounts)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var mountCommand = cli.Command{
|
|
||||||
Name: "mounts",
|
|
||||||
Aliases: []string{"m", "mount"},
|
|
||||||
Usage: "mount gets mount commands for the snapshots",
|
|
||||||
ArgsUsage: "<target> <key>",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
if context.NArg() != 2 {
|
|
||||||
return cli.ShowSubcommandHelp(context)
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
target = context.Args().Get(0)
|
|
||||||
key = context.Args().Get(1)
|
|
||||||
)
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
snapshotter := client.SnapshotService(context.GlobalString("snapshotter"))
|
|
||||||
mounts, err := snapshotter.Mounts(ctx, key)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
printMounts(target, mounts)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var commitCommand = cli.Command{
|
|
||||||
Name: "commit",
|
|
||||||
Usage: "commit an active snapshot into the provided name",
|
|
||||||
ArgsUsage: "<key> <active>",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
if context.NArg() != 2 {
|
|
||||||
return cli.ShowSubcommandHelp(context)
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
key = context.Args().Get(0)
|
|
||||||
active = context.Args().Get(1)
|
|
||||||
)
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
snapshotter := client.SnapshotService(context.GlobalString("snapshotter"))
|
|
||||||
labels := map[string]string{
|
|
||||||
"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339),
|
|
||||||
}
|
|
||||||
return snapshotter.Commit(ctx, key, active, snapshots.WithLabels(labels))
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var treeCommand = cli.Command{
|
|
||||||
Name: "tree",
|
|
||||||
Usage: "display tree view of snapshot branches",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
var (
|
|
||||||
snapshotter = client.SnapshotService(context.GlobalString("snapshotter"))
|
|
||||||
tree = newSnapshotTree()
|
|
||||||
)
|
|
||||||
|
|
||||||
if err := snapshotter.Walk(ctx, func(ctx gocontext.Context, info snapshots.Info) error {
|
|
||||||
// Get or create node and add node details
|
|
||||||
tree.add(info)
|
|
||||||
return nil
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
printTree(tree)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var infoCommand = cli.Command{
|
|
||||||
Name: "info",
|
|
||||||
Usage: "get info about a snapshot",
|
|
||||||
ArgsUsage: "<key>",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
if context.NArg() != 1 {
|
|
||||||
return cli.ShowSubcommandHelp(context)
|
|
||||||
}
|
|
||||||
|
|
||||||
key := context.Args().Get(0)
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
snapshotter := client.SnapshotService(context.GlobalString("snapshotter"))
|
|
||||||
info, err := snapshotter.Stat(ctx, key)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
commands.PrintAsJSON(info)
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var setLabelCommand = cli.Command{
|
|
||||||
Name: "label",
|
|
||||||
Usage: "add labels to content",
|
|
||||||
ArgsUsage: "<name> [<label>=<value> ...]",
|
|
||||||
Description: "labels snapshots in the snapshotter",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
key, labels := commands.ObjectWithLabelArgs(context)
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
snapshotter := client.SnapshotService(context.GlobalString("snapshotter"))
|
|
||||||
|
|
||||||
info := snapshots.Info{
|
|
||||||
Name: key,
|
|
||||||
Labels: map[string]string{},
|
|
||||||
}
|
|
||||||
|
|
||||||
var paths []string
|
|
||||||
for k, v := range labels {
|
|
||||||
paths = append(paths, fmt.Sprintf("labels.%s", k))
|
|
||||||
if v != "" {
|
|
||||||
info.Labels[k] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nothing updated, do no clear
|
|
||||||
if len(paths) == 0 {
|
|
||||||
info, err = snapshotter.Stat(ctx, info.Name)
|
|
||||||
} else {
|
|
||||||
info, err = snapshotter.Update(ctx, info, paths...)
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var labelStrings []string
|
|
||||||
for k, v := range info.Labels {
|
|
||||||
labelStrings = append(labelStrings, fmt.Sprintf("%s=%s", k, v))
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(strings.Join(labelStrings, ","))
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var unpackCommand = cli.Command{
|
|
||||||
Name: "unpack",
|
|
||||||
Usage: "unpack applies layers from a manifest to a snapshot",
|
|
||||||
ArgsUsage: "[flags] <digest>",
|
|
||||||
Flags: commands.SnapshotterFlags,
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
dgst, err := digest.Parse(context.Args().First())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
log.G(ctx).Debugf("unpacking layers from manifest %s", dgst.String())
|
|
||||||
// TODO: Support unpack by name
|
|
||||||
images, err := client.ListImages(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var unpacked bool
|
|
||||||
for _, image := range images {
|
|
||||||
if image.Target().Digest == dgst {
|
|
||||||
fmt.Printf("unpacking %s (%s)...", dgst, image.Target().MediaType)
|
|
||||||
if err := image.Unpack(ctx, context.String("snapshotter")); err != nil {
|
|
||||||
fmt.Println()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Println("done")
|
|
||||||
unpacked = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !unpacked {
|
|
||||||
return errors.New("manifest not found")
|
|
||||||
}
|
|
||||||
// TODO: Get rootfs from Image
|
|
||||||
//log.G(ctx).Infof("chain ID: %s", chainID.String())
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
type snapshotTree struct {
|
|
||||||
nodes []*snapshotTreeNode
|
|
||||||
index map[string]*snapshotTreeNode
|
|
||||||
}
|
|
||||||
|
|
||||||
func newSnapshotTree() *snapshotTree {
|
|
||||||
return &snapshotTree{
|
|
||||||
index: make(map[string]*snapshotTreeNode),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type snapshotTreeNode struct {
|
|
||||||
info snapshots.Info
|
|
||||||
children []string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (st *snapshotTree) add(info snapshots.Info) *snapshotTreeNode {
|
|
||||||
entry, ok := st.index[info.Name]
|
|
||||||
if !ok {
|
|
||||||
entry = &snapshotTreeNode{info: info}
|
|
||||||
st.nodes = append(st.nodes, entry)
|
|
||||||
st.index[info.Name] = entry
|
|
||||||
} else {
|
|
||||||
entry.info = info // update info if we created placeholder
|
|
||||||
}
|
|
||||||
|
|
||||||
if info.Parent != "" {
|
|
||||||
pn := st.get(info.Parent)
|
|
||||||
if pn == nil {
|
|
||||||
// create a placeholder
|
|
||||||
pn = st.add(snapshots.Info{Name: info.Parent})
|
|
||||||
}
|
|
||||||
|
|
||||||
pn.children = append(pn.children, info.Name)
|
|
||||||
}
|
|
||||||
return entry
|
|
||||||
}
|
|
||||||
|
|
||||||
func (st *snapshotTree) get(name string) *snapshotTreeNode {
|
|
||||||
return st.index[name]
|
|
||||||
}
|
|
||||||
|
|
||||||
func printTree(st *snapshotTree) {
|
|
||||||
for _, node := range st.nodes {
|
|
||||||
// Print for root(parent-less) nodes only
|
|
||||||
if node.info.Parent == "" {
|
|
||||||
printNode(node.info.Name, st, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func printNode(name string, tree *snapshotTree, level int) {
|
|
||||||
node := tree.index[name]
|
|
||||||
prefix := strings.Repeat(" ", level)
|
|
||||||
|
|
||||||
if level > 0 {
|
|
||||||
prefix += "\\_"
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf(prefix+" %s\n", node.info.Name)
|
|
||||||
level++
|
|
||||||
for _, child := range node.children {
|
|
||||||
printNode(child, tree, level)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func printMounts(target string, mounts []mount.Mount) {
|
|
||||||
// FIXME: This is specific to Unix
|
|
||||||
for _, m := range mounts {
|
|
||||||
fmt.Printf("mount -t %s %s %s -o %s\n", m.Type, m.Source, target, strings.Join(m.Options, ","))
|
|
||||||
}
|
|
||||||
}
|
|
86
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/attach.go
generated
vendored
86
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/attach.go
generated
vendored
@ -1,86 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 tasks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/containerd/console"
|
|
||||||
"github.com/containerd/containerd/cio"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var attachCommand = cli.Command{
|
|
||||||
Name: "attach",
|
|
||||||
Usage: "attach to the IO of a running container",
|
|
||||||
ArgsUsage: "CONTAINER",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
container, err := client.LoadContainer(ctx, context.Args().First())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
spec, err := container.Spec(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
con console.Console
|
|
||||||
tty = spec.Process.Terminal
|
|
||||||
)
|
|
||||||
if tty {
|
|
||||||
con = console.Current()
|
|
||||||
defer con.Reset()
|
|
||||||
if err := con.SetRaw(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
task, err := container.Task(ctx, cio.NewAttach(cio.WithStdio))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer task.Delete(ctx)
|
|
||||||
|
|
||||||
statusC, err := task.Wait(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if tty {
|
|
||||||
if err := HandleConsoleResize(ctx, task, con); err != nil {
|
|
||||||
logrus.WithError(err).Error("console resize")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sigc := commands.ForwardAllSignals(ctx, task)
|
|
||||||
defer commands.StopCatch(sigc)
|
|
||||||
}
|
|
||||||
|
|
||||||
ec := <-statusC
|
|
||||||
code, _, err := ec.Result()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if code != 0 {
|
|
||||||
return cli.NewExitError("", int(code))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
123
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/checkpoint.go
generated
vendored
123
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/checkpoint.go
generated
vendored
@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 tasks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/plugin"
|
|
||||||
"github.com/containerd/containerd/runtime/linux/runctypes"
|
|
||||||
"github.com/containerd/containerd/runtime/v2/runc/options"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var checkpointCommand = cli.Command{
|
|
||||||
Name: "checkpoint",
|
|
||||||
Usage: "checkpoint a container",
|
|
||||||
ArgsUsage: "[flags] CONTAINER",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "exit",
|
|
||||||
Usage: "stop the container after the checkpoint",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "image-path",
|
|
||||||
Usage: "path to criu image files",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "work-path",
|
|
||||||
Usage: "path to criu work files and logs",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
id := context.Args().First()
|
|
||||||
if id == "" {
|
|
||||||
return errors.New("container id must be provided")
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context, containerd.WithDefaultRuntime(context.String("runtime")))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
container, err := client.LoadContainer(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
task, err := container.Task(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
info, err := container.Info(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
opts := []containerd.CheckpointTaskOpts{withCheckpointOpts(info.Runtime.Name, context)}
|
|
||||||
checkpoint, err := task.Checkpoint(ctx, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if context.String("image-path") == "" {
|
|
||||||
fmt.Println(checkpoint.Name())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// withCheckpointOpts only suitable for runc runtime now
|
|
||||||
func withCheckpointOpts(rt string, context *cli.Context) containerd.CheckpointTaskOpts {
|
|
||||||
return func(r *containerd.CheckpointTaskInfo) error {
|
|
||||||
imagePath := context.String("image-path")
|
|
||||||
workPath := context.String("work-path")
|
|
||||||
|
|
||||||
switch rt {
|
|
||||||
case plugin.RuntimeRuncV1, plugin.RuntimeRuncV2:
|
|
||||||
if r.Options == nil {
|
|
||||||
r.Options = &options.CheckpointOptions{}
|
|
||||||
}
|
|
||||||
opts, _ := r.Options.(*options.CheckpointOptions)
|
|
||||||
|
|
||||||
if context.Bool("exit") {
|
|
||||||
opts.Exit = true
|
|
||||||
}
|
|
||||||
if imagePath != "" {
|
|
||||||
opts.ImagePath = imagePath
|
|
||||||
}
|
|
||||||
if workPath != "" {
|
|
||||||
opts.WorkPath = workPath
|
|
||||||
}
|
|
||||||
case plugin.RuntimeLinuxV1:
|
|
||||||
if r.Options == nil {
|
|
||||||
r.Options = &runctypes.CheckpointOptions{}
|
|
||||||
}
|
|
||||||
opts, _ := r.Options.(*runctypes.CheckpointOptions)
|
|
||||||
|
|
||||||
if context.Bool("exit") {
|
|
||||||
opts.Exit = true
|
|
||||||
}
|
|
||||||
if imagePath != "" {
|
|
||||||
opts.ImagePath = imagePath
|
|
||||||
}
|
|
||||||
if workPath != "" {
|
|
||||||
opts.WorkPath = workPath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
85
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/delete.go
generated
vendored
85
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/delete.go
generated
vendored
@ -1,85 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 tasks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/cio"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var deleteCommand = cli.Command{
|
|
||||||
Name: "delete",
|
|
||||||
Usage: "[flags] delete a task",
|
|
||||||
ArgsUsage: "CONTAINER",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "force, f",
|
|
||||||
Usage: "force delete task process",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "exec-id",
|
|
||||||
Usage: "process ID to kill",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
execID = context.String("exec-id")
|
|
||||||
force = context.Bool("force")
|
|
||||||
)
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
container, err := client.LoadContainer(ctx, context.Args().First())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
task, err := container.Task(ctx, cio.Load)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var opts []containerd.ProcessDeleteOpts
|
|
||||||
if force {
|
|
||||||
opts = append(opts, containerd.WithProcessKill)
|
|
||||||
}
|
|
||||||
if execID != "" {
|
|
||||||
p, err := task.LoadProcess(ctx, execID, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
status, err := p.Delete(ctx, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if ec := status.ExitCode(); ec != 0 {
|
|
||||||
return cli.NewExitError("", int(ec))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
status, err := task.Delete(ctx, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if ec := status.ExitCode(); ec != 0 {
|
|
||||||
return cli.NewExitError("", int(ec))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
143
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/exec.go
generated
vendored
143
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/exec.go
generated
vendored
@ -1,143 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 tasks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
|
|
||||||
"github.com/containerd/console"
|
|
||||||
"github.com/containerd/containerd/cio"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
//TODO:(jessvalarezo) exec-id is optional here, update to required arg
|
|
||||||
var execCommand = cli.Command{
|
|
||||||
Name: "exec",
|
|
||||||
Usage: "execute additional processes in an existing container",
|
|
||||||
ArgsUsage: "[flags] CONTAINER CMD [ARG...]",
|
|
||||||
SkipArgReorder: true,
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "cwd",
|
|
||||||
Usage: "working directory of the new process",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "tty,t",
|
|
||||||
Usage: "allocate a TTY for the container",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "detach,d",
|
|
||||||
Usage: "detach from the task after it has started execution",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "exec-id",
|
|
||||||
Usage: "exec specific id for the process",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "fifo-dir",
|
|
||||||
Usage: "directory used for storing IO FIFOs",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
id = context.Args().First()
|
|
||||||
args = context.Args().Tail()
|
|
||||||
tty = context.Bool("tty")
|
|
||||||
detach = context.Bool("detach")
|
|
||||||
)
|
|
||||||
if id == "" {
|
|
||||||
return errors.New("container id must be provided")
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
container, err := client.LoadContainer(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
spec, err := container.Spec(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
task, err := container.Task(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
pspec := spec.Process
|
|
||||||
pspec.Terminal = tty
|
|
||||||
pspec.Args = args
|
|
||||||
|
|
||||||
cioOpts := []cio.Opt{cio.WithStdio, cio.WithFIFODir(context.String("fifo-dir"))}
|
|
||||||
if tty {
|
|
||||||
cioOpts = append(cioOpts, cio.WithTerminal)
|
|
||||||
}
|
|
||||||
ioCreator := cio.NewCreator(cioOpts...)
|
|
||||||
process, err := task.Exec(ctx, context.String("exec-id"), pspec, ioCreator)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// if detach, we should not call this defer
|
|
||||||
if !detach {
|
|
||||||
defer process.Delete(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
statusC, err := process.Wait(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var con console.Console
|
|
||||||
if tty {
|
|
||||||
con = console.Current()
|
|
||||||
defer con.Reset()
|
|
||||||
if err := con.SetRaw(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !detach {
|
|
||||||
if tty {
|
|
||||||
if err := HandleConsoleResize(ctx, process, con); err != nil {
|
|
||||||
logrus.WithError(err).Error("console resize")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sigc := commands.ForwardAllSignals(ctx, process)
|
|
||||||
defer commands.StopCatch(sigc)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := process.Start(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if detach {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
status := <-statusC
|
|
||||||
code, _, err := status.Result()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if code != 0 {
|
|
||||||
return cli.NewExitError("", int(code))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
96
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/kill.go
generated
vendored
96
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/kill.go
generated
vendored
@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 tasks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
const defaultSignal = "SIGTERM"
|
|
||||||
|
|
||||||
var killCommand = cli.Command{
|
|
||||||
Name: "kill",
|
|
||||||
Usage: "signal a container (default: SIGTERM)",
|
|
||||||
ArgsUsage: "[flags] CONTAINER",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "signal, s",
|
|
||||||
Value: "",
|
|
||||||
Usage: "signal to send to the container",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "exec-id",
|
|
||||||
Usage: "process ID to kill",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "all, a",
|
|
||||||
Usage: "send signal to all processes inside the container",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
id := context.Args().First()
|
|
||||||
if id == "" {
|
|
||||||
return errors.New("container id must be provided")
|
|
||||||
}
|
|
||||||
signal, err := containerd.ParseSignal(defaultSignal)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
all = context.Bool("all")
|
|
||||||
execID = context.String("exec-id")
|
|
||||||
opts []containerd.KillOpts
|
|
||||||
)
|
|
||||||
if all && execID != "" {
|
|
||||||
return errors.New("specify an exec-id or all; not both")
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
if all {
|
|
||||||
opts = append(opts, containerd.WithKillAll)
|
|
||||||
}
|
|
||||||
if execID != "" {
|
|
||||||
opts = append(opts, containerd.WithKillExecID(execID))
|
|
||||||
}
|
|
||||||
container, err := client.LoadContainer(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if context.String("signal") != "" {
|
|
||||||
signal, err = containerd.ParseSignal(context.String("signal"))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
signal, err = containerd.GetStopSignal(ctx, container, signal)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
task, err := container.Task(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return task.Kill(ctx, signal, opts...)
|
|
||||||
},
|
|
||||||
}
|
|
71
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/list.go
generated
vendored
71
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/list.go
generated
vendored
@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 tasks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"text/tabwriter"
|
|
||||||
|
|
||||||
tasks "github.com/containerd/containerd/api/services/tasks/v1"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var listCommand = cli.Command{
|
|
||||||
Name: "list",
|
|
||||||
Usage: "list tasks",
|
|
||||||
Aliases: []string{"ls"},
|
|
||||||
ArgsUsage: "[flags]",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "quiet, q",
|
|
||||||
Usage: "print only the task id",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
quiet := context.Bool("quiet")
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
s := client.TaskService()
|
|
||||||
response, err := s.List(ctx, &tasks.ListTasksRequest{})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if quiet {
|
|
||||||
for _, task := range response.Tasks {
|
|
||||||
fmt.Println(task.ID)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
w := tabwriter.NewWriter(os.Stdout, 4, 8, 4, ' ', 0)
|
|
||||||
fmt.Fprintln(w, "TASK\tPID\tSTATUS\t")
|
|
||||||
for _, task := range response.Tasks {
|
|
||||||
if _, err := fmt.Fprintf(w, "%s\t%d\t%s\n",
|
|
||||||
task.ID,
|
|
||||||
task.Pid,
|
|
||||||
task.Status.String(),
|
|
||||||
); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return w.Flush()
|
|
||||||
},
|
|
||||||
}
|
|
117
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/metrics.go
generated
vendored
117
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/metrics.go
generated
vendored
@ -1,117 +0,0 @@
|
|||||||
// +build linux
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright The containerd 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 tasks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"text/tabwriter"
|
|
||||||
|
|
||||||
"github.com/containerd/cgroups"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/typeurl"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// metricsCommand is only added on Linux as github.com/containerd/cgroups
|
|
||||||
// does not compile on darwin or windows
|
|
||||||
Command.Subcommands = append(Command.Subcommands, metricsCommand)
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
formatFlag = "format"
|
|
||||||
formatTable = "table"
|
|
||||||
formatJSON = "json"
|
|
||||||
)
|
|
||||||
|
|
||||||
var metricsCommand = cli.Command{
|
|
||||||
Name: "metrics",
|
|
||||||
Usage: "get a single data point of metrics for a task with the built-in Linux runtime",
|
|
||||||
ArgsUsage: "CONTAINER",
|
|
||||||
Aliases: []string{"metric"},
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: formatFlag,
|
|
||||||
Usage: `"table" or "json"`,
|
|
||||||
Value: formatTable,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
container, err := client.LoadContainer(ctx, context.Args().First())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
task, err := container.Task(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
metric, err := task.Metrics(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
anydata, err := typeurl.UnmarshalAny(metric.Data)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
data, ok := anydata.(*cgroups.Metrics)
|
|
||||||
if !ok {
|
|
||||||
return errors.New("cannot convert metric data to cgroups.Metrics")
|
|
||||||
}
|
|
||||||
|
|
||||||
switch context.String(formatFlag) {
|
|
||||||
case formatTable:
|
|
||||||
w := tabwriter.NewWriter(os.Stdout, 1, 8, 4, ' ', 0)
|
|
||||||
fmt.Fprintf(w, "ID\tTIMESTAMP\t\n")
|
|
||||||
fmt.Fprintf(w, "%s\t%s\t\n\n", metric.ID, metric.Timestamp)
|
|
||||||
|
|
||||||
fmt.Fprintf(w, "METRIC\tVALUE\t\n")
|
|
||||||
if data.Memory != nil {
|
|
||||||
fmt.Fprintf(w, "memory.usage_in_bytes\t%d\t\n", data.Memory.Usage.Usage)
|
|
||||||
fmt.Fprintf(w, "memory.limit_in_bytes\t%d\t\n", data.Memory.Usage.Limit)
|
|
||||||
fmt.Fprintf(w, "memory.stat.cache\t%d\t\n", data.Memory.TotalCache)
|
|
||||||
}
|
|
||||||
if data.CPU != nil {
|
|
||||||
fmt.Fprintf(w, "cpuacct.usage\t%d\t\n", data.CPU.Usage.Total)
|
|
||||||
fmt.Fprintf(w, "cpuacct.usage_percpu\t%v\t\n", data.CPU.Usage.PerCPU)
|
|
||||||
}
|
|
||||||
if data.Pids != nil {
|
|
||||||
fmt.Fprintf(w, "pids.current\t%v\t\n", data.Pids.Current)
|
|
||||||
fmt.Fprintf(w, "pids.limit\t%v\t\n", data.Pids.Limit)
|
|
||||||
}
|
|
||||||
return w.Flush()
|
|
||||||
case formatJSON:
|
|
||||||
marshaledJSON, err := json.MarshalIndent(data, "", " ")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Println(string(marshaledJSON))
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
return errors.New("format must be table or json")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
44
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/pause.go
generated
vendored
44
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/pause.go
generated
vendored
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 tasks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var pauseCommand = cli.Command{
|
|
||||||
Name: "pause",
|
|
||||||
Usage: "pause an existing container",
|
|
||||||
ArgsUsage: "CONTAINER",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
container, err := client.LoadContainer(ctx, context.Args().First())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
task, err := container.Task(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return task.Pause(ctx)
|
|
||||||
},
|
|
||||||
}
|
|
72
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/ps.go
generated
vendored
72
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/ps.go
generated
vendored
@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 tasks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"text/tabwriter"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/typeurl"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var psCommand = cli.Command{
|
|
||||||
Name: "ps",
|
|
||||||
Usage: "list processes for container",
|
|
||||||
ArgsUsage: "CONTAINER",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
id := context.Args().First()
|
|
||||||
if id == "" {
|
|
||||||
return errors.New("container id must be provided")
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
container, err := client.LoadContainer(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
task, err := container.Task(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
processes, err := task.Pids(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w := tabwriter.NewWriter(os.Stdout, 1, 8, 4, ' ', 0)
|
|
||||||
fmt.Fprintln(w, "PID\tINFO")
|
|
||||||
for _, ps := range processes {
|
|
||||||
var info interface{} = "-"
|
|
||||||
if ps.Info != nil {
|
|
||||||
info, err = typeurl.UnmarshalAny(ps.Info)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if _, err := fmt.Fprintf(w, "%d\t%+v\n", ps.Pid, info); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return w.Flush()
|
|
||||||
},
|
|
||||||
}
|
|
44
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/resume.go
generated
vendored
44
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/resume.go
generated
vendored
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 tasks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var resumeCommand = cli.Command{
|
|
||||||
Name: "resume",
|
|
||||||
Usage: "resume a paused container",
|
|
||||||
ArgsUsage: "CONTAINER",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
container, err := client.LoadContainer(ctx, context.Args().First())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
task, err := container.Task(ctx, nil)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return task.Resume(ctx)
|
|
||||||
},
|
|
||||||
}
|
|
137
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/start.go
generated
vendored
137
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/start.go
generated
vendored
@ -1,137 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 tasks
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/containerd/console"
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/cio"
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
var startCommand = cli.Command{
|
|
||||||
Name: "start",
|
|
||||||
Usage: "start a container that have been created",
|
|
||||||
ArgsUsage: "CONTAINER",
|
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "null-io",
|
|
||||||
Usage: "send all IO to /dev/null",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "log-uri",
|
|
||||||
Usage: "log uri",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "fifo-dir",
|
|
||||||
Usage: "directory used for storing IO FIFOs",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "pid-file",
|
|
||||||
Usage: "file path to write the task's pid",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "detach,d",
|
|
||||||
Usage: "detach from the task after it has started execution",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
id = context.Args().Get(0)
|
|
||||||
detach = context.Bool("detach")
|
|
||||||
)
|
|
||||||
if id == "" {
|
|
||||||
return errors.New("container id must be provided")
|
|
||||||
}
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
container, err := client.LoadContainer(ctx, id)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
spec, err := container.Spec(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
tty = spec.Process.Terminal
|
|
||||||
opts = getNewTaskOpts(context)
|
|
||||||
ioOpts = []cio.Opt{cio.WithFIFODir(context.String("fifo-dir"))}
|
|
||||||
)
|
|
||||||
var con console.Console
|
|
||||||
if tty {
|
|
||||||
con = console.Current()
|
|
||||||
defer con.Reset()
|
|
||||||
if err := con.SetRaw(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
task, err := NewTask(ctx, client, container, "", con, context.Bool("null-io"), context.String("log-uri"), ioOpts, opts...)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var statusC <-chan containerd.ExitStatus
|
|
||||||
if !detach {
|
|
||||||
defer task.Delete(ctx)
|
|
||||||
if statusC, err = task.Wait(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if context.IsSet("pid-file") {
|
|
||||||
if err := commands.WritePidFile(context.String("pid-file"), int(task.Pid())); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := task.Start(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if detach {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if tty {
|
|
||||||
if err := HandleConsoleResize(ctx, task, con); err != nil {
|
|
||||||
logrus.WithError(err).Error("console resize")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sigc := commands.ForwardAllSignals(ctx, task)
|
|
||||||
defer commands.StopCatch(sigc)
|
|
||||||
}
|
|
||||||
|
|
||||||
status := <-statusC
|
|
||||||
code, _, err := status.Result()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if _, err := task.Delete(ctx); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if code != 0 {
|
|
||||||
return cli.NewExitError("", int(code))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
46
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/tasks.go
generated
vendored
46
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/tasks.go
generated
vendored
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 tasks
|
|
||||||
|
|
||||||
import (
|
|
||||||
gocontext "context"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
type resizer interface {
|
|
||||||
Resize(ctx gocontext.Context, w, h uint32) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command is the cli command for managing tasks
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "tasks",
|
|
||||||
Usage: "manage tasks",
|
|
||||||
Aliases: []string{"t", "task"},
|
|
||||||
Subcommands: []cli.Command{
|
|
||||||
attachCommand,
|
|
||||||
checkpointCommand,
|
|
||||||
deleteCommand,
|
|
||||||
execCommand,
|
|
||||||
listCommand,
|
|
||||||
killCommand,
|
|
||||||
pauseCommand,
|
|
||||||
psCommand,
|
|
||||||
resumeCommand,
|
|
||||||
startCommand,
|
|
||||||
},
|
|
||||||
}
|
|
105
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/tasks_unix.go
generated
vendored
105
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/tasks_unix.go
generated
vendored
@ -1,105 +0,0 @@
|
|||||||
// +build !windows
|
|
||||||
|
|
||||||
/*
|
|
||||||
Copyright The containerd 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 tasks
|
|
||||||
|
|
||||||
import (
|
|
||||||
gocontext "context"
|
|
||||||
"net/url"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
|
|
||||||
"github.com/containerd/console"
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/cio"
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
"golang.org/x/sys/unix"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
startCommand.Flags = append(startCommand.Flags, cli.BoolFlag{
|
|
||||||
Name: "no-pivot",
|
|
||||||
Usage: "disable use of pivot-root (linux only)",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleConsoleResize resizes the console
|
|
||||||
func HandleConsoleResize(ctx gocontext.Context, task resizer, con console.Console) error {
|
|
||||||
// do an initial resize of the console
|
|
||||||
size, err := con.Size()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := task.Resize(ctx, uint32(size.Width), uint32(size.Height)); err != nil {
|
|
||||||
log.G(ctx).WithError(err).Error("resize pty")
|
|
||||||
}
|
|
||||||
s := make(chan os.Signal, 16)
|
|
||||||
signal.Notify(s, unix.SIGWINCH)
|
|
||||||
go func() {
|
|
||||||
for range s {
|
|
||||||
size, err := con.Size()
|
|
||||||
if err != nil {
|
|
||||||
log.G(ctx).WithError(err).Error("get pty size")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if err := task.Resize(ctx, uint32(size.Width), uint32(size.Height)); err != nil {
|
|
||||||
log.G(ctx).WithError(err).Error("resize pty")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewTask creates a new task
|
|
||||||
func NewTask(ctx gocontext.Context, client *containerd.Client, container containerd.Container, checkpoint string, con console.Console, nullIO bool, logURI string, ioOpts []cio.Opt, opts ...containerd.NewTaskOpts) (containerd.Task, error) {
|
|
||||||
stdio := cio.NewCreator(append([]cio.Opt{cio.WithStdio}, ioOpts...)...)
|
|
||||||
if checkpoint != "" {
|
|
||||||
im, err := client.GetImage(ctx, checkpoint)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
opts = append(opts, containerd.WithTaskCheckpoint(im))
|
|
||||||
}
|
|
||||||
ioCreator := stdio
|
|
||||||
if con != nil {
|
|
||||||
ioCreator = cio.NewCreator(append([]cio.Opt{cio.WithStreams(con, con, nil), cio.WithTerminal}, ioOpts...)...)
|
|
||||||
}
|
|
||||||
if nullIO {
|
|
||||||
if con != nil {
|
|
||||||
return nil, errors.New("tty and null-io cannot be used together")
|
|
||||||
}
|
|
||||||
ioCreator = cio.NullIO
|
|
||||||
}
|
|
||||||
if logURI != "" {
|
|
||||||
u, err := url.Parse(logURI)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
ioCreator = cio.LogURI(u)
|
|
||||||
}
|
|
||||||
return container.NewTask(ctx, ioCreator, opts...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getNewTaskOpts(context *cli.Context) []containerd.NewTaskOpts {
|
|
||||||
if context.Bool("no-pivot") {
|
|
||||||
return []containerd.NewTaskOpts{containerd.WithNoPivotRoot}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
78
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/tasks_windows.go
generated
vendored
78
vendor/github.com/containerd/containerd/cmd/ctr/commands/tasks/tasks_windows.go
generated
vendored
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 tasks
|
|
||||||
|
|
||||||
import (
|
|
||||||
gocontext "context"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/containerd/console"
|
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/cio"
|
|
||||||
"github.com/containerd/containerd/log"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
// HandleConsoleResize resizes the console
|
|
||||||
func HandleConsoleResize(ctx gocontext.Context, task resizer, con console.Console) error {
|
|
||||||
// do an initial resize of the console
|
|
||||||
size, err := con.Size()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
prevSize := size
|
|
||||||
for {
|
|
||||||
time.Sleep(time.Millisecond * 250)
|
|
||||||
|
|
||||||
size, err := con.Size()
|
|
||||||
if err != nil {
|
|
||||||
log.G(ctx).WithError(err).Error("get pty size")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if size.Width != prevSize.Width || size.Height != prevSize.Height {
|
|
||||||
if err := task.Resize(ctx, uint32(size.Width), uint32(size.Height)); err != nil {
|
|
||||||
log.G(ctx).WithError(err).Error("resize pty")
|
|
||||||
}
|
|
||||||
prevSize = size
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewTask creates a new task
|
|
||||||
func NewTask(ctx gocontext.Context, client *containerd.Client, container containerd.Container, _ string, con console.Console, nullIO bool, logURI string, ioOpts []cio.Opt, opts ...containerd.NewTaskOpts) (containerd.Task, error) {
|
|
||||||
var ioCreator cio.Creator
|
|
||||||
if con != nil {
|
|
||||||
if nullIO {
|
|
||||||
return nil, errors.New("tty and null-io cannot be used together")
|
|
||||||
}
|
|
||||||
ioCreator = cio.NewCreator(append([]cio.Opt{cio.WithStreams(con, con, nil), cio.WithTerminal}, ioOpts...)...)
|
|
||||||
} else if nullIO {
|
|
||||||
ioCreator = cio.NullIO
|
|
||||||
} else {
|
|
||||||
ioCreator = cio.NewCreator(append([]cio.Opt{cio.WithStdio}, ioOpts...)...)
|
|
||||||
}
|
|
||||||
return container.NewTask(ctx, ioCreator)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getNewTaskOpts(_ *cli.Context) []containerd.NewTaskOpts {
|
|
||||||
return nil
|
|
||||||
}
|
|
57
vendor/github.com/containerd/containerd/cmd/ctr/commands/version/version.go
generated
vendored
57
vendor/github.com/containerd/containerd/cmd/ctr/commands/version/version.go
generated
vendored
@ -1,57 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 version
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/cmd/ctr/commands"
|
|
||||||
"github.com/containerd/containerd/version"
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Command is a cli command to output the client and containerd server version
|
|
||||||
var Command = cli.Command{
|
|
||||||
Name: "version",
|
|
||||||
Usage: "print the client and server versions",
|
|
||||||
Action: func(context *cli.Context) error {
|
|
||||||
fmt.Println("Client:")
|
|
||||||
fmt.Println(" Version: ", version.Version)
|
|
||||||
fmt.Println(" Revision:", version.Revision)
|
|
||||||
fmt.Println("")
|
|
||||||
client, ctx, cancel, err := commands.NewClient(context)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer cancel()
|
|
||||||
v, err := client.Version(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Println("Server:")
|
|
||||||
fmt.Println(" Version: ", v.Version)
|
|
||||||
fmt.Println(" Revision:", v.Revision)
|
|
||||||
if v.Version != version.Version {
|
|
||||||
fmt.Fprintln(os.Stderr, "WARNING: version mismatch")
|
|
||||||
}
|
|
||||||
if v.Revision != version.Revision {
|
|
||||||
fmt.Fprintln(os.Stderr, "WARNING: revision mismatch")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
211
vendor/github.com/containerd/containerd/contrib/nvidia/nvidia.go
generated
vendored
211
vendor/github.com/containerd/containerd/contrib/nvidia/nvidia.go
generated
vendored
@ -1,211 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 nvidia
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"os/exec"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/containers"
|
|
||||||
"github.com/containerd/containerd/oci"
|
|
||||||
specs "github.com/opencontainers/runtime-spec/specs-go"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NvidiaCLI is the path to the Nvidia helper binary
|
|
||||||
const NvidiaCLI = "nvidia-container-cli"
|
|
||||||
|
|
||||||
// Capability specifies capabilities for the gpu inside the container
|
|
||||||
// Detailed explanation of options can be found:
|
|
||||||
// https://github.com/nvidia/nvidia-container-runtime#supported-driver-capabilities
|
|
||||||
type Capability string
|
|
||||||
|
|
||||||
const (
|
|
||||||
// Compute capability
|
|
||||||
Compute Capability = "compute"
|
|
||||||
// Compat32 capability
|
|
||||||
Compat32 Capability = "compat32"
|
|
||||||
// Graphics capability
|
|
||||||
Graphics Capability = "graphics"
|
|
||||||
// Utility capability
|
|
||||||
Utility Capability = "utility"
|
|
||||||
// Video capability
|
|
||||||
Video Capability = "video"
|
|
||||||
// Display capability
|
|
||||||
Display Capability = "display"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AllCaps returns the complete list of supported Nvidia capabilties.
|
|
||||||
func AllCaps() []Capability {
|
|
||||||
return []Capability{
|
|
||||||
Compute,
|
|
||||||
Compat32,
|
|
||||||
Graphics,
|
|
||||||
Utility,
|
|
||||||
Video,
|
|
||||||
Display,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithGPUs adds NVIDIA gpu support to a container
|
|
||||||
func WithGPUs(opts ...Opts) oci.SpecOpts {
|
|
||||||
return func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
|
|
||||||
c := &config{}
|
|
||||||
for _, o := range opts {
|
|
||||||
if err := o(c); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if c.OCIHookPath == "" {
|
|
||||||
path, err := exec.LookPath("containerd")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
c.OCIHookPath = path
|
|
||||||
}
|
|
||||||
nvidiaPath, err := exec.LookPath(NvidiaCLI)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if s.Hooks == nil {
|
|
||||||
s.Hooks = &specs.Hooks{}
|
|
||||||
}
|
|
||||||
s.Hooks.Prestart = append(s.Hooks.Prestart, specs.Hook{
|
|
||||||
Path: c.OCIHookPath,
|
|
||||||
Args: append([]string{
|
|
||||||
"containerd",
|
|
||||||
"oci-hook",
|
|
||||||
"--",
|
|
||||||
nvidiaPath,
|
|
||||||
// ensures the required kernel modules are properly loaded
|
|
||||||
"--load-kmods",
|
|
||||||
}, c.args()...),
|
|
||||||
Env: os.Environ(),
|
|
||||||
})
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type config struct {
|
|
||||||
Devices []string
|
|
||||||
Capabilities []Capability
|
|
||||||
LoadKmods bool
|
|
||||||
LDCache string
|
|
||||||
LDConfig string
|
|
||||||
Requirements []string
|
|
||||||
OCIHookPath string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *config) args() []string {
|
|
||||||
var args []string
|
|
||||||
|
|
||||||
if c.LoadKmods {
|
|
||||||
args = append(args, "--load-kmods")
|
|
||||||
}
|
|
||||||
if c.LDCache != "" {
|
|
||||||
args = append(args, fmt.Sprintf("--ldcache=%s", c.LDCache))
|
|
||||||
}
|
|
||||||
args = append(args,
|
|
||||||
"configure",
|
|
||||||
)
|
|
||||||
if len(c.Devices) > 0 {
|
|
||||||
args = append(args, fmt.Sprintf("--device=%s", strings.Join(c.Devices, ",")))
|
|
||||||
}
|
|
||||||
for _, c := range c.Capabilities {
|
|
||||||
args = append(args, fmt.Sprintf("--%s", c))
|
|
||||||
}
|
|
||||||
if c.LDConfig != "" {
|
|
||||||
args = append(args, fmt.Sprintf("--ldconfig=%s", c.LDConfig))
|
|
||||||
}
|
|
||||||
for _, r := range c.Requirements {
|
|
||||||
args = append(args, fmt.Sprintf("--require=%s", r))
|
|
||||||
}
|
|
||||||
args = append(args, "--pid={{pid}}", "{{rootfs}}")
|
|
||||||
return args
|
|
||||||
}
|
|
||||||
|
|
||||||
// Opts are options for configuring gpu support
|
|
||||||
type Opts func(*config) error
|
|
||||||
|
|
||||||
// WithDevices adds the provided device indexes to the container
|
|
||||||
func WithDevices(ids ...int) Opts {
|
|
||||||
return func(c *config) error {
|
|
||||||
for _, i := range ids {
|
|
||||||
c.Devices = append(c.Devices, strconv.Itoa(i))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithDeviceUUIDs adds the specific device UUID to the container
|
|
||||||
func WithDeviceUUIDs(uuids ...string) Opts {
|
|
||||||
return func(c *config) error {
|
|
||||||
c.Devices = append(c.Devices, uuids...)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithAllDevices adds all gpus to the container
|
|
||||||
func WithAllDevices(c *config) error {
|
|
||||||
c.Devices = []string{"all"}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithAllCapabilities adds all capabilities to the container for the gpus
|
|
||||||
func WithAllCapabilities(c *config) error {
|
|
||||||
c.Capabilities = AllCaps()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithCapabilities adds the specified capabilities to the container for the gpus
|
|
||||||
func WithCapabilities(caps ...Capability) Opts {
|
|
||||||
return func(c *config) error {
|
|
||||||
c.Capabilities = append(c.Capabilities, caps...)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithRequiredCUDAVersion sets the required cuda version
|
|
||||||
func WithRequiredCUDAVersion(major, minor int) Opts {
|
|
||||||
return func(c *config) error {
|
|
||||||
c.Requirements = append(c.Requirements, fmt.Sprintf("cuda>=%d.%d", major, minor))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithOCIHookPath sets the hook path for the binary
|
|
||||||
func WithOCIHookPath(path string) Opts {
|
|
||||||
return func(c *config) error {
|
|
||||||
c.OCIHookPath = path
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithLookupOCIHookPath sets the hook path for the binary via a binary name
|
|
||||||
func WithLookupOCIHookPath(name string) Opts {
|
|
||||||
return func(c *config) error {
|
|
||||||
path, err := exec.LookPath(name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
c.OCIHookPath = path
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
82
vendor/github.com/containerd/containerd/pkg/progress/bar.go
generated
vendored
82
vendor/github.com/containerd/containerd/pkg/progress/bar.go
generated
vendored
@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 progress
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TODO(stevvooe): We may want to support more interesting parameterization of
|
|
||||||
// the bar. For now, it is very simple.
|
|
||||||
|
|
||||||
// Bar provides a very simple progress bar implementation.
|
|
||||||
//
|
|
||||||
// Use with fmt.Printf and "r" to format the progress bar. A "-" flag makes it
|
|
||||||
// progress from right to left.
|
|
||||||
type Bar float64
|
|
||||||
|
|
||||||
var _ fmt.Formatter = Bar(1.0)
|
|
||||||
|
|
||||||
// Format the progress bar as output
|
|
||||||
func (h Bar) Format(state fmt.State, r rune) {
|
|
||||||
switch r {
|
|
||||||
case 'r':
|
|
||||||
default:
|
|
||||||
panic(fmt.Sprintf("%v: unexpected format character", float64(h)))
|
|
||||||
}
|
|
||||||
|
|
||||||
if h > 1.0 {
|
|
||||||
h = 1.0
|
|
||||||
}
|
|
||||||
|
|
||||||
if h < 0.0 {
|
|
||||||
h = 0.0
|
|
||||||
}
|
|
||||||
|
|
||||||
if state.Flag('-') {
|
|
||||||
h = 1.0 - h
|
|
||||||
}
|
|
||||||
|
|
||||||
width, ok := state.Width()
|
|
||||||
if !ok {
|
|
||||||
// default width of 40
|
|
||||||
width = 40
|
|
||||||
}
|
|
||||||
|
|
||||||
var pad int
|
|
||||||
|
|
||||||
extra := len([]byte(green)) + len([]byte(reset))
|
|
||||||
|
|
||||||
p := make([]byte, width+extra)
|
|
||||||
p[0], p[len(p)-1] = '|', '|'
|
|
||||||
pad += 2
|
|
||||||
|
|
||||||
positive := int(Bar(width-pad) * h)
|
|
||||||
negative := width - pad - positive
|
|
||||||
|
|
||||||
n := 1
|
|
||||||
n += copy(p[n:], green)
|
|
||||||
n += copy(p[n:], bytes.Repeat([]byte("+"), positive))
|
|
||||||
n += copy(p[n:], reset)
|
|
||||||
|
|
||||||
if negative > 0 {
|
|
||||||
copy(p[n:len(p)-1], bytes.Repeat([]byte("-"), negative))
|
|
||||||
}
|
|
||||||
|
|
||||||
state.Write(p)
|
|
||||||
}
|
|
18
vendor/github.com/containerd/containerd/pkg/progress/doc.go
generated
vendored
18
vendor/github.com/containerd/containerd/pkg/progress/doc.go
generated
vendored
@ -1,18 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 progress assists in displaying human readable progress information.
|
|
||||||
package progress
|
|
24
vendor/github.com/containerd/containerd/pkg/progress/escape.go
generated
vendored
24
vendor/github.com/containerd/containerd/pkg/progress/escape.go
generated
vendored
@ -1,24 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 progress
|
|
||||||
|
|
||||||
const (
|
|
||||||
escape = "\x1b"
|
|
||||||
reset = escape + "[0m"
|
|
||||||
red = escape + "[31m" // nolint: staticcheck, varcheck
|
|
||||||
green = escape + "[32m"
|
|
||||||
)
|
|
45
vendor/github.com/containerd/containerd/pkg/progress/humaans.go
generated
vendored
45
vendor/github.com/containerd/containerd/pkg/progress/humaans.go
generated
vendored
@ -1,45 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 progress
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
units "github.com/docker/go-units"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Bytes converts a regular int64 to human readable type.
|
|
||||||
type Bytes int64
|
|
||||||
|
|
||||||
// String returns the string representation of bytes
|
|
||||||
func (b Bytes) String() string {
|
|
||||||
return units.CustomSize("%02.1f %s", float64(b), 1024.0, []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"})
|
|
||||||
}
|
|
||||||
|
|
||||||
// BytesPerSecond is the rate in seconds for byte operations
|
|
||||||
type BytesPerSecond int64
|
|
||||||
|
|
||||||
// NewBytesPerSecond returns the rate that n bytes were written in the provided duration
|
|
||||||
func NewBytesPerSecond(n int64, duration time.Duration) BytesPerSecond {
|
|
||||||
return BytesPerSecond(float64(n) / duration.Seconds())
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns the string representation of the rate
|
|
||||||
func (bps BytesPerSecond) String() string {
|
|
||||||
return fmt.Sprintf("%v/s", Bytes(bps))
|
|
||||||
}
|
|
115
vendor/github.com/containerd/containerd/pkg/progress/writer.go
generated
vendored
115
vendor/github.com/containerd/containerd/pkg/progress/writer.go
generated
vendored
@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 progress
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"regexp"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/containerd/console"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
regexCleanLine = regexp.MustCompile("\x1b\\[[0-9]+m[\x1b]?")
|
|
||||||
)
|
|
||||||
|
|
||||||
// Writer buffers writes until flush, at which time the last screen is cleared
|
|
||||||
// and the current buffer contents are written. This is useful for
|
|
||||||
// implementing progress displays, such as those implemented in docker and
|
|
||||||
// git.
|
|
||||||
type Writer struct {
|
|
||||||
buf bytes.Buffer
|
|
||||||
w io.Writer
|
|
||||||
lines int
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewWriter returns a writer
|
|
||||||
func NewWriter(w io.Writer) *Writer {
|
|
||||||
return &Writer{
|
|
||||||
w: w,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the provided bytes
|
|
||||||
func (w *Writer) Write(p []byte) (n int, err error) {
|
|
||||||
return w.buf.Write(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flush should be called when refreshing the current display.
|
|
||||||
func (w *Writer) Flush() error {
|
|
||||||
if w.buf.Len() == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := w.clearLines(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.lines = countLines(w.buf.String())
|
|
||||||
|
|
||||||
if _, err := w.w.Write(w.buf.Bytes()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
w.buf.Reset()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(stevvooe): The following are system specific. Break these out if we
|
|
||||||
// decide to build this package further.
|
|
||||||
|
|
||||||
func (w *Writer) clearLines() error {
|
|
||||||
for i := 0; i < w.lines; i++ {
|
|
||||||
if _, err := fmt.Fprintf(w.w, "\x1b[1A\x1b[2K\r"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// countLines in the output. If a line is longer than the console width then
|
|
||||||
// an extra line is added to the count for each wrapped line. If the console
|
|
||||||
// width is undefined then 0 is returned so that no lines are cleared on the next
|
|
||||||
// flush.
|
|
||||||
func countLines(output string) int {
|
|
||||||
con, err := console.ConsoleFromFile(os.Stdin)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
ws, err := con.Size()
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
width := int(ws.Width)
|
|
||||||
if width <= 0 {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
strlines := strings.Split(output, "\n")
|
|
||||||
lines := -1
|
|
||||||
for _, line := range strlines {
|
|
||||||
lines += (len(stripLine(line))-1)/width + 1
|
|
||||||
}
|
|
||||||
return lines
|
|
||||||
}
|
|
||||||
|
|
||||||
func stripLine(line string) string {
|
|
||||||
return string(regexCleanLine.ReplaceAll([]byte(line), []byte{}))
|
|
||||||
}
|
|
17
vendor/github.com/containerd/containerd/runtime/v2/runhcs/options/doc.go
generated
vendored
17
vendor/github.com/containerd/containerd/runtime/v2/runhcs/options/doc.go
generated
vendored
@ -1,17 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright The containerd 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 options
|
|
627
vendor/github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.pb.go
generated
vendored
627
vendor/github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.pb.go
generated
vendored
@ -1,627 +0,0 @@
|
|||||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
|
||||||
// source: github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.proto
|
|
||||||
|
|
||||||
package options
|
|
||||||
|
|
||||||
import (
|
|
||||||
fmt "fmt"
|
|
||||||
proto "github.com/gogo/protobuf/proto"
|
|
||||||
io "io"
|
|
||||||
math "math"
|
|
||||||
reflect "reflect"
|
|
||||||
strings "strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Reference imports to suppress errors if they are not otherwise used.
|
|
||||||
var _ = proto.Marshal
|
|
||||||
var _ = fmt.Errorf
|
|
||||||
var _ = math.Inf
|
|
||||||
|
|
||||||
// This is a compile-time assertion to ensure that this generated file
|
|
||||||
// is compatible with the proto package it is being compiled against.
|
|
||||||
// A compilation error at this line likely means your copy of the
|
|
||||||
// proto package needs to be updated.
|
|
||||||
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
|
|
||||||
|
|
||||||
type Options_DebugType int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
Options_NPIPE Options_DebugType = 0
|
|
||||||
Options_FILE Options_DebugType = 1
|
|
||||||
Options_ETW Options_DebugType = 2
|
|
||||||
)
|
|
||||||
|
|
||||||
var Options_DebugType_name = map[int32]string{
|
|
||||||
0: "NPIPE",
|
|
||||||
1: "FILE",
|
|
||||||
2: "ETW",
|
|
||||||
}
|
|
||||||
|
|
||||||
var Options_DebugType_value = map[string]int32{
|
|
||||||
"NPIPE": 0,
|
|
||||||
"FILE": 1,
|
|
||||||
"ETW": 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x Options_DebugType) String() string {
|
|
||||||
return proto.EnumName(Options_DebugType_name, int32(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Options_DebugType) EnumDescriptor() ([]byte, []int) {
|
|
||||||
return fileDescriptor_f30b88a94da34796, []int{0, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Options_SandboxIsolation int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
Options_PROCESS Options_SandboxIsolation = 0
|
|
||||||
Options_HYPERVISOR Options_SandboxIsolation = 1
|
|
||||||
)
|
|
||||||
|
|
||||||
var Options_SandboxIsolation_name = map[int32]string{
|
|
||||||
0: "PROCESS",
|
|
||||||
1: "HYPERVISOR",
|
|
||||||
}
|
|
||||||
|
|
||||||
var Options_SandboxIsolation_value = map[string]int32{
|
|
||||||
"PROCESS": 0,
|
|
||||||
"HYPERVISOR": 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x Options_SandboxIsolation) String() string {
|
|
||||||
return proto.EnumName(Options_SandboxIsolation_name, int32(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (Options_SandboxIsolation) EnumDescriptor() ([]byte, []int) {
|
|
||||||
return fileDescriptor_f30b88a94da34796, []int{0, 1}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Options struct {
|
|
||||||
// enable debug tracing
|
|
||||||
Debug bool `protobuf:"varint,1,opt,name=debug,proto3" json:"debug,omitempty"`
|
|
||||||
// debug tracing output type
|
|
||||||
DebugType Options_DebugType `protobuf:"varint,2,opt,name=debug_type,json=debugType,proto3,enum=containerd.runhcs.v1.Options_DebugType" json:"debug_type,omitempty"`
|
|
||||||
// registry key root for storage of the runhcs container state
|
|
||||||
RegistryRoot string `protobuf:"bytes,3,opt,name=registry_root,json=registryRoot,proto3" json:"registry_root,omitempty"`
|
|
||||||
// sandbox_image is the image to use for the sandbox that matches the
|
|
||||||
// sandbox_platform.
|
|
||||||
SandboxImage string `protobuf:"bytes,4,opt,name=sandbox_image,json=sandboxImage,proto3" json:"sandbox_image,omitempty"`
|
|
||||||
// sandbox_platform is a CRI setting that specifies the platform
|
|
||||||
// architecture for all sandbox's in this runtime. Values are
|
|
||||||
// 'windows/amd64' and 'linux/amd64'.
|
|
||||||
SandboxPlatform string `protobuf:"bytes,5,opt,name=sandbox_platform,json=sandboxPlatform,proto3" json:"sandbox_platform,omitempty"`
|
|
||||||
// sandbox_isolation is a CRI setting that specifies the isolation level of
|
|
||||||
// the sandbox. For Windows runtime PROCESS and HYPERVISOR are valid. For
|
|
||||||
// LCOW only HYPERVISOR is valid and default if omitted.
|
|
||||||
SandboxIsolation Options_SandboxIsolation `protobuf:"varint,6,opt,name=sandbox_isolation,json=sandboxIsolation,proto3,enum=containerd.runhcs.v1.Options_SandboxIsolation" json:"sandbox_isolation,omitempty"`
|
|
||||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
|
||||||
XXX_unrecognized []byte `json:"-"`
|
|
||||||
XXX_sizecache int32 `json:"-"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Options) Reset() { *m = Options{} }
|
|
||||||
func (*Options) ProtoMessage() {}
|
|
||||||
func (*Options) Descriptor() ([]byte, []int) {
|
|
||||||
return fileDescriptor_f30b88a94da34796, []int{0}
|
|
||||||
}
|
|
||||||
func (m *Options) XXX_Unmarshal(b []byte) error {
|
|
||||||
return m.Unmarshal(b)
|
|
||||||
}
|
|
||||||
func (m *Options) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
|
||||||
if deterministic {
|
|
||||||
return xxx_messageInfo_Options.Marshal(b, m, deterministic)
|
|
||||||
} else {
|
|
||||||
b = b[:cap(b)]
|
|
||||||
n, err := m.MarshalTo(b)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return b[:n], nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (m *Options) XXX_Merge(src proto.Message) {
|
|
||||||
xxx_messageInfo_Options.Merge(m, src)
|
|
||||||
}
|
|
||||||
func (m *Options) XXX_Size() int {
|
|
||||||
return m.Size()
|
|
||||||
}
|
|
||||||
func (m *Options) XXX_DiscardUnknown() {
|
|
||||||
xxx_messageInfo_Options.DiscardUnknown(m)
|
|
||||||
}
|
|
||||||
|
|
||||||
var xxx_messageInfo_Options proto.InternalMessageInfo
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
proto.RegisterEnum("containerd.runhcs.v1.Options_DebugType", Options_DebugType_name, Options_DebugType_value)
|
|
||||||
proto.RegisterEnum("containerd.runhcs.v1.Options_SandboxIsolation", Options_SandboxIsolation_name, Options_SandboxIsolation_value)
|
|
||||||
proto.RegisterType((*Options)(nil), "containerd.runhcs.v1.Options")
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
proto.RegisterFile("github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.proto", fileDescriptor_f30b88a94da34796)
|
|
||||||
}
|
|
||||||
|
|
||||||
var fileDescriptor_f30b88a94da34796 = []byte{
|
|
||||||
// 383 bytes of a gzipped FileDescriptorProto
|
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x92, 0xcd, 0x6e, 0x9b, 0x40,
|
|
||||||
0x14, 0x85, 0x19, 0xff, 0x73, 0xdb, 0xba, 0x74, 0xe4, 0x05, 0xea, 0x02, 0x59, 0xee, 0xa2, 0xf6,
|
|
||||||
0x06, 0x54, 0x77, 0xd9, 0x9d, 0x5b, 0xdc, 0x22, 0x55, 0x35, 0x1a, 0xac, 0xb6, 0xf9, 0x91, 0x2c,
|
|
||||||
0x30, 0x04, 0x23, 0x19, 0x06, 0xc1, 0xd8, 0x8a, 0x77, 0x79, 0x89, 0xbc, 0x93, 0x97, 0x59, 0x66,
|
|
||||||
0x19, 0xf3, 0x24, 0x11, 0x30, 0x38, 0x51, 0x14, 0x65, 0x91, 0x15, 0xe7, 0x1e, 0xbe, 0x7b, 0xee,
|
|
||||||
0x5c, 0xcd, 0xc0, 0x4f, 0x3f, 0x60, 0xab, 0x8d, 0xa3, 0x2e, 0x69, 0xa8, 0x2d, 0x69, 0xc4, 0xec,
|
|
||||||
0x20, 0xf2, 0x12, 0xf7, 0xb1, 0x4c, 0x36, 0x11, 0x0b, 0x42, 0x4f, 0xdb, 0x8e, 0x73, 0xb9, 0x5a,
|
|
||||||
0xa6, 0x1a, 0x8d, 0x59, 0x40, 0xa3, 0x94, 0x97, 0x6a, 0x9c, 0x50, 0x46, 0x71, 0xef, 0xa1, 0x45,
|
|
||||||
0xe5, 0x3f, 0xb6, 0x5f, 0x3e, 0xf6, 0x7c, 0xea, 0xd3, 0x02, 0xd0, 0x72, 0x55, 0xb2, 0x83, 0xeb,
|
|
||||||
0x3a, 0xb4, 0x67, 0x65, 0x08, 0xee, 0x41, 0xd3, 0xf5, 0x9c, 0x8d, 0x2f, 0xa3, 0x3e, 0x1a, 0x76,
|
|
||||||
0x48, 0x59, 0xe0, 0x29, 0x40, 0x21, 0x16, 0x6c, 0x17, 0x7b, 0x72, 0xad, 0x8f, 0x86, 0xdd, 0xf1,
|
|
||||||
0x67, 0xf5, 0xb9, 0x11, 0x2a, 0x0f, 0x52, 0x7f, 0xe4, 0xfc, 0x7c, 0x17, 0x7b, 0x44, 0x74, 0x2b,
|
|
||||||
0x89, 0x3f, 0xc1, 0xbb, 0xc4, 0xf3, 0x83, 0x94, 0x25, 0xbb, 0x45, 0x42, 0x29, 0x93, 0xeb, 0x7d,
|
|
||||||
0x34, 0x14, 0xc9, 0xdb, 0xca, 0x24, 0x94, 0xb2, 0x1c, 0x4a, 0xed, 0xc8, 0x75, 0xe8, 0xe5, 0x22,
|
|
||||||
0x08, 0x6d, 0xdf, 0x93, 0x1b, 0x25, 0xc4, 0x4d, 0x23, 0xf7, 0xf0, 0x08, 0xa4, 0x0a, 0x8a, 0xd7,
|
|
||||||
0x36, 0xbb, 0xa0, 0x49, 0x28, 0x37, 0x0b, 0xee, 0x3d, 0xf7, 0x4d, 0x6e, 0xe3, 0x33, 0xf8, 0x70,
|
|
||||||
0xcc, 0x4b, 0xe9, 0xda, 0xce, 0xcf, 0x27, 0xb7, 0x8a, 0x1d, 0xd4, 0x97, 0x77, 0xb0, 0xf8, 0xc4,
|
|
||||||
0xaa, 0x8b, 0x54, 0x33, 0x8f, 0xce, 0x60, 0x04, 0xe2, 0x71, 0x53, 0x2c, 0x42, 0xf3, 0x8f, 0x69,
|
|
||||||
0x98, 0xba, 0x24, 0xe0, 0x0e, 0x34, 0xa6, 0xc6, 0x6f, 0x5d, 0x42, 0xb8, 0x0d, 0x75, 0x7d, 0xfe,
|
|
||||||
0x4f, 0xaa, 0x0d, 0x34, 0x90, 0x9e, 0x06, 0xe2, 0x37, 0xd0, 0x36, 0xc9, 0xec, 0xbb, 0x6e, 0x59,
|
|
||||||
0x92, 0x80, 0xbb, 0x00, 0xbf, 0x4e, 0x4c, 0x9d, 0xfc, 0x35, 0xac, 0x19, 0x91, 0xd0, 0xe4, 0x7c,
|
|
||||||
0x7f, 0x50, 0x84, 0xdb, 0x83, 0x22, 0x5c, 0x65, 0x0a, 0xda, 0x67, 0x0a, 0xba, 0xc9, 0x14, 0x74,
|
|
||||||
0x97, 0x29, 0xe8, 0x74, 0xf2, 0xfa, 0x67, 0xf2, 0x8d, 0x7f, 0xff, 0x0b, 0x4e, 0xab, 0xb8, 0xfe,
|
|
||||||
0xaf, 0xf7, 0x01, 0x00, 0x00, 0xff, 0xff, 0xe8, 0xe0, 0x0a, 0x7a, 0x75, 0x02, 0x00, 0x00,
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Options) Marshal() (dAtA []byte, err error) {
|
|
||||||
size := m.Size()
|
|
||||||
dAtA = make([]byte, size)
|
|
||||||
n, err := m.MarshalTo(dAtA)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return dAtA[:n], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Options) MarshalTo(dAtA []byte) (int, error) {
|
|
||||||
var i int
|
|
||||||
_ = i
|
|
||||||
var l int
|
|
||||||
_ = l
|
|
||||||
if m.Debug {
|
|
||||||
dAtA[i] = 0x8
|
|
||||||
i++
|
|
||||||
if m.Debug {
|
|
||||||
dAtA[i] = 1
|
|
||||||
} else {
|
|
||||||
dAtA[i] = 0
|
|
||||||
}
|
|
||||||
i++
|
|
||||||
}
|
|
||||||
if m.DebugType != 0 {
|
|
||||||
dAtA[i] = 0x10
|
|
||||||
i++
|
|
||||||
i = encodeVarintRunhcs(dAtA, i, uint64(m.DebugType))
|
|
||||||
}
|
|
||||||
if len(m.RegistryRoot) > 0 {
|
|
||||||
dAtA[i] = 0x1a
|
|
||||||
i++
|
|
||||||
i = encodeVarintRunhcs(dAtA, i, uint64(len(m.RegistryRoot)))
|
|
||||||
i += copy(dAtA[i:], m.RegistryRoot)
|
|
||||||
}
|
|
||||||
if len(m.SandboxImage) > 0 {
|
|
||||||
dAtA[i] = 0x22
|
|
||||||
i++
|
|
||||||
i = encodeVarintRunhcs(dAtA, i, uint64(len(m.SandboxImage)))
|
|
||||||
i += copy(dAtA[i:], m.SandboxImage)
|
|
||||||
}
|
|
||||||
if len(m.SandboxPlatform) > 0 {
|
|
||||||
dAtA[i] = 0x2a
|
|
||||||
i++
|
|
||||||
i = encodeVarintRunhcs(dAtA, i, uint64(len(m.SandboxPlatform)))
|
|
||||||
i += copy(dAtA[i:], m.SandboxPlatform)
|
|
||||||
}
|
|
||||||
if m.SandboxIsolation != 0 {
|
|
||||||
dAtA[i] = 0x30
|
|
||||||
i++
|
|
||||||
i = encodeVarintRunhcs(dAtA, i, uint64(m.SandboxIsolation))
|
|
||||||
}
|
|
||||||
if m.XXX_unrecognized != nil {
|
|
||||||
i += copy(dAtA[i:], m.XXX_unrecognized)
|
|
||||||
}
|
|
||||||
return i, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func encodeVarintRunhcs(dAtA []byte, offset int, v uint64) int {
|
|
||||||
for v >= 1<<7 {
|
|
||||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
|
||||||
v >>= 7
|
|
||||||
offset++
|
|
||||||
}
|
|
||||||
dAtA[offset] = uint8(v)
|
|
||||||
return offset + 1
|
|
||||||
}
|
|
||||||
func (m *Options) Size() (n int) {
|
|
||||||
if m == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
var l int
|
|
||||||
_ = l
|
|
||||||
if m.Debug {
|
|
||||||
n += 2
|
|
||||||
}
|
|
||||||
if m.DebugType != 0 {
|
|
||||||
n += 1 + sovRunhcs(uint64(m.DebugType))
|
|
||||||
}
|
|
||||||
l = len(m.RegistryRoot)
|
|
||||||
if l > 0 {
|
|
||||||
n += 1 + l + sovRunhcs(uint64(l))
|
|
||||||
}
|
|
||||||
l = len(m.SandboxImage)
|
|
||||||
if l > 0 {
|
|
||||||
n += 1 + l + sovRunhcs(uint64(l))
|
|
||||||
}
|
|
||||||
l = len(m.SandboxPlatform)
|
|
||||||
if l > 0 {
|
|
||||||
n += 1 + l + sovRunhcs(uint64(l))
|
|
||||||
}
|
|
||||||
if m.SandboxIsolation != 0 {
|
|
||||||
n += 1 + sovRunhcs(uint64(m.SandboxIsolation))
|
|
||||||
}
|
|
||||||
if m.XXX_unrecognized != nil {
|
|
||||||
n += len(m.XXX_unrecognized)
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func sovRunhcs(x uint64) (n int) {
|
|
||||||
for {
|
|
||||||
n++
|
|
||||||
x >>= 7
|
|
||||||
if x == 0 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
func sozRunhcs(x uint64) (n int) {
|
|
||||||
return sovRunhcs(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
|
||||||
}
|
|
||||||
func (this *Options) String() string {
|
|
||||||
if this == nil {
|
|
||||||
return "nil"
|
|
||||||
}
|
|
||||||
s := strings.Join([]string{`&Options{`,
|
|
||||||
`Debug:` + fmt.Sprintf("%v", this.Debug) + `,`,
|
|
||||||
`DebugType:` + fmt.Sprintf("%v", this.DebugType) + `,`,
|
|
||||||
`RegistryRoot:` + fmt.Sprintf("%v", this.RegistryRoot) + `,`,
|
|
||||||
`SandboxImage:` + fmt.Sprintf("%v", this.SandboxImage) + `,`,
|
|
||||||
`SandboxPlatform:` + fmt.Sprintf("%v", this.SandboxPlatform) + `,`,
|
|
||||||
`SandboxIsolation:` + fmt.Sprintf("%v", this.SandboxIsolation) + `,`,
|
|
||||||
`XXX_unrecognized:` + fmt.Sprintf("%v", this.XXX_unrecognized) + `,`,
|
|
||||||
`}`,
|
|
||||||
}, "")
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
func valueToStringRunhcs(v interface{}) string {
|
|
||||||
rv := reflect.ValueOf(v)
|
|
||||||
if rv.IsNil() {
|
|
||||||
return "nil"
|
|
||||||
}
|
|
||||||
pv := reflect.Indirect(rv).Interface()
|
|
||||||
return fmt.Sprintf("*%v", pv)
|
|
||||||
}
|
|
||||||
func (m *Options) Unmarshal(dAtA []byte) error {
|
|
||||||
l := len(dAtA)
|
|
||||||
iNdEx := 0
|
|
||||||
for iNdEx < l {
|
|
||||||
preIndex := iNdEx
|
|
||||||
var wire uint64
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowRunhcs
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
wire |= uint64(b&0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fieldNum := int32(wire >> 3)
|
|
||||||
wireType := int(wire & 0x7)
|
|
||||||
if wireType == 4 {
|
|
||||||
return fmt.Errorf("proto: Options: wiretype end group for non-group")
|
|
||||||
}
|
|
||||||
if fieldNum <= 0 {
|
|
||||||
return fmt.Errorf("proto: Options: illegal tag %d (wire type %d)", fieldNum, wire)
|
|
||||||
}
|
|
||||||
switch fieldNum {
|
|
||||||
case 1:
|
|
||||||
if wireType != 0 {
|
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field Debug", wireType)
|
|
||||||
}
|
|
||||||
var v int
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowRunhcs
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
v |= int(b&0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m.Debug = bool(v != 0)
|
|
||||||
case 2:
|
|
||||||
if wireType != 0 {
|
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field DebugType", wireType)
|
|
||||||
}
|
|
||||||
m.DebugType = 0
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowRunhcs
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
m.DebugType |= Options_DebugType(b&0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case 3:
|
|
||||||
if wireType != 2 {
|
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field RegistryRoot", wireType)
|
|
||||||
}
|
|
||||||
var stringLen uint64
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowRunhcs
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
stringLen |= uint64(b&0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
intStringLen := int(stringLen)
|
|
||||||
if intStringLen < 0 {
|
|
||||||
return ErrInvalidLengthRunhcs
|
|
||||||
}
|
|
||||||
postIndex := iNdEx + intStringLen
|
|
||||||
if postIndex < 0 {
|
|
||||||
return ErrInvalidLengthRunhcs
|
|
||||||
}
|
|
||||||
if postIndex > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
m.RegistryRoot = string(dAtA[iNdEx:postIndex])
|
|
||||||
iNdEx = postIndex
|
|
||||||
case 4:
|
|
||||||
if wireType != 2 {
|
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field SandboxImage", wireType)
|
|
||||||
}
|
|
||||||
var stringLen uint64
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowRunhcs
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
stringLen |= uint64(b&0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
intStringLen := int(stringLen)
|
|
||||||
if intStringLen < 0 {
|
|
||||||
return ErrInvalidLengthRunhcs
|
|
||||||
}
|
|
||||||
postIndex := iNdEx + intStringLen
|
|
||||||
if postIndex < 0 {
|
|
||||||
return ErrInvalidLengthRunhcs
|
|
||||||
}
|
|
||||||
if postIndex > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
m.SandboxImage = string(dAtA[iNdEx:postIndex])
|
|
||||||
iNdEx = postIndex
|
|
||||||
case 5:
|
|
||||||
if wireType != 2 {
|
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field SandboxPlatform", wireType)
|
|
||||||
}
|
|
||||||
var stringLen uint64
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowRunhcs
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
stringLen |= uint64(b&0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
intStringLen := int(stringLen)
|
|
||||||
if intStringLen < 0 {
|
|
||||||
return ErrInvalidLengthRunhcs
|
|
||||||
}
|
|
||||||
postIndex := iNdEx + intStringLen
|
|
||||||
if postIndex < 0 {
|
|
||||||
return ErrInvalidLengthRunhcs
|
|
||||||
}
|
|
||||||
if postIndex > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
m.SandboxPlatform = string(dAtA[iNdEx:postIndex])
|
|
||||||
iNdEx = postIndex
|
|
||||||
case 6:
|
|
||||||
if wireType != 0 {
|
|
||||||
return fmt.Errorf("proto: wrong wireType = %d for field SandboxIsolation", wireType)
|
|
||||||
}
|
|
||||||
m.SandboxIsolation = 0
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return ErrIntOverflowRunhcs
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
m.SandboxIsolation |= Options_SandboxIsolation(b&0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
iNdEx = preIndex
|
|
||||||
skippy, err := skipRunhcs(dAtA[iNdEx:])
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if skippy < 0 {
|
|
||||||
return ErrInvalidLengthRunhcs
|
|
||||||
}
|
|
||||||
if (iNdEx + skippy) < 0 {
|
|
||||||
return ErrInvalidLengthRunhcs
|
|
||||||
}
|
|
||||||
if (iNdEx + skippy) > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
m.XXX_unrecognized = append(m.XXX_unrecognized, dAtA[iNdEx:iNdEx+skippy]...)
|
|
||||||
iNdEx += skippy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if iNdEx > l {
|
|
||||||
return io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
func skipRunhcs(dAtA []byte) (n int, err error) {
|
|
||||||
l := len(dAtA)
|
|
||||||
iNdEx := 0
|
|
||||||
for iNdEx < l {
|
|
||||||
var wire uint64
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return 0, ErrIntOverflowRunhcs
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return 0, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
wire |= (uint64(b) & 0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wireType := int(wire & 0x7)
|
|
||||||
switch wireType {
|
|
||||||
case 0:
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return 0, ErrIntOverflowRunhcs
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return 0, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
iNdEx++
|
|
||||||
if dAtA[iNdEx-1] < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return iNdEx, nil
|
|
||||||
case 1:
|
|
||||||
iNdEx += 8
|
|
||||||
return iNdEx, nil
|
|
||||||
case 2:
|
|
||||||
var length int
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return 0, ErrIntOverflowRunhcs
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return 0, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
length |= (int(b) & 0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if length < 0 {
|
|
||||||
return 0, ErrInvalidLengthRunhcs
|
|
||||||
}
|
|
||||||
iNdEx += length
|
|
||||||
if iNdEx < 0 {
|
|
||||||
return 0, ErrInvalidLengthRunhcs
|
|
||||||
}
|
|
||||||
return iNdEx, nil
|
|
||||||
case 3:
|
|
||||||
for {
|
|
||||||
var innerWire uint64
|
|
||||||
var start int = iNdEx
|
|
||||||
for shift := uint(0); ; shift += 7 {
|
|
||||||
if shift >= 64 {
|
|
||||||
return 0, ErrIntOverflowRunhcs
|
|
||||||
}
|
|
||||||
if iNdEx >= l {
|
|
||||||
return 0, io.ErrUnexpectedEOF
|
|
||||||
}
|
|
||||||
b := dAtA[iNdEx]
|
|
||||||
iNdEx++
|
|
||||||
innerWire |= (uint64(b) & 0x7F) << shift
|
|
||||||
if b < 0x80 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
innerWireType := int(innerWire & 0x7)
|
|
||||||
if innerWireType == 4 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
next, err := skipRunhcs(dAtA[start:])
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
iNdEx = start + next
|
|
||||||
if iNdEx < 0 {
|
|
||||||
return 0, ErrInvalidLengthRunhcs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return iNdEx, nil
|
|
||||||
case 4:
|
|
||||||
return iNdEx, nil
|
|
||||||
case 5:
|
|
||||||
iNdEx += 4
|
|
||||||
return iNdEx, nil
|
|
||||||
default:
|
|
||||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
ErrInvalidLengthRunhcs = fmt.Errorf("proto: negative length found during unmarshaling")
|
|
||||||
ErrIntOverflowRunhcs = fmt.Errorf("proto: integer overflow")
|
|
||||||
)
|
|
43
vendor/github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.proto
generated
vendored
43
vendor/github.com/containerd/containerd/runtime/v2/runhcs/options/runhcs.proto
generated
vendored
@ -1,43 +0,0 @@
|
|||||||
syntax = "proto3";
|
|
||||||
|
|
||||||
package containerd.runhcs.v1;
|
|
||||||
|
|
||||||
import weak "gogoproto/gogo.proto";
|
|
||||||
|
|
||||||
option go_package = "github.com/containerd/containerd/runtime/v2/runhcs/options;options";
|
|
||||||
|
|
||||||
message Options {
|
|
||||||
// enable debug tracing
|
|
||||||
bool debug = 1;
|
|
||||||
|
|
||||||
enum DebugType {
|
|
||||||
NPIPE = 0;
|
|
||||||
FILE = 1;
|
|
||||||
ETW = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// debug tracing output type
|
|
||||||
DebugType debug_type = 2;
|
|
||||||
|
|
||||||
// registry key root for storage of the runhcs container state
|
|
||||||
string registry_root = 3;
|
|
||||||
|
|
||||||
// sandbox_image is the image to use for the sandbox that matches the
|
|
||||||
// sandbox_platform.
|
|
||||||
string sandbox_image = 4;
|
|
||||||
|
|
||||||
// sandbox_platform is a CRI setting that specifies the platform
|
|
||||||
// architecture for all sandbox's in this runtime. Values are
|
|
||||||
// 'windows/amd64' and 'linux/amd64'.
|
|
||||||
string sandbox_platform = 5;
|
|
||||||
|
|
||||||
enum SandboxIsolation {
|
|
||||||
PROCESS = 0;
|
|
||||||
HYPERVISOR = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sandbox_isolation is a CRI setting that specifies the isolation level of
|
|
||||||
// the sandbox. For Windows runtime PROCESS and HYPERVISOR are valid. For
|
|
||||||
// LCOW only HYPERVISOR is valid and default if omitted.
|
|
||||||
SandboxIsolation sandbox_isolation = 6;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user