From e0e57aa60e7ff3f306d0b32178c20f317c768238 Mon Sep 17 00:00:00 2001 From: Fabricio Aguiar Date: Wed, 6 Mar 2024 10:00:25 +0000 Subject: [PATCH] Add AnsibleVarsFrom Inspired by Pod's Env x EnvFrom: https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/#define-an-environment-variable-for-a-container https://github.com/kubernetes/kubernetes/blob/v1.28.7/pkg/apis/core/types.go#L2321-L2330 https://github.com/kubernetes/kubernetes/blob/v1.28.7/pkg/kubelet/kubelet_pods.go#L619 AnsibleVarsFrom will add variables from ConfigMap/Secret to the inventory, variables from AnsibleVars will take precedence Signed-off-by: Fabricio Aguiar --- ...nstack.org_openstackdataplanenodesets.yaml | 46 +++++++++ api/v1beta1/common.go | 5 + api/v1beta1/zz_generated.deepcopy.go | 7 ++ ...nstack.org_openstackdataplanenodesets.yaml | 46 +++++++++ ...ane_v1beta1_openstackdataplanenodeset.yaml | 4 +- docs/assemblies/custom_resources.adoc | 5 + ...oc_creating-a-set-of-data-plane-nodes.adoc | 60 ++++++++++++ .../base/crs/openstackdataplanenodeset.yaml | 59 ++++-------- examples/base/kustomization.yaml | 2 + examples/base/vars/neutron.yaml | 7 ++ examples/base/vars/nic-config.yaml | 37 ++++++++ examples/bgp/values.yaml | 4 +- examples/bgp_ovn_cluster/values.yaml | 4 +- examples/customnetworks/values.yaml | 4 +- examples/networker/values.yaml | 4 +- examples/nmstate/values.yaml | 4 +- examples/ovs_dpdk/values.yaml | 4 +- examples/post_ceph_hci/values.yaml | 4 +- examples/pre_ceph_hci/values.yaml | 4 +- pkg/deployment/inventory.go | 93 ++++++++++++++++++- 20 files changed, 341 insertions(+), 62 deletions(-) create mode 100644 examples/base/vars/neutron.yaml create mode 100644 examples/base/vars/nic-config.yaml diff --git a/api/bases/dataplane.openstack.org_openstackdataplanenodesets.yaml b/api/bases/dataplane.openstack.org_openstackdataplanenodesets.yaml index 0c0e51a49..5720f9991 100644 --- a/api/bases/dataplane.openstack.org_openstackdataplanenodesets.yaml +++ b/api/bases/dataplane.openstack.org_openstackdataplanenodesets.yaml @@ -277,6 +277,29 @@ spec: type: string ansibleVars: x-kubernetes-preserve-unknown-fields: true + ansibleVarsFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array type: object ansibleSSHPrivateKeySecret: type: string @@ -1078,6 +1101,29 @@ spec: type: string ansibleVars: x-kubernetes-preserve-unknown-fields: true + ansibleVarsFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array type: object extraMounts: items: diff --git a/api/v1beta1/common.go b/api/v1beta1/common.go index 112ae95c2..d0ca6c650 100644 --- a/api/v1beta1/common.go +++ b/api/v1beta1/common.go @@ -43,6 +43,11 @@ type AnsibleOpts struct { // +kubebuilder:pruning:PreserveUnknownFields // +kubebuilder:validation:Schemaless AnsibleVars map[string]json.RawMessage `json:"ansibleVars,omitempty"` + + // AnsibleVarsFrom is a list of sources to populate ansible variables from. + // Values defined by an AnsibleVars with a duplicate key take precedence. + // +kubebuilder:validation:Optional + AnsibleVarsFrom []corev1.EnvFromSource `json:"ansibleVarsFrom,omitempty"` } // NodeSection defines the top level attributes inherited by nodes in the CR. diff --git a/api/v1beta1/zz_generated.deepcopy.go b/api/v1beta1/zz_generated.deepcopy.go index 194277b09..18cbad19f 100644 --- a/api/v1beta1/zz_generated.deepcopy.go +++ b/api/v1beta1/zz_generated.deepcopy.go @@ -102,6 +102,13 @@ func (in *AnsibleOpts) DeepCopyInto(out *AnsibleOpts) { (*out)[key] = outVal } } + if in.AnsibleVarsFrom != nil { + in, out := &in.AnsibleVarsFrom, &out.AnsibleVarsFrom + *out = make([]v1.EnvFromSource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AnsibleOpts. diff --git a/config/crd/bases/dataplane.openstack.org_openstackdataplanenodesets.yaml b/config/crd/bases/dataplane.openstack.org_openstackdataplanenodesets.yaml index 0c0e51a49..5720f9991 100644 --- a/config/crd/bases/dataplane.openstack.org_openstackdataplanenodesets.yaml +++ b/config/crd/bases/dataplane.openstack.org_openstackdataplanenodesets.yaml @@ -277,6 +277,29 @@ spec: type: string ansibleVars: x-kubernetes-preserve-unknown-fields: true + ansibleVarsFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array type: object ansibleSSHPrivateKeySecret: type: string @@ -1078,6 +1101,29 @@ spec: type: string ansibleVars: x-kubernetes-preserve-unknown-fields: true + ansibleVarsFrom: + items: + properties: + configMapRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + prefix: + type: string + secretRef: + properties: + name: + type: string + optional: + type: boolean + type: object + x-kubernetes-map-type: atomic + type: object + type: array type: object extraMounts: items: diff --git a/config/samples/dataplane_v1beta1_openstackdataplanenodeset.yaml b/config/samples/dataplane_v1beta1_openstackdataplanenodeset.yaml index 1ed41fef8..736cf070f 100644 --- a/config/samples/dataplane_v1beta1_openstackdataplanenodeset.yaml +++ b/config/samples/dataplane_v1beta1_openstackdataplanenodeset.yaml @@ -44,8 +44,8 @@ spec: ansibleVars: # CHANGEME -- see https://access.redhat.com/solutions/253273 # edpm_bootstrap_command: | - # subscription-manager register --username --password - # podman login -u -p registry.redhat.io + # subscription-manager register --username {{ subscription_manager_username }} --password {{ subscription_manager_password }} + # podman login -u {{ registry_username }} -p {{ registry_password }} registry.redhat.io edpm_network_config_template: | --- {% set mtu_list = [ctlplane_mtu] %} diff --git a/docs/assemblies/custom_resources.adoc b/docs/assemblies/custom_resources.adoc index 8fcece34f..dada8ac96 100644 --- a/docs/assemblies/custom_resources.adoc +++ b/docs/assemblies/custom_resources.adoc @@ -107,6 +107,11 @@ AnsibleOpts defines a logical grouping of Ansible related configuration options. | AnsibleVars for configuring ansible | map[string]json.RawMessage | false + +| ansibleVarsFrom +| AnsibleVarsFrom is a list of sources to populate ansible variables from. Values defined by an AnsibleVars with a duplicate key take precedence. +| []corev1.EnvFromSource +| false |=== <> diff --git a/docs/assemblies/proc_creating-a-set-of-data-plane-nodes.adoc b/docs/assemblies/proc_creating-a-set-of-data-plane-nodes.adoc index 6a980ba89..de746994a 100644 --- a/docs/assemblies/proc_creating-a-set-of-data-plane-nodes.adoc +++ b/docs/assemblies/proc_creating-a-set-of-data-plane-nodes.adoc @@ -162,7 +162,67 @@ spec: ---- + You can copy a sample template from https://github.com/openstack-k8s-operators/dataplane-operator/tree/main/config/samples/nic-config-samples. For information about customizing the template, see link:https://access.redhat.com/documentation/en-us/red_hat_openstack_platform/17.1/html/installing_and_managing_red_hat_openstack_platform_with_director/assembly_configuring-overcloud-networking_installing-director-on-the-undercloud#ref_network-interface-configuration-options_custom-network-interface-templates[Network interface configuration options]. +ifeval::["{build}" == "downstream"] +. Register the operating system of the nodes that are not registered to the Red Hat Customer Portal, and enable repositories for your nodes: ++ +---- +apiVersion: v1 +kind: Secret +metadata: + name: subscription-manager +data: + username: + password: +---- ++ +* Replace `` with the applicable user name. +* Replace `` with the applicable password. + ++ +---- +apiVersion: v1 +kind: Secret +metadata: + name: redhat-registry +data: + username: + password: +---- ++ +* Replace `` with the applicable user name. +* Replace `` with the applicable password. + ++ +---- +apiVersion: dataplane.openstack.org/v1beta1 +kind: OpenStackDataPlaneNodeSet +metadata: + name: openstack-edpm-ipam +spec: + preProvisioned: True + ... + nodeTemplate: + ansible: + ... + ansibleVars: + edpm_bootstrap_command: | + subscription-manager register --username {{ subscription_manager_username }} --password {{ subscription_manager_password }} + subscription-manager release --set=9.2 + subscription-manager repos --disable=* + subscription-manager repos --enable=rhel-9-for-x86_64-baseos-eus-rpms --enable=rhel-9-for-x86_64-appstream-eus-rpms --enable=rhel-9-for-x86_64-highavailability-eus-rpms --enable=openstack-17.1-for-rhel-9-x86_64-rpms --enable=fast-datapath-for-rhel-9-x86_64-rpms --enable=openstack-dev-preview-for-rhel-9-x86_64-rpms + podman login -u {{ registry_username }} -p {{ registry_password }} registry.redhat.io + ansibleVarsFrom: + - prefix: subscription_manager_ + secretRef: + name: subscription-manager + - prefix: registry_ + secretRef: + name: redhat-registry +---- ++ +For a complete list of the Red Hat Customer Portal registration commands, see https://access.redhat.com/solutions/253273. For information about how to log into `registry.redhat.io`, see https://access.redhat.com/RegistryAuthentication#creating-registry-service-accounts-6. +endif::[] . If your nodes are bare metal, you must configure the bare metal template, see xref:con_provisioning-bare-metal-data-plane-nodes_{context}[Provisioning bare metal data plane nodes]. . Optional: The sample `OpenStackDataPlaneNodeSet` CR you copied includes default node configurations under the `nodes` section. You can add additional nodes, and edit the configured values as required. For example, to add node-specific Ansible variables that customize the node, add the following configuration to your `openstack-edpm.yaml` file: diff --git a/examples/base/crs/openstackdataplanenodeset.yaml b/examples/base/crs/openstackdataplanenodeset.yaml index da417c850..d86bdf830 100644 --- a/examples/base/crs/openstackdataplanenodeset.yaml +++ b/examples/base/crs/openstackdataplanenodeset.yaml @@ -44,54 +44,27 @@ spec: nodeTemplate: ansibleSSHPrivateKeySecret: dataplane-ansible-ssh-private-key-secret ansible: + ansibleVarsFrom: + - prefix: edpm_ + configMapRef: + name: network-config-template + - prefix: neutron_ + configMapRef: + name: neutron-edpm + # CHANGEME -- see https://access.redhat.com/solutions/253273 + # - prefix: subscription_manager_ + # secretRef: + # name: subscription-manager + # - prefix: registry_ + # secretRef: + # name: redhat-registry ansibleVars: # CHANGEME -- see https://access.redhat.com/solutions/253273 # edpm_bootstrap_command: | - # subscription-manager register --username --password - # podman login -u -p registry.redhat.io - edpm_network_config_template: | - --- - {% set mtu_list = [ctlplane_mtu] %} - {% for network in role_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 role_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 %} - - # 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 - # edpm_nodes_validation + # subscription-manager register --username {{ subscription_manager_username }} --password {{ subscription_manager_password }} + # podman login -u {{ registry_username }} -p {{ registry_password }} registry.redhat.io 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/examples/base/kustomization.yaml b/examples/base/kustomization.yaml index 564293f80..28b6208e5 100644 --- a/examples/base/kustomization.yaml +++ b/examples/base/kustomization.yaml @@ -4,6 +4,8 @@ kind: Component resources: - crs/openstackdataplanenodeset.yaml - crs/openstackdataplanedeployment.yaml +- vars/nic-config.yaml +- vars/neutron.yaml namespace: openstack diff --git a/examples/base/vars/neutron.yaml b/examples/base/vars/neutron.yaml new file mode 100644 index 000000000..8c21d8fa0 --- /dev/null +++ b/examples/base/vars/neutron.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: neutron-edpm +data: + physical_bridge_name: br-ex + public_interface_name: eth0 diff --git a/examples/base/vars/nic-config.yaml b/examples/base/vars/nic-config.yaml new file mode 100644 index 000000000..f210e0de7 --- /dev/null +++ b/examples/base/vars/nic-config.yaml @@ -0,0 +1,37 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: network-config-template +data: + network_config_template: | + --- + {% set mtu_list = [ctlplane_mtu] %} + {% for network in role_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 role_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 %} diff --git a/examples/bgp/values.yaml b/examples/bgp/values.yaml index fb5439e1b..116de7c0e 100644 --- a/examples/bgp/values.yaml +++ b/examples/bgp/values.yaml @@ -12,8 +12,8 @@ data: vars: # CHANGEME -- see https://access.redhat.com/solutions/253273 # edpm_bootstrap_command: | - # subscription-manager register --username --password - # podman login -u -p registry.redhat.io + # subscription-manager register --username {{ subscription_manager_username }} --password {{ subscription_manager_password }} + # podman login -u {{ registry_username }} -p {{ registry_password }} registry.redhat.io timesync_ntp_servers: - hostname: pool.ntp.org # edpm_network_config diff --git a/examples/bgp_ovn_cluster/values.yaml b/examples/bgp_ovn_cluster/values.yaml index 1e89f9aad..43069e82f 100644 --- a/examples/bgp_ovn_cluster/values.yaml +++ b/examples/bgp_ovn_cluster/values.yaml @@ -12,8 +12,8 @@ data: vars: # CHANGEME -- see https://access.redhat.com/solutions/253273 # edpm_bootstrap_command: | - # subscription-manager register --username --password - # podman login -u -p registry.redhat.io + # subscription-manager register --username {{ subscription_manager_username }} --password {{ subscription_manager_password }} + # podman login -u {{ registry_username }} -p {{ registry_password }} registry.redhat.io timesync_ntp_servers: - hostname: pool.ntp.org # edpm_network_config diff --git a/examples/customnetworks/values.yaml b/examples/customnetworks/values.yaml index 36d656dd1..19f2a8b43 100644 --- a/examples/customnetworks/values.yaml +++ b/examples/customnetworks/values.yaml @@ -12,8 +12,8 @@ data: vars: # CHANGEME -- see https://access.redhat.com/solutions/253273 # edpm_bootstrap_command: | - # subscription-manager register --username --password - # podman login -u -p registry.redhat.io + # subscription-manager register --username {{ subscription_manager_username }} --password {{ subscription_manager_password }} + # podman login -u {{ registry_username }} -p {{ registry_password }} registry.redhat.io neutron_public_interface_name: enp7s0 ctlplane_dns_nameservers: diff --git a/examples/networker/values.yaml b/examples/networker/values.yaml index f83713705..64dd24f47 100644 --- a/examples/networker/values.yaml +++ b/examples/networker/values.yaml @@ -12,8 +12,8 @@ data: vars: # CHANGEME -- see https://access.redhat.com/solutions/253273 # edpm_bootstrap_command: | - # subscription-manager register --username --password - # podman login -u -p registry.redhat.io + # subscription-manager register --username {{ subscription_manager_username }} --password {{ subscription_manager_password }} + # podman login -u {{ registry_username }} -p {{ registry_password }} registry.redhat.io edpm_enable_chassis_gw: true nodes: edpm-networker-0: diff --git a/examples/nmstate/values.yaml b/examples/nmstate/values.yaml index 743deb30e..05bfd089a 100644 --- a/examples/nmstate/values.yaml +++ b/examples/nmstate/values.yaml @@ -12,8 +12,8 @@ data: vars: # CHANGEME -- see https://access.redhat.com/solutions/253273 # edpm_bootstrap_command: | - # subscription-manager register --username --password - # podman login -u -p registry.redhat.io + # subscription-manager register --username {{ subscription_manager_username }} --password {{ subscription_manager_password }} + # podman login -u {{ registry_username }} -p {{ registry_password }} registry.redhat.io edpm_network_config_hide_sensitive_logs: false edpm_network_config_template: | --- diff --git a/examples/ovs_dpdk/values.yaml b/examples/ovs_dpdk/values.yaml index fe118d2b6..6bb6c9ed9 100644 --- a/examples/ovs_dpdk/values.yaml +++ b/examples/ovs_dpdk/values.yaml @@ -18,8 +18,8 @@ data: vars: # CHANGEME -- see https://access.redhat.com/solutions/253273 # edpm_bootstrap_command: | - # subscription-manager register --username --password - # podman login -u -p registry.redhat.io + # subscription-manager register --username {{ subscription_manager_username }} --password {{ subscription_manager_password }} + # podman login -u {{ registry_username }} -p {{ registry_password }} registry.redhat.io edpm_network_config_hide_sensitive_logs: false edpm_network_config_template: | --- diff --git a/examples/post_ceph_hci/values.yaml b/examples/post_ceph_hci/values.yaml index 13d6b6580..56eb78056 100644 --- a/examples/post_ceph_hci/values.yaml +++ b/examples/post_ceph_hci/values.yaml @@ -14,8 +14,8 @@ data: - hostname: clock.redhat.com # CHANGEME -- see https://access.redhat.com/solutions/253273 # edpm_bootstrap_command: | - # subscription-manager register --username --password - # podman login -u -p registry.redhat.io + # subscription-manager register --username {{ subscription_manager_username }} --password {{ subscription_manager_password }} + # podman login -u {{ registry_username }} -p {{ registry_password }} registry.redhat.io edpm_iscsid_image: '{{ registry_url }}/openstack-iscsid:{{ image_tag }}' edpm_logrotate_crond_image: '{{ registry_url }}/openstack-cron:{{ image_tag }}' edpm_network_config_hide_sensitive_logs: false diff --git a/examples/pre_ceph_hci/values.yaml b/examples/pre_ceph_hci/values.yaml index 8ca589c39..83b6534a2 100644 --- a/examples/pre_ceph_hci/values.yaml +++ b/examples/pre_ceph_hci/values.yaml @@ -14,8 +14,8 @@ data: - hostname: clock.redhat.com # CHANGEME -- see https://access.redhat.com/solutions/253273 # edpm_bootstrap_command: | - # subscription-manager register --username --password - # podman login -u -p registry.redhat.io + # subscription-manager register --username {{ subscription_manager_username }} --password {{ subscription_manager_password }} + # podman login -u {{ registry_username }} -p {{ registry_password }} registry.redhat.io edpm_iscsid_image: '{{ registry_url }}/openstack-iscsid:{{ image_tag }}' edpm_logrotate_crond_image: '{{ registry_url }}/openstack-cron:{{ image_tag }}' edpm_network_config_hide_sensitive_logs: false diff --git a/pkg/deployment/inventory.go b/pkg/deployment/inventory.go index a7c9aae0f..7e866c2be 100644 --- a/pkg/deployment/inventory.go +++ b/pkg/deployment/inventory.go @@ -25,6 +25,9 @@ import ( "strings" yaml "gopkg.in/yaml.v3" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/types" dataplanev1 "github.com/openstack-k8s-operators/dataplane-operator/api/v1beta1" infranetworkv1 "github.com/openstack-k8s-operators/infra-operator/apis/network/v1beta1" @@ -34,13 +37,93 @@ import ( utils "github.com/openstack-k8s-operators/lib-common/modules/common/util" ) +// getAnsibleVarsFrom gets ansible vars from ConfigMap/Secret +func getAnsibleVarsFrom(ctx context.Context, helper *helper.Helper, namespace string, ansible *dataplanev1.AnsibleOpts) (map[string]string, error) { + + var ( + configMaps = make(map[string]*v1.ConfigMap) + secrets = make(map[string]*v1.Secret) + result = make(map[string]string) + ) + client := helper.GetClient() + + // AnsibleVars will override AnsibleVarsFrom variables. + // Process AnsibleVarsFrom first then allow AnsibleVars to replace existing values. + for _, varFrom := range ansible.AnsibleVarsFrom { + switch { + case varFrom.ConfigMapRef != nil: + cm := varFrom.ConfigMapRef + name := cm.Name + configMap, ok := configMaps[name] + if !ok { + optional := cm.Optional != nil && *cm.Optional + configMap = &v1.ConfigMap{} + err := client.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, configMap) + if err != nil { + if errors.IsNotFound(err) && optional { + // ignore error when marked optional + utils.LogErrorForObject(helper, err, "could not get ansible vars, the configMap: "+name+"is missing", configMap) + continue + } + return result, err + } + configMaps[name] = configMap + } + + for k, v := range configMap.Data { + if len(varFrom.Prefix) > 0 { + k = varFrom.Prefix + k + } + + result[k] = v + } + + case varFrom.SecretRef != nil: + s := varFrom.SecretRef + name := s.Name + secret, ok := secrets[name] + if !ok { + optional := s.Optional != nil && *s.Optional + secret = &v1.Secret{} + err := client.Get(ctx, types.NamespacedName{Name: name, Namespace: namespace}, secret) + if err != nil { + if errors.IsNotFound(err) && optional { + // ignore error when marked optional + utils.LogErrorForObject(helper, err, "could not get ansible vars, the secret: "+name+"is missing", secret) + continue + } + return result, err + } + secrets[name] = secret + } + + for k, v := range secret.Data { + if len(varFrom.Prefix) > 0 { + k = varFrom.Prefix + k + } + result[k] = string(v) + } + } + } + + return result, nil +} + // GenerateNodeSetInventory yields a parsed Inventory for role func GenerateNodeSetInventory(ctx context.Context, helper *helper.Helper, instance *dataplanev1.OpenStackDataPlaneNodeSet, allIPSets map[string]infranetworkv1.IPSet, dnsAddresses []string, defaultImages dataplanev1.DataplaneAnsibleImageDefaults) (string, error) { inventory := ansible.MakeInventory() nodeSetGroup := inventory.AddGroup(instance.Name) - err := resolveGroupAnsibleVars(&instance.Spec.NodeTemplate, &nodeSetGroup, defaultImages) + groupVars, err := getAnsibleVarsFrom(ctx, helper, instance.Namespace, &instance.Spec.NodeTemplate.Ansible) + if err != nil { + utils.LogErrorForObject(helper, err, "could not get ansible group vars from configMap/secret", instance) + return "", err + } + for k, v := range groupVars { + nodeSetGroup.Vars[k] = v + } + err = resolveGroupAnsibleVars(&instance.Spec.NodeTemplate, &nodeSetGroup, defaultImages) if err != nil { utils.LogErrorForObject(helper, err, "Could not resolve ansible group vars", instance) return "", err @@ -58,6 +141,14 @@ func GenerateNodeSetInventory(ctx context.Context, helper *helper.Helper, for _, node := range instance.Spec.Nodes { host := nodeSetGroup.AddHost(strings.Split(node.HostName, ".")[0]) + hostVars, err := getAnsibleVarsFrom(ctx, helper, instance.Namespace, &node.Ansible) + if err != nil { + utils.LogErrorForObject(helper, err, "could not get ansible host vars from configMap/secret", instance) + return "", err + } + for k, v := range hostVars { + host.Vars[k] = v + } // Use ansible_host if provided else use hostname. Fall back to // nodeName if all else fails. if node.Ansible.AnsibleHost != "" {