mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-01-18 02:39:30 +00:00
Merge pull request #348 from red-hat-storage/sync_ds--devel
Syncing latest changes from devel for ceph-csi
This commit is contained in:
commit
c3338b3430
@ -6,7 +6,7 @@ require (
|
|||||||
github.com/ghodss/yaml v1.0.0
|
github.com/ghodss/yaml v1.0.0
|
||||||
github.com/openshift/api v0.0.0-20240115183315-0793e918179d
|
github.com/openshift/api v0.0.0-20240115183315-0793e918179d
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
k8s.io/api v0.30.2
|
k8s.io/api v0.30.3
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
@ -23,7 +23,7 @@ require (
|
|||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // 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/klog/v2 v2.120.1 // indirect
|
||||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
|
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
|
||||||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
|
||||||
|
@ -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.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 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
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.3 h1:ImHwK9DCsPA9uoU3rVh4QHAHHK5dTSv1nxJUapx8hoQ=
|
||||||
k8s.io/api v0.30.2/go.mod h1:ULg5g9JvOev2dG0u2hig4Z7tQ2hHIuS+m8MNZ+X6EmI=
|
k8s.io/api v0.30.3/go.mod h1:GPc8jlzoe5JG3pb0KJCSLX5oAFIW3/qNJITlDj8BH04=
|
||||||
k8s.io/apimachinery v0.30.2 h1:fEMcnBj6qkzzPGSVsAZtQThU62SmQ4ZymlXRC5yFSCg=
|
k8s.io/apimachinery v0.30.3 h1:q1laaWCmrszyQuSQCfNB8cFgCuDAoPszKY4ucAjDwHc=
|
||||||
k8s.io/apimachinery v0.30.2/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
|
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 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
|
||||||
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
|
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
|
||||||
|
4
api/vendor/modules.txt
vendored
4
api/vendor/modules.txt
vendored
@ -55,12 +55,12 @@ gopkg.in/yaml.v2
|
|||||||
# gopkg.in/yaml.v3 v3.0.1
|
# gopkg.in/yaml.v3 v3.0.1
|
||||||
## explicit
|
## explicit
|
||||||
gopkg.in/yaml.v3
|
gopkg.in/yaml.v3
|
||||||
# k8s.io/api v0.30.2
|
# k8s.io/api v0.30.3
|
||||||
## explicit; go 1.22.0
|
## explicit; go 1.22.0
|
||||||
k8s.io/api/core/v1
|
k8s.io/api/core/v1
|
||||||
k8s.io/api/rbac/v1
|
k8s.io/api/rbac/v1
|
||||||
k8s.io/api/storage/v1
|
k8s.io/api/storage/v1
|
||||||
# k8s.io/apimachinery v0.30.2
|
# k8s.io/apimachinery v0.30.3
|
||||||
## explicit; go 1.22.0
|
## explicit; go 1.22.0
|
||||||
k8s.io/apimachinery/pkg/api/resource
|
k8s.io/apimachinery/pkg/api/resource
|
||||||
k8s.io/apimachinery/pkg/apis/meta/v1
|
k8s.io/apimachinery/pkg/apis/meta/v1
|
||||||
|
@ -18,14 +18,14 @@ the code and will be pointed out in the review process:
|
|||||||
|
|
||||||
### Imports
|
### Imports
|
||||||
|
|
||||||
We use the following convention for specifying imports:
|
We prefer the following convention for specifying imports:
|
||||||
|
|
||||||
```
|
```
|
||||||
<import standard library packages>
|
<import standard library packages>
|
||||||
|
|
||||||
<import ceph-csi packages>
|
|
||||||
|
|
||||||
<import third-party packages>
|
<import third-party packages>
|
||||||
|
|
||||||
|
<import ceph-csi packages>
|
||||||
```
|
```
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
@ -37,9 +37,9 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/ceph/ceph-csi/internal/util"
|
|
||||||
|
|
||||||
"github.com/pborman/uuid"
|
"github.com/pborman/uuid"
|
||||||
|
|
||||||
|
"github.com/ceph/ceph-csi/internal/util"
|
||||||
)
|
)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
80
go.mod
80
go.mod
@ -4,12 +4,12 @@ go 1.22.0
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/IBM/keyprotect-go-client v0.14.3
|
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/aws/aws-sdk-go-v2/service/sts v1.30.3
|
||||||
github.com/ceph/ceph-csi/api v0.0.0-00010101000000-000000000000
|
github.com/ceph/ceph-csi/api v0.0.0-00010101000000-000000000000
|
||||||
github.com/ceph/go-ceph v0.28.0
|
github.com/ceph/go-ceph v0.28.0
|
||||||
github.com/container-storage-interface/spec v1.10.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/gemalto/kmip-go v0.0.10
|
||||||
github.com/golang/protobuf v1.5.4
|
github.com/golang/protobuf v1.5.4
|
||||||
github.com/google/fscrypt v0.3.6-0.20240502174735-068b9f8f5dec
|
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/libopenstorage/secrets v0.0.0-20231011182615-5f4b25ceede1
|
||||||
github.com/onsi/ginkgo/v2 v2.19.0
|
github.com/onsi/ginkgo/v2 v2.19.0
|
||||||
github.com/onsi/gomega v1.33.1
|
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/prometheus/client_golang v1.19.1
|
||||||
github.com/stretchr/testify v1.9.0
|
github.com/stretchr/testify v1.9.0
|
||||||
golang.org/x/crypto v0.25.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
|
// when updating k8s.io/kubernetes, make sure to update the replace section too
|
||||||
//
|
//
|
||||||
k8s.io/api v0.30.2
|
k8s.io/api v0.30.3
|
||||||
k8s.io/apimachinery v0.30.2
|
k8s.io/apimachinery v0.30.3
|
||||||
k8s.io/client-go v12.0.0+incompatible
|
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/klog/v2 v2.130.1
|
||||||
k8s.io/kubernetes v1.30.2
|
k8s.io/kubernetes v1.30.3
|
||||||
k8s.io/mount-utils v0.30.2
|
k8s.io/mount-utils v0.30.3
|
||||||
k8s.io/pod-security-admission v0.30.2
|
k8s.io/pod-security-admission v0.30.3
|
||||||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
|
k8s.io/utils v0.0.0-20230726121419-3b25d923346b
|
||||||
sigs.k8s.io/controller-runtime v0.18.4
|
sigs.k8s.io/controller-runtime v0.18.4
|
||||||
)
|
)
|
||||||
@ -172,11 +172,11 @@ require (
|
|||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
k8s.io/apiextensions-apiserver v0.30.1 // indirect
|
k8s.io/apiextensions-apiserver v0.30.1 // indirect
|
||||||
k8s.io/apiserver v0.30.2 // indirect
|
k8s.io/apiserver v0.30.3 // indirect
|
||||||
k8s.io/component-base v0.30.2 // indirect
|
k8s.io/component-base v0.30.3 // indirect
|
||||||
k8s.io/component-helpers v0.30.2 // indirect
|
k8s.io/component-helpers v0.30.3 // indirect
|
||||||
k8s.io/controller-manager v0.30.2 // indirect
|
k8s.io/controller-manager v0.30.3 // indirect
|
||||||
k8s.io/kms v0.30.2 // indirect
|
k8s.io/kms v0.30.3 // indirect
|
||||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
|
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
|
||||||
k8s.io/kubectl v0.0.0 // indirect
|
k8s.io/kubectl v0.0.0 // indirect
|
||||||
k8s.io/kubelet 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/kubernetes depends on these k8s.io packages, but unversioned
|
||||||
//
|
//
|
||||||
k8s.io/api => k8s.io/api v0.30.2
|
k8s.io/api => k8s.io/api v0.30.3
|
||||||
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.30.2
|
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.30.3
|
||||||
k8s.io/apimachinery => k8s.io/apimachinery v0.30.2
|
k8s.io/apimachinery => k8s.io/apimachinery v0.30.3
|
||||||
k8s.io/apiserver => k8s.io/apiserver v0.30.2
|
k8s.io/apiserver => k8s.io/apiserver v0.30.3
|
||||||
k8s.io/cli-runtime => k8s.io/cli-runtime v0.30.2
|
k8s.io/cli-runtime => k8s.io/cli-runtime v0.30.3
|
||||||
k8s.io/client-go => k8s.io/client-go v0.30.2
|
k8s.io/client-go => k8s.io/client-go v0.30.3
|
||||||
k8s.io/cloud-provider => k8s.io/cloud-provider v0.30.2
|
k8s.io/cloud-provider => k8s.io/cloud-provider v0.30.3
|
||||||
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.30.2
|
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.30.3
|
||||||
k8s.io/code-generator => k8s.io/code-generator v0.30.2
|
k8s.io/code-generator => k8s.io/code-generator v0.30.3
|
||||||
k8s.io/component-base => k8s.io/component-base v0.30.2
|
k8s.io/component-base => k8s.io/component-base v0.30.3
|
||||||
k8s.io/component-helpers => k8s.io/component-helpers v0.30.2
|
k8s.io/component-helpers => k8s.io/component-helpers v0.30.3
|
||||||
k8s.io/controller-manager => k8s.io/controller-manager v0.30.2
|
k8s.io/controller-manager => k8s.io/controller-manager v0.30.3
|
||||||
k8s.io/cri-api => k8s.io/cri-api v0.30.2
|
k8s.io/cri-api => k8s.io/cri-api v0.30.3
|
||||||
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.30.2
|
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.2
|
k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.30.3
|
||||||
k8s.io/endpointslice => k8s.io/endpointslice v0.30.2
|
k8s.io/endpointslice => k8s.io/endpointslice v0.30.3
|
||||||
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.30.2
|
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.30.3
|
||||||
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.30.2
|
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.30.3
|
||||||
k8s.io/kube-proxy => k8s.io/kube-proxy v0.30.2
|
k8s.io/kube-proxy => k8s.io/kube-proxy v0.30.3
|
||||||
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.30.2
|
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.30.3
|
||||||
k8s.io/kubectl => k8s.io/kubectl v0.30.2
|
k8s.io/kubectl => k8s.io/kubectl v0.30.3
|
||||||
k8s.io/kubelet => k8s.io/kubelet v0.30.2
|
k8s.io/kubelet => k8s.io/kubelet v0.30.3
|
||||||
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.30.2
|
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.30.3
|
||||||
k8s.io/metrics => k8s.io/metrics v0.30.2
|
k8s.io/metrics => k8s.io/metrics v0.30.3
|
||||||
|
|
||||||
// TODO: replace with latest once https://github.com/ceph/ceph-csi/issues/4633 is fixed
|
// 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/mount-utils => k8s.io/mount-utils v0.29.3
|
||||||
k8s.io/pod-security-admission => k8s.io/pod-security-admission 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.2
|
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.30.3
|
||||||
// layeh.com seems to be misbehaving
|
// layeh.com seems to be misbehaving
|
||||||
layeh.com/radius => github.com/layeh/radius v0.0.0-20190322222518-890bc1058917
|
layeh.com/radius => github.com/layeh/radius v0.0.0-20190322222518-890bc1058917
|
||||||
)
|
)
|
||||||
|
74
go.sum
74
go.sum
@ -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 h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
|
||||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
|
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.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.55.0 h1:hVALKPjXz33kP1R9nTyJpUK7qF59dO2mleQxUW9mCVE=
|
||||||
github.com/aws/aws-sdk-go v1.54.19/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
|
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 h1:jUeBtG0Ih+ZIFH0F4UkmL9w3cSpaMv9tYYDbzILP8dY=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.30.3/go.mod h1:nIQjQVp5sfpQcTc9mPSr1B0PaWK5ByX9MOoDadSN4lc=
|
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=
|
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.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/creack/pty v1.1.11/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/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.20240718113938-dc98b454ba65 h1:i9JGGQTEmRQXSpQQPR96+DV4D4o+V1+gjAWf+bpxQxk=
|
||||||
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/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.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.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
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/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.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||||
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
|
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.10 h1:Qe0mtiNFHQZ296vRgUjRCoPHPqH7VdTOrZx3g0T+pGA=
|
||||||
github.com/pkg/xattr v0.4.9/go.mod h1:di8WF84zAKk8jzR1UBTEWh9AUlIZZ7M/JNt8e9B6ktU=
|
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.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 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
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.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.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
|
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.3 h1:ImHwK9DCsPA9uoU3rVh4QHAHHK5dTSv1nxJUapx8hoQ=
|
||||||
k8s.io/api v0.30.2/go.mod h1:ULg5g9JvOev2dG0u2hig4Z7tQ2hHIuS+m8MNZ+X6EmI=
|
k8s.io/api v0.30.3/go.mod h1:GPc8jlzoe5JG3pb0KJCSLX5oAFIW3/qNJITlDj8BH04=
|
||||||
k8s.io/apiextensions-apiserver v0.30.2 h1:l7Eue2t6QiLHErfn2vwK4KgF4NeDgjQkCXtEbOocKIE=
|
k8s.io/apiextensions-apiserver v0.30.3 h1:oChu5li2vsZHx2IvnGP3ah8Nj3KyqG3kRSaKmijhB9U=
|
||||||
k8s.io/apiextensions-apiserver v0.30.2/go.mod h1:lsJFLYyK40iguuinsb3nt+Sj6CmodSI4ACDLep1rgjw=
|
k8s.io/apiextensions-apiserver v0.30.3/go.mod h1:uhXxYDkMAvl6CJw4lrDN4CPbONkF3+XL9cacCT44kV4=
|
||||||
k8s.io/apimachinery v0.30.2 h1:fEMcnBj6qkzzPGSVsAZtQThU62SmQ4ZymlXRC5yFSCg=
|
k8s.io/apimachinery v0.30.3 h1:q1laaWCmrszyQuSQCfNB8cFgCuDAoPszKY4ucAjDwHc=
|
||||||
k8s.io/apimachinery v0.30.2/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
|
k8s.io/apimachinery v0.30.3/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
|
||||||
k8s.io/apiserver v0.30.2 h1:ACouHiYl1yFI2VFI3YGM+lvxgy6ir4yK2oLOsLI1/tw=
|
k8s.io/apiserver v0.30.3 h1:QZJndA9k2MjFqpnyYv/PH+9PE0SHhx3hBho4X0vE65g=
|
||||||
k8s.io/apiserver v0.30.2/go.mod h1:BOTdFBIch9Sv0ypSEcUR6ew/NUFGocRFNl72Ra7wTm8=
|
k8s.io/apiserver v0.30.3/go.mod h1:6Oa88y1CZqnzetd2JdepO0UXzQX4ZnOekx2/PtEjrOg=
|
||||||
k8s.io/client-go v0.30.2 h1:sBIVJdojUNPDU/jObC+18tXWcTJVcwyqS9diGdWHk50=
|
k8s.io/client-go v0.30.3 h1:bHrJu3xQZNXIi8/MoxYtZBBWQQXwy16zqJwloXXfD3k=
|
||||||
k8s.io/client-go v0.30.2/go.mod h1:JglKSWULm9xlJLx4KCkfLLQ7XwtlbflV6uFFSHTMgVs=
|
k8s.io/client-go v0.30.3/go.mod h1:8d4pf8vYu665/kUbsxWAQ/JDBNWqfFeZnvFiVdmx89U=
|
||||||
k8s.io/cloud-provider v0.30.2 h1:yov6r02v7sMUNNvzEz51LtL2krn2c1wsC+dy/8BxKQI=
|
k8s.io/cloud-provider v0.30.3 h1:SNWZmllTymOTzIPJuhtZH6il/qVi75dQARRQAm9k6VY=
|
||||||
k8s.io/cloud-provider v0.30.2/go.mod h1:w69t2dSjDtI9BYK6SEqj6HmMKIojEk08fXRoUzjFN2I=
|
k8s.io/cloud-provider v0.30.3/go.mod h1:Ax0AVdHnM7tMYnJH1Ycy4SMBD98+4zA+tboUR9eYsY8=
|
||||||
k8s.io/code-generator v0.30.2/go.mod h1:RQP5L67QxqgkVquk704CyvWFIq0e6RCMmLTXxjE8dVA=
|
k8s.io/code-generator v0.30.3/go.mod h1:PFgBiv+miFV7TZYp+RXgROkhA+sWYZ+mtpbMLofMke8=
|
||||||
k8s.io/component-base v0.30.2 h1:pqGBczYoW1sno8q9ObExUqrYSKhtE5rW3y6gX88GZII=
|
k8s.io/component-base v0.30.3 h1:Ci0UqKWf4oiwy8hr1+E3dsnliKnkMLZMVbWzeorlk7s=
|
||||||
k8s.io/component-base v0.30.2/go.mod h1:yQLkQDrkK8J6NtP+MGJOws+/PPeEXNpwFixsUI7h/OE=
|
k8s.io/component-base v0.30.3/go.mod h1:C1SshT3rGPCuNtBs14RmVD2xW0EhRSeLvBh7AGk1quA=
|
||||||
k8s.io/component-helpers v0.30.2 h1:kDMYLiWEYeWU7H6jBI+Ua1i2hqNh0DzqDHNIppFC3po=
|
k8s.io/component-helpers v0.30.3 h1:KPc8l0eGx9Wg2OcKc58k9ozNcVcOInAi3NGiuS2xJ/c=
|
||||||
k8s.io/component-helpers v0.30.2/go.mod h1:tI0anfS6AbRqooaICkGg7UVAQLedOauVSQW9srDBnJw=
|
k8s.io/component-helpers v0.30.3/go.mod h1:VOQ7g3q+YbKWwKeACG2BwPv4ftaN8jXYJ5U3xpzuYAE=
|
||||||
k8s.io/controller-manager v0.30.2 h1:tC7V7IdGUW2I4de3bXx4m2fS3naP7VlCYlECCajK9fU=
|
k8s.io/controller-manager v0.30.3 h1:QRFGkWWD5gi/KCSU0qxyUoZRbt+BKgiCUXiTD1RO95w=
|
||||||
k8s.io/controller-manager v0.30.2/go.mod h1:CYltIHGhCgldEkXT5vS2JHCCWM1WyBI4kA2UfP9cZvY=
|
k8s.io/controller-manager v0.30.3/go.mod h1:F95rjHCOH2WwV9XlVxRo71CtddKLhF3FzE+s1lc7E/0=
|
||||||
k8s.io/csi-translation-lib v0.30.2 h1:ZcFVMWDHg7feW3mtdl+xClgmw1Yxv7m9ysOKt8h3K8Y=
|
k8s.io/csi-translation-lib v0.30.3 h1:wBaPWnOi14/vANRIrp8pmbdx/Pgz2QRcroH7wkodezc=
|
||||||
k8s.io/csi-translation-lib v0.30.2/go.mod h1:jFT8vquP6eSDUwDHk0mKT6uKFWlZp60ecUEUhmlGsOY=
|
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 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/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=
|
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.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||||
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
||||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
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.3 h1:NLg+oN45S2Y3U0WiLRzbS61AY/XrS5JBMZp531Z+Pho=
|
||||||
k8s.io/kms v0.30.2/go.mod h1:GrMurD0qk3G4yNgGcsCEmepqf9KyyIrTXYR2lyUOJC4=
|
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-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-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 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
|
||||||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
|
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.3 h1:YIBBvMdTW0xcDpmrOBzcpUVsn+zOgjMYIu7kAq+yqiI=
|
||||||
k8s.io/kubectl v0.30.2/go.mod h1:rz7GHXaxwnigrqob0lJsiA07Df8RE3n1TSaC2CTeuB4=
|
k8s.io/kubectl v0.30.3/go.mod h1:IcR0I9RN2+zzTRUa1BzZCm4oM0NLOawE6RzlDvd1Fpo=
|
||||||
k8s.io/kubelet v0.30.2 h1:Ck4E/pHndI20IzDXxS57dElhDGASPO5pzXF7BcKfmCY=
|
k8s.io/kubelet v0.30.3 h1:KvGWDdhzD0vEyDyGTCjsDc8D+0+lwRMw3fJbfQgF7ys=
|
||||||
k8s.io/kubelet v0.30.2/go.mod h1:DSwwTbLQmdNkebAU7ypIALR4P9aXZNFwgRmedojUE94=
|
k8s.io/kubelet v0.30.3/go.mod h1:D9or45Vkzcqg55CEiqZ8dVbwP3Ksj7DruEVRS9oq3Ys=
|
||||||
k8s.io/kubernetes v1.30.2 h1:11WhS78OYX/lnSy6TXxPO6Hk+E5K9ZNrEsk9JgMSX8I=
|
k8s.io/kubernetes v1.30.3 h1:A0qoXI1YQNzrQZiff33y5zWxYHFT/HeZRK98/sRDJI0=
|
||||||
k8s.io/kubernetes v1.30.2/go.mod h1:yPbIk3MhmhGigX62FLJm+CphNtjxqCvAIFQXup6RKS0=
|
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 h1:iEcqPP7Vv8UClH8nnMfovtmy/04fIloRW9JuSXykoZ0=
|
||||||
k8s.io/mount-utils v0.29.3/go.mod h1:9IWJTMe8tG0MYMLEp60xK9GYVeCdA3g4LowmnVi+t9Y=
|
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.3 h1:UDGZWR3ry/XrN/Ki/w7qrp49OwgQsKyh+6xWbexvJi8=
|
||||||
k8s.io/pod-security-admission v0.30.2/go.mod h1:gMUJUG9zOgNBk0VIz5BS7uIYiYPEoXkBSeHh6rG2m8c=
|
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-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-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
|
||||||
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
k8s.io/utils v0.0.0-20221128185143-99ec85e7a448/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
|
||||||
|
@ -151,7 +151,7 @@ func maybeUnlockFileEncryption(
|
|||||||
}
|
}
|
||||||
defer ioctx.Destroy()
|
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 {
|
if res != 0 {
|
||||||
switch res {
|
switch res {
|
||||||
case -int(syscall.EBUSY):
|
case -int(syscall.EBUSY):
|
||||||
@ -164,13 +164,8 @@ func maybeUnlockFileEncryption(
|
|||||||
}
|
}
|
||||||
log.DebugLog(ctx, "Lock successfully created for volume ID %s", volID)
|
log.DebugLog(ctx, "Lock successfully created for volume ID %s", volID)
|
||||||
|
|
||||||
log.DebugLog(ctx, "cephfs: unlocking fscrypt on volume %q path %s", volID, stagingTargetPath)
|
defer func() {
|
||||||
err = fscrypt.Unlock(ctx, volOptions.Encryption, stagingTargetPath, string(volID))
|
ret, unlockErr := ioctx.Unlock(string(volID), lockName, lockCookie)
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
ret, err := ioctx.Unlock(string(volID), lockName, lockCookie)
|
|
||||||
switch ret {
|
switch ret {
|
||||||
case 0:
|
case 0:
|
||||||
log.DebugLog(ctx, "Lock %s successfully released ", lockName)
|
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)
|
log.DebugLog(ctx, "Lock is not held by the specified %s, %s pair", lockCookie, lockName)
|
||||||
default:
|
default:
|
||||||
log.ErrorLog(ctx, "Failed to release following lock, this will lead to orphan lock %s: %v",
|
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
|
return nil
|
||||||
|
101
internal/csi-addons/rbd/encryptionkeyrotation.go
Normal file
101
internal/csi-addons/rbd/encryptionkeyrotation.go
Normal 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
|
||||||
|
}
|
@ -114,6 +114,12 @@ func (is *IdentityServer) GetCapabilities(
|
|||||||
Type: identity.Capability_VolumeGroup_LIMIT_VOLUME_TO_ONE_VOLUME_GROUP,
|
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,
|
Type: identity.Capability_ReclaimSpace_ONLINE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
&identity.Capability{
|
||||||
|
Type: &identity.Capability_EncryptionKeyRotation_{
|
||||||
|
EncryptionKeyRotation: &identity.Capability_EncryptionKeyRotation{
|
||||||
|
Type: identity.Capability_EncryptionKeyRotation_ENCRYPTIONKEYROTATION,
|
||||||
|
},
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ package rbd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"slices"
|
||||||
|
|
||||||
"github.com/ceph/ceph-csi/internal/rbd"
|
"github.com/ceph/ceph-csi/internal/rbd"
|
||||||
"github.com/ceph/ceph-csi/internal/rbd/types"
|
"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
|
// 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.
|
// don't need to add all RPC methods leading to forward compatibility.
|
||||||
*volumegroup.UnimplementedControllerServer
|
*volumegroup.UnimplementedControllerServer
|
||||||
|
|
||||||
|
// csiID is the unique ID for this CSI-driver deployment.
|
||||||
|
csiID string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewVolumeGroupServer creates a new VolumeGroupServer which handles the
|
// NewVolumeGroupServer creates a new VolumeGroupServer which handles the
|
||||||
// VolumeGroup Service requests from the CSI-Addons specification.
|
// VolumeGroup Service requests from the CSI-Addons specification.
|
||||||
func NewVolumeGroupServer() *VolumeGroupServer {
|
func NewVolumeGroupServer(instanceID string) *VolumeGroupServer {
|
||||||
return &VolumeGroupServer{}
|
return &VolumeGroupServer{
|
||||||
|
csiID: instanceID,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vs *VolumeGroupServer) RegisterService(server grpc.ServiceRegistrar) {
|
func (vs *VolumeGroupServer) RegisterService(server grpc.ServiceRegistrar) {
|
||||||
@ -77,7 +82,7 @@ func (vs *VolumeGroupServer) CreateVolumeGroup(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req *volumegroup.CreateVolumeGroupRequest,
|
req *volumegroup.CreateVolumeGroupRequest,
|
||||||
) (*volumegroup.CreateVolumeGroupResponse, error) {
|
) (*volumegroup.CreateVolumeGroupResponse, error) {
|
||||||
mgr := rbd.NewManager(req.GetParameters(), req.GetSecrets())
|
mgr := rbd.NewManager(vs.csiID, req.GetParameters(), req.GetSecrets())
|
||||||
defer mgr.Destroy(ctx)
|
defer mgr.Destroy(ctx)
|
||||||
|
|
||||||
// resolve all volumes
|
// resolve all volumes
|
||||||
@ -98,7 +103,7 @@ func (vs *VolumeGroupServer) CreateVolumeGroup(
|
|||||||
volumes[i] = vol
|
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
|
// create a RBDVolumeGroup
|
||||||
vg, err := mgr.CreateVolumeGroup(ctx, req.GetName())
|
vg, err := mgr.CreateVolumeGroup(ctx, req.GetName())
|
||||||
@ -110,7 +115,7 @@ func (vs *VolumeGroupServer) CreateVolumeGroup(
|
|||||||
err.Error())
|
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
|
// add each rbd-image to the RBDVolumeGroup
|
||||||
for _, vol := range volumes {
|
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{
|
return &volumegroup.CreateVolumeGroupResponse{
|
||||||
VolumeGroup: vg.ToCSI(ctx),
|
VolumeGroup: csiVG,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +168,7 @@ func (vs *VolumeGroupServer) DeleteVolumeGroup(
|
|||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req *volumegroup.DeleteVolumeGroupRequest,
|
req *volumegroup.DeleteVolumeGroupRequest,
|
||||||
) (*volumegroup.DeleteVolumeGroupResponse, error) {
|
) (*volumegroup.DeleteVolumeGroupResponse, error) {
|
||||||
mgr := rbd.NewManager(nil, req.GetSecrets())
|
mgr := rbd.NewManager(vs.csiID, nil, req.GetSecrets())
|
||||||
defer mgr.Destroy(ctx)
|
defer mgr.Destroy(ctx)
|
||||||
|
|
||||||
// resolve the volume group
|
// resolve the volume group
|
||||||
@ -168,7 +182,7 @@ func (vs *VolumeGroupServer) DeleteVolumeGroup(
|
|||||||
}
|
}
|
||||||
defer vg.Destroy(ctx)
|
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
|
// verify that the volume group is empty
|
||||||
volumes, err := vg.ListVolumes(ctx)
|
volumes, err := vg.ListVolumes(ctx)
|
||||||
@ -180,7 +194,7 @@ func (vs *VolumeGroupServer) DeleteVolumeGroup(
|
|||||||
err.Error())
|
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 {
|
if len(volumes) != 0 {
|
||||||
return nil, status.Errorf(
|
return nil, status.Errorf(
|
||||||
@ -198,7 +212,154 @@ func (vs *VolumeGroupServer) DeleteVolumeGroup(
|
|||||||
err.Error())
|
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
|
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
|
||||||
|
}
|
||||||
|
@ -77,11 +77,15 @@ type VolumeGroupJournalConfig struct {
|
|||||||
Config
|
Config
|
||||||
}
|
}
|
||||||
|
|
||||||
type VolumeGroupJournalConnection struct {
|
type volumeGroupJournalConnection struct {
|
||||||
config *VolumeGroupJournalConfig
|
config *VolumeGroupJournalConfig
|
||||||
connection *Connection
|
connection *Connection
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// assert that volumeGroupJournalConnection implements the VolumeGroupJournal
|
||||||
|
// interface.
|
||||||
|
var _ VolumeGroupJournal = &volumeGroupJournalConnection{}
|
||||||
|
|
||||||
// NewCSIVolumeGroupJournal returns an instance of VolumeGroupJournal for groups.
|
// NewCSIVolumeGroupJournal returns an instance of VolumeGroupJournal for groups.
|
||||||
func NewCSIVolumeGroupJournal(suffix string) VolumeGroupJournalConfig {
|
func NewCSIVolumeGroupJournal(suffix string) VolumeGroupJournalConfig {
|
||||||
return VolumeGroupJournalConfig{
|
return VolumeGroupJournalConfig{
|
||||||
@ -116,7 +120,7 @@ func (vgc *VolumeGroupJournalConfig) Connect(
|
|||||||
namespace string,
|
namespace string,
|
||||||
cr *util.Credentials,
|
cr *util.Credentials,
|
||||||
) (VolumeGroupJournal, error) {
|
) (VolumeGroupJournal, error) {
|
||||||
vgjc := &VolumeGroupJournalConnection{}
|
vgjc := &volumeGroupJournalConnection{}
|
||||||
vgjc.config = &VolumeGroupJournalConfig{
|
vgjc.config = &VolumeGroupJournalConfig{
|
||||||
Config: vgc.Config,
|
Config: vgc.Config,
|
||||||
}
|
}
|
||||||
@ -130,7 +134,7 @@ func (vgc *VolumeGroupJournalConfig) Connect(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Destroy frees any resources and invalidates the journal connection.
|
// Destroy frees any resources and invalidates the journal connection.
|
||||||
func (vgjc *VolumeGroupJournalConnection) Destroy() {
|
func (vgjc *volumeGroupJournalConnection) Destroy() {
|
||||||
vgjc.connection.Destroy()
|
vgjc.connection.Destroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,7 +171,7 @@ Return values:
|
|||||||
reservation found.
|
reservation found.
|
||||||
- error: non-nil in case of any errors.
|
- 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,
|
journalPool, reqName, namePrefix string,
|
||||||
) (*VolumeGroupData, error) {
|
) (*VolumeGroupData, error) {
|
||||||
var (
|
var (
|
||||||
@ -244,7 +248,7 @@ Input arguments:
|
|||||||
- groupID: ID of the volume group, generated from the UUID
|
- groupID: ID of the volume group, generated from the UUID
|
||||||
- reqName: Request name for the volume group
|
- 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,
|
csiJournalPool, groupID, reqName string,
|
||||||
) error {
|
) error {
|
||||||
// delete volume UUID omap (first, inverse of create order)
|
// 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
|
- string: Contains the VolumeGroup name that was reserved for the passed in reqName
|
||||||
- error: non-nil in case of any errors
|
- 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,
|
journalPool, reqName, namePrefix string,
|
||||||
) (string, string, error) {
|
) (string, string, error) {
|
||||||
cj := vgjc.config
|
cj := vgjc.config
|
||||||
@ -366,7 +370,7 @@ type VolumeGroupAttributes struct {
|
|||||||
VolumeMap map[string]string // Contains the volumeID and the corresponding value mapping
|
VolumeMap map[string]string // Contains the volumeID and the corresponding value mapping
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vgjc *VolumeGroupJournalConnection) GetVolumeGroupAttributes(
|
func (vgjc *volumeGroupJournalConnection) GetVolumeGroupAttributes(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
pool, objectUUID string,
|
pool, objectUUID string,
|
||||||
) (*VolumeGroupAttributes, error) {
|
) (*VolumeGroupAttributes, error) {
|
||||||
@ -401,7 +405,7 @@ func (vgjc *VolumeGroupJournalConnection) GetVolumeGroupAttributes(
|
|||||||
return groupAttributes, nil
|
return groupAttributes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vgjc *VolumeGroupJournalConnection) AddVolumesMapping(
|
func (vgjc *volumeGroupJournalConnection) AddVolumesMapping(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
pool,
|
pool,
|
||||||
reservedUUID string,
|
reservedUUID string,
|
||||||
@ -418,7 +422,7 @@ func (vgjc *VolumeGroupJournalConnection) AddVolumesMapping(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (vgjc *VolumeGroupJournalConnection) RemoveVolumesMapping(
|
func (vgjc *volumeGroupJournalConnection) RemoveVolumesMapping(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
pool,
|
pool,
|
||||||
reservedUUID string,
|
reservedUUID string,
|
||||||
|
@ -28,6 +28,8 @@ import (
|
|||||||
"github.com/hashicorp/vault/api"
|
"github.com/hashicorp/vault/api"
|
||||||
loss "github.com/libopenstorage/secrets"
|
loss "github.com/libopenstorage/secrets"
|
||||||
"github.com/libopenstorage/secrets/vault"
|
"github.com/libopenstorage/secrets/vault"
|
||||||
|
|
||||||
|
"github.com/ceph/ceph-csi/internal/util/file"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -269,10 +271,12 @@ func (vc *vaultConnection) initCertificates(config map[string]interface{}, secre
|
|||||||
return fmt.Errorf("missing vault CA in secret %s", vaultCAFromSecret)
|
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create temporary file for Vault CA: %w", err)
|
return fmt.Errorf("failed to create temporary file for Vault CA: %w", err)
|
||||||
}
|
}
|
||||||
|
vaultConfig[api.EnvVaultCACert] = tf.Name()
|
||||||
|
|
||||||
// update the existing config
|
// update the existing config
|
||||||
for key, value := range vaultConfig {
|
for key, value := range vaultConfig {
|
||||||
vc.vaultConfig[key] = value
|
vc.vaultConfig[key] = value
|
||||||
@ -480,31 +484,3 @@ func detectAuthMountPath(path string) (string, error) {
|
|||||||
|
|
||||||
return authMountPath, nil
|
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
|
|
||||||
}
|
|
||||||
|
@ -18,7 +18,6 @@ package kms
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
loss "github.com/libopenstorage/secrets"
|
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) {
|
func TestSetConfigString(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
const defaultValue = "default-value"
|
const defaultValue = "default-value"
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/ceph/ceph-csi/internal/util/file"
|
||||||
"github.com/ceph/ceph-csi/internal/util/k8s"
|
"github.com/ceph/ceph-csi/internal/util/k8s"
|
||||||
|
|
||||||
"github.com/hashicorp/vault/api"
|
"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)
|
return fmt.Errorf("failed to get CA certificate from secret %s: %w", vaultCAFromSecret, cErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vaultConfig[api.EnvVaultCACert], err = createTempFile("vault-ca-cert", []byte(cert))
|
cer, ferr := file.CreateTempFile("vault-ca-cert", cert)
|
||||||
if err != nil {
|
if ferr != nil {
|
||||||
return fmt.Errorf("failed to create temporary file for Vault CA: %w", err)
|
return fmt.Errorf("failed to create temporary file for Vault CA: %w", ferr)
|
||||||
}
|
}
|
||||||
|
vaultConfig[api.EnvVaultCACert] = cer.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
vaultClientCertFromSecret := "" // optional
|
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)
|
return fmt.Errorf("failed to get client certificate from secret %s: %w", vaultCAFromSecret, cErr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vaultConfig[api.EnvVaultClientCert], err = createTempFile("vault-ca-cert", []byte(cert))
|
cer, ferr := file.CreateTempFile("vault-ca-cert", cert)
|
||||||
if err != nil {
|
if ferr != nil {
|
||||||
return fmt.Errorf("failed to create temporary file for Vault client certificate: %w", err)
|
return fmt.Errorf("failed to create temporary file for Vault client certificate: %w", ferr)
|
||||||
}
|
}
|
||||||
|
vaultConfig[api.EnvVaultClientCert] = cer.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
vaultClientCertKeyFromSecret := "" // optional
|
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)
|
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create temporary file for Vault client cert key: %w", err)
|
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 {
|
for key, value := range vaultConfig {
|
||||||
|
@ -239,7 +239,7 @@ func (cs *ControllerServer) parseVolCreateRequest(
|
|||||||
return rbdVol, nil
|
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{
|
vol := &csi.Volume{
|
||||||
VolumeId: rbdVol.VolID,
|
VolumeId: rbdVol.VolID,
|
||||||
CapacityBytes: rbdVol.VolSize,
|
CapacityBytes: rbdVol.VolSize,
|
||||||
@ -266,22 +266,29 @@ func (rbdVol *rbdVolume) ToCSI(ctx context.Context) *csi.Volume {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return vol
|
return vol, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildCreateVolumeResponse(
|
func buildCreateVolumeResponse(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
req *csi.CreateVolumeRequest,
|
req *csi.CreateVolumeRequest,
|
||||||
rbdVol *rbdVolume,
|
rbdVol *rbdVolume,
|
||||||
) *csi.CreateVolumeResponse {
|
) (*csi.CreateVolumeResponse, error) {
|
||||||
volume := rbdVol.ToCSI(ctx)
|
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()
|
volume.ContentSource = req.GetVolumeContentSource()
|
||||||
|
|
||||||
for param, value := range util.GetVolumeContext(req.GetParameters()) {
|
for param, value := range util.GetVolumeContext(req.GetParameters()) {
|
||||||
volume.VolumeContext[param] = value
|
volume.VolumeContext[param] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
return &csi.CreateVolumeResponse{Volume: volume}
|
return &csi.CreateVolumeResponse{Volume: volume}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getGRPCErrorForCreateVolume converts the returns the GRPC errors based on
|
// 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 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,
|
// 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 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
|
// check snapshots on the rbd image, as we have limit from krbd that an image
|
||||||
|
@ -222,13 +222,16 @@ func (r *Driver) setupCSIAddonsServer(conf *util.Config) error {
|
|||||||
rcs := casrbd.NewReplicationServer(NewControllerServer(r.cd))
|
rcs := casrbd.NewReplicationServer(NewControllerServer(r.cd))
|
||||||
r.cas.RegisterService(rcs)
|
r.cas.RegisterService(rcs)
|
||||||
|
|
||||||
vgcs := casrbd.NewVolumeGroupServer()
|
vgcs := casrbd.NewVolumeGroupServer(conf.InstanceID)
|
||||||
r.cas.RegisterService(vgcs)
|
r.cas.RegisterService(vgcs)
|
||||||
}
|
}
|
||||||
|
|
||||||
if conf.IsNodeServer {
|
if conf.IsNodeServer {
|
||||||
rs := casrbd.NewReclaimSpaceNodeServer()
|
rs := casrbd.NewReclaimSpaceNodeServer()
|
||||||
r.cas.RegisterService(rs)
|
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
|
// start the server, this does not block, it runs a new go-routine
|
||||||
|
@ -63,6 +63,10 @@ const (
|
|||||||
// user did not specify an "encryptionType", but set
|
// user did not specify an "encryptionType", but set
|
||||||
// "encryption": true.
|
// "encryption": true.
|
||||||
rbdDefaultEncryptionType = util.EncryptionTypeBlock
|
rbdDefaultEncryptionType = util.EncryptionTypeBlock
|
||||||
|
|
||||||
|
// Luks slots.
|
||||||
|
luksSlot0 = "0"
|
||||||
|
luksSlot1 = "1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// checkRbdImageEncrypted verifies if rbd image was encrypted when created.
|
// 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
|
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
79
internal/rbd/group.go
Normal 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)
|
||||||
|
}
|
468
internal/rbd/group/volume_group.go
Normal file
468
internal/rbd/group/volume_group.go
Normal 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
|
||||||
|
}
|
@ -19,24 +19,38 @@ package rbd
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"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/rbd/types"
|
||||||
"github.com/ceph/ceph-csi/internal/util"
|
"github.com/ceph/ceph-csi/internal/util"
|
||||||
|
"github.com/ceph/ceph-csi/internal/util/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ types.Manager = &rbdManager{}
|
var _ types.Manager = &rbdManager{}
|
||||||
|
|
||||||
type rbdManager struct {
|
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
|
parameters map[string]string
|
||||||
|
// secrets contain the credentials to connect to the Ceph cluster.
|
||||||
secrets map[string]string
|
secrets map[string]string
|
||||||
|
|
||||||
|
// creds are the cached credentials, will be freed on Destroy()
|
||||||
creds *util.Credentials
|
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
|
// NewManager returns a new manager for handling Volume and Volume Group
|
||||||
// operations, combining the requests for RBD and the journalling in RADOS.
|
// 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{
|
return &rbdManager{
|
||||||
|
csiID: csiID,
|
||||||
parameters: parameters,
|
parameters: parameters,
|
||||||
secrets: secrets,
|
secrets: secrets,
|
||||||
}
|
}
|
||||||
@ -47,43 +61,225 @@ func (mgr *rbdManager) Destroy(ctx context.Context) {
|
|||||||
mgr.creds.DeleteCredentials()
|
mgr.creds.DeleteCredentials()
|
||||||
mgr.creds = nil
|
mgr.creds = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if mgr.vgJournal != nil {
|
||||||
|
mgr.vgJournal.Destroy()
|
||||||
|
mgr.vgJournal = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// connect sets up credentials and connects to the journal.
|
// getCredentials sets up credentials and connects to the journal.
|
||||||
func (mgr *rbdManager) connect() error {
|
func (mgr *rbdManager) getCredentials() (*util.Credentials, error) {
|
||||||
if mgr.creds == nil {
|
if mgr.creds != nil {
|
||||||
|
return mgr.creds, nil
|
||||||
|
}
|
||||||
|
|
||||||
creds, err := util.NewUserCredentials(mgr.secrets)
|
creds, err := util.NewUserCredentials(mgr.secrets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return nil, fmt.Errorf("failed to get credentials: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mgr.creds = creds
|
mgr.creds = creds
|
||||||
|
|
||||||
|
return creds, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mgr *rbdManager) getVolumeGroupJournal(clusterID string) (journal.VolumeGroupJournal, error) {
|
||||||
|
if mgr.vgJournal != nil {
|
||||||
|
return mgr.vgJournal, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return 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) {
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
volume, err := GenVolFromVolID(ctx, id, mgr.creds, mgr.secrets)
|
volume, err := GenVolFromVolID(ctx, id, creds, mgr.secrets)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("failed to get volume from id %q: %w", id, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return volume, nil
|
return volume, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mgr *rbdManager) GetVolumeGroupByID(ctx context.Context, id string) (types.VolumeGroup, error) {
|
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) {
|
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 {
|
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
|
||||||
}
|
}
|
||||||
|
@ -19,20 +19,41 @@ package types
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/ceph/go-ceph/rados"
|
||||||
"github.com/csi-addons/spec/lib/go/volumegroup"
|
"github.com/csi-addons/spec/lib/go/volumegroup"
|
||||||
)
|
)
|
||||||
|
|
||||||
// VolumeGroup contains a number of volumes, and can be used to create a
|
type journalledObject interface {
|
||||||
// VolumeGroupSnapshot.
|
|
||||||
type VolumeGroup interface {
|
|
||||||
// Destroy frees the resources used by the VolumeGroup.
|
|
||||||
Destroy(ctx context.Context)
|
|
||||||
|
|
||||||
// GetID returns the CSI-Addons VolumeGroupId of the VolumeGroup.
|
// GetID returns the CSI-Addons VolumeGroupId of the VolumeGroup.
|
||||||
GetID(ctx context.Context) (string, error)
|
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 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 removes the VolumeGroup from the backend storage.
|
||||||
Delete(ctx context.Context) error
|
Delete(ctx context.Context) error
|
||||||
|
@ -20,16 +20,22 @@ import (
|
|||||||
"context"
|
"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.
|
// Manager provides a way for other packages to get Volumes and VolumeGroups.
|
||||||
// It handles the operations on the backend, and makes sure the journal
|
// It handles the operations on the backend, and makes sure the journal
|
||||||
// reflects the expected state.
|
// reflects the expected state.
|
||||||
type Manager interface {
|
type Manager interface {
|
||||||
|
// VolumeResolver is fully implemented by the Manager.
|
||||||
|
VolumeResolver
|
||||||
|
|
||||||
// Destroy frees all resources that the Manager allocated.
|
// Destroy frees all resources that the Manager allocated.
|
||||||
Destroy(ctx context.Context)
|
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
|
// GetVolumeGroupByID uses the CSI-Addons VolumeGroupId to resolve the
|
||||||
// returned VolumeGroup.
|
// returned VolumeGroup.
|
||||||
GetVolumeGroupByID(ctx context.Context, id string) (VolumeGroup, error)
|
GetVolumeGroupByID(ctx context.Context, id string) (VolumeGroup, error)
|
||||||
|
@ -33,5 +33,11 @@ type Volume interface {
|
|||||||
GetID(ctx context.Context) (string, error)
|
GetID(ctx context.Context) (string, error)
|
||||||
|
|
||||||
// ToCSI creates a CSI protocol formatted struct of the volume.
|
// 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
|
||||||
}
|
}
|
||||||
|
@ -237,6 +237,11 @@ func (ve *VolumeEncryption) GetCryptoPassphrase(ctx context.Context, volumeID st
|
|||||||
return ve.KMS.DecryptDEK(ctx, volumeID, passphrase)
|
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.
|
// generateNewEncryptionPassphrase generates a random passphrase for encryption.
|
||||||
func generateNewEncryptionPassphrase(length int) (string, error) {
|
func generateNewEncryptionPassphrase(length int) (string, error) {
|
||||||
bytesPassphrase := make([]byte, length)
|
bytesPassphrase := make([]byte, length)
|
||||||
|
@ -19,9 +19,13 @@ package util
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"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.
|
// 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)
|
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) {
|
func execCryptsetupCommand(stdin *string, args ...string) (string, string, error) {
|
||||||
var (
|
var (
|
||||||
program = "cryptsetup"
|
program = "cryptsetup"
|
||||||
|
54
internal/util/file/file.go
Normal file
54
internal/util/file/file.go
Normal 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
|
||||||
|
}
|
100
internal/util/file/file_test.go
Normal file
100
internal/util/file/file_test.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
72
vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go
generated
vendored
72
vendor/github.com/aws/aws-sdk-go/aws/endpoints/defaults.go
generated
vendored
@ -13068,6 +13068,9 @@ var awsPartition = partition{
|
|||||||
endpointKey{
|
endpointKey{
|
||||||
Region: "eu-central-1",
|
Region: "eu-central-1",
|
||||||
}: endpoint{},
|
}: endpoint{},
|
||||||
|
endpointKey{
|
||||||
|
Region: "eu-central-2",
|
||||||
|
}: endpoint{},
|
||||||
endpointKey{
|
endpointKey{
|
||||||
Region: "eu-north-1",
|
Region: "eu-north-1",
|
||||||
}: endpoint{},
|
}: endpoint{},
|
||||||
@ -22522,6 +22525,9 @@ var awsPartition = partition{
|
|||||||
}: endpoint{
|
}: endpoint{
|
||||||
Hostname: "network-firewall-fips.ca-central-1.amazonaws.com",
|
Hostname: "network-firewall-fips.ca-central-1.amazonaws.com",
|
||||||
},
|
},
|
||||||
|
endpointKey{
|
||||||
|
Region: "ca-west-1",
|
||||||
|
}: endpoint{},
|
||||||
endpointKey{
|
endpointKey{
|
||||||
Region: "eu-central-1",
|
Region: "eu-central-1",
|
||||||
}: endpoint{},
|
}: endpoint{},
|
||||||
@ -24479,6 +24485,14 @@ var awsPartition = partition{
|
|||||||
Region: "ca-central-1",
|
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{
|
endpointKey{
|
||||||
Region: "eu-central-1",
|
Region: "eu-central-1",
|
||||||
}: endpoint{
|
}: endpoint{
|
||||||
@ -33621,6 +33635,20 @@ var awsPartition = partition{
|
|||||||
}: endpoint{},
|
}: 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{
|
"textract": service{
|
||||||
Endpoints: serviceEndpoints{
|
Endpoints: serviceEndpoints{
|
||||||
endpointKey{
|
endpointKey{
|
||||||
@ -39973,16 +40001,12 @@ var awsusgovPartition = partition{
|
|||||||
Endpoints: serviceEndpoints{
|
Endpoints: serviceEndpoints{
|
||||||
endpointKey{
|
endpointKey{
|
||||||
Region: "us-gov-east-1",
|
Region: "us-gov-east-1",
|
||||||
}: endpoint{
|
}: endpoint{},
|
||||||
Hostname: "autoscaling-plans.us-gov-east-1.amazonaws.com",
|
|
||||||
Protocols: []string{"http", "https"},
|
|
||||||
},
|
|
||||||
endpointKey{
|
endpointKey{
|
||||||
Region: "us-gov-east-1",
|
Region: "us-gov-east-1",
|
||||||
Variant: fipsVariant,
|
Variant: fipsVariant,
|
||||||
}: endpoint{
|
}: endpoint{
|
||||||
Hostname: "autoscaling-plans.us-gov-east-1.amazonaws.com",
|
Hostname: "autoscaling-plans.us-gov-east-1.amazonaws.com",
|
||||||
Protocols: []string{"http", "https"},
|
|
||||||
},
|
},
|
||||||
endpointKey{
|
endpointKey{
|
||||||
Region: "us-gov-east-1-fips",
|
Region: "us-gov-east-1-fips",
|
||||||
@ -39994,16 +40018,12 @@ var awsusgovPartition = partition{
|
|||||||
},
|
},
|
||||||
endpointKey{
|
endpointKey{
|
||||||
Region: "us-gov-west-1",
|
Region: "us-gov-west-1",
|
||||||
}: endpoint{
|
}: endpoint{},
|
||||||
Hostname: "autoscaling-plans.us-gov-west-1.amazonaws.com",
|
|
||||||
Protocols: []string{"http", "https"},
|
|
||||||
},
|
|
||||||
endpointKey{
|
endpointKey{
|
||||||
Region: "us-gov-west-1",
|
Region: "us-gov-west-1",
|
||||||
Variant: fipsVariant,
|
Variant: fipsVariant,
|
||||||
}: endpoint{
|
}: endpoint{
|
||||||
Hostname: "autoscaling-plans.us-gov-west-1.amazonaws.com",
|
Hostname: "autoscaling-plans.us-gov-west-1.amazonaws.com",
|
||||||
Protocols: []string{"http", "https"},
|
|
||||||
},
|
},
|
||||||
endpointKey{
|
endpointKey{
|
||||||
Region: "us-gov-west-1-fips",
|
Region: "us-gov-west-1-fips",
|
||||||
@ -40969,20 +40989,40 @@ var awsusgovPartition = partition{
|
|||||||
"directconnect": service{
|
"directconnect": service{
|
||||||
Endpoints: serviceEndpoints{
|
Endpoints: serviceEndpoints{
|
||||||
endpointKey{
|
endpointKey{
|
||||||
Region: "us-gov-east-1",
|
Region: "fips-us-gov-east-1",
|
||||||
}: endpoint{
|
}: endpoint{
|
||||||
Hostname: "directconnect.us-gov-east-1.amazonaws.com",
|
Hostname: "directconnect-fips.us-gov-east-1.amazonaws.com",
|
||||||
CredentialScope: credentialScope{
|
CredentialScope: credentialScope{
|
||||||
Region: "us-gov-east-1",
|
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{
|
endpointKey{
|
||||||
Region: "us-gov-west-1",
|
Region: "us-gov-west-1",
|
||||||
}: endpoint{
|
}: endpoint{},
|
||||||
Hostname: "directconnect.us-gov-west-1.amazonaws.com",
|
endpointKey{
|
||||||
CredentialScope: credentialScope{
|
|
||||||
Region: "us-gov-west-1",
|
Region: "us-gov-west-1",
|
||||||
},
|
Variant: fipsVariant,
|
||||||
|
}: endpoint{
|
||||||
|
Hostname: "directconnect-fips.us-gov-west-1.amazonaws.com",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
2
vendor/github.com/aws/aws-sdk-go/aws/version.go
generated
vendored
2
vendor/github.com/aws/aws-sdk-go/aws/version.go
generated
vendored
@ -5,4 +5,4 @@ package aws
|
|||||||
const SDKName = "aws-sdk-go"
|
const SDKName = "aws-sdk-go"
|
||||||
|
|
||||||
// SDKVersion is the version of this SDK
|
// SDKVersion is the version of this SDK
|
||||||
const SDKVersion = "1.54.19"
|
const SDKVersion = "1.55.0"
|
||||||
|
317
vendor/github.com/csi-addons/spec/lib/go/encryptionkeyrotation/encryptionkeyrotation.pb.go
generated
vendored
Normal file
317
vendor/github.com/csi-addons/spec/lib/go/encryptionkeyrotation/encryptionkeyrotation.pb.go
generated
vendored
Normal 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
|
||||||
|
}
|
116
vendor/github.com/csi-addons/spec/lib/go/encryptionkeyrotation/encryptionkeyrotation_grpc.pb.go
generated
vendored
Normal file
116
vendor/github.com/csi-addons/spec/lib/go/encryptionkeyrotation/encryptionkeyrotation_grpc.pb.go
generated
vendored
Normal 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",
|
||||||
|
}
|
9
vendor/github.com/pkg/xattr/xattr.go
generated
vendored
9
vendor/github.com/pkg/xattr/xattr.go
generated
vendored
@ -87,8 +87,8 @@ func get(path string, name string, getxattrFunc getxattrFunc) ([]byte, error) {
|
|||||||
initialBufSize = 1024
|
initialBufSize = 1024
|
||||||
|
|
||||||
// The theoretical maximum xattr value size on MacOS is 64 MB. On Linux it's
|
// 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
|
// much smaller: documented at 64 KB. However, at least on TrueNAS SCALE, a
|
||||||
// hit the limit.
|
// Debian-based Linux distro, it can be larger.
|
||||||
maxBufSize = 64 * 1024 * 1024
|
maxBufSize = 64 * 1024 * 1024
|
||||||
|
|
||||||
// Function name as reported in error messages
|
// 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
|
// If the buffer was too small to fit the value, Linux and MacOS react
|
||||||
// differently:
|
// 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
|
// 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
|
// 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,
|
// truncated, and we retry with a bigger buffer. Contrary to documentation,
|
||||||
// MacOS never seems to return ERANGE!
|
// MacOS never seems to return ERANGE!
|
||||||
// To keep the code simple, we always check both conditions, and sometimes
|
// To keep the code simple, we always check both conditions, and sometimes
|
||||||
// double the buffer size without it being strictly necessary.
|
// 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.
|
// The buffer was too small. Try again.
|
||||||
size <<= 1
|
size <<= 1
|
||||||
if size >= maxBufSize {
|
if size >= maxBufSize {
|
||||||
|
20
vendor/github.com/pkg/xattr/xattr_solaris.go
generated
vendored
20
vendor/github.com/pkg/xattr/xattr_solaris.go
generated
vendored
@ -24,7 +24,7 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func getxattr(path string, name string, data []byte) (int, error) {
|
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 {
|
if err != nil {
|
||||||
return 0, err
|
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 {
|
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 {
|
if err != nil {
|
||||||
return err
|
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 {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -114,7 +115,7 @@ func fremovexattr(f *os.File, name string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func listxattr(path string, data []byte) (int, 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 {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
@ -151,8 +152,17 @@ func flistxattr(f *os.File, data []byte) (int, error) {
|
|||||||
return copy(data, buf), nil
|
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.
|
// 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) {
|
func stringsFromByteSlice(buf []byte) (result []string) {
|
||||||
offset := 0
|
offset := 0
|
||||||
for index, b := range buf {
|
for index, b := range buf {
|
||||||
|
3
vendor/k8s.io/kubernetes/pkg/securitycontext/util.go
generated
vendored
3
vendor/k8s.io/kubernetes/pkg/securitycontext/util.go
generated
vendored
@ -188,7 +188,7 @@ func AddNoNewPrivileges(sc *v1.SecurityContext) bool {
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// These *must* be kept in sync with moby/moby.
|
// 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.
|
// @jessfraz will watch changes to those files upstream.
|
||||||
defaultMaskedPaths = []string{
|
defaultMaskedPaths = []string{
|
||||||
"/proc/asound",
|
"/proc/asound",
|
||||||
@ -201,6 +201,7 @@ var (
|
|||||||
"/proc/sched_debug",
|
"/proc/sched_debug",
|
||||||
"/proc/scsi",
|
"/proc/scsi",
|
||||||
"/sys/firmware",
|
"/sys/firmware",
|
||||||
|
"/sys/devices/virtual/powercap",
|
||||||
}
|
}
|
||||||
defaultReadonlyPaths = []string{
|
defaultReadonlyPaths = []string{
|
||||||
"/proc/bus",
|
"/proc/bus",
|
||||||
|
5
vendor/k8s.io/kubernetes/pkg/util/filesystem/defaultfs.go
generated
vendored
5
vendor/k8s.io/kubernetes/pkg/util/filesystem/defaultfs.go
generated
vendored
@ -72,9 +72,8 @@ func (fs *DefaultFs) Rename(oldpath, newpath string) error {
|
|||||||
return os.Rename(oldpath, newpath)
|
return os.Rename(oldpath, newpath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MkdirAll via os.MkdirAll
|
|
||||||
func (fs *DefaultFs) MkdirAll(path string, perm os.FileMode) error {
|
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
|
// 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)
|
return fmt.Errorf("path %v exists but is not a directory", path)
|
||||||
}
|
}
|
||||||
// If existence of path not known, attempt to create it.
|
// 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 err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
10
vendor/k8s.io/kubernetes/pkg/util/filesystem/util_unix.go
generated
vendored
10
vendor/k8s.io/kubernetes/pkg/util/filesystem/util_unix.go
generated
vendored
@ -37,6 +37,16 @@ func IsUnixDomainSocket(filePath string) (bool, error) {
|
|||||||
return true, nil
|
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.
|
// IsAbs is same as filepath.IsAbs on Unix.
|
||||||
func IsAbs(path string) bool {
|
func IsAbs(path string) bool {
|
||||||
return filepath.IsAbs(path)
|
return filepath.IsAbs(path)
|
||||||
|
156
vendor/k8s.io/kubernetes/pkg/util/filesystem/util_windows.go
generated
vendored
156
vendor/k8s.io/kubernetes/pkg/util/filesystem/util_windows.go
generated
vendored
@ -29,6 +29,8 @@ import (
|
|||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -88,6 +90,160 @@ func IsUnixDomainSocket(filePath string) (bool, error) {
|
|||||||
return true, nil
|
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.
|
// 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
|
// 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).
|
// though they can be used as absolute paths (https://docs.microsoft.com/en-us/dotnet/standard/io/file-path-formats).
|
||||||
|
2
vendor/k8s.io/kubernetes/test/utils/image/manifest.go
generated
vendored
2
vendor/k8s.io/kubernetes/test/utils/image/manifest.go
generated
vendored
@ -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[BusyBox] = Config{list.PromoterE2eRegistry, "busybox", "1.36.1-1"}
|
||||||
configs[CudaVectorAdd] = Config{list.PromoterE2eRegistry, "cuda-vector-add", "1.0"}
|
configs[CudaVectorAdd] = Config{list.PromoterE2eRegistry, "cuda-vector-add", "1.0"}
|
||||||
configs[CudaVectorAdd2] = Config{list.PromoterE2eRegistry, "cuda-vector-add", "2.3"}
|
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[Etcd] = Config{list.GcEtcdRegistry, "etcd", "3.5.12-0"}
|
||||||
configs[Httpd] = Config{list.PromoterE2eRegistry, "httpd", "2.4.38-4"}
|
configs[Httpd] = Config{list.PromoterE2eRegistry, "httpd", "2.4.38-4"}
|
||||||
configs[HttpdNew] = Config{list.PromoterE2eRegistry, "httpd", "2.4.39-4"}
|
configs[HttpdNew] = Config{list.PromoterE2eRegistry, "httpd", "2.4.39-4"}
|
||||||
|
89
vendor/modules.txt
vendored
89
vendor/modules.txt
vendored
@ -81,7 +81,7 @@ github.com/antlr/antlr4/runtime/Go/antlr/v4
|
|||||||
# github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a
|
# github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a
|
||||||
## explicit
|
## explicit
|
||||||
github.com/asaskevich/govalidator
|
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
|
## explicit; go 1.19
|
||||||
github.com/aws/aws-sdk-go/aws
|
github.com/aws/aws-sdk-go/aws
|
||||||
github.com/aws/aws-sdk-go/aws/auth/bearer
|
github.com/aws/aws-sdk-go/aws/auth/bearer
|
||||||
@ -236,8 +236,9 @@ github.com/coreos/go-semver/semver
|
|||||||
## explicit; go 1.12
|
## explicit; go 1.12
|
||||||
github.com/coreos/go-systemd/v22/daemon
|
github.com/coreos/go-systemd/v22/daemon
|
||||||
github.com/coreos/go-systemd/v22/journal
|
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
|
## explicit
|
||||||
|
github.com/csi-addons/spec/lib/go/encryptionkeyrotation
|
||||||
github.com/csi-addons/spec/lib/go/fence
|
github.com/csi-addons/spec/lib/go/fence
|
||||||
github.com/csi-addons/spec/lib/go/identity
|
github.com/csi-addons/spec/lib/go/identity
|
||||||
github.com/csi-addons/spec/lib/go/reclaimspace
|
github.com/csi-addons/spec/lib/go/reclaimspace
|
||||||
@ -567,7 +568,7 @@ github.com/pkg/browser
|
|||||||
# github.com/pkg/errors v0.9.1
|
# github.com/pkg/errors v0.9.1
|
||||||
## explicit
|
## explicit
|
||||||
github.com/pkg/errors
|
github.com/pkg/errors
|
||||||
# github.com/pkg/xattr v0.4.9
|
# github.com/pkg/xattr v0.4.10
|
||||||
## explicit; go 1.14
|
## explicit; go 1.14
|
||||||
github.com/pkg/xattr
|
github.com/pkg/xattr
|
||||||
# github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2
|
# 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
|
# gopkg.in/yaml.v3 v3.0.1
|
||||||
## explicit
|
## explicit
|
||||||
gopkg.in/yaml.v3
|
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
|
## explicit; go 1.22.0
|
||||||
k8s.io/api/admission/v1
|
k8s.io/api/admission/v1
|
||||||
k8s.io/api/admission/v1beta1
|
k8s.io/api/admission/v1beta1
|
||||||
@ -989,12 +990,12 @@ k8s.io/api/storage/v1
|
|||||||
k8s.io/api/storage/v1alpha1
|
k8s.io/api/storage/v1alpha1
|
||||||
k8s.io/api/storage/v1beta1
|
k8s.io/api/storage/v1beta1
|
||||||
k8s.io/api/storagemigration/v1alpha1
|
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
|
## explicit; go 1.22.0
|
||||||
k8s.io/apiextensions-apiserver/pkg/apis/apiextensions
|
k8s.io/apiextensions-apiserver/pkg/apis/apiextensions
|
||||||
k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1
|
k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1
|
||||||
k8s.io/apiextensions-apiserver/pkg/features
|
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
|
## explicit; go 1.22.0
|
||||||
k8s.io/apimachinery/pkg/api/equality
|
k8s.io/apimachinery/pkg/api/equality
|
||||||
k8s.io/apimachinery/pkg/api/errors
|
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/json
|
||||||
k8s.io/apimachinery/third_party/forked/golang/netutil
|
k8s.io/apimachinery/third_party/forked/golang/netutil
|
||||||
k8s.io/apimachinery/third_party/forked/golang/reflect
|
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
|
## explicit; go 1.22.0
|
||||||
k8s.io/apiserver/pkg/admission
|
k8s.io/apiserver/pkg/admission
|
||||||
k8s.io/apiserver/pkg/admission/configuration
|
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/authenticator/token/webhook
|
||||||
k8s.io/apiserver/plugin/pkg/authorizer/webhook
|
k8s.io/apiserver/plugin/pkg/authorizer/webhook
|
||||||
k8s.io/apiserver/plugin/pkg/authorizer/webhook/metrics
|
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
|
## explicit; go 1.22.0
|
||||||
k8s.io/client-go/applyconfigurations/admissionregistration/v1
|
k8s.io/client-go/applyconfigurations/admissionregistration/v1
|
||||||
k8s.io/client-go/applyconfigurations/admissionregistration/v1alpha1
|
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/keyutil
|
||||||
k8s.io/client-go/util/retry
|
k8s.io/client-go/util/retry
|
||||||
k8s.io/client-go/util/workqueue
|
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
|
## explicit; go 1.22.0
|
||||||
k8s.io/cloud-provider
|
k8s.io/cloud-provider
|
||||||
k8s.io/cloud-provider/app/config
|
k8s.io/cloud-provider/app/config
|
||||||
@ -1555,7 +1556,7 @@ k8s.io/cloud-provider/names
|
|||||||
k8s.io/cloud-provider/options
|
k8s.io/cloud-provider/options
|
||||||
k8s.io/cloud-provider/volume
|
k8s.io/cloud-provider/volume
|
||||||
k8s.io/cloud-provider/volume/helpers
|
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
|
## explicit; go 1.22.0
|
||||||
k8s.io/component-base/cli/flag
|
k8s.io/component-base/cli/flag
|
||||||
k8s.io/component-base/config
|
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
|
||||||
k8s.io/component-base/tracing/api/v1
|
k8s.io/component-base/tracing/api/v1
|
||||||
k8s.io/component-base/version
|
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
|
## explicit; go 1.22.0
|
||||||
k8s.io/component-helpers/node/util/sysctl
|
k8s.io/component-helpers/node/util/sysctl
|
||||||
k8s.io/component-helpers/scheduling/corev1
|
k8s.io/component-helpers/scheduling/corev1
|
||||||
k8s.io/component-helpers/scheduling/corev1/nodeaffinity
|
k8s.io/component-helpers/scheduling/corev1/nodeaffinity
|
||||||
k8s.io/component-helpers/storage/volume
|
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
|
## explicit; go 1.22.0
|
||||||
k8s.io/controller-manager/config
|
k8s.io/controller-manager/config
|
||||||
k8s.io/controller-manager/config/v1
|
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/sloghandler
|
||||||
k8s.io/klog/v2/internal/verbosity
|
k8s.io/klog/v2/internal/verbosity
|
||||||
k8s.io/klog/v2/textlogger
|
k8s.io/klog/v2/textlogger
|
||||||
# k8s.io/kms v0.30.2
|
# k8s.io/kms v0.30.3
|
||||||
## explicit; go 1.22.0
|
## explicit; go 1.22.0
|
||||||
k8s.io/kms/apis/v1beta1
|
k8s.io/kms/apis/v1beta1
|
||||||
k8s.io/kms/apis/v2
|
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/spec
|
||||||
k8s.io/kube-openapi/pkg/validation/strfmt
|
k8s.io/kube-openapi/pkg/validation/strfmt
|
||||||
k8s.io/kube-openapi/pkg/validation/strfmt/bson
|
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
|
## explicit; go 1.22.0
|
||||||
k8s.io/kubectl/pkg/scale
|
k8s.io/kubectl/pkg/scale
|
||||||
k8s.io/kubectl/pkg/util/podutils
|
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
|
## explicit; go 1.22.0
|
||||||
k8s.io/kubelet/pkg/apis
|
k8s.io/kubelet/pkg/apis
|
||||||
k8s.io/kubelet/pkg/apis/stats/v1alpha1
|
k8s.io/kubelet/pkg/apis/stats/v1alpha1
|
||||||
# k8s.io/kubernetes v1.30.2
|
# k8s.io/kubernetes v1.30.3
|
||||||
## explicit; go 1.22.0
|
## explicit; go 1.22.0
|
||||||
k8s.io/kubernetes/pkg/api/legacyscheme
|
k8s.io/kubernetes/pkg/api/legacyscheme
|
||||||
k8s.io/kubernetes/pkg/api/service
|
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/format
|
||||||
k8s.io/kubernetes/test/utils/image
|
k8s.io/kubernetes/test/utils/image
|
||||||
k8s.io/kubernetes/test/utils/kubeconfig
|
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
|
## explicit; go 1.21
|
||||||
k8s.io/mount-utils
|
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
|
## explicit; go 1.22.0
|
||||||
k8s.io/pod-security-admission/api
|
k8s.io/pod-security-admission/api
|
||||||
k8s.io/pod-security-admission/policy
|
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/client_golang => github.com/prometheus/client_golang v1.18.0
|
||||||
# github.com/prometheus/common => github.com/prometheus/common v0.47.0
|
# github.com/prometheus/common => github.com/prometheus/common v0.47.0
|
||||||
# gomodules.xyz/jsonpatch/v2 => github.com/gomodules/jsonpatch/v2 v2.2.0
|
# gomodules.xyz/jsonpatch/v2 => github.com/gomodules/jsonpatch/v2 v2.2.0
|
||||||
# k8s.io/api => k8s.io/api v0.30.2
|
# k8s.io/api => k8s.io/api v0.30.3
|
||||||
# k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.30.2
|
# k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.30.3
|
||||||
# k8s.io/apimachinery => k8s.io/apimachinery v0.30.2
|
# k8s.io/apimachinery => k8s.io/apimachinery v0.30.3
|
||||||
# k8s.io/apiserver => k8s.io/apiserver v0.30.2
|
# k8s.io/apiserver => k8s.io/apiserver v0.30.3
|
||||||
# k8s.io/cli-runtime => k8s.io/cli-runtime v0.30.2
|
# k8s.io/cli-runtime => k8s.io/cli-runtime v0.30.3
|
||||||
# k8s.io/client-go => k8s.io/client-go v0.30.2
|
# k8s.io/client-go => k8s.io/client-go v0.30.3
|
||||||
# k8s.io/cloud-provider => k8s.io/cloud-provider v0.30.2
|
# k8s.io/cloud-provider => k8s.io/cloud-provider v0.30.3
|
||||||
# k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.30.2
|
# k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.30.3
|
||||||
# k8s.io/code-generator => k8s.io/code-generator v0.30.2
|
# k8s.io/code-generator => k8s.io/code-generator v0.30.3
|
||||||
# k8s.io/component-base => k8s.io/component-base v0.30.2
|
# k8s.io/component-base => k8s.io/component-base v0.30.3
|
||||||
# k8s.io/component-helpers => k8s.io/component-helpers v0.30.2
|
# k8s.io/component-helpers => k8s.io/component-helpers v0.30.3
|
||||||
# k8s.io/controller-manager => k8s.io/controller-manager v0.30.2
|
# k8s.io/controller-manager => k8s.io/controller-manager v0.30.3
|
||||||
# k8s.io/cri-api => k8s.io/cri-api v0.30.2
|
# k8s.io/cri-api => k8s.io/cri-api v0.30.3
|
||||||
# k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.30.2
|
# 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.2
|
# k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.30.3
|
||||||
# k8s.io/endpointslice => k8s.io/endpointslice v0.30.2
|
# k8s.io/endpointslice => k8s.io/endpointslice v0.30.3
|
||||||
# k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.30.2
|
# k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.30.3
|
||||||
# k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.30.2
|
# k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.30.3
|
||||||
# k8s.io/kube-proxy => k8s.io/kube-proxy v0.30.2
|
# k8s.io/kube-proxy => k8s.io/kube-proxy v0.30.3
|
||||||
# k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.30.2
|
# k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.30.3
|
||||||
# k8s.io/kubectl => k8s.io/kubectl v0.30.2
|
# k8s.io/kubectl => k8s.io/kubectl v0.30.3
|
||||||
# k8s.io/kubelet => k8s.io/kubelet v0.30.2
|
# k8s.io/kubelet => k8s.io/kubelet v0.30.3
|
||||||
# k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.30.2
|
# k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.30.3
|
||||||
# k8s.io/metrics => k8s.io/metrics v0.30.2
|
# k8s.io/metrics => k8s.io/metrics v0.30.3
|
||||||
# k8s.io/mount-utils => k8s.io/mount-utils v0.29.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/pod-security-admission => k8s.io/pod-security-admission v0.30.3
|
||||||
# k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.30.2
|
# k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.30.3
|
||||||
# layeh.com/radius => github.com/layeh/radius v0.0.0-20190322222518-890bc1058917
|
# layeh.com/radius => github.com/layeh/radius v0.0.0-20190322222518-890bc1058917
|
||||||
|
Loading…
Reference in New Issue
Block a user