GCP Python SDK TypeError: Value must be iterable

651 Views Asked by At

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"
2

There are 2 best solutions below

0
Romain On BEST ANSWER

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)
0
NoCommandLine On

Based on updated question, the issue is around the PATCH operation.

According to documentation, bgp_peers should be a list.

Sequence[google.cloud.compute_v1.types.RouterBgpPeer] BGP information that must be configured into the routing stack to establish BGP peering. This information must specify the peer ASN and either the interface name, IP address, or peer IP address. Please refer to RFC4273.