├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_report.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── pr.yaml │ └── release.yaml ├── .gitignore ├── .golangci.yaml ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Makefile ├── OWNERS ├── README.md ├── SECURITY.md ├── SECURITY_CONTACTS ├── bindep.txt ├── charts ├── cinder-csi-plugin │ ├── .helmignore │ ├── Chart.yaml │ ├── README.md │ ├── templates │ │ ├── NOTES.txt │ │ ├── _helpers.tpl │ │ ├── cinder-csi-driver.yaml │ │ ├── controllerplugin-deployment.yaml │ │ ├── controllerplugin-podmonitor.yaml │ │ ├── controllerplugin-rbac.yaml │ │ ├── custom_storageclass.yaml │ │ ├── nodeplugin-daemonset.yaml │ │ ├── nodeplugin-rbac.yaml │ │ ├── secret.yaml │ │ └── storageclass.yaml │ └── values.yaml ├── manila-csi-plugin │ ├── Chart.yaml │ ├── README.md │ ├── templates │ │ ├── _helpers.tpl │ │ ├── controllerplugin-clusterrole.yaml │ │ ├── controllerplugin-clusterrolebinding.yaml │ │ ├── controllerplugin-role.yaml │ │ ├── controllerplugin-rolebinding.yaml │ │ ├── controllerplugin-rules-clusterrole.yaml │ │ ├── controllerplugin-service.yaml │ │ ├── controllerplugin-serviceaccount.yaml │ │ ├── controllerplugin-statefulset.yaml │ │ ├── csidriver.yaml │ │ ├── nodeplugin-clusterrole.yaml │ │ ├── nodeplugin-clusterrolebinding.yaml │ │ ├── nodeplugin-daemonset.yaml │ │ ├── nodeplugin-rules-clusterrole.yaml │ │ ├── nodeplugin-serviceaccount.yaml │ │ └── runtimeconfig-cm.yaml │ └── values.yaml └── openstack-cloud-controller-manager │ ├── Chart.yaml │ ├── README.md │ ├── templates │ ├── _helpers.tpl │ ├── clusterrole.yaml │ ├── clusterrolebinding-sm.yaml │ ├── clusterrolebinding.yaml │ ├── daemonset.yaml │ ├── secret.yaml │ ├── service-sm.yaml │ ├── serviceaccount.yaml │ └── servicemonitor.yaml │ └── values.yaml ├── cloudbuild.yaml ├── cmd ├── barbican-kms-plugin │ └── main.go ├── cinder-csi-plugin │ └── main.go ├── client-keystone-auth │ └── main.go ├── k8s-keystone-auth │ └── main.go ├── magnum-auto-healer │ └── main.go ├── manila-csi-plugin │ └── main.go ├── octavia-ingress-controller │ └── main.go ├── openstack-cloud-controller-manager │ └── main.go └── tests │ └── manila-csi-e2e-suite │ └── manila_csi_e2e_suite_test.go ├── code-of-conduct.md ├── docs ├── barbican-kms-plugin │ └── using-barbican-kms-plugin.md ├── cinder-csi-plugin │ ├── development.md │ ├── examples.md │ ├── features.md │ ├── multi-region-clouds.md │ ├── sidecarcompatibility.md │ ├── troubleshooting.md │ └── using-cinder-csi-plugin.md ├── developers-guide.md ├── keystone-auth │ ├── using-auth-data-synchronization.md │ ├── using-client-keystone-auth.md │ └── using-keystone-webhook-authenticator-and-authorizer.md ├── magnum-auto-healer │ └── using-magnum-auto-healer.md ├── manila-csi-plugin │ ├── developers-csi-manila.md │ └── using-manila-csi-plugin.md ├── metrics.md ├── octavia-ingress-controller │ └── using-octavia-ingress-controller.md ├── openstack-cloud-controller-manager │ ├── expose-applications-using-loadbalancer-type-service.md │ ├── migrate-to-ccm-with-csimigration.md │ └── using-openstack-cloud-controller-manager.md └── release-procedure.md ├── examples ├── cinder-csi-plugin │ ├── block │ │ └── block.yaml │ ├── clone │ │ ├── example-clone.yaml │ │ ├── sc.yaml │ │ └── source-pvc.yaml │ ├── ephemeral │ │ ├── csi-ephemeral-volumes-example.yaml │ │ └── generic-ephemeral-volumes.yaml │ ├── nginx.yaml │ ├── resize │ │ └── example.yaml │ ├── snapshot │ │ ├── example.yaml │ │ ├── snapshotcreate.yaml │ │ └── snapshotrestore.yaml │ └── topology │ │ └── example.yaml ├── loadbalancers │ ├── README.MD │ ├── external-http-nginx.yaml │ └── internal-http-nginx.yaml ├── manila-csi-plugin │ ├── README.md │ ├── exec-bash.sh │ ├── logs.sh │ ├── nfs │ │ ├── auto-topology-aware │ │ │ ├── pod.yaml │ │ │ ├── pvc.yaml │ │ │ └── storageclass.yaml │ │ ├── dynamic-provisioning │ │ │ ├── pod.yaml │ │ │ ├── pvc.yaml │ │ │ └── storageclass.yaml │ │ ├── secrets.yaml │ │ ├── snapshot │ │ │ ├── pod.yaml │ │ │ ├── snapshotclass.yaml │ │ │ ├── snapshotcreate.yaml │ │ │ └── snapshotrestore.yaml │ │ ├── static-provisioning │ │ │ ├── pod.yaml │ │ │ └── preprovisioned-pvc.yaml │ │ └── topology-aware │ │ │ ├── pod.yaml │ │ │ ├── pvc.yaml │ │ │ └── storageclass.yaml │ └── runtimeconfig-cm.yaml └── webhook │ ├── keystone-apiserver-webhook.yaml │ ├── keystone-deployment.yaml │ ├── keystone-policy-configmap.yaml │ ├── keystone-rbac.yaml │ ├── keystone-service.yaml │ └── policy.json ├── go.mod ├── go.sum ├── hack ├── bump-release.sh ├── make.sh └── update-gofmt.sh ├── manifests ├── barbican-kms │ ├── ds.yaml │ ├── encryption-config.yaml │ └── pod.yaml ├── cinder-csi-plugin │ ├── cinder-csi-controllerplugin-rbac.yaml │ ├── cinder-csi-controllerplugin.yaml │ ├── cinder-csi-nodeplugin-rbac.yaml │ ├── cinder-csi-nodeplugin.yaml │ ├── csi-cinder-driver.yaml │ └── csi-secret-cinderplugin.yaml ├── controller-manager │ ├── cloud-config │ ├── cloud-controller-manager-role-bindings.yaml │ ├── cloud-controller-manager-roles.yaml │ ├── kubeadm.conf │ ├── openstack-cloud-controller-manager-ds.yaml │ └── openstack-cloud-controller-manager-pod.yaml ├── magnum-auto-healer │ └── magnum-auto-healer.yaml └── manila-csi-plugin │ ├── csi-controllerplugin-rbac.yaml │ ├── csi-controllerplugin.yaml │ ├── csi-nodeplugin-rbac.yaml │ ├── csi-nodeplugin.yaml │ └── csidriver.yaml ├── pkg ├── autohealing │ ├── OWNERS │ ├── cloudprovider │ │ ├── cloudprovider.go │ │ └── openstack │ │ │ └── provider.go │ ├── cmd │ │ └── root.go │ ├── config │ │ └── config.go │ ├── controller │ │ └── controller.go │ ├── healthcheck │ │ ├── healthcheck.go │ │ ├── plugin_endpoint.go │ │ └── plugin_nodecondition.go │ └── utils │ │ └── utils.go ├── client │ ├── client.go │ └── service.go ├── csi │ ├── cinder │ │ ├── controllerserver.go │ │ ├── controllerserver_test.go │ │ ├── driver.go │ │ ├── driver_test.go │ │ ├── etc │ │ │ └── cloud.conf │ │ ├── fake.go │ │ ├── identityserver.go │ │ ├── identityserver_test.go │ │ ├── nodeserver.go │ │ ├── nodeserver_test.go │ │ ├── openstack │ │ │ ├── fixtures │ │ │ │ └── clouds.yaml │ │ │ ├── openstack.go │ │ │ ├── openstack_backups.go │ │ │ ├── openstack_instances.go │ │ │ ├── openstack_mock.go │ │ │ ├── openstack_snapshots.go │ │ │ ├── openstack_test.go │ │ │ └── openstack_volumes.go │ │ ├── server.go │ │ ├── server_test.go │ │ ├── utils.go │ │ └── utils_test.go │ ├── csi.go │ └── manila │ │ ├── OWNERS │ │ ├── adapters.go │ │ ├── controllerserver.go │ │ ├── controllerserver_test.go │ │ ├── csiclient.go │ │ ├── csiclient │ │ ├── builder.go │ │ ├── client.go │ │ └── interface.go │ │ ├── driver.go │ │ ├── identityserver.go │ │ ├── manilaclient │ │ ├── builder.go │ │ ├── client.go │ │ └── interface.go │ │ ├── nodeserver.go │ │ ├── options │ │ ├── openstackoptions.go │ │ └── shareoptions.go │ │ ├── runtimeconfig │ │ ├── nfsconfig.go │ │ └── runtimeconfig.go │ │ ├── share.go │ │ ├── shareadapters │ │ ├── cephfs.go │ │ ├── nfs.go │ │ ├── shareadapter.go │ │ └── util.go │ │ ├── snapshot.go │ │ ├── util.go │ │ ├── util │ │ ├── exportlocation.go │ │ └── exportlocation_test.go │ │ ├── validator │ │ ├── dependsexpr.go │ │ ├── identity.go │ │ ├── matchexpr.go │ │ ├── precludesexpr.go │ │ ├── util.go │ │ ├── validator.go │ │ ├── validator_test.go │ │ └── valueexpr.go │ │ └── volumesource.go ├── identity │ └── keystone │ │ ├── authenticator.go │ │ ├── authenticator_test.go │ │ ├── authorizer.go │ │ ├── authorizer_test.go │ │ ├── authorizer_test_policy.json │ │ ├── authorizer_test_policy_version2.json │ │ ├── config.go │ │ ├── keystone.go │ │ ├── keystone_test.go │ │ ├── mock_IKeystone.go │ │ ├── policy.go │ │ ├── sync.go │ │ ├── sync_test.go │ │ ├── sync_test.yaml │ │ ├── token_getter.go │ │ └── token_getter_test.go ├── ingress │ ├── cmd │ │ └── root.go │ ├── config │ │ └── config.go │ ├── controller │ │ ├── controller.go │ │ └── openstack │ │ │ ├── client.go │ │ │ ├── neutron.go │ │ │ └── octavia.go │ └── utils │ │ └── utils.go ├── kms │ ├── barbican │ │ ├── barbican.go │ │ └── fake_barbican.go │ ├── client │ │ └── client.go │ ├── encryption │ │ └── aescbc │ │ │ ├── aescbc.go │ │ │ └── aescbc_test.go │ └── server │ │ ├── server.go │ │ └── server_test.go ├── metrics │ ├── metrics.go │ ├── metrics_api.go │ └── metrics_reconcile.go ├── openstack │ ├── OWNERS │ ├── doc.go │ ├── events.go │ ├── instances.go │ ├── instances_addresses.go │ ├── instances_addresses_test.go │ ├── instances_test.go │ ├── loadbalancer.go │ ├── loadbalancer_rename.go │ ├── loadbalancer_rename_test.go │ ├── loadbalancer_service_patcher.go │ ├── loadbalancer_sg.go │ ├── loadbalancer_subnet_match.go │ ├── loadbalancer_subnet_match_test.go │ ├── loadbalancer_test.go │ ├── openstack.go │ ├── openstack_test.go │ ├── routes.go │ └── routes_test.go ├── util │ ├── blockdevice │ │ ├── blockdevice_linux.go │ │ └── blockdevice_unsupported.go │ ├── errors │ │ └── errors.go │ ├── metadata │ │ ├── metadata.go │ │ ├── metadata_mock.go │ │ └── metadata_test.go │ ├── mount │ │ ├── mount.go │ │ └── mount_mock.go │ ├── net │ │ └── sets │ │ │ └── ipnet.go │ ├── openstack │ │ ├── keymanager.go │ │ ├── loadbalancer.go │ │ ├── loadbalancer_serial.go │ │ ├── network.go │ │ └── security_group.go │ ├── util.go │ └── util_test.go └── version │ └── version.go ├── tests ├── ci-csi-cinder-e2e.sh ├── ci-csi-manila-e2e.sh ├── ci-keystone-e2e.sh ├── ci-occm-e2e.sh ├── e2e │ ├── cloudprovider │ │ └── test-lb-service.sh │ ├── csi │ │ ├── cinder │ │ │ └── test-driver.yaml │ │ └── manila │ │ │ ├── manilavolume.go │ │ │ ├── testdriver.go │ │ │ └── testsuite.go │ └── k8s-keystone-auth │ │ └── test-authz.sh ├── playbooks │ ├── fetch-logs.yaml │ ├── roles │ │ ├── fetch-logs │ │ │ ├── README.md │ │ │ ├── defaults │ │ │ │ └── main.yaml │ │ │ └── tasks │ │ │ │ └── main.yaml │ │ ├── install-cpo-occm │ │ │ ├── README.md │ │ │ ├── defaults │ │ │ │ └── main.yaml │ │ │ └── tasks │ │ │ │ └── main.yaml │ │ ├── install-csi-cinder │ │ │ ├── README.md │ │ │ ├── defaults │ │ │ │ └── main.yaml │ │ │ └── tasks │ │ │ │ └── main.yaml │ │ ├── install-csi-manila │ │ │ ├── README.md │ │ │ ├── defaults │ │ │ │ └── main.yaml │ │ │ └── tasks │ │ │ │ └── main.yaml │ │ ├── install-devstack │ │ │ ├── defaults │ │ │ │ └── main.yaml │ │ │ ├── tasks │ │ │ │ └── main.yml │ │ │ └── templates │ │ │ │ └── local.conf.j2 │ │ ├── install-docker-registry │ │ │ ├── defaults │ │ │ │ └── main.yaml │ │ │ ├── tasks │ │ │ │ └── main.yml │ │ │ └── templates │ │ │ │ ├── ca-config.json.j2 │ │ │ │ └── ca-csr.json.j2 │ │ ├── install-docker │ │ │ ├── defaults │ │ │ │ └── main.yml │ │ │ ├── handlers │ │ │ │ └── main.yml │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── install-golang │ │ │ ├── defaults │ │ │ │ └── main.yml │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── install-helm │ │ │ └── tasks │ │ │ │ └── main.yml │ │ ├── install-k3s-bare-single │ │ │ ├── README.md │ │ │ ├── defaults │ │ │ │ └── main.yaml │ │ │ └── tasks │ │ │ │ └── main.yaml │ │ └── install-k3s │ │ │ ├── README.md │ │ │ ├── defaults │ │ │ └── main.yaml │ │ │ └── tasks │ │ │ └── main.yaml │ ├── test-csi-cinder-e2e.yaml │ ├── test-csi-manila-e2e.yaml │ └── test-occm-e2e.yaml ├── sanity │ ├── cinder │ │ ├── fakecloud.go │ │ ├── fakemetadata.go │ │ ├── fakemount.go │ │ └── sanity_test.go │ └── manila │ │ ├── fake-secrets.yaml │ │ ├── fakecsiclient.go │ │ ├── fakemanilaclient.go │ │ ├── fakemetadata.go │ │ └── sanity_test.go └── scripts │ ├── boskos.py │ └── create-gce-vm.sh └── tools ├── csi-deps-check.sh ├── csi-deps.sh ├── install-distro-packages.sh └── test-setup.sh /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Bug report 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 25 | 26 | /kind bug 27 | 28 | **What happened**: 29 | 30 | 31 | **What you expected to happen**: 32 | 33 | 34 | **How to reproduce it**: 35 | 36 | 37 | **Anything else we need to know?**: 38 | 39 | 40 | **Environment**: 41 | - openstack-cloud-controller-manager(or other related binary) version: 42 | - OpenStack version: 43 | - Others: 44 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature report 3 | about: Feature report 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | 25 | 26 | /kind feature 27 | 28 | **What happened**: 29 | 30 | 31 | **What you expected to happen**: 32 | 33 | 34 | **How to reproduce it**: 35 | 36 | 37 | **Anything else we need to know?**: 38 | 39 | 40 | **Environment**: 41 | - openstack-cloud-controller-manager(or other related binary) version: 42 | - OpenStack version: 43 | - Others: 44 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 16 | 17 | **What this PR does / why we need it**: 18 | 19 | **Which issue this PR fixes(if applicable)**: 20 | fixes # 21 | 22 | **Special notes for reviewers**: 23 | 24 | 25 | **Release note**: 26 | 31 | ```release-note 32 | NONE 33 | ``` 34 | -------------------------------------------------------------------------------- /.github/workflows/pr.yaml: -------------------------------------------------------------------------------- 1 | name: Lint Charts 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - 'charts/**' 7 | 8 | jobs: 9 | lint: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v3 14 | with: 15 | fetch-depth: 0 16 | 17 | - name: Set up Helm 18 | uses: azure/setup-helm@v3 19 | with: 20 | version: v3.10.0 21 | 22 | - uses: actions/setup-python@v4 23 | with: 24 | python-version: '3.9' 25 | check-latest: true 26 | 27 | # see example https://github.com/helm/chart-testing-action 28 | - name: Set up chart-testing 29 | uses: helm/chart-testing-action@v2.3.1 30 | 31 | - name: Run chart-testing (lint) 32 | run: ct lint --target-branch ${GITHUB_BASE_REF} 33 | -------------------------------------------------------------------------------- /.github/workflows/release.yaml: -------------------------------------------------------------------------------- 1 | name: Release Charts 2 | 3 | on: 4 | push: 5 | branches: 6 | - "master" 7 | - "release-*" 8 | 9 | jobs: 10 | release: 11 | runs-on: ubuntu-latest 12 | permissions: 13 | contents: write 14 | steps: 15 | - name: Checkout 16 | uses: actions/checkout@v3 17 | with: 18 | fetch-depth: 0 19 | 20 | - name: Configure Git 21 | run: | 22 | git config user.name "$GITHUB_ACTOR" 23 | git config user.email "$GITHUB_ACTOR@users.noreply.github.com" 24 | 25 | - name: Run chart-releaser 26 | uses: helm/chart-releaser-action@v1.6.0 27 | env: 28 | CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 29 | -------------------------------------------------------------------------------- /.golangci.yaml: -------------------------------------------------------------------------------- 1 | run: 2 | concurrency: 2 3 | timeout: 10m0s 4 | linters: 5 | enable: 6 | - gofmt 7 | output: 8 | formats: 9 |  - format: line-number 10 |  path: stdout 11 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | The **kubernetes/cloud-provider-openstack** project accepts contribution via github [pull request](https://help.github.com/articles/about-pull-requests/). This document outlines the process to help get your contribution accepted. Please also read the [Kubernetes contributor guide](https://github.com/kubernetes/community/blob/master/contributors/guide/README.md) 4 | 5 | ## Sign the Contributor License Agreement 6 | We'd love to accept your patches! Before we can accept them you need to sign Cloud Native Computing Foundation (CNCF) [CLA](https://github.com/kubernetes/community/blob/master/CLA.md). 7 | 8 | ## Reporting an issue 9 | If you find a bug or a feature request related to cloud-provider-openstack you can create a new github issue in this repo @[kubernetes/cloud-provider-openstack](https://github.com/kubernetes/cloud-provider-openstack/issues). 10 | 11 | ## Submitting a Pull Request 12 | * Fork the cloud-provider-openstack repo, develop and test your code changes. 13 | * Submit a pull request. 14 | * The bot will automatically assigns someone to review your PR. 15 | 16 | ## Contact 17 | * [Slack](https://kubernetes.slack.com/messages/provider-openstack). 18 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | emeritus_approvers: 2 | - chrigl 3 | - lingxiankong 4 | - ramineni 5 | - jichenjc 6 | approvers: 7 | - dulek 8 | - kayrus 9 | - stephenfin 10 | - zetaab 11 | reviewers: 12 | - dulek 13 | - kayrus 14 | - mdbooth 15 | - stephenfin 16 | - zetaab 17 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cloud Provider OpenStack 2 | 3 | Thank you for visiting the `Cloud Provider OpenStack` repository! 4 | 5 | This Repository hosts various plugins relevant to OpenStack and Kubernetes Integration 6 | 7 | * [OpenStack Cloud Controller Manager](/docs/openstack-cloud-controller-manager/using-openstack-cloud-controller-manager.md/) 8 | * [Octavia Ingress Controller](/docs/octavia-ingress-controller/using-octavia-ingress-controller.md/) 9 | * [Cinder CSI Plugin](/docs/cinder-csi-plugin/using-cinder-csi-plugin.md/) 10 | * [Keystone Webhook Authentication Authorization](/docs/keystone-auth/using-keystone-webhook-authenticator-and-authorizer.md/) 11 | * [Client Keystone](/docs/keystone-auth/using-client-keystone-auth.md/) 12 | * [Manila CSI Plugin](/docs/manila-csi-plugin/using-manila-csi-plugin.md/) 13 | * [Barbican KMS Plugin](/docs/barbican-kms-plugin/using-barbican-kms-plugin.md/) 14 | * [Magnum Auto Healer](/docs/magnum-auto-healer/using-magnum-auto-healer.md/) 15 | 16 | **NOTE:** 17 | 18 | * Cinder Standalone Provisioner, Manila Provisioner and Cinder FlexVolume Driver were removed since release v1.18.0. 19 | * Version 1.17 was the last release of Manila Provisioner, which is unmaintained from now on. Due to dependency issues, we removed the code from master but it is still accessible in the [release-1.17](https://github.com/kubernetes/cloud-provider-openstack/tree/release-1.17) branch. Please consider migrating to Manila CSI Plugin. 20 | * Start from release v1.26.0, neutron lbaasv1 support is removed and only Octavia is supported. 21 | 22 | ## Developing 23 | 24 | Refer to [Getting Started Guide](/docs/developers-guide.md/) for setting up development environment and contributing. 25 | 26 | ## Contact 27 | 28 | Please join us on [Kubernetes provider-openstack slack channel](https://kubernetes.slack.com/messages/provider-openstack) 29 | 30 | Project Co-Leads: 31 | * @dulek - Michał Dulko 32 | * @jichenjc - Chen Ji 33 | * @kayrus 34 | * @zetaab - Jesse Haka 35 | 36 | ## License 37 | 38 | Licensed under the Apache License, Version 2.0 (the "License"); 39 | you may not use this file except in compliance with the License. 40 | You may obtain a copy of the License at 41 | 42 | [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0) 43 | 44 | Unless required by applicable law or agreed to in writing, software 45 | distributed under the License is distributed on an "AS IS" BASIS, 46 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 47 | See the License for the specific language governing permissions and 48 | limitations under the License. 49 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Security Announcements 4 | 5 | Join the [kubernetes-security-announce] group for security and vulnerability announcements. 6 | 7 | You can also subscribe to an RSS feed of the above using [this link][kubernetes-security-announce-rss]. 8 | 9 | ## Reporting a Vulnerability 10 | 11 | Instructions for reporting a vulnerability can be found on the 12 | [Kubernetes Security and Disclosure Information] page. 13 | 14 | ## Supported Versions 15 | 16 | Information about supported Kubernetes versions can be found on the 17 | [Kubernetes version and version skew support policy] page on the Kubernetes website. 18 | 19 | [kubernetes-security-announce]: https://groups.google.com/forum/#!forum/kubernetes-security-announce 20 | [kubernetes-security-announce-rss]: https://groups.google.com/forum/feed/kubernetes-security-announce/msgs/rss_v2_0.xml?num=50 21 | [Kubernetes version and version skew support policy]: https://kubernetes.io/docs/setup/release/version-skew-policy/#supported-versions 22 | [Kubernetes Security and Disclosure Information]: https://kubernetes.io/docs/reference/issues-security/security/#report-a-vulnerability 23 | -------------------------------------------------------------------------------- /SECURITY_CONTACTS: -------------------------------------------------------------------------------- 1 | # Defined below are the security contacts for this repo. 2 | # 3 | # They are the contact point for the Product Security Committee to reach out 4 | # to for triaging and handling of incoming issues. 5 | # 6 | # The below names agree to abide by the 7 | # [Embargo Policy](https://git.k8s.io/security/private-distributors-list.md#embargo-policy) 8 | # and will be removed and replaced if they violate that agreement. 9 | # 10 | # DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE 11 | # INSTRUCTIONS AT https://kubernetes.io/security/ 12 | 13 | dulek 14 | kayrus 15 | zetaab 16 | -------------------------------------------------------------------------------- /bindep.txt: -------------------------------------------------------------------------------- 1 | pkg-config 2 | build-essential 3 | mercurial 4 | golang-go 5 | golint 6 | make 7 | -------------------------------------------------------------------------------- /charts/cinder-csi-plugin/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *~ 18 | # Various IDEs 19 | .project 20 | .idea/ 21 | *.tmproj 22 | .vscode/ 23 | -------------------------------------------------------------------------------- /charts/cinder-csi-plugin/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | appVersion: v1.32.0 3 | description: Cinder CSI Chart for OpenStack 4 | name: openstack-cinder-csi 5 | version: 2.33.0-alpha.2 6 | home: https://github.com/kubernetes/cloud-provider-openstack 7 | icon: https://github.com/kubernetes/kubernetes/blob/master/logo/logo.png 8 | maintainers: 9 | - name: mnasiadka 10 | email: mnasiadka@gmail.com 11 | - name: mkjpryor 12 | email: matt@stackhpc.com 13 | -------------------------------------------------------------------------------- /charts/cinder-csi-plugin/README.md: -------------------------------------------------------------------------------- 1 | # Cinder CSI volume provisioner 2 | 3 | Deploys a Cinder csi provisioner to your cluster, with the appropriate storageClass. 4 | 5 | ## How To install 6 | - Enable deployment of storageclasses using `storageClass.enabled` 7 | - Tag the retain or delete class as default class using `storageClass.delete.isDefault` in your value yaml 8 | - Set `storageClass..allowVolumeExpansion` to `true` or `false` 9 | 10 | First add the repo: 11 | 12 | helm repo add cpo https://kubernetes.github.io/cloud-provider-openstack 13 | helm repo update 14 | 15 | If you are using Helm v3: 16 | 17 | helm install cinder-csi cpo/openstack-cinder-csi 18 | 19 | If you are using Helm v2: 20 | 21 | helm install --name cinder-csi cpo/openstack-cinder-csi 22 | -------------------------------------------------------------------------------- /charts/cinder-csi-plugin/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | Use the following storageClass csi-cinder-sc-retain and csi-cinder-sc-delete only for RWO volumes. -------------------------------------------------------------------------------- /charts/cinder-csi-plugin/templates/cinder-csi-driver.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: CSIDriver 3 | metadata: 4 | name: cinder.csi.openstack.org 5 | spec: 6 | attachRequired: true 7 | podInfoOnMount: true 8 | volumeLifecycleModes: 9 | - Persistent 10 | - Ephemeral 11 | -------------------------------------------------------------------------------- /charts/cinder-csi-plugin/templates/controllerplugin-podmonitor.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.csi.plugin.podMonitor.enabled }} 2 | apiVersion: monitoring.coreos.com/v1 3 | kind: PodMonitor 4 | metadata: 5 | labels: 6 | {{- include "cinder-csi.controllerplugin.labels" . | nindent 4 }} 7 | {{- if .Values.csi.plugin.podMonitor.additionalLabels }} 8 | {{- toYaml .Values.csi.plugin.podMonitor.additionalLabels | nindent 4 }} 9 | {{- end }} 10 | name: {{ include "cinder-csi.name" . }}-controllerplugin 11 | namespace: {{ .Release.Namespace }} 12 | annotations: 13 | {{- with .Values.commonAnnotations }} 14 | {{- toYaml . | nindent 4 }} 15 | {{- end }} 16 | spec: 17 | podMetricsEndpoints: 18 | - interval: 30s 19 | port: http 20 | scheme: http 21 | jobLabel: component 22 | selector: 23 | matchLabels: 24 | {{- include "cinder-csi.controllerplugin.matchLabels" . | nindent 6 }} 25 | {{- end }} 26 | -------------------------------------------------------------------------------- /charts/cinder-csi-plugin/templates/custom_storageclass.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.storageClass.custom -}} 2 | {{ .Values.storageClass.custom }} 3 | {{- end }} 4 | -------------------------------------------------------------------------------- /charts/cinder-csi-plugin/templates/nodeplugin-rbac.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: csi-cinder-node-sa 5 | namespace: {{ .Release.Namespace }} 6 | --- 7 | kind: ClusterRole 8 | apiVersion: rbac.authorization.k8s.io/v1 9 | metadata: 10 | name: csi-nodeplugin-role 11 | rules: 12 | - apiGroups: [""] 13 | resources: ["events"] 14 | verbs: ["get", "list", "watch", "create", "update", "patch"] 15 | 16 | --- 17 | kind: ClusterRoleBinding 18 | apiVersion: rbac.authorization.k8s.io/v1 19 | metadata: 20 | name: csi-nodeplugin-binding 21 | subjects: 22 | - kind: ServiceAccount 23 | name: csi-cinder-node-sa 24 | namespace: {{ .Release.Namespace }} 25 | roleRef: 26 | kind: ClusterRole 27 | name: csi-nodeplugin-role 28 | apiGroup: rbac.authorization.k8s.io 29 | -------------------------------------------------------------------------------- /charts/cinder-csi-plugin/templates/secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if and (.Values.secret.create) (.Values.secret.enabled) }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ .Values.secret.name }} 6 | namespace: {{ .Release.Namespace }} 7 | type: Opaque 8 | stringData: 9 | {{ .Values.secret.data | toYaml | trimSuffix "\n" | nindent 2 }} 10 | {{- end }} 11 | -------------------------------------------------------------------------------- /charts/cinder-csi-plugin/templates/storageclass.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.storageClass.enabled }} 2 | apiVersion: storage.k8s.io/v1 3 | kind: StorageClass 4 | metadata: 5 | name: csi-cinder-sc-delete 6 | {{- if .Values.storageClass.delete.isDefault }} 7 | annotations: 8 | storageclass.kubernetes.io/is-default-class: "true" 9 | {{- end }} 10 | provisioner: cinder.csi.openstack.org 11 | reclaimPolicy: Delete 12 | allowVolumeExpansion: {{ .Values.storageClass.delete.allowVolumeExpansion }} 13 | --- 14 | apiVersion: storage.k8s.io/v1 15 | kind: StorageClass 16 | metadata: 17 | name: csi-cinder-sc-retain 18 | {{- if .Values.storageClass.retain.isDefault }} 19 | annotations: 20 | storageclass.kubernetes.io/is-default-class: "true" 21 | {{- end }} 22 | provisioner: cinder.csi.openstack.org 23 | reclaimPolicy: Retain 24 | allowVolumeExpansion: {{ .Values.storageClass.retain.allowVolumeExpansion }} 25 | {{- end }} -------------------------------------------------------------------------------- /charts/manila-csi-plugin/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | appVersion: v1.32.0 3 | description: Manila CSI Chart for OpenStack 4 | name: openstack-manila-csi 5 | version: 2.33.0-alpha.3 6 | home: http://github.com/kubernetes/cloud-provider-openstack 7 | icon: https://github.com/kubernetes/kubernetes/blob/master/logo/logo.png 8 | maintainers: 9 | - name: mnasiadka 10 | email: mnasiadka@gmail.com 11 | - name: mkjpryor 12 | email: matt@stackhpc.com 13 | -------------------------------------------------------------------------------- /charts/manila-csi-plugin/README.md: -------------------------------------------------------------------------------- 1 | # Manila CSI provisioner 2 | 3 | First add the repo: 4 | 5 | helm repo add cpo https://kubernetes.github.io/cloud-provider-openstack 6 | helm repo update 7 | 8 | If you are using Helm v3: 9 | 10 | helm install manila-csi cpo/openstack-manila-csi 11 | 12 | If you are using Helm v2: 13 | 14 | helm install --name manila-csi cpo/openstack-manila-csi 15 | -------------------------------------------------------------------------------- /charts/manila-csi-plugin/templates/controllerplugin-clusterrole.yaml: -------------------------------------------------------------------------------- 1 | kind: ClusterRole 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | metadata: 4 | name: {{ include "openstack-manila-csi.controllerplugin.fullname" . }} 5 | labels: 6 | {{- include "openstack-manila-csi.controllerplugin.labels" . | nindent 4 }} 7 | aggregationRule: 8 | clusterRoleSelectors: 9 | - matchLabels: 10 | rbac.manila.csi.openstack.org/aggregate-to-controller-{{ include "openstack-manila-csi.name" . }}: "true" 11 | rules: [] 12 | -------------------------------------------------------------------------------- /charts/manila-csi-plugin/templates/controllerplugin-clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | kind: ClusterRoleBinding 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | metadata: 4 | name: {{ include "openstack-manila-csi.controllerplugin.fullname" . }} 5 | labels: 6 | {{- include "openstack-manila-csi.controllerplugin.labels" . | nindent 4 }} 7 | subjects: 8 | - kind: ServiceAccount 9 | name: {{ include "openstack-manila-csi.serviceAccountName.controllerplugin" . }} 10 | namespace: {{ .Release.Namespace }} 11 | roleRef: 12 | kind: ClusterRole 13 | name: {{ include "openstack-manila-csi.controllerplugin.fullname" . }} 14 | apiGroup: rbac.authorization.k8s.io 15 | -------------------------------------------------------------------------------- /charts/manila-csi-plugin/templates/controllerplugin-role.yaml: -------------------------------------------------------------------------------- 1 | kind: Role 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | metadata: 4 | name: {{ include "openstack-manila-csi.controllerplugin.fullname" . }} 5 | namespace: {{ .Release.Namespace }} 6 | labels: 7 | {{- include "openstack-manila-csi.controllerplugin.labels" . | nindent 4 }} 8 | rules: 9 | - apiGroups: [""] 10 | resources: ["endpoints"] 11 | verbs: ["get", "watch", "list", "delete", "update", "create"] 12 | - apiGroups: [""] 13 | resources: ["configmaps"] 14 | verbs: ["get", "list", "watch", "create", "delete"] 15 | -------------------------------------------------------------------------------- /charts/manila-csi-plugin/templates/controllerplugin-rolebinding.yaml: -------------------------------------------------------------------------------- 1 | kind: RoleBinding 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | metadata: 4 | name: {{ include "openstack-manila-csi.controllerplugin.fullname" . }} 5 | namespace: {{ .Release.Namespace }} 6 | labels: 7 | {{- include "openstack-manila-csi.controllerplugin.labels" . | nindent 4 }} 8 | subjects: 9 | - kind: ServiceAccount 10 | name: {{ include "openstack-manila-csi.serviceAccountName.controllerplugin" . }} 11 | namespace: {{ .Release.Namespace }} 12 | roleRef: 13 | kind: Role 14 | name: {{ include "openstack-manila-csi.controllerplugin.fullname" . }} 15 | apiGroup: rbac.authorization.k8s.io 16 | -------------------------------------------------------------------------------- /charts/manila-csi-plugin/templates/controllerplugin-rules-clusterrole.yaml: -------------------------------------------------------------------------------- 1 | kind: ClusterRole 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | metadata: 4 | name: {{ include "openstack-manila-csi.controllerplugin.fullname" . }}-rules 5 | labels: 6 | {{- include "openstack-manila-csi.controllerplugin.labels" . | nindent 4 }} 7 | rbac.manila.csi.openstack.org/aggregate-to-controller-{{ include "openstack-manila-csi.name" . }}: "true" 8 | rules: 9 | - apiGroups: [""] 10 | resources: ["nodes"] 11 | verbs: ["get", "list", "watch"] 12 | - apiGroups: [""] 13 | resources: ["secrets"] 14 | verbs: ["get", "list"] 15 | - apiGroups: [""] 16 | resources: ["persistentvolumes"] 17 | verbs: ["get", "list", "watch", "create", "delete", "patch"] 18 | - apiGroups: [""] 19 | resources: ["persistentvolumeclaims"] 20 | verbs: ["get", "list", "watch", "update"] 21 | - apiGroups: [""] 22 | resources: ["persistentvolumeclaims/status"] 23 | verbs: ["patch"] 24 | - apiGroups: [""] 25 | resources: ["events"] 26 | verbs: ["list", "watch", "create", "update", "patch"] 27 | - apiGroups: ["storage.k8s.io"] 28 | resources: ["storageclasses"] 29 | verbs: ["get", "list", "watch"] 30 | - apiGroups: ["storage.k8s.io"] 31 | resources: ["csinodes"] 32 | verbs: ["get", "list", "watch"] 33 | - apiGroups: ["snapshot.storage.k8s.io"] 34 | resources: ["volumesnapshotclasses"] 35 | verbs: ["get", "list", "watch"] 36 | - apiGroups: ["snapshot.storage.k8s.io"] 37 | resources: ["volumesnapshots"] 38 | verbs: ["get", "list"] 39 | - apiGroups: ["snapshot.storage.k8s.io"] 40 | resources: ["volumesnapshotcontents"] 41 | verbs: ["create", "get", "list", "watch", "update", "delete", "patch"] 42 | - apiGroups: ["snapshot.storage.k8s.io"] 43 | resources: ["volumesnapshotcontents/status"] 44 | verbs: ["update", "patch"] 45 | -------------------------------------------------------------------------------- /charts/manila-csi-plugin/templates/controllerplugin-service.yaml: -------------------------------------------------------------------------------- 1 | kind: Service 2 | apiVersion: v1 3 | metadata: 4 | name: {{ include "openstack-manila-csi.controllerplugin.fullname" . }} 5 | namespace: {{ .Release.Namespace }} 6 | labels: 7 | {{- include "openstack-manila-csi.controllerplugin.labels" . | nindent 4 }} 8 | spec: 9 | selector: 10 | app: {{ include "openstack-manila-csi.name" . }} 11 | component: {{ .Values.controllerplugin.name }} 12 | release: {{ .Release.Name }} 13 | ports: 14 | - name: dummy 15 | port: 12345 16 | -------------------------------------------------------------------------------- /charts/manila-csi-plugin/templates/controllerplugin-serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: {{ include "openstack-manila-csi.serviceAccountName.controllerplugin" . }} 5 | namespace: {{ .Release.Namespace }} 6 | labels: 7 | {{- include "openstack-manila-csi.controllerplugin.labels" . | nindent 4 }} 8 | -------------------------------------------------------------------------------- /charts/manila-csi-plugin/templates/csidriver.yaml: -------------------------------------------------------------------------------- 1 | {{- range .Values.shareProtocols }} 2 | apiVersion: storage.k8s.io/v1 3 | kind: CSIDriver 4 | metadata: 5 | name: {{ printf "%s.%s" .protocolSelector $.Values.driverName | lower }} 6 | spec: 7 | attachRequired: false 8 | podInfoOnMount: false 9 | fsGroupPolicy: {{ printf "%s" .fsGroupPolicy }} 10 | --- 11 | {{- end }} 12 | -------------------------------------------------------------------------------- /charts/manila-csi-plugin/templates/nodeplugin-clusterrole.yaml: -------------------------------------------------------------------------------- 1 | kind: ClusterRole 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | metadata: 4 | name: {{ include "openstack-manila-csi.nodeplugin.fullname" . }} 5 | labels: 6 | {{- include "openstack-manila-csi.nodeplugin.labels" . | nindent 4 }} 7 | aggregationRule: 8 | clusterRoleSelectors: 9 | - matchLabels: 10 | rbac.manila.csi.openstack.org/aggregate-to-nodeplugin-{{ include "openstack-manila-csi.name" . }}: "true" 11 | rules: [] 12 | -------------------------------------------------------------------------------- /charts/manila-csi-plugin/templates/nodeplugin-clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | kind: ClusterRoleBinding 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | metadata: 4 | name: {{ include "openstack-manila-csi.nodeplugin.fullname" . }} 5 | labels: 6 | {{- include "openstack-manila-csi.nodeplugin.labels" . | nindent 4 }} 7 | subjects: 8 | - kind: ServiceAccount 9 | name: {{ include "openstack-manila-csi.serviceAccountName.nodeplugin" . }} 10 | namespace: {{ .Release.Namespace }} 11 | roleRef: 12 | kind: ClusterRole 13 | name: {{ include "openstack-manila-csi.nodeplugin.fullname" . }} 14 | apiGroup: rbac.authorization.k8s.io 15 | -------------------------------------------------------------------------------- /charts/manila-csi-plugin/templates/nodeplugin-rules-clusterrole.yaml: -------------------------------------------------------------------------------- 1 | kind: ClusterRole 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | metadata: 4 | name: {{ include "openstack-manila-csi.nodeplugin.fullname" . }}-rules 5 | labels: 6 | {{- include "openstack-manila-csi.nodeplugin.labels" . | nindent 4 }} 7 | rbac.manila.csi.openstack.org/aggregate-to-nodeplugin-{{ include "openstack-manila-csi.name" . }}: "true" 8 | rules: 9 | - apiGroups: [""] 10 | resources: ["configmaps"] 11 | verbs: ["get", "list"] 12 | - apiGroups: [""] 13 | resources: ["nodes"] 14 | verbs: ["get", "list", "update"] 15 | - apiGroups: [""] 16 | resources: ["namespaces"] 17 | verbs: ["get", "list"] 18 | - apiGroups: [""] 19 | resources: ["persistentvolumes"] 20 | verbs: ["get", "list", "watch", "update"] 21 | -------------------------------------------------------------------------------- /charts/manila-csi-plugin/templates/nodeplugin-serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: {{ include "openstack-manila-csi.serviceAccountName.nodeplugin" . }} 5 | namespace: {{ .Release.Namespace }} 6 | labels: 7 | {{- include "openstack-manila-csi.nodeplugin.labels" . | nindent 4 }} 8 | -------------------------------------------------------------------------------- /charts/manila-csi-plugin/templates/runtimeconfig-cm.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.csimanila.runtimeConfig.enabled }} 2 | apiVersion: v1 3 | kind: ConfigMap 4 | metadata: 5 | name: manila-csi-runtimeconf-cm 6 | namespace: {{ .Release.Namespace }} 7 | data: 8 | runtimeconfig.json: |- 9 | {{ .Values.csimanila.runtimeConfig.jsonData | indent 4 }} 10 | {{- end }} 11 | -------------------------------------------------------------------------------- /charts/openstack-cloud-controller-manager/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | appVersion: v1.32.0 3 | description: Openstack Cloud Controller Manager Helm Chart 4 | icon: https://object-storage-ca-ymq-1.vexxhost.net/swift/v1/6e4619c416ff4bd19e1c087f27a43eea/www-images-prod/openstack-logo/OpenStack-Logo-Vertical.png 5 | home: https://github.com/kubernetes/cloud-provider-openstack 6 | name: openstack-cloud-controller-manager 7 | version: 2.33.0-alpha.0 8 | maintainers: 9 | - name: eumel8 10 | email: f.kloeker@telekom.de 11 | url: https://www.telekom.com 12 | dependencies: 13 | - name: common 14 | version: 2.14.1 15 | repository: https://charts.bitnami.com/bitnami 16 | -------------------------------------------------------------------------------- /charts/openstack-cloud-controller-manager/README.md: -------------------------------------------------------------------------------- 1 | # openstack-cloud-controller-manager 2 | 3 | Deploys the OpenStack Cloud Controller Manager to your cluster. 4 | 5 | Default configuration values are the same as the CCM itself. 6 | 7 | ## How To install 8 | 9 | You need to configure an `openstack-ccm.yaml` values file with at least: 10 | 11 | - `cloudConfig.global.auth-url` with the Keystone URL 12 | - Authentication 13 | - with password: `cloudConfig.global.username` and `cloudconfig.global.password` 14 | - with application credentials: (`cloudConfig.global.application-credential-id` or `cloudConfig.global.application-credential-name`) and `cloudConfig.global.application-credential-secret` 15 | - Load balancing 16 | - `cloudConfig.loadBalancer.floating-network-id` **or** 17 | - `cloudConfig.loadBalancer.floating-subnet-id` **or** 18 | - `cloudConfig.loadBalancer.floating-subnet` 19 | 20 | If you want to enable health checks for your Load Balancers (optional), set `cloudConfig.loadBalancer.create-monitor: true`. 21 | 22 | Then run: 23 | 24 | ```sh 25 | helm repo add cpo https://kubernetes.github.io/cloud-provider-openstack 26 | helm repo update 27 | helm install openstack-ccm cpo/openstack-cloud-controller-manager --values openstack-ccm.yaml 28 | ``` 29 | 30 | ## Using an external secret 31 | 32 | In order to use an external secret for the OCCM: 33 | 34 | ```yaml 35 | secret: 36 | enabled: true 37 | name: cloud-config 38 | create: false 39 | ``` 40 | 41 | Create the secret with: 42 | 43 | ```sh 44 | kubectl create secret -n kube-system generic cloud-config --from-file=./cloud.conf 45 | ``` 46 | 47 | ## Tolerations 48 | 49 | To deploy OCCM to worker nodes only (e.g. when the controlplane is isolated), adjust the tolerations in the chart: 50 | 51 | ```yaml 52 | tolerations: 53 | - key: node.cloudprovider.kubernetes.io/uninitialized 54 | value: "true" 55 | effect: NoSchedule 56 | ``` 57 | 58 | ## Unsupported configurations 59 | 60 | - The chart does not support the mounting of custom `clouds.yaml` files. Therefore, the following config values in the `[Global]` section won’t have any effect: 61 | - `use-clouds` 62 | - `clouds-file` 63 | - `cloud` 64 | -------------------------------------------------------------------------------- /charts/openstack-cloud-controller-manager/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "occm.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} 6 | {{- end -}} 7 | 8 | {{/* 9 | Create chart name and version as used by the chart label. 10 | */}} 11 | {{- define "occm.chart" -}} 12 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} 13 | {{- end -}} 14 | 15 | {{- define "occm.common.matchLabels" -}} 16 | app: {{ template "occm.name" . }} 17 | release: {{ .Release.Name }} 18 | {{- end -}} 19 | 20 | {{- define "occm.common.metaLabels" -}} 21 | chart: {{ template "occm.chart" . }} 22 | heritage: {{ .Release.Service }} 23 | {{- end -}} 24 | 25 | {{- define "occm.controllermanager.matchLabels" -}} 26 | component: controllermanager 27 | {{ include "occm.common.matchLabels" . }} 28 | {{- end -}} 29 | 30 | {{- define "occm.controllermanager.labels" -}} 31 | {{ include "occm.controllermanager.matchLabels" . }} 32 | {{ include "occm.common.metaLabels" . }} 33 | {{ if .Values.podLabels }} 34 | {{- toYaml .Values.podLabels }} 35 | {{- end }} 36 | {{- end -}} 37 | 38 | {{/* 39 | Common annotations and pod annotations 40 | */}} 41 | {{- define "occm.controllermanager.annotations" -}} 42 | {{- if .Values.commonAnnotations }} 43 | {{- toYaml .Values.commonAnnotations }} 44 | {{- end }} 45 | {{ if .Values.podAnnotations }} 46 | {{- toYaml .Values.podAnnotations }} 47 | {{- end }} 48 | {{- end -}} 49 | 50 | 51 | {{/* 52 | Create cloud-config makro. 53 | */}} 54 | {{- define "cloudConfig" -}} 55 | [Global] 56 | {{- range $key, $value := .Values.cloudConfig.global }} 57 | {{ $key }} = {{ $value | quote }} 58 | {{- end }} 59 | 60 | [Networking] 61 | {{- range $key, $value := .Values.cloudConfig.networking }} 62 | {{ $key }} = {{ $value | quote }} 63 | {{- end }} 64 | 65 | [LoadBalancer] 66 | {{- range $key, $value := .Values.cloudConfig.loadBalancer }} 67 | {{ $key }} = {{ $value | quote }} 68 | {{- end }} 69 | 70 | [BlockStorage] 71 | {{- range $key, $value := .Values.cloudConfig.blockStorage }} 72 | {{ $key }} = {{ $value | quote }} 73 | {{- end }} 74 | 75 | [Metadata] 76 | {{- range $key, $value := .Values.cloudConfig.metadata }} 77 | {{ $key }} = {{ $value | quote }} 78 | {{- end }} 79 | 80 | [Route] 81 | {{- range $key, $value := .Values.cloudConfig.route }} 82 | {{ $key }} = {{ $value | quote }} 83 | {{- end }} 84 | {{- end }} 85 | 86 | {{/* 87 | Generate string of enabled controllers. Might have a trailing comma (,) which needs to be trimmed. 88 | */}} 89 | {{- define "occm.enabledControllers" }} 90 | {{- range .Values.enabledControllers -}}{{ . }},{{- end -}} 91 | {{- end }} 92 | -------------------------------------------------------------------------------- /charts/openstack-cloud-controller-manager/templates/clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: {{ .Values.clusterRoleName }} 5 | labels: {{- include "common.labels.standard" . | nindent 4 }} 6 | annotations: 7 | {{- with .Values.commonAnnotations }} 8 | {{- toYaml . | nindent 4 }} 9 | {{- end }} 10 | rules: 11 | - apiGroups: 12 | - coordination.k8s.io 13 | resources: 14 | - leases 15 | verbs: 16 | - get 17 | - create 18 | - update 19 | - apiGroups: 20 | - "" 21 | resources: 22 | - events 23 | verbs: 24 | - create 25 | - patch 26 | - update 27 | - apiGroups: 28 | - "" 29 | resources: 30 | - nodes 31 | verbs: 32 | - '*' 33 | - apiGroups: 34 | - "" 35 | resources: 36 | - nodes/status 37 | verbs: 38 | - patch 39 | - apiGroups: 40 | - "" 41 | resources: 42 | - services 43 | verbs: 44 | - list 45 | - patch 46 | - update 47 | - watch 48 | - apiGroups: 49 | - "" 50 | resources: 51 | - services/status 52 | verbs: 53 | - patch 54 | - apiGroups: 55 | - "" 56 | resources: 57 | - serviceaccounts/token 58 | verbs: 59 | - create 60 | - apiGroups: 61 | - "" 62 | resources: 63 | - serviceaccounts 64 | verbs: 65 | - create 66 | - get 67 | - apiGroups: 68 | - "" 69 | resources: 70 | - persistentvolumes 71 | verbs: 72 | - '*' 73 | - apiGroups: 74 | - "" 75 | resources: 76 | - endpoints 77 | verbs: 78 | - create 79 | - get 80 | - list 81 | - watch 82 | - update 83 | - apiGroups: 84 | - "" 85 | resources: 86 | - configmaps 87 | verbs: 88 | - get 89 | - list 90 | - watch 91 | - apiGroups: 92 | - "" 93 | resources: 94 | - secrets 95 | verbs: 96 | - list 97 | - get 98 | - watch 99 | -------------------------------------------------------------------------------- /charts/openstack-cloud-controller-manager/templates/clusterrolebinding-sm.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceMonitor.enabled }} 2 | kind: ClusterRoleBinding 3 | apiVersion: rbac.authorization.k8s.io/v1 4 | metadata: 5 | name: system:{{ include "occm.name" . }}:auth-delegate 6 | labels: {{- include "common.labels.standard" . | nindent 4 }} 7 | annotations: 8 | {{- with .Values.commonAnnotations }} 9 | {{- toYaml . | nindent 4 }} 10 | {{- end }} 11 | subjects: 12 | - kind: User 13 | name: system:serviceaccount:{{ .Release.Namespace }}:{{ include "occm.name" . }} 14 | apiGroup: rbac.authorization.k8s.io 15 | roleRef: 16 | kind: ClusterRole 17 | name: system:auth-delegator 18 | apiGroup: rbac.authorization.k8s.io 19 | {{- end }} 20 | -------------------------------------------------------------------------------- /charts/openstack-cloud-controller-manager/templates/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRoleBinding 4 | metadata: 5 | name: {{ .Values.clusterRoleName }} 6 | labels: {{- include "common.labels.standard" . | nindent 4 }} 7 | annotations: 8 | {{- with .Values.commonAnnotations }} 9 | {{- toYaml . | nindent 4 }} 10 | {{- end }} 11 | roleRef: 12 | apiGroup: rbac.authorization.k8s.io 13 | kind: ClusterRole 14 | name: {{ .Values.clusterRoleName }} 15 | subjects: 16 | - kind: ServiceAccount 17 | name: {{ .Values.serviceAccountName }} 18 | namespace: {{ .Release.Namespace | quote }} 19 | -------------------------------------------------------------------------------- /charts/openstack-cloud-controller-manager/templates/secret.yaml: -------------------------------------------------------------------------------- 1 | {{- if and (.Values.secret.create) (.Values.secret.enabled) }} 2 | apiVersion: v1 3 | kind: Secret 4 | metadata: 5 | name: {{ .Values.secret.name | default "cloud-config" }} 6 | labels: {{- include "common.labels.standard" . | nindent 4 }} 7 | namespace: {{ .Release.Namespace }} 8 | annotations: 9 | {{- with .Values.commonAnnotations }} 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | type: Opaque 13 | data: 14 | {{ if .Values.cloudConfigContents -}} 15 | cloud.conf: | 16 | {{ .Values.cloudConfigContents | b64enc }} 17 | {{ else -}} 18 | cloud.conf: {{ include "cloudConfig" . | b64enc }} 19 | {{ end -}} 20 | {{- end }} 21 | -------------------------------------------------------------------------------- /charts/openstack-cloud-controller-manager/templates/service-sm.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceMonitor.enabled }} 2 | apiVersion: v1 3 | kind: Service 4 | metadata: 5 | name: {{ include "occm.name" . }} 6 | labels: {{- include "common.labels.standard" . | nindent 4 }} 7 | namespace: {{ .Release.Namespace }} 8 | annotations: 9 | {{- with .Values.commonAnnotations }} 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | spec: 13 | ports: 14 | - name: http 15 | port: 10258 16 | protocol: TCP 17 | selector: 18 | {{- include "occm.controllermanager.matchLabels" . | nindent 4 }} 19 | {{- end }} 20 | -------------------------------------------------------------------------------- /charts/openstack-cloud-controller-manager/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: {{ .Values.serviceAccountName }} 5 | labels: {{- include "common.labels.standard" . | nindent 4 }} 6 | namespace: {{ .Release.Namespace }} 7 | annotations: 8 | {{- with .Values.commonAnnotations }} 9 | {{- toYaml . | nindent 4 }} 10 | {{- end }} 11 | -------------------------------------------------------------------------------- /charts/openstack-cloud-controller-manager/templates/servicemonitor.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceMonitor.enabled }} 2 | apiVersion: monitoring.coreos.com/v1 3 | kind: ServiceMonitor 4 | metadata: 5 | name: {{ include "occm.name" . }} 6 | labels: 7 | {{- include "common.labels.standard" . | nindent 4 }} 8 | {{- if .Values.serviceMonitor.additionalLabels }} 9 | {{- toYaml .Values.serviceMonitor.additionalLabels | nindent 4 }} 10 | {{- end }} 11 | namespace: {{ .Release.Namespace }} 12 | annotations: 13 | {{- with .Values.commonAnnotations }} 14 | {{- toYaml . | nindent 4 }} 15 | {{- end }} 16 | spec: 17 | endpoints: 18 | - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 19 | interval: 30s 20 | port: http 21 | scheme: https 22 | tlsConfig: 23 | insecureSkipVerify: true 24 | jobLabel: component 25 | selector: 26 | matchLabels: 27 | {{- include "occm.controllermanager.matchLabels" . | nindent 6 }} 28 | {{- end }} 29 | -------------------------------------------------------------------------------- /cloudbuild.yaml: -------------------------------------------------------------------------------- 1 | # See https://cloud.google.com/cloud-build/docs/build-config 2 | 3 | # this must be specified in seconds. If omitted, defaults to 600s (10 mins) 4 | timeout: 1200s 5 | # this prevents errors if you don't use both _GIT_TAG and _PULL_BASE_REF, 6 | # or any new substitutions added in the future. 7 | options: 8 | dynamic_substitutions: true 9 | substitution_option: ALLOW_LOOSE 10 | machineType: 'N1_HIGHCPU_8' 11 | steps: 12 | - name: gcr.io/k8s-testimages/gcb-docker-gcloud 13 | entrypoint: bash 14 | env: 15 | # default cloudbuild has HOME=/builder/home and docker buildx is in /root/.docker/cli-plugins/docker-buildx 16 | # set the home to /root explicitly to if using docker buildx 17 | - HOME=/root 18 | args: 19 | - -c 20 | - | 21 | set -xeuo pipefail 22 | 23 | # Create docker credentials for pushing to gcr.io from our inherited 24 | # gcloud credentials 25 | gcloud auth configure-docker 26 | 27 | # Run the image's buildx entrypoint to initialise the build environment 28 | # appropriately for the image before running make 29 | /buildx-entrypoint version 30 | 31 | make push-multiarch-images \ 32 | REGISTRY=gcr.io/$PROJECT_ID 33 | substitutions: 34 | # _GIT_TAG will be filled with a git-based tag for the image, of the form 35 | # vYYYYMMDD-hash, and can be used as a substitution 36 | _GIT_TAG: 'v99999999-v12345' 37 | # Remove date prefix (first 10 characters) to create valid semver version: 38 | # v20220510-v1.24.0-alpha.0-15-g09bd268 => v1.24.0-alpha.0-15-g09bd268 39 | _SHORT_TAG: '${_GIT_TAG:10}' 40 | # _PULL_BASE_REF will contain the ref that was pushed to to trigger this 41 | # build - a branch like 'master' or 'release-0.2', or a tag like 'v0.2'. 42 | _PULL_BASE_REF: 'master' 43 | -------------------------------------------------------------------------------- /cmd/barbican-kms-plugin/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 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 main 18 | 19 | import ( 20 | "os" 21 | "os/signal" 22 | 23 | "github.com/spf13/cobra" 24 | "golang.org/x/sys/unix" 25 | "k8s.io/cloud-provider-openstack/pkg/kms/server" 26 | "k8s.io/cloud-provider-openstack/pkg/version" 27 | "k8s.io/component-base/cli" 28 | "k8s.io/klog/v2" 29 | ) 30 | 31 | var ( 32 | socketPath string 33 | cloudConfig string 34 | ) 35 | 36 | func main() { 37 | cmd := &cobra.Command{ 38 | Use: "barbican-kms-plugin", 39 | Short: "Barbican KMS plugin for Kubernetes", 40 | RunE: func(cmd *cobra.Command, args []string) error { 41 | sigChan := make(chan os.Signal, 1) 42 | signal.Notify(sigChan, unix.SIGTERM, unix.SIGINT) 43 | err := server.Run(cloudConfig, socketPath, sigChan) 44 | return err 45 | }, 46 | Version: version.Version, 47 | } 48 | 49 | cmd.PersistentFlags().StringVar(&socketPath, "socketpath", "", "Barbican KMS Plugin unix socket endpoint") 50 | if err := cmd.MarkPersistentFlagRequired("socketpath"); err != nil { 51 | klog.Fatalf("Unable to mark flag socketpath as required: %v", err) 52 | } 53 | 54 | cmd.PersistentFlags().StringVar(&cloudConfig, "cloud-config", "", "Barbican KMS Plugin cloud config") 55 | if err := cmd.MarkPersistentFlagRequired("cloud-config"); err != nil { 56 | klog.Fatalf("Unable to mark flag cloud-config as required: %v", err) 57 | } 58 | 59 | code := cli.Run(cmd) 60 | os.Exit(code) 61 | } 62 | -------------------------------------------------------------------------------- /cmd/k8s-keystone-auth/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed under the Apache License, Version 2.0 (the "License"); 3 | you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software 9 | distributed under the License is distributed on an "AS IS" BASIS, 10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | See the License for the specific language governing permissions and 12 | limitations under the License. 13 | */ 14 | 15 | package main 16 | 17 | import ( 18 | "context" 19 | "os" 20 | 21 | "github.com/spf13/cobra" 22 | "github.com/spf13/pflag" 23 | "k8s.io/component-base/cli" 24 | "k8s.io/klog/v2" 25 | 26 | "k8s.io/cloud-provider-openstack/pkg/identity/keystone" 27 | "k8s.io/cloud-provider-openstack/pkg/version" 28 | ) 29 | 30 | var config = keystone.NewConfig() 31 | 32 | func main() { 33 | cmd := &cobra.Command{ 34 | Use: "k8s-keystone-auth", 35 | Short: "Keystone authentication webhook plugin for Kubernetes", 36 | Run: func(cmd *cobra.Command, args []string) { 37 | if err := config.ValidateFlags(); err != nil { 38 | klog.Errorf("%v", err) 39 | os.Exit(1) 40 | } 41 | 42 | keystoneAuth, err := keystone.NewKeystoneAuth(context.Background(), config) 43 | if err != nil { 44 | klog.Errorf("%v", err) 45 | os.Exit(1) 46 | } 47 | keystoneAuth.Run() 48 | 49 | }, 50 | Version: version.Version, 51 | } 52 | 53 | keystone.AddExtraFlags(pflag.CommandLine) 54 | 55 | config.AddFlags(pflag.CommandLine) 56 | 57 | code := cli.Run(cmd) 58 | os.Exit(code) 59 | 60 | } 61 | -------------------------------------------------------------------------------- /cmd/magnum-auto-healer/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 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 main 18 | 19 | import ( 20 | "k8s.io/cloud-provider-openstack/pkg/autohealing/cmd" 21 | ) 22 | 23 | func main() { 24 | cmd.Execute() 25 | } 26 | -------------------------------------------------------------------------------- /cmd/octavia-ingress-controller/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 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 main 18 | 19 | import ( 20 | "k8s.io/cloud-provider-openstack/pkg/ingress/cmd" 21 | ) 22 | 23 | func main() { 24 | cmd.Execute() 25 | } 26 | -------------------------------------------------------------------------------- /cmd/tests/manila-csi-e2e-suite/manila_csi_e2e_suite_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "flag" 5 | "os" 6 | "testing" 7 | 8 | "github.com/onsi/ginkgo/v2" 9 | "github.com/onsi/gomega" 10 | _ "k8s.io/cloud-provider-openstack/tests/e2e/csi/manila" 11 | "k8s.io/klog/v2" 12 | "k8s.io/kubernetes/test/e2e/framework" 13 | frameworkconfig "k8s.io/kubernetes/test/e2e/framework/config" 14 | ) 15 | 16 | func init() { 17 | frameworkconfig.CopyFlags(frameworkconfig.Flags, flag.CommandLine) 18 | framework.RegisterCommonFlags(flag.CommandLine) 19 | framework.RegisterClusterFlags(flag.CommandLine) 20 | framework.AfterReadingAllFlags(&framework.TestContext) 21 | } 22 | 23 | func Test(t *testing.T) { 24 | gomega.RegisterFailHandler(framework.Fail) 25 | if framework.TestContext.ReportDir != "" { 26 | if err := os.MkdirAll(framework.TestContext.ReportDir, 0755); err != nil { 27 | klog.Fatalf("Failed creating report directory: %v", err) 28 | } 29 | } 30 | klog.Infof("Starting e2e run %q on Ginkgo node %d", framework.RunID, ginkgo.GinkgoParallelProcess()) 31 | 32 | suiteConfig, reporterConfig := framework.CreateGinkgoConfig() 33 | reporterConfig.FullTrace = true 34 | 35 | klog.Infof("Starting e2e run %q on Ginkgo node %d", framework.RunID, suiteConfig.ParallelProcess) 36 | ginkgo.RunSpecs(t, "Manila CSI e2e Suite", suiteConfig, reporterConfig) 37 | 38 | } 39 | 40 | func main() { 41 | flag.Parse() 42 | Test(&testing.T{}) 43 | } 44 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Community Code of Conduct 2 | 3 | Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) 4 | -------------------------------------------------------------------------------- /docs/cinder-csi-plugin/development.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* 4 | 5 | - [Development tips for Cinder CSI](#development-tips-for-cinder-csi) 6 | - [Update CSI spec version and Cinder CSI driver version](#update-csi-spec-version-and-cinder-csi-driver-version) 7 | 8 | 9 | 10 | 11 | # Development tips for Cinder CSI 12 | 13 | ## Update CSI spec version and Cinder CSI driver version 14 | 15 | There are two versions (`specVersion` and `Version`) defined at [driver.go](../../pkg/csi/cinder/driver.go) and both of them are in `x.y.z` format. `specVersion` indicates the version of [CSI spec](https://github.com/container-storage-interface/spec) that Cinder CSI supports whereas `Version` is the version of Cinder CSI driver itself. For new each release or major functionalities update such as options/params updated, you need increase `.z` version. If the CSI spec version is upgraded, the Cinder CSI version need bump as well. 16 | 17 | For example, `specVersion` is `1.2.0` and `Version` is `1.2.1` then there's a new feature or option added but CSI spec remains same, the `specVersion` need to be kept as `1.2.0` and `Version` need to be bumped to `1.2.2`. If the CSI spec is bumped to `1.3.0`, the `specVersion` and `Version` need to be bumped to `1.3.0` accordingly. 18 | -------------------------------------------------------------------------------- /docs/cinder-csi-plugin/sidecarcompatibility.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* 4 | 5 | - [Plugin sidecar compatibility](#plugin-sidecar-compatibility) 6 | - [Set file type in provisioner](#set-file-type-in-provisioner) 7 | 8 | 9 | 10 | # Plugin sidecar compatibility 11 | 12 | ## Set file type in provisioner 13 | 14 | There is a change in [CSI provisioner 2.0](https://github.com/kubernetes-csi/external-provisioner/blob/master/CHANGELOG/CHANGELOG-2.0.md): The fstype on provisioned PVs no longer defaults to "ext4". A `defaultFSType` argument is added to the provisioner. Admins can also specify this fstype via storage class parameter. If fstype is set in storage class parameter, it will be used. The sidecar argument is only checked if fstype is not set in the SC param. 15 | 16 | By default, in the manifest file a `--default-fstype=ext4` default settings are added to [manifests](../../manifests/cinder-csi-plugin/cinder-csi-controllerplugin.yaml), if you want to update it , please add a `fsType: ext4` into the storage class definition. 17 | -------------------------------------------------------------------------------- /docs/cinder-csi-plugin/troubleshooting.md: -------------------------------------------------------------------------------- 1 | # Troubleshooting 2 | 3 | ## When trying to resize a Cinder Volume, PV/PVC is updated but file system not resized. 4 | 5 | Check the volume status by using `openstack volume show` command about the volume (it should have `pvc-` prefix) and see whether backend openstack need update, contact with your openstack administrator for help on the error reported. 6 | 7 | `openstack volume message list --os-volume-api-version 3.3` might also show some information about a failed resize, e.g. extend volume:Compute service failed to extend volume. 8 | 9 | ## When trying to resize a Cinder Volume based on Ceph, the VM doesn't see the new size. 10 | 11 | Chances are, the underlying OpenStack is not configured properly. 12 | This could be tested by manually creating a VM and Volume, attaching and resizing the Volume. 13 | If you see the same behaviour, no change of the Volume in the VM, try to get in contact with the Admin-Team of the OpenStack you are using. 14 | 15 | Chances are, Cinder is not allowed to send the `volume-extended` event to [Nova API](https://docs.openstack.org/api-ref/compute/?expanded=run-events-detail#run-events). 16 | The error likely can be spotted as a 403 in the logs. 17 | 18 | In that case. The section `nova` in [`cinder.conf`](https://docs.openstack.org/cinder/latest/configuration/block-storage/samples/cinder.conf.html) 19 | must be configured properly, and with a user with sufficient privileges. 20 | -------------------------------------------------------------------------------- /docs/release-procedure.md: -------------------------------------------------------------------------------- 1 | # Release Procedure 2 | 3 | The Cloud Provider OpenStack Release is done in sync with 4 | kubernetes/kubernetes. Minor versions can be released intermittently for 5 | critical bug fixes. 6 | 7 | ## Making a Release 8 | 9 | 1. Checkout the release branch. 10 | 11 | ```bash 12 | $ git fetch upstream 13 | $ git pull upstream master 14 | ``` 15 | 16 | 2. Update the minor version with the expected version. 17 | 18 | Make changes in the `docs/manifests/tests/examples` directories using the 19 | `hack/bump_release.sh` script by running the following command: 20 | 21 | ```bash 22 | $ hack/bump-release.sh 28 29 0 23 | ``` 24 | 25 | This will replace `1.28.x`/`2.28.x` with `1.29.0`/`2.29.0` strings in the 26 | `docs/manifests/tests/examples` directories. Ensure that you double-check the 27 | diff before committing the changes. Non-related changes must not be shipped. 28 | 29 | 3. Create a new pull request (PR) and make sure all CI checks have passed. 30 | 31 | 4. Once the PR is merged, make a tag and push it to the upstream repository. 32 | 33 | ```bash 34 | $ git checkout master 35 | $ git pull upstream master 36 | $ git tag vX.Y.Z 37 | $ git push upstream vX.Y.Z 38 | $ git checkout -b release-X.Y 39 | $ git push origin release-X.Y 40 | ``` 41 | 42 | 5. new [Docker images](https://console.cloud.google.com/gcr/images/k8s-staging-provider-os) will be builded. 43 | 44 | 6. Make PR modifying [images.yaml](https://github.com/kubernetes/k8s.io/blob/main/registry.k8s.io/images/k8s-staging-provider-os/images.yaml) to promote gcr.io images to registry.k8s.io. The point is to copy the proper image sha256 hashes from the staging repository to the images.yaml. 45 | 46 | 7. Once images are promoted create release notes using the "Generate release notes" button in the GitHub "New release" UI and publish the release. 47 | -------------------------------------------------------------------------------- /examples/cinder-csi-plugin/block/block.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: StorageClass 3 | metadata: 4 | name: csi-sc-cinderplugin 5 | provisioner: cinder.csi.openstack.org 6 | 7 | --- 8 | apiVersion: v1 9 | kind: PersistentVolumeClaim 10 | metadata: 11 | name: csi-pvc-cinderplugin 12 | spec: 13 | accessModes: 14 | - ReadWriteOnce 15 | volumeMode: Block 16 | resources: 17 | requests: 18 | storage: 1Gi 19 | storageClassName: csi-sc-cinderplugin 20 | 21 | --- 22 | apiVersion: v1 23 | kind: Pod 24 | metadata: 25 | name: test-block 26 | spec: 27 | containers: 28 | - image: nginx 29 | imagePullPolicy: IfNotPresent 30 | name: nginx 31 | ports: 32 | - containerPort: 80 33 | protocol: TCP 34 | volumeDevices: 35 | - devicePath: /dev/xvda 36 | name: csi-data-cinderplugin 37 | volumes: 38 | - name: csi-data-cinderplugin 39 | persistentVolumeClaim: 40 | claimName: csi-pvc-cinderplugin 41 | readOnly: false 42 | -------------------------------------------------------------------------------- /examples/cinder-csi-plugin/clone/example-clone.yaml: -------------------------------------------------------------------------------- 1 | # This YAML file contains nginx & csi cinder driver objects, 2 | # which are necessary to run nginx with csi cinder driver. 3 | 4 | --- 5 | apiVersion: v1 6 | kind: PersistentVolumeClaim 7 | metadata: 8 | name: csi-pvc-clone 9 | spec: 10 | dataSource: 11 | name: source-pvc 12 | kind: PersistentVolumeClaim 13 | apiGroup: "" 14 | accessModes: 15 | - ReadWriteOnce 16 | resources: 17 | requests: 18 | storage: 1Gi 19 | storageClassName: csi-cinderplugin-sc 20 | 21 | --- 22 | apiVersion: v1 23 | kind: Pod 24 | metadata: 25 | name: nginx 26 | spec: 27 | containers: 28 | - image: nginx 29 | imagePullPolicy: IfNotPresent 30 | name: nginx 31 | ports: 32 | - containerPort: 80 33 | protocol: TCP 34 | volumeMounts: 35 | - mountPath: /var/lib/www/html 36 | name: csi-data-cinderplugin 37 | volumes: 38 | - name: csi-data-cinderplugin 39 | persistentVolumeClaim: 40 | claimName: csi-pvc-clone 41 | readOnly: false 42 | -------------------------------------------------------------------------------- /examples/cinder-csi-plugin/clone/sc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: StorageClass 3 | metadata: 4 | name: csi-cinderplugin-sc 5 | provisioner: cinder.csi.openstack.org 6 | -------------------------------------------------------------------------------- /examples/cinder-csi-plugin/clone/source-pvc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: source-pvc 5 | spec: 6 | storageClassName: csi-cinderplugin-sc 7 | accessModes: 8 | - ReadWriteOnce 9 | resources: 10 | requests: 11 | storage: 1Gi 12 | -------------------------------------------------------------------------------- /examples/cinder-csi-plugin/ephemeral/csi-ephemeral-volumes-example.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: inline-pod 5 | spec: 6 | containers: 7 | - image: nginx 8 | imagePullPolicy: IfNotPresent 9 | name: nginx-inline 10 | volumeMounts: 11 | - name: my-csi-volume 12 | mountPath: /var/lib/www/html 13 | volumes: 14 | - name: my-csi-volume 15 | csi: 16 | driver: cinder.csi.openstack.org 17 | volumeAttributes: 18 | capacity: 1Gi # default is 1Gi 19 | readOnly: false # default is false 20 | fsType: ext4 # default is ext4 21 | -------------------------------------------------------------------------------- /examples/cinder-csi-plugin/ephemeral/generic-ephemeral-volumes.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: StorageClass 3 | metadata: 4 | name: scratch-storage-class 5 | provisioner: cinder.csi.openstack.org 6 | 7 | --- 8 | apiVersion: v1 9 | kind: Pod 10 | metadata: 11 | name: ephemeral-example 12 | spec: 13 | containers: 14 | - image: nginx 15 | imagePullPolicy: IfNotPresent 16 | name: nginx-inline 17 | volumeMounts: 18 | - name: scratch-volume 19 | mountPath: /var/lib/www/html 20 | volumes: 21 | - name: scratch-volume 22 | ephemeral: 23 | volumeClaimTemplate: 24 | metadata: 25 | labels: 26 | type: my-frontend-volume 27 | spec: 28 | accessModes: [ "ReadWriteOnce" ] 29 | storageClassName: scratch-storage-class 30 | resources: 31 | requests: 32 | storage: 1Gi 33 | -------------------------------------------------------------------------------- /examples/cinder-csi-plugin/nginx.yaml: -------------------------------------------------------------------------------- 1 | # This YAML file contains nginx & csi cinder driver objects, 2 | # which are necessary to run nginx with csi cinder driver. 3 | 4 | apiVersion: storage.k8s.io/v1 5 | kind: StorageClass 6 | metadata: 7 | name: csi-sc-cinderplugin 8 | provisioner: cinder.csi.openstack.org 9 | 10 | --- 11 | apiVersion: v1 12 | kind: PersistentVolumeClaim 13 | metadata: 14 | name: csi-pvc-cinderplugin 15 | spec: 16 | accessModes: 17 | - ReadWriteOnce 18 | resources: 19 | requests: 20 | storage: 1Gi 21 | storageClassName: csi-sc-cinderplugin 22 | 23 | --- 24 | apiVersion: v1 25 | kind: Pod 26 | metadata: 27 | name: nginx 28 | spec: 29 | containers: 30 | - image: nginx 31 | imagePullPolicy: IfNotPresent 32 | name: nginx 33 | ports: 34 | - containerPort: 80 35 | protocol: TCP 36 | volumeMounts: 37 | - mountPath: /var/lib/www/html 38 | name: csi-data-cinderplugin 39 | volumes: 40 | - name: csi-data-cinderplugin 41 | persistentVolumeClaim: 42 | claimName: csi-pvc-cinderplugin 43 | readOnly: false 44 | -------------------------------------------------------------------------------- /examples/cinder-csi-plugin/resize/example.yaml: -------------------------------------------------------------------------------- 1 | # This YAML file contains nginx & csi cinder driver objects, 2 | # which are necessary to run nginx with csi cinder driver. 3 | 4 | apiVersion: storage.k8s.io/v1 5 | kind: StorageClass 6 | metadata: 7 | name: csi-sc-cinderplugin 8 | provisioner: cinder.csi.openstack.org 9 | allowVolumeExpansion: true 10 | 11 | --- 12 | apiVersion: v1 13 | kind: PersistentVolumeClaim 14 | metadata: 15 | name: csi-pvc-cinderplugin 16 | spec: 17 | accessModes: 18 | - ReadWriteOnce 19 | resources: 20 | requests: 21 | storage: 1Gi 22 | storageClassName: csi-sc-cinderplugin 23 | 24 | --- 25 | apiVersion: v1 26 | kind: Pod 27 | metadata: 28 | name: nginx 29 | spec: 30 | containers: 31 | - image: nginx 32 | imagePullPolicy: IfNotPresent 33 | name: nginx 34 | ports: 35 | - containerPort: 80 36 | protocol: TCP 37 | volumeMounts: 38 | - mountPath: /var/lib/www/html 39 | name: csi-data-cinderplugin 40 | volumes: 41 | - name: csi-data-cinderplugin 42 | persistentVolumeClaim: 43 | claimName: csi-pvc-cinderplugin 44 | readOnly: false 45 | -------------------------------------------------------------------------------- /examples/cinder-csi-plugin/snapshot/example.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: StorageClass 3 | metadata: 4 | name: csi-sc-cinderplugin 5 | provisioner: cinder.csi.openstack.org 6 | 7 | --- 8 | 9 | apiVersion: snapshot.storage.k8s.io/v1 10 | kind: VolumeSnapshotClass 11 | metadata: 12 | name: csi-cinder-snapclass 13 | driver: cinder.csi.openstack.org 14 | deletionPolicy: Delete 15 | parameters: 16 | force-create: "false" 17 | 18 | --- 19 | 20 | apiVersion: v1 21 | kind: PersistentVolumeClaim 22 | metadata: 23 | name: pvc-snapshot-demo 24 | spec: 25 | accessModes: 26 | - ReadWriteOnce 27 | resources: 28 | requests: 29 | storage: 1Gi 30 | storageClassName: csi-sc-cinderplugin 31 | -------------------------------------------------------------------------------- /examples/cinder-csi-plugin/snapshot/snapshotcreate.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: snapshot.storage.k8s.io/v1 2 | kind: VolumeSnapshot 3 | metadata: 4 | name: new-snapshot-demo 5 | spec: 6 | volumeSnapshotClassName: csi-cinder-snapclass 7 | source: 8 | persistentVolumeClaimName: pvc-snapshot-demo 9 | -------------------------------------------------------------------------------- /examples/cinder-csi-plugin/snapshot/snapshotrestore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: snapshot-demo-restore 5 | spec: 6 | storageClassName: csi-sc-cinderplugin 7 | dataSource: 8 | name: new-snapshot-demo 9 | kind: VolumeSnapshot 10 | apiGroup: snapshot.storage.k8s.io 11 | accessModes: 12 | - ReadWriteOnce 13 | resources: 14 | requests: 15 | storage: 1Gi 16 | -------------------------------------------------------------------------------- /examples/cinder-csi-plugin/topology/example.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: StorageClass 3 | metadata: 4 | name: topology-aware-standard 5 | provisioner: cinder.csi.openstack.org 6 | volumeBindingMode: WaitForFirstConsumer 7 | allowedTopologies: 8 | - matchLabelExpressions: 9 | - key: topology.cinder.csi.openstack.org/zone 10 | values: 11 | - nova1 12 | 13 | --- 14 | apiVersion: v1 15 | kind: PersistentVolumeClaim 16 | metadata: 17 | name: pvc1 18 | spec: 19 | accessModes: 20 | - ReadWriteOnce 21 | resources: 22 | requests: 23 | storage: 1Gi 24 | storageClassName: topology-aware-standard 25 | 26 | --- 27 | apiVersion: v1 28 | kind: Pod 29 | metadata: 30 | name: app 31 | spec: 32 | containers: 33 | - image: nginx 34 | imagePullPolicy: IfNotPresent 35 | name: nginx 36 | ports: 37 | - containerPort: 80 38 | protocol: TCP 39 | volumeMounts: 40 | - mountPath: /var/lib/www/data 41 | name: mydata 42 | volumes: 43 | - name: mydata 44 | persistentVolumeClaim: 45 | claimName: pvc1 46 | readOnly: false 47 | -------------------------------------------------------------------------------- /examples/loadbalancers/external-http-nginx.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: external-http-nginx-deployment 6 | spec: 7 | replicas: 2 8 | selector: 9 | matchLabels: 10 | app: nginx 11 | template: 12 | metadata: 13 | labels: 14 | app: nginx 15 | spec: 16 | containers: 17 | - name: nginx 18 | image: nginx 19 | ports: 20 | - containerPort: 80 21 | --- 22 | kind: Service 23 | apiVersion: v1 24 | metadata: 25 | name: external-http-nginx-service 26 | annotations: 27 | service.beta.kubernetes.io/openstack-internal-load-balancer: "false" 28 | loadbalancer.openstack.org/floating-network-id: "9be23551-38e2-4d27-b5ea-ea2ea1321bd6" 29 | spec: 30 | selector: 31 | app: nginx 32 | type: LoadBalancer 33 | ports: 34 | - name: http 35 | port: 80 36 | targetPort: 80 37 | -------------------------------------------------------------------------------- /examples/loadbalancers/internal-http-nginx.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: Deployment 4 | metadata: 5 | name: internal-http-nginx-deployment 6 | spec: 7 | replicas: 2 8 | selector: 9 | matchLabels: 10 | app: nginx 11 | template: 12 | metadata: 13 | labels: 14 | app: nginx 15 | spec: 16 | containers: 17 | - name: nginx 18 | image: nginx 19 | ports: 20 | - containerPort: 80 21 | --- 22 | kind: Service 23 | apiVersion: v1 24 | metadata: 25 | name: internal-http-nginx-service 26 | annotations: 27 | service.beta.kubernetes.io/openstack-internal-load-balancer: "true" 28 | spec: 29 | selector: 30 | app: nginx 31 | type: LoadBalancer 32 | ports: 33 | - name: http 34 | port: 80 35 | targetPort: 80 36 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/README.md: -------------------------------------------------------------------------------- 1 | ## General notes before continuing 2 | 3 | 1. Make sure you've completed all the steps in `docs/using-manila-csi-plugin.md`: e.g. you've deployed CSI NFS and CSI Manila plugins and CSI Manila is running with `--share-protocol-selector=NFS` and `--fwdendpoint=unix:///csi/csi-nfsplugin/csi.sock` (or similar, based on your environment) 4 | 2. Modify `secrets.yaml` to suite your OpenStack cloud environment. Refer to the _"Secrets, authentication"_ section of CSI Manila docs. You may also use helper scripts from `examples/manila-provisioner` to generate the Secrets manifest. 5 | 3. The same steps apply to all supported Manila share protocols 6 | 4. `exec-bash.sh`, `logs.sh` are convenience scripts for debugging CSI Manila 7 | 8 | ## Example CSI Manila usage with NFS shares 9 | 10 | ``` 11 | nfs/ 12 | ├── dynamic-provisioning/ 13 | │   ├── pod.yaml 14 | │   ├── pvc.yaml 15 | │   └── --> storageclass.yaml <-- 16 | ├── snapshot/ 17 | │   ├── pod.yaml 18 | │   ├── --> snapshotclass.yaml <-- 19 | │   ├── snapshotcreate.yaml 20 | │   └── snapshotrestore.yaml 21 | ├── static-provisioning/ 22 | │ ├── pod.yaml 23 | │ └── --> preprovisioned-pvc.yaml <-- 24 | ├── topology-aware/ 25 | │   ├── pod.yaml 26 | │   ├── pvc.yaml 27 | │   └── --> storageclass.yaml <-- 28 | └── --> secrets.yaml <-- 29 | ``` 30 | 31 | Files marked with `--> ... <--` may need to be customized. 32 | 33 | * `dynamic-provisioning/` : creates a new Manila NFS share and mounts it in a Pod. 34 | * `static-provisioning/` : fetches an existing Manila NFS share and mounts it in a Pod 35 | * `snapshot/` : takes a snapshot from a PVC source, restores it into a new share and mounts it in a Pod. Deploy manifests in `dynamic-provisioning/` first 36 | * `topology-aware/` : topology-aware dynamic provisioning 37 | 38 | Make sure the `provisioner` field in `storageclass.yaml` and `snapshotclass.yaml` matches the driver name in your deployment! 39 | 40 | After deploying each example you should see the corresponding Pod with status _Running_ soon. 41 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/exec-bash.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | CONTAINER_NAME=csi-nodeplugin-manilaplugin 4 | POD_NAME=$(kubectl get pods -l app=$CONTAINER_NAME -o=name | head -n 1) 5 | 6 | function get_pod_status() { 7 | echo -n "$(kubectl get "$POD_NAME" -o jsonpath="{.status.phase}")" 8 | } 9 | 10 | while [[ "$(get_pod_status)" != "Running" ]]; do 11 | sleep 1 12 | echo "Waiting for $POD_NAME (status $(get_pod_status))" 13 | done 14 | 15 | kubectl exec -it "${POD_NAME#*/}" -c "$CONTAINER_NAME" bash 16 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/logs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | POD_NAME=$(kubectl get pods -l app=csi-nodeplugin-manilaplugin -o=name | head -n 1) 4 | 5 | function get_pod_status() { 6 | echo -n $(kubectl get $POD_NAME -o jsonpath="{.status.phase}") 7 | } 8 | 9 | while [[ $(get_pod_status) != "Running" ]]; do 10 | sleep 1 11 | echo "Waiting for $POD_NAME (status $(get_pod_status))" 12 | done 13 | 14 | 15 | kubectl logs -f $POD_NAME -c csi-nodeplugin-manilaplugin 16 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/nfs/auto-topology-aware/pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: new-nfs-share-pod 5 | spec: 6 | containers: 7 | - name: web-server 8 | image: nginx 9 | imagePullPolicy: IfNotPresent 10 | volumeMounts: 11 | - name: mypvc 12 | mountPath: /var/lib/www 13 | nodeSelector: 14 | topology.kubernetes.io/zone: zone-1 15 | volumes: 16 | - name: mypvc 17 | persistentVolumeClaim: 18 | claimName: new-nfs-share-pvc 19 | readOnly: false 20 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/nfs/auto-topology-aware/pvc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: new-nfs-share-pvc 5 | spec: 6 | accessModes: 7 | - ReadWriteMany 8 | resources: 9 | requests: 10 | storage: 1Gi 11 | storageClassName: csi-manila-nfs 12 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/nfs/auto-topology-aware/storageclass.yaml: -------------------------------------------------------------------------------- 1 | # Topology constraints example: 2 | # 3 | # Let's have two Manila AZs: zone-{1..2} 4 | # Let's have six Nova AZs: zone-{1..6} 5 | # 6 | # Manila zone-1 is accessible from nodes in zone-1 only 7 | # Manila zone-2 is accessible from nodes in zone-2 only 8 | # 9 | # We're provisioning into zone-1 10 | # availability parameter and allowedTopologies are empty, therefore the dynamic 11 | # share provisioning with automatic availability zone selection takes place. 12 | # The "volumeBindingMode" must be set to "WaitForFirstConsumer". 13 | 14 | apiVersion: storage.k8s.io/v1 15 | kind: StorageClass 16 | metadata: 17 | name: csi-manila-nfs 18 | provisioner: nfs.manila.csi.openstack.org 19 | volumeBindingMode: WaitForFirstConsumer 20 | allowVolumeExpansion: true 21 | parameters: 22 | type: default 23 | autoTopology: "true" 24 | csi.storage.k8s.io/provisioner-secret-name: csi-manila-secrets 25 | csi.storage.k8s.io/provisioner-secret-namespace: default 26 | csi.storage.k8s.io/node-stage-secret-name: csi-manila-secrets 27 | csi.storage.k8s.io/node-stage-secret-namespace: default 28 | csi.storage.k8s.io/node-publish-secret-name: csi-manila-secrets 29 | csi.storage.k8s.io/node-publish-secret-namespace: default 30 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/nfs/dynamic-provisioning/pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: new-nfs-share-pod 5 | spec: 6 | containers: 7 | - name: web-server 8 | image: nginx 9 | imagePullPolicy: IfNotPresent 10 | volumeMounts: 11 | - name: mypvc 12 | mountPath: /var/lib/www 13 | volumes: 14 | - name: mypvc 15 | persistentVolumeClaim: 16 | claimName: new-nfs-share-pvc 17 | readOnly: false 18 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/nfs/dynamic-provisioning/pvc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: new-nfs-share-pvc 5 | spec: 6 | accessModes: 7 | - ReadWriteMany 8 | resources: 9 | requests: 10 | storage: 1Gi 11 | storageClassName: csi-manila-nfs 12 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/nfs/dynamic-provisioning/storageclass.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: StorageClass 3 | metadata: 4 | name: csi-manila-nfs 5 | provisioner: nfs.manila.csi.openstack.org 6 | allowVolumeExpansion: true 7 | parameters: 8 | # Manila share type 9 | type: default 10 | 11 | csi.storage.k8s.io/provisioner-secret-name: csi-manila-secrets 12 | csi.storage.k8s.io/provisioner-secret-namespace: default 13 | csi.storage.k8s.io/controller-expand-secret-name: csi-manila-secrets 14 | csi.storage.k8s.io/controller-expand-secret-namespace: default 15 | csi.storage.k8s.io/node-stage-secret-name: csi-manila-secrets 16 | csi.storage.k8s.io/node-stage-secret-namespace: default 17 | csi.storage.k8s.io/node-publish-secret-name: csi-manila-secrets 18 | csi.storage.k8s.io/node-publish-secret-namespace: default 19 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/nfs/secrets.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: csi-manila-secrets 5 | namespace: default 6 | stringData: 7 | # Mandatory 8 | os-authURL: "some-auth-url" 9 | os-region: "some-region" 10 | 11 | # Authentication using user credentials 12 | os-userName: "some-username" 13 | os-password: "some-password" 14 | os-projectName: "some-project-name" 15 | os-domainID: "some-domain-id" 16 | 17 | # Authentication using trustee credentials 18 | os-trustID: "some-trust-id" 19 | os-trusteeID: "some-trustee-id" 20 | os-trusteePassword: "some-trustee-password" 21 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/nfs/snapshot/pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: new-nfs-share-snap-restore-pod 5 | spec: 6 | containers: 7 | - name: web-server 8 | image: nginx 9 | imagePullPolicy: IfNotPresent 10 | volumeMounts: 11 | - name: mypvc 12 | mountPath: /var/lib/www 13 | volumes: 14 | - name: mypvc 15 | persistentVolumeClaim: 16 | claimName: new-nfs-share-snap-restore 17 | readOnly: false 18 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/nfs/snapshot/snapshotclass.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: snapshot.storage.k8s.io/v1 2 | kind: VolumeSnapshotClass 3 | metadata: 4 | name: csi-manila-nfs 5 | driver: nfs.manila.csi.openstack.org 6 | deletionPolicy: Delete 7 | parameters: 8 | csi.storage.k8s.io/snapshotter-secret-name: csi-manila-secrets 9 | csi.storage.k8s.io/snapshotter-secret-namespace: default 10 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/nfs/snapshot/snapshotcreate.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: snapshot.storage.k8s.io/v1 2 | kind: VolumeSnapshot 3 | metadata: 4 | name: new-nfs-share-snap 5 | spec: 6 | volumeSnapshotClassName: csi-manila-nfs 7 | source: 8 | persistentVolumeClaimName: new-nfs-share-pvc 9 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/nfs/snapshot/snapshotrestore.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: new-nfs-share-snap-restore 5 | spec: 6 | storageClassName: csi-manila-nfs 7 | dataSource: 8 | name: new-nfs-share-snap 9 | kind: VolumeSnapshot 10 | apiGroup: snapshot.storage.k8s.io 11 | accessModes: 12 | - ReadWriteMany 13 | resources: 14 | requests: 15 | storage: 1Gi 16 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/nfs/static-provisioning/pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: existing-nfs-share-pod 5 | spec: 6 | containers: 7 | - name: web-server 8 | image: nginx 9 | imagePullPolicy: IfNotPresent 10 | volumeMounts: 11 | - name: mypvc 12 | mountPath: /var/lib/www 13 | volumes: 14 | - name: mypvc 15 | persistentVolumeClaim: 16 | claimName: existing-nfs-share-pvc 17 | readOnly: false 18 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/nfs/static-provisioning/preprovisioned-pvc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolume 3 | metadata: 4 | name: preprovisioned-nfs-share 5 | labels: 6 | name: preprovisioned-nfs-share 7 | spec: 8 | accessModes: 9 | - ReadWriteMany 10 | capacity: 11 | storage: 1Gi 12 | csi: 13 | driver: nfs.manila.csi.openstack.org 14 | volumeHandle: preprovisioned-nfs-share 15 | nodeStageSecretRef: 16 | name: csi-manila-secrets 17 | namespace: default 18 | nodePublishSecretRef: 19 | name: csi-manila-secrets 20 | namespace: default 21 | volumeAttributes: 22 | shareID: SHARE-UUID-GOES-HERE 23 | shareAccessID: ACCESS-UUID-OF-THE-SHARE 24 | --- 25 | apiVersion: v1 26 | kind: PersistentVolumeClaim 27 | metadata: 28 | name: existing-nfs-share-pvc 29 | spec: 30 | accessModes: 31 | - ReadWriteMany 32 | resources: 33 | requests: 34 | storage: 1Gi 35 | selector: 36 | matchExpressions: 37 | - key: name 38 | operator: In 39 | values: ["preprovisioned-nfs-share"] 40 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/nfs/topology-aware/pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: new-nfs-share-pod 5 | spec: 6 | containers: 7 | - name: web-server 8 | image: nginx 9 | imagePullPolicy: IfNotPresent 10 | volumeMounts: 11 | - name: mypvc 12 | mountPath: /var/lib/www 13 | volumes: 14 | - name: mypvc 15 | persistentVolumeClaim: 16 | claimName: new-nfs-share-pvc 17 | readOnly: false 18 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/nfs/topology-aware/pvc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: PersistentVolumeClaim 3 | metadata: 4 | name: new-nfs-share-pvc 5 | spec: 6 | accessModes: 7 | - ReadWriteMany 8 | resources: 9 | requests: 10 | storage: 1Gi 11 | storageClassName: csi-manila-nfs-az 12 | 13 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/nfs/topology-aware/storageclass.yaml: -------------------------------------------------------------------------------- 1 | # Topology constraints example: 2 | # 3 | # Let's have two Manila AZs: manila-zone-1, manila-zone-2 4 | # Let's have six Nova AZs: nova-{1..6} 5 | # 6 | # manila-zone-1 is accessible from nodes in nova-{1,2,3} only 7 | # manila-zone-2 is accessible from nodes in nova-{4,5,6} only 8 | # 9 | # We're provisioning into manila-zone-1 10 | # allowedTopologies reflects the topology constraints 11 | 12 | apiVersion: storage.k8s.io/v1 13 | kind: StorageClass 14 | metadata: 15 | name: csi-manila-nfs-az 16 | provisioner: nfs.manila.csi.openstack.org 17 | parameters: 18 | type: default 19 | availability: manila-zone-1 20 | 21 | csi.storage.k8s.io/provisioner-secret-name: csi-manila-secrets 22 | csi.storage.k8s.io/provisioner-secret-namespace: default 23 | csi.storage.k8s.io/node-stage-secret-name: csi-manila-secrets 24 | csi.storage.k8s.io/node-stage-secret-namespace: default 25 | csi.storage.k8s.io/node-publish-secret-name: csi-manila-secrets 26 | csi.storage.k8s.io/node-publish-secret-namespace: default 27 | allowVolumeExpansion: true 28 | allowedTopologies: 29 | - matchLabelExpressions: 30 | - key: topology.manila.csi.openstack.org/zone 31 | values: 32 | - nova-1 33 | - nova-2 34 | - nova-3 35 | # ...or you may use other node labels: 36 | # - key: my-zone-label 37 | # values: 38 | # - nodes-that-can-reach-manila-az-1 39 | -------------------------------------------------------------------------------- /examples/manila-csi-plugin/runtimeconfig-cm.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: manila-csi-runtimeconf-cm 5 | data: 6 | runtimeconfig.json: | 7 | { 8 | "nfs": { 9 | # When mounting an NFS share, select an export location with 10 | # this IP address. No match between this address and 11 | # at least a single export location for this share will 12 | # result in an error. 13 | # Expects a CIDR-formatted address. If prefix is not provided, 14 | # /32 or /128 prefix is assumed for IPv4 and IPv6 respectively. 15 | "matchExportLocationAddress": "172.168.122.0/24" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/webhook/keystone-apiserver-webhook.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Config 3 | preferences: {} 4 | clusters: 5 | - cluster: 6 | insecure-skip-tls-verify: true 7 | server: https://{{ keystone_auth_service_ip }}:8443/webhook 8 | name: webhook 9 | users: 10 | - name: webhook 11 | contexts: 12 | - context: 13 | cluster: webhook 14 | user: webhook 15 | name: webhook 16 | current-context: webhook 17 | -------------------------------------------------------------------------------- /examples/webhook/keystone-deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: k8s-keystone-auth 5 | namespace: kube-system 6 | labels: 7 | app: k8s-keystone-auth 8 | spec: 9 | replicas: 2 10 | selector: 11 | matchLabels: 12 | app: k8s-keystone-auth 13 | template: 14 | metadata: 15 | labels: 16 | app: k8s-keystone-auth 17 | spec: 18 | serviceAccountName: k8s-keystone 19 | containers: 20 | - name: k8s-keystone-auth 21 | image: registry.k8s.io/provider-os/k8s-keystone-auth:v1.32.0 22 | args: 23 | - ./bin/k8s-keystone-auth 24 | - --tls-cert-file 25 | - /etc/pki/tls.crt 26 | - --tls-private-key-file 27 | - /etc/pki/tls.key 28 | - --policy-configmap-name 29 | - k8s-auth-policy 30 | - --keystone-url 31 | - {{ keystone_server_url }} 32 | volumeMounts: 33 | - mountPath: /etc/pki 34 | name: certs 35 | readOnly: true 36 | ports: 37 | - containerPort: 8443 38 | volumes: 39 | - name: certs 40 | secret: 41 | secretName: keystone-auth-certs 42 | -------------------------------------------------------------------------------- /examples/webhook/keystone-policy-configmap.yaml: -------------------------------------------------------------------------------- 1 | # This file lays out the policies of the cluster. It is only used 2 | # if using Keystone for authorization. Note the difference between 3 | # authentication and authorization. 4 | 5 | # This configmap allows the users in the project 'demo' that have 6 | # the 'k8s-viewer' role in Keystone to query the pod information 7 | # from all the namespaces. The configmap is in the kube-system 8 | # namespace due to the k8s-keystone-auth service existing in 9 | # the kube-system namespace. 10 | 11 | # This is version 1 policy definition 12 | 13 | # apiVersion: v1 14 | # kind: ConfigMap 15 | # metadata: 16 | # name: k8s-auth-policy 17 | # namespace: kube-system 18 | # labels: 19 | # k8s-app: k8s-keystone-auth 20 | # data: 21 | # policies: | 22 | # [ 23 | # { 24 | # "resource": { 25 | # "verbs": ["get", "list", "watch"], 26 | # "resources": ["pods"], 27 | # "version": "*", 28 | # "namespace": "default" 29 | # }, 30 | # "match": [ 31 | # { 32 | # "type": "role", 33 | # "values": ["k8s-viewer"] 34 | # }, 35 | # { 36 | # "type": "project", 37 | # "values": ["demo"] 38 | # } 39 | # ] 40 | # } 41 | # ] 42 | 43 | # This is version 2 policy definition 44 | 45 | apiVersion: v1 46 | kind: ConfigMap 47 | metadata: 48 | name: k8s-auth-policy 49 | namespace: kube-system 50 | data: 51 | policies: | 52 | [ 53 | { 54 | "users": { 55 | "projects": ["demo"], 56 | "roles": ["member"] 57 | }, 58 | "resource_permissions": { 59 | "*/pods": ["get", "list", "watch"] 60 | } 61 | } 62 | ] 63 | -------------------------------------------------------------------------------- /examples/webhook/keystone-rbac.yaml: -------------------------------------------------------------------------------- 1 | kind: ClusterRole 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | metadata: 4 | labels: 5 | k8s-app: k8s-keystone-auth 6 | name: k8s-keystone-auth 7 | rules: 8 | # Allow k8s-keystone-auth to get k8s-auth-policy configmap 9 | - apiGroups: [""] 10 | resources: ["configmaps"] 11 | verbs: ["get", "watch", "list"] 12 | --- 13 | apiVersion: rbac.authorization.k8s.io/v1 14 | kind: ClusterRoleBinding 15 | metadata: 16 | name: k8s-keystone-auth 17 | labels: 18 | k8s-app: k8s-keystone-auth 19 | roleRef: 20 | apiGroup: rbac.authorization.k8s.io 21 | kind: ClusterRole 22 | name: k8s-keystone-auth 23 | subjects: 24 | - kind: ServiceAccount 25 | name: k8s-keystone 26 | namespace: kube-system 27 | --- 28 | apiVersion: v1 29 | kind: ServiceAccount 30 | metadata: 31 | name: k8s-keystone 32 | namespace: kube-system 33 | -------------------------------------------------------------------------------- /examples/webhook/keystone-service.yaml: -------------------------------------------------------------------------------- 1 | kind: Service 2 | apiVersion: v1 3 | metadata: 4 | name: k8s-keystone-auth-service 5 | namespace: kube-system 6 | spec: 7 | selector: 8 | app: k8s-keystone-auth 9 | ports: 10 | - protocol: TCP 11 | port: 8443 12 | targetPort: 8443 13 | -------------------------------------------------------------------------------- /examples/webhook/policy.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "resource": { 4 | "verbs": [ 5 | "get", 6 | "list", 7 | "watch" 8 | ], 9 | "resources": [ 10 | "pods" 11 | ], 12 | "version": "*", 13 | "namespace": "default" 14 | }, 15 | "match": [ 16 | { 17 | "type": "role", 18 | "values": [ 19 | "k8s-admin", 20 | "k8s-viewer", 21 | "k8s-editor" 22 | ] 23 | }, 24 | { 25 | "type": "project", 26 | "values": [ 27 | "c1f7910086964990847dc6c8b128f63c" 28 | ] 29 | } 30 | ] 31 | } 32 | ] -------------------------------------------------------------------------------- /hack/bump-release.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright 2023 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | FROM_MAJOR="${1:?FROM_MAJOR (1st arg) not set or empty}" 18 | TO_MAJOR="${2:?TO_MAJOR (2nd arg) not set or empty}" 19 | TO_MINOR="${3:?TO_MINOR (3rd arg) not set or empty}" 20 | 21 | # example usage: hack/bump-release.sh 28 28 1 22 | # should replace 1.28.x with 1.28.1 / 2.28.x with 2.28.1 23 | 24 | find charts docs manifests tests examples -type f -exec sed -i -re 's/((ersion)?: ?v?)?([1-2]\.)'${FROM_MAJOR}'\.([0-9][0-9a-zA-Z.-]*)/\1\3'${TO_MAJOR}'.'${TO_MINOR}'/g' "{}" \; 25 | -------------------------------------------------------------------------------- /hack/make.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2018 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Simple script to offer the ability to run the make directives in a Docker Container. 18 | # In other words you don't need a Go env on your system to run Make (build, test etc) 19 | # This script will just bind-mount the source directory into a container under the correct 20 | # GOPATH and handle all of the Go ENV stuff for you. All you need is Docker 21 | docker run -it -v "$PWD":/go/src/k8s.io/cloud-provider-openstack:z \ 22 | -w /go/src/k8s.io/cloud-provider-openstack \ 23 | golang:1.25 make $1 24 | -------------------------------------------------------------------------------- /hack/update-gofmt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2017 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | find . -name "*.go" | grep -v "\/vendor\/\|\.\/\.go" | xargs gofmt -s -w 22 | -------------------------------------------------------------------------------- /manifests/barbican-kms/ds.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apps/v1 3 | kind: DaemonSet 4 | metadata: 5 | name: barbican-kms 6 | namespace: kube-system 7 | labels: 8 | k8s-app: barbican-kms 9 | spec: 10 | selector: 11 | matchLabels: 12 | k8s-app: barbican-kms 13 | updateStrategy: 14 | type: RollingUpdate 15 | template: 16 | metadata: 17 | labels: 18 | k8s-app: barbican-kms 19 | spec: 20 | nodeSelector: 21 | node-role.kubernetes.io/control-plane: "" 22 | tolerations: 23 | - key: node.cloudprovider.kubernetes.io/uninitialized 24 | value: "true" 25 | effect: NoSchedule 26 | - key: node-role.kubernetes.io/master 27 | effect: NoSchedule 28 | - key: node-role.kubernetes.io/control-plane 29 | effect: NoSchedule 30 | serviceAccountName: cloud-controller-manager 31 | containers: 32 | - name: barbican-kms 33 | image: registry.k8s.io/provider-os/barbican-kms-plugin:v1.32.0 34 | args: 35 | - /bin/barbican-kms-plugin 36 | - --socketpath=$(KMS_ENDPOINT) 37 | - --cloud-config=$(CLOUD_CONFIG) 38 | volumeMounts: 39 | - name: cloud-config-volume 40 | mountPath: /etc/config 41 | - name: socket-dir 42 | mountPath: /kms/ 43 | env: 44 | - name: CLOUD_CONFIG 45 | value: /etc/config/cloud.conf 46 | - name: KMS_ENDPOINT 47 | value: /kms/kms.sock 48 | livenessProbe: 49 | failureThreshold: 5 50 | exec: 51 | command: 52 | - ls 53 | - $(KMS_ENDPOINT) 54 | initialDelaySeconds: 10 55 | timeoutSeconds: 10 56 | periodSeconds: 60 57 | volumes: 58 | - name: cloud-config-volume 59 | secret: 60 | secretName: cloud-config 61 | - name: socket-dir 62 | hostPath: 63 | path: /var/lib/kms/ 64 | type: DirectoryOrCreate 65 | hostNetwork: true 66 | -------------------------------------------------------------------------------- /manifests/barbican-kms/encryption-config.yaml: -------------------------------------------------------------------------------- 1 | kind: EncryptionConfig 2 | apiVersion: v1 3 | resources: 4 | - resources: 5 | - secrets 6 | providers: 7 | - kms: 8 | apiVersion: v2 9 | name: barbican 10 | endpoint: unix:///var/lib/kms/kms.sock 11 | - identity: {} 12 | -------------------------------------------------------------------------------- /manifests/barbican-kms/pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | name: barbican-kms 5 | spec: 6 | containers: 7 | - name: barbican-kms 8 | image: registry.k8s.io/provider-os/barbican-kms-plugin:v1.32.0 9 | args: 10 | - "--socketpath=/kms/kms.sock" 11 | - "--cloud-config=/etc/kubernetes/cloud-config" 12 | volumeMounts: 13 | - name: cloud-config 14 | mountPath: /etc/kubernetes/ 15 | - name: socket-dir 16 | mountPath: /kms/ 17 | volumes: 18 | - name: config 19 | hostPath: 20 | path: /etc/kubernetes 21 | - name: socket-dir 22 | hostPath: 23 | path: /var/lib/kms/ 24 | type: DirectoryOrCreate 25 | -------------------------------------------------------------------------------- /manifests/cinder-csi-plugin/cinder-csi-nodeplugin-rbac.yaml: -------------------------------------------------------------------------------- 1 | # This YAML defines all API objects to create RBAC roles for csi node plugin. 2 | 3 | apiVersion: v1 4 | kind: ServiceAccount 5 | metadata: 6 | name: csi-cinder-node-sa 7 | namespace: kube-system 8 | --- 9 | kind: ClusterRole 10 | apiVersion: rbac.authorization.k8s.io/v1 11 | metadata: 12 | name: csi-nodeplugin-role 13 | rules: 14 | - apiGroups: [""] 15 | resources: ["events"] 16 | verbs: ["get", "list", "watch", "create", "update", "patch"] 17 | 18 | --- 19 | kind: ClusterRoleBinding 20 | apiVersion: rbac.authorization.k8s.io/v1 21 | metadata: 22 | name: csi-nodeplugin-binding 23 | subjects: 24 | - kind: ServiceAccount 25 | name: csi-cinder-node-sa 26 | namespace: kube-system 27 | roleRef: 28 | kind: ClusterRole 29 | name: csi-nodeplugin-role 30 | apiGroup: rbac.authorization.k8s.io 31 | -------------------------------------------------------------------------------- /manifests/cinder-csi-plugin/csi-cinder-driver.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: CSIDriver 3 | metadata: 4 | name: cinder.csi.openstack.org 5 | spec: 6 | attachRequired: true 7 | podInfoOnMount: true 8 | volumeLifecycleModes: 9 | - Persistent 10 | - Ephemeral 11 | -------------------------------------------------------------------------------- /manifests/cinder-csi-plugin/csi-secret-cinderplugin.yaml: -------------------------------------------------------------------------------- 1 | # This YAML file contains secret objects, 2 | # which are necessary to run csi cinder plugin. 3 | 4 | kind: Secret 5 | apiVersion: v1 6 | metadata: 7 | name: cloud-config 8 | namespace: kube-system 9 | data: 10 | cloud.conf: W0dsb2JhbF0KdXNlcm5hbWUgPSBhZG1pbgpwYXNzd29yZCA9IG5vbW9yZXNlY3JldApkb21haW4tbmFtZSA9IGRlZmF1bHQKYXV0aC11cmwgPSBodHRwOi8vMTkyLjE2OC4yMDAuOS9pZGVudGl0eQp0ZW5hbnQtaWQgPSBjYzM0YjExZmY5NWQ0MjMwOTA4MWQwYmQ0NmMwZmY4OQpyZWdpb24gPSBSZWdpb25PbmUK 11 | -------------------------------------------------------------------------------- /manifests/controller-manager/cloud-config: -------------------------------------------------------------------------------- 1 | [Global] 2 | auth-url=http://192.128.1.15:5000/v3 3 | #Tip: You can also use Application Credential ID and Secret in place of username, password, tenant-id, and domain-id. 4 | #application-credential-id= 5 | #application-credential-secret= 6 | username=admin 7 | # user-id= 8 | password=passw0rd 9 | region=RegionOne 10 | tenant-id= 11 | domain-id= 12 | 13 | [LoadBalancer] 14 | subnet-id=9c018814-f2a8-45dd-9679-5400d49b333a 15 | floating-network-id=80c9fc78-a2be-45d5-a85b-f17a6c98df92 16 | -------------------------------------------------------------------------------- /manifests/controller-manager/cloud-controller-manager-role-bindings.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | items: 3 | - apiVersion: rbac.authorization.k8s.io/v1 4 | kind: ClusterRoleBinding 5 | metadata: 6 | name: system:cloud-node-controller 7 | roleRef: 8 | apiGroup: rbac.authorization.k8s.io 9 | kind: ClusterRole 10 | name: system:cloud-node-controller 11 | subjects: 12 | - kind: ServiceAccount 13 | name: cloud-node-controller 14 | namespace: kube-system 15 | - apiVersion: rbac.authorization.k8s.io/v1 16 | kind: ClusterRoleBinding 17 | metadata: 18 | name: system:cloud-controller-manager 19 | roleRef: 20 | apiGroup: rbac.authorization.k8s.io 21 | kind: ClusterRole 22 | name: system:cloud-controller-manager 23 | subjects: 24 | - kind: ServiceAccount 25 | name: cloud-controller-manager 26 | namespace: kube-system 27 | kind: List 28 | metadata: {} -------------------------------------------------------------------------------- /manifests/controller-manager/cloud-controller-manager-roles.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | items: 3 | - apiVersion: rbac.authorization.k8s.io/v1 4 | kind: ClusterRole 5 | metadata: 6 | name: system:cloud-controller-manager 7 | rules: 8 | - apiGroups: 9 | - coordination.k8s.io 10 | resources: 11 | - leases 12 | verbs: 13 | - get 14 | - create 15 | - update 16 | - apiGroups: 17 | - "" 18 | resources: 19 | - events 20 | verbs: 21 | - create 22 | - patch 23 | - update 24 | - apiGroups: 25 | - "" 26 | resources: 27 | - nodes 28 | verbs: 29 | - '*' 30 | - apiGroups: 31 | - "" 32 | resources: 33 | - nodes/status 34 | verbs: 35 | - patch 36 | - apiGroups: 37 | - "" 38 | resources: 39 | - services 40 | verbs: 41 | - list 42 | - patch 43 | - update 44 | - watch 45 | - apiGroups: 46 | - "" 47 | resources: 48 | - services/status 49 | verbs: 50 | - patch 51 | - apiGroups: 52 | - "" 53 | resources: 54 | - serviceaccounts 55 | verbs: 56 | - create 57 | - get 58 | - apiGroups: 59 | - "" 60 | resources: 61 | - serviceaccounts/token 62 | verbs: 63 | - create 64 | - apiGroups: 65 | - "" 66 | resources: 67 | - persistentvolumes 68 | verbs: 69 | - '*' 70 | - apiGroups: 71 | - "" 72 | resources: 73 | - endpoints 74 | verbs: 75 | - create 76 | - get 77 | - list 78 | - watch 79 | - update 80 | - apiGroups: 81 | - "" 82 | resources: 83 | - configmaps 84 | verbs: 85 | - get 86 | - list 87 | - watch 88 | - apiGroups: 89 | - "" 90 | resources: 91 | - secrets 92 | verbs: 93 | - list 94 | - get 95 | - watch 96 | - apiVersion: rbac.authorization.k8s.io/v1 97 | kind: ClusterRole 98 | metadata: 99 | name: system:cloud-node-controller 100 | rules: 101 | - apiGroups: 102 | - "" 103 | resources: 104 | - nodes 105 | verbs: 106 | - '*' 107 | - apiGroups: 108 | - "" 109 | resources: 110 | - nodes/status 111 | verbs: 112 | - patch 113 | - apiGroups: 114 | - "" 115 | resources: 116 | - events 117 | verbs: 118 | - create 119 | - patch 120 | - update 121 | kind: List 122 | metadata: {} 123 | -------------------------------------------------------------------------------- /manifests/controller-manager/kubeadm.conf: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: kubeadm.k8s.io/v1beta2 3 | kind: InitConfiguration 4 | nodeRegistration: 5 | kubeletExtraArgs: 6 | cloud-provider: "external" 7 | 8 | --- 9 | apiVersion: kubeadm.k8s.io/v1beta2 10 | kind: ClusterConfiguration 11 | kubernetesVersion: v1.17.0 12 | networking: 13 | podSubnet: 192.168.0.0/16 14 | controllerManager: 15 | extraArgs: 16 | cloud-provider: "external" 17 | -------------------------------------------------------------------------------- /manifests/controller-manager/openstack-cloud-controller-manager-ds.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: cloud-controller-manager 6 | namespace: kube-system 7 | --- 8 | apiVersion: apps/v1 9 | kind: DaemonSet 10 | metadata: 11 | name: openstack-cloud-controller-manager 12 | namespace: kube-system 13 | labels: 14 | k8s-app: openstack-cloud-controller-manager 15 | spec: 16 | selector: 17 | matchLabels: 18 | k8s-app: openstack-cloud-controller-manager 19 | updateStrategy: 20 | type: RollingUpdate 21 | template: 22 | metadata: 23 | labels: 24 | k8s-app: openstack-cloud-controller-manager 25 | spec: 26 | nodeSelector: 27 | node-role.kubernetes.io/control-plane: "" 28 | securityContext: 29 | runAsUser: 1001 30 | tolerations: 31 | - key: node.cloudprovider.kubernetes.io/uninitialized 32 | value: "true" 33 | effect: NoSchedule 34 | - key: node-role.kubernetes.io/master 35 | effect: NoSchedule 36 | - key: node-role.kubernetes.io/control-plane 37 | effect: NoSchedule 38 | serviceAccountName: cloud-controller-manager 39 | containers: 40 | - name: openstack-cloud-controller-manager 41 | image: registry.k8s.io/provider-os/openstack-cloud-controller-manager:v1.32.0 42 | args: 43 | - /bin/openstack-cloud-controller-manager 44 | - --v=1 45 | - --cluster-name=$(CLUSTER_NAME) 46 | - --cloud-config=$(CLOUD_CONFIG) 47 | - --cloud-provider=openstack 48 | - --use-service-account-credentials=false 49 | - --bind-address=127.0.0.1 50 | volumeMounts: 51 | - mountPath: /etc/kubernetes/pki 52 | name: k8s-certs 53 | readOnly: true 54 | - mountPath: /etc/ssl/certs 55 | name: ca-certs 56 | readOnly: true 57 | - mountPath: /etc/config 58 | name: cloud-config-volume 59 | readOnly: true 60 | resources: 61 | requests: 62 | cpu: 200m 63 | env: 64 | - name: CLOUD_CONFIG 65 | value: /etc/config/cloud.conf 66 | - name: CLUSTER_NAME 67 | value: kubernetes 68 | dnsPolicy: ClusterFirst 69 | hostNetwork: true 70 | volumes: 71 | - hostPath: 72 | path: /etc/kubernetes/pki 73 | type: DirectoryOrCreate 74 | name: k8s-certs 75 | - hostPath: 76 | path: /etc/ssl/certs 77 | type: DirectoryOrCreate 78 | name: ca-certs 79 | - name: cloud-config-volume 80 | secret: 81 | secretName: cloud-config 82 | -------------------------------------------------------------------------------- /manifests/controller-manager/openstack-cloud-controller-manager-pod.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Pod 3 | metadata: 4 | annotations: 5 | scheduler.alpha.kubernetes.io/critical-pod: "" 6 | labels: 7 | component: cloud-controller-manager 8 | tier: control-plane 9 | name: openstack-cloud-controller-manager 10 | namespace: kube-system 11 | spec: 12 | containers: 13 | - name: openstack-cloud-controller-manager 14 | image: registry.k8s.io/provider-os/openstack-cloud-controller-manager:v1.32.0 15 | args: 16 | - /bin/openstack-cloud-controller-manager 17 | - --v=1 18 | - --cluster-name=$(CLUSTER_NAME) 19 | - --cloud-config=$(CLOUD_CONFIG) 20 | - --cloud-provider=openstack 21 | - --use-service-account-credentials=true 22 | - --bind-address=127.0.0.1 23 | volumeMounts: 24 | - mountPath: /etc/kubernetes/pki 25 | name: k8s-certs 26 | readOnly: true 27 | - mountPath: /etc/ssl/certs 28 | name: ca-certs 29 | readOnly: true 30 | - mountPath: /etc/config 31 | name: cloud-config-volume 32 | readOnly: true 33 | resources: 34 | requests: 35 | cpu: 200m 36 | env: 37 | - name: CLOUD_CONFIG 38 | value: /etc/config/cloud.conf 39 | - name: CLUSTER_NAME 40 | value: kubernetes 41 | dnsPolicy: ClusterFirst 42 | hostNetwork: true 43 | securityContext: 44 | runAsUser: 1001 45 | volumes: 46 | - hostPath: 47 | path: /etc/kubernetes/pki 48 | type: DirectoryOrCreate 49 | name: k8s-certs 50 | - hostPath: 51 | path: /etc/ssl/certs 52 | type: DirectoryOrCreate 53 | name: ca-certs 54 | - name: cloud-config-volume 55 | secret: 56 | secretName: cloud-config 57 | -------------------------------------------------------------------------------- /manifests/manila-csi-plugin/csi-nodeplugin-rbac.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: openstack-manila-csi-nodeplugin 5 | labels: 6 | app: openstack-manila-csi 7 | component: nodeplugin 8 | --- 9 | kind: ClusterRole 10 | apiVersion: rbac.authorization.k8s.io/v1 11 | metadata: 12 | name: openstack-manila-csi-nodeplugin 13 | labels: 14 | app: openstack-manila-csi 15 | component: nodeplugin 16 | aggregationRule: 17 | clusterRoleSelectors: 18 | - matchLabels: 19 | rbac.manila.csi.openstack.org/aggregate-to-openstack-manila-csi-nodeplugin: "true" 20 | rules: [] 21 | --- 22 | kind: ClusterRole 23 | apiVersion: rbac.authorization.k8s.io/v1 24 | metadata: 25 | name: openstack-manila-csi-nodeplugin-rules 26 | labels: 27 | app: openstack-manila-csi 28 | component: nodeplugin 29 | rbac.manila.csi.openstack.org/aggregate-to-openstack-manila-csi-nodeplugin: "true" 30 | rules: 31 | - apiGroups: [""] 32 | resources: ["configmaps"] 33 | verbs: ["get", "list"] 34 | - apiGroups: [""] 35 | resources: ["nodes"] 36 | verbs: ["get", "list", "update"] 37 | - apiGroups: [""] 38 | resources: ["namespaces"] 39 | verbs: ["get", "list"] 40 | - apiGroups: [""] 41 | resources: ["persistentvolumes"] 42 | verbs: ["get", "list", "watch", "update"] 43 | --- 44 | kind: ClusterRoleBinding 45 | apiVersion: rbac.authorization.k8s.io/v1 46 | metadata: 47 | name: openstack-manila-csi-nodeplugin 48 | labels: 49 | app: openstack-manila-csi 50 | component: nodeplugin 51 | subjects: 52 | - kind: ServiceAccount 53 | name: openstack-manila-csi-nodeplugin 54 | namespace: default 55 | roleRef: 56 | kind: ClusterRole 57 | name: openstack-manila-csi-nodeplugin 58 | apiGroup: rbac.authorization.k8s.io 59 | -------------------------------------------------------------------------------- /manifests/manila-csi-plugin/csidriver.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: storage.k8s.io/v1 2 | kind: CSIDriver 3 | metadata: 4 | name: manila.csi.openstack.org 5 | spec: 6 | attachRequired: false 7 | podInfoOnMount: false 8 | 9 | -------------------------------------------------------------------------------- /pkg/autohealing/OWNERS: -------------------------------------------------------------------------------- 1 | approvers: 2 | - lingxiankong 3 | - openstacker 4 | reviewers: 5 | - lingxiankong 6 | - openstacker 7 | -------------------------------------------------------------------------------- /pkg/autohealing/cloudprovider/cloudprovider.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 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 cloudprovider 18 | 19 | import ( 20 | "context" 21 | 22 | "k8s.io/client-go/kubernetes" 23 | log "k8s.io/klog/v2" 24 | 25 | "k8s.io/cloud-provider-openstack/pkg/autohealing/config" 26 | "k8s.io/cloud-provider-openstack/pkg/autohealing/healthcheck" 27 | ) 28 | 29 | var ( 30 | providers = make(map[string]RegisterFunc) 31 | ) 32 | 33 | // CloudProvider is an abstract, pluggable interface for cloud providers. 34 | type CloudProvider interface { 35 | // GetName returns the cloud provider name. 36 | GetName() string 37 | 38 | // Update cluster health status. 39 | UpdateHealthStatus(context.Context, []healthcheck.NodeInfo, []healthcheck.NodeInfo) error 40 | 41 | // Repair triggers the node repair process in the cloud. 42 | Repair(context.Context, []healthcheck.NodeInfo) error 43 | 44 | // Enabled decides if the repair should be triggered. 45 | // It's recommended that the `Enabled()` function of the cloud provider doesn't allow to re-trigger when the repair 46 | // is in place, e.g. before the repair process is finished, `Enabled()` should return false so that we won't 47 | // re-trigger the repair process in the subsequent checks. 48 | // This function also provides the cluster admin the capability to disable the cluster auto healing on the fly. 49 | Enabled(context.Context) bool 50 | } 51 | 52 | type RegisterFunc func(config config.Config, client kubernetes.Interface) (CloudProvider, error) 53 | 54 | // RegisterCloudProvider registers a cloudprovider.Factory by name. This 55 | // is expected to happen during app startup. 56 | func RegisterCloudProvider(name string, register RegisterFunc) { 57 | if _, found := providers[name]; found { 58 | log.Fatalf("Cloud provider %s is already registered.", name) 59 | } 60 | 61 | log.Infof("Registered cloud provider %s.", name) 62 | providers[name] = register 63 | } 64 | 65 | // GetCloudProvider creates an instance of the named cloud provider 66 | func GetCloudProvider(name string, config config.Config, client kubernetes.Interface) (CloudProvider, error) { 67 | f, found := providers[name] 68 | if !found { 69 | return nil, nil 70 | } 71 | return f(config, client) 72 | } 73 | -------------------------------------------------------------------------------- /pkg/autohealing/utils/utils.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 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 utils 18 | 19 | // Contains searches if a string list contains the given string or not. 20 | func Contains(list []string, strToSearch string) bool { 21 | for _, item := range list { 22 | if item == strToSearch { 23 | return true 24 | } 25 | } 26 | return false 27 | } 28 | 29 | // ContainsInt searches if a int list contains the given int or not. 30 | func ContainsInt(list []int, toSearch int) bool { 31 | for _, item := range list { 32 | if item == toSearch { 33 | return true 34 | } 35 | } 36 | return false 37 | } 38 | -------------------------------------------------------------------------------- /pkg/csi/cinder/driver_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 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 cinder 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/container-storage-interface/spec/lib/go/csi" 23 | "github.com/stretchr/testify/assert" 24 | ) 25 | 26 | var ( 27 | vendorVersion = "2.0.0" 28 | ) 29 | 30 | func NewFakeDriver() *Driver { 31 | 32 | driver := NewDriver(&DriverOpts{Endpoint: FakeEndpoint, ClusterID: FakeCluster}) 33 | 34 | return driver 35 | } 36 | 37 | func TestValidateControllerServiceRequest(t *testing.T) { 38 | d := NewFakeDriver() 39 | 40 | // Valid requests which require no capabilities 41 | err := d.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_UNKNOWN) 42 | assert.NoError(t, err) 43 | 44 | // Test controller service publish/unpublish is supported 45 | err = d.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_PUBLISH_UNPUBLISH_VOLUME) 46 | assert.NoError(t, err) 47 | 48 | // Test controller service create/delete is supported 49 | err = d.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_CREATE_DELETE_VOLUME) 50 | assert.NoError(t, err) 51 | 52 | // Test controller service list volumes is supported 53 | err = d.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_LIST_VOLUMES) 54 | assert.NoError(t, err) 55 | 56 | // Test controller service create/delete snapshot is supported 57 | err = d.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT) 58 | assert.NoError(t, err) 59 | 60 | // Test controller service list snapshot is supported 61 | err = d.ValidateControllerServiceRequest(csi.ControllerServiceCapability_RPC_LIST_SNAPSHOTS) 62 | assert.NoError(t, err) 63 | } 64 | -------------------------------------------------------------------------------- /pkg/csi/cinder/etc/cloud.conf: -------------------------------------------------------------------------------- 1 | [Global] 2 | username=user 3 | password=pass 4 | auth-url=https:///identity/v3 5 | tenant-id=c869168a828847f39f7f06edd7305637 6 | domain-id=2a73b8f597c04551a0fdc8e95544be8a 7 | -------------------------------------------------------------------------------- /pkg/csi/cinder/identityserver_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 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 cinder 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | "testing" 23 | 24 | "github.com/container-storage-interface/spec/lib/go/csi" 25 | "github.com/stretchr/testify/assert" 26 | ) 27 | 28 | func TestGetPluginInfo(t *testing.T) { 29 | d := NewDriver(&DriverOpts{Endpoint: FakeEndpoint, ClusterID: FakeCluster}) 30 | 31 | ids := NewIdentityServer(d) 32 | 33 | req := csi.GetPluginInfoRequest{} 34 | resp, err := ids.GetPluginInfo(context.Background(), &req) 35 | assert.NoError(t, err) 36 | assert.Equal(t, resp.GetName(), driverName) 37 | 38 | fqVersion := fmt.Sprintf("%s@", vendorVersion) 39 | assert.Equal(t, resp.GetVendorVersion(), fqVersion) 40 | } 41 | -------------------------------------------------------------------------------- /pkg/csi/cinder/openstack/fixtures/clouds.yaml: -------------------------------------------------------------------------------- 1 | clouds: 2 | openstack: 3 | auth: 4 | auth_url: "https://169.254.169.254/identity/v3" 5 | username: "user" 6 | password: "pass" 7 | project_id: "c869168a828847f39f7f06edd7305637" 8 | domain_id: "2a73b8f597c04551a0fdc8e95544be8a" 9 | region_name: "RegionOne" 10 | cacert: "fake-ca.crt" 11 | interface: "public" 12 | identity_api_version: 3 13 | openstack_cloud2: 14 | auth: 15 | auth_url: "https://169.254.169.254/identity/v3" 16 | username: "user" 17 | password: "pass" 18 | project_id: "c869168a828847f39f7f06edd7305637" 19 | domain_id: "2a73b8f597c04551a0fdc8e95544be8a" 20 | region_name: "RegionTwo" 21 | cacert: "fake-ca.crt" 22 | interface: "public" 23 | identity_api_version: 3 24 | openstack_cloud3: 25 | auth: 26 | auth_url: "https://961.452.961.452/identity/v3" 27 | username: "user_cloud3" 28 | password: "pass_cloud3" 29 | project_id: "66c684738f74161ad8b41cb56224b311" 30 | domain_id: "032da590a2714eda744bd321b5356c7e" 31 | region_name: "AnotherRegion" 32 | cacert: "fake-ca_cloud3.crt" 33 | interface: "public" 34 | identity_api_version: 3 35 | -------------------------------------------------------------------------------- /pkg/csi/cinder/openstack/openstack_instances.go: -------------------------------------------------------------------------------- 1 | package openstack 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/gophercloud/gophercloud/v2/openstack/compute/v2/servers" 7 | "k8s.io/cloud-provider-openstack/pkg/metrics" 8 | ) 9 | 10 | // GetInstanceByID returns server with specified instanceID 11 | func (os *OpenStack) GetInstanceByID(ctx context.Context, instanceID string) (*servers.Server, error) { 12 | mc := metrics.NewMetricContext("server", "get") 13 | server, err := servers.Get(ctx, os.compute, instanceID).Extract() 14 | if mc.ObserveRequest(err) != nil { 15 | return nil, err 16 | } 17 | return server, nil 18 | } 19 | -------------------------------------------------------------------------------- /pkg/csi/cinder/server_test.go: -------------------------------------------------------------------------------- 1 | package cinder 2 | 3 | import ( 4 | "net" 5 | "testing" 6 | "time" 7 | 8 | "github.com/stretchr/testify/require" 9 | "go.uber.org/goleak" 10 | ) 11 | 12 | func TestServerReleaseWaitAfterStopCalling(t *testing.T) { 13 | defer goleak.VerifyNone(t) 14 | 15 | var ( 16 | server = NewNonBlockingGRPCServer() 17 | ch = make(chan struct{}) 18 | ) 19 | server.Start(FakeEndpoint, nil, nil, nil) 20 | 21 | go func() { 22 | server.Wait() 23 | }() 24 | 25 | _, address, err := ParseEndpoint(FakeEndpoint) 26 | require.NoError(t, err) 27 | 28 | // this loop is needed to wait for the server start up 29 | timer := time.NewTimer(2 * time.Second) 30 | defer timer.Stop() 31 | for { 32 | select { 33 | case <-timer.C: 34 | require.Fail(t, "server does not started") 35 | default: 36 | } 37 | 38 | conn, err := net.DialTimeout("tcp", address, 200*time.Millisecond) 39 | if err != nil { 40 | continue 41 | } 42 | if conn == nil { 43 | continue 44 | } 45 | _ = conn.Close() 46 | break 47 | } 48 | 49 | go func() { 50 | server.Stop() 51 | close(ch) 52 | }() 53 | 54 | <-ch 55 | } 56 | -------------------------------------------------------------------------------- /pkg/csi/manila/OWNERS: -------------------------------------------------------------------------------- 1 | approvers: 2 | - gman0 3 | - gouthampacha 4 | - tombarron 5 | reviewers: 6 | - gman0 7 | - gouthampacha 8 | - tombarron 9 | - Fedosin 10 | - tsmetana 11 | -------------------------------------------------------------------------------- /pkg/csi/manila/adapters.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 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 manila 18 | 19 | import ( 20 | "strings" 21 | 22 | "k8s.io/cloud-provider-openstack/pkg/csi/manila/shareadapters" 23 | "k8s.io/klog/v2" 24 | ) 25 | 26 | func getShareAdapter(proto string) shareadapters.ShareAdapter { 27 | switch strings.ToUpper(proto) { 28 | case "CEPHFS": 29 | return &shareadapters.Cephfs{} 30 | case "NFS": 31 | return &shareadapters.NFS{} 32 | default: 33 | klog.Fatalf("unknown share adapter %s", proto) 34 | } 35 | 36 | return nil 37 | } 38 | -------------------------------------------------------------------------------- /pkg/csi/manila/csiclient.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 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 manila 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/container-storage-interface/spec/lib/go/csi" 23 | "k8s.io/cloud-provider-openstack/pkg/csi/manila/csiclient" 24 | ) 25 | 26 | type csiNodeCapabilitySet map[csi.NodeServiceCapability_RPC_Type]bool 27 | 28 | func csiNodeGetCapabilities(ctx context.Context, nodeClient csiclient.Node) (csiNodeCapabilitySet, error) { 29 | rsp, err := nodeClient.GetCapabilities(ctx) 30 | if err != nil { 31 | return nil, err 32 | } 33 | 34 | caps := csiNodeCapabilitySet{} 35 | for _, cap := range rsp.GetCapabilities() { 36 | if cap == nil { 37 | continue 38 | } 39 | rpc := cap.GetRpc() 40 | if rpc == nil { 41 | continue 42 | } 43 | t := rpc.GetType() 44 | caps[t] = true 45 | } 46 | 47 | return caps, nil 48 | } 49 | -------------------------------------------------------------------------------- /pkg/csi/manila/csiclient/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 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 csiclient 18 | 19 | import ( 20 | "context" 21 | "time" 22 | 23 | "github.com/container-storage-interface/spec/lib/go/csi" 24 | "github.com/kubernetes-csi/csi-lib-utils/rpc" 25 | "google.golang.org/grpc" 26 | ) 27 | 28 | var ( 29 | _ Node = &NodeSvcClient{} 30 | _ Identity = &IdentitySvcClient{} 31 | ) 32 | 33 | type NodeSvcClient struct { 34 | cl csi.NodeClient 35 | } 36 | 37 | func (c *NodeSvcClient) GetCapabilities(ctx context.Context) (*csi.NodeGetCapabilitiesResponse, error) { 38 | return c.cl.NodeGetCapabilities(ctx, &csi.NodeGetCapabilitiesRequest{}) 39 | } 40 | 41 | func (c *NodeSvcClient) GetVolumeStats(ctx context.Context, req *csi.NodeGetVolumeStatsRequest) (*csi.NodeGetVolumeStatsResponse, error) { 42 | return c.cl.NodeGetVolumeStats(ctx, req) 43 | } 44 | 45 | func (c *NodeSvcClient) StageVolume(ctx context.Context, req *csi.NodeStageVolumeRequest) (*csi.NodeStageVolumeResponse, error) { 46 | return c.cl.NodeStageVolume(ctx, req) 47 | } 48 | 49 | func (c *NodeSvcClient) UnstageVolume(ctx context.Context, req *csi.NodeUnstageVolumeRequest) (*csi.NodeUnstageVolumeResponse, error) { 50 | return c.cl.NodeUnstageVolume(ctx, req) 51 | } 52 | 53 | func (c *NodeSvcClient) PublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) { 54 | return c.cl.NodePublishVolume(ctx, req) 55 | } 56 | 57 | func (c *NodeSvcClient) UnpublishVolume(ctx context.Context, req *csi.NodeUnpublishVolumeRequest) (*csi.NodeUnpublishVolumeResponse, error) { 58 | return c.cl.NodeUnpublishVolume(ctx, req) 59 | } 60 | 61 | type IdentitySvcClient struct { 62 | cl csi.IdentityClient 63 | } 64 | 65 | func (c IdentitySvcClient) Probe(ctx context.Context, req *csi.ProbeRequest) (*csi.ProbeResponse, error) { 66 | return c.cl.Probe(ctx, req) 67 | } 68 | 69 | func (c IdentitySvcClient) ProbeForever(ctx context.Context, conn *grpc.ClientConn, singleProbeTimeout time.Duration) error { 70 | return rpc.ProbeForever(ctx, conn, singleProbeTimeout) 71 | } 72 | 73 | func (c IdentitySvcClient) GetPluginInfo(ctx context.Context) (*csi.GetPluginInfoResponse, error) { 74 | return c.cl.GetPluginInfo(ctx, &csi.GetPluginInfoRequest{}) 75 | } 76 | -------------------------------------------------------------------------------- /pkg/csi/manila/csiclient/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 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 csiclient 18 | 19 | import ( 20 | "context" 21 | "time" 22 | 23 | "github.com/container-storage-interface/spec/lib/go/csi" 24 | "google.golang.org/grpc" 25 | ) 26 | 27 | type Node interface { 28 | GetCapabilities(ctx context.Context) (*csi.NodeGetCapabilitiesResponse, error) 29 | GetVolumeStats(ctx context.Context, req *csi.NodeGetVolumeStatsRequest) (*csi.NodeGetVolumeStatsResponse, error) 30 | 31 | StageVolume(ctx context.Context, req *csi.NodeStageVolumeRequest) (*csi.NodeStageVolumeResponse, error) 32 | UnstageVolume(ctx context.Context, req *csi.NodeUnstageVolumeRequest) (*csi.NodeUnstageVolumeResponse, error) 33 | 34 | PublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error) 35 | UnpublishVolume(ctx context.Context, req *csi.NodeUnpublishVolumeRequest) (*csi.NodeUnpublishVolumeResponse, error) 36 | } 37 | 38 | type Identity interface { 39 | GetPluginInfo(ctx context.Context) (*csi.GetPluginInfoResponse, error) 40 | Probe(ctx context.Context, req *csi.ProbeRequest) (*csi.ProbeResponse, error) 41 | ProbeForever(ctx context.Context, conn *grpc.ClientConn, singleProbeTimeout time.Duration) error 42 | } 43 | 44 | type Builder interface { 45 | NewConnection(endpoint string) (*grpc.ClientConn, error) 46 | NewConnectionWithContext(ctx context.Context, endpoint string) (*grpc.ClientConn, error) 47 | 48 | NewNodeServiceClient(conn *grpc.ClientConn) Node 49 | NewIdentityServiceClient(conn *grpc.ClientConn) Identity 50 | } 51 | -------------------------------------------------------------------------------- /pkg/csi/manila/options/openstackoptions.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 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 options 18 | 19 | import ( 20 | "k8s.io/cloud-provider-openstack/pkg/client" 21 | "k8s.io/cloud-provider-openstack/pkg/csi/manila/validator" 22 | ) 23 | 24 | var ( 25 | osOptionsValidator = validator.New(&client.AuthOpts{}) 26 | ) 27 | 28 | func NewOpenstackOptions(data map[string]string) (*client.AuthOpts, error) { 29 | opts := &client.AuthOpts{} 30 | if err := osOptionsValidator.Populate(data, opts); err != nil { 31 | return nil, err 32 | } 33 | 34 | return opts, nil 35 | } 36 | -------------------------------------------------------------------------------- /pkg/csi/manila/runtimeconfig/nfsconfig.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 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 runtimeconfig 18 | 19 | type NfsConfig struct { 20 | // When mounting an NFS share, select an export location with matching IP address. 21 | // No match between this address and at least a single export location for this share 22 | // will result in an error. 23 | // Expects a CIDR-formatted address. If prefix is not provided, 24 | // /32 or /128 prefix is assumed for IPv4 and IPv6 respectively. 25 | MatchExportLocationAddress string `json:"matchExportLocationAddress,omitempty"` 26 | } 27 | -------------------------------------------------------------------------------- /pkg/csi/manila/runtimeconfig/runtimeconfig.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 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 runtimeconfig 18 | 19 | import ( 20 | "encoding/json" 21 | "os" 22 | ) 23 | 24 | var ( 25 | // Path to the runtime config file 26 | RuntimeConfigFilename string 27 | ) 28 | 29 | type RuntimeConfig struct { 30 | Nfs *NfsConfig `json:"nfs,omitempty"` 31 | } 32 | 33 | func Get() (*RuntimeConfig, error) { 34 | // File contents are deliberately not cached 35 | // as they may change over time. 36 | data, err := os.ReadFile(RuntimeConfigFilename) 37 | if err != nil { 38 | if os.IsNotExist(err) { 39 | return nil, nil 40 | } 41 | 42 | return nil, err 43 | } 44 | 45 | var cfg *RuntimeConfig 46 | if err = json.Unmarshal(data, &cfg); err != nil { 47 | return nil, err 48 | } 49 | 50 | return cfg, nil 51 | } 52 | -------------------------------------------------------------------------------- /pkg/csi/manila/shareadapters/shareadapter.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 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 shareadapters 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/gophercloud/gophercloud/v2/openstack/sharedfilesystems/v2/shares" 23 | "k8s.io/cloud-provider-openstack/pkg/csi/manila/manilaclient" 24 | "k8s.io/cloud-provider-openstack/pkg/csi/manila/options" 25 | ) 26 | 27 | type GrantAccessArgs struct { 28 | ManilaClient manilaclient.Interface 29 | Share *shares.Share 30 | Options *options.ControllerVolumeContext 31 | } 32 | 33 | type VolumeContextArgs struct { 34 | // Share adapters are responsible for choosing 35 | // an export location when building a volume context. 36 | Locations []shares.ExportLocation 37 | 38 | Options *options.NodeVolumeContext 39 | } 40 | 41 | type SecretArgs struct { 42 | AccessRight *shares.AccessRight 43 | } 44 | 45 | type ShareAdapter interface { 46 | // GetOrGrantAccess first tries to retrieve an access right for args.Share. 47 | // An access right is created for the share in case it doesn't exist yet. 48 | // Returns an existing or new access right for args.Share. 49 | GetOrGrantAccess(ctx context.Context, args *GrantAccessArgs) (accessRight *shares.AccessRight, err error) 50 | 51 | // BuildVolumeContext builds a volume context map that's passed to NodeStageVolumeRequest and NodePublishVolumeRequest 52 | BuildVolumeContext(args *VolumeContextArgs) (volumeContext map[string]string, err error) 53 | 54 | // Builds secret map for NodeStageVolumeRequest 55 | BuildNodeStageSecret(args *SecretArgs) (secret map[string]string, err error) 56 | 57 | // Builds secret map for NodePublishVolumeRequest 58 | BuildNodePublishSecret(args *SecretArgs) (secret map[string]string, err error) 59 | } 60 | -------------------------------------------------------------------------------- /pkg/csi/manila/shareadapters/util.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 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 shareadapters 18 | 19 | import ( 20 | "fmt" 21 | "strings" 22 | ) 23 | 24 | func splitExportLocationPath(exportLocationPath string) (address, location string, err error) { 25 | delimPos := strings.LastIndexByte(exportLocationPath, ':') 26 | if delimPos <= 0 { 27 | err = fmt.Errorf("failed to parse address and location from export location '%s'", exportLocationPath) 28 | return 29 | } 30 | 31 | address = exportLocationPath[:delimPos] 32 | location = exportLocationPath[delimPos+1:] 33 | 34 | return 35 | } 36 | -------------------------------------------------------------------------------- /pkg/csi/manila/util/exportlocation.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | 14 | package util 15 | 16 | import ( 17 | "errors" 18 | "strings" 19 | 20 | "github.com/gophercloud/gophercloud/v2/openstack/sharedfilesystems/v2/shares" 21 | ) 22 | 23 | // Predicate type for filtering out export locations. 24 | // It's supplied with the index into the export location slice that's being scanned. 25 | // Should return (true, nil) when search conditions are satisfied, 26 | // and (false, nil) when they are not. 27 | type ExportLocationPredicate func(index int) (match bool, err error) 28 | 29 | // Predicate matching any export location 30 | func AnyExportLocation(int) (bool, error) { return true, nil } 31 | 32 | // Searches for an export location. 33 | // Returns index of an export location from the `locs` slice that satisfies following rules: 34 | // 1. Location is not admin-only and is not empty 35 | // 2. Location satisfies ExportLocationPredicate 36 | // Search is biased: 37 | // 1. Location.Preferred == true is preferred over Location.Preferred == false 38 | // 2. Locations with lower index are preferred over those with higher index 39 | func FindExportLocation(locs []shares.ExportLocation, pred ExportLocationPredicate) (index int, err error) { 40 | const invalidIdx = -1 41 | firstMatchNotPreferred := invalidIdx 42 | 43 | for i := range locs { 44 | if locs[i].IsAdminOnly || strings.TrimSpace(locs[i].Path) == "" { 45 | continue 46 | } 47 | 48 | if hasMatch, err := pred(i); err != nil { 49 | return i, err 50 | } else if hasMatch { 51 | if locs[i].Preferred { 52 | // This export location is a match and it is Preferred. 53 | // Can't get better than that! 54 | return i, nil 55 | } 56 | 57 | if firstMatchNotPreferred == invalidIdx { 58 | firstMatchNotPreferred = i 59 | } 60 | } 61 | } 62 | 63 | if firstMatchNotPreferred == invalidIdx { 64 | err = errors.New("no match, or no suitable non-admin export locations available") 65 | } 66 | 67 | return firstMatchNotPreferred, err 68 | } 69 | -------------------------------------------------------------------------------- /pkg/csi/manila/validator/identity.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 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 validator 18 | 19 | import ( 20 | "fmt" 21 | "reflect" 22 | ) 23 | 24 | const ( 25 | nameFieldTag = "name" 26 | ) 27 | 28 | type ( 29 | fieldIndex int 30 | fieldName string 31 | structName string 32 | 33 | nameIndexMap map[fieldName]fieldIndex 34 | indexNameMap map[fieldIndex]fieldName 35 | ) 36 | 37 | func buildNameIdxMap(t reflect.Type) (nameIndexMap, indexNameMap) { 38 | nameIdxMap := make(nameIndexMap) 39 | idxNameMap := make(indexNameMap) 40 | 41 | for i := 0; i < t.NumField(); i++ { 42 | ft := t.Field(i) 43 | tags := ft.Tag 44 | 45 | name, ok := tags.Lookup(nameFieldTag) 46 | if !ok { 47 | panic(fmt.Sprintf("missing name tag for field %s in struct %s", ft.Name, t.Name())) 48 | } 49 | 50 | nameIdxMap[fieldName(name)] = fieldIndex(i) 51 | idxNameMap[fieldIndex(i)] = fieldName(name) 52 | } 53 | 54 | return nameIdxMap, idxNameMap 55 | } 56 | -------------------------------------------------------------------------------- /pkg/csi/manila/validator/matchexpr.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 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 validator 18 | 19 | import ( 20 | "fmt" 21 | "reflect" 22 | "regexp" 23 | ) 24 | 25 | const ( 26 | matchTag = "matches" 27 | ) 28 | 29 | type ( 30 | matchRegexpMap map[fieldIndex]*regexp.Regexp 31 | ) 32 | 33 | func buildMatchRegexMap(t reflect.Type) matchRegexpMap { 34 | m := make(matchRegexpMap) 35 | 36 | for i := 0; i < t.NumField(); i++ { 37 | if pattern, ok := t.Field(i).Tag.Lookup(matchTag); ok { 38 | m[fieldIndex(i)] = regexp.MustCompile(pattern) 39 | } 40 | } 41 | 42 | return m 43 | } 44 | 45 | func valueSatisfiesPattern(value string, rx *regexp.Regexp, fName fieldName) error { 46 | if !rx.MatchString(value) { 47 | return fmt.Errorf("parameter '%s' does not match pattern %s", fName, rx.String()) 48 | } 49 | 50 | return nil 51 | } 52 | -------------------------------------------------------------------------------- /pkg/csi/manila/validator/precludesexpr.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 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 validator 18 | 19 | import ( 20 | "fmt" 21 | "reflect" 22 | "strings" 23 | ) 24 | 25 | const ( 26 | precludesTag = "precludes" 27 | 28 | preclsDelim = "," 29 | ) 30 | 31 | type ( 32 | precludesExpression []fieldIndex 33 | preclusionsMap map[fieldIndex]precludesExpression 34 | ) 35 | 36 | func parsePreclsExpr(precls string, nameIdxMap nameIndexMap, s structName, f fieldName) precludesExpression { 37 | ps := strings.Split(precls, preclsDelim) 38 | preclsExpr := make(precludesExpression, len(ps)) 39 | 40 | for i := range ps { 41 | fIdx, ok := nameIdxMap[fieldName(ps[i])] 42 | if !ok { 43 | panic(fmt.Sprintf("invalid precludes expression in '%s.%s': no field named '%s' found", 44 | s, f, fieldName(ps[i]))) 45 | } 46 | 47 | preclsExpr[i] = fIdx 48 | } 49 | 50 | return preclsExpr 51 | } 52 | 53 | func buildPreclusionsMap(t reflect.Type, idxNameMap indexNameMap, nameIdxMap nameIndexMap) preclusionsMap { 54 | m := make(preclusionsMap) 55 | 56 | for i := 0; i < t.NumField(); i++ { 57 | ft := t.Field(i) 58 | 59 | precls, ok := ft.Tag.Lookup(precludesTag) 60 | if !ok { 61 | continue 62 | } 63 | 64 | fIdx := fieldIndex(i) 65 | m[fIdx] = parsePreclsExpr(precls, nameIdxMap, structName(t.Name()), idxNameMap[fIdx]) 66 | } 67 | 68 | return m 69 | } 70 | 71 | func preclusionsSatisfied(fIdx fieldIndex, v reflect.Value, precls precludesExpression, idxNameMap indexNameMap) error { 72 | for i := range precls { 73 | if v.Field(int(precls[i])).String() != "" { 74 | return fmt.Errorf("parameter '%s' forbids '%s' to be set", idxNameMap[fIdx], idxNameMap[precls[i]]) 75 | } 76 | } 77 | 78 | return nil 79 | } 80 | -------------------------------------------------------------------------------- /pkg/csi/manila/validator/util.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 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 validator 18 | 19 | import "strings" 20 | 21 | func splitOne(value string, delim byte) (left string, right string, ok bool) { 22 | delimIdx := strings.IndexByte(value, delim) 23 | if delimIdx <= 0 { 24 | return "", "", false 25 | } 26 | 27 | return value[:delimIdx], value[delimIdx+1:], true 28 | } 29 | -------------------------------------------------------------------------------- /pkg/identity/keystone/authenticator_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | Unless required by applicable law or agreed to in writing, software 8 | distributed under the License is distributed on an "AS IS" BASIS, 9 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 10 | See the License for the specific language governing permissions and 11 | limitations under the License. 12 | */ 13 | 14 | package keystone 15 | 16 | import ( 17 | "context" 18 | "testing" 19 | 20 | th "github.com/gophercloud/gophercloud/v2/testhelper" 21 | "k8s.io/apiserver/pkg/authentication/user" 22 | ) 23 | 24 | func TestAuthenticateToken(t *testing.T) { 25 | keystone := &MockIKeystone{} 26 | keystone. 27 | On("GetTokenInfo", "token"). 28 | Return(&tokenInfo{ 29 | userName: "user-name", 30 | userID: "user-id", 31 | projectID: "project-id", 32 | projectName: "project-name", 33 | domainName: "domain-name", 34 | domainID: "domain-id", 35 | roles: []string{"role1", "role2"}, 36 | }, nil). 37 | Once() 38 | keystone. 39 | On("GetGroups", "token", "user-id"). 40 | Return([]string{"group1", "group2"}, nil). 41 | Once() 42 | 43 | a := &Authenticator{ 44 | keystoner: keystone, 45 | } 46 | userInfo, allowed, err := a.AuthenticateToken(context.TODO(), "token") 47 | 48 | th.AssertNoErr(t, err) 49 | th.AssertEquals(t, true, allowed) 50 | 51 | expectedUserInfo := &user.DefaultInfo{ 52 | Name: "user-name", 53 | UID: "user-id", 54 | Groups: []string{"group1", "group2"}, 55 | Extra: map[string][]string{ 56 | Roles: {"role1", "role2"}, 57 | ProjectID: {"project-id"}, 58 | ProjectName: {"project-name"}, 59 | DomainID: {"domain-id"}, 60 | DomainName: {"domain-name"}, 61 | }, 62 | } 63 | th.AssertDeepEquals(t, expectedUserInfo, userInfo) 64 | 65 | keystone.AssertExpectations(t) 66 | } 67 | -------------------------------------------------------------------------------- /pkg/identity/keystone/authorizer_test_policy_version2.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "users": { 4 | "roles": ["developer"], 5 | "projects": ["demo"] 6 | }, 7 | "resource_permissions": { 8 | "!kube-system/!['namespaces', 'clusterrolebindings', 'clusterroles', 'podsecuritypolicies', 'rolebindings', 'roles', 'podSecurityPolicies']": ["*"], 9 | "!kube-system/['namespaces', 'clusterrolebindings', 'clusterroles', 'podsecuritypolicies', 'rolebindings', 'roles', 'podSecurityPolicies']": ["get", "list"], 10 | "*/['namespaces', 'clusterrolebindings', 'clusterroles', 'podsecuritypolicies', 'podSecurityPolicies']": ["get", "list"] 11 | } 12 | }, 13 | { 14 | "users": { 15 | "roles": ["viewer"], 16 | "projects": ["demo", "cd08a539b7c845ddb92c5d08752101d1"] 17 | }, 18 | "resource_permissions": { 19 | "default/['*']": ["get", "list"] 20 | } 21 | }, 22 | { 23 | "users": { 24 | "roles": ["clusteradmin"], 25 | "projects": ["demo"] 26 | }, 27 | "resource_permissions": { 28 | "*/*": ["*"] 29 | }, 30 | "nonresource_permissions": { 31 | "/healthz": ["get", "post"] 32 | } 33 | }, 34 | { 35 | "users": { 36 | "roles": ["testuser"], 37 | "projects": ["demo"] 38 | }, 39 | "resource_permissions": { 40 | "*/['namespaces', 'clusterroles']": ["get", "list"], 41 | "default/['pods', 'deployments']": ["get", "list"] 42 | } 43 | } 44 | ] 45 | -------------------------------------------------------------------------------- /pkg/identity/keystone/keystone_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 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 keystone 18 | 19 | import ( 20 | "reflect" 21 | "testing" 22 | 23 | "github.com/spf13/pflag" 24 | ) 25 | 26 | func TestUserAgentFlag(t *testing.T) { 27 | tests := []struct { 28 | name string 29 | shouldParse bool 30 | flags []string 31 | expected []string 32 | }{ 33 | {"no_flag", true, []string{}, nil}, 34 | {"one_flag", true, []string{"--user-agent=cluster/abc-123"}, []string{"cluster/abc-123"}}, 35 | {"multiple_flags", true, []string{"--user-agent=a/b", "--user-agent=c/d"}, []string{"a/b", "c/d"}}, 36 | {"flag_with_space", true, []string{"--user-agent=a b"}, []string{"a b"}}, 37 | {"flag_split_with_space", true, []string{"--user-agent=a", "b"}, []string{"a"}}, 38 | {"empty_flag", false, []string{"--user-agent"}, nil}, 39 | } 40 | 41 | for _, testCase := range tests { 42 | userAgentData = []string{} 43 | 44 | t.Run(testCase.name, func(t *testing.T) { 45 | fs := pflag.NewFlagSet("test", pflag.ContinueOnError) 46 | AddExtraFlags(fs) 47 | 48 | err := fs.Parse(testCase.flags) 49 | 50 | if testCase.shouldParse && err != nil { 51 | t.Errorf("Flags failed to parse") 52 | } else if !testCase.shouldParse && err == nil { 53 | t.Errorf("Flags should not have parsed") 54 | } else if testCase.shouldParse { 55 | if !reflect.DeepEqual(userAgentData, testCase.expected) { 56 | t.Errorf("userAgentData %#v did not match expected value %#v", userAgentData, testCase.expected) 57 | } 58 | } 59 | }) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /pkg/identity/keystone/mock_IKeystone.go: -------------------------------------------------------------------------------- 1 | // Code generated by mockery v1.0.0. DO NOT EDIT. 2 | 3 | package keystone 4 | 5 | import ( 6 | "context" 7 | 8 | "github.com/stretchr/testify/mock" 9 | ) 10 | 11 | // MockIKeystone is an autogenerated mock type for the IKeystone type 12 | type MockIKeystone struct { 13 | mock.Mock 14 | } 15 | 16 | // GetGroups provides a mock function with given fields: _a0, _a1 17 | func (_m *MockIKeystone) GetGroups(_ context.Context, _a0 string, _a1 string) ([]string, error) { 18 | ret := _m.Called(_a0, _a1) 19 | 20 | var r0 []string 21 | if rf, ok := ret.Get(0).(func(string, string) []string); ok { 22 | r0 = rf(_a0, _a1) 23 | } else { 24 | if ret.Get(0) != nil { 25 | r0 = ret.Get(0).([]string) 26 | } 27 | } 28 | 29 | var r1 error 30 | if rf, ok := ret.Get(1).(func(string, string) error); ok { 31 | r1 = rf(_a0, _a1) 32 | } else { 33 | r1 = ret.Error(1) 34 | } 35 | 36 | return r0, r1 37 | } 38 | 39 | // GetTokenInfo provides a mock function with given fields: _a0 40 | func (_m *MockIKeystone) GetTokenInfo(_ context.Context, _a0 string) (*tokenInfo, error) { 41 | ret := _m.Called(_a0) 42 | 43 | var r0 *tokenInfo 44 | if rf, ok := ret.Get(0).(func(string) *tokenInfo); ok { 45 | r0 = rf(_a0) 46 | } else { 47 | if ret.Get(0) != nil { 48 | r0 = ret.Get(0).(*tokenInfo) 49 | } 50 | } 51 | 52 | var r1 error 53 | if rf, ok := ret.Get(1).(func(string) error); ok { 54 | r1 = rf(_a0) 55 | } else { 56 | r1 = ret.Error(1) 57 | } 58 | 59 | return r0, r1 60 | } 61 | -------------------------------------------------------------------------------- /pkg/identity/keystone/sync_test.yaml: -------------------------------------------------------------------------------- 1 | # In format %d, %n and %i wildcards represent keystone domain id, project name and project id respectively 2 | namespace-format: "prefix-%d-%n-%i-suffix" 3 | 4 | # List of Keystone project ids to omit from syncing 5 | projects-blacklist: ["id1", "id2"] 6 | 7 | # List of Keystone project names to omit from syncing 8 | projects-name-blacklist: ["name1", "name2"] 9 | 10 | # List of data types to synchronize 11 | "data-types-to-sync": ["projects", "role_assignments"] 12 | 13 | "role-mappings": 14 | - keystone-role: _member_ 15 | username: myuser 16 | groups: ["mygroup"] -------------------------------------------------------------------------------- /pkg/ingress/config/config.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 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 config 18 | 19 | import ( 20 | "k8s.io/cloud-provider-openstack/pkg/client" 21 | ) 22 | 23 | // Config struct contains ingress controller configuration 24 | type Config struct { 25 | ClusterName string `mapstructure:"cluster-name"` 26 | Kubernetes kubeConfig `mapstructure:"kubernetes"` 27 | OpenStack client.AuthOpts `mapstructure:"openstack"` 28 | Octavia octaviaConfig `mapstructure:"octavia"` 29 | } 30 | 31 | // Configuration for connecting to Kubernetes API server, either api_host or kubeconfig should be configured. 32 | type kubeConfig struct { 33 | // (Optional)Kubernetes API server host address. 34 | ApiserverHost string `mapstructure:"api-host"` 35 | 36 | // (Optional)Kubeconfig file used to connect to Kubernetes cluster. 37 | KubeConfig string `mapstructure:"kubeconfig"` 38 | } 39 | 40 | // Octavia service related configuration 41 | type octaviaConfig struct { 42 | // (Optional) Provider name for the load balancer. Default: octavia 43 | // For more information: https://docs.openstack.org/octavia/latest/admin/providers.html 44 | Provider string `mapstructure:"provider"` 45 | 46 | // (Required) Subnet ID to create the load balancer. 47 | SubnetID string `mapstructure:"subnet-id"` 48 | 49 | // (Optional) Public network ID to create floating IP. 50 | // If empty, no floating IP will be allocated to the load balancer vip. 51 | FloatingIPNetwork string `mapstructure:"floating-network-id"` 52 | 53 | // (Optional) If the ingress controller should manage the security groups attached to the cluster nodes. 54 | // Default is false. 55 | ManageSecurityGroups bool `mapstructure:"manage-security-groups"` 56 | 57 | // (Optional) Flavor ID to create the load balancer. 58 | // If empty, the default flavor will be used. 59 | FlavorID string `mapstructure:"flavor-id"` 60 | 61 | // (Optional) If the ingress controller should use serial API calls when creating and updating 62 | // the load balancer instead of the bulk update API call. 63 | // Default is false. 64 | ProviderRequiresSerialAPICalls bool `mapstructure:"provider-requires-serial-api-calls"` 65 | } 66 | -------------------------------------------------------------------------------- /pkg/ingress/utils/utils.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 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 utils 18 | 19 | import ( 20 | "crypto/sha256" 21 | "fmt" 22 | "regexp" 23 | "sort" 24 | 25 | apiv1 "k8s.io/api/core/v1" 26 | "k8s.io/apimachinery/pkg/util/sets" 27 | ) 28 | 29 | // Hash gets the data hash. 30 | func Hash(data string) string { 31 | return fmt.Sprintf("%x", sha256.Sum256([]byte(data))) 32 | } 33 | 34 | // GetResourceName get Ingress related resource name. 35 | func GetResourceName(namespace, name, clusterName string) string { 36 | // Keep consistent with the name of load balancer created for Service. 37 | return fmt.Sprintf("kube_ingress_%s_%s_%s", clusterName, namespace, name) 38 | } 39 | 40 | // NodeNames get all the node names. 41 | func NodeNames(nodes []*apiv1.Node) []string { 42 | ret := make([]string, len(nodes)) 43 | for i, node := range nodes { 44 | ret[i] = node.Name 45 | } 46 | return ret 47 | } 48 | 49 | // NodeSlicesEqual check if two nodes equals to each other. 50 | func NodeSlicesEqual(x, y []*apiv1.Node) bool { 51 | if len(x) != len(y) { 52 | return false 53 | } 54 | return stringSlicesEqual(NodeNames(x), NodeNames(y)) 55 | } 56 | 57 | func stringSlicesEqual(x, y []string) bool { 58 | if len(x) != len(y) { 59 | return false 60 | } 61 | if !sort.StringsAreSorted(x) { 62 | sort.Strings(x) 63 | } 64 | if !sort.StringsAreSorted(y) { 65 | sort.Strings(y) 66 | } 67 | for i := range x { 68 | if x[i] != y[i] { 69 | return false 70 | } 71 | } 72 | return true 73 | } 74 | 75 | // GetNodeID get instance ID from the Node spec. 76 | func GetNodeID(node *apiv1.Node) (string, error) { 77 | var providerIDRegexp = regexp.MustCompile(`^openstack://(?:[^/]*)/([^/]+)$`) 78 | 79 | matches := providerIDRegexp.FindStringSubmatch(node.Spec.ProviderID) 80 | if len(matches) != 2 { 81 | return "", fmt.Errorf("failed to find instance ID from node provider ID %s", node.Spec.ProviderID) 82 | } 83 | 84 | return matches[1], nil 85 | } 86 | 87 | // Convert2Set converts a string list to string set. 88 | func Convert2Set(list []string) sets.Set[string] { 89 | set := sets.New[string]() 90 | for _, s := range list { 91 | set.Insert(s) 92 | } 93 | 94 | return set 95 | } 96 | -------------------------------------------------------------------------------- /pkg/kms/barbican/barbican.go: -------------------------------------------------------------------------------- 1 | package barbican 2 | 3 | import ( 4 | "context" 5 | 6 | "github.com/gophercloud/gophercloud/v2" 7 | "github.com/gophercloud/gophercloud/v2/openstack" 8 | "github.com/gophercloud/gophercloud/v2/openstack/keymanager/v1/secrets" 9 | "k8s.io/cloud-provider-openstack/pkg/client" 10 | ) 11 | 12 | type KMSOpts struct { 13 | KeyID string `gcfg:"key-id"` 14 | } 15 | 16 | // Config to read config options 17 | type Config struct { 18 | Global client.AuthOpts 19 | KeyManager KMSOpts 20 | } 21 | 22 | // Barbican is gophercloud service client 23 | type Barbican struct { 24 | Client *gophercloud.ServiceClient 25 | } 26 | 27 | // NewBarbicanClient creates new BarbicanClient 28 | func NewBarbicanClient(cfg Config) (*gophercloud.ServiceClient, error) { 29 | provider, err := client.NewOpenStackClient(&cfg.Global, "barbican-kms-plugin") 30 | if err != nil { 31 | return nil, err 32 | } 33 | 34 | return openstack.NewKeyManagerV1(provider, gophercloud.EndpointOpts{ 35 | Region: cfg.Global.Region, 36 | Availability: cfg.Global.EndpointType, 37 | }) 38 | } 39 | 40 | // GetSecret gets unencrypted secret 41 | func (barbican *Barbican) GetSecret(ctx context.Context, keyID string) ([]byte, error) { 42 | opts := secrets.GetPayloadOpts{ 43 | PayloadContentType: "application/octet-stream", 44 | } 45 | 46 | key, err := secrets.GetPayload(ctx, barbican.Client, keyID, opts).Extract() 47 | if err != nil { 48 | return nil, err 49 | } 50 | 51 | return key, nil 52 | } 53 | -------------------------------------------------------------------------------- /pkg/kms/barbican/fake_barbican.go: -------------------------------------------------------------------------------- 1 | package barbican 2 | 3 | import ( 4 | "context" 5 | "encoding/hex" 6 | ) 7 | 8 | type FakeBarbican struct { 9 | } 10 | 11 | func (client *FakeBarbican) GetSecret(_ context.Context, keyID string) ([]byte, error) { 12 | return hex.DecodeString("6368616e676520746869732070617373") 13 | } 14 | -------------------------------------------------------------------------------- /pkg/kms/client/client.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "log" 6 | 7 | "google.golang.org/grpc" 8 | "google.golang.org/grpc/credentials/insecure" 9 | pb "k8s.io/kms/apis/v2" 10 | ) 11 | 12 | //This client is for test purpose only, Kubernetes api server will call to kms plugin grpc server 13 | 14 | func main() { 15 | connection, err := grpc.NewClient("unix:///var/lib/kms/kms.sock", grpc.WithTransportCredentials(insecure.NewCredentials())) 16 | defer func() { _ = connection.Close() }() 17 | if err != nil { 18 | log.Fatalf("Connection to KMS plugin failed, error: %v", err) 19 | } 20 | 21 | kmsClient := pb.NewKeyManagementServiceClient(connection) 22 | request := &pb.StatusRequest{} 23 | status, err := kmsClient.Status(context.TODO(), request) 24 | if err != nil { 25 | log.Fatalf("Error in getting version from KMS Plugin: %v", err) 26 | } 27 | 28 | if status.Version != "v2" { 29 | log.Fatalf("Unsupported KMS Plugin version: %s", status.Version) 30 | } 31 | 32 | log.Printf("KMS plugin version: %s", status.Version) 33 | 34 | secretBytes := []byte("mypassword") 35 | 36 | //Encryption Request to KMS Plugin 37 | encRequest := &pb.EncryptRequest{ 38 | Plaintext: secretBytes, 39 | } 40 | encResponse, err := kmsClient.Encrypt(context.TODO(), encRequest) 41 | if err != nil { 42 | log.Fatalf("Encrypt Request Failed: %v", err) 43 | } 44 | 45 | cipher := string(encResponse.Ciphertext) 46 | log.Printf("cipher: %s", cipher) 47 | 48 | //Decryption Request to KMS plugin 49 | decRequest := &pb.DecryptRequest{ 50 | Ciphertext: encResponse.Ciphertext, 51 | } 52 | 53 | decResponse, err := kmsClient.Decrypt(context.TODO(), decRequest) 54 | if err != nil { 55 | log.Fatalf("Unable to decrypt response: %v", err) 56 | } 57 | 58 | log.Printf("Decryption response: %v", decResponse) 59 | } 60 | -------------------------------------------------------------------------------- /pkg/kms/encryption/aescbc/aescbc.go: -------------------------------------------------------------------------------- 1 | package aescbc 2 | 3 | import ( 4 | "bytes" 5 | "crypto/aes" 6 | "crypto/cipher" 7 | "crypto/rand" 8 | "errors" 9 | "io" 10 | 11 | "k8s.io/klog/v2" 12 | ) 13 | 14 | // Encrypt plain text 15 | func Encrypt(data, key []byte) (ciphertext []byte, err error) { 16 | 17 | klog.V(3).Infof("aescbc encrypt") 18 | 19 | // NewCipher returns a new cipher block, the key argument should be AES key 20 | // either 16, 24 or 32 bytes to select AES-128, AES-192, AES-256, 32 byte is preferred 21 | block, err := aes.NewCipher(key) 22 | if err != nil { 23 | return nil, err 24 | } 25 | 26 | // determine the padding size for block cipher 27 | paddingSize := aes.BlockSize - (len(data) % aes.BlockSize) 28 | plaintext := make([]byte, len(data)+paddingSize) 29 | // copy data and padding 30 | copy(plaintext, data) 31 | copy(plaintext[len(data):], bytes.Repeat([]byte{byte(paddingSize)}, paddingSize)) 32 | 33 | // create slice to hold ciphertext, iv 34 | ciphertext = make([]byte, aes.BlockSize+len(plaintext)) 35 | iv := ciphertext[:aes.BlockSize] 36 | if _, err := io.ReadFull(rand.Reader, iv); err != nil { 37 | return nil, err 38 | } 39 | 40 | mode := cipher.NewCBCEncrypter(block, iv) 41 | mode.CryptBlocks(ciphertext[aes.BlockSize:], plaintext) 42 | 43 | klog.V(3).Infof("aescbc encrypt %s", string(ciphertext)) 44 | 45 | return 46 | } 47 | 48 | // Decrypt plaintext 49 | func Decrypt(data, key []byte) (plaintext []byte, err error) { 50 | klog.V(3).Infof("aescbc decrypt") 51 | block, err := aes.NewCipher(key) 52 | if err != nil { 53 | return nil, err 54 | } 55 | 56 | iv := data[:aes.BlockSize] 57 | ciphertext := data[aes.BlockSize:] 58 | 59 | if len(ciphertext)%aes.BlockSize != 0 { 60 | return nil, errors.New("Invalid Data, not multiple of block size") 61 | } 62 | 63 | mode := cipher.NewCBCDecrypter(block, iv) 64 | mode.CryptBlocks(ciphertext, ciphertext) 65 | 66 | paddingLength := int(ciphertext[len(ciphertext)-1]) 67 | dataLength := len(ciphertext) - paddingLength 68 | plaintext = ciphertext[:dataLength] 69 | klog.V(3).Infof("aescbc decrypt %s", string(plaintext)) 70 | 71 | return 72 | } 73 | -------------------------------------------------------------------------------- /pkg/kms/encryption/aescbc/aescbc_test.go: -------------------------------------------------------------------------------- 1 | package aescbc 2 | 3 | import ( 4 | "bytes" 5 | "crypto/rand" 6 | "testing" 7 | ) 8 | 9 | var key []byte 10 | 11 | func init() { 12 | // generate key for encrypt decrypt operation 13 | genKey() 14 | } 15 | 16 | func TestEncryptDecrypt(t *testing.T) { 17 | data := []byte("mypassword") 18 | cipher, _ := Encrypt((data), key) 19 | plain, _ := Decrypt(cipher, key) 20 | if !bytes.Equal((data), plain) { 21 | t.FailNow() 22 | } 23 | } 24 | 25 | // testKeyerror 26 | func TestEncryptDecryptInvalidData(t *testing.T) { 27 | data := []byte("mypassword") 28 | cipher, err := Encrypt(data, key) 29 | if err != nil { 30 | t.FailNow() 31 | } 32 | _, err = Decrypt(cipher[1:], key) 33 | if err == nil { 34 | t.FailNow() 35 | } 36 | t.Log(err) 37 | } 38 | 39 | func genKey() { 40 | key = make([]byte, 32) 41 | _, _ = rand.Read(key) 42 | 43 | } 44 | -------------------------------------------------------------------------------- /pkg/kms/server/server_test.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "bytes" 5 | "context" 6 | "testing" 7 | 8 | "k8s.io/cloud-provider-openstack/pkg/kms/barbican" 9 | pb "k8s.io/kms/apis/v2" 10 | ) 11 | 12 | var s = new(KMSserver) 13 | 14 | func TestInitConfig(t *testing.T) { 15 | } 16 | 17 | func TestStatus(t *testing.T) { 18 | req := &pb.StatusRequest{} 19 | _, err := s.Status(context.TODO(), req) 20 | if err != nil { 21 | t.FailNow() 22 | } 23 | } 24 | 25 | func TestEncryptDecrypt(t *testing.T) { 26 | s.barbican = &barbican.FakeBarbican{} 27 | fakeData := []byte("fakedata") 28 | encreq := &pb.EncryptRequest{Plaintext: fakeData} 29 | encresp, err := s.Encrypt(context.TODO(), encreq) 30 | if err != nil { 31 | t.Log(err) 32 | t.FailNow() 33 | } 34 | decreq := &pb.DecryptRequest{Ciphertext: encresp.Ciphertext} 35 | decresp, err := s.Decrypt(context.TODO(), decreq) 36 | if err != nil || !bytes.Equal(decresp.Plaintext, fakeData) { 37 | t.Log(err) 38 | t.FailNow() 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /pkg/metrics/metrics.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 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 metrics 18 | 19 | import ( 20 | "time" 21 | 22 | "k8s.io/component-base/metrics" 23 | ) 24 | 25 | type OpenstackMetrics struct { 26 | Duration *metrics.HistogramVec 27 | Total *metrics.CounterVec 28 | Errors *metrics.CounterVec 29 | } 30 | 31 | // MetricContext indicates the context for OpenStack metrics. 32 | type MetricContext struct { 33 | Start time.Time 34 | Attributes []string 35 | Metrics *OpenstackMetrics 36 | } 37 | 38 | // NewMetricContext creates a new MetricContext. 39 | func NewMetricContext(resource string, request string) *MetricContext { 40 | return &MetricContext{ 41 | Start: time.Now(), 42 | Attributes: []string{resource + "_" + request}, 43 | } 44 | } 45 | 46 | // ObserveRequest records the request latency and counts the errors. 47 | func (mc *MetricContext) Observe(om *OpenstackMetrics, err error) error { 48 | if om == nil { 49 | // mc.RequestMetrics not set, ignore this request 50 | return nil 51 | } 52 | 53 | om.Duration.WithLabelValues(mc.Attributes...).Observe( 54 | time.Since(mc.Start).Seconds()) 55 | om.Total.WithLabelValues(mc.Attributes...).Inc() 56 | if err != nil { 57 | om.Errors.WithLabelValues(mc.Attributes...).Inc() 58 | } 59 | return err 60 | } 61 | 62 | func RegisterMetrics(component string) { 63 | doRegisterAPIMetrics() 64 | if component == "occm" { 65 | doRegisterOccmMetrics() 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /pkg/metrics/metrics_api.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 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 metrics 18 | 19 | import ( 20 | "sync" 21 | 22 | "k8s.io/component-base/metrics" 23 | "k8s.io/component-base/metrics/legacyregistry" 24 | ) 25 | 26 | var ( 27 | APIRequestMetrics = &OpenstackMetrics{ 28 | Duration: metrics.NewHistogramVec( 29 | &metrics.HistogramOpts{ 30 | Name: "openstack_api_request_duration_seconds", 31 | Help: "Latency of an OpenStack API call", 32 | }, []string{"request"}), 33 | Total: metrics.NewCounterVec( 34 | &metrics.CounterOpts{ 35 | Name: "openstack_api_requests_total", 36 | Help: "Total number of OpenStack API calls", 37 | }, []string{"request"}), 38 | Errors: metrics.NewCounterVec( 39 | &metrics.CounterOpts{ 40 | Name: "openstack_api_request_errors_total", 41 | Help: "Total number of errors for an OpenStack API call", 42 | }, []string{"request"}), 43 | } 44 | ) 45 | 46 | // ObserveRequest records the request latency and counts the errors. 47 | func (mc *MetricContext) ObserveRequest(err error) error { 48 | return mc.Observe(APIRequestMetrics, err) 49 | } 50 | 51 | var registerAPIMetrics sync.Once 52 | 53 | // RegisterMetrics registers OpenStack metrics. 54 | func doRegisterAPIMetrics() { 55 | registerAPIMetrics.Do(func() { 56 | legacyregistry.MustRegister( 57 | APIRequestMetrics.Duration, 58 | APIRequestMetrics.Total, 59 | APIRequestMetrics.Errors, 60 | ) 61 | }) 62 | } 63 | -------------------------------------------------------------------------------- /pkg/metrics/metrics_reconcile.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Kubernetes Authors. 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 metrics 18 | 19 | import ( 20 | "sync" 21 | 22 | "k8s.io/component-base/metrics" 23 | "k8s.io/component-base/metrics/legacyregistry" 24 | ) 25 | 26 | var ( 27 | occmReconcileMetrics = &OpenstackMetrics{ 28 | Duration: metrics.NewHistogramVec( 29 | &metrics.HistogramOpts{ 30 | Name: "cloudprovider_openstack_reconcile_duration_seconds", 31 | Help: "Time taken by various parts of OpenStack cloud controller manager reconciliation loops", 32 | Buckets: []float64{0.01, 0.05, 0.1, 0.5, 1.0, 2.5, 5.0, 7.5, 10.0, 12.5, 15.0, 17.5, 20.0, 22.5, 25.0, 27.5, 30.0, 50.0, 75.0, 100.0, 1000.0}, 33 | }, []string{"operation"}), 34 | Total: metrics.NewCounterVec( 35 | &metrics.CounterOpts{ 36 | Name: "cloudprovider_openstack_reconcile_total", 37 | Help: "Total number of OpenStack cloud controller manager reconciliations", 38 | }, []string{"operation"}), 39 | Errors: metrics.NewCounterVec( 40 | &metrics.CounterOpts{ 41 | Name: "cloudprovider_openstack_reconcile_errors_total", 42 | Help: "Total number of OpenStack cloud controller manager reconciliation errors", 43 | }, []string{"operation"}), 44 | } 45 | ) 46 | 47 | // ObserveReconcile records the request reconciliation duration 48 | func (mc *MetricContext) ObserveReconcile(err error) error { 49 | return mc.Observe(occmReconcileMetrics, err) 50 | } 51 | 52 | var registerOccmMetrics sync.Once 53 | 54 | // RegisterMetrics registers OpenStack metrics. 55 | func doRegisterOccmMetrics() { 56 | registerOccmMetrics.Do(func() { 57 | legacyregistry.MustRegister( 58 | occmReconcileMetrics.Duration, 59 | occmReconcileMetrics.Total, 60 | occmReconcileMetrics.Errors, 61 | ) 62 | }) 63 | } 64 | -------------------------------------------------------------------------------- /pkg/openstack/OWNERS: -------------------------------------------------------------------------------- 1 | approvers: 2 | - anguslees 3 | - FengyunPan2 4 | reviewers: 5 | - anguslees 6 | - FengyunPan2 7 | -------------------------------------------------------------------------------- /pkg/openstack/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 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 openstack // import "k8s.io/cloud-provider-openstack/pkg/openstack" 18 | -------------------------------------------------------------------------------- /pkg/openstack/events.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 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 openstack 18 | 19 | const ( 20 | eventLBForceInternal = "LoadBalancerForcedInternal" 21 | eventLBExternalNetworkSearchFailed = "LoadBalancerExternalNetworkSearchFailed" 22 | eventLBSourceRangesIgnored = "LoadBalancerSourceRangesIgnored" 23 | eventLBAZIgnored = "LoadBalancerAvailabilityZonesIgnored" 24 | eventLBFloatingIPSkipped = "LoadBalancerFloatingIPSkipped" 25 | eventLBRename = "LoadBalancerRename" 26 | eventLBLbMethodUnknown = "LoadBalancerLbMethodUnknown" 27 | ) 28 | -------------------------------------------------------------------------------- /pkg/openstack/loadbalancer_service_patcher.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 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 openstack 18 | 19 | import ( 20 | "context" 21 | "reflect" 22 | 23 | corev1 "k8s.io/api/core/v1" 24 | utilerrors "k8s.io/apimachinery/pkg/util/errors" 25 | "k8s.io/client-go/kubernetes" 26 | cpoutil "k8s.io/cloud-provider-openstack/pkg/util" 27 | ) 28 | 29 | type servicePatcher struct { 30 | kclient kubernetes.Interface 31 | base *corev1.Service 32 | updated *corev1.Service 33 | } 34 | 35 | func newServicePatcher(kclient kubernetes.Interface, base *corev1.Service) servicePatcher { 36 | return servicePatcher{ 37 | kclient: kclient, 38 | base: base.DeepCopy(), 39 | updated: base, 40 | } 41 | } 42 | 43 | // Patch will submit a patch request for the Service unless the updated service 44 | // reference contains the same set of annotations as the base copied during 45 | // servicePatcher initialization. 46 | func (sp *servicePatcher) Patch(ctx context.Context, err error) error { 47 | if reflect.DeepEqual(sp.base.Annotations, sp.updated.Annotations) { 48 | return err 49 | } 50 | perr := cpoutil.PatchService(ctx, sp.kclient, sp.base, sp.updated) 51 | return utilerrors.NewAggregate([]error{err, perr}) 52 | } 53 | -------------------------------------------------------------------------------- /pkg/util/blockdevice/blockdevice_unsupported.go: -------------------------------------------------------------------------------- 1 | //go:build !linux 2 | // +build !linux 3 | 4 | /* 5 | Copyright 2020 The Kubernetes Authors. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | package blockdevice 21 | 22 | import ( 23 | "errors" 24 | ) 25 | 26 | func IsBlockDevice(path string) (bool, error) { 27 | return false, errors.New("IsBlockDevice is not implemented for this OS") 28 | } 29 | 30 | func GetBlockDeviceSize(path string) (int64, error) { 31 | return -1, errors.New("GetBlockDeviceSize is not implemented for this OS") 32 | } 33 | 34 | func RescanBlockDeviceGeometry(devicePath string, deviceMountPath string, newSize int64) error { 35 | return errors.New("RescanBlockDeviceGeometry is not implemented for this OS") 36 | } 37 | 38 | func RescanDevice(devicePath string) error { 39 | return errors.New("RescanDevice is not implemented for this OS") 40 | } 41 | -------------------------------------------------------------------------------- /pkg/util/errors/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 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 errors 18 | 19 | import ( 20 | "errors" 21 | "net/http" 22 | 23 | "github.com/gophercloud/gophercloud/v2" 24 | ) 25 | 26 | // ErrNotFound is used to inform that the object is missing 27 | var ErrNotFound = errors.New("failed to find object") 28 | 29 | // ErrMultipleResults is used when we unexpectedly get back multiple results 30 | var ErrMultipleResults = errors.New("multiple results where only one expected") 31 | 32 | // ErrNoAddressFound is used when we cannot find an ip address for the host 33 | var ErrNoAddressFound = errors.New("no address found for host") 34 | 35 | // ErrIPv6SupportDisabled is used when one tries to use IPv6 Addresses when 36 | // IPv6 support is disabled by config 37 | var ErrIPv6SupportDisabled = errors.New("IPv6 support is disabled") 38 | 39 | // ErrNoRouterID is used when router-id is not set 40 | var ErrNoRouterID = errors.New("router-id not set in cloud provider config") 41 | 42 | // ErrNoNodeInformer is used when node informer is not yet initialized 43 | var ErrNoNodeInformer = errors.New("node informer is not yet initialized") 44 | 45 | func IsNotFound(err error) bool { 46 | if err == ErrNotFound { 47 | return true 48 | } 49 | 50 | if _, ok := err.(gophercloud.ErrResourceNotFound); ok { 51 | return true 52 | } 53 | 54 | return gophercloud.ResponseCodeIs(err, http.StatusNotFound) 55 | } 56 | 57 | func IsInvalidError(err error) bool { 58 | return gophercloud.ResponseCodeIs(err, http.StatusBadRequest) 59 | } 60 | 61 | func IsConflictError(err error) bool { 62 | return gophercloud.ResponseCodeIs(err, http.StatusConflict) 63 | } 64 | -------------------------------------------------------------------------------- /pkg/util/metadata/metadata_mock.go: -------------------------------------------------------------------------------- 1 | package metadata 2 | 3 | import mock "github.com/stretchr/testify/mock" 4 | 5 | // revive:disable:exported 6 | // MetadataMock is an autogenerated mock type for the IMetadata type 7 | type MetadataMock struct { 8 | mock.Mock 9 | } 10 | 11 | // revive:enable:exported 12 | 13 | // GetAvailabilityZone provides a mock function with given fields: 14 | func (_m *MetadataMock) GetAvailabilityZone() (string, error) { 15 | ret := _m.Called() 16 | 17 | var r0 string 18 | if rf, ok := ret.Get(0).(func() string); ok { 19 | r0 = rf() 20 | } else { 21 | r0 = ret.Get(0).(string) 22 | } 23 | 24 | var r1 error 25 | if rf, ok := ret.Get(1).(func() error); ok { 26 | r1 = rf() 27 | } else { 28 | r1 = ret.Error(1) 29 | } 30 | 31 | return r0, r1 32 | } 33 | 34 | // GetInstanceID provides a mock function with given fields: 35 | func (_m *MetadataMock) GetInstanceID() (string, error) { 36 | ret := _m.Called() 37 | 38 | var r0 string 39 | if rf, ok := ret.Get(0).(func() string); ok { 40 | r0 = rf() 41 | } else { 42 | r0 = ret.Get(0).(string) 43 | } 44 | 45 | var r1 error 46 | if rf, ok := ret.Get(1).(func() error); ok { 47 | r1 = rf() 48 | } else { 49 | r1 = ret.Error(1) 50 | } 51 | 52 | return r0, r1 53 | } 54 | -------------------------------------------------------------------------------- /pkg/util/openstack/security_group.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2023 The Kubernetes Authors. 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 openstack 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/gophercloud/gophercloud/v2" 23 | "github.com/gophercloud/gophercloud/v2/openstack/networking/v2/extensions/security/rules" 24 | "k8s.io/cloud-provider-openstack/pkg/metrics" 25 | ) 26 | 27 | func GetSecurityGroupRules(ctx context.Context, client *gophercloud.ServiceClient, opts rules.ListOpts) ([]rules.SecGroupRule, error) { 28 | mc := metrics.NewMetricContext("security_group_rule", "list") 29 | page, err := rules.List(client, opts).AllPages(ctx) 30 | if mc.ObserveRequest(err) != nil { 31 | return nil, err 32 | } 33 | return rules.ExtractRules(page) 34 | } 35 | -------------------------------------------------------------------------------- /pkg/util/util_test.go: -------------------------------------------------------------------------------- 1 | package util 2 | 3 | import ( 4 | "testing" 5 | 6 | "github.com/stretchr/testify/assert" 7 | ) 8 | 9 | func TestStringToMap(t *testing.T) { 10 | tests := []struct { 11 | name string 12 | in string 13 | out map[string]string 14 | }{ 15 | { 16 | name: "test1", 17 | in: "k1=v1,k2=v2", 18 | out: map[string]string{"k1": "v1", "k2": "v2"}, 19 | }, 20 | { 21 | name: "test2", 22 | in: "k1=v1,k2=v2=true", 23 | out: map[string]string{"k1": "v1", "k2": "v2=true"}, 24 | }, 25 | { 26 | name: "test3", 27 | in: "k1,k2", 28 | out: map[string]string{"k1": "", "k2": ""}, 29 | }, 30 | { 31 | name: "test4", 32 | in: " k1=v1, k2 ", 33 | out: map[string]string{"k1": "v1", "k2": ""}, 34 | }, 35 | { 36 | name: "test5", 37 | in: "k3=v3,=emptykey", 38 | out: map[string]string{"k3": "v3", "": "emptykey"}, 39 | }, 40 | } 41 | 42 | for _, test := range tests { 43 | t.Run(test.name, func(t *testing.T) { 44 | out := StringToMap(test.in) 45 | 46 | assert.Equal(t, test.out, out) 47 | }) 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /pkg/version/version.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 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 version 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | ) 23 | 24 | // Version is set by the linker flags in the Makefile. 25 | var Version string 26 | 27 | func PrintVersionAndExit() { 28 | fmt.Printf("%s\n", Version) 29 | os.Exit(0) 30 | } 31 | -------------------------------------------------------------------------------- /tests/ci-keystone-e2e.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Tracked in https://github.com/kubernetes/cloud-provider-openstack/issues/1871 4 | echo "FIXME: This is only a placeholder to pass CI" 5 | -------------------------------------------------------------------------------- /tests/e2e/csi/cinder/test-driver.yaml: -------------------------------------------------------------------------------- 1 | StorageClass: 2 | FromName: true 3 | SnapshotClass: 4 | FromName: true 5 | ClaimSize: "2Gi" 6 | DriverInfo: 7 | Name: cinder.csi.openstack.org 8 | SupportedFsType: 9 | ext2: null 10 | ext3: null 11 | ext4: null 12 | xfs: null 13 | SupportedSizeRange: 14 | Min: "1Gi" 15 | TopologyKeys: 16 | - "topology.cinder.csi.openstack.org/zone" 17 | Capabilities: 18 | persistence: true 19 | fsGroup: true 20 | exec: true 21 | multipods: true 22 | block: true 23 | pvcDataSource: true 24 | topology: true 25 | controllerExpansion: true 26 | nodeExpansion: true 27 | snapshotDataSource: true 28 | -------------------------------------------------------------------------------- /tests/e2e/csi/manila/testsuite.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | "fmt" 5 | // revive:disable:dot-imports 6 | 7 | // revive:enable:dot-imports 8 | // revive:disable:blank-imports 9 | "github.com/onsi/ginkgo/v2" 10 | _ "github.com/onsi/gomega" 11 | 12 | // revive:enable:blank-imports 13 | 14 | "k8s.io/kubernetes/test/e2e/framework/testfiles" 15 | storageframework "k8s.io/kubernetes/test/e2e/storage/framework" 16 | "k8s.io/kubernetes/test/e2e/storage/testsuites" 17 | "k8s.io/kubernetes/test/e2e/storage/utils" 18 | e2etestingmanifests "k8s.io/kubernetes/test/e2e/testing-manifests" 19 | ) 20 | 21 | var CSITestSuites = []func() storageframework.TestSuite{ 22 | testsuites.InitVolumesTestSuite, 23 | testsuites.InitSnapshottableTestSuite, 24 | testsuites.InitProvisioningTestSuite, 25 | testsuites.InitSubPathTestSuite, 26 | testsuites.InitVolumeModeTestSuite, 27 | testsuites.InitVolumeExpandTestSuite, 28 | testsuites.InitVolumeIOTestSuite, 29 | } 30 | 31 | var _ = utils.SIGDescribe("[manila-csi-e2e] CSI Volumes", func() { 32 | testfiles.AddFileSource(e2etestingmanifests.GetE2ETestingManifestsFS()) 33 | 34 | testDriver := newManilaTestDriver() 35 | 36 | ginkgo.Context(fmt.Sprintf("%s", storageframework.GetDriverNameWithFeatureTags(testDriver)), func() { 37 | storageframework.DefineTestSuites(testDriver, CSITestSuites) 38 | }) 39 | }) 40 | -------------------------------------------------------------------------------- /tests/playbooks/fetch-logs.yaml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | become: true 3 | become_method: sudo 4 | gather_facts: true 5 | 6 | vars: 7 | user: stack 8 | devstack_workdir: /home/{{ user }}/devstack 9 | 10 | roles: 11 | - role: fetch-logs 12 | -------------------------------------------------------------------------------- /tests/playbooks/roles/fetch-logs/README.md: -------------------------------------------------------------------------------- 1 | The ansible role gets logs of various services running in the CI for further analysis 2 | -------------------------------------------------------------------------------- /tests/playbooks/roles/fetch-logs/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | master_port_name: "k3s_master" 3 | -------------------------------------------------------------------------------- /tests/playbooks/roles/fetch-logs/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | - name: Get k3s master floating IP 2 | shell: 3 | executable: /bin/bash 4 | cmd: | 5 | set +x; source {{ devstack_workdir }}/openrc demo demo > /dev/null 6 | openstack floating ip list --port {{ master_port_name }} -c "Floating IP Address" -f value 7 | register: fip 8 | 9 | - name: Set fact for k3s master floating IP 10 | set_fact: 11 | k3s_fip: "{{ fip.stdout }}" 12 | 13 | - name: Creates directory 14 | ansible.builtin.file: 15 | path: "/root/logs" 16 | state: directory 17 | 18 | - name: Fetch k3s logs 19 | shell: 20 | executable: /bin/bash 21 | cmd: | 22 | ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -i {{ ansible_user_dir }}/.ssh/id_rsa ubuntu@{{ k3s_fip }} sudo journalctl -u k3s.service --no-pager > /root/logs/k3s.log 23 | 24 | - name: Fetch DevStack logs 25 | shell: 26 | executable: /bin/bash 27 | cmd: | 28 | set +x; 29 | units=`systemctl list-units --type service | awk '{ print $1 }' | grep devstack\@` 30 | for unit in $units; do 31 | filename=${unit#"devstack@"} 32 | filename=${filename%".service"} 33 | sudo journalctl -u $unit --no-pager > /root/logs/${filename}.log 34 | done; 35 | -------------------------------------------------------------------------------- /tests/playbooks/roles/install-cpo-occm/README.md: -------------------------------------------------------------------------------- 1 | The ansible role builds and uploads openstack-cloud-controller-manager image and deploys in a k8s cluster. 2 | 3 | Prerequisites: 4 | 5 | * The playbook is running on a host with devstack installed. 6 | * golang, docker and kubectl should be installed. 7 | * docker registry is up and running. 8 | * k8s cluster is running inside VMs on the devstack host. 9 | * `~/.kube/config` exists and is pointing at the k8s cluster 10 | -------------------------------------------------------------------------------- /tests/playbooks/roles/install-cpo-occm/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | devstack_workdir: "{{ ansible_user_dir }}/devstack" 3 | 4 | # Used for uploading image to local registry. 5 | image_registry_host: localhost 6 | run_e2e: false 7 | # Used for access the private registry image from k8s 8 | remote_registry_host: "{{ ansible_default_ipv4.address }}" 9 | 10 | # Octavia provider to configure OCCM with. Empty means we'll use a default 11 | octavia_provider: "" 12 | -------------------------------------------------------------------------------- /tests/playbooks/roles/install-csi-cinder/README.md: -------------------------------------------------------------------------------- 1 | The ansible role builds and uploads cinder-csi-plugin image and deploys in a k8s cluster. 2 | 3 | Prerequisites: 4 | 5 | * The playbook is running on a host with devstack installed. 6 | * golang, docker and kubectl should be installed. 7 | * docker registry is up and running. 8 | * k8s cluster is running inside VMs on the devstack host. 9 | * `~/.kube/config` exists and is pointing at the k8s cluster 10 | -------------------------------------------------------------------------------- /tests/playbooks/roles/install-csi-cinder/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | devstack_workdir: "{{ ansible_user_dir }}/devstack" 3 | 4 | # Used for uploading image to local registry. 5 | image_registry_host: localhost 6 | # Used for access the private registry image from k8s 7 | remote_registry_host: "{{ ansible_default_ipv4.address }}" 8 | -------------------------------------------------------------------------------- /tests/playbooks/roles/install-csi-manila/README.md: -------------------------------------------------------------------------------- 1 | The ansible role builds and uploads manila-csi-plugin image and deploys in a k8s cluster. 2 | 3 | Prerequisites: 4 | 5 | * The playbook is running on a host with devstack installed. 6 | * golang, docker and kubectl should be installed. 7 | * docker registry is up and running. 8 | * k8s cluster is running inside VMs on the devstack host. 9 | * `~/.kube/config` exists and is pointing at the k8s cluster 10 | -------------------------------------------------------------------------------- /tests/playbooks/roles/install-csi-manila/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | devstack_workdir: "{{ ansible_user_dir }}/devstack" 3 | 4 | # Used for uploading image to local registry. 5 | image_registry_host: localhost 6 | # Used for access the private registry image from k8s 7 | remote_registry_host: "{{ ansible_default_ipv4.address }}" 8 | 9 | k8s_log_dir: "/var/log/" 10 | -------------------------------------------------------------------------------- /tests/playbooks/roles/install-devstack/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | user: "stack" 3 | workdir: "/home/{{ user }}/devstack" 4 | branch: "2023.2-eol" 5 | enable_services: 6 | - nova 7 | - glance 8 | - cinder 9 | - neutron 10 | - octavia 11 | - ovn-octavia 12 | - barbican 13 | octavia_amphora_url: "https://tarballs.opendev.org/openstack/octavia/test-images/test-only-amphora-x64-haproxy-ubuntu-jammy.qcow2" 14 | octavia_amphora_dir: /opt/octavia-amphora 15 | octavia_amphora_filename: amphora-x64-haproxy.qcow2 16 | -------------------------------------------------------------------------------- /tests/playbooks/roles/install-docker-registry/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | cfssl_version: 1.6.0 3 | cert_cn: example.com 4 | cert_hosts: 5 | - example.com 6 | - 127.0.0.1 -------------------------------------------------------------------------------- /tests/playbooks/roles/install-docker-registry/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Ensure cert folder 3 | file: 4 | state: directory 5 | path: "{{ ansible_user_dir }}/certs" 6 | 7 | - name: Ensure cfssl is installed 8 | shell: 9 | executable: /bin/bash 10 | cmd: | 11 | _=$(command -v cfssl) 12 | if [[ "$?" != "0" ]]; then 13 | curl -SL https://github.com/cloudflare/cfssl/releases/download/v{{ cfssl_version }}/cfssl_{{ cfssl_version }}_linux_amd64 -o /usr/local/bin/cfssl 14 | chmod +x /usr/local/bin/cfssl 15 | curl -SL https://github.com/cloudflare/cfssl/releases/download/v{{ cfssl_version }}/cfssljson_{{ cfssl_version }}_linux_amd64 -o /usr/local/bin/cfssljson 16 | chmod +x /usr/local/bin/cfssljson 17 | curl -SL https://github.com/cloudflare/cfssl/releases/download/v{{ cfssl_version }}/cfssl-certinfo_{{ cfssl_version }}_linux_amd64 -o /usr/local/bin/cfssl-certinfo 18 | chmod +x /usr/local/bin/cfssl-certinfo 19 | fi 20 | 21 | - name: Prepare cfssl config files 22 | template: 23 | src: "{{ item }}" 24 | dest: "{{ ansible_user_dir }}/certs/{{ item | basename | regex_replace('.j2$', '') }}" 25 | with_fileglob: 26 | - ../templates/*.j2 27 | 28 | - name: Manage self-sign CA 29 | shell: 30 | executable: /bin/bash 31 | chdir: "{{ ansible_user_dir }}/certs" 32 | creates: "{{ ansible_user_dir }}/certs/ca.pem" 33 | cmd: | 34 | cfssl gencert -initca ca-csr.json | cfssljson -bare ca - 35 | 36 | - name: Create server certificate 37 | shell: 38 | executable: /bin/bash 39 | chdir: "{{ ansible_user_dir }}/certs" 40 | creates: "{{ ansible_user_dir }}/certs/server.pem" 41 | cmd: | 42 | cfssl gencert -config ca-config.json -profile server -ca ./ca.pem -ca-key ./ca-key.pem ca-csr.json | cfssljson -bare server 43 | 44 | - name: Run docker registry container 45 | shell: 46 | executable: /bin/bash 47 | cmd: | 48 | docker ps --filter name=registry | grep registry 49 | if [[ "$?" != "0" ]]; then 50 | docker run -d \ 51 | --restart=always \ 52 | --name registry \ 53 | -v "{{ ansible_user_dir }}/certs":/certs \ 54 | -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \ 55 | -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/server.pem \ 56 | -e REGISTRY_HTTP_TLS_KEY=/certs/server-key.pem \ 57 | -p 443:443 \ 58 | registry:2 59 | fi 60 | -------------------------------------------------------------------------------- /tests/playbooks/roles/install-docker-registry/templates/ca-config.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "signing": { 3 | "default": { 4 | "expiry": "8760h" 5 | }, 6 | "profiles": { 7 | "server": { 8 | "expiry": "8760h", 9 | "usages": [ 10 | "signing", 11 | "key encipherment", 12 | "server auth", 13 | "digital signature" 14 | ] 15 | }, 16 | "client": { 17 | "expiry": "8760h", 18 | "usages": [ 19 | "signing", 20 | "key encipherment", 21 | "client auth", 22 | "digital signature" 23 | ] 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /tests/playbooks/roles/install-docker-registry/templates/ca-csr.json.j2: -------------------------------------------------------------------------------- 1 | { 2 | "CN": "{{ cert_cn }}", 3 | "hosts": {{ cert_hosts }}, 4 | "key": { 5 | "algo": "ecdsa", 6 | "size": 256 7 | }, 8 | "names": [ 9 | { 10 | "C": "NZ", 11 | "L": "WLG", 12 | "ST": "Wellington" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /tests/playbooks/roles/install-docker/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | docker_version: 5:27.3.1-1~ubuntu.24.04~noble 3 | -------------------------------------------------------------------------------- /tests/playbooks/roles/install-docker/handlers/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Restart Docker 3 | systemd: 4 | name: docker 5 | state: restarted 6 | daemon_reload: yes -------------------------------------------------------------------------------- /tests/playbooks/roles/install-docker/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # apt-get install -y apt-transport-https ca-certificates curl software-properties-common 3 | - name: Install packages 4 | apt: 5 | name: "{{ packages }}" 6 | state: present 7 | update_cache: yes 8 | vars: 9 | packages: 10 | # allowing you to add external HTTPS sources to your APT sources list. 11 | - apt-transport-https 12 | - ca-certificates 13 | - software-properties-common 14 | - curl 15 | 16 | # curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - 17 | - name: Add Docker's official GPG key 18 | apt_key: 19 | url: https://download.docker.com/linux/ubuntu/gpg 20 | state: present 21 | 22 | # add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" 23 | - name: Set up the stable repository 24 | apt_repository: 25 | repo: 'deb https://download.docker.com/linux/ubuntu {{ hostvars[inventory_hostname].ansible_distribution_release }} stable' 26 | state: present 27 | 28 | # apt-get update; apt install -y docker-ce= 29 | - name: Install docker-ce 30 | apt: 31 | name: docker-ce #={{ docker_version }} 32 | state: present 33 | update_cache: yes 34 | 35 | - name: Config docker 36 | copy: 37 | content: | 38 | { 39 | "exec-opts": ["native.cgroupdriver=systemd"], 40 | "log-driver": "json-file", 41 | "log-opts": { 42 | "max-size": "50m" 43 | }, 44 | "storage-driver": "overlay2" 45 | } 46 | dest: /etc/docker/daemon.json 47 | mode: 0644 48 | notify: "Restart Docker" 49 | -------------------------------------------------------------------------------- /tests/playbooks/roles/install-golang/defaults/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | go_version: '1.22.2' 3 | arch: 'amd64' 4 | go_tarball: 'go{{ go_version }}.linux-{{ arch }}.tar.gz' 5 | go_download_location: 'https://go.dev/dl/{{ go_tarball }}' 6 | -------------------------------------------------------------------------------- /tests/playbooks/roles/install-golang/tasks/main.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - name: Check if go has satisfied requirement 3 | shell: /usr/local/go/bin/go version |grep -Eo '([0-9]+\.)+[0-9]+' 4 | ignore_errors: yes 5 | register: curr_go_version 6 | 7 | - name: Download the Go tarball 8 | get_url: 9 | url: '{{ go_download_location }}' 10 | dest: '/usr/local/src/{{ go_tarball }}' 11 | when: 12 | - curr_go_version.stdout != go_version 13 | 14 | - name: Remove old installation of Go 15 | file: 16 | path: /usr/local/go 17 | state: absent 18 | when: 19 | - curr_go_version.stdout != go_version 20 | 21 | - name: Extract the Go tarball to place 22 | unarchive: 23 | src: '/usr/local/src/{{ go_tarball }}' 24 | dest: /usr/local 25 | remote_src: yes 26 | when: 27 | - curr_go_version.stdout != go_version 28 | 29 | - name: Set GOPATH 30 | lineinfile: 31 | path: ~/.bashrc 32 | line: 'export GOPATH=$HOME' 33 | create: true 34 | state: present 35 | 36 | - name: Add go binary path to PATH 37 | lineinfile: 38 | path: ~/.bashrc 39 | line: 'export PATH=/usr/local/go/bin:{{ ansible_user_dir }}/bin:$PATH' 40 | create: true 41 | state: present 42 | -------------------------------------------------------------------------------- /tests/playbooks/roles/install-helm/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Install Helm v3 2 | shell: 3 | executable: /bin/bash 4 | cmd: | 5 | curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash 6 | -------------------------------------------------------------------------------- /tests/playbooks/roles/install-k3s-bare-single/README.md: -------------------------------------------------------------------------------- 1 | The ansible role deploys single-node k3s on the host. 2 | 3 | Prerequisites: 4 | 5 | * Needs Docker installed. 6 | -------------------------------------------------------------------------------- /tests/playbooks/roles/install-k3s-bare-single/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | k8s_branch: "latest-stable" 3 | -------------------------------------------------------------------------------- /tests/playbooks/roles/install-k3s-bare-single/tasks/main.yaml: -------------------------------------------------------------------------------- 1 | - name: Install packages 2 | apt: 3 | name: "{{ packages }}" 4 | state: present 5 | update_cache: yes 6 | vars: 7 | packages: 8 | - jq 9 | 10 | - name: Get k3s release 11 | shell: 12 | executable: /bin/bash 13 | cmd: | 14 | # Get k3s release based on the given k8s branch. 15 | branch={{ k8s_branch }} 16 | if [[ "$branch" = "master" ]]; then 17 | k3s_release=$(curl -s "https://api.github.com/repos/k3s-io/k3s/tags" | jq -r '.[0].name') 18 | elif [[ "$branch" = "latest-stable" ]]; then 19 | # If no k3s version is provided, the installation script will pull 20 | # the latest version from the stable channel. 21 | k3s_release='' 22 | else 23 | # release-1.20 --> 1.20 24 | k8s_minor=${branch##*-} 25 | # 1.20 --> v1.20.x+k3s1 or v1.20.1-rc1+k3s1 26 | k3s_release=$(curl -s "https://api.github.com/repos/k3s-io/k3s/tags" | jq -r '.[].name' | grep -E "^v${k8s_minor}.[0-9a-z\+\-]+\+k3s1$" | awk 'NR==1 {print}') 27 | fi 28 | echo $k3s_release 29 | register: release 30 | 31 | - name: Install single-node k3s on host 32 | shell: 33 | executable: /bin/bash 34 | cmd: | 35 | set -xe 36 | curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION="{{ release.stdout }}" sh - 37 | 38 | - name: Wait for k8s node ready 39 | shell: 40 | executable: /bin/bash 41 | cmd: | 42 | kubectl --kubeconfig /etc/rancher/k3s/k3s.yaml get node | grep " Ready " | wc -l 43 | register: result 44 | until: result.stdout == "1" 45 | retries: 12 46 | delay: 10 47 | 48 | - name: Create ~/.kube directory 49 | ansible.builtin.file: 50 | path: ~/.kube 51 | state: directory 52 | 53 | - name: Copy kubeconfig to ~/.kube 54 | ansible.builtin.copy: 55 | src: /etc/rancher/k3s/k3s.yaml 56 | dest: ~/.kube/config 57 | remote_src: true 58 | -------------------------------------------------------------------------------- /tests/playbooks/roles/install-k3s/README.md: -------------------------------------------------------------------------------- 1 | The ansible role deploys k3s in openstack VMs. 2 | 3 | Prerequisites: 4 | 5 | * The playbook is supposed to run on a devstack host. 6 | -------------------------------------------------------------------------------- /tests/playbooks/roles/install-k3s/defaults/main.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | k3s_release: v1.32.2-rc3+k3s1 3 | worker_node_count: 1 4 | cluster_token: "K1039d1cf76d1f8b0e8b0d48e7c60d9c4a43c2e7a56de5d86f346f2288a2677f1d7::server:2acba4e60918c0e2d1f1d1a7c4e81e7b" 5 | devstack_workdir: "{{ ansible_user_dir }}/devstack" 6 | flavor_name: "ds2G" 7 | sg_name: "k3s_sg" 8 | keypair_name: "k3s_keypair" 9 | image_url: "https://cloud-images.ubuntu.com/releases/noble/release/ubuntu-24.04-server-cloudimg-amd64.img" 10 | image_name: "ubuntu-noble" 11 | master_port_name: "k3s_master" 12 | -------------------------------------------------------------------------------- /tests/playbooks/test-csi-cinder-e2e.yaml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | become: true 3 | become_method: sudo 4 | gather_facts: true 5 | 6 | vars: 7 | e2e_test_version: v1.32.2 8 | user: stack 9 | devstack_workdir: /home/{{ user }}/devstack 10 | 11 | roles: 12 | - role: install-golang 13 | - role: install-devstack 14 | enable_services: 15 | - nova 16 | - neutron 17 | - glance 18 | - cinder 19 | - role: install-docker 20 | - role: install-docker-registry 21 | cert_hosts: ' ["{{ ansible_default_ipv4.address }}"]' 22 | - role: install-k3s 23 | worker_node_count: 0 24 | - role: install-cpo-occm 25 | run_e2e: false 26 | - role: install-csi-cinder 27 | environment: 28 | GOPATH: '{{ ansible_user_dir }}' 29 | PATH: '/usr/local/go/bin:{{ ansible_user_dir }}/bin:{{ ansible_env.PATH }}' 30 | KUBECONFIG: '{{ ansible_user_dir }}/.kube/config' 31 | -------------------------------------------------------------------------------- /tests/playbooks/test-csi-manila-e2e.yaml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | become: true 3 | become_method: sudo 4 | gather_facts: true 5 | 6 | vars: 7 | user: stack 8 | devstack_workdir: /home/{{ user }}/devstack 9 | 10 | roles: 11 | - role: install-golang 12 | - role: install-devstack 13 | enable_services: 14 | - nova 15 | - neutron 16 | - glance 17 | - manila 18 | - role: install-docker 19 | - role: install-docker-registry 20 | cert_hosts: ' ["{{ ansible_default_ipv4.address }}"]' 21 | - role: install-k3s 22 | worker_node_count: 0 23 | - role: install-cpo-occm 24 | run_e2e: false 25 | - role: install-helm 26 | - role: install-csi-manila 27 | environment: 28 | GOPATH: '{{ ansible_user_dir }}' 29 | PATH: '/usr/local/go/bin:{{ ansible_user_dir }}/bin:{{ ansible_env.PATH }}' 30 | KUBECONFIG: '{{ ansible_user_dir }}/.kube/config' 31 | -------------------------------------------------------------------------------- /tests/playbooks/test-occm-e2e.yaml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | become: true 3 | become_method: sudo 4 | gather_facts: true 5 | 6 | vars: 7 | user: stack 8 | devstack_workdir: /home/{{ user }}/devstack 9 | octavia_provider: "" 10 | 11 | roles: 12 | - role: install-golang 13 | - role: install-devstack 14 | enable_services: 15 | - nova 16 | - glance 17 | - cinder 18 | - neutron 19 | - octavia 20 | - ovn-octavia 21 | - barbican 22 | - role: install-docker 23 | - role: install-docker-registry 24 | cert_hosts: ' ["{{ ansible_default_ipv4.address }}"]' 25 | - role: install-k3s 26 | worker_node_count: 0 27 | - role: install-cpo-occm 28 | run_e2e: "{{ run_e2e }}" 29 | octavia_provider: "{{ octavia_provider }}" 30 | -------------------------------------------------------------------------------- /tests/sanity/cinder/fakemetadata.go: -------------------------------------------------------------------------------- 1 | package sanity 2 | 3 | import "k8s.io/cloud-provider-openstack/pkg/csi/cinder" 4 | 5 | type fakemetadata struct { 6 | } 7 | 8 | // fake metadata 9 | 10 | func (m *fakemetadata) GetInstanceID() (string, error) { 11 | return cinder.FakeInstanceID, nil 12 | } 13 | 14 | func (m *fakemetadata) GetAvailabilityZone() (string, error) { 15 | return cinder.FakeAvailability, nil 16 | } 17 | -------------------------------------------------------------------------------- /tests/sanity/cinder/fakemount.go: -------------------------------------------------------------------------------- 1 | package sanity 2 | 3 | import ( 4 | "k8s.io/cloud-provider-openstack/pkg/csi/cinder" 5 | cpomount "k8s.io/cloud-provider-openstack/pkg/util/mount" 6 | "k8s.io/mount-utils" 7 | exec "k8s.io/utils/exec/testing" 8 | ) 9 | 10 | type fakemount struct { 11 | BaseMounter *mount.SafeFormatAndMount 12 | } 13 | 14 | var _ cpomount.IMount = &fakemount{} 15 | var ( 16 | fakeMounter = &mount.FakeMounter{MountPoints: []mount.MountPoint{}} 17 | fakeExec = &exec.FakeExec{DisableScripts: true} 18 | mounter = &cpomount.Mount{BaseMounter: newFakeSafeFormatAndMounter()} 19 | ) 20 | 21 | // GetFakeMountProvider returns fake instance of Mounter 22 | func GetFakeMountProvider() cpomount.IMount { 23 | return &fakemount{BaseMounter: newFakeSafeFormatAndMounter()} 24 | } 25 | 26 | // NewFakeSafeFormatAndMounter returns base Fake mounter instance 27 | func newFakeSafeFormatAndMounter() *mount.SafeFormatAndMount { 28 | return &mount.SafeFormatAndMount{ 29 | Interface: fakeMounter, 30 | Exec: fakeExec, 31 | } 32 | } 33 | 34 | func (m *fakemount) Mounter() *mount.SafeFormatAndMount { 35 | return m.BaseMounter 36 | } 37 | 38 | func (m *fakemount) ScanForAttach(devicePath string) error { 39 | return nil 40 | } 41 | 42 | func (m *fakemount) IsLikelyNotMountPointAttach(targetpath string) (bool, error) { 43 | return mounter.IsLikelyNotMountPointAttach(targetpath) 44 | } 45 | 46 | func (m *fakemount) UnmountPath(mountPath string) error { 47 | return mounter.UnmountPath(mountPath) 48 | } 49 | 50 | func (m *fakemount) GetInstanceID() (string, error) { 51 | return cinder.FakeInstanceID, nil 52 | } 53 | 54 | func (m *fakemount) GetDevicePath(volumeID string) (string, error) { 55 | return cinder.FakeDevicePath, nil 56 | } 57 | 58 | func (m *fakemount) MakeDir(pathname string) error { 59 | return nil 60 | } 61 | 62 | // MakeFile creates an empty file 63 | func (m *fakemount) MakeFile(pathname string) error { 64 | return nil 65 | } 66 | 67 | func (m *fakemount) GetDeviceStats(path string) (*cpomount.DeviceStats, error) { 68 | return cinder.FakeFsStats, nil 69 | } 70 | 71 | func (m *fakemount) GetMountFs(pathname string) ([]byte, error) { 72 | return []byte("aaa"), nil 73 | } 74 | -------------------------------------------------------------------------------- /tests/sanity/cinder/sanity_test.go: -------------------------------------------------------------------------------- 1 | package sanity 2 | 3 | import ( 4 | "os" 5 | "path" 6 | "testing" 7 | 8 | "github.com/kubernetes-csi/csi-test/v5/pkg/sanity" 9 | "k8s.io/cloud-provider-openstack/pkg/csi/cinder" 10 | "k8s.io/cloud-provider-openstack/pkg/csi/cinder/openstack" 11 | ) 12 | 13 | // start sanity test for driver 14 | func TestDriver(t *testing.T) { 15 | basePath := os.TempDir() 16 | defer os.Remove(basePath) 17 | 18 | socket := path.Join(basePath, "csi.sock") 19 | endpoint := "unix://" + socket 20 | cluster := "kubernetes" 21 | 22 | d := cinder.NewDriver(&cinder.DriverOpts{Endpoint: endpoint, ClusterID: cluster, WithTopology: true}) 23 | 24 | fakecloudprovider := getfakecloud() 25 | openstack.OsInstances = map[string]openstack.IOpenStack{ 26 | "": fakecloudprovider, 27 | } 28 | 29 | fakemnt := GetFakeMountProvider() 30 | fakemeta := &fakemetadata{} 31 | fakeOpts := openstack.BlockStorageOpts{ 32 | RescanOnResize: false, 33 | NodeVolumeAttachLimit: 200, 34 | } 35 | 36 | d.SetupControllerService(openstack.OsInstances) 37 | d.SetupNodeService(fakemnt, fakemeta, fakeOpts, map[string]string{}) 38 | 39 | // TODO: Stop call 40 | 41 | go d.Run() 42 | 43 | config := sanity.NewTestConfig() 44 | config.Address = endpoint 45 | sanity.Test(t, config) 46 | } 47 | -------------------------------------------------------------------------------- /tests/sanity/manila/fake-secrets.yaml: -------------------------------------------------------------------------------- 1 | CreateVolumeSecret: 2 | os-authURL: fake-url 3 | os-region: fake-region 4 | os-userID: fake-user-id 5 | os-password: fake-password 6 | os-domainID: fake-domain-id 7 | os-projectID: fake-project-id 8 | DeleteVolumeSecret: 9 | os-authURL: fake-url 10 | os-region: fake-region 11 | os-userID: fake-user-id 12 | os-password: fake-password 13 | os-domainID: fake-domain-id 14 | os-projectID: fake-project-id 15 | CreateSnapshotSecret: 16 | os-authURL: fake-url 17 | os-region: fake-region 18 | os-userID: fake-user-id 19 | os-password: fake-password 20 | os-domainID: fake-domain-id 21 | os-projectID: fake-project-id 22 | DeleteSnapshotSecret: 23 | os-authURL: fake-url 24 | os-region: fake-region 25 | os-userID: fake-user-id 26 | os-password: fake-password 27 | os-domainID: fake-domain-id 28 | os-projectID: fake-project-id 29 | ControllerValidateVolumeCapabilitiesSecret: 30 | os-authURL: fake-url 31 | os-region: fake-region 32 | os-userID: fake-user-id 33 | os-password: fake-password 34 | os-domainID: fake-domain-id 35 | os-projectID: fake-project-id 36 | ControllerExpandVolumeSecret: 37 | os-authURL: fake-url 38 | os-region: fake-region 39 | os-userID: fake-user-id 40 | os-password: fake-password 41 | os-domainID: fake-domain-id 42 | os-projectID: fake-project-id 43 | NodeStageVolumeSecret: 44 | os-authURL: fake-url 45 | os-region: fake-region 46 | os-userID: fake-user-id 47 | os-password: fake-password 48 | os-domainID: fake-domain-id 49 | os-projectID: fake-project-id 50 | NodePublishVolumeSecret: 51 | os-authURL: fake-url 52 | os-region: fake-region 53 | os-userID: fake-user-id 54 | os-password: fake-password 55 | os-domainID: fake-domain-id 56 | os-projectID: fake-project-id 57 | -------------------------------------------------------------------------------- /tests/sanity/manila/fakemetadata.go: -------------------------------------------------------------------------------- 1 | package sanity 2 | 3 | var FakeInstanceID = "321a8b81-3660-43e5-bab8-6470b65ee4e8" 4 | var FakeAvailability = "fake-az" 5 | 6 | type fakemetadata struct{} 7 | 8 | // fake metadata 9 | 10 | func (m *fakemetadata) GetInstanceID() (string, error) { 11 | return FakeInstanceID, nil 12 | } 13 | 14 | func (m *fakemetadata) GetAvailabilityZone() (string, error) { 15 | return FakeAvailability, nil 16 | } 17 | -------------------------------------------------------------------------------- /tests/sanity/manila/sanity_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 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 sanity 18 | 19 | import ( 20 | "os" 21 | "path" 22 | "testing" 23 | 24 | "github.com/kubernetes-csi/csi-test/v5/pkg/sanity" 25 | "k8s.io/cloud-provider-openstack/pkg/csi/manila" 26 | ) 27 | 28 | func TestDriver(t *testing.T) { 29 | basePath := os.TempDir() 30 | defer os.Remove(basePath) 31 | 32 | endpoint := path.Join(basePath, "csi.sock") 33 | fwdEndpoint := "unix:///fake-fwd-endpoint" 34 | 35 | d, err := manila.NewDriver( 36 | &manila.DriverOpts{ 37 | DriverName: "fake.manila.csi.openstack.org", 38 | WithTopology: true, 39 | ShareProto: "NFS", 40 | ServerCSIEndpoint: endpoint, 41 | FwdCSIEndpoint: fwdEndpoint, 42 | ManilaClientBuilder: &fakeManilaClientBuilder{}, 43 | CSIClientBuilder: &fakeCSIClientBuilder{}, 44 | }, 45 | ) 46 | if err != nil { 47 | t.Fatalf("Failed to initialize CSI Manila driver: %v", err) 48 | } 49 | 50 | err = d.SetupControllerService() 51 | if err != nil { 52 | t.Fatalf("Failed to initialize CSI Manila controller service: %v", err) 53 | } 54 | 55 | fakemeta := &fakemetadata{} 56 | 57 | err = d.SetupNodeService(fakemeta) 58 | if err != nil { 59 | t.Fatalf("Failed to initialize CSI Manila node service: %v", err) 60 | } 61 | 62 | go d.Run() 63 | 64 | config := sanity.NewTestConfig() 65 | config.Address = endpoint 66 | config.SecretsFile = "fake-secrets.yaml" 67 | sanity.Test(t, config) 68 | 69 | } 70 | -------------------------------------------------------------------------------- /tools/csi-deps-check.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright 2022 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | 19 | # We will check all necessary utils in the image. 20 | # They all have to launch without errors. 21 | 22 | # This utils are using by 23 | # go mod k8s.io/mount-utils 24 | /bin/mount -V 25 | /bin/umount -V 26 | /sbin/blkid -V 27 | /sbin/blockdev -V 28 | /sbin/dumpe2fs -V 29 | /sbin/fsck --version 30 | /sbin/mke2fs -V 31 | /sbin/mkfs.ext4 -V 32 | /sbin/mkfs.xfs -V 33 | /usr/sbin/xfs_io -V 34 | /sbin/xfs_repair -V 35 | /usr/sbin/xfs_growfs -V 36 | /bin/btrfs --version 37 | 38 | # This utils are using by 39 | # go mod k8s.io/cloud-provider-openstack/pkg/util/mount 40 | /bin/udevadm --version 41 | /bin/findmnt -V 42 | -------------------------------------------------------------------------------- /tools/install-distro-packages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xe 2 | 3 | BASE_DIR=$(cd $(dirname $BASH_SOURCE)/.. && pwd) 4 | 5 | # Local version to install bindep packages 6 | # Suitable for use for development 7 | 8 | function is_fedora { 9 | [ -f /usr/bin/yum ] && cat /etc/*release | grep -q -e "Fedora" 10 | } 11 | 12 | PACKAGES="" 13 | if ! which virtualenv; then 14 | PACKAGES="$PACKAGES virtualenv" 15 | fi 16 | if ! which make; then 17 | PACKAGES="$PACKAGES make" 18 | fi 19 | if [[ -n $PACKAGES ]]; then 20 | sudo apt-get -q --assume-yes install $PACKAGES 21 | fi 22 | 23 | # Check for bindep 24 | if ! which bindep; then 25 | pushd $BASE_DIR >/dev/null 26 | make bindep 27 | popd >/dev/null 28 | fi 29 | 30 | PACKAGES=$(make bindep || true) 31 | 32 | # inspired from project-config install-distro-packages.sh 33 | if apt-get -v >/dev/null 2>&1 ; then 34 | sudo apt-get -qq update 35 | sudo PATH=/usr/sbin:/sbin:$PATH DEBIAN_FRONTEND=noninteractive \ 36 | apt-get -q --option "Dpkg::Options::=--force-confold" \ 37 | --assume-yes install $PACKAGES 38 | elif emerge --version >/dev/null 2>&1 ; then 39 | sudo emerge -uDNq --jobs=4 @world 40 | sudo PATH=/usr/sbin:/sbin:$PATH emerge -q --jobs=4 $PACKAGES 41 | else 42 | is_fedora && YUM=dnf || YUM=yum 43 | sudo PATH=/usr/sbin:/sbin:$PATH $YUM install -y $PACKAGES 44 | fi 45 | -------------------------------------------------------------------------------- /tools/test-setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -xe 2 | # test-setup.sh - Install required stuffs 3 | # Used in both CI jobs and locally 4 | # 5 | # Install the following tools: 6 | # * dep 7 | 8 | # Get OS 9 | case $(uname -s) in 10 | Darwin) 11 | OS=darwin 12 | ;; 13 | Linux) 14 | if LSB_RELEASE=$(which lsb_release); then 15 | OS=$($LSB_RELEASE -s -c) 16 | else 17 | # No lsb-release, try a hack or two 18 | if which dpkg 1>/dev/null; then 19 | OS=debian 20 | elif which yum 1>/dev/null || which dnf 1>/dev/null; then 21 | OS=redhat 22 | else 23 | echo "Linux distro not yet supported" 24 | exit 1 25 | fi 26 | fi 27 | ;; 28 | *) 29 | echo "Unsupported OS" 30 | exit 1 31 | ;; 32 | esac 33 | 34 | case $OS in 35 | darwin) 36 | if which brew 1>/dev/null; then 37 | if ! which dep 1>/dev/null; then 38 | brew install dep 39 | fi 40 | else 41 | curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh 42 | fi 43 | ;; 44 | xenial|zesty) 45 | APT_GET="DEBIAN_FRONTEND=noninteractive \ 46 | apt-get -q --option "Dpkg::Options::=--force-confold" \ 47 | --assume-yes" 48 | if ! which add-apt-repository 1>/dev/null; then 49 | sudo $APT_GET install software-properties-common 50 | fi 51 | sudo add-apt-repository --yes ppa:gophers/archive 52 | sudo apt-get update && sudo $APT_GET install golang-1.9-go 53 | sudo ln -sf /usr/lib/go-1.9/bin/go /usr/local/bin 54 | sudo ln -sf /usr/lib/go-1.9/bin/gofmt /usr/local/bin 55 | curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh 56 | ;; 57 | esac 58 | --------------------------------------------------------------------------------