forked from kubernetes-sigs/external-dns
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathupdate_route53_k8s_txt_owner.py
128 lines (109 loc) · 4.72 KB
/
update_route53_k8s_txt_owner.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#!/usr/bin/env python
# Copyright 2018 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This is a script that we wrote to try to help the migration over to using external-dns.
# This script looks at kubernetes ingresses and services (which are the two things we have
# external-dns looking at) and compares them to existing TXT and A records in route53 to
# find out where there are gaps. It then assigns the heritage and owner TXT records where
# needed so external-dns can take over managing those resources. You can modify the script
# to only look at one or the other if needed.
#
# pip install kubernetes boto3
import boto3
from kubernetes import client, config
# replace with your hosted zone id
hosted_zone_id = ''
# replace with your txt-owner-id you are using
# inside of your external-dns controller
txt_owner_id = ''
# change to false if you have external-dns not looking at services
external_dns_manages_services = True
# change to false if you have external-dns not looking at ingresses
external_dns_manages_ingresses = True
config.load_kube_config()
# grab all the domains that k8s thinks it is going to
# manage (services with domainName specified and
# ingress hosts)
k8s_domains = []
if external_dns_manages_services:
v1 = client.CoreV1Api()
svcs = v1.list_service_for_all_namespaces()
for i in svcs.items:
annotations = i.metadata.annotations
if annotations is not None and 'domainName' in annotations:
k8s_domains.extend(annotations['domainName'].split(','))
if external_dns_manages_ingresses:
ev1 = client.NetworkingV1Api()
ings = ev1.list_ingress_for_all_namespaces()
for i in ings.items:
for r in i.spec.rules:
if r.host not in k8s_domains:
k8s_domains.append(r.host)
r53client = boto3.client('route53')
# grab the existing route53 domains and identify gaps where a domain may be
# missing a txt record pair
existing_r53_txt_domains=[]
existing_r53_domains=[]
has_next = True
next_record_name, next_record_type='',''
while has_next:
if next_record_name is not '' and next_record_type is not '':
resource_records = r53client.list_resource_record_sets(HostedZoneId=hosted_zone_id,
StartRecordName=next_record_name,
StartRecordType=next_record_type)
else:
resource_records = r53client.list_resource_record_sets(HostedZoneId=hosted_zone_id)
for r in resource_records['ResourceRecordSets']:
if r['Type'] == 'TXT':
existing_r53_txt_domains.append(r['Name'][:-1])
elif r['Type'] == 'A':
existing_r53_domains.append(r['Name'][:-1])
has_next = resource_records['IsTruncated']
if has_next:
next_record_name, next_record_type = resource_records['NextRecordName'], resource_records['NextRecordType']
# grab only the domains in route53 that kubernetes is managing
r53_k8s_domains = [r for r in k8s_domains if r in existing_r53_domains]
# from those find the ones that do not have matching txt entries
missing_k8s_txt = [r for r in r53_k8s_domains if r not in existing_r53_txt_domains]
# make the change batch for the route53 call, modify this as needed
change_batch=[]
for r in missing_k8s_txt:
change_batch.append(
{
'Action': 'CREATE',
'ResourceRecordSet': {
'Name': r,
'Type': 'TXT',
'TTL': 300,
'ResourceRecords': [
{
'Value': '\heritage=external-dns,owner="' + txt_owner_id + '\"'
},
]
}
})
print('This will create the following resources')
print(change_batch)
response = input("Good to go? ")
if response.lower() in ['y', 'yes', 'yup', 'ok', 'sure', 'why not', 'why not?']:
print('Updating route53')
change_response = r53client.change_resource_record_sets(
HostedZoneId=hosted_zone_id,
ChangeBatch={
'Changes': change_batch
})
print('Submitted change request to route53. Details below.')
print(change_response)
else:
print('No changes were made')