Skip to content

Commit 89d3a18

Browse files
committed
Stubzone support
Initial implementation of support for stub zones for the unbound resolver.
1 parent 8b01920 commit 89d3a18

File tree

14 files changed

+230
-10
lines changed

14 files changed

+230
-10
lines changed

api/bases/designate.openstack.org_designates.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1840,6 +1840,22 @@ spec:
18401840
description: ServiceAccount - service account name used internally
18411841
to provide Designate services the default SA name
18421842
type: string
1843+
stubZones:
1844+
description: Allows configuring stub zone entries in the managed
1845+
Unbound servers for the managed nameservers.
1846+
items:
1847+
properties:
1848+
name:
1849+
type: string
1850+
options:
1851+
additionalProperties:
1852+
type: string
1853+
type: object
1854+
required:
1855+
- name
1856+
type: object
1857+
type: array
1858+
x-kubernetes-list-type: atomic
18431859
topologyRef:
18441860
description: |-
18451861
TopologyRef to apply the Topology defined by the associated CR referenced

api/bases/designate.openstack.org_designateunbounds.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,22 @@ spec:
311311
description: ServiceAccount - service account name used internally
312312
to provide Designate services the default SA name
313313
type: string
314+
stubZones:
315+
description: Allows configuring stub zone entries in the managed Unbound
316+
servers for the managed nameservers.
317+
items:
318+
properties:
319+
name:
320+
type: string
321+
options:
322+
additionalProperties:
323+
type: string
324+
type: object
325+
required:
326+
- name
327+
type: object
328+
type: array
329+
x-kubernetes-list-type: atomic
314330
topologyRef:
315331
description: |-
316332
TopologyRef to apply the Topology defined by the associated CR referenced

api/v1beta1/designateunbound_types.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,24 @@ type DesignateUnboundSpecBase struct {
5757
// an override for each replica.
5858
// +kubebuilder:validation:Optional
5959
Override UnboundOverrideSpec `json:"override,omitempty"`
60+
61+
// Allows configuring stub zone entries in the managed Unbound servers for the managed nameservers.
62+
// +kubebuilder:validation:Optional
63+
// +listType=atomic
64+
StubZones []StubZone `json:"stubZones,omitempty"`
6065
}
6166

6267
type UnboundOverrideSpec struct {
6368
// +listType=atomic
6469
Services []service.OverrideSpec `json:"services,omitempty"`
6570
}
6671

