Repository: k8gb-io/k8gb

Issue:
Deployment configuration for geotags
Currently we specify 
`operator:yaml:`
```yaml
            - name: CLUSTER_GEO_TAG
              value: {{ quote .Values.k8gb.clusterGeoTag }}
            - name: EXT_GSLB_CLUSTERS_GEO_TAGS
              value: {{ quote .Values.k8gb.extGslbClustersGeoTags }}
```
So for 5 cluster setup it can look like:
```
cluster 1:
CLUSTER_GEO_TAG: eu
EXT_GSLB_CLUSTERS_GEO_TAGS: us, cz, af, ap

cluster 2:
CLUSTER_GEO_TAG: us
EXT_GSLB_CLUSTERS_GEO_TAGS: eu, cz, af, ap

cluster 3:
CLUSTER_GEO_TAG: cz
EXT_GSLB_CLUSTERS_GEO_TAGS: eu, us, af, ap
..
```

This is not ideal because for each cluster `EXT_GSLB_CLUSTERS_GEO_TAGS` needs to be calculated (so that `CLUSTER_GEO_TAG` is not in the list). 

optimisation 1)
If we allowed the `EXT_GSLB_CLUSTERS_GEO_TAGS` to contain all the geo tags, including the "myself" (~`CLUSTER_GEO_TAG`), the deployment burden would be easier and we can easily perform this operation internally in the gslb controller (even check if `EXT_GSLB_CLUSTERS_GEO_TAGS ∈ CLUSTER_GEO_TAG` during validation phase)

optimisation 2)
Another optimisation that would make the life easier for those who deploy us would be inferring the `CLUSTER_GEO_TAG` from the Node's label/annotation. This shifts the problem to some other level, but it would allow for the same helm command (or the same crossplane XRD / whatever) to be run against each cluster.

optimisation 3)
Furthermore, if we look into distributed systems consisting of a lot of clusters (say 10), the `EXT_GSLB_CLUSTERS_GEO_TAGS` list will be pretty long and we need to assure the consistency among all the clusters. Now what if we want to unplug one cluster or add additional one? We are in the situation where we have to update each deployment of k8gb on each cluster to reflect this change in the `EXT_GSLB_CLUSTERS_GEO_TAGS` variable. If we have this list stored as TXT or SOA record on the DNS level (in the similar fashion as we store the split brain logic) this would be no longer needed. On the other hand, we should be careful about how much info would be stored in the centralised fashion, because we might be losing the no spof feature (imho). Well, but if the edge dns fails, we are screwed anyway :D

Discussion:

Solution patch:
diff --git a/controllers/resolver/config_delegationZones.go b/controllers/resolver/config_delegationZones.go
index 18f7a142..3497c114 100644
--- a/controllers/resolver/config_delegationZones.go
+++ b/controllers/resolver/config_delegationZones.go
@@ -56,6 +56,10 @@ func parseDelegationZones(config *Config) ([]*DelegationZoneInfo, error) {
 	extClusterNSNames := func(zone, edge string) map[string]string {
 		m := map[string]string{}
 		for _, tag := range config.ExtClustersGeoTagsRaw {
+			if tag == config.ClusterGeoTag {
+				// skip the cluster GeoTag, see: https://github.com/k8gb-io/k8gb/issues/720
+				continue
+			}
 			m[tag] = getNsName(tag, zone, edge)
 		}
 		return m



Test patch:
diff --git a/controllers/resolver/resolver_test.go b/controllers/resolver/resolver_test.go
index ec873d6b..a54558fc 100644
--- a/controllers/resolver/resolver_test.go
+++ b/controllers/resolver/resolver_test.go
@@ -507,6 +507,52 @@ func TestConfigurations(t *testing.T) {
 				 INFOBLOX_WAPI_PASSWORD="testpassword"`,
 			expectedError: true,
 		},
+		{
+			name: "valid configuration without clusterGeotag in EXT_GSLB_CLUSTERS_GEO_TAGS",
+			envvars: `CLUSTER_GEO_TAG=us;
+				 EXT_GSLB_CLUSTERS_GEO_TAGS=eu;
+				 DNS_ZONES=example.com:cloud.example.com:300;
+				 EDGE_DNS_SERVERS=local.test;
+				 EXTDNS_ENABLED=true`,
+			assert: func(t *testing.T, cfg *Config) {
+				assert.Equal(t, "gslb-ns-us-cloud.example.com", cfg.DelegationZones[0].ClusterNSName)
+				assert.Equal(t, "gslb-ns-eu-cloud.example.com", cfg.DelegationZones[0].ExtClusterNSNames["eu"])
+			},
+		},
+		{
+			name: "valid configuration with clusterGeotag in EXT_GSLB_CLUSTERS_GEO_TAGS",
+			envvars: `CLUSTER_GEO_TAG=us;
+				 EXT_GSLB_CLUSTERS_GEO_TAGS=us,eu;
+				 DNS_ZONES=example.com:cloud.example.com:300;
+				 EDGE_DNS_SERVERS=local.test;
+				 EXTDNS_ENABLED=true`,
+			assert: func(t *testing.T, cfg *Config) {
+				assert.Equal(t, "gslb-ns-us-cloud.example.com", cfg.DelegationZones[0].ClusterNSName)
+				assert.Equal(t, "gslb-ns-eu-cloud.example.com", cfg.DelegationZones[0].ExtClusterNSNames["eu"])
+				assert.Equal(t, "", cfg.DelegationZones[0].ExtClusterNSNames["us"])
+			},
+		},
+		{
+			name: "invalid configuration with multiple clusterGeotag in EXT_GSLB_CLUSTERS_GEO_TAGS",
+			envvars: `CLUSTER_GEO_TAG=us;
+				 EXT_GSLB_CLUSTERS_GEO_TAGS=us,us,eu;
+				 DNS_ZONES=example.com:cloud.example.com:300;
+				 EDGE_DNS_SERVERS=local.test;
+				 EXTDNS_ENABLED=true`,
+			expectedError: true,
+		},
+		{
+			name: "invalid configuration with equal clusterGeotag in EXT_GSLB_CLUSTERS_GEO_TAGS",
+			envvars: `CLUSTER_GEO_TAG=us;
+				 EXT_GSLB_CLUSTERS_GEO_TAGS=us;
+				 DNS_ZONES=example.com:cloud.example.com:300;
+				 EDGE_DNS_SERVERS=local.test;
+				 EXTDNS_ENABLED=true`,
+			assert: func(t *testing.T, cfg *Config) {
+				assert.Equal(t, "gslb-ns-us-cloud.example.com", cfg.DelegationZones[0].ClusterNSName)
+				assert.Equal(t, 0, len(cfg.DelegationZones[0].ExtClusterNSNames))
+			},
+		},
 	}
 
 	for _, test := range tests {