Build own Kubernetes - Pods listing and deletion
Tags: kubernetes, go, devops, programming
Published: 2022-10-07 14:05:43

In the previous article, we created and run the pods, in this article we will list and delete pods on command.

Before this article I had some refactor the code, The methods related to Pod and RunningPod structs are in pkg/pod/pod.go and access functions to run operations related to pods like creating a new pod is in pkg/pod/service.go

---
We want to List all the running pods, we implement a simple function in pkg/pod/service.go to list all the existing tasks:
```go
func initContainerdConnection() (*containerd.Client, context.Context, error) {
	client, err := containerd.New(SOCKET_PATH)
	if err != nil {
		return nil, nil, err
	}

	ctx := namespaces.WithNamespace(context.Background(), NAMESPACE)

	return client, ctx, nil
}

func ListRunningPods() ([]string, error) {
	client, ctx, err := initContainerdConnection()
	if err != nil {
		return nil, err
	}

	runningPods := []string{}

	containers, err := client.Containers(ctx)
	if err != nil {
		return runningPods, err
	}

	for _, container := range containers {
		_, err = container.Task(ctx, cio.Load)

		if err == nil {
			runningPods = append(runningPods, container.ID())
		}
	}

	return runningPods, nil
}

```
The initContainerdConnection function was created on the refactor phase, this function is called to create a client and ctx to make operations on containerd.
The function goes through every existing container and tries to Load to it, if no error returns this means there is a running task on the container, meaning the pod is running.

In the cmd/pod.go
```go
var listCmd = &cobra.Command{
	Use:   "list",
	Short: "lists existing pods",
	RunE: func(cmd *cobra.Command, args []string) error {
		runningPods, err := pod.ListRunningPods()
		if err != nil {
			return err
		}

		for _, pod := range runningPods {
			fmt.Println(pod)
		}

		return nil
	},
}
```

Let's check (for this I commented the kill and deletion of the pod creation):
```bash
❯ sudo ./main pod create --registry docker.io/library/redis:alpine --name redis
pod created: redis-9079a2e3-87a0-4a08-8b96-14926b6edb45
starting pod
pod started: redis-9079a2e3-87a0-4a08-8b96-14926b6edb45
❯ sudo ./main pod list
redis-9079a2e3-87a0-4a08-8b96-14926b6edb45
```
great, It works!

Now let's focus on the delete command, we want the delete to accept a pod id and delete it, it prints the deleted pod id.
So in cmd/pkd/pod.go:
```go
var killCmd = &cobra.Command{
	Use:   "kill",
	Short: "kill existing pod",
	RunE: func(cmd *cobra.Command, args []string) error {
		id, err := pod.KillPod(name)
		if err != nil {
			return err
		}

		fmt.Println(id)

		return nil
	},
}

func init() {
.
.
.

	podCmd.AddCommand(killCmd)
	killCmd.Flags().StringVar(&name, "id", "", "the pod id (required)")
	killCmd.MarkFlagRequired("id")
}

```
Now in the pkg/pod/service.go, we add a KillPod function, which searches for a container and container's task, creates from it a Pod and RunningPod struct, and executes the Kill and Delete methods. The creation of the structs is for the kill and delete to be handled properly.
```go
func KillPod(name string) (string, error) {
	client, ctx, err := initContainerdConnection()
	if err != nil {
		return "", err
	}

	container, err := client.LoadContainer(ctx, name)
	if err != nil {
		return "", err
	}

	task, err := container.Task(ctx, cio.Load)
	if err != nil {
		return "", err
	}

	exitStatusC, err := task.Wait(ctx)
	if err != nil {
		return "", err
	}

	runningPod := RunningPod{
		task: &task,
		Pod: &Pod{
			client:    client,
			ctx:       &ctx,
			container: &container,
			Id:        name,
		},
		exitStatusC: exitStatusC,
	}

	_, err = runningPod.Kill()
	if err != nil {
		return "", err
	}

	runningPod.Pod.Delete()

	return name, nil
}

```
Let's test our changes:
```bash
❯ sudo ./main pod create --registry docker.io/library/redis:alpine --name redis
pod created: redis-3f6f15fb-ff52-4d61-937f-db01d02f1b61
starting pod
❯ sudo ./main pod list
redis-3f6f15fb-ff52-4d61-937f-db01d02f1b61
❯ sudo ./main pod kill --id redis-3f6f15fb-ff52-4d61-937f-db01d02f1b61
redis-3f6f15fb-ff52-4d61-937f-db01d02f1b61
❯ sudo ./main pod list
```
Great, it works!

---
On the next article we will focus on Node setup and agent.

The full source code can be found [here](https://github.com/jonatan5524/own-kubernetes), the changes were in pkg/pod/service.go and cmd/pod.go.