kops delete will also delete the DNS entries for GCE

This commit is contained in:
Christian van der Leeden 2020-01-02 18:24:08 +01:00 committed by Justin Santa Barbara
parent 302bc54782
commit eb3bb41c6b
5 changed files with 103 additions and 21 deletions

View File

@ -9,10 +9,12 @@ go_library(
importpath = "k8s.io/kops/pkg/resources/gce",
visibility = ["//visibility:public"],
deps = [
"//pkg/dns:go_default_library",
"//pkg/resources:go_default_library",
"//upup/pkg/fi:go_default_library",
"//upup/pkg/fi/cloudup/gce:go_default_library",
"//vendor/google.golang.org/api/compute/v0.beta:go_default_library",
"//vendor/google.golang.org/api/dns/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/klog:go_default_library",
],

View File

@ -22,8 +22,10 @@ import (
"strings"
compute "google.golang.org/api/compute/v0.beta"
clouddns "google.golang.org/api/dns/v1"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/klog"
"k8s.io/kops/pkg/dns"
"k8s.io/kops/pkg/resources"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/gce"
@ -42,6 +44,7 @@ const (
typeAddress = "Address"
typeRoute = "Route"
typeSubnet = "Subnet"
typeDNSRecord = "DNSRecord"
)
// Maximum number of `-` separated tokens in a name
@ -796,25 +799,80 @@ func (d *clusterDiscoveryGCE) matchesClusterNameMultipart(name string, maxParts
return false
}
func (d *clusterDiscoveryGCE) listGCEDNSZone() ([]*resources.Resource, error) {
// We never delete the hosted zone, because it is usually shared and we don't create it
return nil, nil
// TODO: When shared resource PR lands, reintroduce
//if dns.IsGossipHostname(d.clusterName) {
// return nil, nil
//}
//zone, err := d.findDNSZone()
//if err != nil {
// return nil, err
//}
//
//return []*resources.Resource{
// {
// Name: zone.Name(),
// ID: zone.Name(),
// Type: "DNS Zone",
// Deleter: d.deleteDNSZone,
// Obj: zone,
// },
//}, nil
func (d *clusterDiscoveryGCE) clusterDNSName() string {
return d.clusterName + "."
}
func (d *clusterDiscoveryGCE) isKopsManagedDNSName(name string) bool {
prefix := []string{`api`, `api.internal`, `bastion`}
for _, p := range prefix {
if name == p+"."+d.clusterDNSName() {
return true
}
}
return false
}
func (d *clusterDiscoveryGCE) listGCEDNSZone() ([]*resources.Resource, error) {
if dns.IsGossipHostname(d.clusterName) {
return nil, nil
}
var resourceTrackers []*resources.Resource
zoneResponse, err := d.gceCloud.CloudDNS().ManagedZones.List(d.gceCloud.Project()).Do()
if err != nil {
return nil, fmt.Errorf("error getting GCE DNS zones %v", err)
}
for _, zone := range zoneResponse.ManagedZones {
if !strings.HasSuffix(d.clusterDNSName(), zone.DnsName) {
continue
}
response, err := d.gceCloud.CloudDNS().ResourceRecordSets.List(d.gceCloud.Project(), zone.Name).Do()
if err != nil {
return nil, fmt.Errorf("error getting GCE DNS zone data %v", err)
}
for _, record := range response.Rrsets {
// adapted from AWS implementation
if record.Type != "A" {
continue
}
if d.isKopsManagedDNSName(record.Name) {
resource := resources.Resource{
Name: zone.Name,
ID: record.Name,
Type: typeDNSRecord,
GroupDeleter: deleteDNSRecords,
GroupKey: zone.Name,
Obj: record,
}
resourceTrackers = append(resourceTrackers, &resource)
}
}
}
return resourceTrackers, nil
}
func deleteDNSRecords(cloud fi.Cloud, r []*resources.Resource) error {
c := cloud.(gce.GCECloud)
var records []*clouddns.ResourceRecordSet
var zoneName string
for _, record := range r {
r := record.Obj.(*clouddns.ResourceRecordSet)
zoneName = record.Name
records = append(records, r)
}
change := clouddns.Change{Deletions: records, Kind: "dns#change", IsServing: true}
_, err := c.CloudDNS().Changes.Create(c.Project(), zoneName, &change).Do()
if err != nil {
return fmt.Errorf("error deleting GCE DNS resource record set %v", err)
}
return nil
}

View File

@ -27,6 +27,7 @@ go_library(
"//vendor/golang.org/x/net/context:go_default_library",
"//vendor/golang.org/x/oauth2/google:go_default_library",
"//vendor/google.golang.org/api/compute/v0.beta:go_default_library",
"//vendor/google.golang.org/api/dns/v1:go_default_library",
"//vendor/google.golang.org/api/googleapi:go_default_library",
"//vendor/google.golang.org/api/iam/v1:go_default_library",
"//vendor/google.golang.org/api/oauth2/v2:go_default_library",

View File

@ -26,6 +26,7 @@ import (
"golang.org/x/net/context"
"golang.org/x/oauth2/google"
compute "google.golang.org/api/compute/v0.beta"
"google.golang.org/api/dns/v1"
"google.golang.org/api/iam/v1"
oauth2 "google.golang.org/api/oauth2/v2"
"google.golang.org/api/storage/v1"
@ -41,6 +42,7 @@ type GCECloud interface {
Compute() *compute.Service
Storage() *storage.Service
IAM() *iam.Service
CloudDNS() *dns.Service
Project() string
WaitForOp(op *compute.Operation) error
@ -60,6 +62,7 @@ type gceCloudImplementation struct {
compute *compute.Service
storage *storage.Service
iam *iam.Service
dns *dns.Service
region string
project string
@ -141,6 +144,12 @@ func NewGCECloud(region string, project string, labels map[string]string) (GCECl
}
c.iam = iamService
dnsService, err := dns.New(client)
if err != nil {
return nil, fmt.Errorf("error building DNS API client: %v", err)
}
c.dns = dnsService
gceCloudInstances[region+"::"+project] = c
{
@ -186,6 +195,11 @@ func (c *gceCloudImplementation) IAM() *iam.Service {
return c.iam
}
// NameService returns the DNS client
func (c *gceCloudImplementation) CloudDNS() *dns.Service {
return c.dns
}
// Region returns private struct element region.
func (c *gceCloudImplementation) Region() string {
return c.region

View File

@ -20,6 +20,7 @@ import (
"fmt"
compute "google.golang.org/api/compute/v0.beta"
"google.golang.org/api/dns/v1"
"google.golang.org/api/iam/v1"
"google.golang.org/api/storage/v1"
v1 "k8s.io/api/core/v1"
@ -105,6 +106,12 @@ func (c *mockGCECloud) IAM() *iam.Service {
return nil
}
// NameService returns the DNS client
func (c *mockGCECloud) CloudDNS() *dns.Service {
klog.Fatalf("mockGCECloud::CloudDNS not implemented")
return nil
}
// WaitForOp implements GCECloud::WaitForOp
func (c *mockGCECloud) WaitForOp(op *compute.Operation) error {
return fmt.Errorf("mockGCECloud::WaitForOp not implemented")