Merge pull request #348 from red-hat-storage/sync_ds--devel

Syncing latest changes from devel for ceph-csi
This commit is contained in:
openshift-merge-bot[bot] 2024-07-29 07:15:37 +00:00 committed by GitHub
commit c3338b3430
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
39 changed files with 2334 additions and 289 deletions

View File

@ -6,7 +6,7 @@ require (
github.com/ghodss/yaml v1.0.0
github.com/openshift/api v0.0.0-20240115183315-0793e918179d
github.com/stretchr/testify v1.9.0
k8s.io/api v0.30.2
k8s.io/api v0.30.3
)
require (
@ -23,7 +23,7 @@ require (
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apimachinery v0.30.2 // indirect
k8s.io/apimachinery v0.30.3 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect

View File

@ -79,10 +79,10 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.30.2 h1:+ZhRj+28QT4UOH+BKznu4CBgPWgkXO7XAvMcMl0qKvI=
k8s.io/api v0.30.2/go.mod h1:ULg5g9JvOev2dG0u2hig4Z7tQ2hHIuS+m8MNZ+X6EmI=
k8s.io/apimachinery v0.30.2 h1:fEMcnBj6qkzzPGSVsAZtQThU62SmQ4ZymlXRC5yFSCg=
k8s.io/apimachinery v0.30.2/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/api v0.30.3 h1:ImHwK9DCsPA9uoU3rVh4QHAHHK5dTSv1nxJUapx8hoQ=
k8s.io/api v0.30.3/go.mod h1:GPc8jlzoe5JG3pb0KJCSLX5oAFIW3/qNJITlDj8BH04=
k8s.io/apimachinery v0.30.3 h1:q1laaWCmrszyQuSQCfNB8cFgCuDAoPszKY4ucAjDwHc=
k8s.io/apimachinery v0.30.3/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=

View File

@ -55,12 +55,12 @@ gopkg.in/yaml.v2
# gopkg.in/yaml.v3 v3.0.1
## explicit
gopkg.in/yaml.v3
# k8s.io/api v0.30.2
# k8s.io/api v0.30.3
## explicit; go 1.22.0
k8s.io/api/core/v1
k8s.io/api/rbac/v1
k8s.io/api/storage/v1
# k8s.io/apimachinery v0.30.2
# k8s.io/apimachinery v0.30.3
## explicit; go 1.22.0
k8s.io/apimachinery/pkg/api/resource
k8s.io/apimachinery/pkg/apis/meta/v1

View File

@ -18,14 +18,14 @@ the code and will be pointed out in the review process:
### Imports
We use the following convention for specifying imports:
We prefer the following convention for specifying imports:
```
<import standard library packages>
<import ceph-csi packages>
<import third-party packages>
<import ceph-csi packages>
```
Example:
@ -37,9 +37,9 @@ import (
"strings"
"time"
"github.com/ceph/ceph-csi/internal/util"
"github.com/pborman/uuid"
"github.com/ceph/ceph-csi/internal/util"
)
```

80
go.mod
View File

@ -4,12 +4,12 @@ go 1.22.0
require (
github.com/IBM/keyprotect-go-client v0.14.3
github.com/aws/aws-sdk-go v1.54.19
github.com/aws/aws-sdk-go v1.55.0
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3
github.com/ceph/ceph-csi/api v0.0.0-00010101000000-000000000000
github.com/ceph/go-ceph v0.28.0
github.com/container-storage-interface/spec v1.10.0
github.com/csi-addons/spec v0.2.1-0.20240627093359-0dd74d521e67
github.com/csi-addons/spec v0.2.1-0.20240718113938-dc98b454ba65
github.com/gemalto/kmip-go v0.0.10
github.com/golang/protobuf v1.5.4
github.com/google/fscrypt v0.3.6-0.20240502174735-068b9f8f5dec
@ -22,7 +22,7 @@ require (
github.com/libopenstorage/secrets v0.0.0-20231011182615-5f4b25ceede1
github.com/onsi/ginkgo/v2 v2.19.0
github.com/onsi/gomega v1.33.1
github.com/pkg/xattr v0.4.9
github.com/pkg/xattr v0.4.10
github.com/prometheus/client_golang v1.19.1
github.com/stretchr/testify v1.9.0
golang.org/x/crypto v0.25.0
@ -33,14 +33,14 @@ require (
//
// when updating k8s.io/kubernetes, make sure to update the replace section too
//
k8s.io/api v0.30.2
k8s.io/apimachinery v0.30.2
k8s.io/api v0.30.3
k8s.io/apimachinery v0.30.3
k8s.io/client-go v12.0.0+incompatible
k8s.io/cloud-provider v0.30.2
k8s.io/cloud-provider v0.30.3
k8s.io/klog/v2 v2.130.1
k8s.io/kubernetes v1.30.2
k8s.io/mount-utils v0.30.2
k8s.io/pod-security-admission v0.30.2
k8s.io/kubernetes v1.30.3
k8s.io/mount-utils v0.30.3
k8s.io/pod-security-admission v0.30.3
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
sigs.k8s.io/controller-runtime v0.18.4
)
@ -172,11 +172,11 @@ require (
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.30.1 // indirect
k8s.io/apiserver v0.30.2 // indirect
k8s.io/component-base v0.30.2 // indirect
k8s.io/component-helpers v0.30.2 // indirect
k8s.io/controller-manager v0.30.2 // indirect
k8s.io/kms v0.30.2 // indirect
k8s.io/apiserver v0.30.3 // indirect
k8s.io/component-base v0.30.3 // indirect
k8s.io/component-helpers v0.30.3 // indirect
k8s.io/controller-manager v0.30.3 // indirect
k8s.io/kms v0.30.3 // indirect
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
k8s.io/kubectl v0.0.0 // indirect
k8s.io/kubelet v0.0.0 // indirect
@ -204,35 +204,35 @@ replace (
//
// k8s.io/kubernetes depends on these k8s.io packages, but unversioned
//
k8s.io/api => k8s.io/api v0.30.2
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.30.2
k8s.io/apimachinery => k8s.io/apimachinery v0.30.2
k8s.io/apiserver => k8s.io/apiserver v0.30.2
k8s.io/cli-runtime => k8s.io/cli-runtime v0.30.2
k8s.io/client-go => k8s.io/client-go v0.30.2
k8s.io/cloud-provider => k8s.io/cloud-provider v0.30.2
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.30.2
k8s.io/code-generator => k8s.io/code-generator v0.30.2
k8s.io/component-base => k8s.io/component-base v0.30.2
k8s.io/component-helpers => k8s.io/component-helpers v0.30.2
k8s.io/controller-manager => k8s.io/controller-manager v0.30.2
k8s.io/cri-api => k8s.io/cri-api v0.30.2
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.30.2
k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.30.2
k8s.io/endpointslice => k8s.io/endpointslice v0.30.2
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.30.2
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.30.2
k8s.io/kube-proxy => k8s.io/kube-proxy v0.30.2
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.30.2
k8s.io/kubectl => k8s.io/kubectl v0.30.2
k8s.io/kubelet => k8s.io/kubelet v0.30.2
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.30.2
k8s.io/metrics => k8s.io/metrics v0.30.2
k8s.io/api => k8s.io/api v0.30.3
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.30.3
k8s.io/apimachinery => k8s.io/apimachinery v0.30.3
k8s.io/apiserver => k8s.io/apiserver v0.30.3
k8s.io/cli-runtime => k8s.io/cli-runtime v0.30.3
k8s.io/client-go => k8s.io/client-go v0.30.3
k8s.io/cloud-provider => k8s.io/cloud-provider v0.30.3
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.30.3
k8s.io/code-generator => k8s.io/code-generator v0.30.3
k8s.io/component-base => k8s.io/component-base v0.30.3
k8s.io/component-helpers => k8s.io/component-helpers v0.30.3
k8s.io/controller-manager => k8s.io/controller-manager v0.30.3
k8s.io/cri-api => k8s.io/cri-api v0.30.3
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.30.3
k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.30.3
k8s.io/endpointslice => k8s.io/endpointslice v0.30.3
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.30.3
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.30.3
k8s.io/kube-proxy => k8s.io/kube-proxy v0.30.3
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.30.3
k8s.io/kubectl => k8s.io/kubectl v0.30.3
k8s.io/kubelet => k8s.io/kubelet v0.30.3
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.30.3
k8s.io/metrics => k8s.io/metrics v0.30.3
// TODO: replace with latest once https://github.com/ceph/ceph-csi/issues/4633 is fixed
k8s.io/mount-utils => k8s.io/mount-utils v0.29.3
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.30.2
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.30.2
k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.30.3
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.30.3
// layeh.com seems to be misbehaving
layeh.com/radius => github.com/layeh/radius v0.0.0-20190322222518-890bc1058917
)

74
go.sum
View File

@ -828,8 +828,8 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkY
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/aws/aws-sdk-go v1.44.164/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.54.19 h1:tyWV+07jagrNiCcGRzRhdtVjQs7Vy41NwsuOcl0IbVI=
github.com/aws/aws-sdk-go v1.54.19/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
github.com/aws/aws-sdk-go v1.55.0 h1:hVALKPjXz33kP1R9nTyJpUK7qF59dO2mleQxUW9mCVE=
github.com/aws/aws-sdk-go v1.55.0/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
github.com/aws/aws-sdk-go-v2 v1.30.3 h1:jUeBtG0Ih+ZIFH0F4UkmL9w3cSpaMv9tYYDbzILP8dY=
github.com/aws/aws-sdk-go-v2 v1.30.3/go.mod h1:nIQjQVp5sfpQcTc9mPSr1B0PaWK5ByX9MOoDadSN4lc=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 h1:SoNJ4RlFEQEbtDcCEt+QG56MY4fm4W8rYirAmq+/DdU=
@ -911,8 +911,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4=
github.com/csi-addons/spec v0.2.1-0.20240627093359-0dd74d521e67 h1:UAcAhE1pTkWaFBS0kvhHUcUsoEv5fsieD0tl8psQMCs=
github.com/csi-addons/spec v0.2.1-0.20240627093359-0dd74d521e67/go.mod h1:Mwq4iLiUV4s+K1bszcWU6aMsR5KPsbIYzzszJ6+56vI=
github.com/csi-addons/spec v0.2.1-0.20240718113938-dc98b454ba65 h1:i9JGGQTEmRQXSpQQPR96+DV4D4o+V1+gjAWf+bpxQxk=
github.com/csi-addons/spec v0.2.1-0.20240718113938-dc98b454ba65/go.mod h1:Mwq4iLiUV4s+K1bszcWU6aMsR5KPsbIYzzszJ6+56vI=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
@ -1481,8 +1481,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
github.com/pkg/xattr v0.4.9 h1:5883YPCtkSd8LFbs13nXplj9g9tlrwoJRjgpgMu1/fE=
github.com/pkg/xattr v0.4.9/go.mod h1:di8WF84zAKk8jzR1UBTEWh9AUlIZZ7M/JNt8e9B6ktU=
github.com/pkg/xattr v0.4.10 h1:Qe0mtiNFHQZ296vRgUjRCoPHPqH7VdTOrZx3g0T+pGA=
github.com/pkg/xattr v0.4.10/go.mod h1:di8WF84zAKk8jzR1UBTEWh9AUlIZZ7M/JNt8e9B6ktU=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@ -2552,27 +2552,27 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
k8s.io/api v0.30.2 h1:+ZhRj+28QT4UOH+BKznu4CBgPWgkXO7XAvMcMl0qKvI=
k8s.io/api v0.30.2/go.mod h1:ULg5g9JvOev2dG0u2hig4Z7tQ2hHIuS+m8MNZ+X6EmI=
k8s.io/apiextensions-apiserver v0.30.2 h1:l7Eue2t6QiLHErfn2vwK4KgF4NeDgjQkCXtEbOocKIE=
k8s.io/apiextensions-apiserver v0.30.2/go.mod h1:lsJFLYyK40iguuinsb3nt+Sj6CmodSI4ACDLep1rgjw=
k8s.io/apimachinery v0.30.2 h1:fEMcnBj6qkzzPGSVsAZtQThU62SmQ4ZymlXRC5yFSCg=
k8s.io/apimachinery v0.30.2/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/apiserver v0.30.2 h1:ACouHiYl1yFI2VFI3YGM+lvxgy6ir4yK2oLOsLI1/tw=
k8s.io/apiserver v0.30.2/go.mod h1:BOTdFBIch9Sv0ypSEcUR6ew/NUFGocRFNl72Ra7wTm8=
k8s.io/client-go v0.30.2 h1:sBIVJdojUNPDU/jObC+18tXWcTJVcwyqS9diGdWHk50=
k8s.io/client-go v0.30.2/go.mod h1:JglKSWULm9xlJLx4KCkfLLQ7XwtlbflV6uFFSHTMgVs=
k8s.io/cloud-provider v0.30.2 h1:yov6r02v7sMUNNvzEz51LtL2krn2c1wsC+dy/8BxKQI=
k8s.io/cloud-provider v0.30.2/go.mod h1:w69t2dSjDtI9BYK6SEqj6HmMKIojEk08fXRoUzjFN2I=
k8s.io/code-generator v0.30.2/go.mod h1:RQP5L67QxqgkVquk704CyvWFIq0e6RCMmLTXxjE8dVA=
k8s.io/component-base v0.30.2 h1:pqGBczYoW1sno8q9ObExUqrYSKhtE5rW3y6gX88GZII=
k8s.io/component-base v0.30.2/go.mod h1:yQLkQDrkK8J6NtP+MGJOws+/PPeEXNpwFixsUI7h/OE=
k8s.io/component-helpers v0.30.2 h1:kDMYLiWEYeWU7H6jBI+Ua1i2hqNh0DzqDHNIppFC3po=
k8s.io/component-helpers v0.30.2/go.mod h1:tI0anfS6AbRqooaICkGg7UVAQLedOauVSQW9srDBnJw=
k8s.io/controller-manager v0.30.2 h1:tC7V7IdGUW2I4de3bXx4m2fS3naP7VlCYlECCajK9fU=
k8s.io/controller-manager v0.30.2/go.mod h1:CYltIHGhCgldEkXT5vS2JHCCWM1WyBI4kA2UfP9cZvY=
k8s.io/csi-translation-lib v0.30.2 h1:ZcFVMWDHg7feW3mtdl+xClgmw1Yxv7m9ysOKt8h3K8Y=
k8s.io/csi-translation-lib v0.30.2/go.mod h1:jFT8vquP6eSDUwDHk0mKT6uKFWlZp60ecUEUhmlGsOY=
k8s.io/api v0.30.3 h1:ImHwK9DCsPA9uoU3rVh4QHAHHK5dTSv1nxJUapx8hoQ=
k8s.io/api v0.30.3/go.mod h1:GPc8jlzoe5JG3pb0KJCSLX5oAFIW3/qNJITlDj8BH04=
k8s.io/apiextensions-apiserver v0.30.3 h1:oChu5li2vsZHx2IvnGP3ah8Nj3KyqG3kRSaKmijhB9U=
k8s.io/apiextensions-apiserver v0.30.3/go.mod h1:uhXxYDkMAvl6CJw4lrDN4CPbONkF3+XL9cacCT44kV4=
k8s.io/apimachinery v0.30.3 h1:q1laaWCmrszyQuSQCfNB8cFgCuDAoPszKY4ucAjDwHc=
k8s.io/apimachinery v0.30.3/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/apiserver v0.30.3 h1:QZJndA9k2MjFqpnyYv/PH+9PE0SHhx3hBho4X0vE65g=
k8s.io/apiserver v0.30.3/go.mod h1:6Oa88y1CZqnzetd2JdepO0UXzQX4ZnOekx2/PtEjrOg=
k8s.io/client-go v0.30.3 h1:bHrJu3xQZNXIi8/MoxYtZBBWQQXwy16zqJwloXXfD3k=
k8s.io/client-go v0.30.3/go.mod h1:8d4pf8vYu665/kUbsxWAQ/JDBNWqfFeZnvFiVdmx89U=
k8s.io/cloud-provider v0.30.3 h1:SNWZmllTymOTzIPJuhtZH6il/qVi75dQARRQAm9k6VY=
k8s.io/cloud-provider v0.30.3/go.mod h1:Ax0AVdHnM7tMYnJH1Ycy4SMBD98+4zA+tboUR9eYsY8=
k8s.io/code-generator v0.30.3/go.mod h1:PFgBiv+miFV7TZYp+RXgROkhA+sWYZ+mtpbMLofMke8=
k8s.io/component-base v0.30.3 h1:Ci0UqKWf4oiwy8hr1+E3dsnliKnkMLZMVbWzeorlk7s=
k8s.io/component-base v0.30.3/go.mod h1:C1SshT3rGPCuNtBs14RmVD2xW0EhRSeLvBh7AGk1quA=
k8s.io/component-helpers v0.30.3 h1:KPc8l0eGx9Wg2OcKc58k9ozNcVcOInAi3NGiuS2xJ/c=
k8s.io/component-helpers v0.30.3/go.mod h1:VOQ7g3q+YbKWwKeACG2BwPv4ftaN8jXYJ5U3xpzuYAE=
k8s.io/controller-manager v0.30.3 h1:QRFGkWWD5gi/KCSU0qxyUoZRbt+BKgiCUXiTD1RO95w=
k8s.io/controller-manager v0.30.3/go.mod h1:F95rjHCOH2WwV9XlVxRo71CtddKLhF3FzE+s1lc7E/0=
k8s.io/csi-translation-lib v0.30.3 h1:wBaPWnOi14/vANRIrp8pmbdx/Pgz2QRcroH7wkodezc=
k8s.io/csi-translation-lib v0.30.3/go.mod h1:3AizNZbDttVDH1RO0x1yGEQP74e9Xbfb60IBP1oWO1o=
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70/go.mod h1:VH3AT8AaQOqiGjMF9p0/IM1Dj+82ZwjfxUP1IxaHE+8=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
@ -2583,22 +2583,22 @@ k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kms v0.30.2 h1:VSZILO/tkzrz5Tu2j+yFQZ2Dc5JerQZX2GqhFJbQrfw=
k8s.io/kms v0.30.2/go.mod h1:GrMurD0qk3G4yNgGcsCEmepqf9KyyIrTXYR2lyUOJC4=
k8s.io/kms v0.30.3 h1:NLg+oN45S2Y3U0WiLRzbS61AY/XrS5JBMZp531Z+Pho=
k8s.io/kms v0.30.3/go.mod h1:GrMurD0qk3G4yNgGcsCEmepqf9KyyIrTXYR2lyUOJC4=
k8s.io/kube-openapi v0.0.0-20180731170545-e3762e86a74c/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc=
k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280/go.mod h1:+Axhij7bCpeqhklhUTe3xmOn6bWxolyZEeyaFpjGtl4=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
k8s.io/kubectl v0.30.2 h1:cgKNIvsOiufgcs4yjvgkK0+aPCfa8pUwzXdJtkbhsH8=
k8s.io/kubectl v0.30.2/go.mod h1:rz7GHXaxwnigrqob0lJsiA07Df8RE3n1TSaC2CTeuB4=
k8s.io/kubelet v0.30.2 h1:Ck4E/pHndI20IzDXxS57dElhDGASPO5pzXF7BcKfmCY=
k8s.io/kubelet v0.30.2/go.mod h1:DSwwTbLQmdNkebAU7ypIALR4P9aXZNFwgRmedojUE94=
k8s.io/kubernetes v1.30.2 h1:11WhS78OYX/lnSy6TXxPO6Hk+E5K9ZNrEsk9JgMSX8I=
k8s.io/kubernetes v1.30.2/go.mod h1:yPbIk3MhmhGigX62FLJm+CphNtjxqCvAIFQXup6RKS0=
k8s.io/kubectl v0.30.3 h1:YIBBvMdTW0xcDpmrOBzcpUVsn+zOgjMYIu7kAq+yqiI=
k8s.io/kubectl v0.30.3/go.mod h1:IcR0I9RN2+zzTRUa1BzZCm4oM0NLOawE6RzlDvd1Fpo=
k8s.io/kubelet v0.30.3 h1:KvGWDdhzD0vEyDyGTCjsDc8D+0+lwRMw3fJbfQgF7ys=
k8s.io/kubelet v0.30.3/go.mod h1:D9or45Vkzcqg55CEiqZ8dVbwP3Ksj7DruEVRS9oq3Ys=
k8s.io/kubernetes v1.30.3 h1:A0qoXI1YQNzrQZiff33y5zWxYHFT/HeZRK98/sRDJI0=
k8s.io/kubernetes v1.30.3/go.mod h1:yPbIk3MhmhGigX62FLJm+CphNtjxqCvAIFQXup6RKS0=
k8s.io/mount-utils v0.29.3 h1:iEcqPP7Vv8UClH8nnMfovtmy/04fIloRW9JuSXykoZ0=
k8s.io/mount-utils v0.29.3/go.mod h1:9IWJTMe8tG0MYMLEp60xK9GYVeCdA3g4LowmnVi+t9Y=
k8s.io/pod-security-admission v0.30.2 h1:UlHnkvvOr+rgQplOqD+SHzLUF8EgKIOCpDU8kaMeTQQ=
k8s.io/pod-security-admission v0.30.2/go.mod h1:gMUJUG9zOgNBk0VIz5BS7uIYiYPEoXkBSeHh6rG2m8c=
k8s.io/pod-security-admission v0.30.3 h1:UDGZWR3ry/XrN/Ki/w7qrp49OwgQsKyh+6xWbexvJi8=
k8s.io/pod-security-admission v0.30.3/go.mod h1:T1EQSOLl9YyDMnXNJfsq2jeci6uoymY0mrRkkKihd98=
k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=

View File

@ -151,7 +151,7 @@ func maybeUnlockFileEncryption(
}
defer ioctx.Destroy()
res, err := ioctx.LockExclusive(volOptions.VolID, lockName, lockCookie, lockDesc, lockDuration, &flags)
res, err := ioctx.LockExclusive(string(volID), lockName, lockCookie, lockDesc, lockDuration, &flags)
if res != 0 {
switch res {
case -int(syscall.EBUSY):
@ -164,13 +164,8 @@ func maybeUnlockFileEncryption(
}
log.DebugLog(ctx, "Lock successfully created for volume ID %s", volID)
log.DebugLog(ctx, "cephfs: unlocking fscrypt on volume %q path %s", volID, stagingTargetPath)
err = fscrypt.Unlock(ctx, volOptions.Encryption, stagingTargetPath, string(volID))
if err != nil {
return err
}
ret, err := ioctx.Unlock(string(volID), lockName, lockCookie)
defer func() {
ret, unlockErr := ioctx.Unlock(string(volID), lockName, lockCookie)
switch ret {
case 0:
log.DebugLog(ctx, "Lock %s successfully released ", lockName)
@ -178,7 +173,14 @@ func maybeUnlockFileEncryption(
log.DebugLog(ctx, "Lock is not held by the specified %s, %s pair", lockCookie, lockName)
default:
log.ErrorLog(ctx, "Failed to release following lock, this will lead to orphan lock %s: %v",
lockName, err)
lockName, unlockErr)
}
}()
log.DebugLog(ctx, "cephfs: unlocking fscrypt on volume %q path %s", volID, stagingTargetPath)
err = fscrypt.Unlock(ctx, volOptions.Encryption, stagingTargetPath, string(volID))
if err != nil {
return err
}
return nil

View File

@ -0,0 +1,101 @@
/*
Copyright 2024 The Ceph-CSI Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package rbd
import (
"context"
"errors"
csicommon "github.com/ceph/ceph-csi/internal/csi-common"
"github.com/ceph/ceph-csi/internal/rbd"
"github.com/ceph/ceph-csi/internal/util"
"github.com/ceph/ceph-csi/internal/util/log"
"github.com/container-storage-interface/spec/lib/go/csi"
ekr "github.com/csi-addons/spec/lib/go/encryptionkeyrotation"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type EncryptionKeyRotationServer struct {
*ekr.UnimplementedEncryptionKeyRotationControllerServer
volLock *util.VolumeLocks
}
func NewEncryptionKeyRotationServer(volLock *util.VolumeLocks) *EncryptionKeyRotationServer {
return &EncryptionKeyRotationServer{volLock: volLock}
}
func (ekrs *EncryptionKeyRotationServer) RegisterService(svc grpc.ServiceRegistrar) {
ekr.RegisterEncryptionKeyRotationControllerServer(svc, ekrs)
}
func (ekrs *EncryptionKeyRotationServer) EncryptionKeyRotate(
ctx context.Context,
req *ekr.EncryptionKeyRotateRequest,
) (*ekr.EncryptionKeyRotateResponse, error) {
// Get the volume ID from the request
volID := req.GetVolumeId()
if volID == "" {
return nil, status.Error(codes.InvalidArgument, "empty volume ID in request")
}
// Block key rotation for RWX/ROX volumes
_, isMultiNode := csicommon.IsBlockMultiNode([]*csi.VolumeCapability{req.GetVolumeCapability()})
if isMultiNode {
return nil, status.Error(codes.Unimplemented, "multi-node key rotation is not supported")
}
if acquired := ekrs.volLock.TryAcquire(volID); !acquired {
return nil, status.Errorf(codes.Aborted, util.VolumeOperationAlreadyExistsFmt, volID)
}
defer ekrs.volLock.Release(volID)
// Get the credentials required to authenticate
// against a ceph cluster
creds, err := util.NewUserCredentials(req.GetSecrets())
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}
defer creds.DeleteCredentials()
rbdVol, err := rbd.GenVolFromVolID(ctx, volID, creds, req.GetSecrets())
if err != nil {
switch {
case errors.Is(err, rbd.ErrImageNotFound):
err = status.Errorf(codes.NotFound, "volume ID %s not found", volID)
case errors.Is(err, util.ErrPoolNotFound):
log.ErrorLog(ctx, "failed to get backend volume for %s: %v", volID, err)
err = status.Errorf(codes.NotFound, err.Error())
default:
err = status.Errorf(codes.Internal, err.Error())
}
return nil, err
}
defer rbdVol.Destroy(ctx)
err = rbdVol.RotateEncryptionKey(ctx)
if err != nil {
return nil, status.Errorf(
codes.Internal, "failed to rotate the key for volume with ID %q: %s", volID, err.Error())
}
// Success
return &ekr.EncryptionKeyRotateResponse{}, nil
}

View File

@ -114,6 +114,12 @@ func (is *IdentityServer) GetCapabilities(
Type: identity.Capability_VolumeGroup_LIMIT_VOLUME_TO_ONE_VOLUME_GROUP,
},
},
}, &identity.Capability{
Type: &identity.Capability_VolumeGroup_{
VolumeGroup: &identity.Capability_VolumeGroup{
Type: identity.Capability_VolumeGroup_MODIFY_VOLUME_GROUP,
},
},
})
}
@ -133,6 +139,13 @@ func (is *IdentityServer) GetCapabilities(
Type: identity.Capability_ReclaimSpace_ONLINE,
},
},
},
&identity.Capability{
Type: &identity.Capability_EncryptionKeyRotation_{
EncryptionKeyRotation: &identity.Capability_EncryptionKeyRotation{
Type: identity.Capability_EncryptionKeyRotation_ENCRYPTIONKEYROTATION,
},
},
})
}

View File

@ -18,7 +18,7 @@ package rbd
import (
"context"
"fmt"
"slices"
"github.com/ceph/ceph-csi/internal/rbd"
"github.com/ceph/ceph-csi/internal/rbd/types"
@ -37,12 +37,17 @@ type VolumeGroupServer struct {
// if volumegroup spec add more RPC services in the proto file, then we
// don't need to add all RPC methods leading to forward compatibility.
*volumegroup.UnimplementedControllerServer
// csiID is the unique ID for this CSI-driver deployment.
csiID string
}
// NewVolumeGroupServer creates a new VolumeGroupServer which handles the
// VolumeGroup Service requests from the CSI-Addons specification.
func NewVolumeGroupServer() *VolumeGroupServer {
return &VolumeGroupServer{}
func NewVolumeGroupServer(instanceID string) *VolumeGroupServer {
return &VolumeGroupServer{
csiID: instanceID,
}
}
func (vs *VolumeGroupServer) RegisterService(server grpc.ServiceRegistrar) {
@ -77,7 +82,7 @@ func (vs *VolumeGroupServer) CreateVolumeGroup(
ctx context.Context,
req *volumegroup.CreateVolumeGroupRequest,
) (*volumegroup.CreateVolumeGroupResponse, error) {
mgr := rbd.NewManager(req.GetParameters(), req.GetSecrets())
mgr := rbd.NewManager(vs.csiID, req.GetParameters(), req.GetSecrets())
defer mgr.Destroy(ctx)
// resolve all volumes
@ -98,7 +103,7 @@ func (vs *VolumeGroupServer) CreateVolumeGroup(
volumes[i] = vol
}
log.DebugLog(ctx, fmt.Sprintf("all %d Volumes for VolumeGroup %q have been found", len(volumes), req.GetName()))
log.DebugLog(ctx, "all %d Volumes for VolumeGroup %q have been found", len(volumes), req.GetName())
// create a RBDVolumeGroup
vg, err := mgr.CreateVolumeGroup(ctx, req.GetName())
@ -110,7 +115,7 @@ func (vs *VolumeGroupServer) CreateVolumeGroup(
err.Error())
}
log.DebugLog(ctx, fmt.Sprintf("VolumeGroup %q had been created", req.GetName()))
log.DebugLog(ctx, "VolumeGroup %q has been created: %+v", req.GetName(), vg)
// add each rbd-image to the RBDVolumeGroup
for _, vol := range volumes {
@ -125,10 +130,19 @@ func (vs *VolumeGroupServer) CreateVolumeGroup(
}
}
log.DebugLog(ctx, fmt.Sprintf("all %d Volumes have been added to for VolumeGroup %q", len(volumes), req.GetName()))
log.DebugLog(ctx, "all %d Volumes have been added to for VolumeGroup %q", len(volumes), req.GetName())
csiVG, err := vg.ToCSI(ctx)
if err != nil {
return nil, status.Errorf(
codes.Internal,
"failed to convert volume group %q to CSI type: %s",
req.GetName(),
err.Error())
}
return &volumegroup.CreateVolumeGroupResponse{
VolumeGroup: vg.ToCSI(ctx),
VolumeGroup: csiVG,
}, nil
}
@ -154,7 +168,7 @@ func (vs *VolumeGroupServer) DeleteVolumeGroup(
ctx context.Context,
req *volumegroup.DeleteVolumeGroupRequest,
) (*volumegroup.DeleteVolumeGroupResponse, error) {
mgr := rbd.NewManager(nil, req.GetSecrets())
mgr := rbd.NewManager(vs.csiID, nil, req.GetSecrets())
defer mgr.Destroy(ctx)
// resolve the volume group
@ -168,7 +182,7 @@ func (vs *VolumeGroupServer) DeleteVolumeGroup(
}
defer vg.Destroy(ctx)
log.DebugLog(ctx, fmt.Sprintf("VolumeGroup %q has been found", req.GetVolumeGroupId()))
log.DebugLog(ctx, "VolumeGroup %q has been found", req.GetVolumeGroupId())
// verify that the volume group is empty
volumes, err := vg.ListVolumes(ctx)
@ -180,7 +194,7 @@ func (vs *VolumeGroupServer) DeleteVolumeGroup(
err.Error())
}
log.DebugLog(ctx, fmt.Sprintf("VolumeGroup %q contains %d volumes", req.GetVolumeGroupId(), len(volumes)))
log.DebugLog(ctx, "VolumeGroup %q contains %d volumes", req.GetVolumeGroupId(), len(volumes))
if len(volumes) != 0 {
return nil, status.Errorf(
@ -198,7 +212,154 @@ func (vs *VolumeGroupServer) DeleteVolumeGroup(
err.Error())
}
log.DebugLog(ctx, fmt.Sprintf("VolumeGroup %q has been deleted", req.GetVolumeGroupId()))
log.DebugLog(ctx, "VolumeGroup %q has been deleted", req.GetVolumeGroupId())
return &volumegroup.DeleteVolumeGroupResponse{}, nil
}
// ModifyVolumeGroupMembership RPC call to modify a volume group.
//
// From the spec:
// This RPC will be called by the CO to modify an existing volume group on
// behalf of a user. volume_ids provided in the
// ModifyVolumeGroupMembershipRequest will be compared to the ones in the
// existing volume group. New volume_ids in the modified volume group will be
// added to the volume group. Existing volume_ids not in the modified volume
// group will be removed from the volume group. If volume_ids is empty, the
// volume group will be removed of all existing volumes. This operation MUST be
// idempotent.
//
// File-based storage systems usually do not support this PRC. Block-based
// storage systems usually support this PRC.
//
// By adding an existing volume to a group, however, there is no way to pass in
// parameters to influence placement when provisioning a volume.
//
// It is out of the scope of the CSI spec to determine whether a group is
// consistent or not. It is up to the storage provider to clarify that in the
// vendor specific documentation. This is true either when creating a new
// volume with a group id or adding an existing volume to a group.
//
// CSI drivers supporting MODIFY_VOLUME_GROUP_MEMBERSHIP MUST implement
// ModifyVolumeGroupMembership RPC.
//
// Note:
//
// The implementation works as the following:
// - resolve the existing volume group
// - get the CSI-IDs of all volumes
// - create a list of volumes that should be removed
// - create a list of volume IDs that should be added
// - remove the volumes from the group
// - add the volumes to the group
//
// Also, MODIFY_VOLUME_GROUP_MEMBERSHIP does not exist, it is called
// MODIFY_VOLUME_GROUP instead.
func (vs *VolumeGroupServer) ModifyVolumeGroupMembership(
ctx context.Context,
req *volumegroup.ModifyVolumeGroupMembershipRequest,
) (*volumegroup.ModifyVolumeGroupMembershipResponse, error) {
mgr := rbd.NewManager(vs.csiID, nil, req.GetSecrets())
defer mgr.Destroy(ctx)
// resolve the volume group
vg, err := mgr.GetVolumeGroupByID(ctx, req.GetVolumeGroupId())
if err != nil {
return nil, status.Errorf(
codes.NotFound,
"could not find volume group %q: %s",
req.GetVolumeGroupId(),
err.Error())
}
defer vg.Destroy(ctx)
beforeVolumes, err := vg.ListVolumes(ctx)
if err != nil {
return nil, status.Errorf(
codes.Internal,
"failed to list volumes of volume group %q: %v",
vg,
err)
}
// beforeIDs contains the csiID as key, volume as value
beforeIDs := make(map[string]types.Volume, len(beforeVolumes))
for _, vol := range beforeVolumes {
id, idErr := vol.GetID(ctx)
if idErr != nil {
return nil, status.Errorf(
codes.InvalidArgument,
"failed to get the CSI ID of volume %q: %v",
vol,
err)
}
beforeIDs[id] = vol
}
// check which volumes should not be part of the group
afterIDs := req.GetVolumeIds()
toRemove := make([]string, 0)
for id := range beforeIDs {
if !slices.Contains(afterIDs, id) {
toRemove = append(toRemove, id)
}
}
// check which volumes are new to the group
toAdd := make([]string, 0)
for _, id := range afterIDs {
if _, ok := beforeIDs[id]; !ok {
toAdd = append(toAdd, id)
}
}
// remove the volume that should not be part of the group
for _, id := range toRemove {
vol := beforeIDs[id]
err = vg.RemoveVolume(ctx, vol)
if err != nil {
return nil, status.Errorf(
codes.Internal,
"failed to remove volume %q from volume group %q: %v",
vol,
vg,
err)
}
}
// add the new volumes to the group
for _, id := range toAdd {
vol, getErr := mgr.GetVolumeByID(ctx, id)
if getErr != nil {
return nil, status.Errorf(
codes.NotFound,
"failed to find a volume with CSI ID %q: %v",
id,
err)
}
err = vg.AddVolume(ctx, vol)
if err != nil {
return nil, status.Errorf(
codes.Internal,
"failed to add volume %q to volume group %q: %v",
vol,
vg,
err)
}
}
csiVG, err := vg.ToCSI(ctx)
if err != nil {
return nil, status.Errorf(
codes.Internal,
"failed to convert volume group %q to CSI format: %v",
vg,
err)
}
return &volumegroup.ModifyVolumeGroupMembershipResponse{
VolumeGroup: csiVG,
}, nil
}

View File

@ -77,11 +77,15 @@ type VolumeGroupJournalConfig struct {
Config
}
type VolumeGroupJournalConnection struct {
type volumeGroupJournalConnection struct {
config *VolumeGroupJournalConfig
connection *Connection
}
// assert that volumeGroupJournalConnection implements the VolumeGroupJournal
// interface.
var _ VolumeGroupJournal = &volumeGroupJournalConnection{}
// NewCSIVolumeGroupJournal returns an instance of VolumeGroupJournal for groups.
func NewCSIVolumeGroupJournal(suffix string) VolumeGroupJournalConfig {
return VolumeGroupJournalConfig{
@ -116,7 +120,7 @@ func (vgc *VolumeGroupJournalConfig) Connect(
namespace string,
cr *util.Credentials,
) (VolumeGroupJournal, error) {
vgjc := &VolumeGroupJournalConnection{}
vgjc := &volumeGroupJournalConnection{}
vgjc.config = &VolumeGroupJournalConfig{
Config: vgc.Config,
}
@ -130,7 +134,7 @@ func (vgc *VolumeGroupJournalConfig) Connect(
}
// Destroy frees any resources and invalidates the journal connection.
func (vgjc *VolumeGroupJournalConnection) Destroy() {
func (vgjc *volumeGroupJournalConnection) Destroy() {
vgjc.connection.Destroy()
}
@ -167,7 +171,7 @@ Return values:
reservation found.
- error: non-nil in case of any errors.
*/
func (vgjc *VolumeGroupJournalConnection) CheckReservation(ctx context.Context,
func (vgjc *volumeGroupJournalConnection) CheckReservation(ctx context.Context,
journalPool, reqName, namePrefix string,
) (*VolumeGroupData, error) {
var (
@ -244,7 +248,7 @@ Input arguments:
- groupID: ID of the volume group, generated from the UUID
- reqName: Request name for the volume group
*/
func (vgjc *VolumeGroupJournalConnection) UndoReservation(ctx context.Context,
func (vgjc *volumeGroupJournalConnection) UndoReservation(ctx context.Context,
csiJournalPool, groupID, reqName string,
) error {
// delete volume UUID omap (first, inverse of create order)
@ -303,7 +307,7 @@ Return values:
- string: Contains the VolumeGroup name that was reserved for the passed in reqName
- error: non-nil in case of any errors
*/
func (vgjc *VolumeGroupJournalConnection) ReserveName(ctx context.Context,
func (vgjc *volumeGroupJournalConnection) ReserveName(ctx context.Context,
journalPool, reqName, namePrefix string,
) (string, string, error) {
cj := vgjc.config
@ -366,7 +370,7 @@ type VolumeGroupAttributes struct {
VolumeMap map[string]string // Contains the volumeID and the corresponding value mapping
}
func (vgjc *VolumeGroupJournalConnection) GetVolumeGroupAttributes(
func (vgjc *volumeGroupJournalConnection) GetVolumeGroupAttributes(
ctx context.Context,
pool, objectUUID string,
) (*VolumeGroupAttributes, error) {
@ -401,7 +405,7 @@ func (vgjc *VolumeGroupJournalConnection) GetVolumeGroupAttributes(
return groupAttributes, nil
}
func (vgjc *VolumeGroupJournalConnection) AddVolumesMapping(
func (vgjc *volumeGroupJournalConnection) AddVolumesMapping(
ctx context.Context,
pool,
reservedUUID string,
@ -418,7 +422,7 @@ func (vgjc *VolumeGroupJournalConnection) AddVolumesMapping(
return nil
}
func (vgjc *VolumeGroupJournalConnection) RemoveVolumesMapping(
func (vgjc *volumeGroupJournalConnection) RemoveVolumesMapping(
ctx context.Context,
pool,
reservedUUID string,

View File

@ -28,6 +28,8 @@ import (
"github.com/hashicorp/vault/api"
loss "github.com/libopenstorage/secrets"
"github.com/libopenstorage/secrets/vault"
"github.com/ceph/ceph-csi/internal/util/file"
)
const (
@ -269,10 +271,12 @@ func (vc *vaultConnection) initCertificates(config map[string]interface{}, secre
return fmt.Errorf("missing vault CA in secret %s", vaultCAFromSecret)
}
vaultConfig[api.EnvVaultCACert], err = createTempFile("vault-ca-cert", []byte(caPEM))
tf, err := file.CreateTempFile("vault-ca-cert", caPEM)
if err != nil {
return fmt.Errorf("failed to create temporary file for Vault CA: %w", err)
}
vaultConfig[api.EnvVaultCACert] = tf.Name()
// update the existing config
for key, value := range vaultConfig {
vc.vaultConfig[key] = value
@ -480,31 +484,3 @@ func detectAuthMountPath(path string) (string, error) {
return authMountPath, nil
}
// createTempFile writes data to a temporary file that contains the pattern in
// the filename (see os.CreateTemp for details).
func createTempFile(pattern string, data []byte) (string, error) {
t, err := os.CreateTemp("", pattern)
if err != nil {
return "", fmt.Errorf("failed to create temporary file: %w", err)
}
// delete the tmpfile on error
defer func() {
if err != nil {
// ignore error on failure to remove tmpfile (gosec complains)
_ = os.Remove(t.Name())
}
}()
s, err := t.Write(data)
if err != nil || s != len(data) {
return "", fmt.Errorf("failed to write temporary file: %w", err)
}
err = t.Close()
if err != nil {
return "", fmt.Errorf("failed to close temporary file: %w", err)
}
return t.Name(), nil
}

View File

@ -18,7 +18,6 @@ package kms
import (
"errors"
"os"
"testing"
loss "github.com/libopenstorage/secrets"
@ -44,23 +43,6 @@ func TestDetectAuthMountPath(t *testing.T) {
}
}
func TestCreateTempFile(t *testing.T) {
t.Parallel()
data := []byte("Hello World!")
tmpfile, err := createTempFile("my-file", data)
if err != nil {
t.Errorf("createTempFile() failed: %s", err)
}
if tmpfile == "" {
t.Errorf("createTempFile() returned an empty filename")
}
err = os.Remove(tmpfile)
if err != nil {
t.Errorf("failed to remove tmpfile (%s): %s", tmpfile, err)
}
}
func TestSetConfigString(t *testing.T) {
t.Parallel()
const defaultValue = "default-value"

View File

@ -24,6 +24,7 @@ import (
"os"
"strconv"
"github.com/ceph/ceph-csi/internal/util/file"
"github.com/ceph/ceph-csi/internal/util/k8s"
"github.com/hashicorp/vault/api"
@ -378,10 +379,11 @@ func (vtc *vaultTenantConnection) initCertificates(config map[string]interface{}
return fmt.Errorf("failed to get CA certificate from secret %s: %w", vaultCAFromSecret, cErr)
}
}
vaultConfig[api.EnvVaultCACert], err = createTempFile("vault-ca-cert", []byte(cert))
if err != nil {
return fmt.Errorf("failed to create temporary file for Vault CA: %w", err)
cer, ferr := file.CreateTempFile("vault-ca-cert", cert)
if ferr != nil {
return fmt.Errorf("failed to create temporary file for Vault CA: %w", ferr)
}
vaultConfig[api.EnvVaultCACert] = cer.Name()
}
vaultClientCertFromSecret := "" // optional
@ -403,10 +405,11 @@ func (vtc *vaultTenantConnection) initCertificates(config map[string]interface{}
return fmt.Errorf("failed to get client certificate from secret %s: %w", vaultCAFromSecret, cErr)
}
}
vaultConfig[api.EnvVaultClientCert], err = createTempFile("vault-ca-cert", []byte(cert))
if err != nil {
return fmt.Errorf("failed to create temporary file for Vault client certificate: %w", err)
cer, ferr := file.CreateTempFile("vault-ca-cert", cert)
if ferr != nil {
return fmt.Errorf("failed to create temporary file for Vault client certificate: %w", ferr)
}
vaultConfig[api.EnvVaultClientCert] = cer.Name()
}
vaultClientCertKeyFromSecret := "" // optional
@ -432,10 +435,11 @@ func (vtc *vaultTenantConnection) initCertificates(config map[string]interface{}
return fmt.Errorf("failed to get client certificate key from secret %s: %w", vaultCAFromSecret, err)
}
}
vaultConfig[api.EnvVaultClientKey], err = createTempFile("vault-client-cert-key", []byte(certKey))
ckey, err := file.CreateTempFile("vault-client-cert-key", certKey)
if err != nil {
return fmt.Errorf("failed to create temporary file for Vault client cert key: %w", err)
}
vaultConfig[api.EnvVaultClientKey] = ckey.Name()
}
for key, value := range vaultConfig {

View File

@ -239,7 +239,7 @@ func (cs *ControllerServer) parseVolCreateRequest(
return rbdVol, nil
}
func (rbdVol *rbdVolume) ToCSI(ctx context.Context) *csi.Volume {
func (rbdVol *rbdVolume) ToCSI(ctx context.Context) (*csi.Volume, error) {
vol := &csi.Volume{
VolumeId: rbdVol.VolID,
CapacityBytes: rbdVol.VolSize,
@ -266,22 +266,29 @@ func (rbdVol *rbdVolume) ToCSI(ctx context.Context) *csi.Volume {
}
}
return vol
return vol, nil
}
func buildCreateVolumeResponse(
ctx context.Context,
req *csi.CreateVolumeRequest,
rbdVol *rbdVolume,
) *csi.CreateVolumeResponse {
volume := rbdVol.ToCSI(ctx)
) (*csi.CreateVolumeResponse, error) {
volume, err := rbdVol.ToCSI(ctx)
if err != nil {
return nil, status.Errorf(
codes.Internal,
"BUG, can not happen: failed to convert volume %q to CSI type: %v",
rbdVol, err)
}
volume.ContentSource = req.GetVolumeContentSource()
for param, value := range util.GetVolumeContext(req.GetParameters()) {
volume.VolumeContext[param] = value
}
return &csi.CreateVolumeResponse{Volume: volume}
return &csi.CreateVolumeResponse{Volume: volume}, nil
}
// getGRPCErrorForCreateVolume converts the returns the GRPC errors based on
@ -424,7 +431,7 @@ func (cs *ControllerServer) CreateVolume(
return nil, status.Error(codes.Internal, err.Error())
}
return buildCreateVolumeResponse(ctx, req, rbdVol), nil
return buildCreateVolumeResponse(ctx, req, rbdVol)
}
// flattenParentImage is to be called before proceeding with creating volume,
@ -559,7 +566,7 @@ func (cs *ControllerServer) repairExistingVolume(ctx context.Context, req *csi.C
return nil, err
}
return buildCreateVolumeResponse(ctx, req, rbdVol), nil
return buildCreateVolumeResponse(ctx, req, rbdVol)
}
// check snapshots on the rbd image, as we have limit from krbd that an image

View File

@ -222,13 +222,16 @@ func (r *Driver) setupCSIAddonsServer(conf *util.Config) error {
rcs := casrbd.NewReplicationServer(NewControllerServer(r.cd))
r.cas.RegisterService(rcs)
vgcs := casrbd.NewVolumeGroupServer()
vgcs := casrbd.NewVolumeGroupServer(conf.InstanceID)
r.cas.RegisterService(vgcs)
}
if conf.IsNodeServer {
rs := casrbd.NewReclaimSpaceNodeServer()
r.cas.RegisterService(rs)
ekr := casrbd.NewEncryptionKeyRotationServer(r.ns.VolumeLocks)
r.cas.RegisterService(ekr)
}
// start the server, this does not block, it runs a new go-routine

View File

@ -63,6 +63,10 @@ const (
// user did not specify an "encryptionType", but set
// "encryption": true.
rbdDefaultEncryptionType = util.EncryptionTypeBlock
// Luks slots.
luksSlot0 = "0"
luksSlot1 = "1"
)
// checkRbdImageEncrypted verifies if rbd image was encrypted when created.
@ -437,3 +441,72 @@ func (ri *rbdImage) RemoveDEK(ctx context.Context, volumeID string) error {
return nil
}
// GetEncryptionPassphraseSize returns the value of `encryptionPassphraseSize`.
func GetEncryptionPassphraseSize() int {
return encryptionPassphraseSize
}
// RotateEncryptionKey processes the key rotation for the RBD Volume.
func (rv *rbdVolume) RotateEncryptionKey(ctx context.Context) error {
if !rv.isBlockEncrypted() {
return errors.New("key rotation unsupported for non block encrypted device")
}
// Verify that the underlying device has been setup for encryption
currState, err := rv.checkRbdImageEncrypted(ctx)
if err != nil {
return fmt.Errorf("failed to check encryption state: %w", err)
}
if currState != rbdImageEncrypted {
return errors.New("key rotation not supported for unencrypted device")
}
// Get the device path for the underlying image
useNbd := rv.Mounter == rbdNbdMounter && hasNBD
devicePath, found := waitForPath(ctx, rv.Pool, rv.RadosNamespace, rv.RbdImageName, 1, useNbd)
if !found {
return fmt.Errorf("failed to get the device path for %q: %w", rv, err)
}
// Step 1: Get the current passphrase
oldPassphrase, err := rv.blockEncryption.GetCryptoPassphrase(ctx, rv.VolID)
if err != nil {
return fmt.Errorf("failed to fetch the current passphrase for %q: %w", rv, err)
}
// Step 2: Add current key to slot 1
err = util.LuksAddKey(devicePath, oldPassphrase, oldPassphrase, luksSlot1)
if err != nil {
return fmt.Errorf("failed to add curr key to luksSlot1: %w", err)
}
// Step 3: Generate new key and add it to slot 0
newPassphrase, err := rv.blockEncryption.GetNewCryptoPassphrase(
GetEncryptionPassphraseSize())
if err != nil {
return fmt.Errorf("failed to generate a new passphrase: %w", err)
}
err = util.LuksAddKey(devicePath, oldPassphrase, newPassphrase, luksSlot0)
if err != nil {
return fmt.Errorf("failed to add the new key to luksSlot0: %w", err)
}
// Step 4: Add the new key to KMS
err = rv.blockEncryption.StoreCryptoPassphrase(ctx, rv.VolID, newPassphrase)
if err != nil {
return fmt.Errorf("failed to update the new key into the KMS: %w", err)
}
// Step 5: Remove the old key from slot 1
// We use the newPassphrase to authenticate LUKS here
err = util.LuksRemoveKey(devicePath, newPassphrase, luksSlot1)
if err != nil {
return fmt.Errorf("failed to remove the backup key from luksSlot1: %w", err)
}
// Return error accordingly.
return nil
}

79
internal/rbd/group.go Normal file
View File

@ -0,0 +1,79 @@
/*
Copyright 2024 The Ceph-CSI Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package rbd
import (
"context"
"fmt"
librbd "github.com/ceph/go-ceph/rbd"
"github.com/ceph/ceph-csi/internal/rbd/types"
)
// AddToGroup adds the image to the group. This is called from the rbd_group
// package.
func (rv *rbdVolume) AddToGroup(ctx context.Context, vg types.VolumeGroup) error {
ioctx, err := vg.GetIOContext(ctx)
if err != nil {
return fmt.Errorf("could not get iocontext for volume group %q: %w", vg, err)
}
name, err := vg.GetName(ctx)
if err != nil {
return fmt.Errorf("could not get name for volume group %q: %w", vg, err)
}
// check if the image is already part of a group
// "rbd: ret=-17, File exists" is returned if the image is part of ANY group
image, err := rv.open()
if err != nil {
return fmt.Errorf("failed to open image %q: %w", rv, err)
}
info, err := image.GetGroup()
if err != nil {
return fmt.Errorf("could not get group information for image %q: %w", rv, err)
}
if info.Name != "" && info.Name != name {
return fmt.Errorf("image %q is already part of volume group %q", rv, info.Name)
}
err = librbd.GroupImageAdd(ioctx, name, rv.ioctx, rv.RbdImageName)
if err != nil {
return fmt.Errorf("failed to add image %q to volume group %q: %w", rv, vg, err)
}
return nil
}
// RemoveFromGroup removes the image from the group. This is called from the
// rbd_group package.
func (rv *rbdVolume) RemoveFromGroup(ctx context.Context, vg types.VolumeGroup) error {
ioctx, err := vg.GetIOContext(ctx)
if err != nil {
return fmt.Errorf("could not get iocontext for volume group %q: %w", vg, err)
}
name, err := vg.GetName(ctx)
if err != nil {
return fmt.Errorf("could not get name for volume group %q: %w", vg, err)
}
return librbd.GroupImageRemove(ioctx, name, rv.ioctx, rv.RbdImageName)
}

View File

@ -0,0 +1,468 @@
/*
Copyright 2024 The Ceph-CSI Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package rbd_group
import (
"context"
"errors"
"fmt"
"strings"
"github.com/ceph/go-ceph/rados"
librbd "github.com/ceph/go-ceph/rbd"
"github.com/container-storage-interface/spec/lib/go/csi"
"github.com/csi-addons/spec/lib/go/volumegroup"
"github.com/ceph/ceph-csi/internal/journal"
"github.com/ceph/ceph-csi/internal/rbd/types"
"github.com/ceph/ceph-csi/internal/util"
"github.com/ceph/ceph-csi/internal/util/log"
)
var ErrRBDGroupNotConnected = errors.New("RBD group is not connected")
// volumeGroup handles all requests for 'rbd group' operations.
type volumeGroup struct {
// id is a unique value for this volume group in the Ceph cluster, it
// is used to find the group in the journal.
id string
// name is used in RBD API calls as the name of this object
name string
clusterID string
credentials *util.Credentials
// temporary connection attributes
conn *util.ClusterConnection
ioctx *rados.IOContext
// required details to perform operations on the group
monitors string
pool string
namespace string
journal journal.VolumeGroupJournal
// volumes is a list of rbd-images that are part of the group. The ID
// of each volume is stored in the journal.
volumes []types.Volume
// volumeToFree contains Volumes that were resolved during
// GetVolumeGroup. The volumes slice can be updated independently of
// this by calling AddVolume (Volumes are allocated elsewhere), and
// RemoveVolume (need to keep track of the allocated Volume).
volumesToFree []types.Volume
}
// verify that volumeGroup implements the VolumeGroup and Stringer interfaces.
var (
_ types.VolumeGroup = &volumeGroup{}
_ fmt.Stringer = &volumeGroup{}
)
// GetVolumeGroup initializes a new VolumeGroup object that can be used
// to manage an `rbd group`.
// If the .GetName() function returns an error, the VolumeGroup does not exist
// yet. It is needed to call .Create() in that case first.
func GetVolumeGroup(
ctx context.Context,
id string,
j journal.VolumeGroupJournal,
creds *util.Credentials,
volumeResolver types.VolumeResolver,
) (types.VolumeGroup, error) {
csiID := util.CSIIdentifier{}
err := csiID.DecomposeCSIID(id)
if err != nil {
return nil, fmt.Errorf("failed to decompose volume group id %q: %w", id, err)
}
mons, err := util.Mons(util.CsiConfigFile, csiID.ClusterID)
if err != nil {
return nil, fmt.Errorf("failed to get MONs for cluster id %q: %w", csiID.ClusterID, err)
}
namespace, err := util.GetRadosNamespace(util.CsiConfigFile, csiID.ClusterID)
if err != nil {
return nil, fmt.Errorf("failed to get RADOS namespace for cluster id %q: %w", csiID.ClusterID, err)
}
pool, err := util.GetPoolName(mons, creds, csiID.LocationID)
if err != nil {
return nil, fmt.Errorf("failed to get pool for volume group id %q: %w", id, err)
}
attrs, err := j.GetVolumeGroupAttributes(ctx, pool, csiID.ObjectUUID)
if err != nil {
if !errors.Is(err, util.ErrKeyNotFound) && !errors.Is(err, util.ErrPoolNotFound) {
return nil, fmt.Errorf("failed to get attributes for volume group id %q: %w", id, err)
}
attrs = &journal.VolumeGroupAttributes{}
}
var volumes []types.Volume
for volID := range attrs.VolumeMap {
vol, err := volumeResolver.GetVolumeByID(ctx, volID)
if err != nil {
// free the previously allocated volumes
for _, v := range volumes {
v.Destroy(ctx)
}
return nil, fmt.Errorf("failed to get attributes for volume group id %q: %w", id, err)
}
volumes = append(volumes, vol)
}
vg := &volumeGroup{
journal: j,
credentials: creds,
id: id,
name: attrs.GroupName,
clusterID: csiID.ClusterID,
monitors: mons,
pool: pool,
namespace: namespace,
volumes: volumes,
// all allocated volumes need to be free'd at Destroy() time
volumesToFree: volumes,
}
log.DebugLog(ctx, "GetVolumeGroup(%s) returns %+v", id, *vg)
return vg, nil
}
// String makes it easy to include the volumeGroup object in log and error
// messages.
func (vg *volumeGroup) String() string {
if vg.name != "" {
return vg.name
}
if vg.id != "" {
return vg.id
}
return fmt.Sprintf("<unidentified volume %v>", *vg)
}
// GetID returns the CSI-Addons VolumeGroupId of the VolumeGroup.
func (vg *volumeGroup) GetID(ctx context.Context) (string, error) {
if vg.id == "" {
return "", errors.New("BUG: ID is not set")
}
return vg.id, nil
}
// GetName returns the name in the backend storage for the VolumeGroup.
func (vg *volumeGroup) GetName(ctx context.Context) (string, error) {
if vg.name == "" {
return "", errors.New("BUG: name is not set")
}
return vg.name, nil
}
// GetPool returns the name of the pool that holds the VolumeGroup.
func (vg *volumeGroup) GetPool(ctx context.Context) (string, error) {
if vg.pool == "" {
return "", errors.New("BUG: pool is not set")
}
return vg.pool, nil
}
// GetClusterID returns the name of the pool that holds the VolumeGroup.
func (vg *volumeGroup) GetClusterID(ctx context.Context) (string, error) {
if vg.clusterID == "" {
return "", errors.New("BUG: clusterID is not set")
}
return vg.clusterID, nil
}
// ToCSI creates a CSI-Addons type for the VolumeGroup.
func (vg *volumeGroup) ToCSI(ctx context.Context) (*volumegroup.VolumeGroup, error) {
volumes, err := vg.ListVolumes(ctx)
if err != nil {
return nil, fmt.Errorf("failed to list volumes for volume group %q: %w", vg, err)
}
csiVolumes := make([]*csi.Volume, len(volumes))
for i, vol := range volumes {
csiVolumes[i], err = vol.ToCSI(ctx)
if err != nil {
return nil, fmt.Errorf("failed to convert volume %q to CSI type: %w", vol, err)
}
}
id, err := vg.GetID(ctx)
if err != nil {
return nil, fmt.Errorf("failed to get id for volume group %q: %w", vg, err)
}
// TODO: maybe store the VolumeContext in the journal?
vgContext := map[string]string{}
return &volumegroup.VolumeGroup{
VolumeGroupId: id,
VolumeGroupContext: vgContext,
Volumes: csiVolumes,
}, nil
}
// getConnection returns the ClusterConnection for the volume group if it
// exists, otherwise it will open a new one.
// Destroy should be used to close the ClusterConnection.
func (vg *volumeGroup) getConnection(ctx context.Context) (*util.ClusterConnection, error) {
if vg.conn != nil {
return vg.conn, nil
}
conn := &util.ClusterConnection{}
err := conn.Connect(vg.monitors, vg.credentials)
if err != nil {
return nil, fmt.Errorf("failed to connect to MONs %q: %w", vg.monitors, err)
}
vg.conn = conn
log.DebugLog(ctx, "connection established for volume group %q", vg.id)
return conn, nil
}
// GetIOContext returns the IOContext for the volume group if it exists,
// otherwise it will allocate a new one.
// Destroy should be used to free the IOContext.
func (vg *volumeGroup) GetIOContext(ctx context.Context) (*rados.IOContext, error) {
if vg.ioctx != nil {
return vg.ioctx, nil
}
conn, err := vg.getConnection(ctx)
if err != nil {
return nil, fmt.Errorf("%w: failed to connect: %w", ErrRBDGroupNotConnected, err)
}
ioctx, err := conn.GetIoctx(vg.pool)
if err != nil {
return nil, fmt.Errorf("%w: failed to get IOContext: %w", ErrRBDGroupNotConnected, err)
}
if vg.namespace != "" {
ioctx.SetNamespace(vg.namespace)
}
vg.ioctx = ioctx
log.DebugLog(ctx, "iocontext created for volume group %q in pool %q", vg.id, vg.pool)
return ioctx, nil
}
// Destroy frees the resources used by the volumeGroup.
func (vg *volumeGroup) Destroy(ctx context.Context) {
// free the volumes that were allocated in GetVolumeGroup()
if len(vg.volumesToFree) > 0 {
for _, volume := range vg.volumesToFree {
volume.Destroy(ctx)
}
vg.volumesToFree = make([]types.Volume, 0)
}
if vg.ioctx != nil {
vg.ioctx.Destroy()
vg.ioctx = nil
}
if vg.conn != nil {
vg.conn.Destroy()
vg.conn = nil
}
if vg.credentials != nil {
vg.credentials.DeleteCredentials()
vg.credentials = nil
}
log.DebugLog(ctx, "destroyed volume group instance with id %q", vg.id)
}
func (vg *volumeGroup) Create(ctx context.Context) error {
name, err := vg.GetName(ctx)
if err != nil {
return fmt.Errorf("missing name to create volume group: %w", err)
}
ioctx, err := vg.GetIOContext(ctx)
if err != nil {
return err
}
err = librbd.GroupCreate(ioctx, name)
if err != nil {
if !errors.Is(rados.ErrObjectExists, err) && !strings.Contains(err.Error(), "rbd: ret=-17, File exists") {
return fmt.Errorf("failed to create volume group %q: %w", name, err)
}
log.DebugLog(ctx, "ignoring error while creating volume group %q: %v", vg, err)
}
log.DebugLog(ctx, "volume group %q has been created", vg)
return nil
}
func (vg *volumeGroup) Delete(ctx context.Context) error {
name, err := vg.GetName(ctx)
if err != nil {
return err
}
ioctx, err := vg.GetIOContext(ctx)
if err != nil {
return err
}
err = librbd.GroupRemove(ioctx, name)
if err != nil && !errors.Is(rados.ErrNotFound, err) {
return fmt.Errorf("failed to remove volume group %q: %w", vg, err)
}
log.DebugLog(ctx, "volume group %q has been removed", vg)
return nil
}
func (vg *volumeGroup) AddVolume(ctx context.Context, vol types.Volume) error {
err := vol.AddToGroup(ctx, vg)
if err != nil {
return fmt.Errorf("failed to add volume %q to volume group %q: %w", vol, vg, err)
}
vg.volumes = append(vg.volumes, vol)
volID, err := vol.GetID(ctx)
if err != nil {
return err
}
pool, err := vg.GetPool(ctx)
if err != nil {
return err
}
id, err := vg.GetID(ctx)
if err != nil {
return err
}
csiID := util.CSIIdentifier{}
err = csiID.DecomposeCSIID(id)
if err != nil {
return fmt.Errorf("failed to decompose volume group id %q: %w", id, err)
}
toAdd := map[string]string{
volID: "",
}
err = vg.journal.AddVolumesMapping(ctx, pool, csiID.ObjectUUID, toAdd)
if err != nil {
return fmt.Errorf("failed to add mapping for volume %q to volume group id %q: %w", volID, id, err)
}
return nil
}
func (vg *volumeGroup) RemoveVolume(ctx context.Context, vol types.Volume) error {
// volume was already removed from the group
if len(vg.volumes) == 0 {
return nil
}
err := vol.RemoveFromGroup(ctx, vg)
if err != nil {
if errors.Is(librbd.ErrNotExist, err) {
return nil
}
return fmt.Errorf("failed to remove volume %q from volume group %q: %w", vol, vg, err)
}
// toRemove contain the ID of the volume that is removed from the group
toRemove, err := vol.GetID(ctx)
if err != nil {
return fmt.Errorf("failed to get volume id for %q: %w", vol, err)
}
// volumes is the updated list, without the volume that was removed
volumes := make([]types.Volume, 0)
var id string
for _, v := range vg.volumes {
id, err = v.GetID(ctx)
if err != nil {
return err
}
if id == toRemove {
// do not add the volume to the list
continue
}
volumes = append(volumes, v)
}
// update the list of volumes
vg.volumes = volumes
pool, err := vg.GetPool(ctx)
if err != nil {
return err
}
id, err = vg.GetID(ctx)
if err != nil {
return err
}
csiID := util.CSIIdentifier{}
err = csiID.DecomposeCSIID(id)
if err != nil {
return fmt.Errorf("failed to decompose volume group id %q: %w", id, err)
}
mapping := []string{
toRemove,
}
err = vg.journal.RemoveVolumesMapping(ctx, pool, csiID.ObjectUUID, mapping)
if err != nil {
return fmt.Errorf("failed to remove mapping for volume %q to volume group id %q: %w", toRemove, id, err)
}
return nil
}
func (vg *volumeGroup) ListVolumes(ctx context.Context) ([]types.Volume, error) {
return vg.volumes, nil
}

View File

@ -19,24 +19,38 @@ package rbd
import (
"context"
"errors"
"fmt"
"github.com/ceph/go-ceph/rados"
"github.com/ceph/ceph-csi/internal/journal"
rbd_group "github.com/ceph/ceph-csi/internal/rbd/group"
"github.com/ceph/ceph-csi/internal/rbd/types"
"github.com/ceph/ceph-csi/internal/util"
"github.com/ceph/ceph-csi/internal/util/log"
)
var _ types.Manager = &rbdManager{}
type rbdManager struct {
// csiID is the instance id of the CSI-driver (driver name).
csiID string
// parameters can contain the parameters of a create request.
parameters map[string]string
// secrets contain the credentials to connect to the Ceph cluster.
secrets map[string]string
// creds are the cached credentials, will be freed on Destroy()
creds *util.Credentials
// vgJournal is the journal that is used during opetations, it will be freed on Destroy().
vgJournal journal.VolumeGroupJournal
}
// NewManager returns a new manager for handling Volume and Volume Group
// operations, combining the requests for RBD and the journalling in RADOS.
func NewManager(parameters, secrets map[string]string) types.Manager {
func NewManager(csiID string, parameters, secrets map[string]string) types.Manager {
return &rbdManager{
csiID: csiID,
parameters: parameters,
secrets: secrets,
}
@ -47,43 +61,225 @@ func (mgr *rbdManager) Destroy(ctx context.Context) {
mgr.creds.DeleteCredentials()
mgr.creds = nil
}
if mgr.vgJournal != nil {
mgr.vgJournal.Destroy()
mgr.vgJournal = nil
}
}
// getCredentials sets up credentials and connects to the journal.
func (mgr *rbdManager) getCredentials() (*util.Credentials, error) {
if mgr.creds != nil {
return mgr.creds, nil
}
// connect sets up credentials and connects to the journal.
func (mgr *rbdManager) connect() error {
if mgr.creds == nil {
creds, err := util.NewUserCredentials(mgr.secrets)
if err != nil {
return err
return nil, fmt.Errorf("failed to get credentials: %w", err)
}
mgr.creds = creds
return creds, nil
}
return nil
func (mgr *rbdManager) getVolumeGroupJournal(clusterID string) (journal.VolumeGroupJournal, error) {
if mgr.vgJournal != nil {
return mgr.vgJournal, nil
}
creds, err := mgr.getCredentials()
if err != nil {
return nil, err
}
monitors, err := util.Mons(util.CsiConfigFile, clusterID)
if err != nil {
return nil, fmt.Errorf("failed to find MONs for cluster %q: %w", clusterID, err)
}
ns, err := util.GetRadosNamespace(util.CsiConfigFile, clusterID)
if err != nil {
return nil, fmt.Errorf("failed to find the RADOS namespace for cluster %q: %w", clusterID, err)
}
vgJournalConfig := journal.NewCSIVolumeGroupJournalWithNamespace(mgr.csiID, ns)
vgJournal, err := vgJournalConfig.Connect(monitors, ns, creds)
if err != nil {
return nil, fmt.Errorf("failed to connect to journal: %w", err)
}
mgr.vgJournal = vgJournal
return vgJournal, nil
}
func (mgr *rbdManager) GetVolumeByID(ctx context.Context, id string) (types.Volume, error) {
if err := mgr.connect(); err != nil {
creds, err := mgr.getCredentials()
if err != nil {
return nil, err
}
volume, err := GenVolFromVolID(ctx, id, mgr.creds, mgr.secrets)
volume, err := GenVolFromVolID(ctx, id, creds, mgr.secrets)
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to get volume from id %q: %w", id, err)
}
return volume, nil
}
func (mgr *rbdManager) GetVolumeGroupByID(ctx context.Context, id string) (types.VolumeGroup, error) {
return nil, errors.New("rbdManager.GetVolumeGroupByID() is not implemented yet")
vi := &util.CSIIdentifier{}
if err := vi.DecomposeCSIID(id); err != nil {
return nil, fmt.Errorf("failed to parse volume group id %q: %w", id, err)
}
vgJournal, err := mgr.getVolumeGroupJournal(vi.ClusterID)
if err != nil {
return nil, err
}
creds, err := mgr.getCredentials()
if err != nil {
return nil, err
}
vg, err := rbd_group.GetVolumeGroup(ctx, id, vgJournal, creds, mgr)
if err != nil {
return nil, fmt.Errorf("failed to get volume group with id %q: %w", id, err)
}
return vg, nil
}
func (mgr *rbdManager) CreateVolumeGroup(ctx context.Context, name string) (types.VolumeGroup, error) {
return nil, errors.New("rbdManager.CreateVolumeGroup() is not implemented yet")
creds, err := mgr.getCredentials()
if err != nil {
return nil, err
}
clusterID, err := util.GetClusterID(mgr.parameters)
if err != nil {
return nil, fmt.Errorf("failed to get cluster-id: %w", err)
}
vgJournal, err := mgr.getVolumeGroupJournal(clusterID)
if err != nil {
return nil, err
}
// pool is a required parameter
pool, ok := mgr.parameters["pool"]
if !ok || pool == "" {
return nil, errors.New("required 'pool' option missing in volume group parameters")
}
// journalPool is an optional parameter, use pool if it is not set
journalPool, ok := mgr.parameters["journalPool"]
if !ok || journalPool == "" {
journalPool = pool
}
// volumeNamePrefix is an optional parameter, can be an empty string
prefix := mgr.parameters["volumeNamePrefix"]
// check if the journal contains a generated name for the group already
vgData, err := vgJournal.CheckReservation(ctx, journalPool, name, prefix)
if err != nil {
return nil, fmt.Errorf("failed to reserve volume group for name %q: %w", name, err)
}
var uuid string
if vgData != nil && vgData.GroupUUID != "" {
uuid = vgData.GroupUUID
} else {
log.DebugLog(ctx, "the journal does not contain a reservation for a volume group with name %q yet", name)
var vgName string
uuid, vgName, err = vgJournal.ReserveName(ctx, journalPool, name, prefix)
if err != nil {
return nil, fmt.Errorf("failed to reserve volume group for name %q: %w", name, err)
}
defer func() {
if err != nil {
err = vgJournal.UndoReservation(ctx, pool, vgName, name)
if err != nil {
log.ErrorLog(ctx, "failed to undo the reservation for volume group %q: %w", name, err)
}
}
}()
}
monitors, err := util.Mons(util.CsiConfigFile, clusterID)
if err != nil {
return nil, fmt.Errorf("failed to find MONs for cluster %q: %w", clusterID, err)
}
_ /*journalPoolID*/, poolID, err := util.GetPoolIDs(ctx, monitors, journalPool, pool, creds)
if err != nil {
return nil, fmt.Errorf("failed to generate a unique CSI volume group with uuid for %q: %w", uuid, err)
}
csiID, err := util.GenerateVolID(ctx, monitors, creds, poolID, pool, clusterID, uuid)
if err != nil {
return nil, fmt.Errorf("failed to generate a unique CSI volume group with uuid for %q: %w", uuid, err)
}
vg, err := rbd_group.GetVolumeGroup(ctx, csiID, vgJournal, creds, mgr)
if err != nil {
return nil, fmt.Errorf("failed to get volume group %q at cluster %q: %w", name, clusterID, err)
}
defer func() {
if err != nil {
vg.Destroy(ctx)
}
}()
err = vg.Create(ctx)
if err != nil {
return nil, fmt.Errorf("failed to create volume group %q: %w", name, err)
}
return vg, nil
}
func (mgr *rbdManager) DeleteVolumeGroup(ctx context.Context, vg types.VolumeGroup) error {
return errors.New("rbdManager.CreateVolumeGroup() is not implemented yet")
err := vg.Delete(ctx)
if err != nil && !errors.Is(rados.ErrNotFound, err) {
return fmt.Errorf("failed to delete volume group %q: %w", vg, err)
}
clusterID, err := vg.GetClusterID(ctx)
if err != nil {
return fmt.Errorf("failed to get cluster id for volume group %q: %w", vg, err)
}
vgJournal, err := mgr.getVolumeGroupJournal(clusterID)
if err != nil {
return err
}
name, err := vg.GetName(ctx)
if err != nil {
return fmt.Errorf("failed to get name for volume group %q: %w", vg, err)
}
csiID, err := vg.GetID(ctx)
if err != nil {
return fmt.Errorf("failed to get id for volume group %q: %w", vg, err)
}
pool, err := vg.GetPool(ctx)
if err != nil {
return fmt.Errorf("failed to get pool for volume group %q: %w", vg, err)
}
err = vgJournal.UndoReservation(ctx, pool, name, csiID)
if err != nil /* TODO? !errors.Is(..., err) */ {
return fmt.Errorf("failed to undo the reservation for volume group %q: %w", vg, err)
}
return nil
}

View File

@ -19,20 +19,41 @@ package types
import (
"context"
"github.com/ceph/go-ceph/rados"
"github.com/csi-addons/spec/lib/go/volumegroup"
)
// VolumeGroup contains a number of volumes, and can be used to create a
// VolumeGroupSnapshot.
type VolumeGroup interface {
// Destroy frees the resources used by the VolumeGroup.
Destroy(ctx context.Context)
type journalledObject interface {
// GetID returns the CSI-Addons VolumeGroupId of the VolumeGroup.
GetID(ctx context.Context) (string, error)
// GetName returns the name in the backend storage for the VolumeGroup.
GetName(ctx context.Context) (string, error)
// GetPool returns the name of the pool that holds the VolumeGroup.
GetPool(ctx context.Context) (string, error)
// GetClusterID returns the ID of the cluster of the VolumeGroup.
GetClusterID(ctx context.Context) (string, error)
}
// VolumeGroup contains a number of volumes.
type VolumeGroup interface {
journalledObject
// Destroy frees the resources used by the VolumeGroup.
Destroy(ctx context.Context)
// GetIOContext returns the IOContext for performing librbd operations
// on the VolumeGroup. This is used by the rbdVolume struct when it
// needs to add/remove itself from the VolumeGroup.
GetIOContext(ctx context.Context) (*rados.IOContext, error)
// ToCSI creates a CSI-Addons type for the VolumeGroup.
ToCSI(ctx context.Context) *volumegroup.VolumeGroup
ToCSI(ctx context.Context) (*volumegroup.VolumeGroup, error)
// Create makes a new group in the backend storage.
Create(ctx context.Context) error
// Delete removes the VolumeGroup from the backend storage.
Delete(ctx context.Context) error

View File

@ -20,16 +20,22 @@ import (
"context"
)
// VolumeResolver can be used to construct a Volume from a CSI VolumeId.
type VolumeResolver interface {
// GetVolumeByID uses the CSI VolumeId to resolve the returned Volume.
GetVolumeByID(ctx context.Context, id string) (Volume, error)
}
// Manager provides a way for other packages to get Volumes and VolumeGroups.
// It handles the operations on the backend, and makes sure the journal
// reflects the expected state.
type Manager interface {
// VolumeResolver is fully implemented by the Manager.
VolumeResolver
// Destroy frees all resources that the Manager allocated.
Destroy(ctx context.Context)
// GetVolumeByID uses the CSI VolumeId to resolve the returned Volume.
GetVolumeByID(ctx context.Context, id string) (Volume, error)
// GetVolumeGroupByID uses the CSI-Addons VolumeGroupId to resolve the
// returned VolumeGroup.
GetVolumeGroupByID(ctx context.Context, id string) (VolumeGroup, error)

View File

@ -33,5 +33,11 @@ type Volume interface {
GetID(ctx context.Context) (string, error)
// ToCSI creates a CSI protocol formatted struct of the volume.
ToCSI(ctx context.Context) *csi.Volume
ToCSI(ctx context.Context) (*csi.Volume, error)
// AddToGroup adds the Volume to the VolumeGroup.
AddToGroup(ctx context.Context, vg VolumeGroup) error
// RemoveFromGroup removes the Volume from the VolumeGroup.
RemoveFromGroup(ctx context.Context, vg VolumeGroup) error
}

View File

@ -237,6 +237,11 @@ func (ve *VolumeEncryption) GetCryptoPassphrase(ctx context.Context, volumeID st
return ve.KMS.DecryptDEK(ctx, volumeID, passphrase)
}
// GetNewCryptoPassphrase returns a random passphrase of given length.
func (ve *VolumeEncryption) GetNewCryptoPassphrase(length int) (string, error) {
return generateNewEncryptionPassphrase(length)
}
// generateNewEncryptionPassphrase generates a random passphrase for encryption.
func generateNewEncryptionPassphrase(length int) (string, error) {
bytesPassphrase := make([]byte, length)

View File

@ -19,9 +19,13 @@ package util
import (
"bytes"
"fmt"
"os"
"os/exec"
"strconv"
"strings"
"github.com/ceph/ceph-csi/internal/util/file"
"github.com/ceph/ceph-csi/internal/util/log"
)
// Limit memory used by Argon2i PBKDF to 32 MiB.
@ -66,6 +70,135 @@ func LuksStatus(mapperFile string) (string, string, error) {
return execCryptsetupCommand(nil, "status", mapperFile)
}
// LuksAddKey adds a new key to the specified slot.
func LuksAddKey(devicePath, passphrase, newPassphrase, slot string) error {
passFile, err := file.CreateTempFile("luks-", passphrase)
if err != nil {
return err
}
defer os.Remove(passFile.Name())
newPassFile, err := file.CreateTempFile("luks-", newPassphrase)
if err != nil {
return err
}
defer os.Remove(newPassFile.Name())
_, stderr, err := execCryptsetupCommand(
nil,
"--verbose",
"--key-file="+passFile.Name(),
"--key-slot="+slot,
"luksAddKey",
devicePath,
newPassFile.Name(),
)
// Return early if no error to save us some time
if err == nil {
return nil
}
// Possible scenarios
// 1. The provided passphrase to unlock the disk is wrong
// 2. The key slot is already in use
// If so, check if the key we want to add to the slot is already there
// If not, remove it and then add the new key to the slot
if strings.Contains(stderr, fmt.Sprintf("Key slot %s is full", slot)) {
// The given slot already has a key
// Check if it is the one that we want to update with
exists, fErr := LuksVerifyKey(devicePath, newPassphrase, slot)
if fErr != nil {
return fErr
}
// Verification passed, return early
if exists {
return nil
}
// Else, we remove the key from the given slot and add the new one
// Note: we use existing passphrase here as we are not yet sure if
// the newPassphrase is present in the headers
fErr = LuksRemoveKey(devicePath, passphrase, slot)
if fErr != nil {
return fErr
}
// Now the slot is free, add the new key to it
fErr = LuksAddKey(devicePath, passphrase, newPassphrase, slot)
if fErr != nil {
return fErr
}
// No errors, we good.
return nil
}
// The existing passphrase is wrong and the slot is empty
return err
}
// LuksRemoveKey removes the key by killing the specified slot.
func LuksRemoveKey(devicePath, passphrase, slot string) error {
keyFile, err := file.CreateTempFile("luks-", passphrase)
if err != nil {
return err
}
defer os.Remove(keyFile.Name())
_, stderr, err := execCryptsetupCommand(
nil,
"--verbose",
"--key-file="+keyFile.Name(),
"luksKillSlot",
devicePath,
slot,
)
if err != nil {
// If a slot is not active, don't treat that as an error
if !strings.Contains(stderr, fmt.Sprintf("Keyslot %s is not active.", slot)) {
return fmt.Errorf("failed to kill slot %s for device %s: %w", slot, devicePath, err)
}
}
return nil
}
// LuksVerifyKey verifies that a key exists in a given slot.
func LuksVerifyKey(devicePath, passphrase, slot string) (bool, error) {
// Create a temp file that we will use to open the device
keyFile, err := file.CreateTempFile("luks-", passphrase)
if err != nil {
return false, err
}
defer os.Remove(keyFile.Name())
_, stderr, err := execCryptsetupCommand(
nil,
"--verbose",
"--key-file="+keyFile.Name(),
"--key-slot="+slot,
"luksChangeKey",
devicePath,
keyFile.Name(),
)
if err != nil {
// If the passphrase doesn't match the key in given slot
if strings.Contains(stderr, "No key available with this passphrase.") {
// No match, no error
return false, nil
}
// Otherwise it was something else, return the wrapped error
log.ErrorLogMsg("failed to verify key in slot %s. stderr: %s. err: %v", slot, stderr, err)
return false, fmt.Errorf("failed to verify key in slot %s for device %s: %w", slot, devicePath, err)
}
return true, nil
}
func execCryptsetupCommand(stdin *string, args ...string) (string, string, error) {
var (
program = "cryptsetup"

View File

@ -0,0 +1,54 @@
/*
Copyright 2024 The Ceph-CSI Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package file
import (
"fmt"
"os"
)
// CreateTempFile create a temporary file with the given string
// content and returns the reference to the file.
// The caller is responsible for disposing the file.
func CreateTempFile(prefix, contents string) (*os.File, error) {
// Create a temp file
file, err := os.CreateTemp("", prefix)
if err != nil {
return nil, fmt.Errorf("failed to create temporary file: %w", err)
}
// In case of error, remove the file if it was created
defer func() {
if err != nil {
_ = os.Remove(file.Name())
}
}()
// Write the contents
var c int
c, err = file.WriteString(contents)
if err != nil || c != len(contents) {
return nil, fmt.Errorf("failed to write temporary file: %w", err)
}
// Close the handle
if err = file.Close(); err != nil {
return nil, fmt.Errorf("failed to close temporary file: %w", err)
}
return file, nil
}

View File

@ -0,0 +1,100 @@
/*
Copyright 2024 The Ceph-CSI Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package file
import (
"os"
"testing"
)
func TestCreateTempFile_WithValidContent(t *testing.T) {
t.Parallel()
content := "Valid Content"
file, err := CreateTempFile("test-", content)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
defer func() {
err = os.Remove(file.Name())
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
}()
readContent, err := os.ReadFile(file.Name())
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if string(readContent) != content {
t.Fatalf("Content mismatch: got %v, want %v", string(readContent), content)
}
}
func TestCreateTempFile_WithEmptyContent(t *testing.T) {
t.Parallel()
content := ""
file, err := CreateTempFile("test-", content)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
defer func() {
err = os.Remove(file.Name())
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
}()
readContent, err := os.ReadFile(file.Name())
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if string(readContent) != content {
t.Fatalf("Content mismatch: got %v, want %v", string(readContent), content)
}
}
func TestCreateTempFile_WithLargeContent(t *testing.T) {
t.Parallel()
content := string(make([]byte, 1<<20))
file, err := CreateTempFile("test-", content)
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
defer func() {
err = os.Remove(file.Name())
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
}()
readContent, err := os.ReadFile(file.Name())
if err != nil {
t.Fatalf("Unexpected error: %v", err)
}
if string(readContent) != content {
t.Fatalf("Content mismatch: got %v, want %v", string(readContent), content)
}
}

View File

@ -13068,6 +13068,9 @@ var awsPartition = partition{
endpointKey{
Region: "eu-central-1",
}: endpoint{},
endpointKey{
Region: "eu-central-2",
}: endpoint{},
endpointKey{
Region: "eu-north-1",
}: endpoint{},
@ -22522,6 +22525,9 @@ var awsPartition = partition{
}: endpoint{
Hostname: "network-firewall-fips.ca-central-1.amazonaws.com",
},
endpointKey{
Region: "ca-west-1",
}: endpoint{},
endpointKey{
Region: "eu-central-1",
}: endpoint{},
@ -24479,6 +24485,14 @@ var awsPartition = partition{
Region: "ca-central-1",
},
},
endpointKey{
Region: "ca-west-1",
}: endpoint{
Hostname: "portal.sso.ca-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "ca-west-1",
},
},
endpointKey{
Region: "eu-central-1",
}: endpoint{
@ -33621,6 +33635,20 @@ var awsPartition = partition{
}: endpoint{},
},
},
"tax": service{
PartitionEndpoint: "aws-global",
IsRegionalized: boxedFalse,
Endpoints: serviceEndpoints{
endpointKey{
Region: "aws-global",
}: endpoint{
Hostname: "tax.us-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-east-1",
},
},
},
},
"textract": service{
Endpoints: serviceEndpoints{
endpointKey{
@ -39973,16 +40001,12 @@ var awsusgovPartition = partition{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
}: endpoint{
Hostname: "autoscaling-plans.us-gov-east-1.amazonaws.com",
Protocols: []string{"http", "https"},
},
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "autoscaling-plans.us-gov-east-1.amazonaws.com",
Protocols: []string{"http", "https"},
},
endpointKey{
Region: "us-gov-east-1-fips",
@ -39994,16 +40018,12 @@ var awsusgovPartition = partition{
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "autoscaling-plans.us-gov-west-1.amazonaws.com",
Protocols: []string{"http", "https"},
},
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "autoscaling-plans.us-gov-west-1.amazonaws.com",
Protocols: []string{"http", "https"},
},
endpointKey{
Region: "us-gov-west-1-fips",
@ -40969,20 +40989,40 @@ var awsusgovPartition = partition{
"directconnect": service{
Endpoints: serviceEndpoints{
endpointKey{
Region: "us-gov-east-1",
Region: "fips-us-gov-east-1",
}: endpoint{
Hostname: "directconnect.us-gov-east-1.amazonaws.com",
Hostname: "directconnect-fips.us-gov-east-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-east-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "fips-us-gov-west-1",
}: endpoint{
Hostname: "directconnect-fips.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
Region: "us-gov-west-1",
},
Deprecated: boxedTrue,
},
endpointKey{
Region: "us-gov-east-1",
}: endpoint{},
endpointKey{
Region: "us-gov-east-1",
Variant: fipsVariant,
}: endpoint{
Hostname: "directconnect-fips.us-gov-east-1.amazonaws.com",
},
endpointKey{
Region: "us-gov-west-1",
}: endpoint{
Hostname: "directconnect.us-gov-west-1.amazonaws.com",
CredentialScope: credentialScope{
}: endpoint{},
endpointKey{
Region: "us-gov-west-1",
},
Variant: fipsVariant,
}: endpoint{
Hostname: "directconnect-fips.us-gov-west-1.amazonaws.com",
},
},
},

View File

@ -5,4 +5,4 @@ package aws
const SDKName = "aws-sdk-go"
// SDKVersion is the version of this SDK
const SDKVersion = "1.54.19"
const SDKVersion = "1.55.0"

View File

@ -0,0 +1,317 @@
// Code generated by make; DO NOT EDIT.
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.28.1
// protoc v3.20.2
// source: encryptionkeyrotation/encryptionkeyrotation.proto
package encryptionkeyrotation
import (
csi "github.com/container-storage-interface/spec/lib/go/csi"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
_ "google.golang.org/protobuf/types/descriptorpb"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// EncryptionKeyRotateRequest contains the information needed to identify
// the volume by the SP and access any backend services so that the key can be
// rotated.
type EncryptionKeyRotateRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// The ID of the volume for which the key is to be rotated.
// This field is required
VolumeId string `protobuf:"bytes,1,opt,name=volume_id,json=volumeId,proto3" json:"volume_id,omitempty"`
// The path where the volume is available.
// This field is OPTIONAL
// Useful if you are implementing the RPC on CSI Driver NodePlugin
VolumePath string `protobuf:"bytes,2,opt,name=volume_path,json=volumePath,proto3" json:"volume_path,omitempty"`
// Provide the encryption key to be set
// This field is OPTIONAL
EncryptionKey string `protobuf:"bytes,3,opt,name=encryption_key,json=encryptionKey,proto3" json:"encryption_key,omitempty"`
// Plugin specific parameters passed in as opaque key-value pairs.
Parameters map[string]string `protobuf:"bytes,4,rep,name=parameters,proto3" json:"parameters,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
// Secrets required by the plugin to complete the request.
Secrets map[string]string `protobuf:"bytes,5,rep,name=secrets,proto3" json:"secrets,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
// Volume capability describing how the CO intends to use this volume.
// This allows SP to determine if volume is being used as a block
// device or mounted file system. This is OPTIONAL.
VolumeCapability *csi.VolumeCapability `protobuf:"bytes,6,opt,name=volume_capability,json=volumeCapability,proto3" json:"volume_capability,omitempty"`
}
func (x *EncryptionKeyRotateRequest) Reset() {
*x = EncryptionKeyRotateRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_encryptionkeyrotation_encryptionkeyrotation_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *EncryptionKeyRotateRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*EncryptionKeyRotateRequest) ProtoMessage() {}
func (x *EncryptionKeyRotateRequest) ProtoReflect() protoreflect.Message {
mi := &file_encryptionkeyrotation_encryptionkeyrotation_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use EncryptionKeyRotateRequest.ProtoReflect.Descriptor instead.
func (*EncryptionKeyRotateRequest) Descriptor() ([]byte, []int) {
return file_encryptionkeyrotation_encryptionkeyrotation_proto_rawDescGZIP(), []int{0}
}
func (x *EncryptionKeyRotateRequest) GetVolumeId() string {
if x != nil {
return x.VolumeId
}
return ""
}
func (x *EncryptionKeyRotateRequest) GetVolumePath() string {
if x != nil {
return x.VolumePath
}
return ""
}
func (x *EncryptionKeyRotateRequest) GetEncryptionKey() string {
if x != nil {
return x.EncryptionKey
}
return ""
}
func (x *EncryptionKeyRotateRequest) GetParameters() map[string]string {
if x != nil {
return x.Parameters
}
return nil
}
func (x *EncryptionKeyRotateRequest) GetSecrets() map[string]string {
if x != nil {
return x.Secrets
}
return nil
}
func (x *EncryptionKeyRotateRequest) GetVolumeCapability() *csi.VolumeCapability {
if x != nil {
return x.VolumeCapability
}
return nil
}
// EncryptionKeyRotateResponse holds the information about the result of the
// EncryptionKeyRotateRequest call.
type EncryptionKeyRotateResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
}
func (x *EncryptionKeyRotateResponse) Reset() {
*x = EncryptionKeyRotateResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_encryptionkeyrotation_encryptionkeyrotation_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *EncryptionKeyRotateResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*EncryptionKeyRotateResponse) ProtoMessage() {}
func (x *EncryptionKeyRotateResponse) ProtoReflect() protoreflect.Message {
mi := &file_encryptionkeyrotation_encryptionkeyrotation_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use EncryptionKeyRotateResponse.ProtoReflect.Descriptor instead.
func (*EncryptionKeyRotateResponse) Descriptor() ([]byte, []int) {
return file_encryptionkeyrotation_encryptionkeyrotation_proto_rawDescGZIP(), []int{1}
}
var File_encryptionkeyrotation_encryptionkeyrotation_proto protoreflect.FileDescriptor
var file_encryptionkeyrotation_encryptionkeyrotation_proto_rawDesc = []byte{
0x0a, 0x31, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x6b, 0x65, 0x79, 0x72,
0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x6b, 0x65, 0x79, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x12, 0x15, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x6b,
0x65, 0x79, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x40, 0x67, 0x69, 0x74, 0x68,
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72,
0x2d, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2d, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61,
0x63, 0x65, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x2f, 0x6c, 0x69, 0x62, 0x2f, 0x67, 0x6f, 0x2f, 0x63,
0x73, 0x69, 0x2f, 0x63, 0x73, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x20, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64, 0x65,
0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x8a,
0x04, 0x0a, 0x1a, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79,
0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1b, 0x0a,
0x09, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x08, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x76, 0x6f,
0x6c, 0x75, 0x6d, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
0x0a, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x2a, 0x0a, 0x0e, 0x65,
0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20,
0x01, 0x28, 0x09, 0x42, 0x03, 0x98, 0x42, 0x01, 0x52, 0x0d, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70,
0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x12, 0x61, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d,
0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x65, 0x6e,
0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x6b, 0x65, 0x79, 0x72, 0x6f, 0x74, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65,
0x79, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x50,
0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a,
0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x5d, 0x0a, 0x07, 0x73, 0x65,
0x63, 0x72, 0x65, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x65, 0x6e,
0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x6b, 0x65, 0x79, 0x72, 0x6f, 0x74, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65,
0x79, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x53,
0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x03, 0x98, 0x42, 0x01,
0x52, 0x07, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x12, 0x45, 0x0a, 0x11, 0x76, 0x6f, 0x6c,
0x75, 0x6d, 0x65, 0x5f, 0x63, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x06,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x73, 0x69, 0x2e, 0x76, 0x31, 0x2e, 0x56, 0x6f,
0x6c, 0x75, 0x6d, 0x65, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x52, 0x10,
0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x43, 0x61, 0x70, 0x61, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79,
0x1a, 0x3d, 0x0a, 0x0f, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x45, 0x6e,
0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a,
0x3a, 0x0a, 0x0c, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x1d, 0x0a, 0x1b, 0x45,
0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x6f, 0x74, 0x61,
0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xa1, 0x01, 0x0a, 0x1f, 0x45,
0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x6f, 0x74, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x7e,
0x0a, 0x13, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x52,
0x6f, 0x74, 0x61, 0x74, 0x65, 0x12, 0x31, 0x2e, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69,
0x6f, 0x6e, 0x6b, 0x65, 0x79, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x45, 0x6e,
0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x6f, 0x74, 0x61, 0x74,
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x65, 0x6e, 0x63, 0x72, 0x79,
0x70, 0x74, 0x69, 0x6f, 0x6e, 0x6b, 0x65, 0x79, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x52, 0x6f,
0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x39,
0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x73, 0x69,
0x2d, 0x61, 0x64, 0x64, 0x6f, 0x6e, 0x73, 0x2f, 0x73, 0x70, 0x65, 0x63, 0x2f, 0x6c, 0x69, 0x62,
0x2f, 0x67, 0x6f, 0x2f, 0x65, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x6b, 0x65,
0x79, 0x72, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
}
var (
file_encryptionkeyrotation_encryptionkeyrotation_proto_rawDescOnce sync.Once
file_encryptionkeyrotation_encryptionkeyrotation_proto_rawDescData = file_encryptionkeyrotation_encryptionkeyrotation_proto_rawDesc
)
func file_encryptionkeyrotation_encryptionkeyrotation_proto_rawDescGZIP() []byte {
file_encryptionkeyrotation_encryptionkeyrotation_proto_rawDescOnce.Do(func() {
file_encryptionkeyrotation_encryptionkeyrotation_proto_rawDescData = protoimpl.X.CompressGZIP(file_encryptionkeyrotation_encryptionkeyrotation_proto_rawDescData)
})
return file_encryptionkeyrotation_encryptionkeyrotation_proto_rawDescData
}
var file_encryptionkeyrotation_encryptionkeyrotation_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_encryptionkeyrotation_encryptionkeyrotation_proto_goTypes = []interface{}{
(*EncryptionKeyRotateRequest)(nil), // 0: encryptionkeyrotation.EncryptionKeyRotateRequest
(*EncryptionKeyRotateResponse)(nil), // 1: encryptionkeyrotation.EncryptionKeyRotateResponse
nil, // 2: encryptionkeyrotation.EncryptionKeyRotateRequest.ParametersEntry
nil, // 3: encryptionkeyrotation.EncryptionKeyRotateRequest.SecretsEntry
(*csi.VolumeCapability)(nil), // 4: csi.v1.VolumeCapability
}
var file_encryptionkeyrotation_encryptionkeyrotation_proto_depIdxs = []int32{
2, // 0: encryptionkeyrotation.EncryptionKeyRotateRequest.parameters:type_name -> encryptionkeyrotation.EncryptionKeyRotateRequest.ParametersEntry
3, // 1: encryptionkeyrotation.EncryptionKeyRotateRequest.secrets:type_name -> encryptionkeyrotation.EncryptionKeyRotateRequest.SecretsEntry
4, // 2: encryptionkeyrotation.EncryptionKeyRotateRequest.volume_capability:type_name -> csi.v1.VolumeCapability
0, // 3: encryptionkeyrotation.EncryptionKeyRotationController.EncryptionKeyRotate:input_type -> encryptionkeyrotation.EncryptionKeyRotateRequest
1, // 4: encryptionkeyrotation.EncryptionKeyRotationController.EncryptionKeyRotate:output_type -> encryptionkeyrotation.EncryptionKeyRotateResponse
4, // [4:5] is the sub-list for method output_type
3, // [3:4] is the sub-list for method input_type
3, // [3:3] is the sub-list for extension type_name
3, // [3:3] is the sub-list for extension extendee
0, // [0:3] is the sub-list for field type_name
}
func init() { file_encryptionkeyrotation_encryptionkeyrotation_proto_init() }
func file_encryptionkeyrotation_encryptionkeyrotation_proto_init() {
if File_encryptionkeyrotation_encryptionkeyrotation_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_encryptionkeyrotation_encryptionkeyrotation_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*EncryptionKeyRotateRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_encryptionkeyrotation_encryptionkeyrotation_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*EncryptionKeyRotateResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_encryptionkeyrotation_encryptionkeyrotation_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_encryptionkeyrotation_encryptionkeyrotation_proto_goTypes,
DependencyIndexes: file_encryptionkeyrotation_encryptionkeyrotation_proto_depIdxs,
MessageInfos: file_encryptionkeyrotation_encryptionkeyrotation_proto_msgTypes,
}.Build()
File_encryptionkeyrotation_encryptionkeyrotation_proto = out.File
file_encryptionkeyrotation_encryptionkeyrotation_proto_rawDesc = nil
file_encryptionkeyrotation_encryptionkeyrotation_proto_goTypes = nil
file_encryptionkeyrotation_encryptionkeyrotation_proto_depIdxs = nil
}

View File

@ -0,0 +1,116 @@
// Code generated by make; DO NOT EDIT.
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc v3.20.2
// source: encryptionkeyrotation/encryptionkeyrotation.proto
package encryptionkeyrotation
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
const (
EncryptionKeyRotationController_EncryptionKeyRotate_FullMethodName = "/encryptionkeyrotation.EncryptionKeyRotationController/EncryptionKeyRotate"
)
// EncryptionKeyRotationControllerClient is the client API for EncryptionKeyRotationController service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type EncryptionKeyRotationControllerClient interface {
// EncryptionKeyRotate is a procedure that is called
// on the CSI ControllerPlugin or NodePlugin
EncryptionKeyRotate(ctx context.Context, in *EncryptionKeyRotateRequest, opts ...grpc.CallOption) (*EncryptionKeyRotateResponse, error)
}
type encryptionKeyRotationControllerClient struct {
cc grpc.ClientConnInterface
}
func NewEncryptionKeyRotationControllerClient(cc grpc.ClientConnInterface) EncryptionKeyRotationControllerClient {
return &encryptionKeyRotationControllerClient{cc}
}
func (c *encryptionKeyRotationControllerClient) EncryptionKeyRotate(ctx context.Context, in *EncryptionKeyRotateRequest, opts ...grpc.CallOption) (*EncryptionKeyRotateResponse, error) {
out := new(EncryptionKeyRotateResponse)
err := c.cc.Invoke(ctx, EncryptionKeyRotationController_EncryptionKeyRotate_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// EncryptionKeyRotationControllerServer is the server API for EncryptionKeyRotationController service.
// All implementations must embed UnimplementedEncryptionKeyRotationControllerServer
// for forward compatibility
type EncryptionKeyRotationControllerServer interface {
// EncryptionKeyRotate is a procedure that is called
// on the CSI ControllerPlugin or NodePlugin
EncryptionKeyRotate(context.Context, *EncryptionKeyRotateRequest) (*EncryptionKeyRotateResponse, error)
mustEmbedUnimplementedEncryptionKeyRotationControllerServer()
}
// UnimplementedEncryptionKeyRotationControllerServer must be embedded to have forward compatible implementations.
type UnimplementedEncryptionKeyRotationControllerServer struct {
}
func (UnimplementedEncryptionKeyRotationControllerServer) EncryptionKeyRotate(context.Context, *EncryptionKeyRotateRequest) (*EncryptionKeyRotateResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method EncryptionKeyRotate not implemented")
}
func (UnimplementedEncryptionKeyRotationControllerServer) mustEmbedUnimplementedEncryptionKeyRotationControllerServer() {
}
// UnsafeEncryptionKeyRotationControllerServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to EncryptionKeyRotationControllerServer will
// result in compilation errors.
type UnsafeEncryptionKeyRotationControllerServer interface {
mustEmbedUnimplementedEncryptionKeyRotationControllerServer()
}
func RegisterEncryptionKeyRotationControllerServer(s grpc.ServiceRegistrar, srv EncryptionKeyRotationControllerServer) {
s.RegisterService(&EncryptionKeyRotationController_ServiceDesc, srv)
}
func _EncryptionKeyRotationController_EncryptionKeyRotate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(EncryptionKeyRotateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(EncryptionKeyRotationControllerServer).EncryptionKeyRotate(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: EncryptionKeyRotationController_EncryptionKeyRotate_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(EncryptionKeyRotationControllerServer).EncryptionKeyRotate(ctx, req.(*EncryptionKeyRotateRequest))
}
return interceptor(ctx, in, info, handler)
}
// EncryptionKeyRotationController_ServiceDesc is the grpc.ServiceDesc for EncryptionKeyRotationController service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var EncryptionKeyRotationController_ServiceDesc = grpc.ServiceDesc{
ServiceName: "encryptionkeyrotation.EncryptionKeyRotationController",
HandlerType: (*EncryptionKeyRotationControllerServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "EncryptionKeyRotate",
Handler: _EncryptionKeyRotationController_EncryptionKeyRotate_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "encryptionkeyrotation/encryptionkeyrotation.proto",
}

View File

@ -87,8 +87,8 @@ func get(path string, name string, getxattrFunc getxattrFunc) ([]byte, error) {
initialBufSize = 1024
// The theoretical maximum xattr value size on MacOS is 64 MB. On Linux it's
// much smaller at 64 KB. Unless the kernel is evil or buggy, we should never
// hit the limit.
// much smaller: documented at 64 KB. However, at least on TrueNAS SCALE, a
// Debian-based Linux distro, it can be larger.
maxBufSize = 64 * 1024 * 1024
// Function name as reported in error messages
@ -102,14 +102,15 @@ func get(path string, name string, getxattrFunc getxattrFunc) ([]byte, error) {
// If the buffer was too small to fit the value, Linux and MacOS react
// differently:
// Linux: returns an ERANGE error and "-1" bytes.
// Linux: returns an ERANGE error and "-1" bytes. However, the TrueNAS
// SCALE distro sometimes returns E2BIG.
// MacOS: truncates the value and returns "size" bytes. If the value
// happens to be exactly as big as the buffer, we cannot know if it was
// truncated, and we retry with a bigger buffer. Contrary to documentation,
// MacOS never seems to return ERANGE!
// To keep the code simple, we always check both conditions, and sometimes
// double the buffer size without it being strictly necessary.
if err == syscall.ERANGE || read == size {
if err == syscall.ERANGE || err == syscall.E2BIG || read == size {
// The buffer was too small. Try again.
size <<= 1
if size >= maxBufSize {

View File

@ -24,7 +24,7 @@ const (
)
func getxattr(path string, name string, data []byte) (int, error) {
f, err := os.OpenFile(path, os.O_RDONLY, 0)
f, err := openNonblock(path)
if err != nil {
return 0, err
}
@ -50,7 +50,7 @@ func fgetxattr(f *os.File, name string, data []byte) (int, error) {
}
func setxattr(path string, name string, data []byte, flags int) error {
f, err := os.OpenFile(path, os.O_RDONLY, 0)
f, err := openNonblock(path)
if err != nil {
return err
}
@ -87,7 +87,8 @@ func fsetxattr(f *os.File, name string, data []byte, flags int) error {
}
func removexattr(path string, name string) error {
fd, err := unix.Open(path, unix.O_RDONLY|unix.O_XATTR, 0)
mode := unix.O_RDONLY | unix.O_XATTR | unix.O_NONBLOCK | unix.O_CLOEXEC
fd, err := unix.Open(path, mode, 0)
if err != nil {
return err
}
@ -114,7 +115,7 @@ func fremovexattr(f *os.File, name string) error {
}
func listxattr(path string, data []byte) (int, error) {
f, err := os.OpenFile(path, os.O_RDONLY, 0)
f, err := openNonblock(path)
if err != nil {
return 0, err
}
@ -151,8 +152,17 @@ func flistxattr(f *os.File, data []byte) (int, error) {
return copy(data, buf), nil
}
// Like os.Open, but passes O_NONBLOCK to the open(2) syscall.
func openNonblock(path string) (*os.File, error) {
fd, err := unix.Open(path, unix.O_RDONLY|unix.O_CLOEXEC|unix.O_NONBLOCK, 0)
if err != nil {
return nil, err
}
return os.NewFile(uintptr(fd), path), err
}
// stringsFromByteSlice converts a sequence of attributes to a []string.
// On Darwin and Linux, each entry is a NULL-terminated string.
// We simulate Linux/Darwin, where each entry is a NULL-terminated string.
func stringsFromByteSlice(buf []byte) (result []string) {
offset := 0
for index, b := range buf {

View File

@ -188,7 +188,7 @@ func AddNoNewPrivileges(sc *v1.SecurityContext) bool {
var (
// These *must* be kept in sync with moby/moby.
// https://github.com/moby/moby/blob/master/oci/defaults.go#L105-L123
// https://github.com/moby/moby/blob/master/oci/defaults.go#L105-L124
// @jessfraz will watch changes to those files upstream.
defaultMaskedPaths = []string{
"/proc/asound",
@ -201,6 +201,7 @@ var (
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware",
"/sys/devices/virtual/powercap",
}
defaultReadonlyPaths = []string{
"/proc/bus",

View File

@ -72,9 +72,8 @@ func (fs *DefaultFs) Rename(oldpath, newpath string) error {
return os.Rename(oldpath, newpath)
}
// MkdirAll via os.MkdirAll
func (fs *DefaultFs) MkdirAll(path string, perm os.FileMode) error {
return os.MkdirAll(fs.prefix(path), perm)
return MkdirAll(fs.prefix(path), perm)
}
// MkdirAllWithPathCheck checks if path exists already. If not, it creates a directory
@ -97,7 +96,7 @@ func MkdirAllWithPathCheck(path string, perm os.FileMode) error {
return fmt.Errorf("path %v exists but is not a directory", path)
}
// If existence of path not known, attempt to create it.
if err := os.MkdirAll(path, perm); err != nil {
if err := MkdirAll(path, perm); err != nil {
return err
}
return nil

View File

@ -37,6 +37,16 @@ func IsUnixDomainSocket(filePath string) (bool, error) {
return true, nil
}
// Chmod is the same as os.Chmod on Linux.
func Chmod(name string, mode os.FileMode) error {
return os.Chmod(name, mode)
}
// MkdirAll is the same as os.MkdirAll on Linux.
func MkdirAll(path string, perm os.FileMode) error {
return os.MkdirAll(path, perm)
}
// IsAbs is same as filepath.IsAbs on Unix.
func IsAbs(path string) bool {
return filepath.IsAbs(path)

View File

@ -29,6 +29,8 @@ import (
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/klog/v2"
"golang.org/x/sys/windows"
)
const (
@ -88,6 +90,160 @@ func IsUnixDomainSocket(filePath string) (bool, error) {
return true, nil
}
// On Windows os.Mkdir all doesn't set any permissions so call the Chown function below to set
// permissions once the directory is created.
func MkdirAll(path string, perm os.FileMode) error {
klog.V(6).InfoS("Function MkdirAll starts", "path", path, "perm", perm)
err := os.MkdirAll(path, perm)
if err != nil {
return fmt.Errorf("Error creating directory %s: %v", path, err)
}
err = Chmod(path, perm)
if err != nil {
return fmt.Errorf("Error setting permissions for directory %s: %v", path, err)
}
return nil
}
const (
// These aren't defined in the syscall package for Windows :(
USER_READ = 0x100
USER_WRITE = 0x80
USER_EXECUTE = 0x40
GROUP_READ = 0x20
GROUP_WRITE = 0x10
GROUP_EXECUTE = 0x8
OTHERS_READ = 0x4
OTHERS_WRITE = 0x2
OTHERS_EXECUTE = 0x1
USER_ALL = USER_READ | USER_WRITE | USER_EXECUTE
GROUP_ALL = GROUP_READ | GROUP_WRITE | GROUP_EXECUTE
OTHERS_ALL = OTHERS_READ | OTHERS_WRITE | OTHERS_EXECUTE
)
// On Windows os.Chmod only sets the read-only flag on files, so we need to use Windows APIs to set the desired access on files / directories.
// The OWNER mode will set file permissions for the file owner SID, the GROUP mode will set file permissions for the file group SID,
// and the OTHERS mode will set file permissions for BUILTIN\Users.
// Please note that Windows containers can be run as one of two user accounts; ContainerUser or ContainerAdministrator.
// Containers run as ContainerAdministrator will inherit permissions from BUILTIN\Administrators,
// while containers run as ContainerUser will inherit permissions from BUILTIN\Users.
// Windows containers do not have the ability to run as a custom user account that is known to the host so the OTHERS group mode
// is used to grant / deny permissions of files on the hosts to the ContainerUser account.
func Chmod(path string, filemode os.FileMode) error {
klog.V(6).InfoS("Function Chmod starts", "path", path, "filemode", filemode)
// Get security descriptor for the file
sd, err := windows.GetNamedSecurityInfo(
path,
windows.SE_FILE_OBJECT,
windows.DACL_SECURITY_INFORMATION|windows.PROTECTED_DACL_SECURITY_INFORMATION|windows.OWNER_SECURITY_INFORMATION|windows.GROUP_SECURITY_INFORMATION)
if err != nil {
return fmt.Errorf("Error getting security descriptor for file %s: %v", path, err)
}
// Get owner SID from the security descriptor for assigning USER permissions
owner, _, err := sd.Owner()
if err != nil {
return fmt.Errorf("Error getting owner SID for file %s: %v", path, err)
}
ownerString := owner.String()
// Get the group SID from the security descriptor for assigning GROUP permissions
group, _, err := sd.Group()
if err != nil {
return fmt.Errorf("Error getting group SID for file %s: %v", path, err)
}
groupString := group.String()
mask := uint32(windows.ACCESS_MASK(filemode))
// Build a new Discretionary Access Control List (DACL) with the desired permissions using
//the Security Descriptor Definition Language (SDDL) format.
// https://learn.microsoft.com/windows/win32/secauthz/security-descriptor-definition-language
// the DACL is a list of Access Control Entries (ACEs) where each ACE represents the permissions (Allow or Deny) for a specific SID.
// Each ACE has the following format:
// (AceType;AceFlags;Rights;ObjectGuid;InheritObjectGuid;AccountSid)
// We can leave ObjectGuid and InheritObjectGuid empty for our purposes.
dacl := "D:"
// build the owner ACE
dacl += "(A;OICI;"
if mask&USER_ALL == USER_ALL {
dacl += "FA"
} else {
if mask&USER_READ == USER_READ {
dacl += "FR"
}
if mask&USER_WRITE == USER_WRITE {
dacl += "FW"
}
if mask&USER_EXECUTE == USER_EXECUTE {
dacl += "FX"
}
}
dacl += ";;;" + ownerString + ")"
// Build the group ACE
dacl += "(A;OICI;"
if mask&GROUP_ALL == GROUP_ALL {
dacl += "FA"
} else {
if mask&GROUP_READ == GROUP_READ {
dacl += "FR"
}
if mask&GROUP_WRITE == GROUP_WRITE {
dacl += "FW"
}
if mask&GROUP_EXECUTE == GROUP_EXECUTE {
dacl += "FX"
}
}
dacl += ";;;" + groupString + ")"
// Build the others ACE
dacl += "(A;OICI;"
if mask&OTHERS_ALL == OTHERS_ALL {
dacl += "FA"
} else {
if mask&OTHERS_READ == OTHERS_READ {
dacl += "FR"
}
if mask&OTHERS_WRITE == OTHERS_WRITE {
dacl += "FW"
}
if mask&OTHERS_EXECUTE == OTHERS_EXECUTE {
dacl += "FX"
}
}
dacl += ";;;BU)"
klog.V(6).InfoS("Setting new DACL for path", "path", path, "dacl", dacl)
// create a new security descriptor from the DACL string
newSD, err := windows.SecurityDescriptorFromString(dacl)
if err != nil {
return fmt.Errorf("Error creating new security descriptor from DACL string: %v", err)
}
// get the DACL in binary format from the newly created security descriptor
newDACL, _, err := newSD.DACL()
if err != nil {
return fmt.Errorf("Error getting DACL from new security descriptor: %v", err)
}
// Write the new security descriptor to the file
return windows.SetNamedSecurityInfo(
path,
windows.SE_FILE_OBJECT,
windows.DACL_SECURITY_INFORMATION|windows.PROTECTED_DACL_SECURITY_INFORMATION,
nil, // owner SID
nil, // group SID
newDACL,
nil) // SACL
}
// IsAbs returns whether the given path is absolute or not.
// On Windows, filepath.IsAbs will not return True for paths prefixed with a slash, even
// though they can be used as absolute paths (https://docs.microsoft.com/en-us/dotnet/standard/io/file-path-formats).

View File

@ -237,7 +237,7 @@ func initImageConfigs(list RegistryList) (map[ImageID]Config, map[ImageID]Config
configs[BusyBox] = Config{list.PromoterE2eRegistry, "busybox", "1.36.1-1"}
configs[CudaVectorAdd] = Config{list.PromoterE2eRegistry, "cuda-vector-add", "1.0"}
configs[CudaVectorAdd2] = Config{list.PromoterE2eRegistry, "cuda-vector-add", "2.3"}
configs[DistrolessIptables] = Config{list.BuildImageRegistry, "distroless-iptables", "v0.5.5"}
configs[DistrolessIptables] = Config{list.BuildImageRegistry, "distroless-iptables", "v0.5.6"}
configs[Etcd] = Config{list.GcEtcdRegistry, "etcd", "3.5.12-0"}
configs[Httpd] = Config{list.PromoterE2eRegistry, "httpd", "2.4.38-4"}
configs[HttpdNew] = Config{list.PromoterE2eRegistry, "httpd", "2.4.39-4"}

89
vendor/modules.txt vendored
View File

@ -81,7 +81,7 @@ github.com/antlr/antlr4/runtime/Go/antlr/v4
# github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a
## explicit
github.com/asaskevich/govalidator
# github.com/aws/aws-sdk-go v1.54.19
# github.com/aws/aws-sdk-go v1.55.0
## explicit; go 1.19
github.com/aws/aws-sdk-go/aws
github.com/aws/aws-sdk-go/aws/auth/bearer
@ -236,8 +236,9 @@ github.com/coreos/go-semver/semver
## explicit; go 1.12
github.com/coreos/go-systemd/v22/daemon
github.com/coreos/go-systemd/v22/journal
# github.com/csi-addons/spec v0.2.1-0.20240627093359-0dd74d521e67
# github.com/csi-addons/spec v0.2.1-0.20240718113938-dc98b454ba65
## explicit
github.com/csi-addons/spec/lib/go/encryptionkeyrotation
github.com/csi-addons/spec/lib/go/fence
github.com/csi-addons/spec/lib/go/identity
github.com/csi-addons/spec/lib/go/reclaimspace
@ -567,7 +568,7 @@ github.com/pkg/browser
# github.com/pkg/errors v0.9.1
## explicit
github.com/pkg/errors
# github.com/pkg/xattr v0.4.9
# github.com/pkg/xattr v0.4.10
## explicit; go 1.14
github.com/pkg/xattr
# github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2
@ -931,7 +932,7 @@ gopkg.in/yaml.v2
# gopkg.in/yaml.v3 v3.0.1
## explicit
gopkg.in/yaml.v3
# k8s.io/api v0.30.2 => k8s.io/api v0.30.2
# k8s.io/api v0.30.3 => k8s.io/api v0.30.3
## explicit; go 1.22.0
k8s.io/api/admission/v1
k8s.io/api/admission/v1beta1
@ -989,12 +990,12 @@ k8s.io/api/storage/v1
k8s.io/api/storage/v1alpha1
k8s.io/api/storage/v1beta1
k8s.io/api/storagemigration/v1alpha1
# k8s.io/apiextensions-apiserver v0.30.1 => k8s.io/apiextensions-apiserver v0.30.2
# k8s.io/apiextensions-apiserver v0.30.1 => k8s.io/apiextensions-apiserver v0.30.3
## explicit; go 1.22.0
k8s.io/apiextensions-apiserver/pkg/apis/apiextensions
k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1
k8s.io/apiextensions-apiserver/pkg/features
# k8s.io/apimachinery v0.30.2 => k8s.io/apimachinery v0.30.2
# k8s.io/apimachinery v0.30.3 => k8s.io/apimachinery v0.30.3
## explicit; go 1.22.0
k8s.io/apimachinery/pkg/api/equality
k8s.io/apimachinery/pkg/api/errors
@ -1058,7 +1059,7 @@ k8s.io/apimachinery/pkg/watch
k8s.io/apimachinery/third_party/forked/golang/json
k8s.io/apimachinery/third_party/forked/golang/netutil
k8s.io/apimachinery/third_party/forked/golang/reflect
# k8s.io/apiserver v0.30.2 => k8s.io/apiserver v0.30.2
# k8s.io/apiserver v0.30.3 => k8s.io/apiserver v0.30.3
## explicit; go 1.22.0
k8s.io/apiserver/pkg/admission
k8s.io/apiserver/pkg/admission/configuration
@ -1206,7 +1207,7 @@ k8s.io/apiserver/plugin/pkg/audit/webhook
k8s.io/apiserver/plugin/pkg/authenticator/token/webhook
k8s.io/apiserver/plugin/pkg/authorizer/webhook
k8s.io/apiserver/plugin/pkg/authorizer/webhook/metrics
# k8s.io/client-go v12.0.0+incompatible => k8s.io/client-go v0.30.2
# k8s.io/client-go v12.0.0+incompatible => k8s.io/client-go v0.30.3
## explicit; go 1.22.0
k8s.io/client-go/applyconfigurations/admissionregistration/v1
k8s.io/client-go/applyconfigurations/admissionregistration/v1alpha1
@ -1540,7 +1541,7 @@ k8s.io/client-go/util/homedir
k8s.io/client-go/util/keyutil
k8s.io/client-go/util/retry
k8s.io/client-go/util/workqueue
# k8s.io/cloud-provider v0.30.2 => k8s.io/cloud-provider v0.30.2
# k8s.io/cloud-provider v0.30.3 => k8s.io/cloud-provider v0.30.3
## explicit; go 1.22.0
k8s.io/cloud-provider
k8s.io/cloud-provider/app/config
@ -1555,7 +1556,7 @@ k8s.io/cloud-provider/names
k8s.io/cloud-provider/options
k8s.io/cloud-provider/volume
k8s.io/cloud-provider/volume/helpers
# k8s.io/component-base v0.30.2 => k8s.io/component-base v0.30.2
# k8s.io/component-base v0.30.3 => k8s.io/component-base v0.30.3
## explicit; go 1.22.0
k8s.io/component-base/cli/flag
k8s.io/component-base/config
@ -1578,13 +1579,13 @@ k8s.io/component-base/metrics/testutil
k8s.io/component-base/tracing
k8s.io/component-base/tracing/api/v1
k8s.io/component-base/version
# k8s.io/component-helpers v0.30.2 => k8s.io/component-helpers v0.30.2
# k8s.io/component-helpers v0.30.3 => k8s.io/component-helpers v0.30.3
## explicit; go 1.22.0
k8s.io/component-helpers/node/util/sysctl
k8s.io/component-helpers/scheduling/corev1
k8s.io/component-helpers/scheduling/corev1/nodeaffinity
k8s.io/component-helpers/storage/volume
# k8s.io/controller-manager v0.30.2 => k8s.io/controller-manager v0.30.2
# k8s.io/controller-manager v0.30.3 => k8s.io/controller-manager v0.30.3
## explicit; go 1.22.0
k8s.io/controller-manager/config
k8s.io/controller-manager/config/v1
@ -1607,7 +1608,7 @@ k8s.io/klog/v2/internal/severity
k8s.io/klog/v2/internal/sloghandler
k8s.io/klog/v2/internal/verbosity
k8s.io/klog/v2/textlogger
# k8s.io/kms v0.30.2
# k8s.io/kms v0.30.3
## explicit; go 1.22.0
k8s.io/kms/apis/v1beta1
k8s.io/kms/apis/v2
@ -1634,15 +1635,15 @@ k8s.io/kube-openapi/pkg/validation/errors
k8s.io/kube-openapi/pkg/validation/spec
k8s.io/kube-openapi/pkg/validation/strfmt
k8s.io/kube-openapi/pkg/validation/strfmt/bson
# k8s.io/kubectl v0.0.0 => k8s.io/kubectl v0.30.2
# k8s.io/kubectl v0.0.0 => k8s.io/kubectl v0.30.3
## explicit; go 1.22.0
k8s.io/kubectl/pkg/scale
k8s.io/kubectl/pkg/util/podutils
# k8s.io/kubelet v0.0.0 => k8s.io/kubelet v0.30.2
# k8s.io/kubelet v0.0.0 => k8s.io/kubelet v0.30.3
## explicit; go 1.22.0
k8s.io/kubelet/pkg/apis
k8s.io/kubelet/pkg/apis/stats/v1alpha1
# k8s.io/kubernetes v1.30.2
# k8s.io/kubernetes v1.30.3
## explicit; go 1.22.0
k8s.io/kubernetes/pkg/api/legacyscheme
k8s.io/kubernetes/pkg/api/service
@ -1707,10 +1708,10 @@ k8s.io/kubernetes/test/utils
k8s.io/kubernetes/test/utils/format
k8s.io/kubernetes/test/utils/image
k8s.io/kubernetes/test/utils/kubeconfig
# k8s.io/mount-utils v0.30.2 => k8s.io/mount-utils v0.29.3
# k8s.io/mount-utils v0.30.3 => k8s.io/mount-utils v0.29.3
## explicit; go 1.21
k8s.io/mount-utils
# k8s.io/pod-security-admission v0.30.2 => k8s.io/pod-security-admission v0.30.2
# k8s.io/pod-security-admission v0.30.3 => k8s.io/pod-security-admission v0.30.3
## explicit; go 1.22.0
k8s.io/pod-security-admission/api
k8s.io/pod-security-admission/policy
@ -1798,31 +1799,31 @@ sigs.k8s.io/yaml/goyaml.v2
# github.com/prometheus/client_golang => github.com/prometheus/client_golang v1.18.0
# github.com/prometheus/common => github.com/prometheus/common v0.47.0
# gomodules.xyz/jsonpatch/v2 => github.com/gomodules/jsonpatch/v2 v2.2.0
# k8s.io/api => k8s.io/api v0.30.2
# k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.30.2
# k8s.io/apimachinery => k8s.io/apimachinery v0.30.2
# k8s.io/apiserver => k8s.io/apiserver v0.30.2
# k8s.io/cli-runtime => k8s.io/cli-runtime v0.30.2
# k8s.io/client-go => k8s.io/client-go v0.30.2
# k8s.io/cloud-provider => k8s.io/cloud-provider v0.30.2
# k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.30.2
# k8s.io/code-generator => k8s.io/code-generator v0.30.2
# k8s.io/component-base => k8s.io/component-base v0.30.2
# k8s.io/component-helpers => k8s.io/component-helpers v0.30.2
# k8s.io/controller-manager => k8s.io/controller-manager v0.30.2
# k8s.io/cri-api => k8s.io/cri-api v0.30.2
# k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.30.2
# k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.30.2
# k8s.io/endpointslice => k8s.io/endpointslice v0.30.2
# k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.30.2
# k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.30.2
# k8s.io/kube-proxy => k8s.io/kube-proxy v0.30.2
# k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.30.2
# k8s.io/kubectl => k8s.io/kubectl v0.30.2
# k8s.io/kubelet => k8s.io/kubelet v0.30.2
# k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.30.2
# k8s.io/metrics => k8s.io/metrics v0.30.2
# k8s.io/api => k8s.io/api v0.30.3
# k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.30.3
# k8s.io/apimachinery => k8s.io/apimachinery v0.30.3
# k8s.io/apiserver => k8s.io/apiserver v0.30.3
# k8s.io/cli-runtime => k8s.io/cli-runtime v0.30.3
# k8s.io/client-go => k8s.io/client-go v0.30.3
# k8s.io/cloud-provider => k8s.io/cloud-provider v0.30.3
# k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.30.3
# k8s.io/code-generator => k8s.io/code-generator v0.30.3
# k8s.io/component-base => k8s.io/component-base v0.30.3
# k8s.io/component-helpers => k8s.io/component-helpers v0.30.3
# k8s.io/controller-manager => k8s.io/controller-manager v0.30.3
# k8s.io/cri-api => k8s.io/cri-api v0.30.3
# k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.30.3
# k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.30.3
# k8s.io/endpointslice => k8s.io/endpointslice v0.30.3
# k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.30.3
# k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.30.3
# k8s.io/kube-proxy => k8s.io/kube-proxy v0.30.3
# k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.30.3
# k8s.io/kubectl => k8s.io/kubectl v0.30.3
# k8s.io/kubelet => k8s.io/kubelet v0.30.3
# k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.30.3
# k8s.io/metrics => k8s.io/metrics v0.30.3
# k8s.io/mount-utils => k8s.io/mount-utils v0.29.3
# k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.30.2
# k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.30.2
# k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.30.3
# k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.30.3
# layeh.com/radius => github.com/layeh/radius v0.0.0-20190322222518-890bc1058917