First of all, I have an internet network endpoint group (NEG):
gcloud compute network-endpoint-groups update [neg-name] \
--add-endpoint="fqdn=[service.example.com],port=443" \
--global
This is what's called "Global external HTTP(S) load balancer (classic)" in the Backend Service documentation.
I have two services, created like this:
gcloud beta compute backend-services create [service-name] \
--load-balancing-scheme=EXTERNAL \
--protocol=HTTPS \
--port-name=https \
--enable-logging \
--logging-sample-rate=1 \
--global
gcloud beta compute backend-services add-backend [service-name] \
--network-endpoint-group=[neg-name] \
--global-network-endpoint-group \
--global \
--custom-request-header="Host: service.example.com" # Fix SSL issue
I also have a url map, created like this:
gcloud beta compute url-maps create [url-map-name] \
--default-service [service 1 name]
I want to create a traffic splitting rule that routes traffic between service 1 and service 2. Following the load balancing docs, I came up with this:
creationTimestamp: '2021-11-26T12:41:59.779-08:00'
defaultService: https://www.googleapis.com/compute/beta/projects/[project-name]/global/backendServices/[service 1 name]
fingerprint: [fingerprint]
hostRules:
- hosts:
- '*'
pathMatcher: default-matcher
id: [id]
kind: compute#urlMap
name: [url-map-name]
pathMatchers:
- defaultService: https://www.googleapis.com/compute/beta/projects/[project-name]/global/backendServices/[service 1 name]
name: default-matcher
routeRules:
- priority: 1
matchRules:
- prefixMatch: '/'
routeAction:
weightedBackendServices:
- weight: 50
backendService: https://www.googleapis.com/compute/beta/projects/[project-name]/global/backendServices/[service 2 name]
- weight: 50
backendService: https://www.googleapis.com/compute/beta/projects/[project-name]/global/backendServices/[service 1 name]
selfLink: https://www.googleapis.com/compute/beta/projects/[project-name]/global/urlMaps/[url-map-name]
When I try to edit the url map with the above configuration, the following error is returned (debugger breakpoints included in output):
$ gcloud beta compute url-maps edit [url-map-name] --global --verbosity=debug
DEBUG: Running [gcloud.beta.compute.url-maps.edit] with arguments: [--global: "True", --verbosity: "debug", URL_MAP: "[url-map-name]"]
INFO: Display format: "default"
DEBUG: Starting new HTTPS connection (1): compute.googleapis.com:443
DEBUG: https://compute.googleapis.com:443 "POST /batch/compute/beta HTTP/1.1" 200 None
> /opt/google-cloud-sdk/lib/surface/compute/url_maps/edit.py(100)_ProcessEditedResource()
-> return holder.client.MakeRequests(
(Pdb) c
DEBUG: https://compute.googleapis.com:443 "POST /batch/compute/beta HTTP/1.1" 200 None
> /opt/google-cloud-sdk/lib/googlecloudsdk/api_lib/compute/batch_helper.py(117)MakeRequests()
-> error_message = None
(Pdb) c
> /opt/google-cloud-sdk/lib/googlecloudsdk/api_lib/compute/client_adapter.py(116)MakeRequests()
-> utils.RaiseToolException(errors, error_message="Could not fetch resource:")
(Pdb) errors
[(400, 'Invalid value for field \'resource\': \'{ "name": "[url-map-name]", "hostRule": [{ "host": ["*"], "pathMatcher": "default-matcher...\'. One of backend_service or url_redirect must be set')]
(Pdb) c
There was a problem applying your changes: Could not fetch resource:
- Invalid value for field 'resource': '{ "name": "[url-map-name]", "hostRule": [{ "host": ["*"], "pathMatcher": "default-matcher...'. One of backend_service or url_redirect must be
set
Would you like to edit the resource again? (Y/n)? n
Validating (Thank you Alex G):
$ gcloud beta compute url-maps validate --source=url-map-traffic-splitting.yml --global --verbosity=debug
DEBUG: Running [gcloud.beta.compute.url-maps.validate] with arguments: [--global: "True", --source: "url-map-traffic-splitting.yml", --verbosity: "debug"]
DEBUG: Starting new HTTPS connection (1): compute.googleapis.com:443
DEBUG: https://compute.googleapis.com:443 "POST /compute/beta/projects/[project-name]/global/urlMaps/[url-map-name]/validate?alt=json HTTP/1.1" 200 None
INFO: Display format: "default"
result:
loadErrors:
- One of backend_service or url_redirect must be set
loadSucceeded: false
testPassed: false
DEBUG: SDK update checks are disabled.
What I've tried:
- Tried with pathRules instead of routeRules, it works and the url map is updated.
- I tried hacking the gcloud libraries to give better errors - but the error is returned by the API, not the client:
HttpError accessing <https://compute.googleapis.com/batch/compute/beta>: response: <{'Content-Type': 'application/json; charset=UTF-8', 'Vary': 'Origin', 'status': '400'}>, content <{ "error": { "code": 400, "message": "Invalid value for field 'resource': '{ \"name\": \"[url-map-name]\", \"hostRule\": [{ \"host\": [\"*\"], \"pathMatcher\": \"default-matcher...'. One of backend_service or url_redirect must be set", "errors": [ { "message": "Invalid value for field 'resource': '{ \"name\": \"[url-map-name]\", \"hostRule\": [{ \"host\": [\"*\"], \"pathMatcher\": \"default-matcher...'. One of backend_service or url_redirect must be set", "domain": "global", "reason": "invalid" } ] } } - I've searched the GCP documentation for any mentions of this error, or mentions of limits to what url maps can do, but found nothing.