Rename ocid to crio.

The ocid project was renamed to CRI-O, months ago, it is time that we moved
all of the code to the new name.  We want to elminate the name ocid from use.
Move fully to crio.

Also cric is being renamed to crioctl for the time being.

Signed-off-by: Dan Walsh <dwalsh@redhat.com>
This commit is contained in:
Dan Walsh 2017-05-12 09:36:15 -04:00
parent 81cfba283a
commit 4493b6f176
52 changed files with 677 additions and 677 deletions

605
cmd/crioctl/container.go Normal file
View file

@ -0,0 +1,605 @@
package main
import (
"fmt"
"log"
"net/url"
"os"
"strings"
"time"
"github.com/urfave/cli"
"golang.org/x/net/context"
restclient "k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/client/unversioned/remotecommand"
pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
remotecommandserver "k8s.io/kubernetes/pkg/kubelet/server/remotecommand"
)
var containerCommand = cli.Command{
Name: "container",
Aliases: []string{"ctr"},
Subcommands: []cli.Command{
createContainerCommand,
startContainerCommand,
stopContainerCommand,
removeContainerCommand,
containerStatusCommand,
listContainersCommand,
execSyncCommand,
execCommand,
},
}
type createOptions struct {
// configPath is path to the config for container
configPath string
// name sets the container name
name string
// podID of the container
podID string
// labels for the container
labels map[string]string
}
var createContainerCommand = cli.Command{
Name: "create",
Usage: "create a container",
Flags: []cli.Flag{
cli.StringFlag{
Name: "pod",
Usage: "the id of the pod sandbox to which the container belongs",
},
cli.StringFlag{
Name: "config",
Value: "config.json",
Usage: "the path of a container config file",
},
cli.StringFlag{
Name: "name",
Value: "",
Usage: "the name of the container",
},
cli.StringSliceFlag{
Name: "label",
Usage: "add key=value labels to the container",
},
},
Action: func(context *cli.Context) error {
// Set up a connection to the server.
conn, err := getClientConnection(context)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewRuntimeServiceClient(conn)
if !context.IsSet("pod") {
return fmt.Errorf("Please specify the id of the pod sandbox to which the container belongs via the --pod option")
}
opts := createOptions{
configPath: context.String("config"),
name: context.String("name"),
podID: context.String("pod"),
labels: make(map[string]string),
}
for _, l := range context.StringSlice("label") {
pair := strings.Split(l, "=")
if len(pair) != 2 {
return fmt.Errorf("incorrectly specified label: %v", l)
}
opts.labels[pair[0]] = pair[1]
}
// Test RuntimeServiceClient.CreateContainer
err = CreateContainer(client, opts)
if err != nil {
return fmt.Errorf("Creating container failed: %v", err)
}
return nil
},
}
var startContainerCommand = cli.Command{
Name: "start",
Usage: "start a container",
Flags: []cli.Flag{
cli.StringFlag{
Name: "id",
Value: "",
Usage: "id of the container",
},
},
Action: func(context *cli.Context) error {
// Set up a connection to the server.
conn, err := getClientConnection(context)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewRuntimeServiceClient(conn)
err = StartContainer(client, context.String("id"))
if err != nil {
return fmt.Errorf("Starting the container failed: %v", err)
}
return nil
},
}
var stopContainerCommand = cli.Command{
Name: "stop",
Usage: "stop a container",
Flags: []cli.Flag{
cli.StringFlag{
Name: "id",
Value: "",
Usage: "id of the container",
},
},
Action: func(context *cli.Context) error {
// Set up a connection to the server.
conn, err := getClientConnection(context)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewRuntimeServiceClient(conn)
err = StopContainer(client, context.String("id"))
if err != nil {
return fmt.Errorf("Stopping the container failed: %v", err)
}
return nil
},
}
var removeContainerCommand = cli.Command{
Name: "remove",
Usage: "remove a container",
Flags: []cli.Flag{
cli.StringFlag{
Name: "id",
Value: "",
Usage: "id of the container",
},
},
Action: func(context *cli.Context) error {
// Set up a connection to the server.
conn, err := getClientConnection(context)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewRuntimeServiceClient(conn)
err = RemoveContainer(client, context.String("id"))
if err != nil {
return fmt.Errorf("Removing the container failed: %v", err)
}
return nil
},
}
var containerStatusCommand = cli.Command{
Name: "status",
Usage: "get the status of a container",
Flags: []cli.Flag{
cli.StringFlag{
Name: "id",
Value: "",
Usage: "id of the container",
},
},
Action: func(context *cli.Context) error {
// Set up a connection to the server.
conn, err := getClientConnection(context)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewRuntimeServiceClient(conn)
err = ContainerStatus(client, context.String("id"))
if err != nil {
return fmt.Errorf("Getting the status of the container failed: %v", err)
}
return nil
},
}
var execSyncCommand = cli.Command{
Name: "execsync",
Usage: "exec a command synchronously in a container",
Flags: []cli.Flag{
cli.StringFlag{
Name: "id",
Value: "",
Usage: "id of the container",
},
cli.Int64Flag{
Name: "timeout",
Value: 0,
Usage: "timeout for the command",
},
},
Action: func(context *cli.Context) error {
// Set up a connection to the server.
conn, err := getClientConnection(context)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewRuntimeServiceClient(conn)
err = ExecSync(client, context.String("id"), context.Args(), context.Int64("timeout"))
if err != nil {
return fmt.Errorf("execing command in container failed: %v", err)
}
return nil
},
}
var execCommand = cli.Command{
Name: "exec",
Usage: "prepare a streaming endpoint to execute a command in the container",
Flags: []cli.Flag{
cli.StringFlag{
Name: "id",
Value: "",
Usage: "id of the container",
},
cli.BoolFlag{
Name: "tty",
Usage: "whether to use tty",
},
cli.BoolFlag{
Name: "stdin",
Usage: "whether to stream to stdin",
},
cli.BoolFlag{
Name: "url",
Usage: "do not exec command, just prepare streaming endpoint",
},
},
Action: func(context *cli.Context) error {
// Set up a connection to the server.
conn, err := getClientConnection(context)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewRuntimeServiceClient(conn)
err = Exec(client, context.String("id"), context.Bool("tty"), context.Bool("stdin"), context.Bool("url"), context.Args())
if err != nil {
return fmt.Errorf("execing command in container failed: %v", err)
}
return nil
},
}
type listOptions struct {
// id of the container
id string
// podID of the container
podID string
// state of the container
state string
// quiet is for listing just container IDs
quiet bool
// labels are selectors for the container
labels map[string]string
}
var listContainersCommand = cli.Command{
Name: "list",
Usage: "list containers",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "quiet",
Usage: "list only container IDs",
},
cli.StringFlag{
Name: "id",
Value: "",
Usage: "filter by container id",
},
cli.StringFlag{
Name: "pod",
Value: "",
Usage: "filter by container pod id",
},
cli.StringFlag{
Name: "state",
Value: "",
Usage: "filter by container state",
},
cli.StringSliceFlag{
Name: "label",
Usage: "filter by key=value label",
},
},
Action: func(context *cli.Context) error {
// Set up a connection to the server.
conn, err := getClientConnection(context)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewRuntimeServiceClient(conn)
opts := listOptions{
id: context.String("id"),
podID: context.String("pod"),
state: context.String("state"),
quiet: context.Bool("quiet"),
labels: make(map[string]string),
}
for _, l := range context.StringSlice("label") {
pair := strings.Split(l, "=")
if len(pair) != 2 {
return fmt.Errorf("incorrectly specified label: %v", l)
}
opts.labels[pair[0]] = pair[1]
}
err = ListContainers(client, opts)
if err != nil {
return fmt.Errorf("listing containers failed: %v", err)
}
return nil
},
}
// CreateContainer sends a CreateContainerRequest to the server, and parses
// the returned CreateContainerResponse.
func CreateContainer(client pb.RuntimeServiceClient, opts createOptions) error {
config, err := loadContainerConfig(opts.configPath)
if err != nil {
return err
}
// Override the name by the one specified through CLI
if opts.name != "" {
config.Metadata.Name = opts.name
}
for k, v := range opts.labels {
config.Labels[k] = v
}
r, err := client.CreateContainer(context.Background(), &pb.CreateContainerRequest{
PodSandboxId: opts.podID,
Config: config,
// TODO(runcom): this is missing PodSandboxConfig!!!
// we should/could find a way to retrieve it from the fs and set it here
})
if err != nil {
return err
}
fmt.Println(r.ContainerId)
return nil
}
// StartContainer sends a StartContainerRequest to the server, and parses
// the returned StartContainerResponse.
func StartContainer(client pb.RuntimeServiceClient, ID string) error {
if ID == "" {
return fmt.Errorf("ID cannot be empty")
}
_, err := client.StartContainer(context.Background(), &pb.StartContainerRequest{
ContainerId: ID,
})
if err != nil {
return err
}
fmt.Println(ID)
return nil
}
// StopContainer sends a StopContainerRequest to the server, and parses
// the returned StopContainerResponse.
func StopContainer(client pb.RuntimeServiceClient, ID string) error {
if ID == "" {
return fmt.Errorf("ID cannot be empty")
}
_, err := client.StopContainer(context.Background(), &pb.StopContainerRequest{
ContainerId: ID,
})
if err != nil {
return err
}
fmt.Println(ID)
return nil
}
// RemoveContainer sends a RemoveContainerRequest to the server, and parses
// the returned RemoveContainerResponse.
func RemoveContainer(client pb.RuntimeServiceClient, ID string) error {
if ID == "" {
return fmt.Errorf("ID cannot be empty")
}
_, err := client.RemoveContainer(context.Background(), &pb.RemoveContainerRequest{
ContainerId: ID,
})
if err != nil {
return err
}
fmt.Println(ID)
return nil
}
// ContainerStatus sends a ContainerStatusRequest to the server, and parses
// the returned ContainerStatusResponse.
func ContainerStatus(client pb.RuntimeServiceClient, ID string) error {
if ID == "" {
return fmt.Errorf("ID cannot be empty")
}
r, err := client.ContainerStatus(context.Background(), &pb.ContainerStatusRequest{
ContainerId: ID})
if err != nil {
return err
}
fmt.Printf("ID: %s\n", r.Status.Id)
if r.Status.Metadata != nil {
if r.Status.Metadata.Name != "" {
fmt.Printf("Name: %s\n", r.Status.Metadata.Name)
}
fmt.Printf("Attempt: %v\n", r.Status.Metadata.Attempt)
}
// TODO(mzylowski): print it prettier
fmt.Printf("Status: %s\n", r.Status.State)
ctm := time.Unix(0, r.Status.CreatedAt)
fmt.Printf("Created: %v\n", ctm)
stm := time.Unix(0, r.Status.StartedAt)
fmt.Printf("Started: %v\n", stm)
ftm := time.Unix(0, r.Status.FinishedAt)
fmt.Printf("Finished: %v\n", ftm)
fmt.Printf("Exit Code: %v\n", r.Status.ExitCode)
return nil
}
// ExecSync sends an ExecSyncRequest to the server, and parses
// the returned ExecSyncResponse.
func ExecSync(client pb.RuntimeServiceClient, ID string, cmd []string, timeout int64) error {
if ID == "" {
return fmt.Errorf("ID cannot be empty")
}
r, err := client.ExecSync(context.Background(), &pb.ExecSyncRequest{
ContainerId: ID,
Cmd: cmd,
Timeout: timeout,
})
if err != nil {
return err
}
fmt.Println("Stdout:")
fmt.Println(string(r.Stdout))
fmt.Println("Stderr:")
fmt.Println(string(r.Stderr))
fmt.Printf("Exit code: %v\n", r.ExitCode)
return nil
}
// Exec sends an ExecRequest to the server, and parses
// the returned ExecResponse.
func Exec(client pb.RuntimeServiceClient, ID string, tty bool, stdin bool, urlOnly bool, cmd []string) error {
if ID == "" {
return fmt.Errorf("ID cannot be empty")
}
r, err := client.Exec(context.Background(), &pb.ExecRequest{
ContainerId: ID,
Cmd: cmd,
Tty: tty,
Stdin: stdin,
})
if err != nil {
return err
}
if urlOnly {
fmt.Println("URL:")
fmt.Println(r.Url)
return nil
}
execURL, err := url.Parse(r.Url)
if err != nil {
return err
}
streamExec, err := remotecommand.NewExecutor(&restclient.Config{}, "GET", execURL)
if err != nil {
return err
}
options := remotecommand.StreamOptions{
SupportedProtocols: remotecommandserver.SupportedStreamingProtocols,
Stdout: os.Stdout,
Stderr: os.Stderr,
Tty: tty,
}
if stdin {
options.Stdin = os.Stdin
}
return streamExec.Stream(options)
}
// ListContainers sends a ListContainerRequest to the server, and parses
// the returned ListContainerResponse.
func ListContainers(client pb.RuntimeServiceClient, opts listOptions) error {
filter := &pb.ContainerFilter{}
if opts.id != "" {
filter.Id = opts.id
}
if opts.podID != "" {
filter.PodSandboxId = opts.podID
}
if opts.state != "" {
st := &pb.ContainerStateValue{}
st.State = pb.ContainerState_CONTAINER_UNKNOWN
switch opts.state {
case "created":
st.State = pb.ContainerState_CONTAINER_CREATED
filter.State = st
case "running":
st.State = pb.ContainerState_CONTAINER_RUNNING
filter.State = st
case "stopped":
st.State = pb.ContainerState_CONTAINER_EXITED
filter.State = st
default:
log.Fatalf("--state should be one of created, running or stopped")
}
}
if opts.labels != nil {
filter.LabelSelector = opts.labels
}
r, err := client.ListContainers(context.Background(), &pb.ListContainersRequest{
Filter: filter,
})
if err != nil {
return err
}
for _, c := range r.GetContainers() {
if opts.quiet {
fmt.Println(c.Id)
continue
}
fmt.Printf("ID: %s\n", c.Id)
fmt.Printf("Pod: %s\n", c.PodSandboxId)
if c.Metadata != nil {
if c.Metadata.Name != "" {
fmt.Printf("Name: %s\n", c.Metadata.Name)
}
fmt.Printf("Attempt: %v\n", c.Metadata.Attempt)
}
fmt.Printf("Status: %s\n", c.State)
if c.Image != nil {
fmt.Printf("Image: %s\n", c.Image.Image)
}
ctm := time.Unix(0, c.CreatedAt)
fmt.Printf("Created: %v\n", ctm)
if c.Labels != nil {
fmt.Println("Labels:")
for _, k := range getSortedKeys(c.Labels) {
fmt.Printf("\t%s -> %s\n", k, c.Labels[k])
}
}
if c.Annotations != nil {
fmt.Println("Annotations:")
for _, k := range getSortedKeys(c.Annotations) {
fmt.Printf("\t%s -> %s\n", k, c.Annotations[k])
}
}
fmt.Println()
}
return nil
}

