diff --git a/api/bases/dataplane.openstack.org_openstackdataplaneservices.yaml b/api/bases/dataplane.openstack.org_openstackdataplaneservices.yaml index 3adcfd10d..87ba1b942 100644 --- a/api/bases/dataplane.openstack.org_openstackdataplaneservices.yaml +++ b/api/bases/dataplane.openstack.org_openstackdataplaneservices.yaml @@ -34,6 +34,8 @@ spec: items: type: string type: array + hasTLSCerts: + type: boolean label: maxLength: 53 pattern: '[a-z]([-a-z0-9]*[a-z0-9])' diff --git a/api/v1beta1/openstackdataplaneservice_types.go b/api/v1beta1/openstackdataplaneservice_types.go index c8d82238b..f8c368f40 100644 --- a/api/v1beta1/openstackdataplaneservice_types.go +++ b/api/v1beta1/openstackdataplaneservice_types.go @@ -76,6 +76,11 @@ type OpenStackDataPlaneServiceSpec struct { // OpenStackAnsibleEERunnerImage image to use as the ansibleEE runner image // +kubebuilder:validation:Optional OpenStackAnsibleEERunnerImage string `json:"openStackAnsibleEERunnerImage,omitempty" yaml:"openStackAnsibleEERunnerImage,omitempty"` + + // HasTLSCerts - Whether the nodes have TLS certs + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:booleanSwitch"} + HasTLSCerts *bool `json:"hasTLSCerts,omitempty" yaml:"hasTLSCerts,omitempty"` } // OpenStackDataPlaneServiceStatus defines the observed state of OpenStackDataPlaneService diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index a87c87918..843f1eb73 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -519,6 +519,11 @@ func (in *OpenStackDataPlaneServiceSpec) DeepCopyInto(out *OpenStackDataPlaneSer *out = make([]string, len(*in)) copy(*out, *in) } + if in.HasTLSCerts != nil { + in, out := &in.HasTLSCerts, &out.HasTLSCerts + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenStackDataPlaneServiceSpec. diff --git a/config/crd/bases/dataplane.openstack.org_openstackdataplaneservices.yaml b/config/crd/bases/dataplane.openstack.org_openstackdataplaneservices.yaml index 3adcfd10d..87ba1b942 100644 --- a/config/crd/bases/dataplane.openstack.org_openstackdataplaneservices.yaml +++ b/config/crd/bases/dataplane.openstack.org_openstackdataplaneservices.yaml @@ -34,6 +34,8 @@ spec: items: type: string type: array + hasTLSCerts: + type: boolean label: maxLength: 53 pattern: '[a-z]([-a-z0-9]*[a-z0-9])' diff --git a/config/manifests/bases/dataplane-operator.clusterserviceversion.yaml b/config/manifests/bases/dataplane-operator.clusterserviceversion.yaml index b0345abdc..694c25029 100644 --- a/config/manifests/bases/dataplane-operator.clusterserviceversion.yaml +++ b/config/manifests/bases/dataplane-operator.clusterserviceversion.yaml @@ -77,6 +77,12 @@ spec: displayName: OpenStack Data Plane Service kind: OpenStackDataPlaneService name: openstackdataplaneservices.dataplane.openstack.org + specDescriptors: + - description: HasTLSCerts - Whether the nodes have TLS certs + displayName: Has TLSCerts + path: hasTLSCerts + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch statusDescriptors: - description: Conditions displayName: Conditions diff --git a/config/services/dataplane_v1beta1_openstackdataplaneservice_libvirt.yaml b/config/services/dataplane_v1beta1_openstackdataplaneservice_libvirt.yaml index 8c877210e..75d48bfb4 100644 --- a/config/services/dataplane_v1beta1_openstackdataplaneservice_libvirt.yaml +++ b/config/services/dataplane_v1beta1_openstackdataplaneservice_libvirt.yaml @@ -5,3 +5,4 @@ metadata: spec: label: libvirt playbook: osp.edpm.libvirt + hasTLSCerts: True diff --git a/config/services/dataplane_v1beta1_openstackdataplaneservice_nova.yaml b/config/services/dataplane_v1beta1_openstackdataplaneservice_nova.yaml index e13a2ef0c..66182b50d 100644 --- a/config/services/dataplane_v1beta1_openstackdataplaneservice_nova.yaml +++ b/config/services/dataplane_v1beta1_openstackdataplaneservice_nova.yaml @@ -11,3 +11,4 @@ spec: # and ssh-publickey - nova-migration-ssh-key playbook: osp.edpm.nova + hasTLSCerts: True diff --git a/controllers/openstackdataplanenodeset_controller.go b/controllers/openstackdataplanenodeset_controller.go index 97c54183e..8c2b9c527 100644 --- a/controllers/openstackdataplanenodeset_controller.go +++ b/controllers/openstackdataplanenodeset_controller.go @@ -200,7 +200,7 @@ func (r *OpenStackDataPlaneNodeSetReconciler) Reconcile(ctx context.Context, req } // Ensure DNSData Required for Nodes - dnsAddresses, dnsClusterAddresses, ctlplaneSearchDomain, isReady, err := deployment.EnsureDNSData( + dnsAddresses, dnsClusterAddresses, ctlplaneSearchDomain, isReady, allHostnames, allIPs, err := deployment.EnsureDNSData( ctx, helper, instance, allIPSets) if err != nil || !isReady { @@ -209,6 +209,22 @@ func (r *OpenStackDataPlaneNodeSetReconciler) Reconcile(ctx context.Context, req instance.Status.DNSClusterAddresses = dnsClusterAddresses instance.Status.CtlplaneSearchDomain = ctlplaneSearchDomain + // Issue certs for TLS for services that need them + for _, serviceName := range instance.Spec.Services { + service, err := deployment.GetService(ctx, helper, serviceName) + if err != nil { + return ctrl.Result{}, err + } + if service.Spec.HasTLSCerts != nil && *service.Spec.HasTLSCerts { + result, err = deployment.EnsureTLSCerts(ctx, helper, instance, allHostnames, allIPs, serviceName) + if err != nil { + return ctrl.Result{}, err + } else if (result != ctrl.Result{}) { + return result, nil + } + } + } + ansibleSSHPrivateKeySecret := instance.Spec.NodeTemplate.AnsibleSSHPrivateKeySecret secretKeys := []string{} diff --git a/docs/openstack_dataplaneservice.md b/docs/openstack_dataplaneservice.md index d59b7fbee..8ad55f387 100644 --- a/docs/openstack_dataplaneservice.md +++ b/docs/openstack_dataplaneservice.md @@ -125,6 +125,7 @@ OpenStackDataPlaneServiceSpec defines the desired state of OpenStackDataPlaneSer | configMaps | ConfigMaps list of ConfigMap names to mount as ExtraMounts for the OpenStackAnsibleEE | []string | false | | secrets | Secrets list of Secret names to mount as ExtraMounts for the OpenStackAnsibleEE | []string | false | | openStackAnsibleEERunnerImage | OpenStackAnsibleEERunnerImage image to use as the ansibleEE runner image | string | false | +| hasTLSCerts | HasTLSCerts - Whether the nodes have TLS certs | *bool | false | [Back to Custom Resources](#custom-resources) diff --git a/go.mod b/go.mod index c2fa8e10f..5563ff57d 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ replace golang.org/x/net => golang.org/x/net v0.18.0 //allow-merging replace github.com/openstack-k8s-operators/dataplane-operator/api => ./api require ( + github.com/cert-manager/cert-manager v1.11.5 github.com/go-logr/logr v1.3.0 github.com/google/uuid v1.4.0 github.com/k8snetworkplumbingwg/network-attachment-definition-client v1.4.0 @@ -16,6 +17,7 @@ require ( github.com/openstack-k8s-operators/dataplane-operator/api v0.0.0-20230724101130-2d6fe1f4706b github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20231122104142-3b449040167e github.com/openstack-k8s-operators/lib-common/modules/ansible v0.3.1-0.20231122111552-6bd6025ade37 + github.com/openstack-k8s-operators/lib-common/modules/certmanager v0.0.0-20231006072650-7fe7fe16bcd1 github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20231122111552-6bd6025ade37 github.com/openstack-k8s-operators/lib-common/modules/storage v0.3.1-0.20231122111552-6bd6025ade37 github.com/openstack-k8s-operators/lib-common/modules/test v0.3.1-0.20231122111552-6bd6025ade37 diff --git a/go.sum b/go.sum index c52bc7d5b..a3cf0cf89 100644 --- a/go.sum +++ b/go.sum @@ -47,6 +47,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cert-manager/cert-manager v1.11.5 h1:K2LurvwIE4hIhODQZnkOW6ljYe3lVMAliS/to+gI05o= +github.com/cert-manager/cert-manager v1.11.5/go.mod h1:zNOyoTEwdn9Rtj5Or2pjBY1Bqwtw4vBElP2fKSP8/g8= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -239,6 +241,8 @@ github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20231122104142-3 github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20231122104142-3b449040167e/go.mod h1:FnKU6sravC43Uj0iq2bhZaPMjoPCBhkNlVdiVoGi5/E= github.com/openstack-k8s-operators/lib-common/modules/ansible v0.3.1-0.20231122111552-6bd6025ade37 h1:DpfHnE6YERlwPX/zd0eaZ59uv/l6+uXThwHTaxdRPQ4= github.com/openstack-k8s-operators/lib-common/modules/ansible v0.3.1-0.20231122111552-6bd6025ade37/go.mod h1:A9sWNibvjr1a9B/mpy4k6J9xkH11fnn0Dx/X1EZ3On8= +github.com/openstack-k8s-operators/lib-common/modules/certmanager v0.0.0-20231006072650-7fe7fe16bcd1 h1:sE/qio/WNUEng0VBmefSr46e/cq4R83payEzge/Y48U= +github.com/openstack-k8s-operators/lib-common/modules/certmanager v0.0.0-20231006072650-7fe7fe16bcd1/go.mod h1:u1pqzqGNLcof95aqhLfU6xHVTD6ZTc5gWy2FE03UrZQ= github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20231122111552-6bd6025ade37 h1:ftwUwA41Y6R8U883Saz7aDg2lqUTh2ewm0qKwLuGLcU= github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20231122111552-6bd6025ade37/go.mod h1:/6//JWNEY68jOMoaoaSI0koL2jzpEKim3m60+jFCbqY= github.com/openstack-k8s-operators/lib-common/modules/storage v0.3.1-0.20231122111552-6bd6025ade37 h1:F/sQ5+TzB1dVf4VyeyLDtcyNQDHnIkqZPK9V+cr/f6s= @@ -641,6 +645,8 @@ rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/controller-runtime v0.14.7 h1:Vrnm2vk9ZFlRkXATHz0W0wXcqNl7kPat8q2JyxVy0Q8= sigs.k8s.io/controller-runtime v0.14.7/go.mod h1:ErTs3SJCOujNUnTz4AS+uh8hp6DHMo1gj6fFndJT1X8= +sigs.k8s.io/gateway-api v0.6.0 h1:v2FqrN2ROWZLrSnI2o91taHR8Sj3s+Eh3QU7gLNWIqA= +sigs.k8s.io/gateway-api v0.6.0/go.mod h1:EYJT+jlPWTeNskjV0JTki/03WX1cyAnBhwBJfYHpV/0= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= diff --git a/main.go b/main.go index 83f972794..0d104d3ba 100644 --- a/main.go +++ b/main.go @@ -41,6 +41,8 @@ import ( baremetalv1 "github.com/openstack-k8s-operators/openstack-baremetal-operator/api/v1beta1" "sigs.k8s.io/controller-runtime/pkg/client/config" + certmgrv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" + certmgrmetav1 "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" dataplanev1 "github.com/openstack-k8s-operators/dataplane-operator/api/v1beta1" dataplanev1beta1 "github.com/openstack-k8s-operators/dataplane-operator/api/v1beta1" "github.com/openstack-k8s-operators/dataplane-operator/controllers" @@ -61,6 +63,8 @@ func init() { utilruntime.Must(baremetalv1.AddToScheme(scheme)) utilruntime.Must(infranetworkv1.AddToScheme(scheme)) utilruntime.Must(dataplanev1beta1.AddToScheme(scheme)) + utilruntime.Must(certmgrv1.AddToScheme(scheme)) + utilruntime.Must(certmgrmetav1.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } diff --git a/pkg/deployment/cert.go b/pkg/deployment/cert.go new file mode 100644 index 000000000..a423d922c --- /dev/null +++ b/pkg/deployment/cert.go @@ -0,0 +1,128 @@ +/* +Copyright 2023. + +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. +*/ + +package deployment + +import ( + "context" + "fmt" + "time" + + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + dataplanev1 "github.com/openstack-k8s-operators/dataplane-operator/api/v1beta1" + "github.com/openstack-k8s-operators/lib-common/modules/certmanager" + "github.com/openstack-k8s-operators/lib-common/modules/common/helper" + "github.com/openstack-k8s-operators/lib-common/modules/common/secret" +) + +// EnsureTLSCerts generates a secret containing all the certificates for the relevant service +// This secret will be mounted by the ansibleEE pod as an extra mount when the service is deployed. +func EnsureTLSCerts(ctx context.Context, helper *helper.Helper, + instance *dataplanev1.OpenStackDataPlaneNodeSet, + allHostnames map[string][]string, + allIPs map[string][]string, + serviceName string) (ctrl.Result, error) { + + certsData := map[string][]byte{} + + // for each node in the nodeset, issue all the TLS certs needed based on the + // ips or DNS Names + for nodeName := range instance.Spec.Nodes { + var dnsNames []string + var secretName string + var certName string + var certSecret *corev1.Secret = nil + var err error + var result ctrl.Result + + // TODO(alee) decide if we want to use other labels + // For now we just add the hostname so we can select all the certs on one node + labels := map[string]string{ + "hostname": nodeName, + } + + dnsNames = allHostnames[nodeName] + // ips = allIPs[nodeName] + + switch serviceName { + default: + // The default case provides a cert with all the dns names for the host. + // This will probably be sufficient for most services. If a service needs + // a different kind of cert (for example, containing ips, or using a different + // issuer) then add a case for the service in this switch statement + + secretName = "cert-" + nodeName + certSecret, _, err = secret.GetSecret(ctx, helper, secretName, instance.Namespace) + if err != nil { + if !k8serrors.IsNotFound(err) { + err = fmt.Errorf("Error retrieving secret %s - %w", secretName, err) + return ctrl.Result{}, err + } + + certName = secretName + duration := ptr.To(time.Hour * 24 * 365) + certSecret, result, err = certmanager.EnsureCert(ctx, helper, certmanager.RootCAIssuerInternalLabel, + certName, duration, dnsNames, nil, labels) + if err != nil { + return ctrl.Result{}, err + } else if (result != ctrl.Result{}) { + return result, nil + } + } + } + + // TODO(alee) Add an owner reference to the secret so it can be monitored + // We'll do this once stuggi adds a function to do this in libcommon + + // To use this cert, add it to the relevant service data + // TODO(alee) We only need the cert and key. The cacert will come from another label + for key, value := range certSecret.Data { + certsData[nodeName+"-"+key] = value + } + } + + // create a secret to hold the certs for the service + serviceCertsSecret := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: GetServiceCertsSecretName(instance, serviceName), + Namespace: instance.Namespace, + }, + Data: certsData, + } + _, result, err := secret.CreateOrPatchSecret(ctx, helper, instance, serviceCertsSecret) + if err != nil { + err = fmt.Errorf("Error creating certs secret for %s - %w", serviceName, err) + return ctrl.Result{}, err + } else if result != controllerutil.OperationResultNone { + return ctrl.Result{RequeueAfter: time.Second * 5}, nil + } + + return ctrl.Result{}, nil +} + +// GetServiceCertsSecretName - return name of secret to be mounted in ansibleEE which contains +// all the TLS certs for the relevant service +// The convention we use here is "--certs", so for example, +// openstack-epdm-nova-certs. +func GetServiceCertsSecretName(instance *dataplanev1.OpenStackDataPlaneNodeSet, serviceName string) string { + return fmt.Sprintf("%s-%s-certs", instance.Name, serviceName) +} diff --git a/pkg/deployment/const.go b/pkg/deployment/const.go index 2e19cc96a..eb79b5a78 100644 --- a/pkg/deployment/const.go +++ b/pkg/deployment/const.go @@ -47,4 +47,7 @@ const ( // ConfigPaths base path for volume mounts in OpenStackAnsibleEE pod ConfigPaths = "/var/lib/openstack/configs" + + // CertPaths base path for cert volume mount in OpenStackAnsibleEE pod + CertPaths = "/var/lib/openstack/certs" ) diff --git a/pkg/deployment/deployment.go b/pkg/deployment/deployment.go index 1252edd6b..7bf1a4b6f 100644 --- a/pkg/deployment/deployment.go +++ b/pkg/deployment/deployment.go @@ -81,7 +81,7 @@ func Deploy( // specific mounts. aeeSpec.ExtraMounts = make([]storage.VolMounts, len(aeeSpecMounts)) copy(aeeSpec.ExtraMounts, aeeSpecMounts) - aeeSpec, err = addServiceExtraMounts(ctx, helper, aeeSpec, foundService) + aeeSpec, err = addServiceExtraMounts(ctx, helper, aeeSpec, foundService, nodeSet) if err != nil { return &ctrl.Result{}, err @@ -225,6 +225,7 @@ func addServiceExtraMounts( helper *helper.Helper, aeeSpec dataplanev1.AnsibleEESpec, service dataplanev1.OpenStackDataPlaneService, + nodeSet *dataplanev1.OpenStackDataPlaneNodeSet, ) (dataplanev1.AnsibleEESpec, error) { client := helper.GetClient() baseMountPath := path.Join(ConfigPaths, service.Name) @@ -322,5 +323,34 @@ func addServiceExtraMounts( aeeSpec.ExtraMounts = append(aeeSpec.ExtraMounts, volMounts) } + + // Add mount for TLS certs + if service.Spec.HasTLSCerts != nil && *service.Spec.HasTLSCerts { + volMounts := storage.VolMounts{} + secretName := GetServiceCertsSecretName(nodeSet, service.Name) + sec := &corev1.Secret{} + err := client.Get(ctx, types.NamespacedName{Name: secretName, Namespace: service.Namespace}, sec) + if err != nil { + return aeeSpec, err + } + volume := corev1.Volume{ + Name: secretName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: secretName, + }, + }, + } + + volumeMount := corev1.VolumeMount{ + Name: secretName, + MountPath: path.Join(CertPaths, service.Name), + } + + volMounts.Volumes = append(volMounts.Volumes, volume) + volMounts.Mounts = append(volMounts.Mounts, volumeMount) + aeeSpec.ExtraMounts = append(aeeSpec.ExtraMounts, volMounts) + + } return aeeSpec, nil } diff --git a/pkg/deployment/ipam.go b/pkg/deployment/ipam.go index 1b34f4472..31d706e4f 100644 --- a/pkg/deployment/ipam.go +++ b/pkg/deployment/ipam.go @@ -67,10 +67,14 @@ func EnsureIPSets(ctx context.Context, helper *helper.Helper, // createOrPatchDNSData builds the DNSData func createOrPatchDNSData(ctx context.Context, helper *helper.Helper, instance *dataplanev1.OpenStackDataPlaneNodeSet, - allIPSets map[string]infranetworkv1.IPSet) (string, error) { + allIPSets map[string]infranetworkv1.IPSet) ( + string, map[string][]string, map[string][]string, error) { var allDNSRecords []infranetworkv1.DNSHost var ctlplaneSearchDomain string + allHostnames := map[string][]string{} + allIPs := map[string][]string{} + // Build DNSData CR for nodeName, node := range instance.Spec.Nodes { var shortName string @@ -101,6 +105,8 @@ func createOrPatchDNSData(ctx context.Context, helper *helper.Helper, if isFQDN(hostName) && res.Network == CtlPlaneNetwork { fqdnNames = append(fqdnNames, hostName) } + allHostnames[nodeName] = append(allHostnames[nodeName], fqdnNames...) + allIPs[nodeName] = append(allIPs[nodeName], res.Address) dnsRecord.Hostnames = fqdnNames allDNSRecords = append(allDNSRecords, dnsRecord) // Adding only ctlplane domain for ansibleee. @@ -130,16 +136,17 @@ func createOrPatchDNSData(ctx context.Context, helper *helper.Helper, return err }) if err != nil { - return "", err + return "", allHostnames, allIPs, err } - return ctlplaneSearchDomain, nil + return ctlplaneSearchDomain, allHostnames, allIPs, nil } // EnsureDNSData Ensures DNSData is created func EnsureDNSData(ctx context.Context, helper *helper.Helper, instance *dataplanev1.OpenStackDataPlaneNodeSet, - allIPSets map[string]infranetworkv1.IPSet) ([]string, []string, string, bool, error) { + allIPSets map[string]infranetworkv1.IPSet) ( + []string, []string, string, bool, map[string][]string, map[string][]string, error) { // Verify dnsmasq CR exists dnsAddresses, dnsClusterAddresses, isReady, err := CheckDNSService( @@ -161,17 +168,17 @@ func EnsureDNSData(ctx context.Context, helper *helper.Helper, if dnsAddresses == nil { instance.Status.Conditions.Remove(dataplanev1.NodeSetDNSDataReadyCondition) } - return nil, nil, "", isReady, err + return nil, nil, "", isReady, nil, nil, err } // Create or Patch DNSData - ctlplaneSearchDomain, err := createOrPatchDNSData( + ctlplaneSearchDomain, allHostnames, allIPs, err := createOrPatchDNSData( ctx, helper, instance, allIPSets) if err != nil { instance.Status.Conditions.MarkFalse( dataplanev1.NodeSetDNSDataReadyCondition, condition.ErrorReason, condition.SeverityError, dataplanev1.NodeSetDNSDataReadyErrorMessage) - return nil, nil, "", false, err + return nil, nil, "", false, nil, nil, err } dnsData := &infranetworkv1.DNSData{ @@ -187,7 +194,7 @@ func EnsureDNSData(ctx context.Context, helper *helper.Helper, dataplanev1.NodeSetDNSDataReadyCondition, condition.ErrorReason, condition.SeverityError, dataplanev1.NodeSetDNSDataReadyErrorMessage) - return nil, nil, "", false, err + return nil, nil, "", false, nil, nil, err } if !dnsData.IsReady() { @@ -196,12 +203,12 @@ func EnsureDNSData(ctx context.Context, helper *helper.Helper, dataplanev1.NodeSetDNSDataReadyCondition, condition.RequestedReason, condition.SeverityInfo, dataplanev1.NodeSetDNSDataReadyWaitingMessage) - return nil, nil, "", false, nil + return nil, nil, "", false, nil, nil, nil } instance.Status.Conditions.MarkTrue( dataplanev1.NodeSetDNSDataReadyCondition, dataplanev1.NodeSetDNSDataReadyMessage) - return dnsAddresses, dnsClusterAddresses, ctlplaneSearchDomain, true, nil + return dnsAddresses, dnsClusterAddresses, ctlplaneSearchDomain, true, allHostnames, allIPs, nil } // reserveIPs Reserves IPs by creating IPSets