hisamounaのブログ

アウトプットを習慣化するためのブログ

node上のpod一覧を表示する画面を作成する ~ (1) Goでサーバを構築 ~

はじめに

フロントエンドの勉強をしてみたくなったので、Reactを触ってみました。

以前作ったGoのコードをベースにサーバーを構築し、ReactからAPIリクエストでnodeの情報を取得しブラウザ上で表示するようにしていきます。 hisamouna.hatenablog.com

本記事では、サーバの構築をしていきます。

コード

Protocol Buffersでリクエスト/レスポンスのインターフェースを定義

message NodesResponse {
  repeated Node nodes = 1;
}

message Node {
  string name = 1;
  repeated Pod pods = 2;
}

message Pod {
  string namespace = 1;
  string name = 2;
}

service NodeService {
  rpc DescribeNodes(google.protobuf.Empty) returns (NodesResponse) {
    option (google.api.http) = {
      get: "/v1/node/describe"
    };
  }
}

gRPCのコードを生成

└─> protoc -I ./pkg/server/node -I ${GOPATH}/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis --go_out ./pkg/server/node --go_opt paths=source_relative --go-grpc_out ./pkg/server/node --go-grpc_opt paths=source_relative --grpc-gateway_out ./pkg/server/node --grpc-gateway_opt paths=source_relative ./pkg/server/node/node.proto

"google/protobuf/empty.proto";を使うときに注意すること

github.com

Unimplemented~をhandler用structに定義

type NodeHandler struct {
    node.UnimplementedNodeServiceServer
}

gRPCで定義されたインターフェースを満たすHandlerを作成

より良いエラーハンドリングを模索中、、、今回は、どこでエラーが発生したかを明確にしてみました。

func (handler *NodeHandler) DescribeNodes(ctx context.Context, in *emptypb.Empty) (*node.NodesResponse, error) {
    fmt.Println("handler.DescribeNodes")
    kc, err := kube.NewClient("kind_config")
    if err != nil {
        return nil, fmt.Errorf("DescribeNode(kueb.NewClient): %v", err)
    }
    nodes, err := kc.GetNodes()
    if err != nil {
        return nil, fmt.Errorf("GetNode(kueb.GetNodes): %v", err)
    }

    var response = &node.NodesResponse{}
    for _, nd := range nodes {
        dn, err := kc.DescribeNode(nd)
        if err != nil {
            return nil, fmt.Errorf("DescribeNode(kube.DescribeNode): %v", err)
        }
        var np = []*node.Pod{}
        for _, p := range dn.Pods {
            np = append(np, &node.Pod{
                Namespace: p.Namespace,
                Name:      p.Name,
            })
        }
        n := &node.Node{
            Name: dn.Name,
            Pods: np,
        }
        response.Nodes = append(response.Nodes, n)
    }
    return response, nil
}

ローカルで起動させて、動作確認

└─> go run cmd/server/main.go
2021/09/19 11:47:58 Serving gRPC on 0.0.0.0::8080

# 別ターミナルで
└─> go run cmd/gateway/main.go
2021/09/19 11:48:01 Serving gRPC-Gateway on http://0.0.0.0:8090

└─> curl http://localhost:8090/v1/node/describe | jq -r '.'
{
  "nodes": [
    {
      "name": "kinda-control-plane",
      "pods": [
        {
          "namespace": "kube-system",
          "name": "etcd-kinda-control-plane"
        },
        {
          "namespace": "kube-system",
          "name": "kindnet-c8fhf"
        },
.
.
.