173
cmd/crioctl/image.go Normal file
View file

@ -0,0 +1,173 @@
package main
import (
"fmt"
"github.com/urfave/cli"
"golang.org/x/net/context"
pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
)
var imageCommand = cli.Command{
Name: "image",
Subcommands: []cli.Command{
pullImageCommand,
listImageCommand,
imageStatusCommand,
removeImageCommand,
},
}
var pullImageCommand = cli.Command{
Name: "pull",
Usage: "pull an image",
Action: func(context *cli.Context) error {
// Set up a connection to the server.
conn, err := getClientConnection(context)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewImageServiceClient(conn)
_, err = PullImage(client, context.Args().Get(0))
if err != nil {
return fmt.Errorf("pulling image failed: %v", err)
}
return nil
},
}
var listImageCommand = cli.Command{
Name: "list",
Usage: "list images",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "quiet",
Usage: "list only image IDs",
},
},
Action: func(context *cli.Context) error {
// Set up a connection to the server.
conn, err := getClientConnection(context)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewImageServiceClient(conn)
r, err := ListImages(client, context.Args().Get(0))
if err != nil {
return fmt.Errorf("listing images failed: %v", err)
}
quiet := context.Bool("quiet")
for _, image := range r.Images {
if quiet {
fmt.Printf("%s\n", image.Id)
continue
}
fmt.Printf("ID: %s\n", image.Id)
for _, tag := range image.RepoTags {
fmt.Printf("Tag: %s\n", tag)
}
for _, digest := range image.RepoDigests {
fmt.Printf("Digest: %s\n", digest)
}
if image.Size_ != 0 {
fmt.Printf("Size: %d\n", image.Size_)
}
}
return nil
},
}
var imageStatusCommand = cli.Command{
Name: "status",
Usage: "return the status of an image",
Flags: []cli.Flag{
cli.StringFlag{
Name: "id",
Usage: "id of the image",
},
},
Action: func(context *cli.Context) error {
// Set up a connection to the server.
conn, err := getClientConnection(context)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewImageServiceClient(conn)
r, err := ImageStatus(client, context.String("id"))
if err != nil {
return fmt.Errorf("image status request failed: %v", err)
}
image := r.Image
if image == nil {
return fmt.Errorf("no such image present")
}
fmt.Printf("ID: %s\n", image.Id)
for _, tag := range image.RepoTags {
fmt.Printf("Tag: %s\n", tag)
}
for _, digest := range image.RepoDigests {
fmt.Printf("Digest: %s\n", digest)
}
fmt.Printf("Size: %d\n", image.Size_)
return nil
},
}
var removeImageCommand = cli.Command{
Name: "remove",
Usage: "remove an image",
Flags: []cli.Flag{
cli.StringFlag{
Name: "id",
Value: "",
Usage: "id of the image",
},
},
Action: func(context *cli.Context) error {
// Set up a connection to the server.
conn, err := getClientConnection(context)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewImageServiceClient(conn)
_, err = RemoveImage(client, context.String("id"))
if err != nil {
return fmt.Errorf("removing the image failed: %v", err)
}
return nil
},
}
// PullImage sends a PullImageRequest to the server, and parses
// the returned PullImageResponse.
func PullImage(client pb.ImageServiceClient, image string) (*pb.PullImageResponse, error) {
return client.PullImage(context.Background(), &pb.PullImageRequest{Image: &pb.ImageSpec{Image: image}})
}
// ListImages sends a ListImagesRequest to the server, and parses
// the returned ListImagesResponse.
func ListImages(client pb.ImageServiceClient, image string) (*pb.ListImagesResponse, error) {
return client.ListImages(context.Background(), &pb.ListImagesRequest{Filter: &pb.ImageFilter{Image: &pb.ImageSpec{Image: image}}})
}
// ImageStatus sends an ImageStatusRequest to the server, and parses
// the returned ImageStatusResponse.
func ImageStatus(client pb.ImageServiceClient, image string) (*pb.ImageStatusResponse, error) {
return client.ImageStatus(context.Background(), &pb.ImageStatusRequest{Image: &pb.ImageSpec{Image: image}})
}
// RemoveImage sends a RemoveImageRequest to the server, and parses
// the returned RemoveImageResponse.
func RemoveImage(client pb.ImageServiceClient, image string) (*pb.RemoveImageResponse, error) {
if image == "" {
return nil, fmt.Errorf("ID cannot be empty")
}
return client.RemoveImage(context.Background(), &pb.RemoveImageRequest{Image: &pb.ImageSpec{Image: image}})
}

