├── docs ├── images │ └── .gitkeep ├── OWNERS ├── assemblies │ ├── updating-the-data-plane.adoc │ ├── hotfixing-the-data-plane.adoc │ └── proc_hotfixing-the-data-plane-rpm-content.adoc ├── index.html └── dataplane.adoc ├── config ├── manager │ └── kustomization.yaml ├── network-policy │ ├── kustomization.yaml │ ├── allow-metrics-traffic.yaml │ └── allow-webhook-traffic.yaml ├── samples │ ├── core_v1beta1_openstackcontrolplane.yaml │ ├── dataplane │ │ ├── nova_cell_custom │ │ │ ├── nova-extra.conf │ │ │ ├── servicename.yaml │ │ │ └── kustomization.yaml │ │ ├── preprovisioned │ │ │ └── kustomization.yaml │ │ ├── README.md │ │ ├── base │ │ │ ├── config │ │ │ │ ├── nodesetname.yaml │ │ │ │ └── varsfromname.yaml │ │ │ ├── kustomization.yaml │ │ │ └── files │ │ │ │ └── nic-config.j2 │ │ ├── sriov │ │ │ ├── values.yaml │ │ │ └── kustomization.yaml │ │ ├── customnetworks │ │ │ └── values.yaml │ │ ├── nmstate │ │ │ └── kustomization.yaml │ │ ├── baremetal │ │ │ └── values.yaml │ │ ├── networker │ │ │ ├── kustomization.yaml │ │ │ └── values.yaml │ │ ├── bgp │ │ │ └── kustomization.yaml │ │ ├── bgp_ovn_cluster │ │ │ └── kustomization.yaml │ │ ├── swift │ │ │ └── kustomization.yaml │ │ ├── ceph │ │ │ └── values.yaml │ │ ├── no_vars_from │ │ │ └── kustomization.yaml │ │ └── pre_ceph_hci │ │ │ └── kustomization.yaml │ ├── core_v1beta1_openstackversion_empty.yaml │ ├── tls │ │ ├── custom_ca │ │ │ ├── patch.yaml │ │ │ └── kustomization.yaml │ │ ├── tls_ingress │ │ │ ├── patch.yaml │ │ │ └── kustomization.yaml │ │ ├── custom_duration │ │ │ ├── kustomization.yaml │ │ │ └── patch.yaml │ │ ├── custom_issuers │ │ │ ├── kustomization.yaml │ │ │ └── patch.yaml │ │ └── custom_route_cert │ │ │ ├── patch.yaml │ │ │ └── kustomization.yaml │ ├── client_v1beta1_openstackclient_empty.yaml │ ├── core_v1beta1_openstackcontrolplane_empty.yaml │ ├── nodeselectors │ │ └── global │ │ │ ├── patch.yaml │ │ │ └── kustomization.yaml │ ├── dataplane_v1beta1_openstackdataplanedeployment.yaml │ ├── dataplane_v1beta1_openstackdataplanenodeset_empty.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_empty.yaml │ ├── dataplane_v1beta1_openstackdataplanedeployment_empty.yaml │ ├── base │ │ └── openstackcontrolplane │ │ │ └── kustomization.yaml │ ├── nad_datacentre.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice.yaml │ ├── operator_v1beta1_openstack.yaml │ ├── core_v1beta1_openstackversion.yaml │ ├── kustomization.yaml │ └── nic-config-samples │ │ ├── single_nic_vlans │ │ ├── single_nic_vlans_bgp.j2 │ │ ├── single_nic_vlans_storage.j2 │ │ ├── single_nic_vlans.j2 │ │ └── controller_no_external.j2 │ │ ├── bonds_vlans │ │ ├── bonds_vlans_storage.j2 │ │ ├── bonds_vlans.j2 │ │ └── controller_no_external.j2 │ │ └── multiple_nics │ │ └── multiple_nics.j2 ├── webhook │ ├── kustomization.yaml │ ├── service.yaml │ └── kustomizeconfig.yaml ├── certmanager │ ├── kustomization.yaml │ ├── kustomizeconfig.yaml │ ├── issuer.yaml │ ├── certificate-webhook.yaml │ └── certificate-metrics.yaml ├── scorecard │ ├── bases │ │ └── config.yaml │ ├── patches │ │ ├── basic.config.yaml │ │ └── olm.config.yaml │ └── kustomization.yaml ├── default │ ├── manager_metrics_patch.yaml │ ├── metrics_service.yaml │ ├── cert_metrics_manager_patch.yaml │ └── manager_webhook_patch.yaml ├── rbac │ ├── metrics_reader_role.yaml │ ├── service_account.yaml │ ├── metrics_auth_role_binding.yaml │ ├── metrics_auth_role.yaml │ ├── role_binding.yaml │ ├── leader_election_role_binding.yaml │ ├── leader_election_role.yaml │ ├── operator_openstack_admin_role.yaml │ ├── core_openstackversion_admin_role.yaml │ ├── client_openstackclient_admin_role.yaml │ ├── core_openstackcontrolplane_admin_role.yaml │ ├── operator_openstack_viewer_role.yaml │ ├── core_openstackversion_viewer_role.yaml │ ├── client_openstackclient_viewer_role.yaml │ ├── core_openstackcontrolplane_viewer_role.yaml │ ├── dataplane_openstackdataplanenodeset_admin_role.yaml │ ├── dataplane_openstackdataplaneservice_admin_role.yaml │ ├── dataplane_openstackdataplanedeployment_admin_role.yaml │ ├── operator_openstack_editor_role.yaml │ ├── core_openstackversion_editor_role.yaml │ ├── client_openstackclient_editor_role.yaml │ ├── dataplane_openstackdataplanenodeset_viewer_role.yaml │ ├── dataplane_openstackdataplaneservice_viewer_role.yaml │ ├── core_openstackcontrolplane_editor_role.yaml │ ├── dataplane_openstackdataplanedeployment_viewer_role.yaml │ ├── dataplane_openstackdataplanenodeset_editor_role.yaml │ ├── dataplane_openstackdataplaneservice_editor_role.yaml │ └── dataplane_openstackdataplanedeployment_editor_role.yaml ├── operator │ ├── rbac │ │ ├── metrics_reader_role.yaml │ │ ├── service_account.yaml │ │ ├── metrics_auth_role.yaml │ │ ├── metrics_auth_role_binding.yaml │ │ ├── role_binding.yaml │ │ ├── leader_election_role_binding.yaml │ │ ├── leader_election_role.yaml │ │ └── kustomization.yaml │ ├── deployment │ │ ├── controller_operator_config.yaml │ │ └── kustomization.yaml │ ├── kustomization.yaml │ └── manifests │ │ └── kustomization.yaml ├── services │ ├── dataplane_v1beta1_openstackdataplaneservice_redhat.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_update.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_os_reboot.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_install_os.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_ceph_client.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_ceph_hci_pre.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_configure_os.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_update_system.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_download_cache.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_update_services.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_validate_network.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_bootstrap.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_configure_network.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_configure_ovs_dpdk.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_fips_status.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_frr.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_ddp_package_option.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_install_certs.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_derive_pci_devicespec.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_ssh_known_hosts.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_run_os.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_logging.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_swift.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_neutron_dhcp.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_neutron_sriov.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_telemetry.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_nova.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_telemetry_power_monitoring.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_ovn.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_neutron_ovn.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_libvirt.yaml │ ├── dataplane_v1beta1_openstackdataplaneservice_ovn_bgp_agent.yaml │ └── dataplane_v1beta1_openstackdataplaneservice_neutron_metadata.yaml ├── prometheus │ ├── kustomization.yaml │ ├── monitor_tls_patch.yaml │ └── monitor.yaml ├── crd │ ├── kustomizeconfig.yaml │ └── kustomization.yaml └── manifests │ └── kustomization.yaml ├── test └── kuttl │ ├── tests │ ├── ctlplane-collapsed │ │ ├── 02-errors-cleanup.yaml │ │ ├── 00-deps.yaml │ │ ├── 01-deploy-openstack-collapsed-cell.yaml │ │ └── 02-cleanup.yaml │ ├── ctlplane-basic-deployment │ │ ├── 05-errors-cleanup.yaml │ │ ├── 01-assert-deploy-openstack.yaml │ │ ├── 02-assert-custom-cacert-secret.yaml │ │ ├── 01-deploy-openstack.yaml │ │ ├── 02-deploy-custom-cacert-secret.yaml │ │ ├── 03-deploy-custom-cacert.yaml │ │ ├── 05-cleanup.yaml │ │ └── 04-assert-custom-cacert.yaml │ ├── ctlplane-galera-3replicas │ │ ├── 02-errors-cleanup.yaml │ │ ├── 01-deploy-galera-3replicas.yaml │ │ └── 02-cleanup.yaml │ ├── ctlplane-nodeselectors │ │ ├── 05-errors-cleanup.yaml │ │ ├── 01-assert-deploy-openstack.yaml │ │ ├── 03-assert-deploy-openstack.yaml │ │ ├── 01-deploy-openstack.yaml │ │ ├── 03-update-nodeselector.yaml │ │ ├── 05-cleanup.yaml │ │ ├── 02-assert-nodeselector.yaml │ │ └── 04-assert-nodeselector.yaml │ ├── ctlplane-tls-cert-rotation │ │ ├── 05-errors-cleanup.yaml │ │ ├── 01-assert-deploy-openstack.yaml │ │ ├── 01-deploy-openstack.yaml │ │ ├── 00-deploy-openstack-tls-ingress-only.yaml │ │ ├── 03-change-cert-duration.yaml │ │ ├── 02-get-endpoints-certs.yaml │ │ ├── 05-cleanup.yaml │ │ ├── 04-assert-service-cert-rotation.yaml │ │ └── 02-assert-endpoint-proto.yaml │ ├── ctlplane-tls-custom-route │ │ ├── 05-errors-cleanup.yaml │ │ ├── 01-assert-deploy-openstack.yaml │ │ ├── 01-deploy-openstack.yaml │ │ ├── 04-errors-cleanup.yaml │ │ ├── 03-deploy-openstack.yaml │ │ ├── 02-assert-custom-route-secret.yaml │ │ ├── 02-deploy-custom-route-secret.yaml │ │ ├── 04-assert-custom-route-cert.yaml │ │ └── 05-cleanup.yaml │ ├── ctlplane-tls-custom-issuers │ │ ├── 05-errors-cleanup.yaml │ │ ├── 11-errors-cleanup.yaml │ │ ├── 03-assert-deploy-openstack.yaml │ │ ├── 06-assert-deploy-openstack.yaml │ │ ├── 01-deploy-openstack.yaml │ │ ├── 09-deploy-openstack.yaml │ │ ├── 00-deploy-custom-issuers.yaml │ │ ├── 08-deploy-custom-issuers.yaml │ │ ├── 03-deploy-openstack.yaml │ │ ├── 06-deploy-openstack.yaml │ │ ├── 04-rotate-service-certs.yaml │ │ ├── 10-rotate-service-certs.yaml │ │ ├── 00-assert-custom-issuers.yaml │ │ ├── 08-assert-custom-issuers.yaml │ │ ├── 05-cleanup.yaml │ │ ├── 11-cleanup.yaml │ │ ├── 02-assert-service-certs-issuers.yaml │ │ ├── 07-assert-service-certs-default-issuers.yaml │ │ ├── 04-assert-service-certs-default-issuers.yaml │ │ └── 10-assert-service-certs-issuers.yaml │ ├── ctlplane-basic-deployment-with-nicMappings │ │ ├── 02-assert-deploy-openstack.yaml │ │ ├── 01-create-nic-mappings.yaml │ │ ├── 02-deploy-openstack.yaml │ │ ├── 03-assert.yaml │ │ ├── 04-remove-ovn-nic-mappings.yaml │ │ ├── 03-add-ovn-nic-mappings.yaml │ │ ├── 05-cleanup.yaml │ │ └── 04-assert.yaml │ ├── dataplane-deploy-tls-test │ │ ├── 02-dataplane-deploy.yaml │ │ ├── 04-rotate-certs.yaml │ │ ├── 05-dataplane-redeploy.yaml │ │ ├── 01-create-cert-issuers.yaml │ │ ├── certs.yaml │ │ └── 05-assert.yaml │ ├── dataplane-deploy-global-service-test │ │ ├── 01-dataplane-deploy.yaml │ │ └── 02-add-nodeset.yaml │ ├── dataplane-deploy-no-nodes-test │ │ ├── 01-dataplane-deploy.yaml │ │ ├── 04-dataplane-deploy.yaml │ │ ├── 05-dataplane-deploy-service-not-found.yaml │ │ ├── 07-dataplane-deploy-node-selector.yaml │ │ ├── 03-update-ovn-cm.yaml │ │ ├── 02-dataplane-deploy-services-override.yaml │ │ └── 06-add-nodeset.yaml │ ├── dataplane-deploy-multiple-secrets │ │ ├── 02-dataplane-deploy.yaml │ │ ├── 01-create-cert-issuers.yaml │ │ └── certs.yaml │ ├── dataplane-multinode-nodeset-create-test │ │ └── 01-dataplane-scale-in.yaml │ ├── dataplane-service-custom-image │ │ └── 00-dataplane-create.yaml │ ├── dataplane-service-failure │ │ └── 00-create.yaml │ └── dataplane-extramounts │ │ └── 00-dataplane-create.yaml │ └── common │ ├── rhobs.yaml │ ├── custom-ingress-issuer.yaml │ ├── custom-internal-issuer.yaml │ ├── osp_endpoint_fingerprints.sh │ ├── osp_check_fingerprints.sh │ ├── custom-ca.yaml │ └── osp_check_route_cert.sh ├── .prow_ci.env ├── .ci-operator.yaml ├── .dockerignore ├── OWNERS ├── Gemfile ├── .golangci.yaml ├── .github └── workflows │ ├── release-branch-sync.yaml │ ├── crd-sync-check-olive.yaml │ ├── lints.yaml │ ├── force-bump-pr-manual.yaml │ ├── force-bump-pr-scheduled.yaml │ ├── build-openstack-operator.yaml │ ├── kustom.yaml │ ├── crd-sync-check.yaml │ └── release-openstack-operator.yaml ├── OWNERS_ALIASES ├── hack ├── build-crd-schema-checker.sh ├── boilerplate.go.txt ├── fake_minor_update.sh ├── crd-schema-checker.sh ├── clean_local_webhook.sh └── catalog-build-olm-upgrade.sh ├── zuul.d └── projects.yaml ├── api ├── dataplane │ └── v1beta1 │ │ ├── const.go │ │ ├── openstackdataplanenodeset.go │ │ └── groupversion_info.go ├── core │ └── v1beta1 │ │ ├── webhook_suite_test.go │ │ └── groupversion_info.go ├── client │ └── v1beta1 │ │ └── groupversion_info.go └── operator │ └── v1beta1 │ └── groupversion_info.go ├── renovate.json ├── .gitignore └── kuttl-test.yaml /docs/images/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manager.yaml 3 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-collapsed/02-errors-cleanup.yaml: -------------------------------------------------------------------------------- 1 | ../../common/errors_cleanup_openstack.yaml -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-basic-deployment/05-errors-cleanup.yaml: -------------------------------------------------------------------------------- 1 | ../../common/errors_cleanup_openstack.yaml -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-galera-3replicas/02-errors-cleanup.yaml: -------------------------------------------------------------------------------- 1 | ../../common/errors_cleanup_openstack.yaml -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-nodeselectors/05-errors-cleanup.yaml: -------------------------------------------------------------------------------- 1 | ../../common/errors_cleanup_openstack.yaml -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-cert-rotation/05-errors-cleanup.yaml: -------------------------------------------------------------------------------- 1 | ../../common/errors_cleanup_openstack.yaml -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-route/05-errors-cleanup.yaml: -------------------------------------------------------------------------------- 1 | ../../common/errors_cleanup_openstack.yaml -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-nodeselectors/01-assert-deploy-openstack.yaml: -------------------------------------------------------------------------------- 1 | ../../common/assert-sample-deployment.yaml -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-nodeselectors/03-assert-deploy-openstack.yaml: -------------------------------------------------------------------------------- 1 | ../../common/assert-sample-deployment.yaml -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/05-errors-cleanup.yaml: -------------------------------------------------------------------------------- 1 | ../../common/errors_cleanup_openstack.yaml -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/11-errors-cleanup.yaml: -------------------------------------------------------------------------------- 1 | ../../common/errors_cleanup_openstack.yaml -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-basic-deployment/01-assert-deploy-openstack.yaml: -------------------------------------------------------------------------------- 1 | ../../common/assert-sample-deployment.yaml -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-cert-rotation/01-assert-deploy-openstack.yaml: -------------------------------------------------------------------------------- 1 | ../../common/assert-sample-deployment.yaml -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/03-assert-deploy-openstack.yaml: -------------------------------------------------------------------------------- 1 | ../../common/assert-sample-deployment.yaml -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/06-assert-deploy-openstack.yaml: -------------------------------------------------------------------------------- 1 | ../../common/assert-sample-deployment.yaml -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-route/01-assert-deploy-openstack.yaml: -------------------------------------------------------------------------------- 1 | ../../common/assert-sample-deployment.yaml -------------------------------------------------------------------------------- /config/network-policy/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - allow-webhook-traffic.yaml 3 | - allow-metrics-traffic.yaml 4 | -------------------------------------------------------------------------------- /config/samples/core_v1beta1_openstackcontrolplane.yaml: -------------------------------------------------------------------------------- 1 | base/openstackcontrolplane/core_v1beta1_openstackcontrolplane.yaml -------------------------------------------------------------------------------- /.prow_ci.env: -------------------------------------------------------------------------------- 1 | export USE_IMAGE_DIGESTS=true 2 | export BUNDLE_DOCKERFILE=bundle.Dockerfile 3 | export FAIL_FIPS_CHECK=true 4 | -------------------------------------------------------------------------------- /config/samples/dataplane/nova_cell_custom/nova-extra.conf: -------------------------------------------------------------------------------- 1 | [compute] 2 | cpu_shared_set = 2,6 3 | cpu_dedicated_set = 1,3,5,7 4 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-basic-deployment-with-nicMappings/02-assert-deploy-openstack.yaml: -------------------------------------------------------------------------------- 1 | ../../common/assert-sample-deployment.yaml -------------------------------------------------------------------------------- /config/webhook/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manifests.yaml 3 | - service.yaml 4 | 5 | configurations: 6 | - kustomizeconfig.yaml 7 | -------------------------------------------------------------------------------- /.ci-operator.yaml: -------------------------------------------------------------------------------- 1 | build_root_image: 2 | name: tools 3 | namespace: openstack-k8s-operators 4 | tag: ci-build-root-golang-1.24-sdk-1.41.1 5 | -------------------------------------------------------------------------------- /docs/OWNERS: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs at https://go.k8s.io/owners 2 | approvers: 3 | - docs-approvers 4 | 5 | reviewers: 6 | - docs-approvers 7 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file 2 | # Ignore build and test binaries. 3 | bin/ 4 | testbin/ 5 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-basic-deployment/02-assert-custom-cacert-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: ca-custom-kuttl 5 | -------------------------------------------------------------------------------- /config/samples/core_v1beta1_openstackversion_empty.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: core.openstack.org/v1beta1 2 | kind: OpenStackVersion 3 | metadata: 4 | name: default 5 | spec: 6 | -------------------------------------------------------------------------------- /config/certmanager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - issuer.yaml 3 | - certificate-webhook.yaml 4 | - certificate-metrics.yaml 5 | 6 | configurations: 7 | - kustomizeconfig.yaml 8 | -------------------------------------------------------------------------------- /config/scorecard/bases/config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: scorecard.operatorframework.io/v1alpha3 2 | kind: Configuration 3 | metadata: 4 | name: config 5 | stages: 6 | - parallel: true 7 | tests: [] 8 | -------------------------------------------------------------------------------- /config/samples/dataplane/preprovisioned/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1alpha1 2 | kind: Component 3 | 4 | namespace: openstack 5 | nameSuffix: -ipam 6 | 7 | components: 8 | - ../base 9 | -------------------------------------------------------------------------------- /config/samples/tls/custom_ca/patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: core.openstack.org/v1beta1 2 | kind: OpenStackControlPlane 3 | metadata: 4 | name: openstack 5 | spec: 6 | tls: 7 | caBundleSecretName: ca-custom-kuttl 8 | -------------------------------------------------------------------------------- /config/samples/tls/tls_ingress/patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: core.openstack.org/v1beta1 2 | kind: OpenStackControlPlane 3 | metadata: 4 | name: openstack 5 | spec: 6 | tls: 7 | podLevel: 8 | enabled: false 9 | -------------------------------------------------------------------------------- /config/samples/client_v1beta1_openstackclient_empty.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: client.openstack.org/v1beta1 2 | kind: OpenStackClient 3 | metadata: 4 | name: default 5 | spec: 6 | # this is a placeholder and shall remain empty 7 | -------------------------------------------------------------------------------- /config/default/manager_metrics_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch adds the args to allow exposing the metrics endpoint using HTTPS 2 | - op: add 3 | path: /spec/template/spec/containers/0/args/0 4 | value: --metrics-bind-address=:8443 5 | -------------------------------------------------------------------------------- /config/rbac/metrics_reader_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: 7 | - "/metrics" 8 | verbs: 9 | - get 10 | -------------------------------------------------------------------------------- /config/samples/core_v1beta1_openstackcontrolplane_empty.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: core.openstack.org/v1beta1 2 | kind: OpenStackControlPlane 3 | metadata: 4 | name: default 5 | spec: 6 | # this is a placeholder and shall remain empty 7 | -------------------------------------------------------------------------------- /config/samples/nodeselectors/global/patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: core.openstack.org/v1beta1 2 | kind: OpenStackControlPlane 3 | metadata: 4 | name: openstack 5 | spec: 6 | nodeSelector: 7 | node-role.kubernetes.io/worker: "" 8 | -------------------------------------------------------------------------------- /config/samples/dataplane_v1beta1_openstackdataplanedeployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneDeployment 3 | metadata: 4 | name: edpm-deployment 5 | spec: 6 | nodeSets: 7 | - openstack-edpm 8 | -------------------------------------------------------------------------------- /config/samples/dataplane_v1beta1_openstackdataplanenodeset_empty.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneNodeSet 3 | metadata: 4 | name: default 5 | spec: 6 | # this is a placeholder and shall remain empty 7 | -------------------------------------------------------------------------------- /config/samples/dataplane_v1beta1_openstackdataplaneservice_empty.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: default 5 | spec: 6 | # this is a placeholder and shall remain empty 7 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-collapsed/00-deps.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | oc apply -f ../../common/rhobs.yaml 6 | until oc api-resources | grep -q rhobs; do sleep 1; done 7 | -------------------------------------------------------------------------------- /config/operator/rbac/metrics_reader_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader-operator 5 | rules: 6 | - nonResourceURLs: 7 | - "/metrics" 8 | verbs: 9 | - get 10 | -------------------------------------------------------------------------------- /config/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: openstack-operator 6 | app.kubernetes.io/managed-by: kustomize 7 | name: controller-manager 8 | namespace: system 9 | -------------------------------------------------------------------------------- /config/samples/dataplane_v1beta1_openstackdataplanedeployment_empty.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneDeployment 3 | metadata: 4 | name: default 5 | spec: 6 | # this is a placeholder and shall remain empty 7 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-basic-deployment-with-nicMappings/01-create-nic-mappings.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | oc apply -n $NAMESPACE -f ../../../../config/samples/nad_datacentre.yaml 6 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs at https://go.k8s.io/owners 2 | approvers: 3 | - ci-approvers 4 | - openstack-approvers 5 | - dataplane-approvers 6 | 7 | reviewers: 8 | - ci-approvers 9 | - openstack-approvers 10 | - dataplane-approvers 11 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_redhat.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: redhat 5 | spec: 6 | playbook: osp.edpm.redhat 7 | edpmServiceType: redhat 8 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_update.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: update 5 | spec: 6 | playbook: osp.edpm.update 7 | edpmServiceType: update 8 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-basic-deployment/01-deploy-openstack.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | oc kustomize ../../../../config/samples/base/openstackcontrolplane | oc apply -n $NAMESPACE -f - 6 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-cert-rotation/01-deploy-openstack.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | oc kustomize ../../../../config/samples/base/openstackcontrolplane | oc apply -n $NAMESPACE -f - 6 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-route/01-deploy-openstack.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | oc kustomize ../../../../config/samples/base/openstackcontrolplane | oc apply -n $NAMESPACE -f - 6 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-deploy-tls-test/02-dataplane-deploy.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: dataplane.openstack.org/v1beta1 3 | kind: OpenStackDataPlaneDeployment 4 | metadata: 5 | name: openstack-edpm-tls 6 | spec: 7 | nodeSets: 8 | - openstack-edpm-tls 9 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-cert-rotation/00-deploy-openstack-tls-ingress-only.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | oc kustomize ../../../../config/samples/tls/tls_ingress | oc apply -n $NAMESPACE -f - 6 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_os_reboot.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: reboot-os 5 | spec: 6 | playbook: osp.edpm.reboot 7 | edpmServiceType: reboot-os 8 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-deploy-tls-test/04-rotate-certs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - command: oc delete -n openstack-kuttl-tests secrets cert-custom-tls-dns-default-edpm-compute-0 cert-tls-dns-ips-default-edpm-compute-0 5 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_install_os.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: install-os 5 | spec: 6 | playbook: osp.edpm.install_os 7 | edpmServiceType: install-os 8 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-basic-deployment-with-nicMappings/02-deploy-openstack.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | oc kustomize ../../../../config/samples/base/openstackcontrolplane | oc apply -n $NAMESPACE -f - 6 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-collapsed/01-deploy-openstack-collapsed-cell.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | oc apply -n $NAMESPACE -f ../../../../config/samples/core_v1beta1_openstackcontrolplane_collapsed_cell.yaml 6 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-deploy-global-service-test/01-dataplane-deploy.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: dataplane.openstack.org/v1beta1 3 | kind: OpenStackDataPlaneDeployment 4 | metadata: 5 | name: edpm-compute-global 6 | spec: 7 | nodeSets: 8 | - edpm-compute-global 9 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_ceph_client.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: ceph-client 5 | spec: 6 | playbook: osp.edpm.ceph_client 7 | edpmServiceType: ceph-client 8 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-galera-3replicas/01-deploy-galera-3replicas.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | oc apply -n $NAMESPACE -f ../../../../config/samples/core_v1beta1_openstackcontrolplane_galera_3replicas.yaml 6 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-route/04-errors-cleanup.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: Certificate 3 | metadata: 4 | barbican-public-route 5 | --- 6 | apiVersion: cert-manager.io/v1 7 | kind: Certificate 8 | metadata: 9 | placement-public-route 10 | -------------------------------------------------------------------------------- /config/operator/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: openstack-operator-controller-operator 6 | app.kubernetes.io/managed-by: kustomize 7 | name: controller-operator 8 | namespace: system 9 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_ceph_hci_pre.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: ceph-hci-pre 5 | spec: 6 | playbook: osp.edpm.ceph_hci_pre 7 | edpmServiceType: ceph-hci-pre 8 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_configure_os.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: configure-os 5 | spec: 6 | playbook: osp.edpm.configure_os 7 | edpmServiceType: configure-os 8 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_update_system.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: update-system 5 | spec: 6 | playbook: osp.edpm.update_system 7 | edpmServiceType: update-system 8 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'asciidoctor', '~> 2.0', '>= 2.0.20' 4 | 5 | # Uncomment for ability to render pdf: 6 | # gem 'asciidoctor-pdf', '~> 2.0', '>= 2.0.20' 7 | 8 | # Uncomment for ability to convert Markdown to AsciiDoc 9 | gem 'kramdown-asciidoc' 10 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_download_cache.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: download-cache 5 | spec: 6 | playbook: osp.edpm.download_cache 7 | edpmServiceType: download-cache 8 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_update_services.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: update-services 5 | spec: 6 | playbook: osp.edpm.update_services 7 | edpmServiceType: update-services 8 | -------------------------------------------------------------------------------- /config/certmanager/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This configuration is for teaching kustomize how to update name ref substitution 2 | nameReference: 3 | - kind: Issuer 4 | group: cert-manager.io 5 | fieldSpecs: 6 | - kind: Certificate 7 | group: cert-manager.io 8 | path: spec/issuerRef/name 9 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_validate_network.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: validate-network 5 | spec: 6 | playbook: osp.edpm.validate_network 7 | edpmServiceType: validate-network 8 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_bootstrap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: bootstrap 5 | spec: 6 | playbook: osp.edpm.bootstrap 7 | edpmServiceType: bootstrap 8 | caCerts: combined-ca-bundle 9 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_configure_network.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: configure-network 5 | spec: 6 | playbook: osp.edpm.configure_network 7 | edpmServiceType: configure-network 8 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_configure_ovs_dpdk.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: configure-ovs-dpdk 5 | spec: 6 | playbook: osp.edpm.configure_ovs_dpdk 7 | edpmServiceType: configure-ovs-dpdk 8 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_fips_status.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: fips-status 5 | spec: 6 | label: fips-status 7 | playbook: osp.edpm.fips_status 8 | edpmServiceType: fips-status 9 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_frr.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: frr 5 | spec: 6 | playbook: osp.edpm.frr 7 | containerImageFields: 8 | - EdpmFrrImage 9 | edpmServiceType: frr 10 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-basic-deployment/02-deploy-custom-cacert-secret.yaml: -------------------------------------------------------------------------------- 1 | # Deploys the custom CA to be added to the combined-ca-bundle by operator 2 | apiVersion: kuttl.dev/v1beta1 3 | kind: TestStep 4 | commands: 5 | - script: | 6 | oc apply -n $NAMESPACE -f ../../common/custom-ca.yaml 7 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/01-deploy-openstack.yaml: -------------------------------------------------------------------------------- 1 | # Deploy with custom internal and ingress issuers 2 | apiVersion: kuttl.dev/v1beta1 3 | kind: TestStep 4 | commands: 5 | - script: | 6 | oc kustomize ../../../../config/samples/tls/custom_issuers | oc apply -n $NAMESPACE -f - 7 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/09-deploy-openstack.yaml: -------------------------------------------------------------------------------- 1 | # Deploy with custom internal and ingress issuers 2 | apiVersion: kuttl.dev/v1beta1 3 | kind: TestStep 4 | commands: 5 | - script: | 6 | oc kustomize ../../../../config/samples/tls/custom_issuers | oc apply -n $NAMESPACE -f - 7 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/00-deploy-custom-issuers.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | oc apply -n $NAMESPACE -f ../../common/custom-internal-issuer.yaml 6 | oc apply -n $NAMESPACE -f ../../common/custom-ingress-issuer.yaml 7 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/08-deploy-custom-issuers.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | oc apply -n $NAMESPACE -f ../../common/custom-internal-issuer.yaml 6 | oc apply -n $NAMESPACE -f ../../common/custom-ingress-issuer.yaml 7 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_ddp_package_option.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: ddp-package-option 5 | spec: 6 | playbook: osp.edpm.select_kernel_ddp_package 7 | edpmServiceType: ddp-package-option 8 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_install_certs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: install-certs 5 | spec: 6 | playbook: osp.edpm.install_certs 7 | addCertMounts: True 8 | edpmServiceType: install-certs 9 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/03-deploy-openstack.yaml: -------------------------------------------------------------------------------- 1 | # Deploy with default internal and ingress issuers 2 | apiVersion: kuttl.dev/v1beta1 3 | kind: TestStep 4 | commands: 5 | - script: | 6 | oc kustomize ../../../../config/samples/base/openstackcontrolplane | oc apply -n $NAMESPACE -f - 7 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/06-deploy-openstack.yaml: -------------------------------------------------------------------------------- 1 | # Deploy with default internal and ingress issuers 2 | apiVersion: kuttl.dev/v1beta1 3 | kind: TestStep 4 | commands: 5 | - script: | 6 | oc kustomize ../../../../config/samples/base/openstackcontrolplane | oc apply -n $NAMESPACE -f - 7 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-deploy-no-nodes-test/01-dataplane-deploy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneDeployment 3 | metadata: 4 | name: edpm-compute-no-nodes 5 | spec: 6 | nodeSets: 7 | - edpm-compute-no-nodes 8 | ansibleExtraVars: 9 | foo: bar 10 | -------------------------------------------------------------------------------- /config/samples/base/openstackcontrolplane/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - core_v1beta1_openstackcontrolplane.yaml 3 | patches: 4 | - target: 5 | kind: OpenStackControlPlane 6 | name: .* 7 | patch: |- 8 | - op: replace 9 | path: /metadata/name 10 | value: openstack 11 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_derive_pci_devicespec.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: derive-pci-devicespec 5 | spec: 6 | playbook: osp.edpm.sriov_derive_device_spec 7 | edpmServiceType: derive-pci-devicespec 8 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-cert-rotation/03-change-cert-duration.yaml: -------------------------------------------------------------------------------- 1 | # Deploys with custom tls service certs and CA certs duration 2 | apiVersion: kuttl.dev/v1beta1 3 | kind: TestStep 4 | commands: 5 | - script: | 6 | oc kustomize ../../../../config/samples/tls/custom_duration | oc apply -n $NAMESPACE -f - 7 | -------------------------------------------------------------------------------- /config/scorecard/patches/basic.config.yaml: -------------------------------------------------------------------------------- 1 | - op: add 2 | path: /stages/0/tests/- 3 | value: 4 | entrypoint: 5 | - scorecard-test 6 | - basic-check-spec 7 | image: quay.io/operator-framework/scorecard-test:v1.41.1 8 | labels: 9 | suite: basic 10 | test: basic-check-spec-test 11 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_ssh_known_hosts.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: ssh-known-hosts 5 | spec: 6 | playbook: osp.edpm.ssh_known_hosts 7 | deployOnAllNodeSets: true 8 | edpmServiceType: ssh-known-hosts 9 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-basic-deployment/03-deploy-custom-cacert.yaml: -------------------------------------------------------------------------------- 1 | # Deploys the custom CA to be added to the combined-ca-bundle by operator 2 | apiVersion: kuttl.dev/v1beta1 3 | kind: TestStep 4 | commands: 5 | - script: | 6 | oc kustomize ../../../../config/samples/tls/custom_ca | oc apply -n $NAMESPACE -f - 7 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-deploy-multiple-secrets/02-dataplane-deploy.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: dataplane.openstack.org/v1beta1 3 | kind: OpenStackDataPlaneDeployment 4 | metadata: 5 | name: openstack-edpm-tls 6 | spec: 7 | nodeSets: 8 | - openstack-edpm-tls 9 | services: 10 | - generic-service1 11 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-deploy-no-nodes-test/04-dataplane-deploy.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneDeployment 3 | metadata: 4 | name: edpm-compute-no-nodes-updated-ovn-cm 5 | spec: 6 | nodeSets: 7 | - edpm-compute-no-nodes 8 | servicesOverride: 9 | - ovn 10 | -------------------------------------------------------------------------------- /.golangci.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | linters: 4 | # Enable specific linter 5 | # https://golangci-lint.run/usage/linters/#enabled-by-default 6 | enable: 7 | - errorlint 8 | - revive 9 | - ginkgolinter 10 | - govet 11 | 12 | formatters: 13 | enable: 14 | - gofmt 15 | 16 | run: 17 | timeout: 5m 18 | -------------------------------------------------------------------------------- /.github/workflows/release-branch-sync.yaml: -------------------------------------------------------------------------------- 1 | name: Release Branch sync 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | schedule: 8 | - cron: '0 * * * *' 9 | 10 | jobs: 11 | call-build-workflow: 12 | uses: openstack-k8s-operators/openstack-k8s-operators-ci/.github/workflows/release-branch-sync.yaml@main 13 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/04-rotate-service-certs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | echo "Deleting secrets..." 6 | oc get secret -l service-cert -n $NAMESPACE -o name > /tmp/deleted-secrets.txt 7 | oc delete secret -l service-cert -n $NAMESPACE 8 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/10-rotate-service-certs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | echo "Deleting secrets..." 6 | oc get secret -l service-cert -n $NAMESPACE -o name > /tmp/deleted-secrets.txt 7 | oc delete secret -l service-cert -n $NAMESPACE 8 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-route/03-deploy-openstack.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | # Apply OpenStackControlPlane with kustomize (ConfigMap was created in step 02) 6 | oc kustomize ../../../../config/samples/tls/custom_route_cert | oc apply -n $NAMESPACE -f - 7 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-multinode-nodeset-create-test/01-dataplane-scale-in.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | oc patch openstackdataplanenodeset/openstack-edpm-multinode -n openstack-kuttl-tests --type json --patch '[{ "op": "remove", "path": "/spec/nodes/edpm-compute-1" }]' 6 | -------------------------------------------------------------------------------- /config/samples/dataplane/README.md: -------------------------------------------------------------------------------- 1 | # Kustomize examples 2 | 3 | Requires [OpenShift CLI](https://docs.openshift.com/container-platform/4.14/cli_reference/openshift_cli/getting-started-cli.html#installing-openshift-cli) (oc) 4.14 or higher 4 | ``` 5 | oc kustomize --load-restrictor LoadRestrictionsNone config/samples/dataplane/ 6 | ``` 7 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-cert-rotation/02-get-endpoints-certs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | echo "Get fingerprints of all service certs" 6 | oc exec -i openstackclient -n $NAMESPACE -- bash -s < ../../common/osp_endpoint_fingerprints.sh > /tmp/endpoint_fingerprints_before 7 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_run_os.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: run-os 5 | spec: 6 | playbook: osp.edpm.run_os 7 | containerImageFields: 8 | - EdpmLogrotateCrondImage 9 | - EdpmIscsidImage 10 | edpmServiceType: run-os 11 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-basic-deployment-with-nicMappings/03-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | labels: 5 | service: ovn-controller 6 | status: 7 | phase: Running 8 | --- 9 | apiVersion: v1 10 | kind: Pod 11 | metadata: 12 | labels: 13 | service: ovn-controller-ovs 14 | status: 15 | phase: Running 16 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-route/02-assert-custom-route-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: barbican-custom-route 5 | --- 6 | apiVersion: v1 7 | kind: Secret 8 | metadata: 9 | name: placement-custom-route 10 | --- 11 | apiVersion: v1 12 | kind: ConfigMap 13 | metadata: 14 | name: placement-cert-data 15 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-nodeselectors/01-deploy-openstack.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | oc annotate namespace $NAMESPACE openshift.io/node-selector="beta.kubernetes.io/os=linux" 6 | - script: | 7 | oc kustomize ../../../../config/samples/nodeselectors/global | oc apply -n $NAMESPACE -f - 8 | -------------------------------------------------------------------------------- /config/operator/deployment/controller_operator_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 2 | kind: ControllerManagerConfig 3 | health: 4 | healthProbeBindAddress: :8081 5 | metrics: 6 | bindAddress: 127.0.0.1:8080 7 | webhook: 8 | port: 9443 9 | leaderElection: 10 | leaderElect: true 11 | resourceName: 20ca801f.openstack.org 12 | -------------------------------------------------------------------------------- /config/samples/tls/custom_ca/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../../base/openstackcontrolplane 3 | 4 | patches: 5 | - target: 6 | kind: OpenStackControlPlane 7 | name: .* 8 | patch: |- 9 | - op: replace 10 | path: /metadata/name 11 | value: openstack 12 | - target: 13 | kind: OpenStackControlPlane 14 | path: patch.yaml 15 | -------------------------------------------------------------------------------- /config/samples/tls/tls_ingress/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../../base/openstackcontrolplane 3 | 4 | patches: 5 | - target: 6 | kind: OpenStackControlPlane 7 | name: .* 8 | patch: |- 9 | - op: replace 10 | path: /metadata/name 11 | value: openstack 12 | - target: 13 | kind: OpenStackControlPlane 14 | path: patch.yaml 15 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_logging.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: logging 5 | spec: 6 | dataSources: 7 | - secretRef: 8 | name: logging-compute-config-data 9 | playbook: osp.edpm.telemetry_logging 10 | edpmServiceType: logging 11 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-deploy-tls-test/05-dataplane-redeploy.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: dataplane.openstack.org/v1beta1 3 | kind: OpenStackDataPlaneDeployment 4 | metadata: 5 | name: certs-refresh 6 | spec: 7 | nodeSets: 8 | - openstack-edpm-tls 9 | servicesOverride: 10 | - install-certs-ovrd 11 | - tls-dns-ips 12 | - custom-tls-dns 13 | -------------------------------------------------------------------------------- /config/samples/nodeselectors/global/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../../base/openstackcontrolplane 3 | 4 | patches: 5 | - target: 6 | kind: OpenStackControlPlane 7 | name: .* 8 | patch: |- 9 | - op: replace 10 | path: /metadata/name 11 | value: openstack 12 | - target: 13 | kind: OpenStackControlPlane 14 | path: patch.yaml 15 | -------------------------------------------------------------------------------- /config/samples/tls/custom_duration/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../../base/openstackcontrolplane 3 | 4 | patches: 5 | - target: 6 | kind: OpenStackControlPlane 7 | name: .* 8 | patch: |- 9 | - op: replace 10 | path: /metadata/name 11 | value: openstack 12 | - target: 13 | kind: OpenStackControlPlane 14 | path: patch.yaml 15 | -------------------------------------------------------------------------------- /config/samples/tls/custom_issuers/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../../base/openstackcontrolplane 3 | 4 | patches: 5 | - target: 6 | kind: OpenStackControlPlane 7 | name: .* 8 | patch: |- 9 | - op: replace 10 | path: /metadata/name 11 | value: openstack 12 | - target: 13 | kind: OpenStackControlPlane 14 | path: patch.yaml 15 | -------------------------------------------------------------------------------- /config/samples/tls/custom_issuers/patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: core.openstack.org/v1beta1 2 | kind: OpenStackControlPlane 3 | metadata: 4 | name: openstack 5 | spec: 6 | tls: 7 | ingress: 8 | ca: 9 | customIssuer: rootca-ingress-custom 10 | podLevel: 11 | internal: 12 | ca: 13 | customIssuer: rootca-internal-custom 14 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-deploy-no-nodes-test/05-dataplane-deploy-service-not-found.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneDeployment 3 | metadata: 4 | name: edpm-compute-no-nodes-non-existent-service 5 | spec: 6 | nodeSets: 7 | - edpm-compute-no-nodes 8 | servicesOverride: 9 | - this-service-does-not-exist 10 | -------------------------------------------------------------------------------- /config/operator/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../crd/bases/operator.openstack.org_openstacks.yaml 3 | - ../samples/operator_v1beta1_openstack.yaml 4 | 5 | bases: 6 | - manifests 7 | - rbac 8 | - deployment 9 | 10 | patches: 11 | 12 | # Injects our custom images (ENV variable settings) 13 | - path: manager_operator_images.yaml 14 | - path: default_images.yaml 15 | -------------------------------------------------------------------------------- /config/rbac/metrics_auth_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: metrics-auth-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: metrics-auth-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /test/kuttl/common/rhobs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operators.coreos.com/v1alpha1 2 | kind: Subscription 3 | metadata: 4 | name: cluster-observability-operator 5 | namespace: openshift-operators 6 | spec: 7 | channel: stable 8 | installPlanApproval: Automatic 9 | name: cluster-observability-operator 10 | source: redhat-operators 11 | sourceNamespace: openshift-marketplace 12 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-basic-deployment-with-nicMappings/04-remove-ovn-nic-mappings.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | timeout: 60 4 | commands: 5 | - script: | 6 | oc patch OpenStackControlPlane -n $NAMESPACE openstack --type='json' -p='[{ 7 | "op": "remove", 8 | "path": "/spec/ovn/template/ovnController/nicMappings", 9 | }]' 10 | -------------------------------------------------------------------------------- /.github/workflows/crd-sync-check-olive.yaml: -------------------------------------------------------------------------------- 1 | name: CRD sync check olive branch 2 | 3 | on: 4 | schedule: 5 | - cron: '0 */2 * * *' # every 2 hours 6 | workflow_dispatch: 7 | 8 | jobs: 9 | call-build-workflow: 10 | if: github.repository_owner == 'openstack-k8s-operators' 11 | uses: ./.github/workflows/crd-sync-check.yaml 12 | with: 13 | branch_name: olive 14 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-nodeselectors/03-update-nodeselector.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | timeout: 60 4 | commands: 5 | - script: | 6 | oc patch openstackcontrolplane -n $NAMESPACE openstack --type='json' -p='[{ 7 | "op": "replace", 8 | "path": "/spec/nodeSelector", 9 | "value": {"kubernetes.io/os":"linux"} 10 | }]' 11 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-deploy-no-nodes-test/07-dataplane-deploy-node-selector.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneDeployment 3 | metadata: 4 | name: edpm-compute-node-selection 5 | spec: 6 | nodeSets: 7 | - edpm-compute-no-nodes 8 | ansibleJobNodeSelector: 9 | nodeWith: ctlplane 10 | servicesOverride: 11 | - configure-os 12 | -------------------------------------------------------------------------------- /config/rbac/metrics_auth_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-auth-role 5 | rules: 6 | - apiGroups: 7 | - authentication.k8s.io 8 | resources: 9 | - tokenreviews 10 | verbs: 11 | - create 12 | - apiGroups: 13 | - authorization.k8s.io 14 | resources: 15 | - subjectaccessreviews 16 | verbs: 17 | - create 18 | -------------------------------------------------------------------------------- /OWNERS_ALIASES: -------------------------------------------------------------------------------- 1 | # See the OWNERS_ALIASES docs: https://git.k8s.io/community/contributors/guide/owners.md#owners_aliases 2 | 3 | aliases: 4 | ci-approvers: 5 | - viroel 6 | docs-approvers: 7 | - Jenny-Anne 8 | openstack-approvers: 9 | - abays 10 | - dprince 11 | - olliewalsh 12 | - stuggi 13 | dataplane-approvers: 14 | - fultonj 15 | - rebtoor 16 | - slagle 17 | - rabi 18 | -------------------------------------------------------------------------------- /config/operator/rbac/metrics_auth_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-auth-role-operator 5 | rules: 6 | - apiGroups: 7 | - authentication.k8s.io 8 | resources: 9 | - tokenreviews 10 | verbs: 11 | - create 12 | - apiGroups: 13 | - authorization.k8s.io 14 | resources: 15 | - subjectaccessreviews 16 | verbs: 17 | - create 18 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/00-assert-custom-issuers.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: Issuer 3 | metadata: 4 | name: rootca-internal-custom 5 | spec: 6 | ca: 7 | secretName: rootca-internal-custom 8 | --- 9 | apiVersion: cert-manager.io/v1 10 | kind: Issuer 11 | metadata: 12 | name: rootca-ingress-custom 13 | spec: 14 | ca: 15 | secretName: rootca-ingress-custom 16 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/08-assert-custom-issuers.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: Issuer 3 | metadata: 4 | name: rootca-internal-custom 5 | spec: 6 | ca: 7 | secretName: rootca-internal-custom 8 | --- 9 | apiVersion: cert-manager.io/v1 10 | kind: Issuer 11 | metadata: 12 | name: rootca-ingress-custom 13 | spec: 14 | ca: 15 | secretName: rootca-ingress-custom 16 | -------------------------------------------------------------------------------- /config/operator/rbac/metrics_auth_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: metrics-auth-rolebinding-operator 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: metrics-auth-role-operator 9 | subjects: 10 | - kind: ServiceAccount 11 | name: openstack-operator-controller-operator 12 | namespace: system 13 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-basic-deployment-with-nicMappings/03-add-ovn-nic-mappings.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | timeout: 60 4 | commands: 5 | - script: | 6 | oc patch openstackcontrolplane -n $NAMESPACE openstack --type='json' -p='[{ 7 | "op": "replace", 8 | "path": "/spec/ovn/template/ovnController/nicMappings", 9 | "value":{"datacentre":"ospbr"} 10 | }]' 11 | -------------------------------------------------------------------------------- /config/samples/nad_datacentre.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: k8s.cni.cncf.io/v1 2 | kind: NetworkAttachmentDefinition 3 | metadata: 4 | annotations: 5 | labels: 6 | osp/net: data-centre 7 | service: ovn-controller 8 | name: datacentre 9 | spec: 10 | config: | 11 | { 12 | "cniVersion": "0.3.1", 13 | "name": "datacentre", 14 | "type": "bridge", 15 | "bridge": "ospbr", 16 | "ipam": {} 17 | } 18 | -------------------------------------------------------------------------------- /config/webhook/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: openstack-operator 6 | app.kubernetes.io/managed-by: kustomize 7 | name: webhook-service 8 | namespace: system 9 | spec: 10 | ports: 11 | - port: 443 12 | protocol: TCP 13 | targetPort: 9443 14 | selector: 15 | control-plane: controller-manager 16 | app.kubernetes.io/name: openstack-operator 17 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-collapsed/02-cleanup.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | delete: 4 | - apiVersion: core.openstack.org/v1beta1 5 | kind: OpenStackControlPlane 6 | name: openstack-collapsed-cell 7 | commands: 8 | - script: | 9 | oc delete secret --ignore-not-found=true combined-ca-bundle -n $NAMESPACE 10 | oc delete secret -l service-cert -n $NAMESPACE 11 | oc delete secret -l ca-cert -n $NAMESPACE 12 | -------------------------------------------------------------------------------- /config/operator/deployment/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - deployment.yaml 3 | 4 | generatorOptions: 5 | disableNameSuffixHash: true 6 | 7 | configMapGenerator: 8 | - files: 9 | - controller_operator_config.yaml 10 | name: operator-config 11 | apiVersion: kustomize.config.k8s.io/v1beta1 12 | kind: Kustomization 13 | images: 14 | - name: controller 15 | newName: quay.io/openstack-k8s-operators/openstack-operator 16 | newTag: latest 17 | -------------------------------------------------------------------------------- /config/samples/dataplane/base/config/nodesetname.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute OpenStackDataPlaneNodeSet name reference in OpenStackDataPlaneDeployment 2 | nameReference: 3 | - kind: OpenStackDataPlaneNodeSet 4 | version: v1beta1 5 | group: dataplane.openstack.org 6 | fieldSpecs: 7 | - kind: OpenStackDataPlaneDeployment 8 | version: v1beta1 9 | group: dataplane.openstack.org 10 | path: spec/nodeSets 11 | -------------------------------------------------------------------------------- /config/samples/dataplane/nova_cell_custom/servicename.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute OpenStackDataPlaneService name reference in OpenStackDataPlaneNodeSet 2 | nameReference: 3 | - kind: OpenStackDataPlaneService 4 | version: v1beta1 5 | group: dataplane.openstack.org 6 | fieldSpecs: 7 | - kind: OpenStackDataPlaneNodeSet 8 | version: v1beta1 9 | group: dataplane.openstack.org 10 | path: spec/services 11 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_swift.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: swift 5 | spec: 6 | playbook: osp.edpm.swift 7 | dataSources: 8 | - secretRef: 9 | name: swift-conf 10 | - configMapRef: 11 | name: swift-storage-config-data 12 | - configMapRef: 13 | name: swift-ring-files 14 | edpmServiceType: swift 15 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-deploy-no-nodes-test/03-update-ovn-cm.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: ovncontroller-config 5 | data: 6 | ovsdb-config: test-ovn-config-updated 7 | --- 8 | # Sleep for 30s, b/c this test is meant to assert that even though we've 9 | # changed the above CM, the hash on the NodeSet does not change. 10 | apiVersion: kuttl.dev/v1beta1 11 | kind: TestStep 12 | commands: 13 | - script: sleep 30 14 | -------------------------------------------------------------------------------- /config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: openstack-operator 6 | app.kubernetes.io/managed-by: kustomize 7 | name: manager-rolebinding 8 | roleRef: 9 | apiGroup: rbac.authorization.k8s.io 10 | kind: ClusterRole 11 | name: manager-role 12 | subjects: 13 | - kind: ServiceAccount 14 | name: controller-manager 15 | namespace: system 16 | -------------------------------------------------------------------------------- /hack/build-crd-schema-checker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | if [ -f "$INSTALL_DIR/crd-schema-checker" ]; then 5 | exit 0 6 | fi 7 | 8 | mkdir -p "$INSTALL_DIR/git-tmp" 9 | git clone https://github.com/openshift/crd-schema-checker.git \ 10 | -b "$CRD_SCHEMA_CHECKER_VERSION" "$INSTALL_DIR/git-tmp" 11 | pushd "$INSTALL_DIR/git-tmp" 12 | GOWORK=off make 13 | cp crd-schema-checker "$INSTALL_DIR/" 14 | popd 15 | rm -rf "$INSTALL_DIR/git-tmp" 16 | -------------------------------------------------------------------------------- /config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: openstack-operator 6 | app.kubernetes.io/managed-by: kustomize 7 | name: leader-election-rolebinding 8 | roleRef: 9 | apiGroup: rbac.authorization.k8s.io 10 | kind: Role 11 | name: leader-election-role 12 | subjects: 13 | - kind: ServiceAccount 14 | name: controller-manager 15 | namespace: system 16 | -------------------------------------------------------------------------------- /config/samples/tls/custom_route_cert/patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: core.openstack.org/v1beta1 2 | kind: OpenStackControlPlane 3 | metadata: 4 | name: openstack 5 | spec: 6 | barbican: 7 | apiOverride: 8 | tls: 9 | secretName: barbican-custom-route 10 | placement: 11 | apiOverride: 12 | route: 13 | spec: 14 | tls: 15 | certificate: "" 16 | key: "" 17 | caCertificate: "" 18 | termination: reencrypt 19 | -------------------------------------------------------------------------------- /config/operator/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: openstack-operator-controller-operator 6 | app.kubernetes.io/managed-by: kustomize 7 | name: operator-rolebinding 8 | roleRef: 9 | apiGroup: rbac.authorization.k8s.io 10 | kind: ClusterRole 11 | name: operator-role 12 | subjects: 13 | - kind: ServiceAccount 14 | name: openstack-operator-controller-operator 15 | namespace: system 16 | -------------------------------------------------------------------------------- /.github/workflows/lints.yaml: -------------------------------------------------------------------------------- 1 | name: Lints 2 | 3 | on: [pull_request] 4 | 5 | jobs: 6 | check-go-mod-replace-lines: 7 | name: check for replace lines in go.mod files 8 | runs-on: ubuntu-latest 9 | steps: 10 | - name: Checkout project code 11 | uses: actions/checkout@v4 12 | - name: check for replace lines in go.mod files 13 | run: | 14 | ! egrep --invert-match -e '^replace.*/apis => \./apis|^replace.*//allow-merging$' `find . -name 'go.mod'` | egrep -e 'go.mod:replace' 15 | -------------------------------------------------------------------------------- /config/operator/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: openstack-operator 6 | app.kubernetes.io/managed-by: kustomize 7 | name: leader-election-rolebinding-operator 8 | roleRef: 9 | apiGroup: rbac.authorization.k8s.io 10 | kind: Role 11 | name: leader-election-role-operator 12 | subjects: 13 | - kind: ServiceAccount 14 | name: openstack-operator-controller-operator 15 | namespace: system 16 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-basic-deployment/05-cleanup.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | delete: 4 | - apiVersion: core.openstack.org/v1beta1 5 | kind: OpenStackControlPlane 6 | name: openstack 7 | commands: 8 | - script: | 9 | oc delete --ignore-not-found=true -n $NAMESPACE pvc \ 10 | srv-swift-storage-0 11 | oc delete secret --ignore-not-found=true combined-ca-bundle -n $NAMESPACE 12 | oc delete secret -l service-cert -n $NAMESPACE 13 | oc delete secret -l ca-cert -n $NAMESPACE 14 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-cert-rotation/05-cleanup.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | delete: 4 | - apiVersion: core.openstack.org/v1beta1 5 | kind: OpenStackControlPlane 6 | name: openstack 7 | commands: 8 | - script: | 9 | oc delete --ignore-not-found=true -n $NAMESPACE pvc \ 10 | srv-swift-storage-0 11 | oc delete secret --ignore-not-found=true combined-ca-bundle -n $NAMESPACE 12 | oc delete secret -l service-cert -n $NAMESPACE 13 | oc delete secret -l ca-cert -n $NAMESPACE 14 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/05-cleanup.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | delete: 4 | - apiVersion: core.openstack.org/v1beta1 5 | kind: OpenStackControlPlane 6 | name: openstack 7 | commands: 8 | - script: | 9 | oc delete --ignore-not-found=true -n $NAMESPACE pvc \ 10 | srv-swift-storage-0 11 | oc delete secret --ignore-not-found=true combined-ca-bundle -n $NAMESPACE 12 | oc delete secret -l service-cert -n $NAMESPACE 13 | oc delete secret -l ca-cert -n $NAMESPACE 14 | -------------------------------------------------------------------------------- /config/default/metrics_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | app.kubernetes.io/name: openstack-operator 7 | app.kubernetes.io/managed-by: kustomize 8 | name: controller-manager-metrics-service 9 | namespace: system 10 | spec: 11 | ports: 12 | - name: https 13 | port: 8443 14 | protocol: TCP 15 | targetPort: 8443 16 | selector: 17 | control-plane: controller-manager 18 | app.kubernetes.io/name: openstack-operator 19 | -------------------------------------------------------------------------------- /config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | 4 | # [PROMETHEUS-WITH-CERTS] The following patch configures the ServiceMonitor in ../prometheus 5 | # to securely reference certificates created and managed by cert-manager. 6 | # Additionally, ensure that you uncomment the [METRICS WITH CERTMANAGER] patch under config/default/kustomization.yaml 7 | # to mount the "metrics-server-cert" secret in the Manager Deployment. 8 | patches: 9 | - path: monitor_tls_patch.yaml 10 | target: 11 | kind: ServiceMonitor 12 | -------------------------------------------------------------------------------- /config/scorecard/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - bases/config.yaml 3 | apiVersion: kustomize.config.k8s.io/v1beta1 4 | kind: Kustomization 5 | patches: 6 | - path: patches/basic.config.yaml 7 | target: 8 | group: scorecard.operatorframework.io 9 | kind: Configuration 10 | name: config 11 | version: v1alpha3 12 | - path: patches/olm.config.yaml 13 | target: 14 | group: scorecard.operatorframework.io 15 | kind: Configuration 16 | name: config 17 | version: v1alpha3 18 | # +kubebuilder:scaffold:patches 19 | -------------------------------------------------------------------------------- /config/certmanager/issuer.yaml: -------------------------------------------------------------------------------- 1 | # The following manifest contains a self-signed issuer CR. 2 | # More information can be found at https://docs.cert-manager.io 3 | # WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes. 4 | apiVersion: cert-manager.io/v1 5 | kind: Issuer 6 | metadata: 7 | labels: 8 | app.kubernetes.io/name: openstack-operator 9 | app.kubernetes.io/managed-by: kustomize 10 | name: selfsigned-issuer 11 | namespace: system 12 | spec: 13 | selfSigned: {} 14 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-basic-deployment-with-nicMappings/05-cleanup.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | delete: 4 | - apiVersion: core.openstack.org/v1beta1 5 | kind: OpenStackControlPlane 6 | name: openstack 7 | commands: 8 | - script: | 9 | oc delete --ignore-not-found=true -n $NAMESPACE pvc \ 10 | srv-swift-storage-0 11 | oc delete secret --ignore-not-found=true combined-ca-bundle -n $NAMESPACE 12 | oc delete secret -l service-cert -n $NAMESPACE 13 | oc delete secret -l ca-cert -n $NAMESPACE 14 | -------------------------------------------------------------------------------- /config/samples/dataplane_v1beta1_openstackdataplaneservice.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: openstackdataplaneservice 6 | app.kubernetes.io/instance: openstackdataplaneservice-sample 7 | app.kubernetes.io/part-of: openstack-operator 8 | app.kubernetes.io/managed-by: kustomize 9 | app.kubernetes.io/created-by: openstack-operator 10 | name: openstackdataplaneservice-sample 11 | spec: 12 | # TODO(user): Add fields here 13 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-route/02-deploy-custom-route-secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | source ../../common/create_custom_cert.sh 6 | INGRESS_DOMAIN=$(oc get ingresses.config.openshift.io cluster -o jsonpath='{.spec.domain}') 7 | create_barbican_placement_routes "${INGRESS_DOMAIN}" "${NAMESPACE}" 8 | 9 | - script: | 10 | # Generate ConfigMap for kustomize from the placement-custom-route secret 11 | bash ../../common/prepare_placement_certs.sh 12 | -------------------------------------------------------------------------------- /zuul.d/projects.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | - project: 3 | name: openstack-k8s-operators/openstack-operator 4 | templates: 5 | - podified-multinode-edpm-baremetal-pipeline 6 | - data-plane-adoption-pipeline 7 | github-check: 8 | jobs: 9 | - openstack-k8s-operators-content-provider: 10 | vars: 11 | cifmw_install_yamls_sdk_version: v1.41.1 12 | - openstack-operator-tempest-multinode 13 | - openstack-operator-docs-preview 14 | - openstack-operator-kuttl: 15 | voting: false 16 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_neutron_dhcp.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: neutron-dhcp 5 | spec: 6 | playbook: osp.edpm.neutron_dhcp 7 | dataSources: 8 | - secretRef: 9 | name: neutron-dhcp-agent-neutron-config 10 | - configMapRef: 11 | name: neutron-dhcp-extra-config 12 | optional: true 13 | caCerts: combined-ca-bundle 14 | containerImageFields: 15 | - EdpmNeutronDhcpAgentImage 16 | edpmServiceType: neutron-dhcp 17 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_neutron_sriov.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: neutron-sriov 5 | spec: 6 | playbook: osp.edpm.neutron_sriov 7 | dataSources: 8 | - secretRef: 9 | name: neutron-sriov-agent-neutron-config 10 | - configMapRef: 11 | name: neutron-sriov-extra-config 12 | optional: true 13 | caCerts: combined-ca-bundle 14 | containerImageFields: 15 | - EdpmNeutronSriovAgentImage 16 | edpmServiceType: neutron-sriov 17 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_telemetry.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: telemetry 5 | spec: 6 | dataSources: 7 | - secretRef: 8 | name: ceilometer-compute-config-data 9 | playbook: osp.edpm.telemetry 10 | tlsCerts: 11 | default: 12 | contents: 13 | - ips 14 | - dnsnames 15 | caCerts: combined-ca-bundle 16 | containerImageFields: 17 | - CeilometerComputeImage 18 | - EdpmNodeExporterImage 19 | edpmServiceType: telemetry 20 | -------------------------------------------------------------------------------- /.github/workflows/force-bump-pr-manual.yaml: -------------------------------------------------------------------------------- 1 | name: Manually Trigger a Force Bump PR 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | call-build-workflow: 8 | uses: openstack-k8s-operators/openstack-k8s-operators-ci/.github/workflows/force-bump-pull-request.yaml@main 9 | with: 10 | operator_name: openstack 11 | branch_name: ${{ github.ref_name }} 12 | custom_image: quay.io/openstack-k8s-operators/openstack-k8s-operators-ci-build-tools:golang-1.24-sdk-1.41.1 13 | secrets: 14 | FORCE_BUMP_PULL_REQUEST_PAT: ${{ secrets.FORCE_BUMP_PULL_REQUEST_PAT }} 15 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-nodeselectors/05-cleanup.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | delete: 4 | - apiVersion: core.openstack.org/v1beta1 5 | kind: OpenStackControlPlane 6 | name: openstack 7 | commands: 8 | - script: | 9 | oc annotate namespace $NAMESPACE openshift.io/node-selector- 10 | oc delete --ignore-not-found=true -n $NAMESPACE pvc \ 11 | srv-swift-storage-0 12 | oc delete secret --ignore-not-found=true combined-ca-bundle -n $NAMESPACE 13 | oc delete secret -l service-cert -n $NAMESPACE 14 | oc delete secret -l ca-cert -n $NAMESPACE 15 | -------------------------------------------------------------------------------- /config/samples/dataplane/base/config/varsfromname.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute ansibleVarsFrom name reference in OpenStackDataPlaneNodeSet 2 | nameReference: 3 | - kind: ConfigMap 4 | version: v1 5 | fieldSpecs: 6 | - kind: OpenStackDataPlaneNodeSet 7 | version: v1beta1 8 | group: dataplane.openstack.org 9 | path: spec/nodeTemplate/ansible/ansibleVarsFrom/configMapRef/name 10 | - kind: OpenStackDataPlaneNodeSet 11 | version: v1beta1 12 | group: dataplane.openstack.org 13 | path: spec/nodeTemplate/ansible/ansibleVarsFrom/secretRef/name 14 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_nova.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: nova 5 | spec: 6 | dataSources: 7 | - secretRef: 8 | name: nova-cell1-compute-config 9 | - secretRef: 10 | name: nova-migration-ssh-key 11 | - configMapRef: 12 | name: nova-extra-config 13 | optional: true 14 | playbook: osp.edpm.nova 15 | caCerts: combined-ca-bundle 16 | edpmServiceType: nova 17 | containerImageFields: 18 | - NovaComputeImage 19 | - EdpmIscsidImage 20 | -------------------------------------------------------------------------------- /config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | version: v1 8 | group: apiextensions.k8s.io 9 | path: spec/conversion/webhook/clientConfig/service/name 10 | 11 | namespace: 12 | - kind: CustomResourceDefinition 13 | version: v1 14 | group: apiextensions.k8s.io 15 | path: spec/conversion/webhook/clientConfig/service/namespace 16 | create: false 17 | 18 | varReference: 19 | - path: metadata/annotations 20 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-basic-deployment-with-nicMappings/04-assert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestAssert 3 | timeout: 300 4 | commands: 5 | - script: | 6 | ovs_controller_pod_count=$(oc get pod -n $NAMESPACE -l service=ovn-controller-ovs --no-headers=true --ignore-not-found=true | wc -l) 7 | ovn_controller_pod_count=$(oc get pod -n $NAMESPACE -l service=ovn-controller --no-headers=true --ignore-not-found=true | wc -l) 8 | if [ $ovs_controller_pod_count -eq 0 ] && [ $ovn_controller_pod_count -eq 0 ]; then 9 | exit 0 10 | fi 11 | exit 1 12 | -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_telemetry_power_monitoring.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: telemetry-power-monitoring 5 | spec: 6 | dataSources: 7 | - secretRef: 8 | name: ceilometer-ipmi-config-data 9 | playbook: osp.edpm.telemetry_power_monitoring 10 | tlsCerts: 11 | default: 12 | contents: 13 | - ips 14 | - dnsnames 15 | caCerts: combined-ca-bundle 16 | containerImageFields: 17 | - CeilometerIpmiImage 18 | - EdpmKeplerImage 19 | edpmServiceType: telemetry-power-monitoring 20 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/11-cleanup.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | delete: 4 | - apiVersion: core.openstack.org/v1beta1 5 | kind: OpenStackControlPlane 6 | name: openstack 7 | commands: 8 | - script: | 9 | oc delete --ignore-not-found=true -n $NAMESPACE pvc \ 10 | srv-swift-storage-0 11 | oc delete --ignore-not-found=true -n $NAMESPACE issuer rootca-internal-custom rootca-ingress-custom 12 | oc delete secret --ignore-not-found=true combined-ca-bundle -n $NAMESPACE 13 | oc delete secret -l service-cert -n $NAMESPACE 14 | oc delete secret -l ca-cert -n $NAMESPACE 15 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-route/04-assert-custom-route-cert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestAssert 3 | timeout: 60 4 | commands: 5 | - script: | 6 | echo "Checking barbican custom route certificate..." 7 | bash ../../common/osp_check_route_cert.sh "barbican" 8 | 9 | - script: | 10 | echo "Checking placement custom route certificate..." 11 | bash ../../common/osp_check_route_cert.sh "placement" 12 | 13 | - script: | 14 | echo "Verifying placement route override certificates in OpenStackControlPlane..." 15 | bash ../../common/verify_route_override_certs.sh "placement" 16 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-route/05-cleanup.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | delete: 4 | - apiVersion: core.openstack.org/v1beta1 5 | kind: OpenStackControlPlane 6 | name: openstack 7 | commands: 8 | - script: | 9 | oc delete --ignore-not-found=true -n $NAMESPACE pvc \ 10 | srv-swift-storage-0 11 | oc delete --ignore-not-found=true -n $NAMESPACE issuer rootca-internal-custom rootca-ingress-custom 12 | oc delete secret --ignore-not-found=true combined-ca-bundle -n $NAMESPACE 13 | oc delete secret -l service-cert -n $NAMESPACE 14 | oc delete secret -l ca-cert -n $NAMESPACE 15 | -------------------------------------------------------------------------------- /config/samples/operator_v1beta1_openstack.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: operator.openstack.org/v1beta1 2 | kind: OpenStack 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: openstack 6 | app.kubernetes.io/instance: openstack 7 | app.kubernetes.io/part-of: openstack-operator 8 | app.kubernetes.io/managed-by: kustomize 9 | app.kubernetes.io/created-by: openstack-operator 10 | name: openstack 11 | namespace: openstack-operators 12 | spec: 13 | operatorOverrides: 14 | - name: infra 15 | controllerManager: 16 | resources: 17 | limits: 18 | cpu: 600m 19 | memory: 2Gi 20 | replicas: 1 21 | -------------------------------------------------------------------------------- /config/samples/dataplane/sriov/values.yaml: -------------------------------------------------------------------------------- 1 | # local-config: referenced, but not emitted by kustomize 2 | apiVersion: v1 3 | kind: DataPlaneConfig 4 | metadata: 5 | name: edpm-sriov-values 6 | annotations: 7 | config.kubernetes.io/local-config: "true" 8 | data: 9 | nodeset: 10 | services: 11 | - bootstrap 12 | - download-cache 13 | - configure-network 14 | - validate-network 15 | - install-os 16 | - configure-os 17 | - ssh-known-hosts 18 | - run-os 19 | - reboot-os 20 | - install-certs 21 | - ovn 22 | - neutron-ovn 23 | - neutron-sriov 24 | - libvirt 25 | - nova 26 | - telemetry 27 | -------------------------------------------------------------------------------- /test/kuttl/common/custom-ingress-issuer.yaml: -------------------------------------------------------------------------------- 1 | # Create a custom Issuer 2 | apiVersion: cert-manager.io/v1 3 | kind: Issuer 4 | metadata: 5 | name: rootca-ingress-custom 6 | spec: 7 | ca: 8 | secretName: rootca-ingress-custom 9 | 10 | --- 11 | # Create the CA for the custom issuer 12 | apiVersion: cert-manager.io/v1 13 | kind: Certificate 14 | metadata: 15 | name: rootca-ingress-custom 16 | spec: 17 | commonName: rootca-ingress-custom 18 | isCA: true 19 | duration: 87600h 20 | privateKey: 21 | algorithm: ECDSA 22 | size: 256 23 | issuerRef: 24 | name: selfsigned-issuer 25 | kind: Issuer 26 | secretName: rootca-ingress-custom 27 | -------------------------------------------------------------------------------- /config/samples/core_v1beta1_openstackversion.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: core.openstack.org/v1beta1 2 | kind: OpenStackVersion 3 | metadata: 4 | labels: 5 | #app.kubernetes.io/name: openstackversionupdate 6 | #app.kubernetes.io/instance: openstackversionupdate-sample 7 | #app.kubernetes.io/part-of: openstack-operator 8 | #app.kubernetes.io/managed-by: kustomize 9 | #app.kubernetes.io/created-by: openstack-operator 10 | name: openstack 11 | spec: 12 | targetVersion: 1.0.1 13 | customContainerImages: 14 | cinderApiImage: 15 | cinderVolumeImages: 16 | netapp: 17 | dell: 18 | -------------------------------------------------------------------------------- /config/prometheus/monitor_tls_patch.yaml: -------------------------------------------------------------------------------- 1 | # Patch for Prometheus ServiceMonitor to enable secure TLS configuration 2 | # using certificates managed by cert-manager 3 | - op: replace 4 | path: /spec/endpoints/0/tlsConfig 5 | value: 6 | # SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize 7 | serverName: SERVICE_NAME.SERVICE_NAMESPACE.svc 8 | insecureSkipVerify: false 9 | ca: 10 | secret: 11 | name: metrics-server-cert 12 | key: ca.crt 13 | cert: 14 | secret: 15 | name: metrics-server-cert 16 | key: tls.crt 17 | keySecret: 18 | name: metrics-server-cert 19 | key: tls.key 20 | -------------------------------------------------------------------------------- /config/samples/tls/custom_duration/patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: core.openstack.org/v1beta1 2 | kind: OpenStackControlPlane 3 | metadata: 4 | name: openstack 5 | spec: 6 | tls: 7 | ingress: 8 | ca: 9 | duration: 1000h0m0s 10 | cert: 11 | duration: 500h0m0s 12 | podLevel: 13 | internal: 14 | ca: 15 | duration: 1000h0m0s 16 | cert: 17 | duration: 500h0m0s 18 | libvirt: 19 | ca: 20 | duration: 1000h0m0s 21 | cert: 22 | duration: 500h0m0s 23 | ovn: 24 | ca: 25 | duration: 1000h0m0s 26 | cert: 27 | duration: 500h0m0s 28 | -------------------------------------------------------------------------------- /test/kuttl/common/custom-internal-issuer.yaml: -------------------------------------------------------------------------------- 1 | # Create a custom Issuer 2 | apiVersion: cert-manager.io/v1 3 | kind: Issuer 4 | metadata: 5 | name: rootca-internal-custom 6 | spec: 7 | ca: 8 | secretName: rootca-internal-custom 9 | 10 | --- 11 | # Create the CA for the custom issuer 12 | apiVersion: cert-manager.io/v1 13 | kind: Certificate 14 | metadata: 15 | name: rootca-internal-custom 16 | spec: 17 | commonName: rootca-internal-custom 18 | isCA: true 19 | duration: 87600h 20 | privateKey: 21 | algorithm: ECDSA 22 | size: 256 23 | issuerRef: 24 | name: selfsigned-issuer 25 | kind: Issuer 26 | secretName: rootca-internal-custom 27 | -------------------------------------------------------------------------------- /.github/workflows/force-bump-pr-scheduled.yaml: -------------------------------------------------------------------------------- 1 | name: Scheduled Force Bump PR 2 | 3 | on: 4 | schedule: 5 | - cron: '0 10 * * 6' # 10AM UTC Saturday 6 | 7 | jobs: 8 | call-build-workflow: 9 | if: github.ref == 'refs/heads/main' && github.repository_owner == 'openstack-k8s-operators' 10 | uses: openstack-k8s-operators/openstack-k8s-operators-ci/.github/workflows/force-bump-branches.yaml@main 11 | with: 12 | operator_name: openstack 13 | custom_image: quay.io/openstack-k8s-operators/openstack-k8s-operators-ci-build-tools:golang-1.24-sdk-1.41.1 14 | secrets: 15 | FORCE_BUMP_PULL_REQUEST_PAT: ${{ secrets.FORCE_BUMP_PULL_REQUEST_PAT }} 16 | -------------------------------------------------------------------------------- /config/samples/kustomization.yaml: -------------------------------------------------------------------------------- 1 | ## Append samples you want in your CSV to this file as resources ## 2 | # NOTE(dprince): these get added to the bundle ALM examples 3 | # we do not have space for long examples here and want 4 | # to guide users to documentation instead 5 | resources: 6 | #- core_v1beta1_openstackcontrolplane_empty.yaml 7 | #- client_v1beta1_openstackclient_empty.yaml 8 | #- core_v1beta1_openstackversion_empty.yaml 9 | #- dataplane_v1beta1_openstackdataplanenodeset_empty.yaml 10 | #- dataplane_v1beta1_openstackdataplaneservice_empty.yaml 11 | #- dataplane_v1beta1_openstackdataplanedeployment_empty.yaml 12 | - operator_v1beta1_openstack.yaml 13 | #+kubebuilder:scaffold:manifestskustomizesamples 14 | -------------------------------------------------------------------------------- /test/kuttl/common/osp_endpoint_fingerprints.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -x 3 | 4 | for url in $(openstack endpoint list -c URL -f value | awk -F/ '{print $3}'); do 5 | # Extract the hostname and port 6 | host_port=$(echo "$url" | sed -E 's|^[^:/]+://([^:/]+)(:([0-9]+))?.*|\1:\3|') 7 | 8 | # If no port is specified, add :443 9 | if [[ ! "$host_port" =~ :[0-9]+$ ]]; then 10 | host_port="${host_port}:443" 11 | fi 12 | 13 | finger_print=$(openssl s_client -connect $host_port < /dev/null 2>/dev/null | openssl x509 -fingerprint -noout -in /dev/stdin | sed 's/.* Fingerprint=//') 14 | if [[ -n "$finger_print" ]]; then 15 | echo "$host_port $finger_print" 16 | fi 17 | done 18 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-deploy-no-nodes-test/02-dataplane-deploy-services-override.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: dataplane.openstack.org/v1beta1 3 | kind: OpenStackDataPlaneService 4 | metadata: 5 | name: custom-svc 6 | spec: 7 | label: custom-svc 8 | playbookContents: | 9 | - hosts: localhost 10 | gather_facts: no 11 | name: kuttl play 12 | tasks: 13 | - name: Sleep 14 | command: sleep 1 15 | delegate_to: localhost 16 | --- 17 | apiVersion: dataplane.openstack.org/v1beta1 18 | kind: OpenStackDataPlaneDeployment 19 | metadata: 20 | name: edpm-compute-no-nodes-ovrd 21 | spec: 22 | nodeSets: 23 | - edpm-compute-no-nodes 24 | servicesOverride: 25 | - custom-svc 26 | -------------------------------------------------------------------------------- /config/samples/dataplane/base/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1alpha1 2 | kind: Component 3 | 4 | resources: 5 | - ../../dataplane_v1beta1_openstackdataplanenodeset.yaml 6 | - ../../dataplane_v1beta1_openstackdataplanedeployment.yaml 7 | 8 | namespace: openstack 9 | 10 | configMapGenerator: 11 | - name: network-config-template 12 | files: 13 | - network_config_template=files/nic-config.j2 14 | options: 15 | disableNameSuffixHash: true 16 | - name: neutron-edpm 17 | literals: 18 | - physical_bridge_name=br-ex 19 | - public_interface_name=eth0 20 | options: 21 | disableNameSuffixHash: true 22 | 23 | configurations: 24 | - config/nodesetname.yaml 25 | - config/varsfromname.yaml 26 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_ovn.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: ovn 5 | spec: 6 | playbook: osp.edpm.ovn 7 | dataSources: 8 | - configMapRef: 9 | name: ovncontroller-config 10 | tlsCerts: 11 | default: 12 | contents: 13 | - dnsnames 14 | - ips 15 | networks: 16 | - ctlplane 17 | issuer: osp-rootca-issuer-ovn 18 | keyUsages: 19 | - digital signature 20 | - key encipherment 21 | - server auth 22 | - client auth 23 | caCerts: combined-ca-bundle 24 | containerImageFields: 25 | - OvnControllerImage 26 | edpmServiceType: ovn 27 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-cert-rotation/04-assert-service-cert-rotation.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestAssert 3 | timeout: 900 4 | commands: 5 | - script: | 6 | echo "Checking rotation of non API service certificates..." 7 | NAMESPACE=$NAMESPACE bash ../../common/osp_check_noapi_service_certs.sh 8 | 9 | - script: | 10 | echo "Get fingerprints of all service certs" 11 | oc exec -i openstackclient -n $NAMESPACE -- bash -s < ../../common/osp_endpoint_fingerprints.sh > /tmp/endpoint_fingerprints_after 12 | 13 | - script: | 14 | echo "Check if all services from before are present in after and have valid fingerprints" 15 | bash -s < ../../common/osp_check_fingerprints.sh 16 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-galera-3replicas/02-cleanup.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | delete: 4 | - apiVersion: core.openstack.org/v1beta1 5 | kind: OpenStackControlPlane 6 | name: openstack-galera-3replicas 7 | commands: 8 | - script: | 9 | oc delete --ignore-not-found=true -n $NAMESPACE pvc \ 10 | mysql-db-openstack-galera-0 \ 11 | mysql-db-openstack-galera-1 \ 12 | mysql-db-openstack-galera-2 \ 13 | mysql-db-openstack-cell1-galera-0 \ 14 | mysql-db-openstack-cell1-galera-1 \ 15 | mysql-db-openstack-cell1-galera-2 16 | oc delete secret --ignore-not-found=true combined-ca-bundle -n $NAMESPACE 17 | oc delete secret -l service-cert -n $NAMESPACE 18 | oc delete secret -l ca-cert -n $NAMESPACE 19 | -------------------------------------------------------------------------------- /hack/fake_minor_update.sh: -------------------------------------------------------------------------------- 1 | # A quick way to test a fake minor update. Run this script, and then once the 2 | # openstackversion reconciles (the CSV will redeploy the controller-manager) 3 | # you can set targetVersion == 0.0.2 for a quick test 4 | VERSION=0.5 5 | CURRENT=${VERSION}.0 6 | UPDATE=${VERSION}.1 7 | oc get csv openstack-operator.v${CURRENT} -o yaml -n openstack-operators > csv.yaml 8 | # bump them to current-podified 9 | sed -i csv.yaml -e "s|value: .*quay.io/podified-antelope-centos9/\(.*\)@.*|value: quay.io/podified-antelope-centos9/\1:current-podified|g" 10 | # also bump the OPENSTACK_RELEASE_VERSION value (it is the only field set like this) 11 | sed -i csv.yaml -e "s|value: ${CURRENT}|value: ${UPDATE}|" 12 | oc apply -n openstack-operators -f csv.yaml 13 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/02-assert-service-certs-issuers.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestAssert 3 | timeout: 60 4 | commands: 5 | - script: | 6 | echo "Checking rotation of non API service certificates..." 7 | NAMESPACE=$NAMESPACE bash ../../common/osp_check_noapi_service_certs.sh 8 | 9 | - script: | 10 | echo "Checking issuer of internal certificates..." 11 | oc exec -i openstackclient -n $NAMESPACE -- bash -s < ../../common/osp_check_cert_issuer.sh "rootca-internal-custom" "internal" 12 | 13 | - script: | 14 | echo "Checking issuer of ingress certificates..." 15 | oc exec -i openstackclient -n $NAMESPACE -- bash -s < ../../common/osp_check_cert_issuer.sh "rootca-ingress-custom" "public" 16 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/07-assert-service-certs-default-issuers.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestAssert 3 | timeout: 60 4 | commands: 5 | - script: | 6 | echo "Checking rotation of non API service certificates..." 7 | NAMESPACE=$NAMESPACE bash ../../common/osp_check_noapi_service_certs.sh 8 | 9 | - script: | 10 | echo "Checking issuer of internal certificates..." 11 | oc exec -i openstackclient -n $NAMESPACE -- bash -s < ../../common/osp_check_cert_issuer.sh "rootca-internal" "internal" 12 | 13 | - script: | 14 | echo "Checking issuer of ingress certificates..." 15 | oc exec -i openstackclient -n $NAMESPACE -- bash -s < ../../common/osp_check_cert_issuer.sh "rootca-public" "public" 16 | -------------------------------------------------------------------------------- /api/dataplane/v1beta1/const.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta1 18 | 19 | const ( 20 | // CtlPlaneNetwork - default ctlplane Network Name in NetConfig 21 | CtlPlaneNetwork = "ctlplane" 22 | ) 23 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "github>openstack-k8s-operators/renovate-config:default.json5" 4 | ], 5 | "baseBranchPatterns": [ 6 | "main" 7 | ], 8 | "useBaseBranchConfig": "merge", 9 | "packageRules": [ 10 | { 11 | "matchPackageNames": [ 12 | "github.com/openstack-k8s-operators/openstack-operator/apis" 13 | ], 14 | "enabled": false 15 | } 16 | ], 17 | "postUpgradeTasks": { 18 | "commands": [ 19 | "make gowork", 20 | "make tidy", 21 | "make manifests generate", 22 | "make bindata" 23 | ], 24 | "fileFilters": [ 25 | "**/go.mod", 26 | "**/go.sum", 27 | "**/*.go", 28 | "**/*.yaml", 29 | "hack/*.sh" 30 | ], 31 | "executionMode": "update" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: openstack-operator 7 | app.kubernetes.io/managed-by: kustomize 8 | name: leader-election-role 9 | rules: 10 | - apiGroups: 11 | - "" 12 | resources: 13 | - configmaps 14 | verbs: 15 | - get 16 | - list 17 | - watch 18 | - create 19 | - update 20 | - patch 21 | - delete 22 | - apiGroups: 23 | - coordination.k8s.io 24 | resources: 25 | - leases 26 | verbs: 27 | - get 28 | - list 29 | - watch 30 | - create 31 | - update 32 | - patch 33 | - delete 34 | - apiGroups: 35 | - "" 36 | resources: 37 | - events 38 | verbs: 39 | - create 40 | - patch 41 | -------------------------------------------------------------------------------- /config/operator/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: openstack-operator-controller-operator 7 | app.kubernetes.io/managed-by: kustomize 8 | name: leader-election-role-operator 9 | rules: 10 | - apiGroups: 11 | - "" 12 | resources: 13 | - configmaps 14 | verbs: 15 | - get 16 | - list 17 | - watch 18 | - create 19 | - update 20 | - patch 21 | - delete 22 | - apiGroups: 23 | - coordination.k8s.io 24 | resources: 25 | - leases 26 | verbs: 27 | - get 28 | - list 29 | - watch 30 | - create 31 | - update 32 | - patch 33 | - delete 34 | - apiGroups: 35 | - "" 36 | resources: 37 | - events 38 | verbs: 39 | - create 40 | - patch 41 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-basic-deployment/04-assert-custom-cacert.yaml: -------------------------------------------------------------------------------- 1 | # Checks the presence of the ca-custom-kuttl cert data in the combined-ca-bundle secret 2 | apiVersion: kuttl.dev/v1beta1 3 | kind: TestAssert 4 | commands: 5 | - script: | 6 | echo "Checking ca-custom-kuttl.pem is present in combined-ca-bundle..." 7 | CUSTOM_CERT_CONTENT=$(oc get secret ca-custom-kuttl -n $NAMESPACE -o jsonpath="{.data['ca-custom-kuttl\.pem']}" | base64 --decode | tr -d '\n') 8 | TLS_BUNDLE_CONTENT=$(oc get secret combined-ca-bundle -n $NAMESPACE -o jsonpath="{.data['tls-ca-bundle\.pem']}" | base64 --decode | tr -d '\n') 9 | if [[ "$TLS_BUNDLE_CONTENT" == *"$CUSTOM_CERT_CONTENT"* ]]; then 10 | echo "OK" 11 | exit 0 12 | else 13 | echo "Not present" 14 | exit 1 15 | fi 16 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_neutron_ovn.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: neutron-ovn 5 | spec: 6 | playbook: osp.edpm.neutron_ovn 7 | dataSources: 8 | - secretRef: 9 | name: neutron-ovn-agent-neutron-config 10 | - configMapRef: 11 | name: neutron-ovn-extra-config 12 | optional: true 13 | tlsCerts: 14 | default: 15 | contents: 16 | - dnsnames 17 | - ips 18 | networks: 19 | - ctlplane 20 | issuer: osp-rootca-issuer-ovn 21 | keyUsages: 22 | - digital signature 23 | - key encipherment 24 | - client auth 25 | caCerts: combined-ca-bundle 26 | containerImageFields: 27 | - EdpmNeutronOvnAgentImage 28 | edpmServiceType: neutron-ovn 29 | -------------------------------------------------------------------------------- /test/kuttl/common/osp_check_fingerprints.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -x 3 | 4 | # Check if all services from before are present in after and have valid fingerprints 5 | while IFS= read -r before; do 6 | eval $(echo "$before" | awk '{print "service_name="$1" fp_before="$2}') 7 | fp_after=$(grep -F "$service_name" /tmp/endpoint_fingerprints_after | awk '{ print $2}') 8 | 9 | echo -n "Endpoint $service_name - " 10 | 11 | if [ -z "$fp_after" ]; then 12 | echo "not found in endpoint_fingerprints_after" 13 | exit 1 14 | fi 15 | 16 | if [ "$fp_before" = "$fp_after" ]; then 17 | echo "ERROR cert not rotated - before: $fp_before - after: $fp_after" 18 | exit 1 19 | fi 20 | 21 | echo "OK cert rotated - before: $fp_before - after: $fp_after" 22 | done < /tmp/endpoint_fingerprints_before 23 | 24 | exit 0 25 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_libvirt.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: libvirt 5 | spec: 6 | playbook: osp.edpm.libvirt 7 | dataSources: 8 | # NOTE: this Secret needs to be created before deploying the data plane. 9 | # It should contain the libvirt sasl auth password using the key LibvirtPassword 10 | - secretRef: 11 | name: libvirt-secret 12 | tlsCerts: 13 | default: 14 | contents: 15 | - dnsnames 16 | - ips 17 | networks: 18 | - ctlplane 19 | keyUsages: 20 | - digital signature 21 | - key encipherment 22 | - server auth 23 | - client auth 24 | issuer: osp-rootca-issuer-libvirt 25 | caCerts: combined-ca-bundle 26 | edpmServiceType: libvirt 27 | -------------------------------------------------------------------------------- /config/certmanager/certificate-webhook.yaml: -------------------------------------------------------------------------------- 1 | # The following manifests contain a self-signed issuer CR and a certificate CR. 2 | # More document can be found at https://docs.cert-manager.io 3 | apiVersion: cert-manager.io/v1 4 | kind: Certificate 5 | metadata: 6 | labels: 7 | app.kubernetes.io/name: openstack-operator 8 | app.kubernetes.io/managed-by: kustomize 9 | name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml 10 | namespace: system 11 | spec: 12 | # SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize 13 | # replacements in the config/default/kustomization.yaml file. 14 | dnsNames: 15 | - SERVICE_NAME.SERVICE_NAMESPACE.svc 16 | - SERVICE_NAME.SERVICE_NAMESPACE.svc.cluster.local 17 | issuerRef: 18 | kind: Issuer 19 | name: selfsigned-issuer 20 | secretName: webhook-server-cert 21 | -------------------------------------------------------------------------------- /config/samples/dataplane/nova_cell_custom/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1alpha1 2 | kind: Component 3 | 4 | namespace: openstack 5 | 6 | components: 7 | - ../preprovisioned # for baremetal nodes, replace with baremetal 8 | 9 | resources: 10 | - ../../../services/dataplane_v1beta1_openstackdataplaneservice_nova.yaml 11 | 12 | configMapGenerator: 13 | - name: nova-extra-config 14 | files: 15 | - 25-nova-extra.conf=nova-extra.conf 16 | options: 17 | disableNameSuffixHash: true 18 | 19 | patches: 20 | - target: 21 | kind: OpenStackDataPlaneService 22 | name: nova 23 | patch: |- 24 | - op: replace 25 | path: /metadata/name 26 | value: nova-cell-custom 27 | - op: add 28 | path: /spec/configMaps 29 | value: 30 | - nova-extra-config 31 | 32 | configurations: 33 | - servicename.yaml 34 | -------------------------------------------------------------------------------- /config/certmanager/certificate-metrics.yaml: -------------------------------------------------------------------------------- 1 | # The following manifests contain a self-signed issuer CR and a metrics certificate CR. 2 | # More document can be found at https://docs.cert-manager.io 3 | apiVersion: cert-manager.io/v1 4 | kind: Certificate 5 | metadata: 6 | labels: 7 | app.kubernetes.io/name: openstack-operator 8 | app.kubernetes.io/managed-by: kustomize 9 | name: metrics-certs # this name should match the one appeared in kustomizeconfig.yaml 10 | namespace: system 11 | spec: 12 | dnsNames: 13 | # SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize 14 | # replacements in the config/default/kustomization.yaml file. 15 | - SERVICE_NAME.SERVICE_NAMESPACE.svc 16 | - SERVICE_NAME.SERVICE_NAMESPACE.svc.cluster.local 17 | issuerRef: 18 | kind: Issuer 19 | name: selfsigned-issuer 20 | secretName: metrics-server-cert 21 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_ovn_bgp_agent.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: ovn-bgp-agent 5 | spec: 6 | playbook: osp.edpm.ovn_bgp_agent 7 | dataSources: 8 | - secretRef: 9 | name: neutron-ovn-agent-neutron-config 10 | - configMapRef: 11 | name: ovn-bgp-agent-extra-config 12 | optional: true 13 | tlsCerts: 14 | default: 15 | contents: 16 | - dnsnames 17 | - ips 18 | networks: 19 | - ctlplane 20 | issuer: osp-rootca-issuer-ovn 21 | keyUsages: 22 | - digital signature 23 | - key encipherment 24 | - server auth 25 | - client auth 26 | caCerts: combined-ca-bundle 27 | containerImageFields: 28 | - EdpmOvnBgpAgentImage 29 | edpmServiceType: ovn-bgp-agent 30 | -------------------------------------------------------------------------------- /config/webhook/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # the following config is for teaching kustomize where to look at when substituting nameReference. 2 | # It requires kustomize v2.1.0 or newer to work properly. 3 | nameReference: 4 | - kind: Service 5 | version: v1 6 | fieldSpecs: 7 | - kind: MutatingWebhookConfiguration 8 | group: admissionregistration.k8s.io 9 | path: webhooks/clientConfig/service/name 10 | - kind: ValidatingWebhookConfiguration 11 | group: admissionregistration.k8s.io 12 | path: webhooks/clientConfig/service/name 13 | 14 | namespace: 15 | - kind: MutatingWebhookConfiguration 16 | group: admissionregistration.k8s.io 17 | path: webhooks/clientConfig/service/namespace 18 | create: true 19 | - kind: ValidatingWebhookConfiguration 20 | group: admissionregistration.k8s.io 21 | path: webhooks/clientConfig/service/namespace 22 | create: true 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin/* 9 | testbin/* 10 | 11 | bundle/* 12 | bundle.Dockerfile 13 | config/operator/deployment/kustomization.yaml 14 | # Generated certificate ConfigMaps for kustomize 15 | config/samples/tls/custom_route_cert/placement-cert-data.yaml 16 | 17 | # Test binary, build with `go test -c` 18 | *.test 19 | 20 | # Output of the go coverage tool, specifically when used with LiteIDE 21 | *.out 22 | 23 | # Kubernetes Generated files - skip generated files, except for vendored files 24 | 25 | !vendor/**/zz_generated.* 26 | 27 | # editor and IDE paraphernalia 28 | .idea 29 | .vscode 30 | *.swp 31 | *.swo 32 | *~ 33 | 34 | # Common CI tools repository 35 | CI_TOOLS_REPO 36 | 37 | # generated workspace file 38 | go.work 39 | go.work.sum 40 | 41 | # docs 42 | .bundle/ 43 | docs_build/ 44 | Gemfile.lock 45 | local/ 46 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-service-custom-image/00-dataplane-create.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: custom-img-svc 5 | spec: 6 | openStackAnsibleEERunnerImage: example.com/repo/runner-image:latest 7 | role: "test role" 8 | --- 9 | apiVersion: dataplane.openstack.org/v1beta1 10 | kind: OpenStackDataPlaneNodeSet 11 | metadata: 12 | name: edpm-no-nodes-custom-svc 13 | spec: 14 | preProvisioned: true 15 | services: 16 | - custom-img-svc 17 | nodes: {} 18 | nodeTemplate: 19 | ansible: 20 | ansibleUser: cloud-admin 21 | ansiblePort: 22 22 | ansibleSSHPrivateKeySecret: dataplane-ansible-ssh-private-key-secret 23 | --- 24 | apiVersion: dataplane.openstack.org/v1beta1 25 | kind: OpenStackDataPlaneDeployment 26 | metadata: 27 | name: edpm-compute-no-nodes 28 | spec: 29 | nodeSets: 30 | - edpm-no-nodes-custom-svc 31 | -------------------------------------------------------------------------------- /api/core/v1beta1/webhook_suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta1 18 | 19 | import ( 20 | "testing" 21 | . "github.com/onsi/ginkgo/v2" 22 | . "github.com/onsi/gomega" 23 | ) 24 | 25 | func TestAPIs(t *testing.T) { 26 | RegisterFailHandler(Fail) 27 | RunSpecs(t, "Controller v1beta1 Suite") 28 | } 29 | -------------------------------------------------------------------------------- /config/rbac/operator_openstack_admin_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants full permissions ('*') over operator.openstack.org. 5 | # This role is intended for users authorized to modify roles and bindings within the cluster, 6 | # enabling them to delegate specific permissions to other users or groups as needed. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: operator-openstack-admin-role 15 | rules: 16 | - apiGroups: 17 | - operator.openstack.org 18 | resources: 19 | - openstacks 20 | verbs: 21 | - '*' 22 | - apiGroups: 23 | - operator.openstack.org 24 | resources: 25 | - openstacks/status 26 | verbs: 27 | - get 28 | -------------------------------------------------------------------------------- /config/rbac/core_openstackversion_admin_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants full permissions ('*') over core.openstack.org. 5 | # This role is intended for users authorized to modify roles and bindings within the cluster, 6 | # enabling them to delegate specific permissions to other users or groups as needed. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: core-openstackversion-admin-role 15 | rules: 16 | - apiGroups: 17 | - core.openstack.org 18 | resources: 19 | - openstackversions 20 | verbs: 21 | - '*' 22 | - apiGroups: 23 | - core.openstack.org 24 | resources: 25 | - openstackversions/status 26 | verbs: 27 | - get 28 | -------------------------------------------------------------------------------- /hack/crd-schema-checker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -euxo pipefail 3 | 4 | CHECKER=$INSTALL_DIR/crd-schema-checker 5 | 6 | DISABLED_VALIDATORS=NoMaps,NoBools,ListsMustHaveSSATags # TODO: https://issues.redhat.com/browse/OSPRH-12254 7 | 8 | CHECKER_ARGS="" 9 | if [[ ${DISABLED_VALIDATORS:+x} ]]; then 10 | CHECKER_ARGS="$CHECKER_ARGS " 11 | for check in ${DISABLED_VALIDATORS//,/ }; do 12 | CHECKER_ARGS+=" --disabled-validators $check" 13 | done 14 | fi 15 | 16 | TMP_DIR=$(mktemp -d) 17 | 18 | function cleanup { 19 | rm -rf "$TMP_DIR" 20 | } 21 | 22 | trap cleanup EXIT 23 | 24 | 25 | for crd in config/crd/bases/*.yaml; do 26 | mkdir -p "$(dirname "$TMP_DIR/$crd")" 27 | if git show "$BASE_REF:$crd" > "$TMP_DIR/$crd"; then 28 | $CHECKER check-manifests \ 29 | $CHECKER_ARGS \ 30 | --existing-crd-filename="$TMP_DIR/$crd" \ 31 | --new-crd-filename="$crd" 32 | fi 33 | done 34 | -------------------------------------------------------------------------------- /config/rbac/client_openstackclient_admin_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants full permissions ('*') over client.openstack.org. 5 | # This role is intended for users authorized to modify roles and bindings within the cluster, 6 | # enabling them to delegate specific permissions to other users or groups as needed. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: client-openstackclient-admin-role 15 | rules: 16 | - apiGroups: 17 | - client.openstack.org 18 | resources: 19 | - openstackclients 20 | verbs: 21 | - '*' 22 | - apiGroups: 23 | - client.openstack.org 24 | resources: 25 | - openstackclients/status 26 | verbs: 27 | - get 28 | -------------------------------------------------------------------------------- /config/services/dataplane_v1beta1_openstackdataplaneservice_neutron_metadata.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: neutron-metadata 5 | spec: 6 | playbook: osp.edpm.neutron_metadata 7 | dataSources: 8 | - secretRef: 9 | name: neutron-ovn-metadata-agent-neutron-config 10 | - secretRef: 11 | name: nova-metadata-neutron-config 12 | - configMapRef: 13 | name: neutron-metadata-extra-config 14 | optional: true 15 | tlsCerts: 16 | default: 17 | contents: 18 | - dnsnames 19 | - ips 20 | networks: 21 | - ctlplane 22 | issuer: osp-rootca-issuer-ovn 23 | keyUsages: 24 | - digital signature 25 | - key encipherment 26 | - client auth 27 | caCerts: combined-ca-bundle 28 | containerImageFields: 29 | - EdpmNeutronMetadataAgentImage 30 | edpmServiceType: neutron-metadata 31 | -------------------------------------------------------------------------------- /.github/workflows/build-openstack-operator.yaml: -------------------------------------------------------------------------------- 1 | name: openstack operator image builder 2 | 3 | on: 4 | push: 5 | branches: 6 | - '*' 7 | 8 | env: 9 | imageregistry: 'quay.io' 10 | imagenamespace: ${{ secrets.IMAGENAMESPACE || secrets.QUAY_USERNAME }} 11 | latesttag: latest 12 | 13 | jobs: 14 | call-build-workflow: 15 | uses: openstack-k8s-operators/openstack-k8s-operators-ci/.github/workflows/reusable-build-operator.yaml@main 16 | with: 17 | operator_name: openstack 18 | go_version: 1.24.x 19 | operator_sdk_version: 1.41.1 20 | bundle_dockerfile: ./bundle.Dockerfile 21 | operator_version: 0.5.0 22 | secrets: 23 | IMAGENAMESPACE: ${{ secrets.IMAGENAMESPACE }} 24 | QUAY_USERNAME: ${{ secrets.QUAY_USERNAME }} 25 | QUAY_PASSWORD: ${{ secrets.QUAY_PASSWORD }} 26 | REDHATIO_USERNAME: ${{ secrets.REDHATIO_USERNAME }} 27 | REDHATIO_PASSWORD: ${{ secrets.REDHATIO_PASSWORD }} 28 | -------------------------------------------------------------------------------- /config/rbac/core_openstackcontrolplane_admin_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants full permissions ('*') over core.openstack.org. 5 | # This role is intended for users authorized to modify roles and bindings within the cluster, 6 | # enabling them to delegate specific permissions to other users or groups as needed. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: core-openstackcontrolplane-admin-role 15 | rules: 16 | - apiGroups: 17 | - core.openstack.org 18 | resources: 19 | - openstackcontrolplanes 20 | verbs: 21 | - '*' 22 | - apiGroups: 23 | - core.openstack.org 24 | resources: 25 | - openstackcontrolplanes/status 26 | verbs: 27 | - get 28 | -------------------------------------------------------------------------------- /docs/assemblies/updating-the-data-plane.adoc: -------------------------------------------------------------------------------- 1 | [id="assembly_updating-the-data-plane"] 2 | = Updating the data plane 3 | 4 | :context: dataplane 5 | 6 | [role="_abstract"] 7 | You can perform a minor update of your OpenStack data plane environment to keep 8 | it updated with the latest packages and containers. 9 | 10 | You must coordinate the minor update of the OpenStack data plane environment 11 | with a minor update of the control plane. OVN containers on the data plane 12 | nodes should not be updated until OVN containers on the control plane have been 13 | updated. 14 | 15 | See 16 | https://github.com/openstack-k8s-operators/dev-docs/blob/main/version_updates.md[OpenStackVersion] 17 | and 18 | https://github.com/openstack-k8s-operators/dev-docs/blob/main/ovs-update.md[Open 19 | vSwitch update] for more information. 20 | 21 | include::proc_updating-the-data-plane-ovn.adoc[leveloffset=+1] 22 | 23 | include::proc_updating-the-data-plane.adoc[leveloffset=+1] 24 | -------------------------------------------------------------------------------- /config/rbac/operator_openstack_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants read-only access to operator.openstack.org resources. 5 | # This role is intended for users who need visibility into these resources 6 | # without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: operator-openstack-viewer-role 15 | rules: 16 | - apiGroups: 17 | - operator.openstack.org 18 | resources: 19 | - openstacks 20 | verbs: 21 | - get 22 | - list 23 | - watch 24 | - apiGroups: 25 | - operator.openstack.org 26 | resources: 27 | - openstacks/status 28 | verbs: 29 | - get 30 | -------------------------------------------------------------------------------- /config/rbac/core_openstackversion_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants read-only access to core.openstack.org resources. 5 | # This role is intended for users who need visibility into these resources 6 | # without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: core-openstackversion-viewer-role 15 | rules: 16 | - apiGroups: 17 | - core.openstack.org 18 | resources: 19 | - openstackversions 20 | verbs: 21 | - get 22 | - list 23 | - watch 24 | - apiGroups: 25 | - core.openstack.org 26 | resources: 27 | - openstackversions/status 28 | verbs: 29 | - get 30 | -------------------------------------------------------------------------------- /config/rbac/client_openstackclient_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants read-only access to client.openstack.org resources. 5 | # This role is intended for users who need visibility into these resources 6 | # without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: client-openstackclient-viewer-role 15 | rules: 16 | - apiGroups: 17 | - client.openstack.org 18 | resources: 19 | - openstackclients 20 | verbs: 21 | - get 22 | - list 23 | - watch 24 | - apiGroups: 25 | - client.openstack.org 26 | resources: 27 | - openstackclients/status 28 | verbs: 29 | - get 30 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/04-assert-service-certs-default-issuers.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestAssert 3 | timeout: 500 4 | commands: 5 | - script: | 6 | echo "Waiting for OpenStack control plane to be ready..." 7 | oc wait openstackcontrolplane -n $NAMESPACE --for=condition=Ready --timeout=400s -l core.openstack.org/openstackcontrolplane 8 | 9 | - script: | 10 | echo "Checking rotation of non API service certificates..." 11 | NAMESPACE=$NAMESPACE bash ../../common/osp_check_noapi_service_certs.sh 12 | 13 | - script: | 14 | echo "Checking issuer of internal certificates..." 15 | oc exec -i openstackclient -n $NAMESPACE -- bash -s < ../../common/osp_check_cert_issuer.sh "rootca-internal" "internal" 16 | 17 | - script: | 18 | echo "Checking issuer of ingress certificates..." 19 | oc exec -i openstackclient -n $NAMESPACE -- bash -s < ../../common/osp_check_cert_issuer.sh "rootca-public" "public" 20 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-deploy-tls-test/01-create-cert-issuers.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | function wait_for() { 6 | timeout=$1 7 | shift 1 8 | until [ $timeout -le 0 ] || ("$@" &> /dev/null); do 9 | echo waiting for "$@" 10 | sleep 1 11 | timeout=$(( timeout - 1 )) 12 | done 13 | if [ $timeout -le 0 ]; then 14 | return 1 15 | fi 16 | } 17 | 18 | if oc get secret combined-ca-bundle -n openstack-kuttl-tests; then oc delete secret combined-ca-bundle -n openstack-kuttl-tests; fi 19 | oc apply -f ./certs.yaml 20 | wait_for 100 oc get secret osp-rootca-secret -n openstack-kuttl-tests 21 | CA_CRT=$(oc get secret osp-rootca-secret -n openstack-kuttl-tests -o json|jq -r '.data."ca.crt"') 22 | oc create secret generic combined-ca-bundle -n openstack-kuttl-tests --from-literal=tls-ca-bundle.pem=$CA_CRT 23 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-custom-issuers/10-assert-service-certs-issuers.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestAssert 3 | timeout: 500 4 | commands: 5 | - script: | 6 | echo "Waiting for OpenStack control plane to be ready..." 7 | oc wait openstackcontrolplane -n $NAMESPACE --for=condition=Ready --timeout=400s -l core.openstack.org/openstackcontrolplane 8 | 9 | - script: | 10 | echo "Checking rotation of non API service certificates..." 11 | NAMESPACE=$NAMESPACE bash ../../common/osp_check_noapi_service_certs.sh 12 | 13 | - script: | 14 | echo "Checking issuer of internal certificates..." 15 | oc exec -i openstackclient -n $NAMESPACE -- bash -s < ../../common/osp_check_cert_issuer.sh "rootca-internal-custom" "internal" 16 | 17 | - script: | 18 | echo "Checking issuer of ingress certificates..." 19 | oc exec -i openstackclient -n $NAMESPACE -- bash -s < ../../common/osp_check_cert_issuer.sh "rootca-ingress-custom" "public" 20 | -------------------------------------------------------------------------------- /config/rbac/core_openstackcontrolplane_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants read-only access to core.openstack.org resources. 5 | # This role is intended for users who need visibility into these resources 6 | # without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: core-openstackcontrolplane-viewer-role 15 | rules: 16 | - apiGroups: 17 | - core.openstack.org 18 | resources: 19 | - openstackcontrolplanes 20 | verbs: 21 | - get 22 | - list 23 | - watch 24 | - apiGroups: 25 | - core.openstack.org 26 | resources: 27 | - openstackcontrolplanes/status 28 | verbs: 29 | - get 30 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-deploy-multiple-secrets/01-create-cert-issuers.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestStep 3 | commands: 4 | - script: | 5 | function wait_for() { 6 | timeout=$1 7 | shift 1 8 | until [ $timeout -le 0 ] || ("$@" &> /dev/null); do 9 | echo waiting for "$@" 10 | sleep 1 11 | timeout=$(( timeout - 1 )) 12 | done 13 | if [ $timeout -le 0 ]; then 14 | return 1 15 | fi 16 | } 17 | 18 | if oc get secret combined-ca-bundle -n openstack-kuttl-tests; then oc delete secret combined-ca-bundle -n openstack-kuttl-tests; fi 19 | oc apply -f ./certs.yaml 20 | wait_for 100 oc get secret osp-rootca-secret -n openstack-kuttl-tests 21 | CA_CRT=$(oc get secret osp-rootca-secret -n openstack-kuttl-tests -o json|jq -r '.data."ca.crt"') 22 | oc create secret generic combined-ca-bundle -n openstack-kuttl-tests --from-literal=TLSCABundleFile=$CA_CRT 23 | -------------------------------------------------------------------------------- /config/network-policy/allow-metrics-traffic.yaml: -------------------------------------------------------------------------------- 1 | # This NetworkPolicy allows ingress traffic 2 | # with Pods running on namespaces labeled with 'metrics: enabled'. Only Pods on those 3 | # namespaces are able to gather data from the metrics endpoint. 4 | apiVersion: networking.k8s.io/v1 5 | kind: NetworkPolicy 6 | metadata: 7 | labels: 8 | app.kubernetes.io/name: openstack-operator 9 | app.kubernetes.io/managed-by: kustomize 10 | name: allow-metrics-traffic 11 | namespace: system 12 | spec: 13 | podSelector: 14 | matchLabels: 15 | control-plane: controller-manager 16 | app.kubernetes.io/name: openstack-operator 17 | policyTypes: 18 | - Ingress 19 | ingress: 20 | # This allows ingress traffic from any namespace with the label metrics: enabled 21 | - from: 22 | - namespaceSelector: 23 | matchLabels: 24 | metrics: enabled # Only from namespaces with this label 25 | ports: 26 | - port: 8443 27 | protocol: TCP 28 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-deploy-tls-test/certs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: Issuer 3 | metadata: 4 | name: selfsigned-issuer 5 | namespace: openstack-kuttl-tests 6 | spec: 7 | selfSigned: {} 8 | --- 9 | # RootCA Certificate used to sign certificates 10 | apiVersion: cert-manager.io/v1 11 | kind: Certificate 12 | metadata: 13 | name: osp-rootca 14 | namespace: openstack-kuttl-tests 15 | spec: 16 | isCA: true 17 | commonName: osp-rootca 18 | secretName: osp-rootca-secret 19 | privateKey: 20 | algorithm: ECDSA 21 | size: 256 22 | issuerRef: 23 | name: selfsigned-issuer 24 | kind: Issuer 25 | group: cert-manager.io 26 | --- 27 | # Issuer that uses the generated CA certificate to issue certs 28 | apiVersion: cert-manager.io/v1 29 | kind: Issuer 30 | metadata: 31 | name: rootca-internal 32 | namespace: openstack-kuttl-tests 33 | labels: 34 | osp-rootca-issuer-internal: "" 35 | spec: 36 | ca: 37 | secretName: osp-rootca-secret 38 | --- 39 | -------------------------------------------------------------------------------- /config/rbac/dataplane_openstackdataplanenodeset_admin_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants full permissions ('*') over dataplane.openstack.org. 5 | # This role is intended for users authorized to modify roles and bindings within the cluster, 6 | # enabling them to delegate specific permissions to other users or groups as needed. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: dataplane-openstackdataplanenodeset-admin-role 15 | rules: 16 | - apiGroups: 17 | - dataplane.openstack.org 18 | resources: 19 | - openstackdataplanenodesets 20 | verbs: 21 | - '*' 22 | - apiGroups: 23 | - dataplane.openstack.org 24 | resources: 25 | - openstackdataplanenodesets/status 26 | verbs: 27 | - get 28 | -------------------------------------------------------------------------------- /config/rbac/dataplane_openstackdataplaneservice_admin_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants full permissions ('*') over dataplane.openstack.org. 5 | # This role is intended for users authorized to modify roles and bindings within the cluster, 6 | # enabling them to delegate specific permissions to other users or groups as needed. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: dataplane-openstackdataplaneservice-admin-role 15 | rules: 16 | - apiGroups: 17 | - dataplane.openstack.org 18 | resources: 19 | - openstackdataplaneservices 20 | verbs: 21 | - '*' 22 | - apiGroups: 23 | - dataplane.openstack.org 24 | resources: 25 | - openstackdataplaneservices/status 26 | verbs: 27 | - get 28 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-deploy-multiple-secrets/certs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: cert-manager.io/v1 2 | kind: Issuer 3 | metadata: 4 | name: selfsigned-issuer 5 | namespace: openstack-kuttl-tests 6 | spec: 7 | selfSigned: {} 8 | --- 9 | # RootCA Certificate used to sign certificates 10 | apiVersion: cert-manager.io/v1 11 | kind: Certificate 12 | metadata: 13 | name: osp-rootca 14 | namespace: openstack-kuttl-tests 15 | spec: 16 | isCA: true 17 | commonName: osp-rootca 18 | secretName: osp-rootca-secret 19 | privateKey: 20 | algorithm: ECDSA 21 | size: 256 22 | issuerRef: 23 | name: selfsigned-issuer 24 | kind: Issuer 25 | group: cert-manager.io 26 | --- 27 | # Issuer that uses the generated CA certificate to issue certs 28 | apiVersion: cert-manager.io/v1 29 | kind: Issuer 30 | metadata: 31 | name: rootca-internal 32 | namespace: openstack-kuttl-tests 33 | labels: 34 | osp-rootca-issuer-internal: "" 35 | spec: 36 | ca: 37 | secretName: osp-rootca-secret 38 | --- 39 | -------------------------------------------------------------------------------- /config/rbac/dataplane_openstackdataplanedeployment_admin_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants full permissions ('*') over dataplane.openstack.org. 5 | # This role is intended for users authorized to modify roles and bindings within the cluster, 6 | # enabling them to delegate specific permissions to other users or groups as needed. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: dataplane-openstackdataplanedeployment-admin-role 15 | rules: 16 | - apiGroups: 17 | - dataplane.openstack.org 18 | resources: 19 | - openstackdataplanedeployments 20 | verbs: 21 | - '*' 22 | - apiGroups: 23 | - dataplane.openstack.org 24 | resources: 25 | - openstackdataplanedeployments/status 26 | verbs: 27 | - get 28 | -------------------------------------------------------------------------------- /config/rbac/operator_openstack_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants permissions to create, update, and delete resources within the operator.openstack.org. 5 | # This role is intended for users who need to manage these resources 6 | # but should not control RBAC or manage permissions for others. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: operator-openstack-editor-role 15 | rules: 16 | - apiGroups: 17 | - operator.openstack.org 18 | resources: 19 | - openstacks 20 | verbs: 21 | - create 22 | - delete 23 | - get 24 | - list 25 | - patch 26 | - update 27 | - watch 28 | - apiGroups: 29 | - operator.openstack.org 30 | resources: 31 | - openstacks/status 32 | verbs: 33 | - get 34 | -------------------------------------------------------------------------------- /config/rbac/core_openstackversion_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants permissions to create, update, and delete resources within the core.openstack.org. 5 | # This role is intended for users who need to manage these resources 6 | # but should not control RBAC or manage permissions for others. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: core-openstackversion-editor-role 15 | rules: 16 | - apiGroups: 17 | - core.openstack.org 18 | resources: 19 | - openstackversions 20 | verbs: 21 | - create 22 | - delete 23 | - get 24 | - list 25 | - patch 26 | - update 27 | - watch 28 | - apiGroups: 29 | - core.openstack.org 30 | resources: 31 | - openstackversions/status 32 | verbs: 33 | - get 34 | -------------------------------------------------------------------------------- /config/rbac/client_openstackclient_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants permissions to create, update, and delete resources within the client.openstack.org. 5 | # This role is intended for users who need to manage these resources 6 | # but should not control RBAC or manage permissions for others. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: client-openstackclient-editor-role 15 | rules: 16 | - apiGroups: 17 | - client.openstack.org 18 | resources: 19 | - openstackclients 20 | verbs: 21 | - create 22 | - delete 23 | - get 24 | - list 25 | - patch 26 | - update 27 | - watch 28 | - apiGroups: 29 | - client.openstack.org 30 | resources: 31 | - openstackclients/status 32 | verbs: 33 | - get 34 | -------------------------------------------------------------------------------- /config/default/cert_metrics_manager_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch adds the args, volumes, and ports to allow the manager to use the metrics-server certs. 2 | 3 | # Add the volumeMount for the metrics-server certs 4 | - op: add 5 | path: /spec/template/spec/containers/0/volumeMounts/- 6 | value: 7 | mountPath: /tmp/k8s-metrics-server/metrics-certs 8 | name: metrics-certs 9 | readOnly: true 10 | 11 | # Add the --metrics-cert-path argument for the metrics server 12 | - op: add 13 | path: /spec/template/spec/containers/0/args/- 14 | value: --metrics-cert-path=/tmp/k8s-metrics-server/metrics-certs 15 | 16 | # Add the metrics-server certs volume configuration 17 | - op: add 18 | path: /spec/template/spec/volumes/- 19 | value: 20 | name: metrics-certs 21 | secret: 22 | secretName: metrics-server-cert 23 | optional: false 24 | items: 25 | - key: ca.crt 26 | path: ca.crt 27 | - key: tls.crt 28 | path: tls.crt 29 | - key: tls.key 30 | path: tls.key 31 | -------------------------------------------------------------------------------- /config/rbac/dataplane_openstackdataplanenodeset_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants read-only access to dataplane.openstack.org resources. 5 | # This role is intended for users who need visibility into these resources 6 | # without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: dataplane-openstackdataplanenodeset-viewer-role 15 | rules: 16 | - apiGroups: 17 | - dataplane.openstack.org 18 | resources: 19 | - openstackdataplanenodesets 20 | verbs: 21 | - get 22 | - list 23 | - watch 24 | - apiGroups: 25 | - dataplane.openstack.org 26 | resources: 27 | - openstackdataplanenodesets/status 28 | verbs: 29 | - get 30 | -------------------------------------------------------------------------------- /config/rbac/dataplane_openstackdataplaneservice_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants read-only access to dataplane.openstack.org resources. 5 | # This role is intended for users who need visibility into these resources 6 | # without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: dataplane-openstackdataplaneservice-viewer-role 15 | rules: 16 | - apiGroups: 17 | - dataplane.openstack.org 18 | resources: 19 | - openstackdataplaneservices 20 | verbs: 21 | - get 22 | - list 23 | - watch 24 | - apiGroups: 25 | - dataplane.openstack.org 26 | resources: 27 | - openstackdataplaneservices/status 28 | verbs: 29 | - get 30 | -------------------------------------------------------------------------------- /config/rbac/core_openstackcontrolplane_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants permissions to create, update, and delete resources within the core.openstack.org. 5 | # This role is intended for users who need to manage these resources 6 | # but should not control RBAC or manage permissions for others. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: core-openstackcontrolplane-editor-role 15 | rules: 16 | - apiGroups: 17 | - core.openstack.org 18 | resources: 19 | - openstackcontrolplanes 20 | verbs: 21 | - create 22 | - delete 23 | - get 24 | - list 25 | - patch 26 | - update 27 | - watch 28 | - apiGroups: 29 | - core.openstack.org 30 | resources: 31 | - openstackcontrolplanes/status 32 | verbs: 33 | - get 34 | -------------------------------------------------------------------------------- /config/rbac/dataplane_openstackdataplanedeployment_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants read-only access to dataplane.openstack.org resources. 5 | # This role is intended for users who need visibility into these resources 6 | # without permissions to modify them. It is ideal for monitoring purposes and limited-access viewing. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: dataplane-openstackdataplanedeployment-viewer-role 15 | rules: 16 | - apiGroups: 17 | - dataplane.openstack.org 18 | resources: 19 | - openstackdataplanedeployments 20 | verbs: 21 | - get 22 | - list 23 | - watch 24 | - apiGroups: 25 | - dataplane.openstack.org 26 | resources: 27 | - openstackdataplanedeployments/status 28 | verbs: 29 | - get 30 | -------------------------------------------------------------------------------- /config/network-policy/allow-webhook-traffic.yaml: -------------------------------------------------------------------------------- 1 | # This NetworkPolicy allows ingress traffic to your webhook server running 2 | # as part of the controller-manager from specific namespaces and pods. CR(s) which uses webhooks 3 | # will only work when applied in namespaces labeled with 'webhook: enabled' 4 | apiVersion: networking.k8s.io/v1 5 | kind: NetworkPolicy 6 | metadata: 7 | labels: 8 | app.kubernetes.io/name: openstack-operator 9 | app.kubernetes.io/managed-by: kustomize 10 | name: allow-webhook-traffic 11 | namespace: system 12 | spec: 13 | podSelector: 14 | matchLabels: 15 | control-plane: controller-manager 16 | app.kubernetes.io/name: openstack-operator 17 | policyTypes: 18 | - Ingress 19 | ingress: 20 | # This allows ingress traffic from any namespace with the label webhook: enabled 21 | - from: 22 | - namespaceSelector: 23 | matchLabels: 24 | webhook: enabled # Only from namespaces with this label 25 | ports: 26 | - port: 443 27 | protocol: TCP 28 | -------------------------------------------------------------------------------- /test/kuttl/common/custom-ca.yaml: -------------------------------------------------------------------------------- 1 | # Secret to test the custom CA cert added to the bundle deployed by the os-operator 2 | apiVersion: v1 3 | kind: Secret 4 | type: Opaque 5 | metadata: 6 | name: ca-custom-kuttl 7 | labels: 8 | combined-ca-bundle: "" 9 | data: 10 | ca-custom-kuttl.pem: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJnVENDQVNlZ0F3SUJBZ0lSQU5TYWxJeHdEclZ5TVBLS3RHK0lLbzB3Q2dZSUtvWkl6ajBFQXdJd0lERWUKTUJ3R0ExVUVBeE1WY205dmRHTmhMV3QxZEhSc0xXbHVkR1Z5Ym1Gc01CNFhEVEkwTURJeU1qRTBNRGcwTTFvWApEVE0wTURJeE9URTBNRGcwTTFvd0lERWVNQndHQTFVRUF4TVZjbTl2ZEdOaExXdDFkSFJzTFdsdWRHVnlibUZzCk1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRTQzd2xOK05BQzhYZnkzSk43S1VaSVMvMjE2OTIKNXpWdHVyYnlpNllmZ3hXbFFONGV4ZU5IcVpGT3ZRcUVoZUVVSFR5K2lpWEVpWDVGcytCeit1eUZWYU5DTUVBdwpEZ1lEVlIwUEFRSC9CQVFEQWdLa01BOEdBMVVkRXdFQi93UUZNQU1CQWY4d0hRWURWUjBPQkJZRUZDRHJnYkhICjh4WmlKbnBKY2gzaEZyZEJLL3lKTUFvR0NDcUdTTTQ5QkFNQ0EwZ0FNRVVDSUNTY3A2QlE3eldQdnlobW9uK00KcTlvbk1PNlRYSVArczdtZjJGaXkvWkVsQWlFQXRxbkF3VE40UXRKQzIrMUZGVUNNd3dpSTZJTmM5blBDVHc1dgo5M1ZWR2ZNPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0t 11 | -------------------------------------------------------------------------------- /config/rbac/dataplane_openstackdataplanenodeset_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants permissions to create, update, and delete resources within the dataplane.openstack.org. 5 | # This role is intended for users who need to manage these resources 6 | # but should not control RBAC or manage permissions for others. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: dataplane-openstackdataplanenodeset-editor-role 15 | rules: 16 | - apiGroups: 17 | - dataplane.openstack.org 18 | resources: 19 | - openstackdataplanenodesets 20 | verbs: 21 | - create 22 | - delete 23 | - get 24 | - list 25 | - patch 26 | - update 27 | - watch 28 | - apiGroups: 29 | - dataplane.openstack.org 30 | resources: 31 | - openstackdataplanenodesets/status 32 | verbs: 33 | - get 34 | -------------------------------------------------------------------------------- /config/rbac/dataplane_openstackdataplaneservice_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants permissions to create, update, and delete resources within the dataplane.openstack.org. 5 | # This role is intended for users who need to manage these resources 6 | # but should not control RBAC or manage permissions for others. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: dataplane-openstackdataplaneservice-editor-role 15 | rules: 16 | - apiGroups: 17 | - dataplane.openstack.org 18 | resources: 19 | - openstackdataplaneservices 20 | verbs: 21 | - create 22 | - delete 23 | - get 24 | - list 25 | - patch 26 | - update 27 | - watch 28 | - apiGroups: 29 | - dataplane.openstack.org 30 | resources: 31 | - openstackdataplaneservices/status 32 | verbs: 33 | - get 34 | -------------------------------------------------------------------------------- /config/rbac/dataplane_openstackdataplanedeployment_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # This rule is not used by the project openstack-operator itself. 2 | # It is provided to allow the cluster admin to help manage permissions for users. 3 | # 4 | # Grants permissions to create, update, and delete resources within the dataplane.openstack.org. 5 | # This role is intended for users who need to manage these resources 6 | # but should not control RBAC or manage permissions for others. 7 | 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | kind: ClusterRole 10 | metadata: 11 | labels: 12 | app.kubernetes.io/name: openstack-operator 13 | app.kubernetes.io/managed-by: kustomize 14 | name: dataplane-openstackdataplanedeployment-editor-role 15 | rules: 16 | - apiGroups: 17 | - dataplane.openstack.org 18 | resources: 19 | - openstackdataplanedeployments 20 | verbs: 21 | - create 22 | - delete 23 | - get 24 | - list 25 | - patch 26 | - update 27 | - watch 28 | - apiGroups: 29 | - dataplane.openstack.org 30 | resources: 31 | - openstackdataplanedeployments/status 32 | verbs: 33 | - get 34 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-service-failure/00-create.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: failed-service 5 | spec: 6 | playbookContents: | 7 | - hosts: localhost 8 | gather_facts: no 9 | name: kuttl play 10 | tasks: 11 | - name: Copy absent file 12 | ansible.builtin.shell: | 13 | set -euxo pipefail 14 | cp absent failed_op 15 | --- 16 | apiVersion: dataplane.openstack.org/v1beta1 17 | kind: OpenStackDataPlaneNodeSet 18 | metadata: 19 | name: edpm-compute-no-nodes 20 | spec: 21 | preProvisioned: true 22 | env: 23 | - name: ANSIBLE_FORCE_COLOR 24 | value: "True" 25 | nodes: {} 26 | nodeTemplate: 27 | ansibleSSHPrivateKeySecret: dataplane-ansible-ssh-private-key-secret 28 | services: 29 | - failed-service 30 | --- 31 | apiVersion: dataplane.openstack.org/v1beta1 32 | kind: OpenStackDataPlaneDeployment 33 | metadata: 34 | name: edpm-compute-no-nodes 35 | spec: 36 | backoffLimit: 3 37 | nodeSets: 38 | - edpm-compute-no-nodes 39 | -------------------------------------------------------------------------------- /config/samples/dataplane/customnetworks/values.yaml: -------------------------------------------------------------------------------- 1 | # local-config: referenced, but not emitted by kustomize 2 | apiVersion: v1 3 | kind: DataPlaneConfig 4 | metadata: 5 | name: edpm-custom-networks-values 6 | annotations: 7 | config.kubernetes.io/local-config: "true" 8 | data: 9 | nodeset: 10 | nodetemplate: 11 | ansible: 12 | vars: 13 | neutron_public_interface_name: enp7s0 14 | ctlplane_dns_nameservers: 15 | - 192.168.1.254 16 | edpm_ovn_dbs: 17 | - 192.168.24.1 18 | edpm_sshd_allowed_ranges: ['192.168.0.0/24', '172.20.0.0/16'] 19 | nodes: 20 | edpm-compute-0: 21 | hostName: edpm-compute-0 22 | ansible: 23 | ansibleHost: 192.168.1.5 24 | networks: 25 | - name: ctlplane 26 | subnetName: subnet1 27 | defaultRoute: true 28 | fixedIP: 192.168.1.5 29 | - name: internalapi 30 | subnetName: subnet1 31 | - name: storage 32 | subnetName: subnet1 33 | - name: tenant 34 | subnetName: subnet1 35 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-extramounts/00-dataplane-create.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneService 3 | metadata: 4 | name: test-service 5 | spec: 6 | label: test-service 7 | playbook: test.yml 8 | --- 9 | apiVersion: dataplane.openstack.org/v1beta1 10 | kind: OpenStackDataPlaneNodeSet 11 | metadata: 12 | name: edpm-extramounts 13 | spec: 14 | preProvisioned: true 15 | services: 16 | - test-service 17 | nodes: {} 18 | nodeTemplate: 19 | ansibleSSHPrivateKeySecret: dataplane-ansible-ssh-private-key-secret 20 | extraMounts: 21 | - extraVolType: edpm-ansible 22 | mounts: 23 | - mountPath: /usr/share/ansible/collections/ansible_collections/osp/edpm 24 | name: edpm-ansible 25 | volumes: 26 | - name: edpm-ansible 27 | persistentVolumeClaim: 28 | claimName: edpm-ansible 29 | readOnly: true 30 | --- 31 | apiVersion: dataplane.openstack.org/v1beta1 32 | kind: OpenStackDataPlaneDeployment 33 | metadata: 34 | name: edpm-extramounts 35 | spec: 36 | nodeSets: 37 | - edpm-extramounts 38 | -------------------------------------------------------------------------------- /config/crd/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # This kustomization.yaml is not intended to be run by itself, 2 | # since it depends on service name and namespace that are out of this kustomize package. 3 | # It should be run by config/default 4 | resources: 5 | - bases/core.openstack.org_openstackcontrolplanes.yaml 6 | - bases/client.openstack.org_openstackclients.yaml 7 | - bases/core.openstack.org_openstackversions.yaml 8 | - bases/dataplane.openstack.org_openstackdataplanenodesets.yaml 9 | - bases/dataplane.openstack.org_openstackdataplaneservices.yaml 10 | - bases/dataplane.openstack.org_openstackdataplanedeployments.yaml 11 | #- bases/operator.openstack.org_openstacks.yaml 12 | # +kubebuilder:scaffold:crdkustomizeresource 13 | 14 | patches: 15 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. 16 | # patches here are for enabling the conversion webhook for each CRD 17 | # +kubebuilder:scaffold:crdkustomizewebhookpatch 18 | 19 | # [WEBHOOK] To enable webhook, uncomment the following section 20 | # the following config is for teaching kustomize how to do kustomization for CRDs. 21 | #configurations: 22 | #- kustomizeconfig.yaml 23 | -------------------------------------------------------------------------------- /hack/clean_local_webhook.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | 4 | oc delete validatingwebhookconfiguration vopenstackcontrolplane.kb.io --ignore-not-found 5 | oc delete mutatingwebhookconfiguration mopenstackcontrolplane.kb.io --ignore-not-found 6 | oc delete validatingwebhookconfiguration/vopenstackclient.kb.io --ignore-not-found 7 | oc delete mutatingwebhookconfiguration/mopenstackclient.kb.io --ignore-not-found 8 | oc delete validatingwebhookconfiguration/vopenstackversion.kb.io --ignore-not-found 9 | oc delete mutatingwebhookconfiguration/mopenstackversion.kb.io --ignore-not-found 10 | oc delete validatingwebhookconfiguration/vopenstackdataplanenodeset.kb.io --ignore-not-found 11 | oc delete validatingwebhookconfiguration/vopenstackdataplanedeployment.kb.io --ignore-not-found 12 | oc delete validatingwebhookconfiguration/vopenstackdataplaneservice.kb.io --ignore-not-found 13 | oc delete mutatingwebhookconfiguration/mopenstackdataplanenodeset.kb.io --ignore-not-found 14 | oc delete mutatingwebhookconfiguration/mopenstackdataplaneservice.kb.io --ignore-not-found 15 | oc delete mutatingwebhookconfiguration/mopenstackdataplanedeployment.kb.io --ignore-not-found 16 | -------------------------------------------------------------------------------- /api/dataplane/v1beta1/openstackdataplanenodeset.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta1 18 | 19 | import ( 20 | "regexp" 21 | ) 22 | 23 | // NodeHostNameIsFQDN Helper to check if a hostname is fqdn 24 | func NodeHostNameIsFQDN(hostname string) bool { 25 | // Regular expression to match a valid FQDN 26 | // This regex assumes that the hostname and domain name segments only contain letters, digits, hyphens, and periods. 27 | regex := `^([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.[a-zA-Z]{2,}$` 28 | 29 | match, _ := regexp.MatchString(regex, hostname) 30 | return match 31 | } 32 | -------------------------------------------------------------------------------- /config/default/manager_webhook_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch ensures the webhook certificates are properly mounted in the manager container. 2 | # It configures the necessary arguments, volumes, volume mounts, and container ports. 3 | 4 | # Add the --webhook-cert-path argument for configuring the webhook certificate path 5 | - op: add 6 | path: /spec/template/spec/containers/0/args/- 7 | value: --webhook-cert-path=/tmp/k8s-webhook-server/serving-certs 8 | 9 | # Add the volumeMount for the webhook certificates 10 | - op: add 11 | path: /spec/template/spec/containers/0/volumeMounts/- 12 | value: 13 | mountPath: /tmp/k8s-webhook-server/serving-certs 14 | name: webhook-certs 15 | readOnly: true 16 | 17 | # Add the port configuration for the webhook server 18 | - op: add 19 | path: /spec/template/spec/containers/0/ports/- 20 | value: 21 | containerPort: 9443 22 | name: webhook-server 23 | protocol: TCP 24 | 25 | # Add the volume configuration for the webhook certificates 26 | - op: add 27 | path: /spec/template/spec/volumes/- 28 | value: 29 | name: webhook-certs 30 | secret: 31 | secretName: webhook-server-cert 32 | -------------------------------------------------------------------------------- /.github/workflows/kustom.yaml: -------------------------------------------------------------------------------- 1 | name: Kustomize Build 2 | on: 3 | workflow_dispatch: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | branches: 9 | - main 10 | paths: 11 | - config/samples/** 12 | jobs: 13 | kustomize: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Install Go 17 | uses: actions/setup-go@v3 18 | with: 19 | go-version: 1.24.x 20 | - uses: actions/checkout@v4 21 | with: 22 | # this fetches all branches. Needed because we need gh-pages branch for deploy to work 23 | fetch-depth: 0 24 | - name: download kustomize 25 | run: | 26 | mkdir bin 27 | LINK=https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh 28 | curl -Ss $LINK | bash -s -- 5.0.1 ./bin 29 | - name: kustomize build 30 | run: | 31 | cd config/samples/dataplane 32 | 33 | for d in */ ; do 34 | echo "=============== $d ===============" 35 | ../../../bin/kustomize build --load-restrictor LoadRestrictionsNone "$d" 36 | done 37 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-deploy-global-service-test/02-add-nodeset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneNodeSet 3 | metadata: 4 | name: edpm-compute-beta-nodeset 5 | spec: 6 | baremetalSetTemplate: 7 | automatedCleaningMode: metadata 8 | bmhNamespace: openshift-machine-api 9 | cloudUserName: "" 10 | ctlplaneInterface: "" 11 | deploymentSSHSecret: "" 12 | hardwareReqs: 13 | cpuReqs: 14 | countReq: {} 15 | mhzReq: {} 16 | diskReqs: 17 | gbReq: {} 18 | ssdReq: {} 19 | memReqs: 20 | gbReq: {} 21 | preProvisioned: true 22 | services: 23 | - download-cache 24 | - bootstrap 25 | env: 26 | - name: ANSIBLE_FORCE_COLOR 27 | value: "True" 28 | nodes: {} 29 | nodeTemplate: 30 | ansibleSSHPrivateKeySecret: dataplane-ansible-ssh-private-key-secret 31 | ansible: 32 | ansibleUser: cloud-admin 33 | --- 34 | apiVersion: dataplane.openstack.org/v1beta1 35 | kind: OpenStackDataPlaneDeployment 36 | metadata: 37 | name: edpm-multinodeset 38 | spec: 39 | nodeSets: 40 | - edpm-compute-global 41 | - edpm-compute-beta-nodeset 42 | -------------------------------------------------------------------------------- /config/samples/nic-config-samples/single_nic_vlans/single_nic_vlans_bgp.j2: -------------------------------------------------------------------------------- 1 | --- 2 | {% set mtu_list = [ctlplane_mtu] %} 3 | {% for network in nodeset_networks %} 4 | {% set _ = mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) %} 5 | {%- endfor %} 6 | {% set min_viable_mtu = mtu_list | max %} 7 | network_config: 8 | - type: interface 9 | name: nic1 10 | mtu: {{ ctlplane_mtu }} 11 | dns_servers: {{ ctlplane_dns_nameservers }} 12 | domain: {{ dns_search_domains }} 13 | routes: {{ ctlplane_host_routes }} 14 | use_dhcp: false 15 | addresses: 16 | - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_cidr }} 17 | {% for network in nodeset_networks %} 18 | - type: vlan 19 | device: nic1 20 | mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} 21 | vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }} 22 | addresses: 23 | - ip_netmask: 24 | {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }} 25 | routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }} 26 | {% endfor %} 27 | - type: ovs_bridge 28 | name: {{ neutron_physical_bridge_name }} 29 | use_dhcp: false 30 | -------------------------------------------------------------------------------- /config/samples/dataplane/sriov/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1alpha1 2 | kind: Component 3 | 4 | namespace: openstack 5 | nameSuffix: -sriov 6 | 7 | components: 8 | - ../preprovisioned # for baremetal nodes, replace with baremetal 9 | 10 | resources: 11 | - values.yaml 12 | 13 | replacements: 14 | # OpenStackDataPlaneNodeSet customizations 15 | - source: 16 | kind: DataPlaneConfig 17 | name: edpm-sriov-values 18 | fieldPath: data.nodeset.services 19 | targets: 20 | - select: 21 | kind: OpenStackDataPlaneNodeSet 22 | fieldPaths: 23 | - spec.services 24 | options: 25 | create: true 26 | 27 | patches: 28 | - target: 29 | kind: OpenStackDataPlaneNodeSet 30 | name: .* 31 | patch: |- 32 | - op: copy 33 | from: /spec/nodes/edpm-compute-0 34 | path: /spec/nodes/edpm-compute-1 35 | - op: replace 36 | path: /spec/nodes/edpm-compute-1/ansible/ansibleHost 37 | value: 192.168.122.101 38 | - op: replace 39 | path: /spec/nodes/edpm-compute-1/hostName 40 | value: edpm-compute-1 41 | - op: replace 42 | path: /spec/nodes/edpm-compute-1/networks/0/fixedIP 43 | value: 192.168.122.101 44 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-deploy-no-nodes-test/06-add-nodeset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: dataplane.openstack.org/v1beta1 2 | kind: OpenStackDataPlaneNodeSet 3 | metadata: 4 | name: edpm-compute-beta-nodeset 5 | spec: 6 | baremetalSetTemplate: 7 | automatedCleaningMode: metadata 8 | bmhNamespace: openshift-machine-api 9 | cloudUserName: "" 10 | ctlplaneInterface: "" 11 | deploymentSSHSecret: "" 12 | hardwareReqs: 13 | cpuReqs: 14 | countReq: {} 15 | mhzReq: {} 16 | diskReqs: 17 | gbReq: {} 18 | ssdReq: {} 19 | memReqs: 20 | gbReq: {} 21 | preProvisioned: true 22 | services: 23 | - download-cache 24 | - bootstrap 25 | env: 26 | - name: ANSIBLE_FORCE_COLOR 27 | value: "True" 28 | nodes: {} 29 | nodeTemplate: 30 | ansibleSSHPrivateKeySecret: dataplane-ansible-ssh-private-key-secret 31 | ansible: 32 | ansibleUser: cloud-admin 33 | --- 34 | apiVersion: dataplane.openstack.org/v1beta1 35 | kind: OpenStackDataPlaneDeployment 36 | metadata: 37 | name: edpm-multinodeset 38 | spec: 39 | nodeSets: 40 | - edpm-compute-no-nodes 41 | - edpm-compute-beta-nodeset 42 | ansibleExtraVars: 43 | foo: bar 44 | -------------------------------------------------------------------------------- /config/samples/tls/custom_route_cert/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - ../../base/openstackcontrolplane 3 | - placement-cert-data.yaml 4 | 5 | patches: 6 | - target: 7 | kind: OpenStackControlPlane 8 | name: .* 9 | patch: |- 10 | - op: replace 11 | path: /metadata/name 12 | value: openstack 13 | 14 | - path: patch.yaml 15 | 16 | # Use replacements to inject cert data from ConfigMap 17 | replacements: 18 | - source: 19 | kind: ConfigMap 20 | name: placement-cert-data 21 | fieldPath: data.[tls.crt] 22 | targets: 23 | - select: 24 | kind: OpenStackControlPlane 25 | fieldPaths: 26 | - spec.placement.apiOverride.route.spec.tls.certificate 27 | 28 | - source: 29 | kind: ConfigMap 30 | name: placement-cert-data 31 | fieldPath: data.[tls.key] 32 | targets: 33 | - select: 34 | kind: OpenStackControlPlane 35 | fieldPaths: 36 | - spec.placement.apiOverride.route.spec.tls.key 37 | 38 | - source: 39 | kind: ConfigMap 40 | name: placement-cert-data 41 | fieldPath: data.[ca.crt] 42 | targets: 43 | - select: 44 | kind: OpenStackControlPlane 45 | fieldPaths: 46 | - spec.placement.apiOverride.route.spec.tls.caCertificate 47 | -------------------------------------------------------------------------------- /config/samples/dataplane/nmstate/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1alpha1 2 | kind: Component 3 | 4 | namespace: openstack 5 | 6 | components: 7 | - ../preprovisioned # for baremetal nodes, replace with baremetal 8 | 9 | resources: 10 | - values.yaml 11 | 12 | replacements: 13 | # OpenStackDataPlaneNodeSet customizations 14 | - source: 15 | kind: DataPlaneConfig 16 | name: edpm-nmstate-values 17 | fieldPath: data.nodeset.nodetemplate.ansible.vars 18 | targets: 19 | - select: 20 | kind: OpenStackDataPlaneNodeSet 21 | fieldPaths: 22 | - spec.nodeTemplate.ansible.ansibleVars 23 | options: 24 | create: true 25 | 26 | patches: 27 | - target: 28 | kind: OpenStackDataPlaneNodeSet 29 | name: .* 30 | patch: |- 31 | - op: copy 32 | from: /spec/nodes/edpm-compute-0 33 | path: /spec/nodes/edpm-compute-1 34 | - op: replace 35 | path: /spec/nodes/edpm-compute-1/ansible/ansibleHost 36 | value: 192.168.122.101 37 | - op: replace 38 | path: /spec/nodes/edpm-compute-1/hostName 39 | value: edpm-compute-1 40 | - op: replace 41 | path: /spec/nodes/edpm-compute-1/networks/0/fixedIP 42 | value: 192.168.122.101 43 | -------------------------------------------------------------------------------- /config/samples/dataplane/baremetal/values.yaml: -------------------------------------------------------------------------------- 1 | # local-config: referenced, but not emitted by kustomize 2 | apiVersion: v1 3 | kind: DataPlaneConfig 4 | metadata: 5 | name: edpm-baremetal-values 6 | annotations: 7 | config.kubernetes.io/local-config: "true" 8 | data: 9 | preProvisioned: false 10 | nodeset: 11 | baremetalsettemplate: 12 | bmhLabelSelector: 13 | app: openstack 14 | ctlplaneInterface: enp1s0 15 | cloudUserName: cloud-admin 16 | nodetemplate: 17 | ansible: 18 | vars: 19 | # edpm firewall, change the allowed CIDR if needed 20 | edpm_sshd_allowed_ranges: ['192.168.111.0/24'] 21 | networks: 22 | - defaultRoute: true 23 | name: ctlplane 24 | subnetName: subnet1 25 | - name: internalapi 26 | subnetName: subnet1 27 | - name: storage 28 | subnetName: subnet1 29 | - name: tenant 30 | subnetName: subnet1 31 | nodes: 32 | edpm-compute-0: 33 | hostName: edpm-compute-0 34 | # arbitrary labels that must be set on a BaremetalSetHost in order for it to be 35 | # selected for this node 36 | bmhLabelSelector: 37 | hostName: edpm-compute-0 38 | -------------------------------------------------------------------------------- /docs/assemblies/hotfixing-the-data-plane.adoc: -------------------------------------------------------------------------------- 1 | [id="assembly_hotfixing-the-data-plane"] 2 | = Hotfixing the data plane 3 | 4 | :context: dataplane 5 | 6 | [role="_abstract"] 7 | You can update the OpenStack data plane when hotfix content is available. Hotfix content 8 | can be delivered as RPM packages or container images. 9 | 10 | You apply a container hotfix to the data plane nodes by updating any running 11 | containers to run from container images where the hotfix content has been 12 | applied. Container hotfix content can be delivered as either RPM’s or already 13 | updated container images. 14 | 15 | How the software is installed on the data plane nodes determines which of the 16 | following methods you need to use to apply the hotfix content: 17 | 18 | * Node software was installed by using RPMs: Apply the hotfix to the RPM content. 19 | * Node software was installed by using container images: Apply the hotfix to the container content with either RPMs or container images. 20 | 21 | 22 | include::proc_hotfixing-the-data-plane-rpm-content.adoc[leveloffset=+1] 23 | 24 | include::proc_hotfixing-the-data-plane-container-content-rpms.adoc[leveloffset=+1] 25 | 26 | include::proc_hotfixing-the-data-plane-container-content-images.adoc[leveloffset=+1] 27 | -------------------------------------------------------------------------------- /config/samples/dataplane/base/files/nic-config.j2: -------------------------------------------------------------------------------- 1 | --- 2 | {% set mtu_list = [ctlplane_mtu] %} 3 | {% for network in nodeset_networks %} 4 | {% set _ = mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) %} 5 | {%- endfor %} 6 | {% set min_viable_mtu = mtu_list | max %} 7 | network_config: 8 | - type: ovs_bridge 9 | name: {{ neutron_physical_bridge_name }} 10 | mtu: {{ min_viable_mtu }} 11 | use_dhcp: false 12 | dns_servers: {{ ctlplane_dns_nameservers }} 13 | domain: {{ dns_search_domains }} 14 | addresses: 15 | - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_cidr }} 16 | routes: {{ ctlplane_host_routes }} 17 | members: 18 | - type: interface 19 | name: nic1 20 | mtu: {{ min_viable_mtu }} 21 | # force the MAC address of the bridge to this interface 22 | primary: true 23 | {% for network in nodeset_networks %} 24 | - type: vlan 25 | mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} 26 | vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }} 27 | addresses: 28 | - ip_netmask: 29 | {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }} 30 | routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }} 31 | {% endfor %} 32 | -------------------------------------------------------------------------------- /config/operator/manifests/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # These resources constitute the fully configured set of manifests 2 | # used to generate the 'manifests/' directory in a bundle. 3 | resources: 4 | - bases/openstack-operator.clusterserviceversion.yaml 5 | 6 | # [WEBHOOK] To enable webhooks, uncomment all the sections with [WEBHOOK] prefix. 7 | # Do NOT uncomment sections with prefix [CERTMANAGER], as OLM does not support cert-manager. 8 | # These patches remove the unnecessary "cert" volume and its manager container volumeMount. 9 | #patchesJson6902: 10 | #- target: 11 | # group: apps 12 | # version: v1 13 | # kind: Deployment 14 | # name: controller-manager 15 | # namespace: system 16 | # patch: |- 17 | # # Remove the manager container's "cert" volumeMount, since OLM will create and mount a set of certs. 18 | # # Update the indices in this path if adding or removing containers/volumeMounts in the manager's Deployment. 19 | # - op: remove 20 | # path: /spec/template/spec/containers/1/volumeMounts/0 21 | # # Remove the "cert" volume, since OLM will create and mount a set of certs. 22 | # # Update the indices in this path if adding or removing volumes in the manager's Deployment. 23 | # - op: remove 24 | # path: /spec/template/spec/volumes/0 25 | -------------------------------------------------------------------------------- /config/samples/nic-config-samples/single_nic_vlans/single_nic_vlans_storage.j2: -------------------------------------------------------------------------------- 1 | --- 2 | {% set mtu_list = [ctlplane_mtu] %} 3 | {% for network in nodeset_networks %} 4 | {% set _ = mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) %} 5 | {%- endfor %} 6 | {% set min_viable_mtu = mtu_list | max %} 7 | network_config: 8 | - type: ovs_bridge 9 | name: br-storage 10 | mtu: {{ min_viable_mtu }} 11 | use_dhcp: false 12 | dns_servers: {{ ctlplane_dns_nameservers }} 13 | domain: {{ dns_search_domains }} 14 | addresses: 15 | - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_cidr }} 16 | routes: {{ ctlplane_host_routes }} 17 | members: 18 | - type: interface 19 | name: nic1 20 | mtu: {{ min_viable_mtu }} 21 | # force the MAC address of the bridge to this interface 22 | primary: true 23 | {% for network in nodeset_networks %} 24 | - type: vlan 25 | mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} 26 | vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }} 27 | addresses: 28 | - ip_netmask: 29 | {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }} 30 | routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }} 31 | {% endfor %} 32 | -------------------------------------------------------------------------------- /config/samples/nic-config-samples/single_nic_vlans/single_nic_vlans.j2: -------------------------------------------------------------------------------- 1 | --- 2 | {% set mtu_list = [ctlplane_mtu] %} 3 | {% for network in nodeset_networks %} 4 | {% set _ = mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) %} 5 | {%- endfor %} 6 | {% set min_viable_mtu = mtu_list | max %} 7 | network_config: 8 | - type: ovs_bridge 9 | name: {{ neutron_physical_bridge_name }} 10 | mtu: {{ min_viable_mtu }} 11 | use_dhcp: false 12 | dns_servers: {{ ctlplane_dns_nameservers }} 13 | domain: {{ dns_search_domains }} 14 | addresses: 15 | - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_cidr }} 16 | routes: {{ ctlplane_host_routes }} 17 | members: 18 | - type: interface 19 | name: nic1 20 | mtu: {{ min_viable_mtu }} 21 | # force the MAC address of the bridge to this interface 22 | primary: true 23 | {% for network in nodeset_networks %} 24 | - type: vlan 25 | mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} 26 | vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }} 27 | addresses: 28 | - ip_netmask: 29 | {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }} 30 | routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }} 31 | {% endfor %} 32 | -------------------------------------------------------------------------------- /config/samples/dataplane/networker/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1alpha1 2 | kind: Component 3 | 4 | namespace: openstack 5 | nameSuffix: -networker 6 | 7 | components: 8 | - ../preprovisioned # for baremetal nodes, replace with baremetal 9 | 10 | resources: 11 | - values.yaml 12 | 13 | replacements: 14 | # OpenStackDataPlaneNodeSet customizations 15 | - source: 16 | kind: DataPlaneConfig 17 | name: edpm-networker-values 18 | fieldPath: data.nodeset.nodetemplate.ansible.vars.edpm_enable_chassis_gw 19 | targets: 20 | - select: 21 | kind: OpenStackDataPlaneNodeSet 22 | fieldPaths: 23 | - spec.nodeTemplate.ansible.ansibleVars.edpm_enable_chassis_gw 24 | options: 25 | create: true 26 | - source: 27 | kind: DataPlaneConfig 28 | name: edpm-networker-values 29 | fieldPath: data.nodeset.services 30 | targets: 31 | - select: 32 | kind: OpenStackDataPlaneNodeSet 33 | fieldPaths: 34 | - spec.services 35 | options: 36 | create: true 37 | - source: 38 | kind: DataPlaneConfig 39 | name: edpm-networker-values 40 | fieldPath: data.nodeset.nodes 41 | targets: 42 | - select: 43 | kind: OpenStackDataPlaneNodeSet 44 | fieldPaths: 45 | - spec.nodes 46 | options: 47 | create: true 48 | -------------------------------------------------------------------------------- /config/manifests/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # These resources constitute the fully configured set of manifests 2 | # used to generate the 'manifests/' directory in a bundle. 3 | resources: 4 | - bases/openstack-operator.clusterserviceversion.yaml 5 | - ../default 6 | - ../samples 7 | - ../scorecard 8 | 9 | # [WEBHOOK] To enable webhooks, uncomment all the sections with [WEBHOOK] prefix. 10 | # Do NOT uncomment sections with prefix [CERTMANAGER], as OLM does not support cert-manager. 11 | # These patches remove the unnecessary "cert" volume and its manager container volumeMount. 12 | #patches: 13 | #- target: 14 | # group: apps 15 | # version: v1 16 | # kind: Deployment 17 | # name: controller-manager 18 | # namespace: system 19 | # patch: |- 20 | # # Remove the manager container's "cert" volumeMount, since OLM will create and mount a set of certs. 21 | # # Update the indices in this path if adding or removing containers/volumeMounts in the manager's Deployment. 22 | # - op: remove 23 | 24 | # path: /spec/template/spec/containers/0/volumeMounts/0 25 | # # Remove the "cert" volume, since OLM will create and mount a set of certs. 26 | # # Update the indices in this path if adding or removing volumes in the manager's Deployment. 27 | # - op: remove 28 | # path: /spec/template/spec/volumes/0 29 | -------------------------------------------------------------------------------- /config/samples/nic-config-samples/single_nic_vlans/controller_no_external.j2: -------------------------------------------------------------------------------- 1 | --- 2 | {% set mtu_list = [ctlplane_mtu] %} 3 | {% for network in nodeset_networks %} 4 | {% set _ = mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) %} 5 | {%- endfor %} 6 | {% set min_viable_mtu = mtu_list | max %} 7 | network_config: 8 | - type: ovs_bridge 9 | name: {{ neutron_physical_bridge_name }} 10 | mtu: {{ min_viable_mtu }} 11 | use_dhcp: false 12 | dns_servers: {{ ctlplane_dns_nameservers }} 13 | domain: {{ dns_search_domains }} 14 | addresses: 15 | - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_cidr }} 16 | routes: {{ ctlplane_host_routes }} 17 | members: 18 | - type: interface 19 | name: nic1 20 | mtu: {{ min_viable_mtu }} 21 | # force the MAC address of the bridge to this interface 22 | primary: true 23 | {% for network in nodeset_networks if network != 'external' %} 24 | - type: vlan 25 | mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} 26 | vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }} 27 | addresses: 28 | - ip_netmask: 29 | {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }} 30 | routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }} 31 | {% endfor %} 32 | -------------------------------------------------------------------------------- /config/operator/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Adds namespace to all resources. 2 | namespace: '{{ .OperatorNamespace }}' 3 | 4 | # Value of this field is prepended to the 5 | # names of all resources, e.g. a deployment named 6 | # "wordpress" becomes "alices-wordpress". 7 | # Note that it should also match with the prefix (text before '-') of the namespace 8 | # field above. 9 | namePrefix: openstack-operator- 10 | 11 | resources: 12 | # All RBAC will be applied under this service account in 13 | # the deployment namespace. You may comment out this resource 14 | # if your manager will use a service account that exists at 15 | # runtime. Be sure to update RoleBinding and ClusterRoleBinding 16 | # subjects if changing service account names. 17 | - service_account.yaml 18 | - role.yaml 19 | - role_binding.yaml 20 | - leader_election_role.yaml 21 | - leader_election_role_binding.yaml 22 | # The following RBAC configurations are used to protect 23 | # the metrics endpoint with authn/authz. These configurations 24 | # ensure that only authorized users and service accounts 25 | # can access the metrics endpoint. Comment the following 26 | # permissions if you want to disable this protection. 27 | # More info: https://book.kubebuilder.io/reference/metrics.html 28 | - metrics_auth_role.yaml 29 | - metrics_auth_role_binding.yaml 30 | - metrics_reader_role.yaml 31 | -------------------------------------------------------------------------------- /config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | # Prometheus Monitor Service (Metrics) 2 | apiVersion: monitoring.coreos.com/v1 3 | kind: ServiceMonitor 4 | metadata: 5 | labels: 6 | control-plane: controller-manager 7 | app.kubernetes.io/name: openstack-operator 8 | app.kubernetes.io/managed-by: kustomize 9 | name: controller-manager-metrics-monitor 10 | namespace: system 11 | spec: 12 | endpoints: 13 | - path: /metrics 14 | port: https # Ensure this is the name of the port that exposes HTTPS metrics 15 | scheme: https 16 | bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 17 | tlsConfig: 18 | # TODO(user): The option insecureSkipVerify: true is not recommended for production since it disables 19 | # certificate verification, exposing the system to potential man-in-the-middle attacks. 20 | # For production environments, it is recommended to use cert-manager for automatic TLS certificate management. 21 | # To apply this configuration, enable cert-manager and use the patch located at config/prometheus/servicemonitor_tls_patch.yaml, 22 | # which securely references the certificate from the 'metrics-server-cert' secret. 23 | insecureSkipVerify: true 24 | selector: 25 | matchLabels: 26 | control-plane: controller-manager 27 | app.kubernetes.io/name: openstack-operator 28 | -------------------------------------------------------------------------------- /api/core/v1beta1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1beta1 contains API Schema definitions for the core v1beta1 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=core.openstack.org 20 | package v1beta1 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | ) 26 | 27 | var ( 28 | // GroupVersion is group version used to register these objects 29 | GroupVersion = schema.GroupVersion{Group: "core.openstack.org", Version: "v1beta1"} 30 | 31 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 32 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 33 | 34 | // AddToScheme adds the types in this group-version to the given scheme. 35 | AddToScheme = SchemeBuilder.AddToScheme 36 | ) 37 | -------------------------------------------------------------------------------- /api/client/v1beta1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1beta1 contains API Schema definitions for the client v1beta1 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=client.openstack.org 20 | package v1beta1 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | ) 26 | 27 | var ( 28 | // GroupVersion is group version used to register these objects 29 | GroupVersion = schema.GroupVersion{Group: "client.openstack.org", Version: "v1beta1"} 30 | 31 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 32 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 33 | 34 | // AddToScheme adds the types in this group-version to the given scheme. 35 | AddToScheme = SchemeBuilder.AddToScheme 36 | ) 37 | -------------------------------------------------------------------------------- /api/dataplane/v1beta1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1beta1 contains API Schema definitions for the dataplane v1beta1 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=dataplane.openstack.org 20 | package v1beta1 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | ) 26 | 27 | var ( 28 | // GroupVersion is group version used to register these objects 29 | GroupVersion = schema.GroupVersion{Group: "dataplane.openstack.org", Version: "v1beta1"} 30 | 31 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 32 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 33 | 34 | // AddToScheme adds the types in this group-version to the given scheme. 35 | AddToScheme = SchemeBuilder.AddToScheme 36 | ) 37 | -------------------------------------------------------------------------------- /api/operator/v1beta1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1beta1 contains API Schema definitions for the operator v1beta1 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=operator.openstack.org 20 | package v1beta1 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | ) 26 | 27 | var ( 28 | // GroupVersion is group version used to register these objects 29 | GroupVersion = schema.GroupVersion{Group: "operator.openstack.org", Version: "v1beta1"} 30 | 31 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 32 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 33 | 34 | // AddToScheme adds the types in this group-version to the given scheme. 35 | AddToScheme = SchemeBuilder.AddToScheme 36 | ) 37 | -------------------------------------------------------------------------------- /.github/workflows/crd-sync-check.yaml: -------------------------------------------------------------------------------- 1 | # a simple boolean to check of a CRD sync check is needed 2 | name: CRD sync check 3 | 4 | on: 5 | schedule: 6 | - cron: '0 */2 * * *' # every 2 hours 7 | workflow_dispatch: 8 | inputs: 9 | branch_name: 10 | default: 'main' 11 | type: string 12 | workflow_call: 13 | inputs: 14 | branch_name: 15 | default: 'main' 16 | type: string 17 | 18 | jobs: 19 | 20 | crd-sync-check: 21 | if: github.repository_owner == 'openstack-k8s-operators' 22 | name: CRD sync check 23 | runs-on: ubuntu-latest 24 | 25 | steps: 26 | 27 | - name: Set branch 28 | id: set_branch 29 | run: | 30 | BRANCH_NAME="${{ inputs.branch_name || github.ref_name }}" 31 | echo "branch name set to: $BRANCH_NAME" 32 | echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT 33 | 34 | - name: Checkout repository 35 | uses: actions/checkout@v4 36 | with: 37 | ref: ${{ steps.set_branch.outputs.branch_name }} 38 | 39 | - name: run make force-bump 40 | shell: bash 41 | run: | 42 | BRANCH='${{ steps.set_branch.outputs.branch_name }}' make force-bump 43 | 44 | - name: run make bindata 45 | shell: bash 46 | run: | 47 | make bindata 48 | 49 | - name: Fail if there are local CRD changes in bindata/crds 50 | run: | 51 | git diff --quiet bindata/crds 52 | -------------------------------------------------------------------------------- /config/scorecard/patches/olm.config.yaml: -------------------------------------------------------------------------------- 1 | - op: add 2 | path: /stages/0/tests/- 3 | value: 4 | entrypoint: 5 | - scorecard-test 6 | - olm-bundle-validation 7 | image: quay.io/operator-framework/scorecard-test:v1.41.1 8 | labels: 9 | suite: olm 10 | test: olm-bundle-validation-test 11 | - op: add 12 | path: /stages/0/tests/- 13 | value: 14 | entrypoint: 15 | - scorecard-test 16 | - olm-crds-have-validation 17 | image: quay.io/operator-framework/scorecard-test:v1.41.1 18 | labels: 19 | suite: olm 20 | test: olm-crds-have-validation-test 21 | - op: add 22 | path: /stages/0/tests/- 23 | value: 24 | entrypoint: 25 | - scorecard-test 26 | - olm-crds-have-resources 27 | image: quay.io/operator-framework/scorecard-test:v1.41.1 28 | labels: 29 | suite: olm 30 | test: olm-crds-have-resources-test 31 | - op: add 32 | path: /stages/0/tests/- 33 | value: 34 | entrypoint: 35 | - scorecard-test 36 | - olm-spec-descriptors 37 | image: quay.io/operator-framework/scorecard-test:v1.41.1 38 | labels: 39 | suite: olm 40 | test: olm-spec-descriptors-test 41 | - op: add 42 | path: /stages/0/tests/- 43 | value: 44 | entrypoint: 45 | - scorecard-test 46 | - olm-status-descriptors 47 | image: quay.io/operator-framework/scorecard-test:v1.41.1 48 | labels: 49 | suite: olm 50 | test: olm-status-descriptors-test 51 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 42 | 43 | 44 | 45 | 46 |
47 | ControlPlane 48 | DataPlane 49 |
50 | 51 |
52 | 53 |
54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-tls-cert-rotation/02-assert-endpoint-proto.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: kuttl.dev/v1beta1 3 | kind: TestAssert 4 | timeout: 500 5 | commands: 6 | - script: | 7 | echo "Waiting for OpenStack control plane to be ready..." 8 | oc wait openstackcontrolplane -n $NAMESPACE --for=condition=Ready --timeout=400s -l core.openstack.org/openstackcontrolplane 9 | - script: | 10 | echo "Fail if internal http endpoints are registered" 11 | oc exec -i openstackclient -n $NAMESPACE -- bash -c "openstack endpoint list --interface internal -f value -c URL" | grep 'http:' && exit 1 12 | exit 0 13 | - script: | 14 | echo "check ovn sb internalDbAddress use ssl" 15 | oc get -n $NAMESPACE OVNDBCluster ovndbcluster-sb -o jsonpath={.status.internalDbAddress} | grep -q ssl 16 | - script: | 17 | echo "check ovn sb DB connection use ssl" 18 | oc exec -i statefulset/ovsdbserver-sb -n $NAMESPACE -- bash -c "ovn-sbctl --no-leader-only get-connection | grep -q pssl" 19 | - script: | 20 | echo "check nova transport_url use ssl" 21 | oc exec -i statefulset/nova-cell1-conductor -n $NAMESPACE -- bash -c "grep transport_url /etc/nova/nova.conf.d/01-nova.conf | grep -q 'ssl=1'" 22 | - script: | 23 | echo "check neutron ovn_sb_connection url ssl" 24 | oc exec -i deployment/neutron -n $NAMESPACE -- bash -c "grep ovn_sb_connection /etc/neutron/neutron.conf.d/01-neutron.conf| grep -q ssl" 25 | -------------------------------------------------------------------------------- /config/samples/nic-config-samples/bonds_vlans/bonds_vlans_storage.j2: -------------------------------------------------------------------------------- 1 | --- 2 | {% set mtu_list = [ctlplane_mtu] %} 3 | {% for network in nodeset_networks %} 4 | {% set _ = mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) %} 5 | {%- endfor %} 6 | {% set min_viable_mtu = mtu_list | max %} 7 | network_config: 8 | - type: interface 9 | name: nic1 10 | mtu: {{ ctlplane_mtu }} 11 | use_dhcp: false 12 | addresses: 13 | - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_cidr }} 14 | routes: {{ ctlplane_host_routes }} 15 | - type: ovs_bridge 16 | name: br-bond 17 | dns_servers: {{ ctlplane_dns_nameservers }} 18 | domain: {{ dns_search_domains }} 19 | members: 20 | - type: ovs_bond 21 | name: bond1 22 | mtu: {{ min_viable_mtu }} 23 | ovs_options: {{ edpm_bond_interface_ovs_options }} 24 | members: 25 | - type: interface 26 | name: nic2 27 | mtu: {{ min_viable_mtu }} 28 | primary: true 29 | - type: interface 30 | name: nic3 31 | mtu: {{ min_viable_mtu }} 32 | {% for network in nodeset_networks %} 33 | - type: vlan 34 | mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} 35 | vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }} 36 | addresses: 37 | - ip_netmask: {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }} 38 | routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }} 39 | {% endfor %} 40 | -------------------------------------------------------------------------------- /config/samples/dataplane/bgp/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1alpha1 2 | kind: Component 3 | 4 | namespace: openstack 5 | 6 | components: 7 | - ../preprovisioned # for baremetal nodes, replace with baremetal 8 | 9 | resources: 10 | - values.yaml 11 | 12 | replacements: 13 | # OpenStackDataPlaneNodeSet customizations 14 | - source: 15 | kind: DataPlaneConfig 16 | name: edpm-bgp-values 17 | fieldPath: data.nodeset.nodetemplate.ansible.vars 18 | targets: 19 | - select: 20 | kind: OpenStackDataPlaneNodeSet 21 | fieldPaths: 22 | - spec.nodeTemplate.ansible.ansibleVars 23 | options: 24 | create: true 25 | - source: 26 | kind: DataPlaneConfig 27 | name: edpm-bgp-values 28 | fieldPath: data.nodeset.services 29 | targets: 30 | - select: 31 | kind: OpenStackDataPlaneNodeSet 32 | fieldPaths: 33 | - spec.services 34 | options: 35 | create: true 36 | 37 | patches: 38 | - target: 39 | kind: OpenStackDataPlaneNodeSet 40 | name: .* 41 | patch: |- 42 | - op: copy 43 | from: /spec/nodes/edpm-compute-0 44 | path: /spec/nodes/edpm-compute-1 45 | - op: replace 46 | path: /spec/nodes/edpm-compute-1/ansible/ansibleHost 47 | value: 192.168.122.101 48 | - op: replace 49 | path: /spec/nodes/edpm-compute-1/hostName 50 | value: edpm-compute-1 51 | - op: replace 52 | path: /spec/nodes/edpm-compute-1/networks/0/fixedIP 53 | value: 192.168.122.101 54 | -------------------------------------------------------------------------------- /config/samples/nic-config-samples/bonds_vlans/bonds_vlans.j2: -------------------------------------------------------------------------------- 1 | --- 2 | {% set mtu_list = [ctlplane_mtu] %} 3 | {% for network in nodeset_networks %} 4 | {% set _ = mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) %} 5 | {%- endfor %} 6 | {% set min_viable_mtu = mtu_list | max %} 7 | network_config: 8 | - type: interface 9 | name: nic1 10 | mtu: {{ ctlplane_mtu }} 11 | use_dhcp: false 12 | addresses: 13 | - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_cidr }} 14 | routes: {{ ctlplane_host_routes }} 15 | - type: ovs_bridge 16 | name: {{ neutron_physical_bridge_name }} 17 | dns_servers: {{ ctlplane_dns_nameservers }} 18 | domain: {{ dns_search_domains }} 19 | members: 20 | - type: ovs_bond 21 | name: bond1 22 | mtu: {{ min_viable_mtu }} 23 | ovs_options: {{ edpm_bond_interface_ovs_options }} 24 | members: 25 | - type: interface 26 | name: nic2 27 | mtu: {{ min_viable_mtu }} 28 | primary: true 29 | - type: interface 30 | name: nic3 31 | mtu: {{ min_viable_mtu }} 32 | {% for network in nodeset_networks %} 33 | - type: vlan 34 | mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} 35 | vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }} 36 | addresses: 37 | - ip_netmask: {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }} 38 | routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }} 39 | {% endfor %} 40 | -------------------------------------------------------------------------------- /docs/dataplane.adoc: -------------------------------------------------------------------------------- 1 | = OpenStack Data Plane Operator 2 | :toc: left 3 | :toclevels: 3 4 | :icons: font 5 | :compat-mode: 6 | :doctype: book 7 | :context: osp 8 | 9 | The openstack-operator automates the deployment of an OpenStack dataplane. A 10 | dataplane is a collection of nodes that will be used for hosting OpenStack 11 | workloads. The openstack-operator prepares the nodes with enough operating 12 | system configuration so that they are ready for hosting other required 13 | OpenStack services and workloads. 14 | 15 | See https://github.com/openstack-k8s-operators/dev-docs[contributing] for notes for developers and 16 | contributors, running the operator, building the documentation, etc. 17 | 18 | See <<_data_plane_design,design>> for details about the dataplane design. 19 | 20 | <> documents how to create a dataplane. 21 | 22 | The documentation source is kept within the openstack-operator repo in the 23 | https://github.com/openstack-k8s-operators/openstack-operator/tree/main/docs[docs] directory. The full 24 | generated documentation from that source is available at 25 | https://openstack-k8s-operators.github.io/openstack-operator/. 26 | 27 | 28 | include::assemblies/design.adoc[leveloffset=+1] 29 | 30 | include::assemblies/creating-the-data-plane.adoc[leveloffset=+1] 31 | 32 | include::assemblies/proc_deploying-in-disconnected-environments.adoc[leveloffset=+1] 33 | 34 | include::assemblies/dataplane_resources.adoc[leveloffset=-1] 35 | -------------------------------------------------------------------------------- /config/samples/dataplane/bgp_ovn_cluster/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1alpha1 2 | kind: Component 3 | 4 | namespace: openstack 5 | 6 | components: 7 | - ../preprovisioned # for baremetal nodes, replace with baremetal 8 | 9 | resources: 10 | - values.yaml 11 | 12 | replacements: 13 | # OpenStackDataPlaneNodeSet customizations 14 | - source: 15 | kind: DataPlaneConfig 16 | name: edpm-bgp-ovn-cluster-values 17 | fieldPath: data.nodeset.nodetemplate.ansible.vars 18 | targets: 19 | - select: 20 | kind: OpenStackDataPlaneNodeSet 21 | fieldPaths: 22 | - spec.nodeTemplate.ansible.ansibleVars 23 | options: 24 | create: true 25 | - source: 26 | kind: DataPlaneConfig 27 | name: edpm-bgp-ovn-cluster-values 28 | fieldPath: data.nodeset.services 29 | targets: 30 | - select: 31 | kind: OpenStackDataPlaneNodeSet 32 | fieldPaths: 33 | - spec.services 34 | options: 35 | create: true 36 | 37 | patches: 38 | - target: 39 | kind: OpenStackDataPlaneNodeSet 40 | name: .* 41 | patch: |- 42 | - op: copy 43 | from: /spec/nodes/edpm-compute-0 44 | path: /spec/nodes/edpm-compute-1 45 | - op: replace 46 | path: /spec/nodes/edpm-compute-1/ansible/ansibleHost 47 | value: 192.168.122.101 48 | - op: replace 49 | path: /spec/nodes/edpm-compute-1/hostName 50 | value: edpm-compute-1 51 | - op: replace 52 | path: /spec/nodes/edpm-compute-1/networks/0/fixedIP 53 | value: 192.168.122.101 54 | -------------------------------------------------------------------------------- /config/samples/nic-config-samples/bonds_vlans/controller_no_external.j2: -------------------------------------------------------------------------------- 1 | --- 2 | {% set mtu_list = [ctlplane_mtu] %} 3 | {% for network in nodeset_networks %} 4 | {% set _ = mtu_list.append(lookup('vars', networks_lower[network] ~ '_mtu')) %} 5 | {%- endfor %} 6 | {% set min_viable_mtu = mtu_list | max %} 7 | network_config: 8 | - type: interface 9 | name: nic1 10 | mtu: {{ ctlplane_mtu }} 11 | use_dhcp: false 12 | addresses: 13 | - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_cidr }} 14 | routes: {{ ctlplane_host_routes }} 15 | - type: ovs_bridge 16 | name: {{ neutron_physical_bridge_name }} 17 | dns_servers: {{ ctlplane_dns_nameservers }} 18 | domain: {{ dns_search_domains }} 19 | members: 20 | - type: ovs_bond 21 | name: bond1 22 | mtu: {{ min_viable_mtu }} 23 | ovs_options: {{ edpm_bond_interface_ovs_options }} 24 | members: 25 | - type: interface 26 | name: nic2 27 | mtu: {{ min_viable_mtu }} 28 | primary: true 29 | - type: interface 30 | name: nic3 31 | mtu: {{ min_viable_mtu }} 32 | {% for network in nodeset_networks if network != 'external' %} 33 | - type: vlan 34 | mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} 35 | vlan_id: {{ lookup('vars', networks_lower[network] ~ '_vlan_id') }} 36 | addresses: 37 | - ip_netmask: {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }} 38 | routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }} 39 | {% endfor %} 40 | -------------------------------------------------------------------------------- /test/kuttl/common/osp_check_route_cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ROUTE_NAME=$1 4 | 5 | EXPECTED_CERTIFICATE=$(oc get secret ${ROUTE_NAME}-custom-route -n $NAMESPACE -o jsonpath='{.data.tls\.crt}' | base64 -d) 6 | EXPECTED_CA_CERTIFICATE=$(oc get secret ${ROUTE_NAME}-custom-route -n $NAMESPACE -o jsonpath='{.data.ca\.crt}' | base64 -d) 7 | 8 | TLS_DATA=$(oc get route ${ROUTE_NAME}-public -n $NAMESPACE -o jsonpath='{.spec.tls}') 9 | 10 | # Extract certificates from the route 11 | ACTUAL_CERTIFICATE=$(echo "$TLS_DATA" | jq -r '.certificate') 12 | ACTUAL_CA_CERTIFICATE=$(echo "$TLS_DATA" | jq -r '.caCertificate') 13 | 14 | TRIMMED_EXPECTED_CERTIFICATE=$(echo "$EXPECTED_CERTIFICATE" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') 15 | TRIMMED_ACTUAL_CERTIFICATE=$(echo "$ACTUAL_CERTIFICATE" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') 16 | 17 | TRIMMED_EXPECTED_CA_CERTIFICATE=$(echo "$EXPECTED_CA_CERTIFICATE" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') 18 | TRIMMED_ACTUAL_CA_CERTIFICATE=$(echo "$ACTUAL_CA_CERTIFICATE" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//') 19 | 20 | if [[ "$TRIMMED_EXPECTED_CERTIFICATE" != "$TRIMMED_ACTUAL_CERTIFICATE" ]]; then 21 | echo "Certificate does not match for route $ROUTE_NAME in namespace $NAMESPACE." 22 | exit 1 23 | fi 24 | 25 | if [[ "$TRIMMED_EXPECTED_CA_CERTIFICATE" != "$TRIMMED_ACTUAL_CA_CERTIFICATE" ]]; then 26 | echo "CA Certificate does not match for route $ROUTE_NAME in namespace $NAMESPACE." 27 | exit 1 28 | fi 29 | 30 | echo "TLS data matches for route $ROUTE_NAME in namespace $NAMESPACE." 31 | -------------------------------------------------------------------------------- /config/samples/dataplane/swift/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1alpha1 2 | kind: Component 3 | 4 | namespace: openstack 5 | 6 | components: 7 | - ../preprovisioned # for baremetal nodes, replace with baremetal 8 | 9 | resources: 10 | - values.yaml 11 | 12 | replacements: 13 | # OpenStackDataPlaneNodeSet customizations 14 | - source: 15 | kind: DataPlaneConfig 16 | name: edpm-swift-values 17 | fieldPath: data.nodeset.nodeTemplate.ansible.ansibleVars.edpm_swift_disks 18 | targets: 19 | - select: 20 | kind: OpenStackDataPlaneNodeSet 21 | fieldPaths: 22 | - spec.nodeTemplate.ansible.ansibleVars.edpm_swift_disks 23 | options: 24 | create: true 25 | - source: 26 | kind: DataPlaneConfig 27 | name: edpm-swift-values 28 | fieldPath: data.nodeset.services 29 | targets: 30 | - select: 31 | kind: OpenStackDataPlaneNodeSet 32 | fieldPaths: 33 | - spec.services 34 | options: 35 | create: true 36 | - source: 37 | kind: DataPlaneConfig 38 | name: edpm-swift-values 39 | fieldPath: data.nodeset.networkAttachments 40 | targets: 41 | - select: 42 | kind: OpenStackDataPlaneNodeSet 43 | fieldPaths: 44 | - spec.networkAttachments 45 | options: 46 | create: true 47 | - source: 48 | kind: DataPlaneConfig 49 | name: edpm-swift-values 50 | fieldPath: data.nodeset.nodes 51 | targets: 52 | - select: 53 | kind: OpenStackDataPlaneNodeSet 54 | fieldPaths: 55 | - spec.nodes 56 | options: 57 | create: true 58 | -------------------------------------------------------------------------------- /config/samples/dataplane/ceph/values.yaml: -------------------------------------------------------------------------------- 1 | # local-config: referenced, but not emitted by kustomize 2 | apiVersion: v1 3 | kind: DataPlaneConfig 4 | metadata: 5 | name: edpm-ceph-values 6 | annotations: 7 | config.kubernetes.io/local-config: "true" 8 | data: 9 | nodeset: 10 | # Create a nova-custom-ceph service which uses a ConfigMap 11 | # containing libvirt overrides for Ceph RBD. 12 | services: 13 | - bootstrap 14 | - download-cache 15 | - configure-network 16 | - validate-network 17 | - install-os 18 | - configure-os 19 | - ssh-known-hosts 20 | - run-os 21 | - reboot-os 22 | - ceph-client 23 | - install-certs 24 | - ovn 25 | - neutron-metadata 26 | - libvirt 27 | - nova-custom-ceph 28 | nodetemplate: 29 | # Create a secret called ceph-conf-files with the cephx key and 30 | # ceph.conf file and mount it so the ceph-client service can copy 31 | # those files to the EDPM nodes. 32 | extramounts: 33 | - extraVolType: Logs 34 | mounts: 35 | - mountPath: /runner/artifacts 36 | name: ansible-logs 37 | volumes: 38 | - name: ansible-logs 39 | persistentVolumeClaim: 40 | claimName: ansible-ee-logs 41 | - extraVolType: Ceph 42 | mounts: 43 | - mountPath: /etc/ceph 44 | name: ceph 45 | readOnly: true 46 | volumes: 47 | - name: ceph 48 | projected: 49 | sources: 50 | - secret: 51 | name: ceph-conf-files 52 | -------------------------------------------------------------------------------- /config/samples/dataplane/no_vars_from/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1alpha1 2 | kind: Component 3 | 4 | components: 5 | - ../preprovisioned # for baremetal nodes, replace with baremetal 6 | 7 | replacements: 8 | # OpenStackDataPlaneNodeSet customizations 9 | - source: 10 | kind: ConfigMap 11 | name: neutron-edpm 12 | fieldPath: data.physical_bridge_name 13 | targets: 14 | - select: 15 | kind: OpenStackDataPlaneNodeSet 16 | fieldPaths: 17 | - spec.nodeTemplate.ansible.ansibleVars.neutron_physical_bridge_name 18 | options: 19 | create: true 20 | - source: 21 | kind: ConfigMap 22 | name: neutron-edpm 23 | fieldPath: data.public_interface_name 24 | targets: 25 | - select: 26 | kind: OpenStackDataPlaneNodeSet 27 | fieldPaths: 28 | - spec.nodeTemplate.ansible.ansibleVars.neutron_public_interface_name 29 | options: 30 | create: true 31 | - source: 32 | kind: ConfigMap 33 | name: network-config-template 34 | fieldPath: data.network_config_template 35 | targets: 36 | - select: 37 | kind: OpenStackDataPlaneNodeSet 38 | fieldPaths: 39 | - spec.nodeTemplate.ansible.ansibleVars.edpm_network_config_template 40 | options: 41 | create: true 42 | 43 | 44 | patches: 45 | - target: 46 | kind: OpenStackDataPlaneNodeSet 47 | name: openstack-edpm 48 | patch: |- 49 | - op: remove 50 | path: /spec/nodeTemplate/ansible/ansibleVarsFrom 51 | - op: add 52 | path: /spec/nodeTemplate/ansible/ansibleUser 53 | value: cloud-admin 54 | -------------------------------------------------------------------------------- /config/samples/dataplane/pre_ceph_hci/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1alpha1 2 | kind: Component 3 | 4 | namespace: openstack 5 | 6 | nameSuffix: -ceph 7 | 8 | components: 9 | - ../preprovisioned # for baremetal nodes, replace with baremetal 10 | 11 | resources: 12 | - values.yaml 13 | 14 | replacements: 15 | # OpenStackDataPlaneNodeSet customizations 16 | - source: 17 | kind: DataPlaneConfig 18 | name: edpm-ceph-values 19 | fieldPath: data.nodeset.nodetemplate.ansible.vars 20 | targets: 21 | - select: 22 | kind: OpenStackDataPlaneNodeSet 23 | fieldPaths: 24 | - spec.nodeTemplate.ansible.ansibleVars 25 | options: 26 | create: true 27 | - source: 28 | kind: DataPlaneConfig 29 | name: edpm-ceph-values 30 | fieldPath: data.nodeset.nodes 31 | targets: 32 | - select: 33 | kind: OpenStackDataPlaneNodeSet 34 | fieldPaths: 35 | - spec.nodes 36 | options: 37 | create: true 38 | # OpenStackDataPlaneDeployment customizations 39 | - source: 40 | kind: DataPlaneConfig 41 | name: edpm-ceph-values 42 | fieldPath: data.deployment.services 43 | targets: 44 | - select: 45 | kind: OpenStackDataPlaneDeployment 46 | fieldPaths: 47 | - spec.servicesOverride 48 | options: 49 | create: true 50 | - source: 51 | kind: DataPlaneConfig 52 | name: edpm-ceph-values 53 | fieldPath: data.deployment.name 54 | targets: 55 | - select: 56 | kind: OpenStackDataPlaneDeployment 57 | fieldPaths: 58 | - metadata.name 59 | options: 60 | create: true 61 | -------------------------------------------------------------------------------- /kuttl-test.yaml: -------------------------------------------------------------------------------- 1 | # 2 | # EXECUTION (from install_yamls repo root): 3 | # 4 | # make openstack_kuttl 5 | # 6 | # ASSUMPTIONS: 7 | # 8 | # 1. Latest version of kuttl is installed at /usr/local/bin/kubectl-kuttl 9 | # 2. An OCP 4.10+ CRC cluster with Podified Operators has been deployed 10 | # 3. CLI user has access to $KUBECONFIG 11 | # 4. The environment variable INSTALL_YAMLS is set to the path of the 12 | # install_yamls repo 13 | 14 | apiVersion: kuttl.dev/v1beta1 15 | kind: TestSuite 16 | commands: 17 | - command: oc apply -n openstack-kuttl-tests -f https://raw.githubusercontent.com/openstack-k8s-operators/infra-operator/main/config/samples/network_v1beta1_netconfig.yaml 18 | - command: oc apply -n openstack-kuttl-tests -f https://raw.githubusercontent.com/openstack-k8s-operators/infra-operator/main/config/samples/network_v1beta1_dnsmasq.yaml 19 | - script: | 20 | if [ ! -f ansibleee-ssh-key-id_rsa ]; then 21 | ssh-keygen -f ansibleee-ssh-key-id_rsa -N "" -t rsa -b 4096 22 | fi 23 | oc create secret generic dataplane-ansible-ssh-private-key-secret \ 24 | --save-config \ 25 | --dry-run=client \ 26 | --from-file=authorized_keys=ansibleee-ssh-key-id_rsa.pub \ 27 | --from-file=ssh-privatekey=ansibleee-ssh-key-id_rsa \ 28 | --from-file=ssh-publickey=ansibleee-ssh-key-id_rsa.pub \ 29 | -n openstack-kuttl-tests \ 30 | -o yaml | \ 31 | oc apply -f - 32 | reportFormat: xml 33 | reportName: kuttl-report-openstack 34 | reportGranularity: test 35 | namespace: openstack-kuttl-tests 36 | timeout: 1380 37 | parallel: 1 38 | suppress: 39 | - events # Remove spammy event logs 40 | -------------------------------------------------------------------------------- /config/samples/dataplane/networker/values.yaml: -------------------------------------------------------------------------------- 1 | # local-config: referenced, but not emitted by kustomize 2 | apiVersion: v1 3 | kind: DataPlaneConfig 4 | metadata: 5 | name: edpm-networker-values 6 | annotations: 7 | config.kubernetes.io/local-config: "true" 8 | data: 9 | nodeset: 10 | nodetemplate: 11 | ansible: 12 | vars: 13 | edpm_enable_chassis_gw: true 14 | nodes: 15 | edpm-networker-0: 16 | hostName: edpm-networker-0 17 | ansible: 18 | ansibleHost: 192.168.122.100 19 | networks: 20 | - name: ctlplane 21 | subnetName: subnet1 22 | defaultRoute: true 23 | fixedIP: 192.168.122.100 24 | - name: internalapi 25 | subnetName: subnet1 26 | - name: storage 27 | subnetName: subnet1 28 | - name: tenant 29 | subnetName: subnet1 30 | edpm-networker-1: 31 | hostName: edpm-networker-1 32 | ansible: 33 | ansibleHost: 192.168.122.101 34 | networks: 35 | - name: ctlplane 36 | subnetName: subnet1 37 | defaultRoute: true 38 | fixedIP: 192.168.122.101 39 | - name: internalapi 40 | subnetName: subnet1 41 | - name: storage 42 | subnetName: subnet1 43 | - name: tenant 44 | subnetName: subnet1 45 | services: 46 | - download-cache 47 | - bootstrap 48 | - configure-network 49 | - validate-network 50 | - install-os 51 | - configure-os 52 | - ssh-known-hosts 53 | - run-os 54 | - reboot-os 55 | - install-certs 56 | - ovn 57 | -------------------------------------------------------------------------------- /test/kuttl/tests/dataplane-deploy-tls-test/05-assert.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: kuttl.dev/v1beta1 3 | kind: TestAssert 4 | timeout: 600 5 | commands: 6 | - script: | 7 | PNAME=`oc get pod -l job-name=install-certs-ovrd-certs-refresh-openstack-edpm-tls --field-selector status.phase=Succeeded -n openstack-kuttl-tests -o name` 8 | echo $PNAME 9 | if [ -z "$PNAME" ]; then 10 | echo "Waiting for successful ansibleee pod" 11 | exit 1 12 | fi 13 | 14 | serial1=`oc get secret cert-custom-tls-dns-default-edpm-compute-0 -n openstack-kuttl-tests -o json|jq -r '.data."tls.crt"'|base64 -d |openssl x509 -noout -serial` 15 | echo "serial1:" $serial1 16 | serial2=`oc debug $PNAME -n openstack-kuttl-tests -- cat /var/lib/openstack/certs/custom-tls-dns/default/edpm-compute-0.ctlplane.example.com-tls.crt |openssl x509 -noout -serial` 17 | echo "serial2:" $serial2 18 | if [ $serial1 != $serial2 ]; then 19 | echo "serials for cert-custom-tls-dns-default-edpm-compute-0 not equal" 20 | exit 1 21 | fi 22 | 23 | serial1=`oc get secret cert-tls-dns-ips-default-edpm-compute-0 -n openstack-kuttl-tests -o json|jq -r '.data."tls.crt"'|base64 -d |openssl x509 -noout -serial` 24 | echo "serial1:" $serial1 25 | serial2=`oc debug $PNAME -n openstack-kuttl-tests -- cat /var/lib/openstack/certs/tls-dns-ips/default/edpm-compute-0.ctlplane.example.com-tls.crt |openssl x509 -noout -serial` 26 | echo "serial2:" $serial2 27 | if [ $serial1 != $serial2 ]; then 28 | echo "serials for cert-tls-dns-ips-default-edpm-compute-0 not equal" 29 | exit 1 30 | fi 31 | 32 | exit 0 33 | -------------------------------------------------------------------------------- /config/samples/nic-config-samples/multiple_nics/multiple_nics.j2: -------------------------------------------------------------------------------- 1 | --- 2 | network_config: 3 | - type: interface 4 | name: nic1 5 | mtu: {{ ctlplane_mtu }} 6 | dns_servers: {{ ctlplane_dns_nameservers }} 7 | domain: {{ dns_search_domains }} 8 | routes: {{ ctlplane_host_routes }} 9 | use_dhcp: false 10 | addresses: 11 | - ip_netmask: {{ ctlplane_ip }}/{{ ctlplane_cidr }} 12 | {% for network in nodeset_networks %} 13 | {% if network not in ["external", "tenant"] %} 14 | - type: interface 15 | name: nic{{ loop.index +1 }} 16 | mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} 17 | use_dhcp: false 18 | addresses: 19 | - ip_netmask: 20 | {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }} 21 | routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }} 22 | {% elif 'external_bridge' in nodeset_tags|default([]) %} 23 | - type: ovs_bridge 24 | {% if network == 'external' %} 25 | name: {{ neutron_physical_bridge_name }} 26 | {% else %} 27 | name: {{ 'br-' ~ networks_lower[network] }} 28 | {% endif %} 29 | mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} 30 | dns_servers: {{ ctlplane_dns_nameservers }} 31 | use_dhcp: false 32 | addresses: 33 | - ip_netmask: 34 | {{ lookup('vars', networks_lower[network] ~ '_ip') }}/{{ lookup('vars', networks_lower[network] ~ '_cidr') }} 35 | routes: {{ lookup('vars', networks_lower[network] ~ '_host_routes') }} 36 | members: 37 | - type: interface 38 | name: nic{{loop.index + 1}} 39 | mtu: {{ lookup('vars', networks_lower[network] ~ '_mtu') }} 40 | use_dhcp: false 41 | primary: true 42 | {% endif %} 43 | {% endfor %} 44 | -------------------------------------------------------------------------------- /.github/workflows/release-openstack-operator.yaml: -------------------------------------------------------------------------------- 1 | name: Release OpenStack Operator 2 | 3 | on: 4 | release: 5 | types: 6 | - released 7 | - prereleased 8 | 9 | env: 10 | imageregistry: 'quay.io' 11 | imagenamespace: ${{ secrets.IMAGENAMESPACE || secrets.QUAY_USERNAME }} 12 | 13 | jobs: 14 | release: 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - name: Tag image 21 | uses: tinact/docker.image-retag@1.0.2 22 | with: 23 | image_name: ${{ env.imagenamespace }}/ 24 | image_old_tag: ${{ github.sha }} 25 | image_new_tag: ${{ github.event.release.tag_name }} 26 | registry: ${{ env.imageregistry }} 27 | registry_username: ${{ secrets.QUAY_USERNAME }} 28 | registry_password: ${{ secrets.QUAY_PASSWORD }} 29 | 30 | - name: Tag -bundle image 31 | uses: tinact/docker.image-retag@1.0.2 32 | with: 33 | image_name: ${{ env.imagenamespace }}/-bundle 34 | image_old_tag: ${{ github.sha }} 35 | image_new_tag: ${{ github.event.release.tag_name }} 36 | registry: ${{ env.imageregistry }} 37 | registry_username: ${{ secrets.QUAY_USERNAME }} 38 | registry_password: ${{ secrets.QUAY_PASSWORD }} 39 | 40 | - name: Tag -index image 41 | uses: tinact/docker.image-retag@1.0.2 42 | with: 43 | image_name: ${{ env.imagenamespace }}/-index 44 | image_old_tag: ${{ github.sha }} 45 | image_new_tag: ${{ github.event.release.tag_name }} 46 | registry: ${{ env.imageregistry }} 47 | registry_username: ${{ secrets.QUAY_USERNAME }} 48 | registry_password: ${{ secrets.QUAY_PASSWORD }} 49 | -------------------------------------------------------------------------------- /docs/assemblies/proc_hotfixing-the-data-plane-rpm-content.adoc: -------------------------------------------------------------------------------- 1 | [id="proc_hotfixing-the-data-plane-rpm-content-{context}"] 2 | = Hotfixing the data plane RPM content 3 | 4 | [role="_abstract"] 5 | 6 | You install RPM hotfix content directly on to the data plane nodes. 7 | 8 | .Procedure 9 | 10 | . Obtain the RPM hotfix content from the source and store it locally: 11 | + 12 | ---- 13 | $ mkdir -p /rpms 14 | $ cp /path/to/hotfix/*.rpm /rpms 15 | ---- 16 | + 17 | * Replace `` with a hotfix identifier such as a Jira issue, for example `osprh-0000`. 18 | 19 | . Copy the RPM hotfix content to the affected data plane nodes: 20 | + 21 | ---- 22 | $ ssh @ mkdir -p /tmp//rpms 23 | $ scp /rpms/*.rpm @:/tmp//rpms 24 | ---- 25 | + 26 | * Replace `` with the SSH user name. 27 | * Replace `` with the hostname or IP for the data plane node. 28 | * Replace `` with a hotfix identifier such as a Jira issue, for example `osprh-0000`. 29 | 30 | + 31 | Repeat this step for each data plane node that the hotfix must be applied to. 32 | 33 | . Update the RPM hotfix content on the affected data plane nodes. 34 | + 35 | ---- 36 | $ ssh @ 37 | $ sudo dnf in -y /tmp//rpms/*.rpm 38 | ---- 39 | + 40 | * Replace `` with the SSH user name. 41 | * Replace `` with the hostname or IP for the data plane node. 42 | * Replace `` with a hotfix identifier such as a Jira issue, for example `osprh-0000`. 43 | 44 | . Perform any additional custom steps that are detailed in the hotfix instructions to complete the application of the RPM hotfix content. 45 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-nodeselectors/02-assert-nodeselector.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestAssert 3 | commands: 4 | - script: | 5 | echo "Checking all pods have expected nodeselector" 6 | EXPECTED_NODE_SELECTOR="beta.kubernetes.io/os:linux node-role.kubernetes.io/worker:" 7 | BAD_OR_MISSING_NODE_SELECTOR=$(oc get pods -n $NAMESPACE -l service!=dnsmasq -o=go-template --template='{{ range .items }}{{ .metadata.name}}: {{ .spec.nodeSelector }}{{"\n"}}{{ end }}' | grep -v 'ovn-controller-.*-config' | grep -v 'crc-storage-*' | sed -e '\!map\['"$EXPECTED_NODE_SELECTOR"'\]$!d') 8 | BAD_OR_MISSING_NODE_SELECTOR_COUNT=$(echo -n "$BAD_OR_MISSING_NODE_SELECTOR" | wc -l) 9 | if [ $BAD_OR_MISSING_NODE_SELECTOR_COUNT -ne 0 ]; then 10 | echo "Found $BAD_OR_MISSING_NODE_SELECTOR_COUNT pods with bad or missing nodeselector:" 11 | echo "$BAD_OR_MISSING_NODE_SELECTOR" 12 | exit 1 13 | fi 14 | - script: | 15 | echo "Checking all cronjobs have expected nodeselector" 16 | EXPECTED_NODE_SELECTOR="node-role.kubernetes.io/worker:" 17 | BAD_OR_MISSING_NODE_SELECTOR=$(oc get cronjobs -n $NAMESPACE -o=go-template --template='{{ range .items }}{{ .metadata.name}}: {{ .spec.jobTemplate.spec.template.spec.nodeSelector }}{{"\n"}}{{ end }}' | grep -v 'ovn-controller-.*-config' | grep -v 'crc-storage-*' | sed -e '\!map\['"$EXPECTED_NODE_SELECTOR"'\]$!d') 18 | BAD_OR_MISSING_NODE_SELECTOR_COUNT=$(echo -n "$BAD_OR_MISSING_NODE_SELECTOR" | wc -l) 19 | if [ $BAD_OR_MISSING_NODE_SELECTOR_COUNT -ne 0 ]; then 20 | echo "Found $BAD_OR_MISSING_NODE_SELECTOR_COUNT cronjobs with bad or missing nodeselector:" 21 | echo "$BAD_OR_MISSING_NODE_SELECTOR" 22 | exit 1 23 | fi 24 | -------------------------------------------------------------------------------- /test/kuttl/tests/ctlplane-nodeselectors/04-assert-nodeselector.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kuttl.dev/v1beta1 2 | kind: TestAssert 3 | commands: 4 | - script: | 5 | echo "Checking all running pods have new nodeselector" 6 | EXPECTED_NODE_SELECTOR="beta.kubernetes.io/os:linux kubernetes.io/os:linux" 7 | BAD_OR_MISSING_NODE_SELECTOR=$(oc get pods -n $NAMESPACE -l service!=dnsmasq --field-selector=status.phase=Running -o=go-template --template='{{ range .items }}{{ .metadata.name}}: {{ .spec.nodeSelector }}{{"\n"}}{{ end }}' | grep -v 'ovn-controller-.*-config' | grep -v 'crc-storage-*' | sed -e '\!map\['"$EXPECTED_NODE_SELECTOR"'\]$!d') 8 | BAD_OR_MISSING_NODE_SELECTOR_COUNT=$(echo -n "$BAD_OR_MISSING_NODE_SELECTOR" | wc -l) 9 | if [ $BAD_OR_MISSING_NODE_SELECTOR_COUNT -ne 0 ]; then 10 | echo "Found $BAD_OR_MISSING_NODE_SELECTOR_COUNT pods with bad or missing nodeselector:" 11 | echo "$BAD_OR_MISSING_NODE_SELECTOR" 12 | exit 1 13 | fi 14 | - script: | 15 | echo "Checking all cronjobs have expected nodeselector" 16 | EXPECTED_NODE_SELECTOR="kubernetes.io/os:linux" 17 | BAD_OR_MISSING_NODE_SELECTOR=$(oc get cronjobs -n $NAMESPACE -o=go-template --template='{{ range .items }}{{ .metadata.name}}: {{ .spec.jobTemplate.spec.template.spec.nodeSelector }}{{"\n"}}{{ end }}' | grep -v 'ovn-controller-.*-config' | grep -v 'crc-storage-*' | sed -e '\!map\['"$EXPECTED_NODE_SELECTOR"'\]$!d') 18 | BAD_OR_MISSING_NODE_SELECTOR_COUNT=$(echo -n "$BAD_OR_MISSING_NODE_SELECTOR" | wc -l) 19 | if [ $BAD_OR_MISSING_NODE_SELECTOR_COUNT -ne 0 ]; then 20 | echo "Found $BAD_OR_MISSING_NODE_SELECTOR_COUNT cronjobs with bad or missing nodeselector:" 21 | echo "$BAD_OR_MISSING_NODE_SELECTOR" 22 | exit 1 23 | fi 24 | -------------------------------------------------------------------------------- /hack/catalog-build-olm-upgrade.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #NOTE: this script is used by the catalog-openstack-operator-upgrades.yaml 3 | set -ex 4 | 5 | function toDigestURL { 6 | local URL=$1 7 | 8 | DIGEST=$(skopeo inspect --format '{{.Digest}}' docker://$URL) 9 | echo $URL | sed -e "s|:.*|@$DIGEST|" 10 | 11 | } 12 | 13 | # These variables are mandatory. The script will exit if they are not set. 14 | MAIN_VERSION=${MAIN_VERSION:?"Error: MAIN_VERSION must be set."} 15 | FEATURE_RELEASE_VERSION=${FEATURE_RELEASE_VERSION:?"Error: FEATURE_RELEASE_VERSION must be set."} 16 | FEATURE_RELEASE_BRANCH=${FEATURE_RELEASE_BRANCH:?"Error: FEATURE_RELEASE_BRANCH must be set."} 17 | 18 | BUNDLE=${BUNDLE:-"quay.io/openstack-k8s-operators/openstack-operator-bundle:latest"} 19 | 20 | [ -d "catalog" ] && rm -Rf catalog 21 | [ -e "catalog.Dockerfile" ] && rm catalog.Dockerfile 22 | mkdir catalog 23 | 24 | opm generate dockerfile ./catalog -i registry.redhat.io/openshift4/ose-operator-registry-rhel9:v4.18 25 | opm init openstack-operator --default-channel=alpha --output yaml > catalog/index.yaml 26 | 27 | #opm render ${BUNDLE} --output yaml >> catalog/index.yaml 28 | opm render $(toDigestURL $BUNDLE) --output yaml >> catalog/index.yaml 29 | # always default to use the FR release from openstack-k8s-operators 30 | opm render $(toDigestURL quay.io/openstack-k8s-operators/openstack-operator-bundle:${FEATURE_RELEASE_BRANCH}-latest) --output yaml >> catalog/index.yaml 31 | 32 | cat >> catalog/index.yaml << EOF_CAT 33 | --- 34 | schema: olm.channel 35 | package: openstack-operator 36 | name: alpha 37 | entries: 38 | - name: openstack-operator.v${FEATURE_RELEASE_VERSION} 39 | - name: openstack-operator.v${MAIN_VERSION} 40 | replaces: openstack-operator.v${FEATURE_RELEASE_VERSION} 41 | EOF_CAT 42 | opm validate catalog 43 | --------------------------------------------------------------------------------