@@ -24,6 +24,7 @@ import (
2424
2525 "github.com/go-logr/logr"
2626 networkv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1"
27+ operatorv1 "github.com/openshift/api/operator/v1"
2728 designatev1 "github.com/openstack-k8s-operators/designate-operator/api/v1beta1"
2829 "github.com/openstack-k8s-operators/designate-operator/pkg/designate"
2930 "github.com/openstack-k8s-operators/designate-operator/pkg/designateunbound"
@@ -74,11 +75,24 @@ type StubZoneTmplRec struct {
7475 Servers []string
7576}
7677
78+ func getCIDRsFromNADs (nadList []networkv1.NetworkAttachmentDefinition ) ([]string , error ) {
79+ cidrs := []string {}
80+ for _ , nad := range nadList {
81+ nadConfig , err := designate .GetNADConfig (& nad )
82+ if err != nil {
83+ return nil , err
84+ }
85+ cidrs = append (cidrs , nadConfig .IPAM .CIDR .String ())
86+ }
87+ return cidrs , nil
88+ }
89+
7790//+kubebuilder:rbac:groups=designate.openstack.org,resources=designateunbounds,verbs=get;list;watch;create;update;patch;delete
7891//+kubebuilder:rbac:groups=designate.openstack.org,resources=designateunbounds/status,verbs=get;update;patch
7992//+kubebuilder:rbac:groups=designate.openstack.org,resources=designateunbounds/finalizers,verbs=update;patch
8093//+kubebuilder:rbac:groups=k8s.cni.cncf.io,resources=network-attachment-definitions,verbs=get;list;watch
8194//+kubebuilder:rbac:groups=topology.openstack.org,resources=topologies,verbs=get;list;watch;update
95+ //+kubebuilder:rbac:groups=operator.openshift.io,resources=networks,verbs=get;list;watch
8296
8397// Reconcile implementation for designate's Unbound resolver
8498func (r * UnboundReconciler ) Reconcile (ctx context.Context , req ctrl.Request ) (result ctrl.Result , _err error ) {
@@ -315,33 +329,8 @@ func (r *UnboundReconciler) reconcileNormal(ctx context.Context, instance *desig
315329 }
316330 instance .Status .Conditions .MarkTrue (condition .CreateServiceReadyCondition , condition .CreateServiceReadyMessage )
317331
318- configMapVars := make (map [string ]env.Setter )
319- err := r .generateServiceConfigMaps (ctx , instance , helper , & configMapVars )
320- if err != nil {
321- instance .Status .Conditions .Set (condition .FalseCondition (
322- condition .ServiceConfigReadyCondition ,
323- condition .ErrorReason ,
324- condition .SeverityWarning ,
325- condition .ServiceConfigReadyErrorMessage ,
326- err .Error ()))
327- return ctrl.Result {}, err
328- }
329-
330- //
331- // create hash over all the different input resources to identify if any those changed
332- // and a restart/recreate is required.
333- //
334- inputHash , hashChanged , err := r .createHashOfInputHashes (ctx , instance , configMapVars )
335- if err != nil {
336- return ctrl.Result {}, err
337- } else if hashChanged {
338- // Hash changed and instance status should be updated (which will be done by main defer func),
339- // so we need to return and reconcile again
340- return ctrl.Result {}, nil
341- }
342-
343- instance .Status .Conditions .MarkTrue (condition .ServiceConfigReadyCondition , condition .ServiceConfigReadyMessage )
344-
332+ // We do initial processing of the network attachments before the configs because it influences some of the
333+ // automatically configurations.
345334 nadList := []networkv1.NetworkAttachmentDefinition {}
346335 for _ , networkAttachment := range instance .Spec .NetworkAttachments {
347336 nad , err := nad .GetNADWithName (ctx , helper , networkAttachment , instance .Namespace )
@@ -372,6 +361,33 @@ func (r *UnboundReconciler) reconcileNormal(ctx context.Context, instance *desig
372361 }
373362 }
374363
364+ configMapVars := make (map [string ]env.Setter )
365+ err := r .generateServiceConfigMaps (ctx , instance , helper , & configMapVars , nadList )
366+ if err != nil {
367+ instance .Status .Conditions .Set (condition .FalseCondition (
368+ condition .ServiceConfigReadyCondition ,
369+ condition .ErrorReason ,
370+ condition .SeverityWarning ,
371+ condition .ServiceConfigReadyErrorMessage ,
372+ err .Error ()))
373+ return ctrl.Result {}, err
374+ }
375+
376+ //
377+ // create hash over all the different input resources to identify if any those changed
378+ // and a restart/recreate is required.
379+ //
380+ inputHash , hashChanged , err := r .createHashOfInputHashes (ctx , instance , configMapVars )
381+ if err != nil {
382+ return ctrl.Result {}, err
383+ } else if hashChanged {
384+ // Hash changed and instance status should be updated (which will be done by main defer func),
385+ // so we need to return and reconcile again
386+ return ctrl.Result {}, nil
387+ }
388+
389+ instance .Status .Conditions .MarkTrue (condition .ServiceConfigReadyCondition , condition .ServiceConfigReadyMessage )
390+
375391 serviceAnnotations , err := nad .EnsureNetworksAnnotation (nadList )
376392 if err != nil {
377393 return ctrl.Result {}, fmt .Errorf ("failed create network annotation from %s: %w" ,
@@ -518,6 +534,7 @@ func (r *UnboundReconciler) onIPChange() (ctrl.Result, error) {
518534 return ctrl.Result {}, nil
519535}
520536
537+ // Set stub zone configuration defaults if they are net set by CR data.
521538func stubZoneDefaults (values map [string ]string ) map [string ]string {
522539
523540 if values == nil {
@@ -532,20 +549,84 @@ func stubZoneDefaults(values map[string]string) map[string]string {
532549 return values
533550}
534551
552+ // getClusterJoinSubnets will return configured join subnets from the cluster network if available. If noit will
553+ // return the expected defaults defined in the build.
554+ // TODO(beagles): it might be a good idea to have this settable through an environment variable to bridge
555+ // unexpected compatibility issues.
556+ func (r * UnboundReconciler ) getClusterJoinSubnets (ctx context.Context ) []string {
557+ Log := r .GetLogger (ctx )
558+
559+ // Get the cluster network operator configuration
560+ network := & operatorv1.Network {}
561+ err := r .Get (ctx , types.NamespacedName {Name : "cluster" }, network )
562+ if err != nil {
563+ // If we can't get the network config, fall back to defaults.
564+ // TODO(beagles): while probably not necessary, we should revisit to see if this should be an error.
565+ Log .Info ("Unable to get cluster network configuration, using defaults" , "error" , err )
566+ return []string {designateunbound .DefaultJoinSubnetV4 , designateunbound .DefaultJoinSubnetV6 }
567+ }
568+
569+ var joinSubnets []string
570+
571+ // NOTE(beagles): we are only handling OVN-Kubernetes configuration at this time. There is a
572+ // question of whether we should only set defaults for IP versions that are 'enabled'.
573+ // Unfortunately, I'm not sure we can know that for sure from the network operator configuration.
574+ // That is, absence of configuration might mean that it is enabled, but with all defaults.
575+
576+ // Extract join subnets from OVN-Kubernetes configuration
577+ if network .Spec .DefaultNetwork .OVNKubernetesConfig != nil {
578+ ovnConfig := network .Spec .DefaultNetwork .OVNKubernetesConfig
579+
580+ // IPv4 join subnet
581+ if ovnConfig .IPv4 != nil && ovnConfig .IPv4 .InternalJoinSubnet != "" {
582+ joinSubnets = append (joinSubnets , ovnConfig .IPv4 .InternalJoinSubnet )
583+ Log .Info ("Found IPv4 join subnet from cluster config" , "subnet" , ovnConfig .IPv4 .InternalJoinSubnet )
584+ } else {
585+ joinSubnets = append (joinSubnets , designateunbound .DefaultJoinSubnetV4 )
586+ Log .Info ("Using default IPv4 join subnet" , "subnet" , designateunbound .DefaultJoinSubnetV4 )
587+ }
588+
589+ // IPv6 join subnet
590+ if ovnConfig .IPv6 != nil && ovnConfig .IPv6 .InternalJoinSubnet != "" {
591+ joinSubnets = append (joinSubnets , ovnConfig .IPv6 .InternalJoinSubnet )
592+ Log .Info ("Found IPv6 join subnet from cluster config" , "subnet" , ovnConfig .IPv6 .InternalJoinSubnet )
593+ } else {
594+ joinSubnets = append (joinSubnets , designateunbound .DefaultJoinSubnetV6 )
595+ Log .Info ("Using default IPv6 join subnet" , "subnet" , designateunbound .DefaultJoinSubnetV6 )
596+ }
597+ } else {
598+ // No OVN-Kubernetes config found, use defaults
599+ Log .Info ("No OVN-Kubernetes configuration found, using defaults" )
600+ joinSubnets = []string {designateunbound .DefaultJoinSubnetV4 , designateunbound .DefaultJoinSubnetV6 }
601+ }
602+
603+ return joinSubnets
604+ }
605+
535606func (r * UnboundReconciler ) generateServiceConfigMaps (
536607 ctx context.Context ,
537608 instance * designatev1.DesignateUnbound ,
538609 h * helper.Helper ,
539610 envVars * map [string ]env.Setter ,
611+ nadList []networkv1.NetworkAttachmentDefinition ,
540612) error {
541613 Log := r .GetLogger (ctx )
542614 Log .Info ("Generating service config map" )
543615 cmLabels := labels .GetLabels (instance , labels .GetGroupLabel (designateunbound .Component ), map [string ]string {})
544616 customData := map [string ]string {common .CustomServiceConfigFileName : instance .Spec .CustomServiceConfig }
617+ // NOTE(beagles): DefaultConfigOverwrite is bugged in unbound because it is
618+ // applied to conf.d when it really is meant to for overwriting stuff in
619+ // /etc/unbound. A reasonable fix would be to have special handling for the
620+ // "unbound.conf" and if any of the other files exist in /etc/unbound,
621+ // overwrite them. The ones that aren't can go into /etc/unbound/conf.d for
622+ // backwards compatibility.
545623 maps .Copy (customData , instance .Spec .DefaultConfigOverwrite )
546624
547625 templateParameters := make (map [string ]any )
548626
627+ //
628+ // Create stub zone configuration data from predictable IP map.
629+ //
549630 stubZoneData := make ([]StubZoneTmplRec , len (instance .Spec .StubZones ))
550631 if len (instance .Spec .StubZones ) > 0 {
551632 bindIPMap := & corev1.ConfigMap {}
@@ -572,6 +653,19 @@ func (r *UnboundReconciler) generateServiceConfigMaps(
572653 }
573654 templateParameters ["StubZones" ] = stubZoneData
574655
656+ // TODO(beagles): There are situations where the allowCidrs should be overriddable, do we want to support that at the API level or
657+ // customServiceConfig
658+ // Dynamically discover join subnets from the cluster network operator configuration
659+ allowCidrs := r .getClusterJoinSubnets (ctx )
660+
661+ // TODO(beagles): create entries for each network attachment.
662+ nadCIDRs , nadErr := getCIDRsFromNADs (nadList )
663+ if nadErr != nil {
664+ Log .Error (nadErr , "unable to get CIDRs from network attachment definitions" )
665+ }
666+ allowCidrs = append (allowCidrs , nadCIDRs ... )
667+ templateParameters ["AllowCidrs" ] = allowCidrs
668+
575669 cms := []util.Template {
576670 // ConfigMap
577671 {
@@ -587,7 +681,7 @@ func (r *UnboundReconciler) generateServiceConfigMaps(
587681 err := secret .EnsureSecrets (ctx , h , instance , cms , envVars )
588682
589683 if err != nil {
590- Log .Error (err , "uanble to process config map" )
684+ Log .Error (err , "unable to process config map" )
591685 return err
592686 }
593687 Log .Info ("Service config map generated" )
0 commit comments