95
cmd/crioctl/main.go Normal file
View file

@ -0,0 +1,95 @@
package main
import (
"encoding/json"
"fmt"
"net"
"os"
"time"
"github.com/Sirupsen/logrus"
"github.com/urfave/cli"
"google.golang.org/grpc"
pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
)
func getClientConnection(context *cli.Context) (*grpc.ClientConn, error) {
conn, err := grpc.Dial(context.GlobalString("connect"), grpc.WithInsecure(), grpc.WithTimeout(context.GlobalDuration("timeout")),
grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {
return net.DialTimeout("unix", addr, timeout)
}))
if err != nil {
return nil, fmt.Errorf("failed to connect: %v", err)
}
return conn, nil
}
func openFile(path string) (*os.File, error) {
f, err := os.Open(path)
if err != nil {
if os.IsNotExist(err) {
return nil, fmt.Errorf("config at %s not found", path)
}
return nil, err
}
return f, nil
}
func loadPodSandboxConfig(path string) (*pb.PodSandboxConfig, error) {
f, err := openFile(path)
if err != nil {
return nil, err
}
defer f.Close()
var config pb.PodSandboxConfig
if err := json.NewDecoder(f).Decode(&config); err != nil {
return nil, err
}
return &config, nil
}
func loadContainerConfig(path string) (*pb.ContainerConfig, error) {
f, err := openFile(path)
if err != nil {
return nil, err
}
defer f.Close()
var config pb.ContainerConfig
if err := json.NewDecoder(f).Decode(&config); err != nil {
return nil, err
}
return &config, nil
}
func main() {
app := cli.NewApp()
app.Name = "crioctl"
app.Usage = "client for crio"
app.Version = "0.3"
app.Commands = []cli.Command{
podSandboxCommand,
containerCommand,
runtimeVersionCommand,
imageCommand,
}
app.Flags = []cli.Flag{
cli.StringFlag{
Name: "connect",
Value: "/var/run/crio.sock",
Usage: "Socket to connect to",
},
cli.DurationFlag{
Name: "timeout",
Value: 10 * time.Second,
Usage: "Timeout of connecting to server",
},
}
if err := app.Run(os.Args); err != nil {
logrus.Fatal(err)
}
}

