Skip to content

Commit

Permalink
MutiZones
Browse files Browse the repository at this point in the history
depresolver

move config to gslb instead of edgeDNSServers

getNSNames

fix tests

selecting GSLB by stateus.Servers[*].Host

fixing terratest

Fix externalDNSENdpoint name , IBX finalizer

fix infoblox finalizer test

replace config.DNSZone by config.DelegationZones[*].Domain

use config.DelegationZones[*].Zone instead of EdgeDNSZone

Signed-off-by: Michal Kuritka <[email protected]>

making egdeDNSZone private, so it cant be used cross the project but is still there for backward compatibility

making dnsZone private, so it cant be used cross the project but is still there for backward compatibility

Move GetClusterNSNames to DelegationZones

GetExternalClusterNSNamesByHostname

making getClusterNSName and getExternalClusterNSNames private so it can't be used anymore

extClustersGeoTags field is private
  • Loading branch information
kuritka committed Feb 19, 2025
1 parent cb64ca4 commit a13ba18
Show file tree
Hide file tree
Showing 20 changed files with 745 additions and 247 deletions.
16 changes: 10 additions & 6 deletions controllers/depresolver/depresolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ type Config struct {
NSRecordTTL int `env:"NS_RECORD_TTL, default=30"`
// ClusterGeoTag to determine specific location
ClusterGeoTag string `env:"CLUSTER_GEO_TAG"`
// ExtClustersGeoTags to identify clusters in other locations in format separated by comma. i.e.: "eu,uk,us"
ExtClustersGeoTags []string `env:"EXT_GSLB_CLUSTERS_GEO_TAGS, default=[]"`
// extClustersGeoTags to identify clusters in other locations in format separated by comma. i.e.: "eu,uk,us"
extClustersGeoTags []string `env:"EXT_GSLB_CLUSTERS_GEO_TAGS, default=[]"`
// EdgeDNSType is READONLY and is set automatically by configuration
EdgeDNSType EdgeDNSType
// EdgeDNSServers
Expand All @@ -134,10 +134,14 @@ type Config struct {
fallbackEdgeDNSServerName string `env:"EDGE_DNS_SERVER"`
// to avoid breaking changes is used as fallback server port for EdgeDNSServers
fallbackEdgeDNSServerPort int `env:"EDGE_DNS_SERVER_PORT, default=53"`
// EdgeDNSZone main zone which would contain gslb zone to delegate; e.g. example.com
EdgeDNSZone string `env:"EDGE_DNS_ZONE"`
// DNSZone controlled by gslb; e.g. cloud.example.com
DNSZone string `env:"DNS_ZONE"`
// edgeDNSZone main zone which would contain gslb zone to delegate; e.g. example.com
edgeDNSZone string `env:"EDGE_DNS_ZONE"`
// dnsZone controlled by gslb; e.g. cloud.example.com
dnsZone string `env:"DNS_ZONE"`
// DelegationZones
DelegationZones DelegationZones
// DelegationZones pairs of dnsZone ad edgeDNSZone, eg: DNS_ZONES=example.com:cloud.example.com;example.io:cloud.example.io
dnsZones string `env:"DNS_ZONES"`
// K8gbNamespace k8gb namespace
K8gbNamespace string `env:"POD_NAMESPACE"`
// Infoblox configuration
Expand Down
50 changes: 33 additions & 17 deletions controllers/depresolver/depresolver_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ import (
"github.com/rs/zerolog"
)

// TODO: refactor with kong.CLI to read envvars into Config
// TODO: refactor with go-playground/validator to validate

// Environment variables keys
const (
ReconcileRequeueSecondsKey = "RECONCILE_REQUEUE_SECONDS"
Expand All @@ -41,6 +44,7 @@ const (
EdgeDNSServersKey = "EDGE_DNS_SERVERS"
EdgeDNSZoneKey = "EDGE_DNS_ZONE"
DNSZoneKey = "DNS_ZONE"
DNSZonesKey = "DNS_ZONES"
InfobloxGridHostKey = "INFOBLOX_GRID_HOST"
InfobloxVersionKey = "INFOBLOX_WAPI_VERSION"
InfobloxPortKey = "INFOBLOX_WAPI_PORT"
Expand Down Expand Up @@ -69,6 +73,12 @@ const (
EdgeDNSServerPortKey = "EDGE_DNS_SERVER_PORT"
)

const (
localhost = "localhost"

localhostIPv4 = "127.0.0.1"
)

// ResolveOperatorConfig executes once. It reads operator's configuration
// from environment variables into &Config and validates
func (dr *DependencyResolver) ResolveOperatorConfig() (*Config, error) {
Expand All @@ -87,13 +97,17 @@ func (dr *DependencyResolver) ResolveOperatorConfig() (*Config, error) {
fallbackDNS := fmt.Sprintf("%s:%v", dr.config.fallbackEdgeDNSServerName, dr.config.fallbackEdgeDNSServerPort)
edgeDNSServerList := env.GetEnvAsArrayOfStringsOrFallback(EdgeDNSServersKey, []string{fallbackDNS})
dr.config.EdgeDNSServers = parseEdgeDNSServers(edgeDNSServerList)
dr.config.ExtClustersGeoTags = excludeGeoTag(dr.config.ExtClustersGeoTags, dr.config.ClusterGeoTag)
dr.config.extClustersGeoTags = excludeGeoTag(dr.config.extClustersGeoTags, dr.config.ClusterGeoTag)
dr.config.Log.Level, _ = zerolog.ParseLevel(strings.ToLower(dr.config.Log.level))
dr.config.Log.Format = parseLogOutputFormat(strings.ToLower(dr.config.Log.format))
dr.config.EdgeDNSType, recognizedDNSTypes = getEdgeDNSType(dr.config)

// validation
// replace validations by go-playground/validator
dr.errorConfig = dr.validateConfig(dr.config, recognizedDNSTypes)
// validation
if dr.errorConfig == nil {
dr.config.DelegationZones = parseDelegationZones(dr.config)
}
})
return dr.config, dr.errorConfig
}
Expand Down Expand Up @@ -128,11 +142,11 @@ func (dr *DependencyResolver) validateConfig(config *Config, recognizedDNSTypes
if err != nil {
return err
}
err = field(ExtClustersGeoTagsKey, config.ExtClustersGeoTags).hasItems().hasUniqueItems().err
err = field(ExtClustersGeoTagsKey, config.extClustersGeoTags).hasItems().hasUniqueItems().err
if err != nil {
return err
}
for i, geoTag := range config.ExtClustersGeoTags {
for i, geoTag := range config.extClustersGeoTags {
err = field(fmt.Sprintf("%s[%v]", ExtClustersGeoTagsKey, i), geoTag).
isNotEmpty().matchRegexp(geoTagRegex).err
if err != nil {
Expand Down Expand Up @@ -160,11 +174,11 @@ func (dr *DependencyResolver) validateConfig(config *Config, recognizedDNSTypes
return fmt.Errorf("error for port of edge dns server(%v): it must be a positive integer between 1 and 65535", s)
}
}
err = field(EdgeDNSZoneKey, config.EdgeDNSZone).isNotEmpty().matchRegexp(hostNameRegex).err
err = field(EdgeDNSZoneKey, config.edgeDNSZone).isNotEmpty().matchRegexp(hostNameRegex).err
if err != nil {
return err
}
err = field(DNSZoneKey, config.DNSZone).isNotEmpty().matchRegexp(hostNameRegex).err
err = field(DNSZoneKey, config.dnsZone).isNotEmpty().matchRegexp(hostNameRegex).err
if err != nil {
return err
}
Expand All @@ -185,12 +199,12 @@ func (dr *DependencyResolver) validateConfig(config *Config, recognizedDNSTypes
return nil
}

serverNames := config.GetExternalClusterNSNames()
serverNames[config.ClusterGeoTag] = config.GetClusterNSName()
serverNames := config.getExternalClusterNSNames()
serverNames[config.ClusterGeoTag] = config.getClusterNSName()
for geoTag, nsName := range serverNames {
if len(nsName) > dnsNameMax {
return fmt.Errorf("ns name '%s' exceeds %v charactes limit for [GeoTag: '%s', %s: '%s', %s: '%s']",
nsName, dnsLabelMax, geoTag, EdgeDNSZoneKey, config.EdgeDNSZone, DNSZoneKey, config.DNSZone)
nsName, dnsLabelMax, geoTag, EdgeDNSZoneKey, config.edgeDNSZone, DNSZoneKey, config.dnsZone)
}
if err := validateLabels(nsName); err != nil {
return fmt.Errorf("error for geo tag: %s. %s in ns name %s", geoTag, err, nsName)
Expand All @@ -215,7 +229,7 @@ func (dr *DependencyResolver) validateConfig(config *Config, recognizedDNSTypes
func validateLocalhostNotAmongDNSServers(config *Config) error {
containsLocalhost := func(list utils.DNSList) bool {
for i := 1; i < len(list); i++ { // skipping first because localhost or 127.0.0.1 can occur on the first position
if list[i].Host == "localhost" || list[i].Host == "127.0.0.1" {
if list[i].Host == localhost || list[i].Host == localhostIPv4 {
return true
}
}
Expand Down Expand Up @@ -370,20 +384,22 @@ func parseLogOutputFormat(value string) LogFormat {
return NoFormat
}

func (c *Config) GetExternalClusterNSNames() (m map[string]string) {
m = make(map[string]string, len(c.ExtClustersGeoTags))
for _, tag := range c.ExtClustersGeoTags {
m[tag] = getNsName(tag, c.DNSZone, c.EdgeDNSZone, c.EdgeDNSServers[0].Host)
// deprecated, used for validations only
func (c *Config) getExternalClusterNSNames() (m map[string]string) {
m = make(map[string]string, len(c.extClustersGeoTags))
for _, tag := range c.extClustersGeoTags {
m[tag] = getNsName(tag, c.dnsZone, c.edgeDNSZone, c.EdgeDNSServers[0].Host)
}
return
}

func (c *Config) GetClusterNSName() string {
return getNsName(c.ClusterGeoTag, c.DNSZone, c.EdgeDNSZone, c.EdgeDNSServers[0].Host)
// deprecated, used for validations only
func (c *Config) getClusterNSName() string {
return getNsName(c.ClusterGeoTag, c.dnsZone, c.edgeDNSZone, c.EdgeDNSServers[0].Host)
}

// getNsName returns NS for geo tag.
// The values is combination of DNSZone, EdgeDNSZone and (Ext)ClusterGeoTag, see:
// The values is combination of dnsZone, edgeDNSZone and (Ext)ClusterGeoTag, see:
// DNS_ZONE k8gb-test.gslb.cloud.example.com
// EDGE_DNS_ZONE: cloud.example.com
// CLUSTER_GEOTAG: us
Expand Down
165 changes: 165 additions & 0 deletions controllers/depresolver/depresolver_domaininfo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package depresolver

/*
Copyright 2022 The k8gb Contributors.
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.
Generated by GoLic, for more details see: https://github.com/AbsaOSS/golic
*/

import (
"fmt"
"sort"
"strings"

k8gbv1beta1 "github.com/k8gb-io/k8gb/api/v1beta1"
)

type DelegationZones []DelegationZoneInfo

type DelegationZoneInfo struct {
Domain string
Zone string
ClusterNSName string
ExtClusterNSNames map[string]string
}

func parseDelegationZones(config *Config) []DelegationZoneInfo {

zones := config.dnsZones
edgeDNSZone := config.edgeDNSZone
dnsZone := config.dnsZone

getNsName := func(tag, edgeDNSServer, zone, edge string) string {
if edgeDNSServer == localhost || edgeDNSServer == localhostIPv4 {
return edgeDNSServer
}
const prefix = "gslb-ns"
d := strings.TrimSuffix(zone, "."+edge)
domainX := strings.ReplaceAll(d, ".", "-")
return fmt.Sprintf("%s-%s-%s.%s", prefix, tag, domainX, edge)
}

// parse example.com:cloud.example.com;example.io:cloud.example.io into map[string]string
getEnvAsArrayOfPairsOrFallback := func(zones string, fallback map[string]string) map[string]string {
pairs := make(map[string]string)
slice := strings.Split(zones, ";")
if len(slice) == 0 {
return fallback
}
for _, z := range slice {
pair := strings.Split(z, ":")
if len(pair) != 2 {
return fallback
}
pairs[strings.Trim(pair[0], " ")] = strings.Trim(pair[1], " ")
}
for k, v := range fallback {
if _, found := pairs[k]; !found {
pairs[k] = v
}
}
return pairs
}
var dzi []DelegationZoneInfo
zones = strings.TrimSuffix(strings.TrimSuffix(zones, ";"), " ")
fallbackDNSZone := map[string]string{}
if !(edgeDNSZone == "" && dnsZone == "") {
fallbackDNSZone[edgeDNSZone] = dnsZone
}
di := getEnvAsArrayOfPairsOrFallback(zones, fallbackDNSZone)

for edge, zone := range di {
zoneInfo := DelegationZoneInfo{
Domain: zone,
Zone: edge,
ClusterNSName: getNsName(config.ClusterGeoTag, config.EdgeDNSServers[0].Host, zone, edge),
ExtClusterNSNames: func(zone, edge string) map[string]string {
m := map[string]string{}
for _, tag := range config.extClustersGeoTags {
m[tag] = getNsName(tag, config.EdgeDNSServers[0].Host, zone, edge)
}
return m
}(zone, edge),
}
dzi = append(dzi, zoneInfo)
}
return dzi
}

// GetNSServerList returns a sorted list of all NS servers for the delegation zone
func (z *DelegationZoneInfo) GetNSServerList() []string {
list := []string{z.ClusterNSName}
for _, v := range z.ExtClusterNSNames {
list = append(list, v)
}
sort.Strings(list)
return list
}

// GetExternalDNSEndpointName returns name of endpoint sitting in k8gb namespace
func (z *DelegationZoneInfo) GetExternalDNSEndpointName() string {
var suffix = strings.Trim(strings.ReplaceAll(z.Domain, ".", "-"), " ")
return fmt.Sprintf("k8gb-ns-extdns-%s", suffix)
}

// FindByGslbStatusHostname returns DelegationZoneInfo for the hostname
func (d *DelegationZones) FindByGslbStatusHostname(gslb *k8gbv1beta1.Gslb) *DelegationZoneInfo {
if len(gslb.Status.Servers) == 0 {
return nil
}
for _, z := range *d {
if strings.HasSuffix(gslb.Status.Servers[0].Host, z.Domain) {
return &z
}
}
return nil
}

func (d *DelegationZones) GetClusterNSNameByGslb(gslb *k8gbv1beta1.Gslb) string {
z := d.FindByGslbStatusHostname(gslb)
if z != nil {
return z.ClusterNSName
}
return ""
}

func (d *DelegationZones) GetExternalClusterNSNamesByHostname(host string) map[string]string {
z := d.getZone(host)
if z != nil {
return z.ExtClusterNSNames
}
return map[string]string{}
}

func (d *DelegationZones) ContainsZone(host string) bool {
return d.getZone(host) != nil
}

func (d *DelegationZones) ListZones() []string {
var zones []string
for _, z := range *d {
zones = append(zones, z.Zone)
}
return zones
}

func (d *DelegationZones) getZone(host string) *DelegationZoneInfo {
for _, z := range *d {
if strings.Contains(host, z.Zone) {
return &z
}
}
return nil
}
Loading

0 comments on commit a13ba18

Please sign in to comment.