/
cri.go
131 lines (109 loc) · 3.55 KB
/
cri.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
// Package cri implements calls to the CRI RuntimeEndpoint to get information about Containers.
package cri
import (
"encoding/json"
"fmt"
"time"
"github.com/urfave/cli"
"golang.org/x/net/context"
"google.golang.org/grpc"
pb "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
"k8s.io/kubernetes/pkg/kubelet/util"
)
var (
// RuntimeEndpoint is CRI server runtime endpoint
RuntimeEndpoint string
// Timeout of connecting to server
Timeout time.Duration
)
// CriParameters
type CriParameters struct {
RuntimeEndpoint string
Timeout time.Duration
}
// DefaultCriParameters
func DefaultContainerdCriParameters() CriParameters {
params := CriParameters{}
params.RuntimeEndpoint = "tcp://127.0.0.1:2376"
params.Timeout = 2 * time.Second
return params
}
// ContainerInfo
type ContainerInfo struct {
ContainerId string
NamespaceId string
}
// ListContainers
func ListContainers(criParameters CriParameters) (containers []ContainerInfo, err error) {
foundContainers := []ContainerInfo{}
// Connect to the CRI Endpoint
RuntimeEndpoint = criParameters.RuntimeEndpoint
Timeout = criParameters.Timeout
app := cli.NewApp()
ctx := cli.NewContext(app, nil, nil)
runtimeClient, runtimeConn, err := getRuntimeClient(ctx)
if err != nil {
return nil, err
}
defer closeConnection(ctx, runtimeConn)
request := &pb.ListContainersRequest{}
response, err := runtimeClient.ListContainers(context.Background(), request)
if err != nil {
return nil, err
}
criContainers := response.GetContainers()
for _, container := range criContainers {
containerStatusRequest := &pb.ContainerStatusRequest{
ContainerId: container.Id,
Verbose: true, // Populates the info json
}
containerStatusResponse, err := runtimeClient.ContainerStatus(context.Background(), containerStatusRequest)
if err != nil {
return nil, err
}
// Read the info json
info := containerStatusResponse.Info["info"]
var infoMap map[string]interface{}
json.Unmarshal([]byte(info), &infoMap)
runtimeSpec := infoMap["runtimeSpec"].(map[string]interface{})
windows := runtimeSpec["windows"].(map[string]interface{})
network := windows["network"].(map[string]interface{})
networkNamespace := network["networkNamespace"].(string)
foundContainer := ContainerInfo{
ContainerId: container.Id,
NamespaceId: networkNamespace,
}
foundContainers = append(foundContainers, foundContainer)
}
return foundContainers, nil
}
// Copied from https://github.com/kubernetes-sigs/cri-tools/cmd/crictl/util.go
func getRuntimeClient(context *cli.Context) (pb.RuntimeServiceClient, *grpc.ClientConn, error) {
// Set up a connection to the server.
conn, err := getRuntimeClientConnection(context)
if err != nil {
return nil, nil, fmt.Errorf("failed to connect: %v", err)
}
runtimeClient := pb.NewRuntimeServiceClient(conn)
return runtimeClient, conn, nil
}
func closeConnection(context *cli.Context, conn *grpc.ClientConn) error {
if conn == nil {
return nil
}
return conn.Close()
}
// Copied from https://github.com/kubernetes-sigs/cri-tools/cmd/crictl/main.go
func getRuntimeClientConnection(context *cli.Context) (*grpc.ClientConn, error) {
addr, dialer, err := util.GetAddressAndDialer(RuntimeEndpoint)
if err != nil {
return nil, err
}
conn, err := grpc.Dial(addr, grpc.WithInsecure(), grpc.WithBlock(), grpc.WithTimeout(Timeout), grpc.WithDialer(dialer))
if err != nil {
return nil, fmt.Errorf("failed to connect, make sure you are running as root and the runtime has been started: %v", err)
}
return conn, nil
}