387
cmd/crioctl/sandbox.go Normal file
View file

@ -0,0 +1,387 @@
package main
import (
"fmt"
"log"
"sort"
"strings"
"time"
"github.com/urfave/cli"
"golang.org/x/net/context"
pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
)
var podSandboxCommand = cli.Command{
Name: "pod",
Subcommands: []cli.Command{
runPodSandboxCommand,
stopPodSandboxCommand,
removePodSandboxCommand,
podSandboxStatusCommand,
listPodSandboxCommand,
},
}
var runPodSandboxCommand = cli.Command{
Name: "run",
Usage: "run a pod",
Flags: []cli.Flag{
cli.StringFlag{
Name: "config",
Value: "",
Usage: "the path of a pod sandbox config file",
},
cli.StringFlag{
Name: "name",
Value: "",
Usage: "the name of the pod sandbox",
},
cli.StringSliceFlag{
Name: "label",
Usage: "add key=value labels to the container",
},
},
Action: func(context *cli.Context) error {
// Set up a connection to the server.
conn, err := getClientConnection(context)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewRuntimeServiceClient(conn)
opts := createOptions{
configPath: context.String("config"),
name: context.String("name"),
labels: make(map[string]string),
}
for _, l := range context.StringSlice("label") {
pair := strings.Split(l, "=")
if len(pair) != 2 {
return fmt.Errorf("incorrectly specified label: %v", l)
}
opts.labels[pair[0]] = pair[1]
}
// Test RuntimeServiceClient.RunPodSandbox
err = RunPodSandbox(client, opts)
if err != nil {
return fmt.Errorf("Creating the pod sandbox failed: %v", err)
}
return nil
},
}
var stopPodSandboxCommand = cli.Command{
Name: "stop",
Usage: "stop a pod sandbox",
Flags: []cli.Flag{
cli.StringFlag{
Name: "id",
Value: "",
Usage: "id of the pod sandbox",
},
},
Action: func(context *cli.Context) error {
// Set up a connection to the server.
conn, err := getClientConnection(context)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewRuntimeServiceClient(conn)
err = StopPodSandbox(client, context.String("id"))
if err != nil {
return fmt.Errorf("stopping the pod sandbox failed: %v", err)
}
return nil
},
}
var removePodSandboxCommand = cli.Command{
Name: "remove",
Usage: "remove a pod sandbox",
Flags: []cli.Flag{
cli.StringFlag{
Name: "id",
Value: "",
Usage: "id of the pod sandbox",
},
},
Action: func(context *cli.Context) error {
// Set up a connection to the server.
conn, err := getClientConnection(context)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewRuntimeServiceClient(conn)
err = RemovePodSandbox(client, context.String("id"))
if err != nil {
return fmt.Errorf("removing the pod sandbox failed: %v", err)
}
return nil
},
}
var podSandboxStatusCommand = cli.Command{
Name: "status",
Usage: "return the status of a pod",
Flags: []cli.Flag{
cli.StringFlag{
Name: "id",
Value: "",
Usage: "id of the pod",
},
},
Action: func(context *cli.Context) error {
// Set up a connection to the server.
conn, err := getClientConnection(context)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewRuntimeServiceClient(conn)
err = PodSandboxStatus(client, context.String("id"))
if err != nil {
return fmt.Errorf("getting the pod sandbox status failed: %v", err)
}
return nil
},
}
var listPodSandboxCommand = cli.Command{
Name: "list",
Usage: "list pod sandboxes",
Flags: []cli.Flag{
cli.StringFlag{
Name: "id",
Value: "",
Usage: "filter by pod sandbox id",
},
cli.StringFlag{
Name: "state",
Value: "",
Usage: "filter by pod sandbox state",
},
cli.StringSliceFlag{
Name: "label",
Usage: "filter by key=value label",
},
cli.BoolFlag{
Name: "quiet",
Usage: "list only pod IDs",
},
},
Action: func(context *cli.Context) error {
// Set up a connection to the server.
conn, err := getClientConnection(context)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewRuntimeServiceClient(conn)
opts := listOptions{
id: context.String("id"),
state: context.String("state"),
quiet: context.Bool("quiet"),
labels: make(map[string]string),
}
for _, l := range context.StringSlice("label") {
pair := strings.Split(l, "=")
if len(pair) != 2 {
return fmt.Errorf("incorrectly specified label: %v", l)
}
opts.labels[pair[0]] = pair[1]
}
err = ListPodSandboxes(client, opts)
if err != nil {
return fmt.Errorf("listing pod sandboxes failed: %v", err)
}
return nil
},
}
// RunPodSandbox sends a RunPodSandboxRequest to the server, and parses
// the returned RunPodSandboxResponse.
func RunPodSandbox(client pb.RuntimeServiceClient, opts createOptions) error {
config, err := loadPodSandboxConfig(opts.configPath)
if err != nil {
return err
}
// Override the name by the one specified through CLI
if opts.name != "" {
config.Metadata.Name = opts.name
}
for k, v := range opts.labels {
config.Labels[k] = v
}
r, err := client.RunPodSandbox(context.Background(), &pb.RunPodSandboxRequest{Config: config})
if err != nil {
return err
}
fmt.Println(r.PodSandboxId)
return nil
}
// StopPodSandbox sends a StopPodSandboxRequest to the server, and parses
// the returned StopPodSandboxResponse.
func StopPodSandbox(client pb.RuntimeServiceClient, ID string) error {
if ID == "" {
return fmt.Errorf("ID cannot be empty")
}
_, err := client.StopPodSandbox(context.Background(), &pb.StopPodSandboxRequest{PodSandboxId: ID})
if err != nil {
return err
}
fmt.Println(ID)
return nil
}
// RemovePodSandbox sends a RemovePodSandboxRequest to the server, and parses
// the returned RemovePodSandboxResponse.
func RemovePodSandbox(client pb.RuntimeServiceClient, ID string) error {
if ID == "" {
return fmt.Errorf("ID cannot be empty")
}
_, err := client.RemovePodSandbox(context.Background(), &pb.RemovePodSandboxRequest{PodSandboxId: ID})
if err != nil {
return err
}
fmt.Println(ID)
return nil
}
// PodSandboxStatus sends a PodSandboxStatusRequest to the server, and parses
// the returned PodSandboxStatusResponse.
func PodSandboxStatus(client pb.RuntimeServiceClient, ID string) error {
if ID == "" {
return fmt.Errorf("ID cannot be empty")
}
r, err := client.PodSandboxStatus(context.Background(), &pb.PodSandboxStatusRequest{PodSandboxId: ID})
if err != nil {
return err
}
fmt.Printf("ID: %s\n", r.Status.Id)
if r.Status.Metadata != nil {
if r.Status.Metadata.Name != "" {
fmt.Printf("Name: %s\n", r.Status.Metadata.Name)
}
if r.Status.Metadata.Uid != "" {
fmt.Printf("UID: %s\n", r.Status.Metadata.Uid)
}
if r.Status.Metadata.Namespace != "" {
fmt.Printf("Namespace: %s\n", r.Status.Metadata.Namespace)
}
fmt.Printf("Attempt: %v\n", r.Status.Metadata.Attempt)
}
fmt.Printf("Status: %s\n", r.Status.State)
ctm := time.Unix(0, r.Status.CreatedAt)
fmt.Printf("Created: %v\n", ctm)
fmt.Printf("Network namespace: %s\n", r.Status.Linux.Namespaces.Network)
if r.Status.Network != nil {
fmt.Printf("IP Address: %v\n", r.Status.Network.Ip)
}
if r.Status.Labels != nil {
fmt.Println("Labels:")
for _, k := range getSortedKeys(r.Status.Labels) {
fmt.Printf("\t%s -> %s\n", k, r.Status.Labels[k])
}
}
if r.Status.Annotations != nil {
fmt.Println("Annotations:")
for _, k := range getSortedKeys(r.Status.Annotations) {
fmt.Printf("\t%s -> %s\n", k, r.Status.Annotations[k])
}
}
return nil
}
// ListPodSandboxes sends a ListPodSandboxRequest to the server, and parses
// the returned ListPodSandboxResponse.
func ListPodSandboxes(client pb.RuntimeServiceClient, opts listOptions) error {
filter := &pb.PodSandboxFilter{}
if opts.id != "" {
filter.Id = opts.id
}
if opts.state != "" {
st := &pb.PodSandboxStateValue{}
st.State = pb.PodSandboxState_SANDBOX_NOTREADY
switch opts.state {
case "ready":
st.State = pb.PodSandboxState_SANDBOX_READY
filter.State = st
case "notready":
st.State = pb.PodSandboxState_SANDBOX_NOTREADY
filter.State = st
default:
log.Fatalf("--state should be ready or notready")
}
}
if opts.labels != nil {
filter.LabelSelector = opts.labels
}
r, err := client.ListPodSandbox(context.Background(), &pb.ListPodSandboxRequest{
Filter: filter,
})
if err != nil {
return err
}
for _, pod := range r.Items {
if opts.quiet {
fmt.Println(pod.Id)
continue
}
fmt.Printf("ID: %s\n", pod.Id)
if pod.Metadata != nil {
if pod.Metadata.Name != "" {
fmt.Printf("Name: %s\n", pod.Metadata.Name)
}
if pod.Metadata.Uid != "" {
fmt.Printf("UID: %s\n", pod.Metadata.Uid)
}
if pod.Metadata.Namespace != "" {
fmt.Printf("Namespace: %s\n", pod.Metadata.Namespace)
}
fmt.Printf("Attempt: %v\n", pod.Metadata.Attempt)
}
fmt.Printf("Status: %s\n", pod.State)
ctm := time.Unix(0, pod.CreatedAt)
fmt.Printf("Created: %v\n", ctm)
if pod.Labels != nil {
fmt.Println("Labels:")
for _, k := range getSortedKeys(pod.Labels) {
fmt.Printf("\t%s -> %s\n", k, pod.Labels[k])
}
}
if pod.Annotations != nil {
fmt.Println("Annotations:")
for _, k := range getSortedKeys(pod.Annotations) {
fmt.Printf("\t%s -> %s\n", k, pod.Annotations[k])
}
}
fmt.Println()
}
return nil
}
func getSortedKeys(m map[string]string) []string {
var keys []string
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
return keys
}

41
cmd/crioctl/system.go Normal file
View file

@ -0,0 +1,41 @@
package main
import (
"fmt"
"github.com/urfave/cli"
"golang.org/x/net/context"
pb "k8s.io/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
)
var runtimeVersionCommand = cli.Command{
Name: "runtimeversion",
Usage: "get runtime version information",
Action: func(context *cli.Context) error {
// Set up a connection to the server.
conn, err := getClientConnection(context)
if err != nil {
return fmt.Errorf("failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewRuntimeServiceClient(conn)
// Test RuntimeServiceClient.Version
version := "v1alpha1"
err = Version(client, version)
if err != nil {
return fmt.Errorf("Getting the runtime version failed: %v", err)
}
return nil
},
}
// Version sends a VersionRequest to the server, and parses the returned VersionResponse.
func Version(client pb.RuntimeServiceClient, version string) error {
r, err := client.Version(context.Background(), &pb.VersionRequest{Version: version})
if err != nil {
return err
}
fmt.Printf("VersionResponse: Version: %s, RuntimeName: %s, RuntimeVersion: %s, RuntimeApiVersion: %s\n", r.Version, r.RuntimeName, r.RuntimeVersion, r.RuntimeApiVersion)
return nil
}