gcloud dns record-sets transaction Cannot update IP address

7/13/2016

Getting an error when using command line Google Cloud DNS when attempting to update the External IP of the Hosted Zone Resource Record Type A for my domain ... this works fine using the browser based gce console ... in English when I deploy my app using Kubernetes it gives me a fresh IP I need to link to my existing Domain DNS so people can reach my app pointing their browser at my domain (example.com) ... the rub is this action needs to happen everytime I re-deploy my app hence the need to automate

Note - the Cloud DNS zone already exists and works. I am trying to update the External IP address to match a fresh Kubernetes deployment's LoadBalancer Ingress as per

kubectl describe svc --namespace=ruptureofthemundaneplane | grep Ingress
LoadBalancer Ingress:   104.196.108.178

here is current state

gcloud dns record-sets list --zone  zone-cubalibre --project ruptureofthemundaneplane 
NAME                           TYPE   TTL  DATA
example.com.            A      60   104.196.108.147
example.com.            NS     60   ns-cloud-a1.googledomains.com.,ns-cloud-a2.googledomains.com.,ns-cloud-a3.googledomains.com.,ns-cloud-a4.googledomains.com.
example.com.            SOA    60   ns-cloud-a1.googledomains.com. cloud-dns-hostmaster.google.com. 1 21600 3600 1209600 300
admin.example.com.      CNAME  60   example.com.
www.admin.example.com.  CNAME  60   example.com.
www.example.com.        CNAME  60   example.com.

here is just Type A record

gcloud dns record-sets list    --project ruptureofthemundaneplane   --zone zone-cubalibre   --name "example.com." --type "A"
NAME                 TYPE  TTL  DATA
example.com.  A     60   104.196.108.147

I need to replace IP 104.196.108.147 with a new value 104.196.108.178 ... so I issue

gcloud dns record-sets transaction start --zone zone-cubalibre  --project ruptureofthemundaneplane 

here I add a transaction with my new IP address

gcloud dns record-sets transaction add  "104.196.108.178"  --name "example.com." --ttl 60 --type "A"  --project ruptureofthemundaneplane   --zone zone-cubalibre 

here is the system generated yaml file

cat transaction.yaml 
---
additions:
- kind: dns#resourceRecordSet
  name: example.com.
  rrdatas:
  - ns-cloud-a1.googledomains.com. cloud-dns-hostmaster.google.com. 2 21600 3600 1209600
    300
  ttl: 60
  type: SOA
- kind: dns#resourceRecordSet
  name: example.com.
  rrdatas:
  - 104.196.108.178
  ttl: 60
  type: A
deletions:
- kind: dns#resourceRecordSet
  name: example.com.
  rrdatas:
  - ns-cloud-a1.googledomains.com. cloud-dns-hostmaster.google.com. 1 21600 3600 1209600
    300
  ttl: 60
  type: SOA

for completeness here I ask the system to show the transaction cache

gcloud dns record-sets transaction  describe     --project ruptureofthemundaneplane   --zone zone-cubalibre  

... output

additions:
- kind: dns#resourceRecordSet
  name: example.com.
  rrdatas:
  - ns-cloud-a1.googledomains.com. cloud-dns-hostmaster.google.com. 2 21600 3600 1209600
    300
  ttl: 60
  type: SOA
- kind: dns#resourceRecordSet
  name: example.com.
  rrdatas:
  - 104.196.108.178
  ttl: 60
  type: A
deletions:
- kind: dns#resourceRecordSet
  name: example.com.
  rrdatas:
  - ns-cloud-a1.googledomains.com. cloud-dns-hostmaster.google.com. 1 21600 3600 1209600
    300
  ttl: 60
  type: SOA

finally I commit the transaction with this

gcloud dns record-sets transaction execute    --project ruptureofthemundaneplane    --zone zone-cubalibre 
ERROR: (gcloud.dns.record-sets.transaction.execute) 
The resource 'entity.change.additions[1]' named 'example.com. (A)' already exists (code: 409)

any suggestions ? I want to avoid predefining Static IP as that is not scalable ... the equivalent Amazon aws commands work when I deploy using kube-up.sh over aws ... would be a nice touch if kubernetes achieved a common solution across all its cloud host vendors ... Are folks using some other automated means to achieve this ? some SDK library in lang x ?

-- Scott Stensland
gcloud
google-cloud-dns
google-cloud-platform
google-compute-engine
kubernetes

1 Answer

7/15/2016

The Cloud DNS operations work on entire RR_set_s (record-set or dns#resourceRecordSet), rather than individual RRs. Your example wouldn't do what you want even in the latter case, since you would end up with an RRset containing both the old and new IP addresses, which would only "work mostly."

In any case, it is record sets and only one RRset for each RTYPE is allowed, so your transaction needs to delete the existing A RRset first, then add your new one.

-- Alex Dupuy
Source: StackOverflow