github.com/alibaba/ilogtail/pkg@v0.0.0-20250526110833-c53b480d046c/helper/containercenter/cri_runtime_api_interface.go (about) 1 // Copyright 2025 iLogtail Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package containercenter 16 17 import ( 18 "context" 19 "fmt" 20 "time" 21 22 "github.com/alibaba/ilogtail/pkg/logger" 23 24 "google.golang.org/grpc" 25 ) 26 27 type CriContainerState int32 28 29 const ( 30 ContainerStateContainerCreated CriContainerState = 0 31 ContainerStateContainerRunning CriContainerState = 1 32 ContainerStateContainerExited CriContainerState = 2 33 ContainerStateContainerUnknown CriContainerState = 3 34 ) 35 36 type CriMountPropagation int32 37 38 const ( 39 MountPropagationPropagationPrivate CriMountPropagation = 0 40 MountPropagationPropagationHostToContainer CriMountPropagation = 1 41 MountPropagationPropagationBidirectional CriMountPropagation = 2 42 ) 43 44 type CriVersionInfo struct { 45 Version string 46 RuntimeName string 47 RuntimeVersion string 48 RuntimeAPIVersion string 49 } 50 51 type CriVersionResponse struct { 52 Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` 53 RuntimeName string `protobuf:"bytes,2,opt,name=runtime_name,proto3" json:"runtime_name,omitempty"` 54 RuntimeVersion string `protobuf:"bytes,3,opt,name=runtime_version,proto3" json:"runtime_version,omitempty"` 55 RuntimeAPIVersion string `protobuf:"bytes,4,opt,name=runtime_api_version,proto3" json:"runtime_api_version,omitempty"` 56 } 57 58 type CriContainerMetadata struct { 59 Name string 60 Attempt uint32 61 } 62 63 type CriImageSpec struct { 64 Image string 65 Annotations map[string]string 66 } 67 68 type CriContainer struct { 69 ID string 70 PodSandboxID string 71 Metadata *CriContainerMetadata 72 Image *CriImageSpec 73 ImageRef string 74 State CriContainerState 75 CreatedAt int64 76 Labels map[string]string 77 Annotations map[string]string 78 } 79 80 type CriListContainersResponse struct { 81 Containers []*CriContainer 82 } 83 84 type CriMount struct { 85 ContainerPath string 86 HostPath string 87 Readonly bool 88 SelinuxRelabel bool 89 Propagation CriMountPropagation 90 } 91 92 type CriContainerStatus struct { 93 ID string 94 Metadata *CriContainerMetadata 95 State CriContainerState 96 CreatedAt int64 97 StartedAt int64 98 FinishedAt int64 99 ExitCode int32 100 Image *CriImageSpec 101 ImageRef string 102 Reason string 103 Message string 104 Labels map[string]string 105 Annotations map[string]string 106 Mounts []*CriMount 107 LogPath string 108 } 109 110 type CriContainerStatusResponse struct { 111 Status *CriContainerStatus 112 Info map[string]string 113 } 114 115 type CriPodSandboxMetadata struct { 116 Name string 117 UID string 118 Namespace string 119 Attempt uint32 120 } 121 122 type CriPodSandbox struct { 123 ID string 124 Metadata *CriPodSandboxMetadata 125 State CriContainerState 126 CreatedAt int64 127 Labels map[string]string 128 Annotations map[string]string 129 RuntimeHandler string 130 } 131 132 type CriListPodSandboxResponse struct { 133 Items []*CriPodSandbox 134 } 135 136 type CriPodSandboxStatus struct { 137 ID string 138 Metadata *CriPodSandboxMetadata 139 State CriContainerState 140 CreatedAt int64 141 Labels map[string]string 142 Annotations map[string]string 143 RuntimeHandler string 144 } 145 146 type CriPodSandboxStatusResponse struct { 147 Status *CriPodSandboxStatus 148 Info map[string]string 149 } 150 151 type RuntimeService interface { 152 Version(ctx context.Context) (*CriVersionResponse, error) 153 ListContainers(ctx context.Context) (*CriListContainersResponse, error) 154 ContainerStatus(ctx context.Context, containerID string, verbose bool) (*CriContainerStatusResponse, error) 155 ListPodSandbox(ctx context.Context) (*CriListPodSandboxResponse, error) 156 PodSandboxStatus(ctx context.Context, sandboxID string, verbose bool) (*CriPodSandboxStatusResponse, error) 157 } 158 159 type RuntimeServiceClient struct { 160 service RuntimeService 161 info CriVersionInfo 162 conn *grpc.ClientConn 163 } 164 165 var ( // for mock 166 getAddressAndDialer = GetAddressAndDialer 167 grpcDialContext = grpc.DialContext 168 ) 169 170 func NewRuntimeServiceClient(contextTimeout time.Duration, grpcMaxCallRecvMsgSize int) (*RuntimeServiceClient, error) { 171 addr, dailer, err := getAddressAndDialer(containerdUnixSocket) 172 if err != nil { 173 return nil, err 174 } 175 ctx, cancel := getContextWithTimeout(contextTimeout) 176 defer cancel() 177 178 conn, err := grpcDialContext(ctx, addr, grpc.WithInsecure(), grpc.WithDialer(dailer), grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(grpcMaxCallRecvMsgSize))) 179 if err != nil { 180 return nil, err 181 } 182 183 client := &RuntimeServiceClient{ 184 conn: conn, 185 } 186 // Try v1 first 187 client.service = newCRIRuntimeServiceV1Adapter(conn) 188 if client.getVersion(ctx) == nil { 189 logger.Info(ctx, "Init cri client v1 success, cri info", client.info) 190 return client, nil 191 } 192 193 // Fallback to v1alpha2 194 client.service = newCRIRuntimeServiceV1Alpha2Adapter(conn) 195 if client.getVersion(ctx) == nil { 196 logger.Info(ctx, "Init cri client v1alpha2 success, cri info", client.info) 197 return client, nil 198 } 199 200 // if create client failed, close the connection 201 _ = conn.Close() 202 return nil, fmt.Errorf("failed to initialize RuntimeServiceClient") 203 } 204 205 func (c *RuntimeServiceClient) Version(ctx context.Context) (*CriVersionResponse, error) { 206 if c.service != nil { 207 return c.service.Version(ctx) 208 } 209 return &CriVersionResponse{}, fmt.Errorf("invalid RuntimeServiceClient") 210 } 211 212 func (c *RuntimeServiceClient) ListContainers(ctx context.Context) (*CriListContainersResponse, error) { 213 if c.service != nil { 214 return c.service.ListContainers(ctx) 215 } 216 return &CriListContainersResponse{}, fmt.Errorf("invalid RuntimeServiceClient") 217 } 218 219 func (c *RuntimeServiceClient) ContainerStatus(ctx context.Context, containerID string, verbose bool) (*CriContainerStatusResponse, error) { 220 if c.service != nil { 221 return c.service.ContainerStatus(ctx, containerID, verbose) 222 } 223 return &CriContainerStatusResponse{}, fmt.Errorf("invalid RuntimeServiceClient") 224 } 225 226 func (c *RuntimeServiceClient) ListPodSandbox(ctx context.Context) (*CriListPodSandboxResponse, error) { 227 if c.service != nil { 228 return c.service.ListPodSandbox(ctx) 229 } 230 return &CriListPodSandboxResponse{}, fmt.Errorf("invalid RuntimeServiceClient") 231 } 232 233 func (c *RuntimeServiceClient) PodSandboxStatus(ctx context.Context, sandboxID string, verbose bool) (*CriPodSandboxStatusResponse, error) { 234 if c.service != nil { 235 return c.service.PodSandboxStatus(ctx, sandboxID, verbose) 236 } 237 return &CriPodSandboxStatusResponse{}, fmt.Errorf("invalid RuntimeServiceClient") 238 } 239 240 func (c *RuntimeServiceClient) getVersion(ctx context.Context) error { 241 versionResp, err := c.service.Version(ctx) 242 if err == nil { 243 c.info = CriVersionInfo{ 244 versionResp.Version, 245 versionResp.RuntimeName, 246 versionResp.RuntimeVersion, 247 versionResp.RuntimeAPIVersion, 248 } 249 } 250 return err 251 } 252 253 func (c *RuntimeServiceClient) Close() { 254 if c.conn != nil { 255 _ = c.conn.Close() 256 } 257 }