Home > OS >  Python how to build dictionary from nested protobuf definitions
Python how to build dictionary from nested protobuf definitions

Time:11-08

This is my first time working with grpc/protobuf tech. so far so good I have coded grpc methods for simple (flat?) protobuf definitions. However I have run into nested protobuf declarations and have no idea how to formulate the dictionary payload. Unfortunately the team the created these files is offering little to no coding support.

snippet of proto file:

message UpdateClusterRequest {
    myapp.infrastructure.common.Context context = 1;
    myapp.infrastructure.common.MyAppEnvironment myapp_environment = 2;
    string service_name = 3;

    ClusterTemplate spec = 4;
    string config_revision = 5;

}

message ClusterTemplate {
    message MyAppSettings {
        string version = 1;
        repeated InstanceType instance_layout = 2;
        repeated ClientIDTemplate client_ids = 3;

        bool dedicated_mock_service = 4;
        int64 mock_service_replicas = 5;
    }

    message DbSettings {
        string version = 1;
        repeated DBHostTemplate db_hosts = 2;
        bool analytics_enabled = 3;
    }

My code snippet is below. The issue I have is I dont know how to code the message Cluster Template part into the playload_cluster_detail payload:

def update_cluster(client_stub, console_project_id, metadata_okta_token_and_env):

    try:

        payload_cluster_detail = {"context": {"project_id": console_project_id},
                                  "myapp_environment": common_pb2.MYAPP_ENVIRONMENT_TEST,
                                  "service_name": "web-2024-app",
                                  "config_revision": "1824866",
                                  "spec": {
                                    "MyAppSettings": {
                                        "version": "1824866-unix64-clang-debug",
                                        "branch": "web_mainline",
                                    }
                                  }
                                  }
        request = myapp_pb2.UpdateClusterRequest(**payload_cluster_detail)
        response = client_stub.get_grpc_myapp_stub(grpc_stub_method).UpdateCluster(request=request, metadata=metadata_okta_token_and_env)

When I run my code I get the following error:

ValueError: Protocol message ClusterTemplate has no "MyAppSettings" field.

Help would be greatly appreciated.

CodePudding user response:

I munged your proto file to get it to work for me (as I don't have all your dependencies):

x.proto:

syntax = "proto3";

// (ADDED:dazwilkin) to compile
message Context {
    string project_id = 1;
}

message UpdateClusterRequest {
    Context context = 1;
    // myapp.infrastructure.common.MyAppEnvironment myapp_environment = 2;
    string service_name = 3;

    ClusterTemplate spec = 4;
    string config_revision = 5;

}

message ClusterTemplate {
    message MyAppSettings {
        string version = 1;
        // repeated InstanceType instance_layout = 2;
        // repeated ClientIDTemplate client_ids = 3;

        bool dedicated_mock_service = 4;
        int64 mock_service_replicas = 5;
    }

    message DbSettings {
        string version = 1;
        // repeated DBHostTemplate db_hosts = 2;
        bool analytics_enabled = 3;
    }

    MyAppSettings my_app_settings = 1;
    DbSettings db_settings = 2;
}

NOTE I added MyAppSettings my_app_settings = 1;

Then:

python \
-m grpc_tools.protoc \
--proto_path=${PWD} \
--python_out=${PWD} \
${PWD}/x.proto

Then I can:

import x_pb2


console_project_id = "x"

payload_cluster_detail = {
    "context": {
        "project_id": console_project_id
        },
    "service_name": "web-2024-app",
    "config_revision": "1824866",
    "spec": {
        "my_app_settings": {
            "version": "1824866-unix64-clang-debug",
        },
        "db_settings": {
            "version": "",
            "analytics_enabled": True,
        }

    }
}

x = x_pb2.UpdateClusterRequest(**payload_cluster_detail)
print(x)
  • Related