diff --git a/controllers/openstackdataplanenodeset_controller.go b/controllers/openstackdataplanenodeset_controller.go index d1326ec45..628577136 100644 --- a/controllers/openstackdataplanenodeset_controller.go +++ b/controllers/openstackdataplanenodeset_controller.go @@ -236,18 +236,16 @@ func (r *OpenStackDataPlaneNodeSetReconciler) Reconcile(ctx context.Context, req } // Ensure DNSData Required for Nodes - dnsData := deployment.DataplaneDNSData{} - err = dnsData.EnsureDNSData( + dnsDetails, err := deployment.EnsureDNSData( ctx, helper, instance, allIPSets) - if err != nil || !dnsData.Ready { + if err != nil || !dnsDetails.IsReady { return ctrl.Result{}, err } - - instance.Status.DNSClusterAddresses = dnsData.ClusterAddresses - instance.Status.CtlplaneSearchDomain = dnsData.CtlplaneSearchDomain - instance.Status.AllHostnames = dnsData.Hostnames - instance.Status.AllIPs = dnsData.AllIPs + instance.Status.DNSClusterAddresses = dnsDetails.ClusterAddresses + instance.Status.CtlplaneSearchDomain = dnsDetails.CtlplaneSearchDomain + instance.Status.AllHostnames = dnsDetails.Hostnames + instance.Status.AllIPs = dnsDetails.AllIPs ansibleSSHPrivateKeySecret := instance.Spec.NodeTemplate.AnsibleSSHPrivateKeySecret @@ -363,7 +361,7 @@ func (r *OpenStackDataPlaneNodeSetReconciler) Reconcile(ctx context.Context, req instance.Status.Conditions.MarkUnknown(dataplanev1.NodeSetBareMetalProvisionReadyCondition, condition.InitReason, condition.InitReason) isReady, err := deployment.DeployBaremetalSet(ctx, helper, instance, - allIPSets, dnsData.ServerAddresses) + allIPSets, dnsDetails.ServerAddresses) if err != nil || !isReady { return ctrl.Result{}, err } @@ -383,7 +381,7 @@ func (r *OpenStackDataPlaneNodeSetReconciler) Reconcile(ctx context.Context, req } containerImages := dataplaneutil.GetContainerImages(version) _, err = deployment.GenerateNodeSetInventory(ctx, helper, instance, - allIPSets, dnsData.ServerAddresses, containerImages) + allIPSets, dnsDetails.ServerAddresses, containerImages) if err != nil { errorMsg := fmt.Sprintf("Unable to generate inventory for %s", instance.Name) util.LogErrorForObject(helper, err, errorMsg, instance) diff --git a/kuttl-test.yaml b/kuttl-test.yaml index 87b357194..f7b060df4 100644 --- a/kuttl-test.yaml +++ b/kuttl-test.yaml @@ -18,6 +18,7 @@ apiVersion: kuttl.dev/v1beta1 kind: TestSuite commands: - command: oc apply -n openstack -f https://raw.githubusercontent.com/openstack-k8s-operators/infra-operator/main/config/samples/network_v1beta1_netconfig.yaml + - command: oc apply -n openstack -f https://raw.githubusercontent.com/openstack-k8s-operators/infra-operator/main/config/samples/network_v1beta1_dnsmasq.yaml reportFormat: JSON reportName: kuttl-test-dataplane namespace: openstack diff --git a/pkg/deployment/ipam.go b/pkg/deployment/ipam.go index c2bb97f16..e5c4d9621 100644 --- a/pkg/deployment/ipam.go +++ b/pkg/deployment/ipam.go @@ -18,6 +18,7 @@ package deployment import ( "context" + "fmt" "strings" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -31,65 +32,57 @@ import ( "github.com/openstack-k8s-operators/lib-common/modules/common/util" ) -// EnsureIPSets Creates the IPSets -func EnsureIPSets(ctx context.Context, helper *helper.Helper, - instance *dataplanev1.OpenStackDataPlaneNodeSet, -) (map[string]infranetworkv1.IPSet, bool, error) { - allIPSets, err := reserveIPs(ctx, helper, instance) - if err != nil { - instance.Status.Conditions.MarkFalse( - dataplanev1.NodeSetIPReservationReadyCondition, - condition.ErrorReason, condition.SeverityError, - dataplanev1.NodeSetIPReservationReadyErrorMessage) - return nil, false, err - } - - if len(allIPSets) == 0 { - return nil, true, nil - } - - for _, s := range allIPSets { - if s.Status.Conditions.IsFalse(condition.ReadyCondition) { - instance.Status.Conditions.MarkFalse( - dataplanev1.NodeSetIPReservationReadyCondition, - condition.RequestedReason, condition.SeverityInfo, - dataplanev1.NodeSetIPReservationReadyWaitingMessage) - return nil, false, nil - } - } - instance.Status.Conditions.MarkTrue( - dataplanev1.NodeSetIPReservationReadyCondition, - dataplanev1.NodeSetIPReservationReadyMessage) - return allIPSets, true, nil -} - -// DataplaneDNSData holds information relevant to the OpenStack DNS configuration of the cluster. -type DataplaneDNSData struct { - // Err holds any errors returned from the Kubernetes API while retrieving data. - Err error - // AllIPs holds a map of all IP addresses per hostname. - AllIPs map[string]map[infranetworkv1.NetNameStr]string - // Hostnames is a map of hostnames provided by the NodeSet to the FQDNs - Hostnames map[string]map[infranetworkv1.NetNameStr]string - // CtlplaneSearchDomain is the search domain provided by IPAM - CtlplaneSearchDomain string +// DNSDetails struct for IPAM and DNS details of NodeSet +type DNSDetails struct { + // IsReady has DNSData been reconciled + IsReady bool // ServerAddresses holds a slice of DNS servers in the environment ServerAddresses []string // ClusterAddresses holds a slice of Kubernetes service ClusterIPs for the DNSMasq services ClusterAddresses []string - // Ready indicates the ready status of the DNS service - Ready bool + // CtlplaneSearchDomain is the search domain provided by IPAM + CtlplaneSearchDomain string + // Hostnames is a map of hostnames provided by the NodeSet to the FQDNs + Hostnames map[string]map[infranetworkv1.NetNameStr]string + // AllIPs holds a map of all IP addresses per hostname. + AllIPs map[string]map[infranetworkv1.NetNameStr]string +} + +// checkDNSService checks if DNS is configured and ready +func checkDNSService(ctx context.Context, helper *helper.Helper, + instance client.Object, dnsDetails *DNSDetails, +) error { + dnsmasqList := &infranetworkv1.DNSMasqList{} + listOpts := []client.ListOption{ + client.InNamespace(instance.GetNamespace()), + } + err := helper.GetClient().List(ctx, dnsmasqList, listOpts...) + if err != nil { + util.LogErrorForObject(helper, err, "Error listing dnsmasqs", instance) + return err + } + if len(dnsmasqList.Items) == 0 { + util.LogForObject(helper, "No DNS control plane service exists yet", instance) + return nil + } + if !dnsmasqList.Items[0].IsReady() { + util.LogForObject(helper, "DNS control plane service exists, but not ready yet ", instance) + return nil + } + dnsDetails.ClusterAddresses = dnsmasqList.Items[0].Status.DNSClusterAddresses + dnsDetails.ServerAddresses = dnsmasqList.Items[0].Status.DNSAddresses + return nil } // createOrPatchDNSData builds the DNSData -func (dns *DataplaneDNSData) createOrPatchDNSData(ctx context.Context, helper *helper.Helper, +func createOrPatchDNSData(ctx context.Context, helper *helper.Helper, instance *dataplanev1.OpenStackDataPlaneNodeSet, - allIPSets map[string]infranetworkv1.IPSet, + allIPSets map[string]infranetworkv1.IPSet, dnsDetails *DNSDetails, ) error { var allDNSRecords []infranetworkv1.DNSHost var ctlplaneSearchDomain string - dns.Hostnames = map[string]map[infranetworkv1.NetNameStr]string{} - dns.AllIPs = map[string]map[infranetworkv1.NetNameStr]string{} + dnsDetails.Hostnames = map[string]map[infranetworkv1.NetNameStr]string{} + dnsDetails.AllIPs = map[string]map[infranetworkv1.NetNameStr]string{} // Build DNSData CR for _, node := range instance.Spec.Nodes { @@ -97,8 +90,8 @@ func (dns *DataplaneDNSData) createOrPatchDNSData(ctx context.Context, helper *h nets := node.Networks hostName := node.HostName - dns.Hostnames[hostName] = map[infranetworkv1.NetNameStr]string{} - dns.AllIPs[hostName] = map[infranetworkv1.NetNameStr]string{} + dnsDetails.Hostnames[hostName] = map[infranetworkv1.NetNameStr]string{} + dnsDetails.AllIPs[hostName] = map[infranetworkv1.NetNameStr]string{} shortName = strings.Split(hostName, ".")[0] if len(nets) == 0 { @@ -116,25 +109,24 @@ func (dns *DataplaneDNSData) createOrPatchDNSData(ctx context.Context, helper *h fqdnName := strings.Join([]string{shortName, res.DNSDomain}, ".") if fqdnName != hostName { fqdnNames = append(fqdnNames, fqdnName) - dns.Hostnames[hostName][infranetworkv1.NetNameStr(netLower)] = fqdnName + dnsDetails.Hostnames[hostName][infranetworkv1.NetNameStr(netLower)] = fqdnName } if dataplanev1.NodeHostNameIsFQDN(hostName) && netLower == CtlPlaneNetwork { fqdnNames = append(fqdnNames, hostName) - dns.Hostnames[hostName][infranetworkv1.NetNameStr(netLower)] = hostName + dnsDetails.Hostnames[hostName][infranetworkv1.NetNameStr(netLower)] = hostName } - dns.AllIPs[hostName][infranetworkv1.NetNameStr(netLower)] = res.Address + dnsDetails.AllIPs[hostName][infranetworkv1.NetNameStr(netLower)] = res.Address dnsRecord.Hostnames = fqdnNames allDNSRecords = append(allDNSRecords, dnsRecord) // Adding only ctlplane domain for ansibleee. // TODO (rabi) This is not very efficient. if netLower == CtlPlaneNetwork && ctlplaneSearchDomain == "" { - dns.CtlplaneSearchDomain = res.DNSDomain + dnsDetails.CtlplaneSearchDomain = res.DNSDomain } } } } } - util.LogForObject(helper, "Reconciling DNSData", instance) dnsData := &infranetworkv1.DNSData{ ObjectMeta: metav1.ObjectMeta{ Namespace: instance.Namespace, @@ -158,41 +150,39 @@ func (dns *DataplaneDNSData) createOrPatchDNSData(ctx context.Context, helper *h } // EnsureDNSData Ensures DNSData is created -func (dns *DataplaneDNSData) EnsureDNSData(ctx context.Context, helper *helper.Helper, +func EnsureDNSData(ctx context.Context, helper *helper.Helper, instance *dataplanev1.OpenStackDataPlaneNodeSet, allIPSets map[string]infranetworkv1.IPSet, -) error { +) (dnsDetails *DNSDetails, err error) { + dnsDetails = &DNSDetails{} // Verify dnsmasq CR exists - err := dns.CheckDNSService( - ctx, helper, instance) + err = checkDNSService( + ctx, helper, instance, dnsDetails) - if err != nil || !dns.Ready || dns.ClusterAddresses == nil { - if err != nil { - instance.Status.Conditions.MarkFalse( - dataplanev1.NodeSetDNSDataReadyCondition, - condition.ErrorReason, condition.SeverityError, - dataplanev1.NodeSetDNSDataReadyErrorMessage) - } - if !dns.Ready { - instance.Status.Conditions.MarkFalse( - dataplanev1.NodeSetDNSDataReadyCondition, - condition.RequestedReason, condition.SeverityInfo, - dataplanev1.NodeSetDNSDataReadyWaitingMessage) - } - if dns.ClusterAddresses == nil { - instance.Status.Conditions.Remove(dataplanev1.NodeSetDNSDataReadyCondition) - } - return err + if err != nil { + instance.Status.Conditions.MarkFalse( + dataplanev1.NodeSetDNSDataReadyCondition, + condition.ErrorReason, condition.SeverityError, + dataplanev1.NodeSetDNSDataReadyErrorMessage) + return dnsDetails, err } + if dnsDetails.ClusterAddresses == nil { + instance.Status.Conditions.MarkFalse( + dataplanev1.NodeSetDNSDataReadyCondition, + condition.RequestedReason, condition.SeverityInfo, + dataplanev1.NodeSetDNSDataReadyWaitingMessage) + return dnsDetails, nil + } + // Create or Patch DNSData - err = dns.createOrPatchDNSData( - ctx, helper, instance, allIPSets) + err = createOrPatchDNSData( + ctx, helper, instance, allIPSets, dnsDetails) if err != nil { instance.Status.Conditions.MarkFalse( dataplanev1.NodeSetDNSDataReadyCondition, condition.ErrorReason, condition.SeverityError, dataplanev1.NodeSetDNSDataReadyErrorMessage) - return err + return dnsDetails, err } dnsData := &infranetworkv1.DNSData{ @@ -208,24 +198,50 @@ func (dns *DataplaneDNSData) EnsureDNSData(ctx context.Context, helper *helper.H dataplanev1.NodeSetDNSDataReadyCondition, condition.ErrorReason, condition.SeverityError, dataplanev1.NodeSetDNSDataReadyErrorMessage) - return err + return dnsDetails, err } - if !dnsData.IsReady() { util.LogForObject(helper, "DNSData not ready yet waiting", instance) instance.Status.Conditions.MarkFalse( dataplanev1.NodeSetDNSDataReadyCondition, condition.RequestedReason, condition.SeverityInfo, dataplanev1.NodeSetDNSDataReadyWaitingMessage) - dns.Ready = false - return nil + return dnsDetails, nil } + instance.Status.Conditions.MarkTrue( dataplanev1.NodeSetDNSDataReadyCondition, dataplanev1.NodeSetDNSDataReadyMessage) - dns.Ready = true + dnsDetails.IsReady = true + return dnsDetails, nil +} - return nil +// EnsureIPSets Creates the IPSets +func EnsureIPSets(ctx context.Context, helper *helper.Helper, + instance *dataplanev1.OpenStackDataPlaneNodeSet, +) (map[string]infranetworkv1.IPSet, bool, error) { + allIPSets, err := reserveIPs(ctx, helper, instance) + if err != nil { + instance.Status.Conditions.MarkFalse( + dataplanev1.NodeSetIPReservationReadyCondition, + condition.ErrorReason, condition.SeverityError, + dataplanev1.NodeSetIPReservationReadyErrorMessage) + return nil, false, err + } + + for _, s := range allIPSets { + if s.Status.Conditions.IsFalse(condition.ReadyCondition) { + instance.Status.Conditions.MarkFalse( + dataplanev1.NodeSetIPReservationReadyCondition, + condition.RequestedReason, condition.SeverityInfo, + dataplanev1.NodeSetIPReservationReadyWaitingMessage) + return nil, false, nil + } + } + instance.Status.Conditions.MarkTrue( + dataplanev1.NodeSetIPReservationReadyCondition, + dataplanev1.NodeSetIPReservationReadyMessage) + return allIPSets, true, nil } // reserveIPs Reserves IPs by creating IPSets @@ -242,15 +258,14 @@ func reserveIPs(ctx context.Context, helper *helper.Helper, return nil, err } if len(netConfigList.Items) == 0 { - util.LogForObject(helper, "No NetConfig CR exists yet, IPAM won't be used", instance) - instance.Status.Conditions.Remove(dataplanev1.NodeSetIPReservationReadyCondition) - return nil, nil + errMsg := "No NetConfig CR exists yet" + util.LogForObject(helper, errMsg, instance) + return nil, fmt.Errorf(errMsg) } - ipamUsed := false allIPSets := make(map[string]infranetworkv1.IPSet) // CreateOrPatch IPSets - for _, node := range instance.Spec.Nodes { + for nodeName, node := range instance.Spec.Nodes { nets := node.Networks hostName := node.HostName if len(nets) == 0 { @@ -258,8 +273,6 @@ func reserveIPs(ctx context.Context, helper *helper.Helper, } if len(nets) > 0 { - ipamUsed = true - util.LogForObject(helper, "Reconciling IPSet", instance) ipSet := &infranetworkv1.IPSet{ ObjectMeta: metav1.ObjectMeta{ Namespace: instance.Namespace, @@ -277,40 +290,12 @@ func reserveIPs(ctx context.Context, helper *helper.Helper, return nil, err } allIPSets[hostName] = *ipSet + } else { + msg := fmt.Sprintf("No Networks defined for node %s or template", nodeName) + util.LogForObject(helper, msg, instance) + return nil, fmt.Errorf(msg) } } - if !ipamUsed { - util.LogForObject(helper, "No Networks defined for nodes, IPAM won't be used", instance) - instance.Status.Conditions.Remove(dataplanev1.NodeSetIPReservationReadyCondition) - } return allIPSets, nil } - -// CheckDNSService checks if DNS is configured and ready -func (dns *DataplaneDNSData) CheckDNSService(ctx context.Context, helper *helper.Helper, - instance client.Object, -) error { - dnsmasqList := &infranetworkv1.DNSMasqList{} - listOpts := []client.ListOption{ - client.InNamespace(instance.GetNamespace()), - } - err := helper.GetClient().List(ctx, dnsmasqList, listOpts...) - if err != nil { - dns.Ready = false - return err - } - if len(dnsmasqList.Items) == 0 { - util.LogForObject(helper, "No DNSMasq CR exists yet, DNS Service won't be used", instance) - dns.Ready = true - return nil - } else if !dnsmasqList.Items[0].IsReady() { - util.LogForObject(helper, "DNSMasq service exists, but not ready yet ", instance) - dns.Ready = false - return nil - } - dns.ClusterAddresses = dnsmasqList.Items[0].Status.DNSClusterAddresses - dns.ServerAddresses = dnsmasqList.Items[0].Status.DNSAddresses - dns.Ready = true - return nil -} diff --git a/tests/functional/base_test.go b/tests/functional/base_test.go index 82d2421d4..9bb9d6440 100644 --- a/tests/functional/base_test.go +++ b/tests/functional/base_test.go @@ -63,12 +63,15 @@ func CustomServiceImageSpec() map[string]interface{} { return map[string]interface{}{ "preProvisioned": true, "nodeTemplate": map[string]interface{}{ + "networks": []infrav1.IPSetNetwork{ + {Name: "ctlplane", SubnetName: "subnet1"}, + }, "ansibleSSHPrivateKeySecret": "dataplane-ansible-ssh-private-key-secret", "ansible": map[string]interface{}{ "ansibleVars": ansibleServiceVars, }, }, - "nodes": map[string]interface{}{}, + "nodes": map[string]dataplanev1.NodeSection{"edpm-compute-node-1": {}}, } } @@ -77,6 +80,11 @@ func CreateNetConfig(name types.NamespacedName, spec map[string]interface{}) *un return th.CreateUnstructured(raw) } +func CreateDNSMasq(name types.NamespacedName, spec map[string]interface{}) *unstructured.Unstructured { + raw := DefaultDNSMasq(name, spec) + return th.CreateUnstructured(raw) +} + // Create SSHSecret func CreateSSHSecret(name types.NamespacedName) *corev1.Secret { return th.CreateSecret( @@ -106,12 +114,9 @@ func DefaultDataPlaneNodeSetSpec(nodeSetName string) map[string]interface{} { }, "nodes": map[string]interface{}{ fmt.Sprintf("%s-node-1", nodeSetName): map[string]interface{}{ - "hostname": "edpm-bm-compute-1", - "networks": []map[string]interface{}{{ - "name": "CtlPlane", - "fixedIP": "172.20.12.76", - "subnetName": "ctlplane_subnet", - }, + "hostName": "edpm-compute-node-1", + "networks": []infrav1.IPSetNetwork{ + {Name: "ctlplane", SubnetName: "subnet1"}, }, }, }, @@ -132,6 +137,9 @@ func DefaultDataPlaneNoNodeSetSpec(tlsEnabled bool) map[string]interface{} { spec := map[string]interface{}{ "preProvisioned": true, "nodeTemplate": map[string]interface{}{ + "networks": []infrav1.IPSetNetwork{ + {Name: "ctlplane", SubnetName: "subnet1"}, + }, "ansibleSSHPrivateKeySecret": "dataplane-ansible-ssh-private-key-secret", }, "nodes": map[string]interface{}{}, @@ -140,6 +148,7 @@ func DefaultDataPlaneNoNodeSetSpec(tlsEnabled bool) map[string]interface{} { if tlsEnabled { spec["tlsEnabled"] = true } + spec["nodes"] = map[string]dataplanev1.NodeSection{"edpm-compute-node-1": {}} return spec } @@ -166,7 +175,7 @@ func DefaultNetConfigSpec() map[string]interface{} { "start": "172.20.12.0", }, }, - "name": "ctlplane_subnet", + "name": "subnet1", "cidr": "172.20.12.0/16", "gateway": "172.20.12.1", }, @@ -176,6 +185,39 @@ func DefaultNetConfigSpec() map[string]interface{} { } } +func DefaultDNSMasqSpec() map[string]interface{} { + return map[string]interface{}{ + "replicas": 1, + } +} + +func SimulateDNSMasqComplete(name types.NamespacedName) { + Eventually(func(g Gomega) { + dnsMasq := &infrav1.DNSMasq{} + g.Expect(th.K8sClient.Get(th.Ctx, name, dnsMasq)).Should(Succeed()) + dnsMasq.Status.Conditions.MarkTrue(condition.ReadyCondition, condition.ReadyMessage) + dnsMasq.Status.DNSClusterAddresses = []string{"192.168.122.80"} + dnsMasq.Status.DNSAddresses = []string{"192.168.122.80"} + g.Expect(th.K8sClient.Status().Update(th.Ctx, dnsMasq)).To(Succeed()) + }, th.Timeout, th.Interval).Should(Succeed()) + th.Logger.Info("Simulated DNS creation completed", "on", name) +} + +// SimulateIPSetComplete - Simulates the result of the IPSet status +func SimulateDNSDataComplete(name types.NamespacedName) { + Eventually(func(g Gomega) { + dnsData := &infrav1.DNSData{} + + g.Expect(th.K8sClient.Get(th.Ctx, name, dnsData)).Should(Succeed()) + dnsData.Status.Conditions.MarkTrue(condition.ReadyCondition, condition.ReadyMessage) + // This can return conflict so we have the gomega.Eventually block to retry + g.Expect(th.K8sClient.Status().Update(th.Ctx, dnsData)).To(Succeed()) + + }, th.Timeout, th.Interval).Should(Succeed()) + + th.Logger.Info("Simulated dnsData creation completed", "on", name) +} + // SimulateIPSetComplete - Simulates the result of the IPSet status func SimulateIPSetComplete(name types.NamespacedName) { Eventually(func(g Gomega) { @@ -197,7 +239,7 @@ func SimulateIPSetComplete(name types.NamespacedName) { }, th.Timeout, th.Interval).Should(Succeed()) - th.Logger.Info("Simulated DB completed", "on", name) + th.Logger.Info("Simulated IPSet creation completed", "on", name) } // Build OpenStackDataPlaneNodeSet struct and fill it with preset values @@ -241,6 +283,18 @@ func DefaultNetConfig(name types.NamespacedName, spec map[string]interface{}) ma } } +func DefaultDNSMasq(name types.NamespacedName, spec map[string]interface{}) map[string]interface{} { + return map[string]interface{}{ + "apiVersion": "network.openstack.org/v1beta1", + "kind": "DNSMasq", + "metadata": map[string]interface{}{ + "name": name.Name, + "namespace": name.Namespace, + }, + "spec": spec, + } +} + // Create an empty OpenStackDataPlaneService struct // containing only given NamespacedName as metadata func DefaultDataplaneService(name types.NamespacedName) map[string]interface{} { diff --git a/tests/functional/openstackdataplanedeployment_controller_test.go b/tests/functional/openstackdataplanedeployment_controller_test.go index f73cce000..ecb27dcc4 100644 --- a/tests/functional/openstackdataplanedeployment_controller_test.go +++ b/tests/functional/openstackdataplanedeployment_controller_test.go @@ -30,11 +30,17 @@ var _ = Describe("Dataplane Deployment Test", func() { var novaMigrationSSHKey types.NamespacedName var ceilometerConfigSecretName types.NamespacedName var dataplaneNetConfigName types.NamespacedName + var dnsMasqName types.NamespacedName + var dataplaneNodeName types.NamespacedName var dataplaneMultiNodesetDeploymentName types.NamespacedName var dataplaneServiceName types.NamespacedName var dataplaneGlobalServiceName types.NamespacedName BeforeEach(func() { + dnsMasqName = types.NamespacedName{ + Name: "dnsmasq", + Namespace: namespace, + } dataplaneDeploymentName = types.NamespacedName{ Name: "edpm-deployment", Namespace: namespace, @@ -43,6 +49,10 @@ var _ = Describe("Dataplane Deployment Test", func() { Name: "edpm-compute-nodeset", Namespace: namespace, } + dataplaneNodeName = types.NamespacedName{ + Namespace: namespace, + Name: "edpm-compute-node-1", + } dataplaneSSHSecretName = types.NamespacedName{ Namespace: namespace, Name: "dataplane-ansible-ssh-private-key-secret", @@ -113,7 +123,11 @@ var _ = Describe("Dataplane Deployment Test", func() { DeferCleanup(th.DeleteService, dataplaneServiceName) DeferCleanup(th.DeleteService, dataplaneGlobalServiceName) DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) + SimulateDNSMasqComplete(dnsMasqName) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, DefaultDataPlaneNodeSetSpec(dataplaneNodeSetName.Name))) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) DeferCleanup(th.DeleteInstance, CreateDataplaneDeployment(dataplaneDeploymentName, DefaultDataPlaneDeploymentSpec())) }) @@ -250,9 +264,11 @@ var _ = Describe("Dataplane Deployment Test", func() { DeferCleanup(th.DeleteService, dataplaneGlobalServiceName) DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) - + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) + SimulateDNSMasqComplete(dnsMasqName) // Create both nodesets + betaNodeName := fmt.Sprintf("%s-node-1", betaNodeSetName.Name) betaNodeSetSpec := map[string]interface{}{ "preProvisioned": false, "services": []string{ @@ -265,12 +281,11 @@ var _ = Describe("Dataplane Deployment Test", func() { }, }, "nodes": map[string]interface{}{ - fmt.Sprintf("%s-node-1", betaNodeSetName.Name): map[string]interface{}{ - "hostname": "edpm-bm-compute-2", + betaNodeName: map[string]interface{}{ + "hostname": betaNodeName, "networks": []map[string]interface{}{{ "name": "CtlPlane", - "fixedIP": "172.20.12.77", - "subnetName": "ctlplane_subnet", + "subnetName": "subnet1", }, }, }, @@ -286,6 +301,10 @@ var _ = Describe("Dataplane Deployment Test", func() { } DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(alphaNodeSetName, DefaultDataPlaneNodeSetSpec(alphaNodeSetName.Name))) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(betaNodeSetName, betaNodeSetSpec)) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(alphaNodeSetName) + SimulateIPSetComplete(types.NamespacedName{Name: betaNodeName, Namespace: namespace}) + SimulateDNSDataComplete(betaNodeSetName) deploymentSpec := map[string]interface{}{ "nodeSets": []string{ @@ -476,9 +495,13 @@ var _ = Describe("Dataplane Deployment Test", func() { DeferCleanup(th.DeleteService, dataplaneServiceName) DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) + SimulateDNSMasqComplete(dnsMasqName) // Create only one nodeset DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(alphaNodeSetName, DefaultDataPlaneNodeSetSpec(alphaNodeSetName.Name))) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(alphaNodeSetName) deploymentSpec := map[string]interface{}{ "nodeSets": []string{ @@ -598,8 +621,12 @@ var _ = Describe("Dataplane Deployment Test", func() { // DefaultDataPlanenodeSetSpec comes with two mock services, one marked for deployment on all nodesets // But we will not create them to test this scenario DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) + SimulateDNSMasqComplete(dnsMasqName) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, DefaultDataPlaneNodeSetSpec(dataplaneNodeSetName.Name))) DeferCleanup(th.DeleteInstance, CreateDataplaneDeployment(dataplaneDeploymentName, DefaultDataPlaneDeploymentSpec())) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should have Spec fields initialized", func() { diff --git a/tests/functional/openstackdataplanenodeset_controller_test.go b/tests/functional/openstackdataplanenodeset_controller_test.go index 73040f93c..9e6b57054 100644 --- a/tests/functional/openstackdataplanenodeset_controller_test.go +++ b/tests/functional/openstackdataplanenodeset_controller_test.go @@ -22,10 +22,12 @@ import ( . "github.com/onsi/ginkgo/v2" //revive:disable:dot-imports . "github.com/onsi/gomega" //revive:disable:dot-imports + "github.com/openstack-k8s-operators/dataplane-operator/api/v1beta1" dataplanev1 "github.com/openstack-k8s-operators/dataplane-operator/api/v1beta1" "github.com/openstack-k8s-operators/lib-common/modules/common/condition" //revive:disable-next-line:dot-imports + infrav1 "github.com/openstack-k8s-operators/infra-operator/apis/network/v1beta1" . "github.com/openstack-k8s-operators/lib-common/modules/common/test/helpers" baremetalv1 "github.com/openstack-k8s-operators/openstack-baremetal-operator/api/v1beta1" "gopkg.in/yaml.v3" @@ -58,7 +60,8 @@ var _ = Describe("Dataplane NodeSet Test", func() { var dataplaneSecretName types.NamespacedName var dataplaneSSHSecretName types.NamespacedName var dataplaneNetConfigName types.NamespacedName - var dataplaneIPSetName types.NamespacedName + var dnsMasqName types.NamespacedName + var dataplaneNodeName types.NamespacedName var dataplaneDeploymentName types.NamespacedName var dataplaneConfigHash string var dataplaneGlobalServiceName types.NamespacedName @@ -74,6 +77,10 @@ var _ = Describe("Dataplane NodeSet Test", func() { } BeforeEach(func() { + dnsMasqName = types.NamespacedName{ + Name: "dnsmasq", + Namespace: namespace, + } dataplaneNodeSetName = types.NamespacedName{ Name: "edpm-compute-nodeset", Namespace: namespace, @@ -90,7 +97,7 @@ var _ = Describe("Dataplane NodeSet Test", func() { Namespace: namespace, Name: "dataplane-netconfig", } - dataplaneIPSetName = types.NamespacedName{ + dataplaneNodeName = types.NamespacedName{ Namespace: namespace, Name: "edpm-compute-node-1", } @@ -105,12 +112,84 @@ var _ = Describe("Dataplane NodeSet Test", func() { err := os.Setenv("OPERATOR_SERVICES", "../../config/services") Expect(err).NotTo(HaveOccurred()) }) + When("A Dataplane nodeset is created and no netconfig", func() { + BeforeEach(func() { + DeferCleanup(th.DeleteInstance, + CreateDataplaneNodeSet(dataplaneNodeSetName, + DefaultDataPlaneNoNodeSetSpec(false))) + }) + It("should have ip reservation not ready and unknown Conditions initialized", func() { + th.ExpectCondition( + dataplaneNodeSetName, + ConditionGetterFunc(DataplaneConditionGetter), + condition.ReadyCondition, + corev1.ConditionFalse, + ) + th.ExpectCondition( + dataplaneNodeSetName, + ConditionGetterFunc(DataplaneConditionGetter), + condition.InputReadyCondition, + corev1.ConditionUnknown, + ) + th.ExpectCondition( + dataplaneNodeSetName, + ConditionGetterFunc(DataplaneConditionGetter), + dataplanev1.NodeSetIPReservationReadyCondition, + corev1.ConditionFalse, + ) + }) + }) + + When("A Dataplane nodeset is created and no dnsmasq", func() { + BeforeEach(func() { + DeferCleanup(th.DeleteInstance, + CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, + CreateDataplaneNodeSet(dataplaneNodeSetName, + DefaultDataPlaneNoNodeSetSpec(false))) + SimulateIPSetComplete(dataplaneNodeName) + }) + It("should have dnsdata not ready and unknown Conditions initialized", func() { + th.ExpectCondition( + dataplaneNodeSetName, + ConditionGetterFunc(DataplaneConditionGetter), + condition.ReadyCondition, + corev1.ConditionFalse, + ) + th.ExpectCondition( + dataplaneNodeSetName, + ConditionGetterFunc(DataplaneConditionGetter), + condition.InputReadyCondition, + corev1.ConditionUnknown, + ) + th.ExpectCondition( + dataplaneNodeSetName, + ConditionGetterFunc(DataplaneConditionGetter), + dataplanev1.NodeSetIPReservationReadyCondition, + corev1.ConditionTrue, + ) + th.ExpectCondition( + dataplaneNodeSetName, + ConditionGetterFunc(DataplaneConditionGetter), + dataplanev1.NodeSetDNSDataReadyCondition, + corev1.ConditionFalse, + ) + + }) + }) When("TLS is enabled", func() { tlsEnabled := true - When("A Dataplane resorce is created with PreProvisioned nodes, no deployment", func() { + When("A Dataplane resource is created with PreProvisioned nodes, no deployment", func() { BeforeEach(func() { - DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, DefaultDataPlaneNoNodeSetSpec(tlsEnabled))) + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) + SimulateDNSMasqComplete(dnsMasqName) + DeferCleanup(th.DeleteInstance, + CreateDataplaneNodeSet(dataplaneNodeSetName, + DefaultDataPlaneNoNodeSetSpec(tlsEnabled))) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("should have the Spec fields initialized", func() { dataplaneNodeSetInstance := GetDataplaneNodeSet(dataplaneNodeSetName) @@ -149,7 +228,6 @@ var _ = Describe("Dataplane NodeSet Test", func() { }, NodeTemplate: dataplanev1.NodeTemplate{ AnsibleSSHPrivateKeySecret: "dataplane-ansible-ssh-private-key-secret", - Networks: nil, ManagementNetwork: "ctlplane", Ansible: dataplanev1.AnsibleOpts{ AnsibleUser: "cloud-admin", @@ -160,13 +238,22 @@ var _ = Describe("Dataplane NodeSet Test", func() { ExtraMounts: nil, UserData: nil, NetworkData: nil, + Networks: []infrav1.IPSetNetwork{{ + Name: "ctlplane", + SubnetName: "subnet1", + }, + }, }, Env: nil, PreProvisioned: true, NetworkAttachments: nil, SecretMaxSize: 1048576, TLSEnabled: tlsEnabled, - Nodes: map[string]dataplanev1.NodeSection{}, + Nodes: map[string]dataplanev1.NodeSection{ + dataplaneNodeName.Name: { + HostName: dataplaneNodeName.Name, + }, + }, Services: []string{ "download-cache", "bootstrap", @@ -239,8 +326,13 @@ var _ = Describe("Dataplane NodeSet Test", func() { "global-service"} CreateDataplaneService(dataplaneGlobalServiceName, true) + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) + SimulateDNSMasqComplete(dnsMasqName) DeferCleanup(th.DeleteService, dataplaneGlobalServiceName) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, nodeSetSpec)) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("should have the Spec fields initialized", func() { dataplaneNodeSetInstance := GetDataplaneNodeSet(dataplaneNodeSetName) @@ -279,8 +371,12 @@ var _ = Describe("Dataplane NodeSet Test", func() { }, NodeTemplate: dataplanev1.NodeTemplate{ AnsibleSSHPrivateKeySecret: "dataplane-ansible-ssh-private-key-secret", - Networks: nil, - ManagementNetwork: "ctlplane", + Networks: []infrav1.IPSetNetwork{{ + Name: "ctlplane", + SubnetName: "subnet1", + }, + }, + ManagementNetwork: "ctlplane", Ansible: dataplanev1.AnsibleOpts{ AnsibleUser: "cloud-admin", AnsibleHost: "", @@ -296,7 +392,11 @@ var _ = Describe("Dataplane NodeSet Test", func() { NetworkAttachments: nil, SecretMaxSize: 1048576, TLSEnabled: tlsEnabled, - Nodes: map[string]dataplanev1.NodeSection{}, + Nodes: map[string]dataplanev1.NodeSection{ + dataplaneNodeName.Name: { + HostName: dataplaneNodeName.Name, + }, + }, Services: []string{ "download-cache", "bootstrap", @@ -358,7 +458,12 @@ var _ = Describe("Dataplane NodeSet Test", func() { spec := DefaultDataPlaneNoNodeSetSpec(tlsEnabled) spec["metadata"] = map[string]interface{}{"ansiblesshprivatekeysecret": ""} spec["preProvisioned"] = false + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, spec)) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("should have the Spec fields initialized", func() { dataplaneNodeSetInstance := GetDataplaneNodeSet(dataplaneNodeSetName) @@ -406,7 +511,12 @@ var _ = Describe("Dataplane NodeSet Test", func() { BeforeEach(func() { spec := DefaultDataPlaneNoNodeSetSpec(tlsEnabled) spec["metadata"] = map[string]interface{}{"ansiblesshprivatekeysecret": ""} + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, spec)) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("should have the Spec fields initialized", func() { dataplaneNodeSetInstance := GetDataplaneNodeSet(dataplaneNodeSetName) @@ -453,8 +563,13 @@ var _ = Describe("Dataplane NodeSet Test", func() { When("A ssh secret is created", func() { BeforeEach(func() { + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, DefaultDataPlaneNoNodeSetSpec(tlsEnabled))) CreateSSHSecret(dataplaneSSHSecretName) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should have created a Secret", func() { secret := th.GetSecret(dataplaneSecretName) @@ -474,8 +589,13 @@ var _ = Describe("Dataplane NodeSet Test", func() { When("No default service image is provided", func() { BeforeEach(func() { + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, DefaultDataPlaneNoNodeSetSpec(tlsEnabled))) CreateSSHSecret(dataplaneSSHSecretName) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should have default service values provided", func() { secret := th.GetSecret(dataplaneSecretName) @@ -488,8 +608,13 @@ var _ = Describe("Dataplane NodeSet Test", func() { When("A user provides a custom service image", func() { BeforeEach(func() { + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, CustomServiceImageSpec())) CreateSSHSecret(dataplaneSSHSecretName) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should have the user defined image in the inventory", func() { secret := th.GetSecret(dataplaneSecretName) @@ -502,8 +627,13 @@ var _ = Describe("Dataplane NodeSet Test", func() { When("No default service image is provided", func() { BeforeEach(func() { + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, DefaultDataPlaneNoNodeSetSpec(tlsEnabled))) CreateSSHSecret(dataplaneSSHSecretName) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should have default service values provided", func() { secret := th.GetSecret(dataplaneSecretName) @@ -516,8 +646,13 @@ var _ = Describe("Dataplane NodeSet Test", func() { When("A user provides a custom service image", func() { BeforeEach(func() { + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, CustomServiceImageSpec())) CreateSSHSecret(dataplaneSSHSecretName) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should have the user defined image in the inventory", func() { secret := th.GetSecret(dataplaneSecretName) @@ -533,9 +668,12 @@ var _ = Describe("Dataplane NodeSet Test", func() { nodeSetSpec := DefaultDataPlaneNodeSetSpec("edpm-compute") nodeSetSpec["preProvisioned"] = true DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, nodeSetSpec)) CreateSSHSecret(dataplaneSSHSecretName) - SimulateIPSetComplete(dataplaneIPSetName) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should not have set the node specific ansible_user variable", func() { secret := th.GetSecret(dataplaneSecretName) @@ -554,16 +692,15 @@ var _ = Describe("Dataplane NodeSet Test", func() { When("The individual node has a AnsibleUser override", func() { BeforeEach(func() { DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) - nodeOverrideSpec := map[string]interface{}{ - "hostname": "edpm-bm-compute-1", - "networks": []map[string]interface{}{{ - "name": "CtlPlane", - "fixedIP": "172.20.12.76", - "subnetName": "ctlplane_subnet", + nodeOverrideSpec := v1beta1.NodeSection{ + HostName: dataplaneNodeName.Name, + Networks: []infrav1.IPSetNetwork{{ + Name: "ctlplane", + SubnetName: "subnet1", }, }, - "ansible": map[string]interface{}{ - "ansibleUser": "test-user", + Ansible: v1beta1.AnsibleOpts{ + AnsibleUser: "test-user", }, } @@ -575,12 +712,15 @@ var _ = Describe("Dataplane NodeSet Test", func() { } nodeSetSpec := DefaultDataPlaneNoNodeSetSpec(tlsEnabled) - nodeSetSpec["nodes"].(map[string]interface{})["edpm-compute-node-1"] = nodeOverrideSpec + nodeSetSpec["nodes"].(map[string]v1beta1.NodeSection)[dataplaneNodeName.Name] = nodeOverrideSpec nodeSetSpec["nodeTemplate"] = nodeTemplateOverrideSpec + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, nodeSetSpec)) CreateSSHSecret(dataplaneSSHSecretName) - SimulateIPSetComplete(dataplaneIPSetName) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should have a node specific override that is different to the group", func() { secret := th.GetSecret(dataplaneSecretName) @@ -601,9 +741,12 @@ var _ = Describe("Dataplane NodeSet Test", func() { nodeSetSpec := DefaultDataPlaneNodeSetSpec("edpm-compute") nodeSetSpec["preProvisioned"] = true DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, nodeSetSpec)) CreateSSHSecret(dataplaneSSHSecretName) - SimulateIPSetComplete(dataplaneIPSetName) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should set the ctlplane_ip variable in the Ansible inventory secret", func() { Eventually(func() string { @@ -615,9 +758,14 @@ var _ = Describe("Dataplane NodeSet Test", func() { When("A DataPlaneNodeSet is created with NoNodes and a OpenStackDataPlaneDeployment is created", func() { BeforeEach(func() { + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, DefaultDataPlaneNoNodeSetSpec(tlsEnabled))) DeferCleanup(th.DeleteInstance, CreateDataplaneDeployment(dataplaneDeploymentName, DefaultDataPlaneDeploymentSpec())) CreateSSHSecret(dataplaneSSHSecretName) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should reach Input and Setup Ready completion", func() { var conditionList = []condition.Type{ @@ -639,7 +787,13 @@ var _ = Describe("Dataplane NodeSet Test", func() { tlsEnabled := true When("A Dataplane resorce is created with PreProvisioned nodes, no deployment", func() { BeforeEach(func() { + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, DefaultDataPlaneNoNodeSetSpec(tlsEnabled))) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) + }) It("should have the Spec fields initialized", func() { dataplaneNodeSetInstance := GetDataplaneNodeSet(dataplaneNodeSetName) @@ -678,8 +832,12 @@ var _ = Describe("Dataplane NodeSet Test", func() { }, NodeTemplate: dataplanev1.NodeTemplate{ AnsibleSSHPrivateKeySecret: "dataplane-ansible-ssh-private-key-secret", - Networks: nil, - ManagementNetwork: "ctlplane", + Networks: []infrav1.IPSetNetwork{{ + Name: "ctlplane", + SubnetName: "subnet1", + }, + }, + ManagementNetwork: "ctlplane", Ansible: dataplanev1.AnsibleOpts{ AnsibleUser: "cloud-admin", AnsibleHost: "", @@ -695,7 +853,11 @@ var _ = Describe("Dataplane NodeSet Test", func() { NetworkAttachments: nil, SecretMaxSize: 1048576, TLSEnabled: tlsEnabled, - Nodes: map[string]dataplanev1.NodeSection{}, + Nodes: map[string]dataplanev1.NodeSection{ + dataplaneNodeName.Name: { + HostName: dataplaneNodeName.Name, + }, + }, Services: []string{ "download-cache", "bootstrap", @@ -752,7 +914,12 @@ var _ = Describe("Dataplane NodeSet Test", func() { spec := DefaultDataPlaneNoNodeSetSpec(tlsEnabled) spec["metadata"] = map[string]interface{}{"ansiblesshprivatekeysecret": ""} spec["preProvisioned"] = false + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, spec)) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("should have the Spec fields initialized", func() { dataplaneNodeSetInstance := GetDataplaneNodeSet(dataplaneNodeSetName) @@ -800,7 +967,12 @@ var _ = Describe("Dataplane NodeSet Test", func() { BeforeEach(func() { spec := DefaultDataPlaneNoNodeSetSpec(tlsEnabled) spec["metadata"] = map[string]interface{}{"ansiblesshprivatekeysecret": ""} + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, spec)) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("should have the Spec fields initialized", func() { dataplaneNodeSetInstance := GetDataplaneNodeSet(dataplaneNodeSetName) @@ -847,8 +1019,13 @@ var _ = Describe("Dataplane NodeSet Test", func() { When("A ssh secret is created", func() { BeforeEach(func() { + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, DefaultDataPlaneNoNodeSetSpec(tlsEnabled))) CreateSSHSecret(dataplaneSSHSecretName) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should have created a Secret", func() { secret := th.GetSecret(dataplaneSecretName) @@ -868,8 +1045,13 @@ var _ = Describe("Dataplane NodeSet Test", func() { When("No default service image is provided", func() { BeforeEach(func() { + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, DefaultDataPlaneNoNodeSetSpec(tlsEnabled))) CreateSSHSecret(dataplaneSSHSecretName) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should have default service values provided", func() { secret := th.GetSecret(dataplaneSecretName) @@ -882,8 +1064,13 @@ var _ = Describe("Dataplane NodeSet Test", func() { When("A user provides a custom service image", func() { BeforeEach(func() { + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, CustomServiceImageSpec())) CreateSSHSecret(dataplaneSSHSecretName) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should have the user defined image in the inventory", func() { secret := th.GetSecret(dataplaneSecretName) @@ -896,8 +1083,13 @@ var _ = Describe("Dataplane NodeSet Test", func() { When("No default service image is provided", func() { BeforeEach(func() { + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, DefaultDataPlaneNoNodeSetSpec(tlsEnabled))) CreateSSHSecret(dataplaneSSHSecretName) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should have default service values provided", func() { secret := th.GetSecret(dataplaneSecretName) @@ -910,8 +1102,13 @@ var _ = Describe("Dataplane NodeSet Test", func() { When("A user provides a custom service image", func() { BeforeEach(func() { + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, CustomServiceImageSpec())) CreateSSHSecret(dataplaneSSHSecretName) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should have the user defined image in the inventory", func() { secret := th.GetSecret(dataplaneSecretName) @@ -927,9 +1124,12 @@ var _ = Describe("Dataplane NodeSet Test", func() { nodeSetSpec := DefaultDataPlaneNodeSetSpec("edpm-compute") nodeSetSpec["preProvisioned"] = true DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, nodeSetSpec)) CreateSSHSecret(dataplaneSSHSecretName) - SimulateIPSetComplete(dataplaneIPSetName) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should not have set the node specific ansible_user variable", func() { secret := th.GetSecret(dataplaneSecretName) @@ -948,16 +1148,16 @@ var _ = Describe("Dataplane NodeSet Test", func() { When("The individual node has a AnsibleUser override", func() { BeforeEach(func() { DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) - nodeOverrideSpec := map[string]interface{}{ - "hostname": "edpm-bm-compute-1", - "networks": []map[string]interface{}{{ - "name": "CtlPlane", - "fixedIP": "172.20.12.76", - "subnetName": "ctlplane_subnet", + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) + nodeOverrideSpec := v1beta1.NodeSection{ + HostName: dataplaneNodeName.Name, + Networks: []infrav1.IPSetNetwork{{ + Name: "ctlplane", + SubnetName: "subnet1", }, }, - "ansible": map[string]interface{}{ - "ansibleUser": "test-user", + Ansible: v1beta1.AnsibleOpts{ + AnsibleUser: "test-user", }, } @@ -969,12 +1169,14 @@ var _ = Describe("Dataplane NodeSet Test", func() { } nodeSetSpec := DefaultDataPlaneNoNodeSetSpec(tlsEnabled) - nodeSetSpec["nodes"].(map[string]interface{})["edpm-compute-node-1"] = nodeOverrideSpec + nodeSetSpec["nodes"].(map[string]v1beta1.NodeSection)[dataplaneNodeName.Name] = nodeOverrideSpec nodeSetSpec["nodeTemplate"] = nodeTemplateOverrideSpec DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, nodeSetSpec)) CreateSSHSecret(dataplaneSSHSecretName) - SimulateIPSetComplete(dataplaneIPSetName) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should have a node specific override that is different to the group", func() { secret := th.GetSecret(dataplaneSecretName) @@ -995,9 +1197,12 @@ var _ = Describe("Dataplane NodeSet Test", func() { nodeSetSpec := DefaultDataPlaneNodeSetSpec("edpm-compute") nodeSetSpec["preProvisioned"] = true DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, nodeSetSpec)) CreateSSHSecret(dataplaneSSHSecretName) - SimulateIPSetComplete(dataplaneIPSetName) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should set the ctlplane_ip variable in the Ansible inventory secret", func() { Eventually(func() string { @@ -1009,9 +1214,14 @@ var _ = Describe("Dataplane NodeSet Test", func() { When("A DataPlaneNodeSet is created with NoNodes and a OpenStackDataPlaneDeployment is created", func() { BeforeEach(func() { + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, DefaultDataPlaneNoNodeSetSpec(tlsEnabled))) DeferCleanup(th.DeleteInstance, CreateDataplaneDeployment(dataplaneDeploymentName, DefaultDataPlaneDeploymentSpec())) CreateSSHSecret(dataplaneSSHSecretName) + SimulateDNSMasqComplete(dnsMasqName) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should reach Input and Setup Ready completion", func() { var conditionList = []condition.Type{ @@ -1032,7 +1242,7 @@ var _ = Describe("Dataplane NodeSet Test", func() { When("A user changes spec field that would require a new Ansible execution", func() { BeforeEach(func() { - nodeSetSpec := DefaultDataPlaneNodeSetSpec("edpm-compute") + nodeSetSpec := DefaultDataPlaneNodeSetSpec(dataplaneNodeSetName.Name) nodeSetSpec["nodeTemplate"] = dataplanev1.NodeTemplate{ Ansible: dataplanev1.AnsibleOpts{ AnsibleVars: map[string]json.RawMessage{ @@ -1040,7 +1250,12 @@ var _ = Describe("Dataplane NodeSet Test", func() { }, }, } + DeferCleanup(th.DeleteInstance, CreateNetConfig(dataplaneNetConfigName, DefaultNetConfigSpec())) + DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec())) + SimulateDNSMasqComplete(dnsMasqName) DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, nodeSetSpec)) + SimulateIPSetComplete(dataplaneNodeName) + SimulateDNSDataComplete(dataplaneNodeSetName) }) It("Should change the ConfigHash", func() { diff --git a/tests/kuttl/tests/dataplane-create-test/00-assert.yaml b/tests/kuttl/tests/dataplane-create-test/00-assert.yaml index f9607998d..65d034665 100644 --- a/tests/kuttl/tests/dataplane-create-test/00-assert.yaml +++ b/tests/kuttl/tests/dataplane-create-test/00-assert.yaml @@ -1,37 +1,35 @@ apiVersion: dataplane.openstack.org/v1beta1 kind: OpenStackDataPlaneNodeSet metadata: - name: openstack-edpm + name: openstack-edpm-ipam spec: env: - name: ANSIBLE_FORCE_COLOR value: "True" nodes: edpm-compute-0: - ansible: - ansibleHost: 192.168.122.100 - ansibleUser: cloud-admin - ansibleVars: - ctlplane_ip: 192.168.122.100 - fqdn_internalapi: edpm-compute-0.example.com - internalapi_ip: 172.17.0.100 - storage_ip: 172.18.0.100 - tenant_ip: 172.19.0.100 hostName: edpm-compute-0 + networks: + - name: ctlplane + subnetName: subnet1 + defaultRoute: true + fixedIP: 192.168.122.100 + - name: internalapi + subnetName: subnet1 + - name: storage + subnetName: subnet1 + - name: tenant + subnetName: subnet1 + nodeTemplate: ansible: ansiblePort: 22 ansibleUser: cloud-admin + ansibleVarsFrom: + - prefix: edpm_ + configMapRef: + name: network-config-template ansibleVars: - ctlplane_dns_nameservers: - - 192.168.122.1 - ctlplane_gateway_ip: 192.168.122.1 - ctlplane_host_routes: - - ip_netmask: 0.0.0.0/0 - next_hop: 192.168.122.1 - ctlplane_mtu: 1500 - ctlplane_cidr: 24 - dns_search_domains: [] timesync_ntp_servers: - hostname: clock.redhat.com edpm_network_config_hide_sensitive_logs: false @@ -42,38 +40,8 @@ spec: - 192.168.122.0/24 edpm_sshd_configure_firewall: true enable_debug: false - external_cidr: "24" - external_host_routes: [] - external_mtu: 1500 - external_vlan_id: 44 - gather_facts: false - internalapi_cidr: "24" - internalapi_host_routes: [] - internalapi_mtu: 1500 - internalapi_vlan_id: 20 - networks_lower: - External: external - InternalApi: internalapi - Storage: storage - Tenant: tenant - neutron_physical_bridge_name: br-ex - neutron_public_interface_name: eth0 - nodeset_networks: - - InternalApi - - Storage - - Tenant - storage_cidr: "24" - storage_host_routes: [] - storage_mtu: 1500 - storage_vlan_id: 21 - tenant_cidr: "24" - tenant_host_routes: [] - tenant_mtu: 1500 - tenant_vlan_id: 22 ansibleSSHPrivateKeySecret: dataplane-ansible-ssh-private-key-secret - managementNetwork: ctlplane preProvisioned: true - tlsEnabled: true services: - download-cache - bootstrap @@ -89,6 +57,19 @@ spec: - nova status: observedGeneration: 1 + allHostnames: + edpm-compute-0: + ctlplane: edpm-compute-0.ctlplane.example.com + internalapi: edpm-compute-0.internalapi.example.com + storage: edpm-compute-0.storage.example.com + tenant: edpm-compute-0.tenant.example.com + allIPs: + edpm-compute-0: + ctlplane: 192.168.122.100 + internalapi: 172.17.0.100 + storage: 172.18.0.100 + tenant: 172.19.0.100 + ctlplaneSearchDomain: ctlplane.example.com conditions: - message: Deployment not started reason: Requested @@ -102,6 +83,14 @@ status: reason: Ready status: "True" type: InputReady + - message: NodeSetDNSDataReady ready + reason: Ready + status: "True" + type: NodeSetDNSDataReady + - message: NodeSetIPReservationReady ready + reason: Ready + status: "True" + type: NodeSetIPReservationReady - message: ServiceAccount created reason: Ready status: "True" @@ -111,7 +100,95 @@ status: status: "True" type: SetupReady --- -apiVersion: v1 -kind: ServiceAccount +apiVersion: network.openstack.org/v1beta1 +kind: IPSet metadata: - name: openstack-edpm + name: edpm-compute-0 +spec: + immutable: false + networks: + - defaultRoute: true + name: ctlplane + subnetName: subnet1 + - name: internalapi + subnetName: subnet1 + - name: storage + subnetName: subnet1 + - name: tenant + subnetName: subnet1 +status: + conditions: + - message: Setup complete + reason: Ready + status: "True" + type: Ready + - message: Input data complete + reason: Ready + status: "True" + type: InputReady + - message: Reservation successful + reason: Ready + status: "True" + type: ReservationReady + reservations: + - address: 192.168.122.100 + cidr: 192.168.122.0/24 + dnsDomain: ctlplane.example.com + gateway: 192.168.122.1 + mtu: 1500 + network: ctlplane + routes: + - destination: 0.0.0.0/0 + nexthop: 192.168.122.1 + subnet: subnet1 + - address: 172.17.0.100 + cidr: 172.17.0.0/24 + dnsDomain: internalapi.example.com + mtu: 1500 + network: internalapi + subnet: subnet1 + vlan: 20 + - address: 172.18.0.100 + cidr: 172.18.0.0/24 + dnsDomain: storage.example.com + mtu: 1500 + network: storage + subnet: subnet1 + vlan: 21 + - address: 172.19.0.100 + cidr: 172.19.0.0/24 + dnsDomain: tenant.example.com + mtu: 1500 + network: tenant + subnet: subnet1 + vlan: 22 +--- +apiVersion: network.openstack.org/v1beta1 +kind: DNSData +metadata: + name: openstack-edpm-ipam +spec: + dnsDataLabelSelectorValue: dnsdata + hosts: + - hostnames: + - edpm-compute-0.ctlplane.example.com + ip: 192.168.122.100 + - hostnames: + - edpm-compute-0.internalapi.example.com + ip: 172.17.0.100 + - hostnames: + - edpm-compute-0.storage.example.com + ip: 172.18.0.100 + - hostnames: + - edpm-compute-0.tenant.example.com + ip: 172.19.0.100 +status: + conditions: + - message: Setup complete + reason: Ready + status: "True" + type: Ready + - message: Input data complete + reason: Ready + status: "True" + type: ServiceConfigReady diff --git a/tests/kuttl/tests/dataplane-create-test/00-dataplane-create.yaml b/tests/kuttl/tests/dataplane-create-test/00-dataplane-create.yaml index 977e977f1..a7f7b889e 100644 --- a/tests/kuttl/tests/dataplane-create-test/00-dataplane-create.yaml +++ b/tests/kuttl/tests/dataplane-create-test/00-dataplane-create.yaml @@ -39,7 +39,7 @@ data: apiVersion: dataplane.openstack.org/v1beta1 kind: OpenStackDataPlaneNodeSet metadata: - name: openstack-edpm + name: openstack-edpm-ipam spec: env: - name: ANSIBLE_FORCE_COLOR @@ -59,20 +59,21 @@ spec: - nova preProvisioned: true nodes: - edpm-compute-0: - hostName: edpm-compute-0 - ansible: - ansibleHost: 192.168.122.100 - ansibleUser: cloud-admin - ansibleVars: - ctlplane_ip: 192.168.122.100 - internalapi_ip: 172.17.0.100 - storage_ip: 172.18.0.100 - tenant_ip: 172.19.0.100 - fqdn_internalapi: edpm-compute-0.example.com + edpm-compute-0: + hostName: edpm-compute-0 + networks: + - name: ctlplane + subnetName: subnet1 + defaultRoute: true + fixedIP: 192.168.122.100 + - name: internalapi + subnetName: subnet1 + - name: storage + subnetName: subnet1 + - name: tenant + subnetName: subnet1 nodeTemplate: ansibleSSHPrivateKeySecret: dataplane-ansible-ssh-private-key-secret - managementNetwork: ctlplane ansible: ansibleUser: cloud-admin ansiblePort: 22 @@ -87,47 +88,8 @@ spec: # Default nic config template for a EDPM compute node # These vars are edpm_network_config role vars edpm_network_config_hide_sensitive_logs: false - # These vars are for the network config templates themselves and are - # considered EDPM network defaults. - neutron_physical_bridge_name: br-ex - neutron_public_interface_name: eth0 - ctlplane_mtu: 1500 - ctlplane_cidr: 24 - ctlplane_gateway_ip: 192.168.122.1 - ctlplane_host_routes: - - ip_netmask: 0.0.0.0/0 - next_hop: 192.168.122.1 - external_mtu: 1500 - external_vlan_id: 44 - external_cidr: '24' - external_host_routes: [] - internalapi_mtu: 1500 - internalapi_vlan_id: 20 - internalapi_cidr: '24' - internalapi_host_routes: [] - storage_mtu: 1500 - storage_vlan_id: 21 - storage_cidr: '24' - storage_host_routes: [] - tenant_mtu: 1500 - tenant_vlan_id: 22 - tenant_cidr: '24' - tenant_host_routes: [] - nodeset_networks: - - InternalApi - - Storage - - Tenant - networks_lower: - External: external - InternalApi: internalapi - Storage: storage - Tenant: tenant - # edpm_nodes_validation edpm_nodes_validation_validate_controllers_icmp: false edpm_nodes_validation_validate_gateway_icmp: false - ctlplane_dns_nameservers: - - 192.168.122.1 - dns_search_domains: [] gather_facts: false enable_debug: false # edpm firewall, change the allowed CIDR if needed diff --git a/tests/kuttl/tests/dataplane-deploy-global-service-test/00-assert.yaml b/tests/kuttl/tests/dataplane-deploy-global-service-test/00-assert.yaml index c134613a7..f06883fe9 100644 --- a/tests/kuttl/tests/dataplane-deploy-global-service-test/00-assert.yaml +++ b/tests/kuttl/tests/dataplane-deploy-global-service-test/00-assert.yaml @@ -120,6 +120,14 @@ status: reason: Ready status: "True" type: InputReady + - message: NodeSetDNSDataReady ready + reason: Ready + status: "True" + type: NodeSetDNSDataReady + - message: NodeSetIPReservationReady ready + reason: Ready + status: "True" + type: NodeSetIPReservationReady - message: ServiceAccount created reason: Ready status: "True" diff --git a/tests/kuttl/tests/dataplane-deploy-global-service-test/01-assert.yaml b/tests/kuttl/tests/dataplane-deploy-global-service-test/01-assert.yaml index e7757a2ce..5672d30da 100644 --- a/tests/kuttl/tests/dataplane-deploy-global-service-test/01-assert.yaml +++ b/tests/kuttl/tests/dataplane-deploy-global-service-test/01-assert.yaml @@ -53,6 +53,14 @@ status: reason: Ready status: "True" type: InputReady + - message: NodeSetDNSDataReady ready + reason: Ready + status: "True" + type: NodeSetDNSDataReady + - message: NodeSetIPReservationReady ready + reason: Ready + status: "True" + type: NodeSetIPReservationReady - message: ServiceAccount created reason: Ready status: "True" diff --git a/tests/kuttl/tests/dataplane-deploy-global-service-test/02-assert.yaml b/tests/kuttl/tests/dataplane-deploy-global-service-test/02-assert.yaml index 0469d77a0..42e9ae1dc 100644 --- a/tests/kuttl/tests/dataplane-deploy-global-service-test/02-assert.yaml +++ b/tests/kuttl/tests/dataplane-deploy-global-service-test/02-assert.yaml @@ -27,6 +27,14 @@ status: reason: Ready status: "True" type: InputReady + - message: NodeSetDNSDataReady ready + reason: Ready + status: "True" + type: NodeSetDNSDataReady + - message: NodeSetIPReservationReady ready + reason: Ready + status: "True" + type: NodeSetIPReservationReady - message: ServiceAccount created reason: Ready status: "True" diff --git a/tests/kuttl/tests/dataplane-deploy-multiple-secrets/00-dataplane-create.yaml b/tests/kuttl/tests/dataplane-deploy-multiple-secrets/00-dataplane-create.yaml index 6ed62d139..6dec0917c 100644 --- a/tests/kuttl/tests/dataplane-deploy-multiple-secrets/00-dataplane-create.yaml +++ b/tests/kuttl/tests/dataplane-deploy-multiple-secrets/00-dataplane-create.yaml @@ -1,16 +1,3 @@ -apiVersion: network.openstack.org/v1beta1 -kind: DNSMasq -metadata: - name: dnsmasq -spec: - replicas: 1 - options: - - key: server - values: - - 192.168.122.1 - debug: - service: false ---- apiVersion: dataplane.openstack.org/v1beta1 kind: OpenStackDataPlaneService metadata: diff --git a/tests/kuttl/tests/dataplane-deploy-no-nodes-test/00-assert.yaml b/tests/kuttl/tests/dataplane-deploy-no-nodes-test/00-assert.yaml index 159855167..5d1797ea8 100644 --- a/tests/kuttl/tests/dataplane-deploy-no-nodes-test/00-assert.yaml +++ b/tests/kuttl/tests/dataplane-deploy-no-nodes-test/00-assert.yaml @@ -42,6 +42,14 @@ status: reason: Ready status: "True" type: InputReady + - message: NodeSetDNSDataReady ready + reason: Ready + status: "True" + type: NodeSetDNSDataReady + - message: NodeSetIPReservationReady ready + reason: Ready + status: "True" + type: NodeSetIPReservationReady - message: ServiceAccount created reason: Ready status: "True" diff --git a/tests/kuttl/tests/dataplane-deploy-no-nodes-test/01-assert.yaml b/tests/kuttl/tests/dataplane-deploy-no-nodes-test/01-assert.yaml index 6e1e3f875..a1096ef70 100644 --- a/tests/kuttl/tests/dataplane-deploy-no-nodes-test/01-assert.yaml +++ b/tests/kuttl/tests/dataplane-deploy-no-nodes-test/01-assert.yaml @@ -41,6 +41,14 @@ status: reason: Ready status: "True" type: InputReady + - message: NodeSetDNSDataReady ready + reason: Ready + status: "True" + type: NodeSetDNSDataReady + - message: NodeSetIPReservationReady ready + reason: Ready + status: "True" + type: NodeSetIPReservationReady - message: ServiceAccount created reason: Ready status: "True" diff --git a/tests/kuttl/tests/dataplane-deploy-no-nodes-test/03-assert.yaml b/tests/kuttl/tests/dataplane-deploy-no-nodes-test/03-assert.yaml index 39f8b8918..15894e6a9 100644 --- a/tests/kuttl/tests/dataplane-deploy-no-nodes-test/03-assert.yaml +++ b/tests/kuttl/tests/dataplane-deploy-no-nodes-test/03-assert.yaml @@ -41,6 +41,14 @@ status: reason: Ready status: "True" type: InputReady + - message: NodeSetDNSDataReady ready + reason: Ready + status: "True" + type: NodeSetDNSDataReady + - message: NodeSetIPReservationReady ready + reason: Ready + status: "True" + type: NodeSetIPReservationReady - message: ServiceAccount created reason: Ready status: "True" diff --git a/tests/kuttl/tests/dataplane-deploy-no-nodes-test/04-assert.yaml b/tests/kuttl/tests/dataplane-deploy-no-nodes-test/04-assert.yaml index c458805f7..021793207 100644 --- a/tests/kuttl/tests/dataplane-deploy-no-nodes-test/04-assert.yaml +++ b/tests/kuttl/tests/dataplane-deploy-no-nodes-test/04-assert.yaml @@ -41,6 +41,14 @@ status: reason: Ready status: "True" type: InputReady + - message: NodeSetDNSDataReady ready + reason: Ready + status: "True" + type: NodeSetDNSDataReady + - message: NodeSetIPReservationReady ready + reason: Ready + status: "True" + type: NodeSetIPReservationReady - message: ServiceAccount created reason: Ready status: "True" diff --git a/tests/kuttl/tests/dataplane-deploy-no-nodes-test/05-assert.yaml b/tests/kuttl/tests/dataplane-deploy-no-nodes-test/05-assert.yaml index ddc3d0d27..75f18d77a 100644 --- a/tests/kuttl/tests/dataplane-deploy-no-nodes-test/05-assert.yaml +++ b/tests/kuttl/tests/dataplane-deploy-no-nodes-test/05-assert.yaml @@ -43,6 +43,14 @@ status: reason: Ready status: "True" type: InputReady + - message: NodeSetDNSDataReady ready + reason: Ready + status: "True" + type: NodeSetDNSDataReady + - message: NodeSetIPReservationReady ready + reason: Ready + status: "True" + type: NodeSetIPReservationReady - message: ServiceAccount created reason: Ready status: "True" diff --git a/tests/kuttl/tests/dataplane-deploy-no-nodes-test/06-assert.yaml b/tests/kuttl/tests/dataplane-deploy-no-nodes-test/06-assert.yaml index 1de67ab9d..6cd10c1d7 100644 --- a/tests/kuttl/tests/dataplane-deploy-no-nodes-test/06-assert.yaml +++ b/tests/kuttl/tests/dataplane-deploy-no-nodes-test/06-assert.yaml @@ -27,6 +27,14 @@ status: reason: Ready status: "True" type: InputReady + - message: NodeSetDNSDataReady ready + reason: Ready + status: "True" + type: NodeSetDNSDataReady + - message: NodeSetIPReservationReady ready + reason: Ready + status: "True" + type: NodeSetIPReservationReady - message: ServiceAccount created reason: Ready status: "True" @@ -37,7 +45,6 @@ status: type: SetupReady configMapHashes: ovncontroller-config: n56h54bh9bhcbh65ch9fhdh66dh95h5dch569h678h7fh599h7ch84h597h59h54dh58dhf6h66bh565h4hc4h587h645hd7hcch5d8h5f4h55cq - deploymentStatuses: {} secretHashes: neutron-dhcp-agent-neutron-config: n68h676h98h689hd4h575h5dbh694h6fh688h57h665h5c5h56dh5ddh65bh5d7h5cdh644hb8h8fh5d9h5b9h555h9ch56dh5fh6chd4h5c5h5c5h68q neutron-ovn-agent-neutron-config: n5f4h89hb8h645h55bh657h9fh5d9h5c6h595h9dh667h5f4hfhffh7fh685h56ch57fh679h5ddh5ddh95h696hbch5c7h669h84h54dh685hfh85q @@ -45,7 +52,6 @@ status: neutron-sriov-agent-neutron-config: n685h567h697h5bch8ch5cfh87h698h658h684h8h99h5dch5c5h699h79hb5h87h66dh664h546h586h7bh56fh5d6h5d4h566h56bh87h678h696h56cq nova-cell1-compute-config: n89hd6h5h545h644h58h556hd9h5c5h598hd4h7bh5f9h5bdh649hb5h99h686h677h8ch575h665h574h587h5b6h5ddh8fh687h9bh657h675h97q nova-metadata-neutron-config: n7fh696h674h5b9h68dh77h677h5c5hd9h5dbh89h646h696h65ch64bh86hd8h56h78h558h5h5c7h87h86h5bh5bch78h6ch5cbh54fh56fhfdq - nova-migration-ssh-key: n64dh97h54dhffh65fh577h59bh664hbch54dhcbh547hdbhdch655hd9h675h5d4h67dh5ch67bh64h5fdh5c8h5cdh66bh5f5h58dhcbh9bh66bhd4q --- apiVersion: dataplane.openstack.org/v1beta1 kind: OpenStackDataPlaneDeployment diff --git a/tests/kuttl/tests/dataplane-deploy-tls-test/00-dataplane-create.yaml b/tests/kuttl/tests/dataplane-deploy-tls-test/00-dataplane-create.yaml index fa215fed3..927286831 100644 --- a/tests/kuttl/tests/dataplane-deploy-tls-test/00-dataplane-create.yaml +++ b/tests/kuttl/tests/dataplane-deploy-tls-test/00-dataplane-create.yaml @@ -1,16 +1,3 @@ -apiVersion: network.openstack.org/v1beta1 -kind: DNSMasq -metadata: - name: dnsmasq -spec: - replicas: 1 - options: - - key: server - values: - - 192.168.122.1 - debug: - service: false ---- apiVersion: dataplane.openstack.org/v1beta1 kind: OpenStackDataPlaneService metadata: diff --git a/tests/kuttl/tests/dataplane-service-custom-image/00-assert.yaml b/tests/kuttl/tests/dataplane-service-custom-image/00-assert.yaml index 2f4f043fa..2fda62972 100644 --- a/tests/kuttl/tests/dataplane-service-custom-image/00-assert.yaml +++ b/tests/kuttl/tests/dataplane-service-custom-image/00-assert.yaml @@ -30,6 +30,14 @@ status: reason: Ready status: "True" type: InputReady + - message: NodeSetDNSDataReady ready + reason: Ready + status: "True" + type: NodeSetDNSDataReady + - message: NodeSetIPReservationReady ready + reason: Ready + status: "True" + type: NodeSetIPReservationReady - message: ServiceAccount created reason: Ready status: "True" diff --git a/tests/kuttl/tests/dataplane-with-ipam-create-test/00-assert.yaml b/tests/kuttl/tests/dataplane-with-ipam-create-test/00-assert.yaml deleted file mode 100644 index 65d034665..000000000 --- a/tests/kuttl/tests/dataplane-with-ipam-create-test/00-assert.yaml +++ /dev/null @@ -1,194 +0,0 @@ -apiVersion: dataplane.openstack.org/v1beta1 -kind: OpenStackDataPlaneNodeSet -metadata: - name: openstack-edpm-ipam -spec: - env: - - name: ANSIBLE_FORCE_COLOR - value: "True" - nodes: - edpm-compute-0: - hostName: edpm-compute-0 - networks: - - name: ctlplane - subnetName: subnet1 - defaultRoute: true - fixedIP: 192.168.122.100 - - name: internalapi - subnetName: subnet1 - - name: storage - subnetName: subnet1 - - name: tenant - subnetName: subnet1 - - nodeTemplate: - ansible: - ansiblePort: 22 - ansibleUser: cloud-admin - ansibleVarsFrom: - - prefix: edpm_ - configMapRef: - name: network-config-template - ansibleVars: - timesync_ntp_servers: - - hostname: clock.redhat.com - edpm_network_config_hide_sensitive_logs: false - edpm_nodes_validation_validate_controllers_icmp: false - edpm_nodes_validation_validate_gateway_icmp: false - edpm_selinux_mode: enforcing - edpm_sshd_allowed_ranges: - - 192.168.122.0/24 - edpm_sshd_configure_firewall: true - enable_debug: false - ansibleSSHPrivateKeySecret: dataplane-ansible-ssh-private-key-secret - preProvisioned: true - services: - - download-cache - - bootstrap - - configure-network - - validate-network - - install-os - - configure-os - - run-os - - install-certs - - ovn - - neutron-metadata - - libvirt - - nova -status: - observedGeneration: 1 - allHostnames: - edpm-compute-0: - ctlplane: edpm-compute-0.ctlplane.example.com - internalapi: edpm-compute-0.internalapi.example.com - storage: edpm-compute-0.storage.example.com - tenant: edpm-compute-0.tenant.example.com - allIPs: - edpm-compute-0: - ctlplane: 192.168.122.100 - internalapi: 172.17.0.100 - storage: 172.18.0.100 - tenant: 172.19.0.100 - ctlplaneSearchDomain: ctlplane.example.com - conditions: - - message: Deployment not started - reason: Requested - status: "False" - type: Ready - - message: Deployment not started - reason: Requested - status: "False" - type: DeploymentReady - - message: Input data complete - reason: Ready - status: "True" - type: InputReady - - message: NodeSetDNSDataReady ready - reason: Ready - status: "True" - type: NodeSetDNSDataReady - - message: NodeSetIPReservationReady ready - reason: Ready - status: "True" - type: NodeSetIPReservationReady - - message: ServiceAccount created - reason: Ready - status: "True" - type: ServiceAccountReady - - message: Setup complete - reason: Ready - status: "True" - type: SetupReady ---- -apiVersion: network.openstack.org/v1beta1 -kind: IPSet -metadata: - name: edpm-compute-0 -spec: - immutable: false - networks: - - defaultRoute: true - name: ctlplane - subnetName: subnet1 - - name: internalapi - subnetName: subnet1 - - name: storage - subnetName: subnet1 - - name: tenant - subnetName: subnet1 -status: - conditions: - - message: Setup complete - reason: Ready - status: "True" - type: Ready - - message: Input data complete - reason: Ready - status: "True" - type: InputReady - - message: Reservation successful - reason: Ready - status: "True" - type: ReservationReady - reservations: - - address: 192.168.122.100 - cidr: 192.168.122.0/24 - dnsDomain: ctlplane.example.com - gateway: 192.168.122.1 - mtu: 1500 - network: ctlplane - routes: - - destination: 0.0.0.0/0 - nexthop: 192.168.122.1 - subnet: subnet1 - - address: 172.17.0.100 - cidr: 172.17.0.0/24 - dnsDomain: internalapi.example.com - mtu: 1500 - network: internalapi - subnet: subnet1 - vlan: 20 - - address: 172.18.0.100 - cidr: 172.18.0.0/24 - dnsDomain: storage.example.com - mtu: 1500 - network: storage - subnet: subnet1 - vlan: 21 - - address: 172.19.0.100 - cidr: 172.19.0.0/24 - dnsDomain: tenant.example.com - mtu: 1500 - network: tenant - subnet: subnet1 - vlan: 22 ---- -apiVersion: network.openstack.org/v1beta1 -kind: DNSData -metadata: - name: openstack-edpm-ipam -spec: - dnsDataLabelSelectorValue: dnsdata - hosts: - - hostnames: - - edpm-compute-0.ctlplane.example.com - ip: 192.168.122.100 - - hostnames: - - edpm-compute-0.internalapi.example.com - ip: 172.17.0.100 - - hostnames: - - edpm-compute-0.storage.example.com - ip: 172.18.0.100 - - hostnames: - - edpm-compute-0.tenant.example.com - ip: 172.19.0.100 -status: - conditions: - - message: Setup complete - reason: Ready - status: "True" - type: Ready - - message: Input data complete - reason: Ready - status: "True" - type: ServiceConfigReady diff --git a/tests/kuttl/tests/dataplane-with-ipam-create-test/00-dataplane-create.yaml b/tests/kuttl/tests/dataplane-with-ipam-create-test/00-dataplane-create.yaml deleted file mode 100644 index 80d3d9cf2..000000000 --- a/tests/kuttl/tests/dataplane-with-ipam-create-test/00-dataplane-create.yaml +++ /dev/null @@ -1,112 +0,0 @@ -apiVersion: network.openstack.org/v1beta1 -kind: DNSMasq -metadata: - name: dnsmasq -spec: - replicas: 1 - options: - - key: server - values: - - 192.168.122.1 - debug: - service: false ---- -apiVersion: v1 -kind: ConfigMap -metadata: - name: network-config-template -data: - network_config_template: | - --- - {% set mtu_list = [ctlplane_mtu] %} - {% for network in nodeset_networks %} - {{ mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) }} - {%- endfor %} - {% set min_viable_mtu = mtu_list | max %} - network_config: - - type: ovs_bridge - name: {{ neutron_physical_bridge_name }} - mtu: {{ min_viable_mtu }} - use_dhcp: false - dns_servers: {{ ctlplane_dns_nameservers }} - domain: {{ dns_search_domains }} - addresses: - - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_cidr }} - routes: {{ ctlplane_host_routes }} - members: - - type: interface - name: nic1 - mtu: {{ min_viable_mtu }} - # force the MAC address of the bridge to this interface - primary: true - {% for network in nodeset_networks %} - - type: vlan - mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} - vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }} - addresses: - - ip_netmask: - {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }} - routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }} - {% endfor %} ---- -apiVersion: dataplane.openstack.org/v1beta1 -kind: OpenStackDataPlaneNodeSet -metadata: - name: openstack-edpm-ipam -spec: - env: - - name: ANSIBLE_FORCE_COLOR - value: "True" - services: - - download-cache - - bootstrap - - configure-network - - validate-network - - install-os - - configure-os - - run-os - - install-certs - - ovn - - neutron-metadata - - libvirt - - nova - preProvisioned: true - nodes: - edpm-compute-0: - hostName: edpm-compute-0 - networks: - - name: ctlplane - subnetName: subnet1 - defaultRoute: true - fixedIP: 192.168.122.100 - - name: internalapi - subnetName: subnet1 - - name: storage - subnetName: subnet1 - - name: tenant - subnetName: subnet1 - nodeTemplate: - ansibleSSHPrivateKeySecret: dataplane-ansible-ssh-private-key-secret - ansible: - ansibleUser: cloud-admin - ansiblePort: 22 - ansibleVarsFrom: - - prefix: edpm_ - configMapRef: - name: network-config-template - ansibleVars: - timesync_ntp_servers: - - hostname: clock.redhat.com - # edpm_network_config - # Default nic config template for a EDPM compute node - # These vars are edpm_network_config role vars - edpm_network_config_hide_sensitive_logs: false - edpm_nodes_validation_validate_controllers_icmp: false - edpm_nodes_validation_validate_gateway_icmp: false - gather_facts: false - enable_debug: false - # edpm firewall, change the allowed CIDR if needed - edpm_sshd_configure_firewall: true - edpm_sshd_allowed_ranges: ['192.168.122.0/24'] - # SELinux module - edpm_selinux_mode: enforcing