pythongoogle-cloud-platformsdkgoogle-compute-engineproto

GCP Python SDK TypeError: Value must be iterable


I am trying to use the patch from Google Python SDK to update a value contained in an array under bgpPeers[0].peerAsn.

I tried different ways and I can't seem to be able to update the value peerASN under bgpPeers. I am able to update the keepaliveInterval under bgp though with:

operation = client.patch(project=project_id, region=zone,
                         router=routerName, router_resource=compute_v1.Router(
                             bgp=compute_v1.RouterBgp(keepalive_interval=20))
                         )

But not what's in bgpPeers.

Python code:

import json
import requests
from google.cloud import compute_v1  # GCP SDK
import os.path
from google.protobuf.json_format import MessageToDict, MessageToJson

##########################
# Get project ID
project_id = "prefab-setting-357415"

# Get Zone
zone = "us-west1"

# Get GCP Service Account details
credential_file_path = "/root/secret.json"

# Python SDK authentication
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = credential_file_path
with open(os.environ['GOOGLE_APPLICATION_CREDENTIALS'], 'r') as fp:
    credentials = json.load(fp)

#####################################################

routerName = "demo-gcp-cloud-router"

# https://cloud.google.com/python/docs/reference/compute/latest/google.cloud.compute_v1.services.routers
client = compute_v1.RoutersClient()
operation = client.get(project=project_id, region=zone, router=routerName)
print(operation)

print("\nUpdate peer_asn=4556\n")

operation = client.patch(project=project_id, region=zone,
                            router=routerName, router_resource=compute_v1.Router(
                                bgp_peers=compute_v1.RouterBgpPeer(peer_asn=4556))
                            )
print(operation)

Output:

root@c67b263513be:~# python3 test.py 

id: 532925236079520732
bgp {
asn: 16550
advertised_groups: "ALL_SUBNETS"
keepalive_interval: 20
advertise_mode: "CUSTOM"
}
kind: "compute#router"
name: "demo-gcp-cloud-router"
interfaces {
name: "auto-ia-if-demo-gcp-interc-97ac78567ed0305"
management_type: "MANAGED_BY_ATTACHMENT"
linked_interconnect_attachment: "https://www.googleapis.com/compute/v1/projects/prefab-setting-357415/regions/us-west1/interconnectAttachments/demo-gcp-interconnect"
}
creation_timestamp: "2022-08-08T20:32:03.805-07:00"
region: "https://www.googleapis.com/compute/v1/projects/prefab-setting-357415/regions/us-west1"
network: "https://www.googleapis.com/compute/v1/projects/prefab-setting-357415/global/networks/demo-pf-vital-wildcat"
description: "hellpworld"
bgp_peers {
bfd {
    session_initialization_mode: "DISABLED"
    min_receive_interval: 1000
    multiplier: 5
    min_transmit_interval: 1000
}
name: "auto-ia-bgp-demo-gcp-interc-97ac78567ed0305"
peer_asn: 4556
management_type: "MANAGED_BY_ATTACHMENT"
enable_ipv6: false
enable: "TRUE"
advertise_mode: "DEFAULT"
interface_name: "auto-ia-if-demo-gcp-interc-97ac78567ed0305"
}
self_link: "https://www.googleapis.com/compute/v1/projects/prefab-setting-357415/regions/us-west1/routers/demo-gcp-cloud-router"


Update peer_asn=4556

Traceback (most recent call last):
File "/root/debug2.py", line 34, in <module>
    router=routerName, router_resource=compute_v1.Router(
File "/usr/local/lib/python3.10/dist-packages/proto/message.py", line 585, in __init__
    super().__setattr__("_pb", self._meta.pb(**params))
TypeError: Value must be iterable
root@c67b263513be:~# 

I also have no problem when using gcloud:

root@c67b263513be:~#  gcloud compute routers update-bgp-peer demo-gcp-cloud-router --peer-name="auto-ia-bgp-demo-gcp-interc-97ac78567ed0305" --region="us-west1" --peer-asn 4556 --verbosity=debug
DEBUG: Running [gcloud.compute.routers.update-bgp-peer] with arguments: [--peer-asn: "4556", --peer-name: "auto-ia-bgp-demo-gcp-interc-97ac78567ed0305", --region: "us-west1", --verbosity: "debug", NAME: "demo-gcp-cloud-router"]
DEBUG: Starting new HTTPS connection (1): compute.googleapis.com:443
DEBUG: https://compute.googleapis.com:443 "GET /compute/v1/projects/prefab-setting-357415/regions/us-west1/routers/demo-gcp-cloud-router?alt=json HTTP/1.1" 200 None
DEBUG: Starting new HTTPS connection (1): compute.googleapis.com:443
DEBUG: https://compute.googleapis.com:443 "PATCH /compute/v1/projects/prefab-setting-357415/regions/us-west1/routers/demo-gcp-cloud-router?alt=json HTTP/1.1" 200 None
Updating peer [auto-ia-bgp-demo-gcp-interc-97ac78567ed0305] in router [demo-gcp-cloud-router]...⠶DEBUG: Starting new HTTPS connection (1): compute.googleapis.com:443
Updating peer [auto-ia-bgp-demo-gcp-interc-97ac78567ed0305] in router [demo-gcp-cloud-router]...⠧DEBUG: https://compute.googleapis.com:443 "POST /compute/v1/projects/prefab-setting-357415/regions/us-west1/operations/operation-1660063232644-5e5d197495741-6b0f32a2-f2a0a9e8/wait?alt=json HTTP/1.1" 200 None
Updating peer [auto-ia-bgp-demo-gcp-interc-97ac78567ed0305] in router [demo-gcp-cloud-router]...done.                     
DEBUG: Starting new HTTPS connection (1): compute.googleapis.com:443
DEBUG: https://compute.googleapis.com:443 "GET /compute/v1/projects/prefab-setting-357415/regions/us-west1/routers/demo-gcp-cloud-router?alt=json HTTP/1.1" 200 None
INFO: Display format: "none"

Solution

  • I found the problem, I had to include at least the name and interface_name properties under bgp_peers, not only the peer_asn...

    router_resource = {
        "bgp_peers": [
            {
                "interface_name":"auto-ia-if-demo-gcp-interc-97ac78567ed0305",
                "name":"auto-ia-bgp-demo-gcp-interc-97ac78567ed0305",
                "peer_asn": 4557
            }
        ]
    }
    
    # Update the google cloud router
    operation = client.patch(project=project_id, region=zone,
                              router=routerName, router_resource=router_resource)
    print(operation)