client.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // Copyright 2017 Google Inc. All Rights Reserved.
  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. package containerd
  15. import (
  16. "context"
  17. "fmt"
  18. "net"
  19. "sync"
  20. "time"
  21. containersapi "github.com/containerd/containerd/api/services/containers/v1"
  22. tasksapi "github.com/containerd/containerd/api/services/tasks/v1"
  23. versionapi "github.com/containerd/containerd/api/services/version/v1"
  24. "github.com/containerd/containerd/containers"
  25. "github.com/containerd/containerd/dialer"
  26. "github.com/containerd/containerd/errdefs"
  27. ptypes "github.com/gogo/protobuf/types"
  28. "google.golang.org/grpc"
  29. )
  30. type client struct {
  31. containerService containersapi.ContainersClient
  32. taskService tasksapi.TasksClient
  33. versionService versionapi.VersionClient
  34. }
  35. type containerdClient interface {
  36. LoadContainer(ctx context.Context, id string) (*containers.Container, error)
  37. TaskPid(ctx context.Context, id string) (uint32, error)
  38. Version(ctx context.Context) (string, error)
  39. }
  40. var once sync.Once
  41. var ctrdClient containerdClient = nil
  42. const (
  43. maxBackoffDelay = 3 * time.Second
  44. connectionTimeout = 2 * time.Second
  45. )
  46. // Client creates a containerd client
  47. func Client(address, namespace string) (containerdClient, error) {
  48. var retErr error
  49. once.Do(func() {
  50. tryConn, err := net.DialTimeout("unix", address, connectionTimeout)
  51. if err != nil {
  52. retErr = fmt.Errorf("containerd: cannot unix dial containerd api service: %v", err)
  53. return
  54. }
  55. tryConn.Close()
  56. gopts := []grpc.DialOption{
  57. grpc.WithInsecure(),
  58. grpc.WithDialer(dialer.Dialer),
  59. grpc.WithBlock(),
  60. grpc.WithBackoffMaxDelay(maxBackoffDelay),
  61. grpc.WithTimeout(connectionTimeout),
  62. }
  63. unary, stream := newNSInterceptors(namespace)
  64. gopts = append(gopts,
  65. grpc.WithUnaryInterceptor(unary),
  66. grpc.WithStreamInterceptor(stream),
  67. )
  68. conn, err := grpc.Dial(dialer.DialAddress(address), gopts...)
  69. if err != nil {
  70. retErr = err
  71. return
  72. }
  73. ctrdClient = &client{
  74. containerService: containersapi.NewContainersClient(conn),
  75. taskService: tasksapi.NewTasksClient(conn),
  76. versionService: versionapi.NewVersionClient(conn),
  77. }
  78. })
  79. return ctrdClient, retErr
  80. }
  81. func (c *client) LoadContainer(ctx context.Context, id string) (*containers.Container, error) {
  82. r, err := c.containerService.Get(ctx, &containersapi.GetContainerRequest{
  83. ID: id,
  84. })
  85. if err != nil {
  86. return nil, errdefs.FromGRPC(err)
  87. }
  88. return containerFromProto(r.Container), nil
  89. }
  90. func (c *client) TaskPid(ctx context.Context, id string) (uint32, error) {
  91. response, err := c.taskService.Get(ctx, &tasksapi.GetRequest{
  92. ContainerID: id,
  93. })
  94. if err != nil {
  95. return 0, errdefs.FromGRPC(err)
  96. }
  97. return response.Process.Pid, nil
  98. }
  99. func (c *client) Version(ctx context.Context) (string, error) {
  100. response, err := c.versionService.Version(ctx, &ptypes.Empty{})
  101. if err != nil {
  102. return "", errdefs.FromGRPC(err)
  103. }
  104. return response.Version, nil
  105. }
  106. func containerFromProto(containerpb containersapi.Container) *containers.Container {
  107. var runtime containers.RuntimeInfo
  108. if containerpb.Runtime != nil {
  109. runtime = containers.RuntimeInfo{
  110. Name: containerpb.Runtime.Name,
  111. Options: containerpb.Runtime.Options,
  112. }
  113. }
  114. return &containers.Container{
  115. ID: containerpb.ID,
  116. Labels: containerpb.Labels,
  117. Image: containerpb.Image,
  118. Runtime: runtime,
  119. Spec: containerpb.Spec,
  120. Snapshotter: containerpb.Snapshotter,
  121. SnapshotKey: containerpb.SnapshotKey,
  122. Extensions: containerpb.Extensions,
  123. }
  124. }