72+
type StubZone struct {
73+
Name string `json:"name"`
74+
// +kubebuilder:validation:Optional
75+
Options map[string]string `json:"options,omitempty"`
76+
}
77+
6778
// DesignateUnboundStatus defines the observed state of DesignateUnbound
6879
type DesignateUnboundStatus struct {
6980
// ReadyCount of designate central instances

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 29 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/designate.openstack.org_designates.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1840,6 +1840,22 @@ spec:
18401840
description: ServiceAccount - service account name used internally
18411841
to provide Designate services the default SA name
18421842
type: string
1843+
stubZones:
1844+
description: Allows configuring stub zone entries in the managed
1845+
Unbound servers for the managed nameservers.
1846+
items:
1847+
properties:
1848+
name:
1849+
type: string
1850+
options:
1851+
additionalProperties:
1852+
type: string
1853+
type: object
1854+
required:
1855+
- name
1856+
type: object
1857+
type: array
1858+
x-kubernetes-list-type: atomic
18431859
topologyRef:
18441860
description: |-
18451861
TopologyRef to apply the Topology defined by the associated CR referenced

config/crd/bases/designate.openstack.org_designateunbounds.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,22 @@ spec:
311311
description: ServiceAccount - service account name used internally
312312
to provide Designate services the default SA name
313313
type: string
314+
stubZones:
315+
description: Allows configuring stub zone entries in the managed Unbound
316+
servers for the managed nameservers.
317+
items:
318+
properties:
319+
name:
320+
type: string
321+
options:
322+
additionalProperties:
323+
type: string
324+
type: object
325+
required:
326+
- name
327+
type: object
328+
type: array
329+
x-kubernetes-list-type: atomic
314330
topologyRef:
315331
description: |-
316332
TopologyRef to apply the Topology defined by the associated CR referenced

controllers/designateunbound_controller.go

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ type UnboundReconciler struct {
6262
Scheme *runtime.Scheme
6363
}
6464

65+
type StubZoneTmplRec struct {
66+
Name string
67+
Options map[string]string
68+
Servers []string
69+
}
70+
6571
func min(i int, j int) int {
6672
if i < j {
6773
return i
@@ -271,11 +277,6 @@ func (r *UnboundReconciler) reconcileUpgrade(instance *designatev1.DesignateUnbo
271277
func (r *UnboundReconciler) reconcileNormal(ctx context.Context, instance *designatev1.DesignateUnbound, helper *helper.Helper) (ctrl.Result, error) {
272278
util.LogForObject(helper, "Reconciling Service", instance)
273279

274-
if controllerutil.AddFinalizer(instance, helper.GetFinalizer()) {
275-
// Return to persist the finalizer immediately
276-
return ctrl.Result{}, nil
277-
}
278-
279280
serviceLabels := map[string]string{
280281
common.AppSelector: instance.ObjectMeta.Name,
281282
common.ComponentSelector: designateunbound.Component,
@@ -515,6 +516,20 @@ func (r *UnboundReconciler) onIPChange() (ctrl.Result, error) {
515516
return ctrl.Result{}, nil
516517
}
517518

519+
func stubZoneDefaults(values map[string]string) map[string]string {
520+
521+
if values == nil {
522+
values = make(map[string]string)
523+
}
524+
if _, ok := values["stub-prime"]; !ok {
525+
values["stub-prime"] = "true"
526+
}
527+
if _, ok := values["stub-first"]; !ok {
528+
values["stub-first"] = "true"
529+
}
530+
return values
531+
}
532+
518533
func (r *UnboundReconciler) generateServiceConfigMaps(
519534
ctx context.Context,
520535
instance *designatev1.DesignateUnbound,
@@ -530,6 +545,32 @@ func (r *UnboundReconciler) generateServiceConfigMaps(
530545

531546
templateParameters := make(map[string]interface{})
532547

548+
stubZoneData := make([]StubZoneTmplRec, len(instance.Spec.StubZones))
549+
if len(instance.Spec.StubZones) > 0 {
550+
bindIPMap := &corev1.ConfigMap{}
551+
err := h.GetClient().Get(ctx, types.NamespacedName{Name: designate.BindPredIPConfigMap, Namespace: instance.GetNamespace()}, bindIPMap)
552+
if err != nil {
553+
if k8s_errors.IsNotFound(err) {
554+
r.Log.Info("nameserver IPs not available, unable to complete unbound configuration at this time")
555+
}
556+
return err
557+
}
558+
bindIPs := make([]string, len(bindIPMap.Data))
559+
keyTmpl := "bind_address_%d"
560+
for i := 0; i < len(bindIPMap.Data); i++ {
561+
bindIPs[i] = bindIPMap.Data[fmt.Sprintf(keyTmpl, i)]
562+
}
563+
564+
for i := 0; i < len(instance.Spec.StubZones); i++ {
565+
stubZoneData[i] = StubZoneTmplRec{
566+
Name: instance.Spec.StubZones[i].Name,
567+
Options: stubZoneDefaults(instance.Spec.StubZones[i].Options),
568+
Servers: bindIPs,
569+
}
570+
}
571+
}
572+
templateParameters["StubZones"] = stubZoneData
573+
533574
cms := []util.Template{
534575
// ScriptsConfigMap
535576
{

pkg/designateunbound/statefulset.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func StatefulSet(instance *designatev1beta1.DesignateUnbound,
5050
VolumeSource: corev1.VolumeSource{
5151
Secret: &corev1.SecretVolumeSource{
5252
DefaultMode: &configMode,
53-
SecretName: "designate-unbound-config-data",
53+
SecretName: fmt.Sprintf("%s-config-data", instance.Name),
5454
},
5555
},
5656
},
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{{- range .StubZones }}
2+
stub-zone:
3+
name: {{ .Name }}
4+
{{- range .Servers }}
5+
stub-addr: {{ . }}
6+
{{- end }}
7+
{{- range $key, $value := .Options }}
8+
{{ $key }}: {{ $value }}
9+
{{- end }}
10+
{{ end }}

tests/functional/base_test.go

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ func SimulateKeystoneReady(
140140
}, timeout, interval).Should(Succeed())
141141
}
142142

143-
func GetDefaultDesignateSpec(bind9ReplicaCount, mdnsReplicaCount int) map[string]interface{} {
143+
func GetDefaultDesignateSpec(bind9ReplicaCount, mdnsReplicaCount int, unboundReplicaCount int) map[string]interface{} {
144144
spec := map[string]interface{}{
145145
"databaseInstance": "test-designate-db-instance",
146146
"secret": SecretName,
@@ -157,6 +157,11 @@ func GetDefaultDesignateSpec(bind9ReplicaCount, mdnsReplicaCount int) map[string
157157
Replicas: ptr.To(int32(mdnsReplicaCount)),
158158
},
159159
}
160+
spec["designateUnbound"] = designatev1.DesignateUnboundSpec{
161+
DesignateUnboundSpecBase: designatev1.DesignateUnboundSpecBase{
162+
Replicas: ptr.To(int32(unboundReplicaCount)),
163+
},
164+
}
160165
return spec
161166
}
162167

@@ -426,6 +431,51 @@ func DesignateProducerConditionGetter(name types.NamespacedName) condition.Condi
426431
return instance.Status.Conditions
427432
}
428433

434+
// DesignateUnbound
435+
func GetDefaultUnboundSpec() map[string]interface{} {
436+
return map[string]interface{}{
437+
"databaseHostame": "hostname-for-designate-unbound",
438+
"secret": SecretName,
439+
"designateNetworkAttachment": "designate-attachment",
440+
"serviceAccount": "designate",
441+
"containerImage": "repo/designate-unbound-image",
442+
}
443+
}
444+
445+
func CreateDesignateUnbound(name types.NamespacedName, spec map[string]interface{}) client.Object {
446+
raw := map[string]interface{}{
447+
"apiVersion": "designate.openstack.org/v1beta1",
448+
"kind": "DesignateUnbound",
449+
"metadata": map[string]interface{}{
450+
"name": name.Name,
451+
"namespace": name.Namespace,
452+
},
453+
"spec": spec,
454+
}
455+
return th.CreateUnstructured(raw)
456+
}
457+
458+
func GetDesignateUnbound(name types.NamespacedName) *designatev1.DesignateUnbound {
459+
instance := &designatev1.DesignateUnbound{}
460+
Eventually(func(g Gomega) {
461+
g.Expect(k8sClient.Get(ctx, name, instance)).Should(Succeed())
462+
}, timeout, interval).Should(Succeed())
463+
return instance
464+
}
465+
466+
func CreateBindIPMap(namespace string, configData map[string]interface{}) client.Object {
467+
raw := map[string]interface{}{
468+
"apiVersion": "v1",
469+
"kind": "ConfigMap",
470+
"metadata": map[string]interface{}{
471+
"name": designate.BindPredIPConfigMap,
472+
"namespace": namespace,
473+
},
474+
"data": configData,
475+
}
476+
return th.CreateUnstructured(raw)
477+
}
478+
429479
// Network attachment
430480
func CreateNAD(name types.NamespacedName) client.Object {
431481
raw := map[string]interface{}{

0 commit comments

Comments
 (0)