1263e54396
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
593 lines
14 KiB
Go
593 lines
14 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"net"
|
|
"os"
|
|
"time"
|
|
|
|
pb "github.com/kubernetes/kubernetes/pkg/kubelet/api/v1alpha1/runtime"
|
|
"github.com/urfave/cli"
|
|
"golang.org/x/net/context"
|
|
"google.golang.org/grpc"
|
|
)
|
|
|
|
var (
|
|
unixDomainSocket string
|
|
)
|
|
|
|
const (
|
|
// TODO: Make configurable
|
|
timeout = 10 * time.Second
|
|
)
|
|
|
|
func getClientConnection() (*grpc.ClientConn, error) {
|
|
conn, err := grpc.Dial(unixDomainSocket, grpc.WithInsecure(), grpc.WithTimeout(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
|
|
}
|
|
|
|
// CreatePodSandbox sends a CreatePodSandboxRequest to the server, and parses
|
|
// the returned CreatePodSandboxResponse.
|
|
func CreatePodSandbox(client pb.RuntimeServiceClient, path string) error {
|
|
config, err := loadPodSandboxConfig(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
r, err := client.CreatePodSandbox(context.Background(), &pb.CreatePodSandboxRequest{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.Println(r)
|
|
return nil
|
|
}
|
|
|
|
// CreateContainer sends a CreateContainerRequest to the server, and parses
|
|
// the returned CreateContainerResponse.
|
|
func CreateContainer(client pb.RuntimeServiceClient, sandbox string, path string) error {
|
|
config, err := loadContainerConfig(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
r, err := client.CreateContainer(context.Background(), &pb.CreateContainerRequest{
|
|
PodSandboxId: &sandbox,
|
|
Config: config,
|
|
})
|
|
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.State != nil {
|
|
fmt.Printf("Status: %s\n", r.Status.State)
|
|
}
|
|
if r.Status.CreatedAt != nil {
|
|
ctm := time.Unix(*r.Status.CreatedAt, 0)
|
|
fmt.Printf("Created: %v\n", ctm)
|
|
}
|
|
if r.Status.StartedAt != nil {
|
|
stm := time.Unix(*r.Status.StartedAt, 0)
|
|
fmt.Printf("Started: %v\n", stm)
|
|
}
|
|
if r.Status.FinishedAt != nil {
|
|
ftm := time.Unix(*r.Status.FinishedAt, 0)
|
|
fmt.Printf("Finished: %v\n", ftm)
|
|
}
|
|
if r.Status.ExitCode != nil {
|
|
fmt.Printf("Exit Code: %v\n", *r.Status.ExitCode)
|
|
}
|
|
|
|
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
|
|
}
|
|
log.Printf("VersionResponse: Version: %s, RuntimeName: %s, RuntimeVersion: %s, RuntimeApiVersion: %s\n", *r.Version, *r.RuntimeName, *r.RuntimeVersion, *r.RuntimeApiVersion)
|
|
return nil
|
|
}
|
|
|
|
func main() {
|
|
app := cli.NewApp()
|
|
app.Name = "ocic"
|
|
app.Usage = "client for ocid"
|
|
app.Version = "0.0.1"
|
|
|
|
app.Commands = []cli.Command{
|
|
podSandboxCommand,
|
|
containerCommand,
|
|
runtimeVersionCommand,
|
|
pullImageCommand,
|
|
}
|
|
|
|
app.Flags = []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "sock",
|
|
Value: "/var/run/ocid.sock",
|
|
Usage: "Socket to connect to",
|
|
Destination: &unixDomainSocket,
|
|
},
|
|
}
|
|
|
|
if err := app.Run(os.Args); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|
|
|
|
// PullImage sends a PullImageRequest to the server, and parses
|
|
// the returned ContainerStatusResponse.
|
|
func PullImage(client pb.ImageServiceClient, image string) (*pb.PullImageResponse, error) {
|
|
return client.PullImage(context.Background(), &pb.PullImageRequest{Image: &pb.ImageSpec{Image: &image}})
|
|
}
|
|
|
|
// try this with ./ocic pullimage docker://busybox
|
|
var pullImageCommand = cli.Command{
|
|
Name: "pullimage",
|
|
Usage: "pull an image",
|
|
Action: func(context *cli.Context) error {
|
|
// Set up a connection to the server.
|
|
conn, err := getClientConnection()
|
|
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 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()
|
|
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
|
|
},
|
|
}
|
|
|
|
var podSandboxCommand = cli.Command{
|
|
Name: "pod",
|
|
Subcommands: []cli.Command{
|
|
createPodSandboxCommand,
|
|
stopPodSandboxCommand,
|
|
removePodSandboxCommand,
|
|
podSandboxStatusCommand,
|
|
},
|
|
}
|
|
|
|
var createPodSandboxCommand = cli.Command{
|
|
Name: "create",
|
|
Usage: "create a pod",
|
|
Flags: []cli.Flag{
|
|
cli.StringFlag{
|
|
Name: "config",
|
|
Value: "config.json",
|
|
Usage: "the path of a pod sandbox config file",
|
|
},
|
|
},
|
|
Action: func(context *cli.Context) error {
|
|
// Set up a connection to the server.
|
|
conn, err := getClientConnection()
|
|
if err != nil {
|
|
return fmt.Errorf("failed to connect: %v", err)
|
|
}
|
|
defer conn.Close()
|
|
client := pb.NewRuntimeServiceClient(conn)
|
|
|
|
// Test RuntimeServiceClient.CreatePodSandbox
|
|
err = CreatePodSandbox(client, context.String("config"))
|
|
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()
|
|
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()
|
|
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()
|
|
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 containerCommand = cli.Command{
|
|
Name: "container",
|
|
Aliases: []string{"ctr"},
|
|
Subcommands: []cli.Command{
|
|
createContainerCommand,
|
|
startContainerCommand,
|
|
stopContainerCommand,
|
|
removeContainerCommand,
|
|
containerStatusCommand,
|
|
},
|
|
}
|
|
|
|
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",
|
|
},
|
|
},
|
|
Action: func(context *cli.Context) error {
|
|
// Set up a connection to the server.
|
|
conn, err := getClientConnection()
|
|
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")
|
|
}
|
|
// Test RuntimeServiceClient.CreateContainer
|
|
err = CreateContainer(client, context.String("pod"), context.String("config"))
|
|
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()
|
|
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()
|
|
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()
|
|
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()
|
|
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
|
|
},
|
|
}
|