mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 10:20:51 +00:00
Merge pull request #113186 from ttakahashi21/KEP-3294
Introduce APIs to support CrossNamespaceSourceProvisioning
This commit is contained in:
commit
d94261e904
31
api/openapi-spec/swagger.json
generated
31
api/openapi-spec/swagger.json
generated
@ -7014,11 +7014,11 @@
|
||||
},
|
||||
"dataSource": {
|
||||
"$ref": "#/definitions/io.k8s.api.core.v1.TypedLocalObjectReference",
|
||||
"description": "dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field."
|
||||
"description": "dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. If the namespace is specified, then dataSourceRef will not be copied to dataSource."
|
||||
},
|
||||
"dataSourceRef": {
|
||||
"$ref": "#/definitions/io.k8s.api.core.v1.TypedLocalObjectReference",
|
||||
"description": "dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. There are two important differences between DataSource and DataSourceRef: * While DataSource only allows two specific types of objects, DataSourceRef\n allows any non-core object, as well as PersistentVolumeClaim objects.\n* While DataSource ignores disallowed values (dropping them), DataSourceRef\n preserves all values, and generates an error if a disallowed value is\n specified.\n(Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled."
|
||||
"$ref": "#/definitions/io.k8s.api.core.v1.TypedObjectReference",
|
||||
"description": "dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, when namespace isn't specified in dataSourceRef, both fields (dataSource and dataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. When namespace is specified in dataSourceRef, dataSource isn't set to the same value and must be empty. There are three important differences between dataSource and dataSourceRef: * While dataSource only allows two specific types of objects, dataSourceRef\n allows any non-core object, as well as PersistentVolumeClaim objects.\n* While dataSource ignores disallowed values (dropping them), dataSourceRef\n preserves all values, and generates an error if a disallowed value is\n specified.\n* While dataSource only allows local objects, dataSourceRef allows objects\n in any namespaces.\n(Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled."
|
||||
},
|
||||
"resources": {
|
||||
"$ref": "#/definitions/io.k8s.api.core.v1.ResourceRequirements",
|
||||
@ -9619,6 +9619,31 @@
|
||||
"type": "object",
|
||||
"x-kubernetes-map-type": "atomic"
|
||||
},
|
||||
"io.k8s.api.core.v1.TypedObjectReference": {
|
||||
"properties": {
|
||||
"apiGroup": {
|
||||
"description": "APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required.",
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"description": "Kind is the type of resource being referenced",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"description": "Name is the name of resource being referenced",
|
||||
"type": "string"
|
||||
},
|
||||
"namespace": {
|
||||
"description": "Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind",
|
||||
"name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"io.k8s.api.core.v1.Volume": {
|
||||
"description": "Volume represents a named volume in a pod that may be accessed by any container in the pod.",
|
||||
"properties": {
|
||||
|
@ -4080,15 +4080,15 @@
|
||||
"$ref": "#/components/schemas/io.k8s.api.core.v1.TypedLocalObjectReference"
|
||||
}
|
||||
],
|
||||
"description": "dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field."
|
||||
"description": "dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. If the namespace is specified, then dataSourceRef will not be copied to dataSource."
|
||||
},
|
||||
"dataSourceRef": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/io.k8s.api.core.v1.TypedLocalObjectReference"
|
||||
"$ref": "#/components/schemas/io.k8s.api.core.v1.TypedObjectReference"
|
||||
}
|
||||
],
|
||||
"description": "dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. There are two important differences between DataSource and DataSourceRef: * While DataSource only allows two specific types of objects, DataSourceRef\n allows any non-core object, as well as PersistentVolumeClaim objects.\n* While DataSource ignores disallowed values (dropping them), DataSourceRef\n preserves all values, and generates an error if a disallowed value is\n specified.\n(Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled."
|
||||
"description": "dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, when namespace isn't specified in dataSourceRef, both fields (dataSource and dataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. When namespace is specified in dataSourceRef, dataSource isn't set to the same value and must be empty. There are three important differences between dataSource and dataSourceRef: * While dataSource only allows two specific types of objects, dataSourceRef\n allows any non-core object, as well as PersistentVolumeClaim objects.\n* While dataSource ignores disallowed values (dropping them), dataSourceRef\n preserves all values, and generates an error if a disallowed value is\n specified.\n* While dataSource only allows local objects, dataSourceRef allows objects\n in any namespaces.\n(Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled."
|
||||
},
|
||||
"resources": {
|
||||
"allOf": [
|
||||
@ -7359,6 +7359,33 @@
|
||||
"type": "object",
|
||||
"x-kubernetes-map-type": "atomic"
|
||||
},
|
||||
"io.k8s.api.core.v1.TypedObjectReference": {
|
||||
"properties": {
|
||||
"apiGroup": {
|
||||
"description": "APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required.",
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"default": "",
|
||||
"description": "Kind is the type of resource being referenced",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"default": "",
|
||||
"description": "Name is the name of resource being referenced",
|
||||
"type": "string"
|
||||
},
|
||||
"namespace": {
|
||||
"description": "Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind",
|
||||
"name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"io.k8s.api.core.v1.Volume": {
|
||||
"description": "Volume represents a named volume in a pod that may be accessed by any container in the pod.",
|
||||
"properties": {
|
||||
|
@ -2973,15 +2973,15 @@
|
||||
"$ref": "#/components/schemas/io.k8s.api.core.v1.TypedLocalObjectReference"
|
||||
}
|
||||
],
|
||||
"description": "dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field."
|
||||
"description": "dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. If the namespace is specified, then dataSourceRef will not be copied to dataSource."
|
||||
},
|
||||
"dataSourceRef": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/io.k8s.api.core.v1.TypedLocalObjectReference"
|
||||
"$ref": "#/components/schemas/io.k8s.api.core.v1.TypedObjectReference"
|
||||
}
|
||||
],
|
||||
"description": "dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. There are two important differences between DataSource and DataSourceRef: * While DataSource only allows two specific types of objects, DataSourceRef\n allows any non-core object, as well as PersistentVolumeClaim objects.\n* While DataSource ignores disallowed values (dropping them), DataSourceRef\n preserves all values, and generates an error if a disallowed value is\n specified.\n(Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled."
|
||||
"description": "dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, when namespace isn't specified in dataSourceRef, both fields (dataSource and dataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. When namespace is specified in dataSourceRef, dataSource isn't set to the same value and must be empty. There are three important differences between dataSource and dataSourceRef: * While dataSource only allows two specific types of objects, dataSourceRef\n allows any non-core object, as well as PersistentVolumeClaim objects.\n* While dataSource ignores disallowed values (dropping them), dataSourceRef\n preserves all values, and generates an error if a disallowed value is\n specified.\n* While dataSource only allows local objects, dataSourceRef allows objects\n in any namespaces.\n(Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled."
|
||||
},
|
||||
"resources": {
|
||||
"allOf": [
|
||||
@ -4475,6 +4475,33 @@
|
||||
"type": "object",
|
||||
"x-kubernetes-map-type": "atomic"
|
||||
},
|
||||
"io.k8s.api.core.v1.TypedObjectReference": {
|
||||
"properties": {
|
||||
"apiGroup": {
|
||||
"description": "APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required.",
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"default": "",
|
||||
"description": "Kind is the type of resource being referenced",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"default": "",
|
||||
"description": "Name is the name of resource being referenced",
|
||||
"type": "string"
|
||||
},
|
||||
"namespace": {
|
||||
"description": "Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind",
|
||||
"name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"io.k8s.api.core.v1.Volume": {
|
||||
"description": "Volume represents a named volume in a pod that may be accessed by any container in the pod.",
|
||||
"properties": {
|
||||
|
@ -2207,15 +2207,15 @@
|
||||
"$ref": "#/components/schemas/io.k8s.api.core.v1.TypedLocalObjectReference"
|
||||
}
|
||||
],
|
||||
"description": "dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field."
|
||||
"description": "dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. If the namespace is specified, then dataSourceRef will not be copied to dataSource."
|
||||
},
|
||||
"dataSourceRef": {
|
||||
"allOf": [
|
||||
{
|
||||
"$ref": "#/components/schemas/io.k8s.api.core.v1.TypedLocalObjectReference"
|
||||
"$ref": "#/components/schemas/io.k8s.api.core.v1.TypedObjectReference"
|
||||
}
|
||||
],
|
||||
"description": "dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. There are two important differences between DataSource and DataSourceRef: * While DataSource only allows two specific types of objects, DataSourceRef\n allows any non-core object, as well as PersistentVolumeClaim objects.\n* While DataSource ignores disallowed values (dropping them), DataSourceRef\n preserves all values, and generates an error if a disallowed value is\n specified.\n(Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled."
|
||||
"description": "dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, when namespace isn't specified in dataSourceRef, both fields (dataSource and dataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. When namespace is specified in dataSourceRef, dataSource isn't set to the same value and must be empty. There are three important differences between dataSource and dataSourceRef: * While dataSource only allows two specific types of objects, dataSourceRef\n allows any non-core object, as well as PersistentVolumeClaim objects.\n* While dataSource ignores disallowed values (dropping them), dataSourceRef\n preserves all values, and generates an error if a disallowed value is\n specified.\n* While dataSource only allows local objects, dataSourceRef allows objects\n in any namespaces.\n(Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled."
|
||||
},
|
||||
"resources": {
|
||||
"allOf": [
|
||||
@ -3649,6 +3649,33 @@
|
||||
"type": "object",
|
||||
"x-kubernetes-map-type": "atomic"
|
||||
},
|
||||
"io.k8s.api.core.v1.TypedObjectReference": {
|
||||
"properties": {
|
||||
"apiGroup": {
|
||||
"description": "APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required.",
|
||||
"type": "string"
|
||||
},
|
||||
"kind": {
|
||||
"default": "",
|
||||
"description": "Kind is the type of resource being referenced",
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"default": "",
|
||||
"description": "Name is the name of resource being referenced",
|
||||
"type": "string"
|
||||
},
|
||||
"namespace": {
|
||||
"description": "Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"kind",
|
||||
"name"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"io.k8s.api.core.v1.Volume": {
|
||||
"description": "Volume represents a named volume in a pod that may be accessed by any container in the pod.",
|
||||
"properties": {
|
||||
|
@ -32,11 +32,22 @@ const (
|
||||
|
||||
// DropDisabledFields removes disabled fields from the pvc spec.
|
||||
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pvc spec.
|
||||
func DropDisabledFields(pvcSpec *core.PersistentVolumeClaimSpec) {
|
||||
func DropDisabledFields(pvcSpec, oldPVCSpec *core.PersistentVolumeClaimSpec) {
|
||||
// Drop the contents of the dataSourceRef field if the AnyVolumeDataSource
|
||||
// feature gate is disabled.
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.AnyVolumeDataSource) {
|
||||
pvcSpec.DataSourceRef = nil
|
||||
if !dataSourceRefInUse(oldPVCSpec) {
|
||||
pvcSpec.DataSourceRef = nil
|
||||
}
|
||||
}
|
||||
|
||||
// Drop the contents of the dataSourceRef field if the CrossNamespaceVolumeDataSource
|
||||
// feature gate is disabled and dataSourceRef.Namespace is specified.
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.CrossNamespaceVolumeDataSource) &&
|
||||
pvcSpec.DataSourceRef != nil && pvcSpec.DataSourceRef.Namespace != nil && len(*pvcSpec.DataSourceRef.Namespace) != 0 {
|
||||
if !dataSourceRefInUse(oldPVCSpec) {
|
||||
pvcSpec.DataSourceRef = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,6 +127,16 @@ func dataSourceIsPvcOrSnapshot(dataSource *core.TypedLocalObjectReference) bool
|
||||
return false
|
||||
}
|
||||
|
||||
func dataSourceRefInUse(oldPVCSpec *core.PersistentVolumeClaimSpec) bool {
|
||||
if oldPVCSpec == nil {
|
||||
return false
|
||||
}
|
||||
if oldPVCSpec.DataSourceRef != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// NormalizeDataSources ensures that DataSource and DataSourceRef have the same contents
|
||||
// as long as both are not explicitly set.
|
||||
// This should be used by creates/gets of PVCs, but not updates
|
||||
@ -126,10 +147,26 @@ func NormalizeDataSources(pvcSpec *core.PersistentVolumeClaimSpec) {
|
||||
}
|
||||
if pvcSpec.DataSource != nil && pvcSpec.DataSourceRef == nil {
|
||||
// Using the old way of setting a data source
|
||||
pvcSpec.DataSourceRef = pvcSpec.DataSource.DeepCopy()
|
||||
pvcSpec.DataSourceRef = &core.TypedObjectReference{
|
||||
Kind: pvcSpec.DataSource.Kind,
|
||||
Name: pvcSpec.DataSource.Name,
|
||||
}
|
||||
if pvcSpec.DataSource.APIGroup != nil {
|
||||
apiGroup := *pvcSpec.DataSource.APIGroup
|
||||
pvcSpec.DataSourceRef.APIGroup = &apiGroup
|
||||
}
|
||||
} else if pvcSpec.DataSourceRef != nil && pvcSpec.DataSource == nil {
|
||||
// Using the new way of setting a data source
|
||||
pvcSpec.DataSource = pvcSpec.DataSourceRef.DeepCopy()
|
||||
if pvcSpec.DataSourceRef.Namespace == nil || len(*pvcSpec.DataSourceRef.Namespace) == 0 {
|
||||
// Using the new way of setting a data source
|
||||
pvcSpec.DataSource = &core.TypedLocalObjectReference{
|
||||
Kind: pvcSpec.DataSourceRef.Kind,
|
||||
Name: pvcSpec.DataSourceRef.Name,
|
||||
}
|
||||
if pvcSpec.DataSourceRef.APIGroup != nil {
|
||||
apiGroup := *pvcSpec.DataSourceRef.APIGroup
|
||||
pvcSpec.DataSource.APIGroup = &apiGroup
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -154,23 +154,47 @@ func TestPVCDataSourceSpecFilter(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestAnyDataSourceFilter checks to ensure the AnyVolumeDataSource feature gate works
|
||||
func TestAnyDataSourceFilter(t *testing.T) {
|
||||
makeDataSource := func(apiGroup, kind, name string) *core.TypedLocalObjectReference {
|
||||
return &core.TypedLocalObjectReference{
|
||||
APIGroup: &apiGroup,
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
}
|
||||
}
|
||||
var (
|
||||
coreGroup = ""
|
||||
snapGroup = "snapshot.storage.k8s.io"
|
||||
genericGroup = "generic.storage.k8s.io"
|
||||
pvcKind = "PersistentVolumeClaim"
|
||||
snapKind = "VolumeSnapshot"
|
||||
genericKind = "Generic"
|
||||
podKind = "Pod"
|
||||
)
|
||||
|
||||
volumeDataSource := makeDataSource("", "PersistentVolumeClaim", "my-vol")
|
||||
func makeDataSource(apiGroup, kind, name string) *core.TypedLocalObjectReference {
|
||||
return &core.TypedLocalObjectReference{
|
||||
APIGroup: &apiGroup,
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
}
|
||||
}
|
||||
|
||||
func makeDataSourceRef(apiGroup, kind, name string, namespace *string) *core.TypedObjectReference {
|
||||
return &core.TypedObjectReference{
|
||||
APIGroup: &apiGroup,
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
// TestDataSourceFilter checks to ensure the AnyVolumeDataSource feature gate and CrossNamespaceVolumeDataSource works
|
||||
func TestDataSourceFilter(t *testing.T) {
|
||||
ns := "ns1"
|
||||
volumeDataSource := makeDataSource(coreGroup, pvcKind, "my-vol")
|
||||
volumeDataSourceRef := makeDataSourceRef(coreGroup, pvcKind, "my-vol", nil)
|
||||
xnsVolumeDataSourceRef := makeDataSourceRef(coreGroup, pvcKind, "my-vol", &ns)
|
||||
|
||||
var tests = map[string]struct {
|
||||
spec core.PersistentVolumeClaimSpec
|
||||
oldSpec core.PersistentVolumeClaimSpec
|
||||
anyEnabled bool
|
||||
xnsEnabled bool
|
||||
want *core.TypedLocalObjectReference
|
||||
wantRef *core.TypedLocalObjectReference
|
||||
wantRef *core.TypedObjectReference
|
||||
}{
|
||||
"any disabled with empty ds": {
|
||||
spec: core.PersistentVolumeClaimSpec{},
|
||||
@ -180,10 +204,10 @@ func TestAnyDataSourceFilter(t *testing.T) {
|
||||
want: volumeDataSource,
|
||||
},
|
||||
"any disabled with volume ds ref": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: volumeDataSource},
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: volumeDataSourceRef},
|
||||
},
|
||||
"any disabled with both data sources": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSource: volumeDataSource, DataSourceRef: volumeDataSource},
|
||||
spec: core.PersistentVolumeClaimSpec{DataSource: volumeDataSource, DataSourceRef: volumeDataSourceRef},
|
||||
want: volumeDataSource,
|
||||
},
|
||||
"any enabled with empty ds": {
|
||||
@ -196,25 +220,63 @@ func TestAnyDataSourceFilter(t *testing.T) {
|
||||
want: volumeDataSource,
|
||||
},
|
||||
"any enabled with volume ds ref": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: volumeDataSource},
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: volumeDataSourceRef},
|
||||
anyEnabled: true,
|
||||
wantRef: volumeDataSource,
|
||||
wantRef: volumeDataSourceRef,
|
||||
},
|
||||
"any enabled with both data sources": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSource: volumeDataSource, DataSourceRef: volumeDataSource},
|
||||
spec: core.PersistentVolumeClaimSpec{DataSource: volumeDataSource, DataSourceRef: volumeDataSourceRef},
|
||||
anyEnabled: true,
|
||||
want: volumeDataSource,
|
||||
wantRef: volumeDataSource,
|
||||
wantRef: volumeDataSourceRef,
|
||||
},
|
||||
"both any and xns enabled with xns volume ds": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: xnsVolumeDataSourceRef},
|
||||
anyEnabled: true,
|
||||
xnsEnabled: true,
|
||||
wantRef: xnsVolumeDataSourceRef,
|
||||
},
|
||||
"both any and xns enabled with xns volume ds when xns volume exists in oldSpec": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: xnsVolumeDataSourceRef},
|
||||
oldSpec: core.PersistentVolumeClaimSpec{DataSourceRef: xnsVolumeDataSourceRef},
|
||||
anyEnabled: true,
|
||||
xnsEnabled: true,
|
||||
wantRef: xnsVolumeDataSourceRef,
|
||||
},
|
||||
"only xns enabled with xns volume ds": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: xnsVolumeDataSourceRef},
|
||||
xnsEnabled: true,
|
||||
},
|
||||
"only any enabled with xns volume ds": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: xnsVolumeDataSourceRef},
|
||||
anyEnabled: true,
|
||||
},
|
||||
"only any enabled with xns volume ds when xns volume exists in oldSpec": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: xnsVolumeDataSourceRef},
|
||||
oldSpec: core.PersistentVolumeClaimSpec{DataSourceRef: xnsVolumeDataSourceRef},
|
||||
anyEnabled: true,
|
||||
wantRef: xnsVolumeDataSourceRef, // existing field isn't dropped.
|
||||
},
|
||||
"only any enabled with xns volume ds when volume exists in oldSpec": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: xnsVolumeDataSourceRef},
|
||||
oldSpec: core.PersistentVolumeClaimSpec{DataSourceRef: volumeDataSourceRef},
|
||||
anyEnabled: true,
|
||||
wantRef: xnsVolumeDataSourceRef, // existing field isn't dropped.
|
||||
},
|
||||
}
|
||||
|
||||
for testName, test := range tests {
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.AnyVolumeDataSource, test.anyEnabled)()
|
||||
DropDisabledFields(&test.spec)
|
||||
if test.spec.DataSource != test.want || test.spec.DataSourceRef != test.wantRef {
|
||||
t.Errorf("expected condition was not met, test: %s, anyEnabled: %v, spec: %v, expected: %v %v",
|
||||
testName, test.anyEnabled, test.spec, test.want, test.wantRef)
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CrossNamespaceVolumeDataSource, test.xnsEnabled)()
|
||||
DropDisabledFields(&test.spec, &test.oldSpec)
|
||||
if test.spec.DataSource != test.want {
|
||||
t.Errorf("expected condition was not met, test: %s, anyEnabled: %v, xnsEnabled: %v, spec: %+v, expected DataSource: %+v",
|
||||
testName, test.anyEnabled, test.xnsEnabled, test.spec, test.want)
|
||||
}
|
||||
if test.spec.DataSourceRef != test.wantRef {
|
||||
t.Errorf("expected condition was not met, test: %s, anyEnabled: %v, xnsEnabled: %v, spec: %+v, expected DataSourceRef: %+v",
|
||||
testName, test.anyEnabled, test.xnsEnabled, test.spec, test.wantRef)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -223,69 +285,99 @@ func TestAnyDataSourceFilter(t *testing.T) {
|
||||
// TestDataSourceRef checks to ensure the DataSourceRef field handles backwards
|
||||
// compatibility with the DataSource field
|
||||
func TestDataSourceRef(t *testing.T) {
|
||||
makeDataSource := func(apiGroup, kind, name string) *core.TypedLocalObjectReference {
|
||||
return &core.TypedLocalObjectReference{
|
||||
APIGroup: &apiGroup,
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
}
|
||||
}
|
||||
|
||||
volumeDataSource := makeDataSource("", "PersistentVolumeClaim", "my-vol")
|
||||
snapshotDataSource := makeDataSource("snapshot.storage.k8s.io", "VolumeSnapshot", "my-snap")
|
||||
genericDataSource := makeDataSource("generic.storage.k8s.io", "Generic", "my-foo")
|
||||
coreDataSource := makeDataSource("", "Pod", "my-pod")
|
||||
ns := "ns1"
|
||||
volumeDataSource := makeDataSource(coreGroup, pvcKind, "my-vol")
|
||||
volumeDataSourceRef := makeDataSourceRef(coreGroup, pvcKind, "my-vol", nil)
|
||||
xnsVolumeDataSourceRef := makeDataSourceRef(coreGroup, pvcKind, "my-vol", &ns)
|
||||
snapshotDataSource := makeDataSource(snapGroup, snapKind, "my-snap")
|
||||
snapshotDataSourceRef := makeDataSourceRef(snapGroup, snapKind, "my-snap", nil)
|
||||
xnsSnapshotDataSourceRef := makeDataSourceRef(snapGroup, snapKind, "my-snap", &ns)
|
||||
genericDataSource := makeDataSource(genericGroup, genericKind, "my-foo")
|
||||
genericDataSourceRef := makeDataSourceRef(genericGroup, genericKind, "my-foo", nil)
|
||||
xnsGenericDataSourceRef := makeDataSourceRef(genericGroup, genericKind, "my-foo", &ns)
|
||||
coreDataSource := makeDataSource(coreGroup, podKind, "my-pod")
|
||||
coreDataSourceRef := makeDataSourceRef(coreGroup, podKind, "my-pod", nil)
|
||||
xnsCoreDataSourceRef := makeDataSourceRef(coreGroup, podKind, "my-pod", &ns)
|
||||
|
||||
var tests = map[string]struct {
|
||||
spec core.PersistentVolumeClaimSpec
|
||||
want *core.TypedLocalObjectReference
|
||||
spec core.PersistentVolumeClaimSpec
|
||||
want *core.TypedLocalObjectReference
|
||||
wantRef *core.TypedObjectReference
|
||||
}{
|
||||
"empty ds": {
|
||||
spec: core.PersistentVolumeClaimSpec{},
|
||||
},
|
||||
"volume ds": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSource: volumeDataSource},
|
||||
want: volumeDataSource,
|
||||
spec: core.PersistentVolumeClaimSpec{DataSource: volumeDataSource},
|
||||
want: volumeDataSource,
|
||||
wantRef: volumeDataSourceRef,
|
||||
},
|
||||
"snapshot ds": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSource: snapshotDataSource},
|
||||
want: snapshotDataSource,
|
||||
spec: core.PersistentVolumeClaimSpec{DataSource: snapshotDataSource},
|
||||
want: snapshotDataSource,
|
||||
wantRef: snapshotDataSourceRef,
|
||||
},
|
||||
"generic ds": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSource: genericDataSource},
|
||||
want: genericDataSource,
|
||||
spec: core.PersistentVolumeClaimSpec{DataSource: genericDataSource},
|
||||
want: genericDataSource,
|
||||
wantRef: genericDataSourceRef,
|
||||
},
|
||||
"core ds": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSource: coreDataSource},
|
||||
want: coreDataSource,
|
||||
spec: core.PersistentVolumeClaimSpec{DataSource: coreDataSource},
|
||||
want: coreDataSource,
|
||||
wantRef: coreDataSourceRef,
|
||||
},
|
||||
"volume ds ref": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: volumeDataSource},
|
||||
want: volumeDataSource,
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: volumeDataSourceRef},
|
||||
want: volumeDataSource,
|
||||
wantRef: volumeDataSourceRef,
|
||||
},
|
||||
"snapshot ds ref": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: snapshotDataSource},
|
||||
want: snapshotDataSource,
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: snapshotDataSourceRef},
|
||||
want: snapshotDataSource,
|
||||
wantRef: snapshotDataSourceRef,
|
||||
},
|
||||
"generic ds ref": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: genericDataSource},
|
||||
want: genericDataSource,
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: genericDataSourceRef},
|
||||
want: genericDataSource,
|
||||
wantRef: genericDataSourceRef,
|
||||
},
|
||||
"core ds ref": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: coreDataSource},
|
||||
want: coreDataSource,
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: coreDataSourceRef},
|
||||
want: coreDataSource,
|
||||
wantRef: coreDataSourceRef,
|
||||
},
|
||||
"xns volume ds ref": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: xnsVolumeDataSourceRef},
|
||||
wantRef: xnsVolumeDataSourceRef,
|
||||
},
|
||||
"xns snapshot ds ref": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: xnsSnapshotDataSourceRef},
|
||||
wantRef: xnsSnapshotDataSourceRef,
|
||||
},
|
||||
"xns generic ds ref": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: xnsGenericDataSourceRef},
|
||||
wantRef: xnsGenericDataSourceRef,
|
||||
},
|
||||
"xns core ds ref": {
|
||||
spec: core.PersistentVolumeClaimSpec{DataSourceRef: xnsCoreDataSourceRef},
|
||||
wantRef: xnsCoreDataSourceRef,
|
||||
},
|
||||
}
|
||||
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.AnyVolumeDataSource, true)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CrossNamespaceVolumeDataSource, true)()
|
||||
|
||||
for testName, test := range tests {
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
NormalizeDataSources(&test.spec)
|
||||
if !reflect.DeepEqual(test.spec.DataSource, test.want) ||
|
||||
!reflect.DeepEqual(test.spec.DataSourceRef, test.want) {
|
||||
t.Errorf("expected condition was not met, test: %s, spec: %v, expected: %v",
|
||||
testName, test.spec, test.want)
|
||||
if !reflect.DeepEqual(test.spec.DataSource, test.want) {
|
||||
t.Errorf("expected condition was not met, test: %s, spec.datasource: %+v, want: %+v",
|
||||
testName, test.spec.DataSource, test.want)
|
||||
}
|
||||
if !reflect.DeepEqual(test.spec.DataSourceRef, test.wantRef) {
|
||||
t.Errorf("expected condition was not met, test: %s, spec.datasourceRef: %+v, wantRef: %+v",
|
||||
testName, test.spec.DataSourceRef, test.wantRef)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -452,29 +452,54 @@ type PersistentVolumeClaimSpec struct {
|
||||
// * An existing PVC (PersistentVolumeClaim)
|
||||
// If the provisioner or an external controller can support the specified data source,
|
||||
// it will create a new volume based on the contents of the specified data source.
|
||||
// If the AnyVolumeDataSource feature gate is enabled, this field will always have
|
||||
// the same contents as the DataSourceRef field.
|
||||
// When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef,
|
||||
// and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified.
|
||||
// If the namespace is specified, then dataSourceRef will not be copied to dataSource.
|
||||
// +optional
|
||||
DataSource *TypedLocalObjectReference
|
||||
// Specifies the object from which to populate the volume with data, if a non-empty
|
||||
// volume is desired. This may be any local object from a non-empty API group (non
|
||||
// volume is desired. This may be any object from a non-empty API group (non
|
||||
// core object) or a PersistentVolumeClaim object.
|
||||
// When this field is specified, volume binding will only succeed if the type of
|
||||
// the specified object matches some installed volume populator or dynamic
|
||||
// provisioner.
|
||||
// This field will replace the functionality of the DataSource field and as such
|
||||
// This field will replace the functionality of the dataSource field and as such
|
||||
// if both fields are non-empty, they must have the same value. For backwards
|
||||
// compatibility, both fields (DataSource and DataSourceRef) will be set to the same
|
||||
// compatibility, when namespace isn't specified in dataSourceRef,
|
||||
// both fields (dataSource and dataSourceRef) will be set to the same
|
||||
// value automatically if one of them is empty and the other is non-empty.
|
||||
// There are two important differences between DataSource and DataSourceRef:
|
||||
// * While DataSource only allows two specific types of objects, DataSourceRef
|
||||
// When namespace is specified in dataSourceRef,
|
||||
// dataSource isn't set to the same value and must be empty.
|
||||
// There are three important differences between dataSource and dataSourceRef:
|
||||
// * While dataSource only allows two specific types of objects, dataSourceRef
|
||||
// allows any non-core object, as well as PersistentVolumeClaim objects.
|
||||
// * While DataSource ignores disallowed values (dropping them), DataSourceRef
|
||||
// * While dataSource ignores disallowed values (dropping them), dataSourceRef
|
||||
// preserves all values, and generates an error if a disallowed value is
|
||||
// specified.
|
||||
// * While dataSource only allows local objects, dataSourceRef allows objects
|
||||
// in any namespaces.
|
||||
// (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled.
|
||||
// (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.
|
||||
// +optional
|
||||
DataSourceRef *TypedLocalObjectReference
|
||||
DataSourceRef *TypedObjectReference
|
||||
}
|
||||
|
||||
type TypedObjectReference struct {
|
||||
// APIGroup is the group for the resource being referenced.
|
||||
// If APIGroup is not specified, the specified Kind must be in the core API group.
|
||||
// For any other third-party types, APIGroup is required.
|
||||
// +optional
|
||||
APIGroup *string
|
||||
// Kind is the type of resource being referenced
|
||||
Kind string
|
||||
// Name is the name of resource being referenced
|
||||
Name string
|
||||
// Namespace is the namespace of resource being referenced
|
||||
// Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details.
|
||||
// (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled.
|
||||
// +featureGate=CrossNamespaceVolumeDataSource
|
||||
// +optional
|
||||
Namespace *string
|
||||
}
|
||||
|
||||
// PersistentVolumeClaimConditionType defines the condition of PV claim.
|
||||
|
40
pkg/apis/core/v1/zz_generated.conversion.go
generated
40
pkg/apis/core/v1/zz_generated.conversion.go
generated
@ -1977,6 +1977,16 @@ func RegisterConversions(s *runtime.Scheme) error {
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v1.TypedObjectReference)(nil), (*core.TypedObjectReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_TypedObjectReference_To_core_TypedObjectReference(a.(*v1.TypedObjectReference), b.(*core.TypedObjectReference), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*core.TypedObjectReference)(nil), (*v1.TypedObjectReference)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_core_TypedObjectReference_To_v1_TypedObjectReference(a.(*core.TypedObjectReference), b.(*v1.TypedObjectReference), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*v1.VolumeDevice)(nil), (*core.VolumeDevice)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1_VolumeDevice_To_core_VolumeDevice(a.(*v1.VolumeDevice), b.(*core.VolumeDevice), scope)
|
||||
}); err != nil {
|
||||
@ -5182,7 +5192,7 @@ func autoConvert_v1_PersistentVolumeClaimSpec_To_core_PersistentVolumeClaimSpec(
|
||||
out.StorageClassName = (*string)(unsafe.Pointer(in.StorageClassName))
|
||||
out.VolumeMode = (*core.PersistentVolumeMode)(unsafe.Pointer(in.VolumeMode))
|
||||
out.DataSource = (*core.TypedLocalObjectReference)(unsafe.Pointer(in.DataSource))
|
||||
out.DataSourceRef = (*core.TypedLocalObjectReference)(unsafe.Pointer(in.DataSourceRef))
|
||||
out.DataSourceRef = (*core.TypedObjectReference)(unsafe.Pointer(in.DataSourceRef))
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -5201,7 +5211,7 @@ func autoConvert_core_PersistentVolumeClaimSpec_To_v1_PersistentVolumeClaimSpec(
|
||||
out.StorageClassName = (*string)(unsafe.Pointer(in.StorageClassName))
|
||||
out.VolumeMode = (*v1.PersistentVolumeMode)(unsafe.Pointer(in.VolumeMode))
|
||||
out.DataSource = (*v1.TypedLocalObjectReference)(unsafe.Pointer(in.DataSource))
|
||||
out.DataSourceRef = (*v1.TypedLocalObjectReference)(unsafe.Pointer(in.DataSourceRef))
|
||||
out.DataSourceRef = (*v1.TypedObjectReference)(unsafe.Pointer(in.DataSourceRef))
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -8083,6 +8093,32 @@ func Convert_core_TypedLocalObjectReference_To_v1_TypedLocalObjectReference(in *
|
||||
return autoConvert_core_TypedLocalObjectReference_To_v1_TypedLocalObjectReference(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_TypedObjectReference_To_core_TypedObjectReference(in *v1.TypedObjectReference, out *core.TypedObjectReference, s conversion.Scope) error {
|
||||
out.APIGroup = (*string)(unsafe.Pointer(in.APIGroup))
|
||||
out.Kind = in.Kind
|
||||
out.Name = in.Name
|
||||
out.Namespace = (*string)(unsafe.Pointer(in.Namespace))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1_TypedObjectReference_To_core_TypedObjectReference is an autogenerated conversion function.
|
||||
func Convert_v1_TypedObjectReference_To_core_TypedObjectReference(in *v1.TypedObjectReference, out *core.TypedObjectReference, s conversion.Scope) error {
|
||||
return autoConvert_v1_TypedObjectReference_To_core_TypedObjectReference(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_core_TypedObjectReference_To_v1_TypedObjectReference(in *core.TypedObjectReference, out *v1.TypedObjectReference, s conversion.Scope) error {
|
||||
out.APIGroup = (*string)(unsafe.Pointer(in.APIGroup))
|
||||
out.Kind = in.Kind
|
||||
out.Name = in.Name
|
||||
out.Namespace = (*string)(unsafe.Pointer(in.Namespace))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_core_TypedObjectReference_To_v1_TypedObjectReference is an autogenerated conversion function.
|
||||
func Convert_core_TypedObjectReference_To_v1_TypedObjectReference(in *core.TypedObjectReference, out *v1.TypedObjectReference, s conversion.Scope) error {
|
||||
return autoConvert_core_TypedObjectReference_To_v1_TypedObjectReference(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1_Volume_To_core_Volume(in *v1.Volume, out *core.Volume, s conversion.Scope) error {
|
||||
out.Name = in.Name
|
||||
if err := Convert_v1_VolumeSource_To_core_VolumeSource(&in.VolumeSource, &out.VolumeSource, s); err != nil {
|
||||
|
@ -2104,7 +2104,34 @@ func validateDataSource(dataSource *core.TypedLocalObjectReference, fldPath *fie
|
||||
apiGroup = *dataSource.APIGroup
|
||||
}
|
||||
if len(apiGroup) == 0 && dataSource.Kind != "PersistentVolumeClaim" {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, dataSource.Kind, ""))
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, dataSource.Kind, "must be 'PersistentVolumeClaim' when referencing the default apiGroup"))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// validateDataSourceRef validates a DataSourceRef in a PersistentVolumeClaimSpec
|
||||
func validateDataSourceRef(dataSourceRef *core.TypedObjectReference, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if len(dataSourceRef.Name) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("name"), ""))
|
||||
}
|
||||
if len(dataSourceRef.Kind) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("kind"), ""))
|
||||
}
|
||||
apiGroup := ""
|
||||
if dataSourceRef.APIGroup != nil {
|
||||
apiGroup = *dataSourceRef.APIGroup
|
||||
}
|
||||
if len(apiGroup) == 0 && dataSourceRef.Kind != "PersistentVolumeClaim" {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, dataSourceRef.Kind, "must be 'PersistentVolumeClaim' when referencing the default apiGroup"))
|
||||
}
|
||||
|
||||
if dataSourceRef.Namespace != nil && len(*dataSourceRef.Namespace) > 0 {
|
||||
for _, msg := range ValidateNameFunc(ValidateNamespaceName)(*dataSourceRef.Namespace, false) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("namespace"), *dataSourceRef.Namespace, msg))
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
@ -2166,10 +2193,15 @@ func ValidatePersistentVolumeClaimSpec(spec *core.PersistentVolumeClaimSpec, fld
|
||||
allErrs = append(allErrs, validateDataSource(spec.DataSource, fldPath.Child("dataSource"))...)
|
||||
}
|
||||
if spec.DataSourceRef != nil {
|
||||
allErrs = append(allErrs, validateDataSource(spec.DataSourceRef, fldPath.Child("dataSourceRef"))...)
|
||||
allErrs = append(allErrs, validateDataSourceRef(spec.DataSourceRef, fldPath.Child("dataSourceRef"))...)
|
||||
}
|
||||
if spec.DataSource != nil && spec.DataSourceRef != nil {
|
||||
if !apiequality.Semantic.DeepEqual(spec.DataSource, spec.DataSourceRef) {
|
||||
if spec.DataSourceRef != nil && spec.DataSourceRef.Namespace != nil && len(*spec.DataSourceRef.Namespace) > 0 {
|
||||
if spec.DataSource != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, fldPath.Child("dataSource"),
|
||||
"may not be specified when dataSourceRef.namespace is specified"))
|
||||
}
|
||||
} else if spec.DataSource != nil && spec.DataSourceRef != nil {
|
||||
if !isDataSourceEqualDataSourceRef(spec.DataSource, spec.DataSourceRef) {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, fldPath.Child("dataSource"),
|
||||
"must match dataSourceRef"))
|
||||
}
|
||||
@ -2178,6 +2210,10 @@ func ValidatePersistentVolumeClaimSpec(spec *core.PersistentVolumeClaimSpec, fld
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func isDataSourceEqualDataSourceRef(dataSource *core.TypedLocalObjectReference, dataSourceRef *core.TypedObjectReference) bool {
|
||||
return reflect.DeepEqual(dataSource.APIGroup, dataSourceRef.APIGroup) && dataSource.Kind == dataSourceRef.Kind && dataSource.Name == dataSourceRef.Name
|
||||
}
|
||||
|
||||
// ValidatePersistentVolumeClaimUpdate validates an update to a PersistentVolumeClaim
|
||||
func ValidatePersistentVolumeClaimUpdate(newPvc, oldPvc *core.PersistentVolumeClaim, opts PersistentVolumeClaimSpecValidationOptions) field.ErrorList {
|
||||
allErrs := ValidateObjectMetaUpdate(&newPvc.ObjectMeta, &oldPvc.ObjectMeta, field.NewPath("metadata"))
|
||||
|
@ -1672,7 +1672,7 @@ func testValidatePVC(t *testing.T, ephemeral bool) {
|
||||
Kind: "PersistentVolumeClaim",
|
||||
Name: "pvc1",
|
||||
},
|
||||
DataSourceRef: &core.TypedLocalObjectReference{
|
||||
DataSourceRef: &core.TypedObjectReference{
|
||||
Kind: "PersistentVolumeClaim",
|
||||
Name: "pvc2",
|
||||
},
|
||||
@ -19816,7 +19816,11 @@ func testAnyDataSource(t *testing.T, ds, dsRef bool) {
|
||||
|
||||
for _, tc := range testCases {
|
||||
if dsRef {
|
||||
tc.claimSpec.DataSourceRef = tc.claimSpec.DataSource.DeepCopy()
|
||||
tc.claimSpec.DataSourceRef = &core.TypedObjectReference{
|
||||
APIGroup: tc.claimSpec.DataSource.APIGroup,
|
||||
Kind: tc.claimSpec.DataSource.Kind,
|
||||
Name: tc.claimSpec.DataSource.Name,
|
||||
}
|
||||
}
|
||||
if !ds {
|
||||
tc.claimSpec.DataSource = nil
|
||||
@ -19840,6 +19844,110 @@ func TestAnyDataSource(t *testing.T) {
|
||||
testAnyDataSource(t, true, false)
|
||||
}
|
||||
|
||||
func pvcSpecWithCrossNamespaceSource(apiGroup *string, kind string, namespace *string, name string, isDataSourceSet bool) *core.PersistentVolumeClaimSpec {
|
||||
scName := "csi-plugin"
|
||||
spec := core.PersistentVolumeClaimSpec{
|
||||
AccessModes: []core.PersistentVolumeAccessMode{
|
||||
core.ReadOnlyMany,
|
||||
},
|
||||
Resources: core.ResourceRequirements{
|
||||
Requests: core.ResourceList{
|
||||
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
|
||||
},
|
||||
},
|
||||
StorageClassName: &scName,
|
||||
DataSourceRef: &core.TypedObjectReference{
|
||||
APIGroup: apiGroup,
|
||||
Kind: kind,
|
||||
Namespace: namespace,
|
||||
Name: name,
|
||||
},
|
||||
}
|
||||
|
||||
if isDataSourceSet {
|
||||
spec.DataSource = &core.TypedLocalObjectReference{
|
||||
APIGroup: apiGroup,
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
}
|
||||
}
|
||||
return &spec
|
||||
}
|
||||
|
||||
func TestCrossNamespaceSource(t *testing.T) {
|
||||
snapAPIGroup := "snapshot.storage.k8s.io"
|
||||
coreAPIGroup := ""
|
||||
unsupportedAPIGroup := "unsupported.example.com"
|
||||
snapKind := "VolumeSnapshot"
|
||||
pvcKind := "PersistentVolumeClaim"
|
||||
goodNS := "ns1"
|
||||
badNS := "a*b"
|
||||
emptyNS := ""
|
||||
goodName := "snapshot1"
|
||||
|
||||
testCases := []struct {
|
||||
testName string
|
||||
expectedFail bool
|
||||
claimSpec *core.PersistentVolumeClaimSpec
|
||||
}{
|
||||
{
|
||||
testName: "Feature gate enabled and valid xns DataSourceRef specified",
|
||||
expectedFail: false,
|
||||
claimSpec: pvcSpecWithCrossNamespaceSource(&snapAPIGroup, snapKind, &goodNS, goodName, false),
|
||||
},
|
||||
{
|
||||
testName: "Feature gate enabled and xns DataSourceRef with PVC source specified",
|
||||
expectedFail: false,
|
||||
claimSpec: pvcSpecWithCrossNamespaceSource(&coreAPIGroup, pvcKind, &goodNS, goodName, false),
|
||||
},
|
||||
{
|
||||
testName: "Feature gate enabled and xns DataSourceRef with unsupported source specified",
|
||||
expectedFail: false,
|
||||
claimSpec: pvcSpecWithCrossNamespaceSource(&unsupportedAPIGroup, "UnsupportedKind", &goodNS, goodName, false),
|
||||
},
|
||||
{
|
||||
testName: "Feature gate enabled and xns DataSourceRef with nil apiGroup",
|
||||
expectedFail: true,
|
||||
claimSpec: pvcSpecWithCrossNamespaceSource(nil, "UnsupportedKind", &goodNS, goodName, false),
|
||||
},
|
||||
{
|
||||
testName: "Feature gate enabled and xns DataSourceRef with invalid namspace specified",
|
||||
expectedFail: true,
|
||||
claimSpec: pvcSpecWithCrossNamespaceSource(&snapAPIGroup, snapKind, &badNS, goodName, false),
|
||||
},
|
||||
{
|
||||
testName: "Feature gate enabled and xns DataSourceRef with nil namspace specified",
|
||||
expectedFail: false,
|
||||
claimSpec: pvcSpecWithCrossNamespaceSource(&snapAPIGroup, snapKind, nil, goodName, false),
|
||||
},
|
||||
{
|
||||
testName: "Feature gate enabled and xns DataSourceRef with empty namspace specified",
|
||||
expectedFail: false,
|
||||
claimSpec: pvcSpecWithCrossNamespaceSource(&snapAPIGroup, snapKind, &emptyNS, goodName, false),
|
||||
},
|
||||
{
|
||||
testName: "Feature gate enabled and both xns DataSourceRef and DataSource specified",
|
||||
expectedFail: true,
|
||||
claimSpec: pvcSpecWithCrossNamespaceSource(&snapAPIGroup, snapKind, &goodNS, goodName, true),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.AnyVolumeDataSource, true)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CrossNamespaceVolumeDataSource, true)()
|
||||
opts := PersistentVolumeClaimSpecValidationOptions{}
|
||||
if tc.expectedFail {
|
||||
if errs := ValidatePersistentVolumeClaimSpec(tc.claimSpec, field.NewPath("spec"), opts); len(errs) == 0 {
|
||||
t.Errorf("%s: expected failure: %v", tc.testName, errs)
|
||||
}
|
||||
} else {
|
||||
if errs := ValidatePersistentVolumeClaimSpec(tc.claimSpec, field.NewPath("spec"), opts); len(errs) != 0 {
|
||||
t.Errorf("%s: expected success: %v", tc.testName, errs)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateTopologySpreadConstraints(t *testing.T) {
|
||||
fieldPath := field.NewPath("field")
|
||||
subFldPath0 := fieldPath.Index(0)
|
||||
|
28
pkg/apis/core/zz_generated.deepcopy.go
generated
28
pkg/apis/core/zz_generated.deepcopy.go
generated
@ -2965,7 +2965,7 @@ func (in *PersistentVolumeClaimSpec) DeepCopyInto(out *PersistentVolumeClaimSpec
|
||||
}
|
||||
if in.DataSourceRef != nil {
|
||||
in, out := &in.DataSourceRef, &out.DataSourceRef
|
||||
*out = new(TypedLocalObjectReference)
|
||||
*out = new(TypedObjectReference)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
@ -5714,6 +5714,32 @@ func (in *TypedLocalObjectReference) DeepCopy() *TypedLocalObjectReference {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TypedObjectReference) DeepCopyInto(out *TypedObjectReference) {
|
||||
*out = *in
|
||||
if in.APIGroup != nil {
|
||||
in, out := &in.APIGroup, &out.APIGroup
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.Namespace != nil {
|
||||
in, out := &in.Namespace, &out.Namespace
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TypedObjectReference.
|
||||
func (in *TypedObjectReference) DeepCopy() *TypedObjectReference {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TypedObjectReference)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Volume) DeepCopyInto(out *Volume) {
|
||||
*out = *in
|
||||
|
@ -36,6 +36,13 @@ const (
|
||||
// of code conflicts because changes are more likely to be scattered
|
||||
// across the file.
|
||||
|
||||
// owner: @ttakahashi21 @mkimuram
|
||||
// kep: https://kep.k8s.io/3294
|
||||
// alpha: v1.26
|
||||
//
|
||||
// Enable usage of Provision of PVCs from snapshots in other namespaces
|
||||
CrossNamespaceVolumeDataSource featuregate.Feature = "CrossNamespaceVolumeDataSource"
|
||||
|
||||
// owner: @bswartz
|
||||
// alpha: v1.18
|
||||
// beta: v1.24
|
||||
@ -893,6 +900,8 @@ func init() {
|
||||
// Entries are separated from each other with blank lines to avoid sweeping gofmt changes
|
||||
// when adding or removing one entry.
|
||||
var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{
|
||||
CrossNamespaceVolumeDataSource: {Default: false, PreRelease: featuregate.Alpha},
|
||||
|
||||
AnyVolumeDataSource: {Default: true, PreRelease: featuregate.Beta}, // on by default in 1.24
|
||||
|
||||
APISelfSubjectReview: {Default: false, PreRelease: featuregate.Alpha},
|
||||
|
52
pkg/generated/openapi/zz_generated.openapi.go
generated
52
pkg/generated/openapi/zz_generated.openapi.go
generated
@ -526,6 +526,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
|
||||
"k8s.io/api/core/v1.TopologySelectorTerm": schema_k8sio_api_core_v1_TopologySelectorTerm(ref),
|
||||
"k8s.io/api/core/v1.TopologySpreadConstraint": schema_k8sio_api_core_v1_TopologySpreadConstraint(ref),
|
||||
"k8s.io/api/core/v1.TypedLocalObjectReference": schema_k8sio_api_core_v1_TypedLocalObjectReference(ref),
|
||||
"k8s.io/api/core/v1.TypedObjectReference": schema_k8sio_api_core_v1_TypedObjectReference(ref),
|
||||
"k8s.io/api/core/v1.Volume": schema_k8sio_api_core_v1_Volume(ref),
|
||||
"k8s.io/api/core/v1.VolumeDevice": schema_k8sio_api_core_v1_VolumeDevice(ref),
|
||||
"k8s.io/api/core/v1.VolumeMount": schema_k8sio_api_core_v1_VolumeMount(ref),
|
||||
@ -21490,21 +21491,21 @@ func schema_k8sio_api_core_v1_PersistentVolumeClaimSpec(ref common.ReferenceCall
|
||||
},
|
||||
"dataSource": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field.",
|
||||
Description: "dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. If the namespace is specified, then dataSourceRef will not be copied to dataSource.",
|
||||
Ref: ref("k8s.io/api/core/v1.TypedLocalObjectReference"),
|
||||
},
|
||||
},
|
||||
"dataSourceRef": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. There are two important differences between DataSource and DataSourceRef: * While DataSource only allows two specific types of objects, DataSourceRef\n allows any non-core object, as well as PersistentVolumeClaim objects.\n* While DataSource ignores disallowed values (dropping them), DataSourceRef\n preserves all values, and generates an error if a disallowed value is\n specified.\n(Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled.",
|
||||
Ref: ref("k8s.io/api/core/v1.TypedLocalObjectReference"),
|
||||
Description: "dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, when namespace isn't specified in dataSourceRef, both fields (dataSource and dataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. When namespace is specified in dataSourceRef, dataSource isn't set to the same value and must be empty. There are three important differences between dataSource and dataSourceRef: * While dataSource only allows two specific types of objects, dataSourceRef\n allows any non-core object, as well as PersistentVolumeClaim objects.\n* While dataSource ignores disallowed values (dropping them), dataSourceRef\n preserves all values, and generates an error if a disallowed value is\n specified.\n* While dataSource only allows local objects, dataSourceRef allows objects\n in any namespaces.\n(Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.",
|
||||
Ref: ref("k8s.io/api/core/v1.TypedObjectReference"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"k8s.io/api/core/v1.ResourceRequirements", "k8s.io/api/core/v1.TypedLocalObjectReference", "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"},
|
||||
"k8s.io/api/core/v1.ResourceRequirements", "k8s.io/api/core/v1.TypedLocalObjectReference", "k8s.io/api/core/v1.TypedObjectReference", "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"},
|
||||
}
|
||||
}
|
||||
|
||||
@ -26813,6 +26814,49 @@ func schema_k8sio_api_core_v1_TypedLocalObjectReference(ref common.ReferenceCall
|
||||
}
|
||||
}
|
||||
|
||||
func schema_k8sio_api_core_v1_TypedObjectReference(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"apiGroup": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"kind": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Kind is the type of resource being referenced",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"name": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Name is the name of resource being referenced",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
"namespace": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled.",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"kind", "name"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_k8sio_api_core_v1_Volume(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
|
@ -216,11 +216,14 @@ func TestDefaultOnReadPvc(t *testing.T) {
|
||||
storage, _, server := newStorage(t)
|
||||
defer server.Terminate(t)
|
||||
defer storage.Store.DestroyFunc()
|
||||
|
||||
dataSource := api.TypedLocalObjectReference{
|
||||
Kind: "PersistentVolumeClaim",
|
||||
Name: "my-pvc",
|
||||
}
|
||||
dataSourceRef := api.TypedObjectReference{
|
||||
Kind: "PersistentVolumeClaim",
|
||||
Name: "my-pvc",
|
||||
}
|
||||
|
||||
var tests = map[string]struct {
|
||||
anyEnabled bool
|
||||
@ -278,15 +281,15 @@ func TestDefaultOnReadPvc(t *testing.T) {
|
||||
pvc.Spec.DataSource = dataSource.DeepCopy()
|
||||
}
|
||||
if test.dataSourceRef {
|
||||
pvc.Spec.DataSourceRef = dataSource.DeepCopy()
|
||||
pvc.Spec.DataSourceRef = dataSourceRef.DeepCopy()
|
||||
}
|
||||
var expectDataSource *api.TypedLocalObjectReference
|
||||
if test.want {
|
||||
expectDataSource = &dataSource
|
||||
}
|
||||
var expectDataSourceRef *api.TypedLocalObjectReference
|
||||
var expectDataSourceRef *api.TypedObjectReference
|
||||
if test.wantRef {
|
||||
expectDataSourceRef = &dataSource
|
||||
expectDataSourceRef = &dataSourceRef
|
||||
}
|
||||
|
||||
// Method under test
|
||||
|
@ -65,7 +65,7 @@ func (persistentvolumeclaimStrategy) GetResetFields() map[fieldpath.APIVersion]*
|
||||
func (persistentvolumeclaimStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
|
||||
pvc := obj.(*api.PersistentVolumeClaim)
|
||||
pvc.Status = api.PersistentVolumeClaimStatus{}
|
||||
pvcutil.DropDisabledFields(&pvc.Spec)
|
||||
pvcutil.DropDisabledFields(&pvc.Spec, nil)
|
||||
|
||||
// For data sources, we need to do 2 things to implement KEP 1495
|
||||
|
||||
@ -103,7 +103,7 @@ func (persistentvolumeclaimStrategy) PrepareForUpdate(ctx context.Context, obj,
|
||||
oldPvc := old.(*api.PersistentVolumeClaim)
|
||||
newPvc.Status = oldPvc.Status
|
||||
|
||||
pvcutil.DropDisabledFields(&newPvc.Spec)
|
||||
pvcutil.DropDisabledFields(&newPvc.Spec, &oldPvc.Spec)
|
||||
|
||||
// We need to use similar logic to PrepareForCreate here both to preserve backwards
|
||||
// compatibility with the old behavior (ignoring of garbage dataSources at both create
|
||||
|
@ -107,28 +107,58 @@ func TestDropConditions(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
var (
|
||||
coreGroup = ""
|
||||
snapGroup = "snapshot.storage.k8s.io"
|
||||
genericGroup = "generic.storage.k8s.io"
|
||||
pvcKind = "PersistentVolumeClaim"
|
||||
snapKind = "VolumeSnapshot"
|
||||
genericKind = "Generic"
|
||||
podKind = "Pod"
|
||||
)
|
||||
|
||||
func makeDataSource(apiGroup, kind, name string) *api.TypedLocalObjectReference {
|
||||
return &api.TypedLocalObjectReference{
|
||||
APIGroup: &apiGroup,
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func makeDataSourceRef(apiGroup, kind, name string, namespace *string) *api.TypedObjectReference {
|
||||
return &api.TypedObjectReference{
|
||||
APIGroup: &apiGroup,
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
Namespace: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrepareForCreate(t *testing.T) {
|
||||
ctx := genericapirequest.NewDefaultContext()
|
||||
|
||||
makeDataSource := func(apiGroup, kind, name string) *api.TypedLocalObjectReference {
|
||||
return &api.TypedLocalObjectReference{
|
||||
APIGroup: &apiGroup,
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
}
|
||||
}
|
||||
|
||||
volumeDataSource := makeDataSource("", "PersistentVolumeClaim", "my-vol")
|
||||
snapshotDataSource := makeDataSource("snapshot.storage.k8s.io", "VolumeSnapshot", "my-snap")
|
||||
genericDataSource := makeDataSource("generic.storage.k8s.io", "Generic", "my-foo")
|
||||
coreDataSource := makeDataSource("", "Pod", "my-pod")
|
||||
ns := "ns1"
|
||||
volumeDataSource := makeDataSource(coreGroup, pvcKind, "my-vol")
|
||||
volumeDataSourceRef := makeDataSourceRef(coreGroup, pvcKind, "my-vol", nil)
|
||||
xnsVolumeDataSourceRef := makeDataSourceRef(coreGroup, pvcKind, "my-vol", &ns)
|
||||
snapshotDataSource := makeDataSource(snapGroup, snapKind, "my-snap")
|
||||
snapshotDataSourceRef := makeDataSourceRef(snapGroup, snapKind, "my-snap", nil)
|
||||
xnsSnapshotDataSourceRef := makeDataSourceRef(snapGroup, snapKind, "my-snap", &ns)
|
||||
genericDataSource := makeDataSource(genericGroup, genericKind, "my-foo")
|
||||
genericDataSourceRef := makeDataSourceRef(genericGroup, genericKind, "my-foo", nil)
|
||||
xnsGenericDataSourceRef := makeDataSourceRef(genericGroup, genericKind, "my-foo", &ns)
|
||||
coreDataSource := makeDataSource(coreGroup, podKind, "my-pod")
|
||||
coreDataSourceRef := makeDataSourceRef(coreGroup, podKind, "my-pod", nil)
|
||||
xnsCoreDataSourceRef := makeDataSourceRef(coreGroup, podKind, "my-pod", &ns)
|
||||
|
||||
var tests = map[string]struct {
|
||||
anyEnabled bool
|
||||
xnsEnabled bool
|
||||
dataSource *api.TypedLocalObjectReference
|
||||
dataSourceRef *api.TypedLocalObjectReference
|
||||
dataSourceRef *api.TypedObjectReference
|
||||
want *api.TypedLocalObjectReference
|
||||
wantRef *api.TypedLocalObjectReference
|
||||
wantRef *api.TypedObjectReference
|
||||
}{
|
||||
"any disabled with empty ds": {
|
||||
want: nil,
|
||||
@ -150,16 +180,16 @@ func TestPrepareForCreate(t *testing.T) {
|
||||
want: nil,
|
||||
},
|
||||
"any disabled with volume ds ref": {
|
||||
dataSourceRef: volumeDataSource,
|
||||
dataSourceRef: volumeDataSourceRef,
|
||||
},
|
||||
"any disabled with snapshot ds ref": {
|
||||
dataSourceRef: snapshotDataSource,
|
||||
dataSourceRef: snapshotDataSourceRef,
|
||||
},
|
||||
"any disabled with generic ds ref": {
|
||||
dataSourceRef: genericDataSource,
|
||||
dataSourceRef: genericDataSourceRef,
|
||||
},
|
||||
"any disabled with invalid ds ref": {
|
||||
dataSourceRef: coreDataSource,
|
||||
dataSourceRef: coreDataSourceRef,
|
||||
},
|
||||
"any enabled with empty ds": {
|
||||
anyEnabled: true,
|
||||
@ -169,13 +199,13 @@ func TestPrepareForCreate(t *testing.T) {
|
||||
dataSource: volumeDataSource,
|
||||
anyEnabled: true,
|
||||
want: volumeDataSource,
|
||||
wantRef: volumeDataSource,
|
||||
wantRef: volumeDataSourceRef,
|
||||
},
|
||||
"any enabled with snapshot ds": {
|
||||
dataSource: snapshotDataSource,
|
||||
anyEnabled: true,
|
||||
want: snapshotDataSource,
|
||||
wantRef: snapshotDataSource,
|
||||
wantRef: snapshotDataSourceRef,
|
||||
},
|
||||
"any enabled with generic ds": {
|
||||
dataSource: genericDataSource,
|
||||
@ -186,41 +216,135 @@ func TestPrepareForCreate(t *testing.T) {
|
||||
anyEnabled: true,
|
||||
},
|
||||
"any enabled with volume ds ref": {
|
||||
dataSourceRef: volumeDataSource,
|
||||
dataSourceRef: volumeDataSourceRef,
|
||||
anyEnabled: true,
|
||||
want: volumeDataSource,
|
||||
wantRef: volumeDataSource,
|
||||
wantRef: volumeDataSourceRef,
|
||||
},
|
||||
"any enabled with snapshot ds ref": {
|
||||
dataSourceRef: snapshotDataSource,
|
||||
dataSourceRef: snapshotDataSourceRef,
|
||||
anyEnabled: true,
|
||||
want: snapshotDataSource,
|
||||
wantRef: snapshotDataSource,
|
||||
wantRef: snapshotDataSourceRef,
|
||||
},
|
||||
"any enabled with generic ds ref": {
|
||||
dataSourceRef: genericDataSource,
|
||||
dataSourceRef: genericDataSourceRef,
|
||||
anyEnabled: true,
|
||||
want: genericDataSource,
|
||||
wantRef: genericDataSource,
|
||||
wantRef: genericDataSourceRef,
|
||||
},
|
||||
"any enabled with invalid ds ref": {
|
||||
dataSourceRef: coreDataSource,
|
||||
dataSourceRef: coreDataSourceRef,
|
||||
anyEnabled: true,
|
||||
want: coreDataSource,
|
||||
wantRef: coreDataSource,
|
||||
wantRef: coreDataSourceRef,
|
||||
},
|
||||
"any enabled with mismatched data sources": {
|
||||
dataSource: volumeDataSource,
|
||||
dataSourceRef: snapshotDataSource,
|
||||
dataSourceRef: snapshotDataSourceRef,
|
||||
anyEnabled: true,
|
||||
want: volumeDataSource,
|
||||
wantRef: snapshotDataSource,
|
||||
wantRef: snapshotDataSourceRef,
|
||||
},
|
||||
"both any and xns enabled with empty ds": {
|
||||
anyEnabled: true,
|
||||
xnsEnabled: true,
|
||||
want: nil,
|
||||
},
|
||||
"both any and xns enabled with volume ds": {
|
||||
dataSource: volumeDataSource,
|
||||
anyEnabled: true,
|
||||
xnsEnabled: true,
|
||||
want: volumeDataSource,
|
||||
wantRef: volumeDataSourceRef,
|
||||
},
|
||||
"both any and xns enabled with snapshot ds": {
|
||||
dataSource: snapshotDataSource,
|
||||
anyEnabled: true,
|
||||
xnsEnabled: true,
|
||||
want: snapshotDataSource,
|
||||
wantRef: snapshotDataSourceRef,
|
||||
},
|
||||
"both any and xns enabled with generic ds": {
|
||||
dataSource: genericDataSource,
|
||||
anyEnabled: true,
|
||||
xnsEnabled: true,
|
||||
},
|
||||
"both any and xns enabled with invalid ds": {
|
||||
dataSource: coreDataSource,
|
||||
anyEnabled: true,
|
||||
xnsEnabled: true,
|
||||
},
|
||||
"both any and xns enabled with volume ds ref": {
|
||||
dataSourceRef: volumeDataSourceRef,
|
||||
anyEnabled: true,
|
||||
xnsEnabled: true,
|
||||
want: volumeDataSource,
|
||||
wantRef: volumeDataSourceRef,
|
||||
},
|
||||
"both any and xns enabled with snapshot ds ref": {
|
||||
dataSourceRef: snapshotDataSourceRef,
|
||||
anyEnabled: true,
|
||||
xnsEnabled: true,
|
||||
want: snapshotDataSource,
|
||||
wantRef: snapshotDataSourceRef,
|
||||
},
|
||||
"both any and xns enabled with generic ds ref": {
|
||||
dataSourceRef: genericDataSourceRef,
|
||||
anyEnabled: true,
|
||||
xnsEnabled: true,
|
||||
want: genericDataSource,
|
||||
wantRef: genericDataSourceRef,
|
||||
},
|
||||
"both any and xns enabled with invalid ds ref": {
|
||||
dataSourceRef: coreDataSourceRef,
|
||||
anyEnabled: true,
|
||||
xnsEnabled: true,
|
||||
want: coreDataSource,
|
||||
wantRef: coreDataSourceRef,
|
||||
},
|
||||
"both any and xns enabled with mismatched data sources": {
|
||||
dataSource: volumeDataSource,
|
||||
dataSourceRef: snapshotDataSourceRef,
|
||||
anyEnabled: true,
|
||||
xnsEnabled: true,
|
||||
want: volumeDataSource,
|
||||
wantRef: snapshotDataSourceRef,
|
||||
},
|
||||
"both any and xns enabled with volume xns ds ref": {
|
||||
dataSourceRef: xnsVolumeDataSourceRef,
|
||||
anyEnabled: true,
|
||||
xnsEnabled: true,
|
||||
wantRef: xnsVolumeDataSourceRef,
|
||||
},
|
||||
"both any and xns enabled with snapshot xns ds ref": {
|
||||
dataSourceRef: xnsSnapshotDataSourceRef,
|
||||
anyEnabled: true,
|
||||
xnsEnabled: true,
|
||||
wantRef: xnsSnapshotDataSourceRef,
|
||||
},
|
||||
"both any and xns enabled with generic xns ds ref": {
|
||||
dataSourceRef: xnsGenericDataSourceRef,
|
||||
anyEnabled: true,
|
||||
xnsEnabled: true,
|
||||
wantRef: xnsGenericDataSourceRef,
|
||||
},
|
||||
"both any and xns enabled with invalid xns ds ref": {
|
||||
dataSourceRef: xnsCoreDataSourceRef,
|
||||
anyEnabled: true,
|
||||
xnsEnabled: true,
|
||||
wantRef: xnsCoreDataSourceRef,
|
||||
},
|
||||
"only xns enabled with snapshot xns ds ref": {
|
||||
dataSourceRef: xnsSnapshotDataSourceRef,
|
||||
xnsEnabled: true,
|
||||
},
|
||||
}
|
||||
|
||||
for testName, test := range tests {
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.AnyVolumeDataSource, test.anyEnabled)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CrossNamespaceVolumeDataSource, test.xnsEnabled)()
|
||||
pvc := api.PersistentVolumeClaim{
|
||||
Spec: api.PersistentVolumeClaimSpec{
|
||||
DataSource: test.dataSource,
|
||||
|
2118
staging/src/k8s.io/api/core/v1/generated.pb.go
generated
2118
staging/src/k8s.io/api/core/v1/generated.pb.go
generated
File diff suppressed because it is too large
Load Diff
@ -2711,30 +2711,37 @@ message PersistentVolumeClaimSpec {
|
||||
// * An existing PVC (PersistentVolumeClaim)
|
||||
// If the provisioner or an external controller can support the specified data source,
|
||||
// it will create a new volume based on the contents of the specified data source.
|
||||
// If the AnyVolumeDataSource feature gate is enabled, this field will always have
|
||||
// the same contents as the DataSourceRef field.
|
||||
// When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef,
|
||||
// and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified.
|
||||
// If the namespace is specified, then dataSourceRef will not be copied to dataSource.
|
||||
// +optional
|
||||
optional TypedLocalObjectReference dataSource = 7;
|
||||
|
||||
// dataSourceRef specifies the object from which to populate the volume with data, if a non-empty
|
||||
// volume is desired. This may be any local object from a non-empty API group (non
|
||||
// volume is desired. This may be any object from a non-empty API group (non
|
||||
// core object) or a PersistentVolumeClaim object.
|
||||
// When this field is specified, volume binding will only succeed if the type of
|
||||
// the specified object matches some installed volume populator or dynamic
|
||||
// provisioner.
|
||||
// This field will replace the functionality of the DataSource field and as such
|
||||
// This field will replace the functionality of the dataSource field and as such
|
||||
// if both fields are non-empty, they must have the same value. For backwards
|
||||
// compatibility, both fields (DataSource and DataSourceRef) will be set to the same
|
||||
// compatibility, when namespace isn't specified in dataSourceRef,
|
||||
// both fields (dataSource and dataSourceRef) will be set to the same
|
||||
// value automatically if one of them is empty and the other is non-empty.
|
||||
// There are two important differences between DataSource and DataSourceRef:
|
||||
// * While DataSource only allows two specific types of objects, DataSourceRef
|
||||
// When namespace is specified in dataSourceRef,
|
||||
// dataSource isn't set to the same value and must be empty.
|
||||
// There are three important differences between dataSource and dataSourceRef:
|
||||
// * While dataSource only allows two specific types of objects, dataSourceRef
|
||||
// allows any non-core object, as well as PersistentVolumeClaim objects.
|
||||
// * While DataSource ignores disallowed values (dropping them), DataSourceRef
|
||||
// * While dataSource ignores disallowed values (dropping them), dataSourceRef
|
||||
// preserves all values, and generates an error if a disallowed value is
|
||||
// specified.
|
||||
// * While dataSource only allows local objects, dataSourceRef allows objects
|
||||
// in any namespaces.
|
||||
// (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled.
|
||||
// (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.
|
||||
// +optional
|
||||
optional TypedLocalObjectReference dataSourceRef = 8;
|
||||
optional TypedObjectReference dataSourceRef = 8;
|
||||
}
|
||||
|
||||
// PersistentVolumeClaimStatus is the current status of a persistent volume claim.
|
||||
@ -5563,6 +5570,27 @@ message TypedLocalObjectReference {
|
||||
optional string name = 3;
|
||||
}
|
||||
|
||||
message TypedObjectReference {
|
||||
// APIGroup is the group for the resource being referenced.
|
||||
// If APIGroup is not specified, the specified Kind must be in the core API group.
|
||||
// For any other third-party types, APIGroup is required.
|
||||
// +optional
|
||||
optional string apiGroup = 1;
|
||||
|
||||
// Kind is the type of resource being referenced
|
||||
optional string kind = 2;
|
||||
|
||||
// Name is the name of resource being referenced
|
||||
optional string name = 3;
|
||||
|
||||
// Namespace is the namespace of resource being referenced
|
||||
// Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details.
|
||||
// (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled.
|
||||
// +featureGate=CrossNamespaceVolumeDataSource
|
||||
// +optional
|
||||
optional string namespace = 4;
|
||||
}
|
||||
|
||||
// Volume represents a named volume in a pod that may be accessed by any container in the pod.
|
||||
message Volume {
|
||||
// name of the volume.
|
||||
|
@ -497,29 +497,54 @@ type PersistentVolumeClaimSpec struct {
|
||||
// * An existing PVC (PersistentVolumeClaim)
|
||||
// If the provisioner or an external controller can support the specified data source,
|
||||
// it will create a new volume based on the contents of the specified data source.
|
||||
// If the AnyVolumeDataSource feature gate is enabled, this field will always have
|
||||
// the same contents as the DataSourceRef field.
|
||||
// When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef,
|
||||
// and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified.
|
||||
// If the namespace is specified, then dataSourceRef will not be copied to dataSource.
|
||||
// +optional
|
||||
DataSource *TypedLocalObjectReference `json:"dataSource,omitempty" protobuf:"bytes,7,opt,name=dataSource"`
|
||||
// dataSourceRef specifies the object from which to populate the volume with data, if a non-empty
|
||||
// volume is desired. This may be any local object from a non-empty API group (non
|
||||
// volume is desired. This may be any object from a non-empty API group (non
|
||||
// core object) or a PersistentVolumeClaim object.
|
||||
// When this field is specified, volume binding will only succeed if the type of
|
||||
// the specified object matches some installed volume populator or dynamic
|
||||
// provisioner.
|
||||
// This field will replace the functionality of the DataSource field and as such
|
||||
// This field will replace the functionality of the dataSource field and as such
|
||||
// if both fields are non-empty, they must have the same value. For backwards
|
||||
// compatibility, both fields (DataSource and DataSourceRef) will be set to the same
|
||||
// compatibility, when namespace isn't specified in dataSourceRef,
|
||||
// both fields (dataSource and dataSourceRef) will be set to the same
|
||||
// value automatically if one of them is empty and the other is non-empty.
|
||||
// There are two important differences between DataSource and DataSourceRef:
|
||||
// * While DataSource only allows two specific types of objects, DataSourceRef
|
||||
// When namespace is specified in dataSourceRef,
|
||||
// dataSource isn't set to the same value and must be empty.
|
||||
// There are three important differences between dataSource and dataSourceRef:
|
||||
// * While dataSource only allows two specific types of objects, dataSourceRef
|
||||
// allows any non-core object, as well as PersistentVolumeClaim objects.
|
||||
// * While DataSource ignores disallowed values (dropping them), DataSourceRef
|
||||
// * While dataSource ignores disallowed values (dropping them), dataSourceRef
|
||||
// preserves all values, and generates an error if a disallowed value is
|
||||
// specified.
|
||||
// * While dataSource only allows local objects, dataSourceRef allows objects
|
||||
// in any namespaces.
|
||||
// (Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled.
|
||||
// (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.
|
||||
// +optional
|
||||
DataSourceRef *TypedLocalObjectReference `json:"dataSourceRef,omitempty" protobuf:"bytes,8,opt,name=dataSourceRef"`
|
||||
DataSourceRef *TypedObjectReference `json:"dataSourceRef,omitempty" protobuf:"bytes,8,opt,name=dataSourceRef"`
|
||||
}
|
||||
|
||||
type TypedObjectReference struct {
|
||||
// APIGroup is the group for the resource being referenced.
|
||||
// If APIGroup is not specified, the specified Kind must be in the core API group.
|
||||
// For any other third-party types, APIGroup is required.
|
||||
// +optional
|
||||
APIGroup *string `json:"apiGroup" protobuf:"bytes,1,opt,name=apiGroup"`
|
||||
// Kind is the type of resource being referenced
|
||||
Kind string `json:"kind" protobuf:"bytes,2,opt,name=kind"`
|
||||
// Name is the name of resource being referenced
|
||||
Name string `json:"name" protobuf:"bytes,3,opt,name=name"`
|
||||
// Namespace is the namespace of resource being referenced
|
||||
// Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details.
|
||||
// (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled.
|
||||
// +featureGate=CrossNamespaceVolumeDataSource
|
||||
// +optional
|
||||
Namespace *string `json:"namespace,omitempty" protobuf:"bytes,4,opt,name=namespace"`
|
||||
}
|
||||
|
||||
// PersistentVolumeClaimConditionType is a valid value of PersistentVolumeClaimCondition.Type
|
||||
|
@ -1311,8 +1311,8 @@ var map_PersistentVolumeClaimSpec = map[string]string{
|
||||
"volumeName": "volumeName is the binding reference to the PersistentVolume backing this claim.",
|
||||
"storageClassName": "storageClassName is the name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1",
|
||||
"volumeMode": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec.",
|
||||
"dataSource": "dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. If the AnyVolumeDataSource feature gate is enabled, this field will always have the same contents as the DataSourceRef field.",
|
||||
"dataSourceRef": "dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any local object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the DataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, both fields (DataSource and DataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. There are two important differences between DataSource and DataSourceRef: * While DataSource only allows two specific types of objects, DataSourceRef\n allows any non-core object, as well as PersistentVolumeClaim objects.\n* While DataSource ignores disallowed values (dropping them), DataSourceRef\n preserves all values, and generates an error if a disallowed value is\n specified.\n(Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled.",
|
||||
"dataSource": "dataSource field can be used to specify either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) * An existing PVC (PersistentVolumeClaim) If the provisioner or an external controller can support the specified data source, it will create a new volume based on the contents of the specified data source. When the AnyVolumeDataSource feature gate is enabled, dataSource contents will be copied to dataSourceRef, and dataSourceRef contents will be copied to dataSource when dataSourceRef.namespace is not specified. If the namespace is specified, then dataSourceRef will not be copied to dataSource.",
|
||||
"dataSourceRef": "dataSourceRef specifies the object from which to populate the volume with data, if a non-empty volume is desired. This may be any object from a non-empty API group (non core object) or a PersistentVolumeClaim object. When this field is specified, volume binding will only succeed if the type of the specified object matches some installed volume populator or dynamic provisioner. This field will replace the functionality of the dataSource field and as such if both fields are non-empty, they must have the same value. For backwards compatibility, when namespace isn't specified in dataSourceRef, both fields (dataSource and dataSourceRef) will be set to the same value automatically if one of them is empty and the other is non-empty. When namespace is specified in dataSourceRef, dataSource isn't set to the same value and must be empty. There are three important differences between dataSource and dataSourceRef: * While dataSource only allows two specific types of objects, dataSourceRef\n allows any non-core object, as well as PersistentVolumeClaim objects.\n* While dataSource ignores disallowed values (dropping them), dataSourceRef\n preserves all values, and generates an error if a disallowed value is\n specified.\n* While dataSource only allows local objects, dataSourceRef allows objects\n in any namespaces.\n(Beta) Using this field requires the AnyVolumeDataSource feature gate to be enabled. (Alpha) Using the namespace field of dataSourceRef requires the CrossNamespaceVolumeDataSource feature gate to be enabled.",
|
||||
}
|
||||
|
||||
func (PersistentVolumeClaimSpec) SwaggerDoc() map[string]string {
|
||||
@ -2437,6 +2437,17 @@ func (TypedLocalObjectReference) SwaggerDoc() map[string]string {
|
||||
return map_TypedLocalObjectReference
|
||||
}
|
||||
|
||||
var map_TypedObjectReference = map[string]string{
|
||||
"apiGroup": "APIGroup is the group for the resource being referenced. If APIGroup is not specified, the specified Kind must be in the core API group. For any other third-party types, APIGroup is required.",
|
||||
"kind": "Kind is the type of resource being referenced",
|
||||
"name": "Name is the name of resource being referenced",
|
||||
"namespace": "Namespace is the namespace of resource being referenced Note that when a namespace is specified, a gateway.networking.k8s.io/ReferenceGrant object is required in the referent namespace to allow that namespace's owner to accept the reference. See the ReferenceGrant documentation for details. (Alpha) This field requires the CrossNamespaceVolumeDataSource feature gate to be enabled.",
|
||||
}
|
||||
|
||||
func (TypedObjectReference) SwaggerDoc() map[string]string {
|
||||
return map_TypedObjectReference
|
||||
}
|
||||
|
||||
var map_Volume = map[string]string{
|
||||
"": "Volume represents a named volume in a pod that may be accessed by any container in the pod.",
|
||||
"name": "name of the volume. Must be a DNS_LABEL and unique within the pod. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
|
||||
|
@ -2963,7 +2963,7 @@ func (in *PersistentVolumeClaimSpec) DeepCopyInto(out *PersistentVolumeClaimSpec
|
||||
}
|
||||
if in.DataSourceRef != nil {
|
||||
in, out := &in.DataSourceRef, &out.DataSourceRef
|
||||
*out = new(TypedLocalObjectReference)
|
||||
*out = new(TypedObjectReference)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
@ -5729,6 +5729,32 @@ func (in *TypedLocalObjectReference) DeepCopy() *TypedLocalObjectReference {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TypedObjectReference) DeepCopyInto(out *TypedObjectReference) {
|
||||
*out = *in
|
||||
if in.APIGroup != nil {
|
||||
in, out := &in.APIGroup, &out.APIGroup
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.Namespace != nil {
|
||||
in, out := &in.Namespace, &out.Namespace
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TypedObjectReference.
|
||||
func (in *TypedObjectReference) DeepCopy() *TypedObjectReference {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TypedObjectReference)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Volume) DeepCopyInto(out *Volume) {
|
||||
*out = *in
|
||||
|
@ -465,7 +465,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -965,6 +965,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -466,7 +466,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -973,6 +973,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -467,7 +467,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -965,6 +965,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -466,7 +466,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1716,7 +1717,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
|
Binary file not shown.
@ -973,6 +973,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
@ -1184,6 +1185,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -466,7 +466,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -975,6 +975,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -466,7 +466,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1716,7 +1717,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
|
Binary file not shown.
@ -973,6 +973,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
@ -1184,6 +1185,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -465,7 +465,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -965,6 +965,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -466,7 +466,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -973,6 +973,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -467,7 +467,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -965,6 +965,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -466,7 +466,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1716,7 +1717,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
|
Binary file not shown.
@ -973,6 +973,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
@ -1184,6 +1185,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -539,7 +539,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -1017,6 +1017,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -490,7 +490,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
BIN
staging/src/k8s.io/api/testdata/HEAD/batch.v1.Job.pb
vendored
BIN
staging/src/k8s.io/api/testdata/HEAD/batch.v1.Job.pb
vendored
Binary file not shown.
@ -981,6 +981,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -539,7 +539,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -1017,6 +1017,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -533,7 +533,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -1014,6 +1014,7 @@ template:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -80,7 +80,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
|
Binary file not shown.
@ -43,6 +43,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -407,7 +407,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
BIN
staging/src/k8s.io/api/testdata/HEAD/core.v1.Pod.pb
vendored
BIN
staging/src/k8s.io/api/testdata/HEAD/core.v1.Pod.pb
vendored
Binary file not shown.
@ -921,6 +921,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -450,7 +450,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -954,6 +954,7 @@ template:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -456,7 +456,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -959,6 +959,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -465,7 +465,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -965,6 +965,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -466,7 +466,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -975,6 +975,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -467,7 +467,8 @@
|
||||
"dataSourceRef": {
|
||||
"apiGroup": "apiGroupValue",
|
||||
"kind": "kindValue",
|
||||
"name": "nameValue"
|
||||
"name": "nameValue",
|
||||
"namespace": "namespaceValue"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
@ -965,6 +965,7 @@ spec:
|
||||
apiGroup: apiGroupValue
|
||||
kind: kindValue
|
||||
name: nameValue
|
||||
namespace: namespaceValue
|
||||
resources:
|
||||
limits:
|
||||
limitsKey: "0"
|
||||
|
@ -33,7 +33,7 @@ type PersistentVolumeClaimSpecApplyConfiguration struct {
|
||||
StorageClassName *string `json:"storageClassName,omitempty"`
|
||||
VolumeMode *v1.PersistentVolumeMode `json:"volumeMode,omitempty"`
|
||||
DataSource *TypedLocalObjectReferenceApplyConfiguration `json:"dataSource,omitempty"`
|
||||
DataSourceRef *TypedLocalObjectReferenceApplyConfiguration `json:"dataSourceRef,omitempty"`
|
||||
DataSourceRef *TypedObjectReferenceApplyConfiguration `json:"dataSourceRef,omitempty"`
|
||||
}
|
||||
|
||||
// PersistentVolumeClaimSpecApplyConfiguration constructs an declarative configuration of the PersistentVolumeClaimSpec type for use with
|
||||
@ -103,7 +103,7 @@ func (b *PersistentVolumeClaimSpecApplyConfiguration) WithDataSource(value *Type
|
||||
// WithDataSourceRef sets the DataSourceRef field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the DataSourceRef field is set to the value of the last call.
|
||||
func (b *PersistentVolumeClaimSpecApplyConfiguration) WithDataSourceRef(value *TypedLocalObjectReferenceApplyConfiguration) *PersistentVolumeClaimSpecApplyConfiguration {
|
||||
func (b *PersistentVolumeClaimSpecApplyConfiguration) WithDataSourceRef(value *TypedObjectReferenceApplyConfiguration) *PersistentVolumeClaimSpecApplyConfiguration {
|
||||
b.DataSourceRef = value
|
||||
return b
|
||||
}
|
||||
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright The Kubernetes 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.
|
||||
*/
|
||||
|
||||
// Code generated by applyconfiguration-gen. DO NOT EDIT.
|
||||
|
||||
package v1
|
||||
|
||||
// TypedObjectReferenceApplyConfiguration represents an declarative configuration of the TypedObjectReference type for use
|
||||
// with apply.
|
||||
type TypedObjectReferenceApplyConfiguration struct {
|
||||
APIGroup *string `json:"apiGroup,omitempty"`
|
||||
Kind *string `json:"kind,omitempty"`
|
||||
Name *string `json:"name,omitempty"`
|
||||
Namespace *string `json:"namespace,omitempty"`
|
||||
}
|
||||
|
||||
// TypedObjectReferenceApplyConfiguration constructs an declarative configuration of the TypedObjectReference type for use with
|
||||
// apply.
|
||||
func TypedObjectReference() *TypedObjectReferenceApplyConfiguration {
|
||||
return &TypedObjectReferenceApplyConfiguration{}
|
||||
}
|
||||
|
||||
// WithAPIGroup sets the APIGroup field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the APIGroup field is set to the value of the last call.
|
||||
func (b *TypedObjectReferenceApplyConfiguration) WithAPIGroup(value string) *TypedObjectReferenceApplyConfiguration {
|
||||
b.APIGroup = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithKind sets the Kind field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Kind field is set to the value of the last call.
|
||||
func (b *TypedObjectReferenceApplyConfiguration) WithKind(value string) *TypedObjectReferenceApplyConfiguration {
|
||||
b.Kind = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithName sets the Name field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Name field is set to the value of the last call.
|
||||
func (b *TypedObjectReferenceApplyConfiguration) WithName(value string) *TypedObjectReferenceApplyConfiguration {
|
||||
b.Name = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithNamespace sets the Namespace field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the Namespace field is set to the value of the last call.
|
||||
func (b *TypedObjectReferenceApplyConfiguration) WithNamespace(value string) *TypedObjectReferenceApplyConfiguration {
|
||||
b.Namespace = &value
|
||||
return b
|
||||
}
|
@ -5544,7 +5544,7 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
namedType: io.k8s.api.core.v1.TypedLocalObjectReference
|
||||
- name: dataSourceRef
|
||||
type:
|
||||
namedType: io.k8s.api.core.v1.TypedLocalObjectReference
|
||||
namedType: io.k8s.api.core.v1.TypedObjectReference
|
||||
- name: resources
|
||||
type:
|
||||
namedType: io.k8s.api.core.v1.ResourceRequirements
|
||||
@ -7133,6 +7133,23 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
scalar: string
|
||||
default: ""
|
||||
elementRelationship: atomic
|
||||
- name: io.k8s.api.core.v1.TypedObjectReference
|
||||
map:
|
||||
fields:
|
||||
- name: apiGroup
|
||||
type:
|
||||
scalar: string
|
||||
- name: kind
|
||||
type:
|
||||
scalar: string
|
||||
default: ""
|
||||
- name: name
|
||||
type:
|
||||
scalar: string
|
||||
default: ""
|
||||
- name: namespace
|
||||
type:
|
||||
scalar: string
|
||||
- name: io.k8s.api.core.v1.Volume
|
||||
map:
|
||||
fields:
|
||||
|
@ -867,6 +867,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} {
|
||||
return &applyconfigurationscorev1.TopologySpreadConstraintApplyConfiguration{}
|
||||
case corev1.SchemeGroupVersion.WithKind("TypedLocalObjectReference"):
|
||||
return &applyconfigurationscorev1.TypedLocalObjectReferenceApplyConfiguration{}
|
||||
case corev1.SchemeGroupVersion.WithKind("TypedObjectReference"):
|
||||
return &applyconfigurationscorev1.TypedObjectReferenceApplyConfiguration{}
|
||||
case corev1.SchemeGroupVersion.WithKind("Volume"):
|
||||
return &applyconfigurationscorev1.VolumeApplyConfiguration{}
|
||||
case corev1.SchemeGroupVersion.WithKind("VolumeDevice"):
|
||||
|
@ -342,7 +342,7 @@ func (t *multiVolumeTestSuite) DefineTests(driver storageframework.TestDriver, p
|
||||
}
|
||||
testConfig := storageframework.ConvertTestConfig(l.config)
|
||||
dc := l.config.Framework.DynamicClient
|
||||
dataSource := prepareSnapshotDataSourceForProvisioning(ctx, f, testConfig, l.config, pattern, l.cs, dc, resource.Pvc, resource.Sc, sDriver, pattern.VolMode, expectedContent)
|
||||
dataSourceRef := prepareSnapshotDataSourceForProvisioning(ctx, f, testConfig, l.config, pattern, l.cs, dc, resource.Pvc, resource.Sc, sDriver, pattern.VolMode, expectedContent)
|
||||
|
||||
// Create 2nd PVC for testing
|
||||
pvc2 := &v1.PersistentVolumeClaim{
|
||||
@ -353,7 +353,7 @@ func (t *multiVolumeTestSuite) DefineTests(driver storageframework.TestDriver, p
|
||||
}
|
||||
resource.Pvc.Spec.DeepCopyInto(&pvc2.Spec)
|
||||
pvc2.Spec.VolumeName = ""
|
||||
pvc2.Spec.DataSource = dataSource
|
||||
pvc2.Spec.DataSourceRef = dataSourceRef
|
||||
|
||||
pvc2, err := l.cs.CoreV1().PersistentVolumeClaims(pvc2.Namespace).Create(context.TODO(), pvc2, metav1.CreateOptions{})
|
||||
framework.ExpectNoError(err)
|
||||
@ -386,7 +386,7 @@ func (t *multiVolumeTestSuite) DefineTests(driver storageframework.TestDriver, p
|
||||
l.resources = append(l.resources, resource)
|
||||
pvcs := []*v1.PersistentVolumeClaim{resource.Pvc}
|
||||
testConfig := storageframework.ConvertTestConfig(l.config)
|
||||
dataSource := preparePVCDataSourceForProvisioning(ctx, f, testConfig, l.cs, resource.Pvc, resource.Sc, pattern.VolMode, expectedContent)
|
||||
dataSourceRef := preparePVCDataSourceForProvisioning(ctx, f, testConfig, l.cs, resource.Pvc, resource.Sc, pattern.VolMode, expectedContent)
|
||||
|
||||
// Create 2nd PVC for testing
|
||||
pvc2 := &v1.PersistentVolumeClaim{
|
||||
@ -397,7 +397,7 @@ func (t *multiVolumeTestSuite) DefineTests(driver storageframework.TestDriver, p
|
||||
}
|
||||
resource.Pvc.Spec.DeepCopyInto(&pvc2.Spec)
|
||||
pvc2.Spec.VolumeName = ""
|
||||
pvc2.Spec.DataSource = dataSource
|
||||
pvc2.Spec.DataSourceRef = dataSourceRef
|
||||
|
||||
pvc2, err := l.cs.CoreV1().PersistentVolumeClaims(pvc2.Namespace).Create(context.TODO(), pvc2, metav1.CreateOptions{})
|
||||
framework.ExpectNoError(err)
|
||||
|
@ -214,9 +214,9 @@ func (p *provisioningTestSuite) DefineTests(driver storageframework.TestDriver,
|
||||
dc := l.config.Framework.DynamicClient
|
||||
testConfig := storageframework.ConvertTestConfig(l.config)
|
||||
expectedContent := fmt.Sprintf("Hello from namespace %s", f.Namespace.Name)
|
||||
dataSource := prepareSnapshotDataSourceForProvisioning(ctx, f, testConfig, l.config, pattern, l.cs, dc, l.pvc, l.sc, sDriver, pattern.VolMode, expectedContent)
|
||||
dataSourceRef := prepareSnapshotDataSourceForProvisioning(ctx, f, testConfig, l.config, pattern, l.cs, dc, l.pvc, l.sc, sDriver, pattern.VolMode, expectedContent)
|
||||
|
||||
l.pvc.Spec.DataSource = dataSource
|
||||
l.pvc.Spec.DataSourceRef = dataSourceRef
|
||||
l.testCase.PvCheck = func(claim *v1.PersistentVolumeClaim) {
|
||||
ginkgo.By("checking whether the created volume has the pre-populated data")
|
||||
tests := []e2evolume.Test{
|
||||
@ -386,7 +386,7 @@ func (p *provisioningTestSuite) DefineTests(driver storageframework.TestDriver,
|
||||
}()
|
||||
|
||||
apiGroup := "hello.example.com"
|
||||
l.pvc.Spec.DataSourceRef = &v1.TypedLocalObjectReference{
|
||||
l.pvc.Spec.DataSourceRef = &v1.TypedObjectReference{
|
||||
APIGroup: &apiGroup,
|
||||
Kind: "Hello",
|
||||
Name: helloCRName,
|
||||
@ -427,8 +427,8 @@ func (p *provisioningTestSuite) DefineTests(driver storageframework.TestDriver,
|
||||
}
|
||||
testConfig := storageframework.ConvertTestConfig(l.config)
|
||||
expectedContent := fmt.Sprintf("Hello from namespace %s", f.Namespace.Name)
|
||||
dataSource := preparePVCDataSourceForProvisioning(ctx, f, testConfig, l.cs, l.sourcePVC, l.sc, pattern.VolMode, expectedContent)
|
||||
l.pvc.Spec.DataSource = dataSource
|
||||
dataSourceRef := preparePVCDataSourceForProvisioning(ctx, f, testConfig, l.cs, l.sourcePVC, l.sc, pattern.VolMode, expectedContent)
|
||||
l.pvc.Spec.DataSourceRef = dataSourceRef
|
||||
l.testCase.NodeSelection = testConfig.ClientNodeSelection
|
||||
l.testCase.PvCheck = func(claim *v1.PersistentVolumeClaim) {
|
||||
ginkgo.By("checking whether the created volume has the pre-populated data")
|
||||
@ -443,7 +443,7 @@ func (p *provisioningTestSuite) DefineTests(driver storageframework.TestDriver,
|
||||
e2evolume.TestVolumeClientSlow(f, testConfig, nil, "", tests)
|
||||
}
|
||||
// Cloning fails if the source disk is still in the process of detaching, so we wait for the VolumeAttachment to be removed before cloning.
|
||||
volumeAttachment := e2evolume.GetVolumeAttachmentName(f.ClientSet, testConfig, l.testCase.Provisioner, dataSource.Name, l.sourcePVC.Namespace)
|
||||
volumeAttachment := e2evolume.GetVolumeAttachmentName(f.ClientSet, testConfig, l.testCase.Provisioner, dataSourceRef.Name, l.sourcePVC.Namespace)
|
||||
e2evolume.WaitForVolumeAttachmentTerminated(volumeAttachment, f.ClientSet, f.Timeouts.DataSourceProvision)
|
||||
l.testCase.TestDynamicProvisioning(ctx)
|
||||
})
|
||||
@ -468,8 +468,8 @@ func (p *provisioningTestSuite) DefineTests(driver storageframework.TestDriver,
|
||||
}
|
||||
testConfig := storageframework.ConvertTestConfig(l.config)
|
||||
expectedContent := fmt.Sprintf("Hello from namespace %s", f.Namespace.Name)
|
||||
dataSource := preparePVCDataSourceForProvisioning(ctx, f, testConfig, l.cs, l.sourcePVC, l.sc, pattern.VolMode, expectedContent)
|
||||
l.pvc.Spec.DataSource = dataSource
|
||||
dataSourceRef := preparePVCDataSourceForProvisioning(ctx, f, testConfig, l.cs, l.sourcePVC, l.sc, pattern.VolMode, expectedContent)
|
||||
l.pvc.Spec.DataSourceRef = dataSourceRef
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for i := 0; i < 5; i++ {
|
||||
@ -497,7 +497,7 @@ func (p *provisioningTestSuite) DefineTests(driver storageframework.TestDriver,
|
||||
e2evolume.TestVolumeClientSlow(f, myTestConfig, nil, "", tests)
|
||||
}
|
||||
// Cloning fails if the source disk is still in the process of detaching, so we wait for the VolumeAttachment to be removed before cloning.
|
||||
volumeAttachment := e2evolume.GetVolumeAttachmentName(f.ClientSet, testConfig, l.testCase.Provisioner, dataSource.Name, l.sourcePVC.Namespace)
|
||||
volumeAttachment := e2evolume.GetVolumeAttachmentName(f.ClientSet, testConfig, l.testCase.Provisioner, dataSourceRef.Name, l.sourcePVC.Namespace)
|
||||
e2evolume.WaitForVolumeAttachmentTerminated(volumeAttachment, f.ClientSet, f.Timeouts.DataSourceProvision)
|
||||
t.TestDynamicProvisioning(ctx)
|
||||
}(i)
|
||||
@ -1049,7 +1049,7 @@ func prepareSnapshotDataSourceForProvisioning(
|
||||
sDriver storageframework.SnapshottableTestDriver,
|
||||
mode v1.PersistentVolumeMode,
|
||||
injectContent string,
|
||||
) *v1.TypedLocalObjectReference {
|
||||
) *v1.TypedObjectReference {
|
||||
SetupStorageClass(ctx, client, class)
|
||||
|
||||
if initClaim.ResourceVersion != "" {
|
||||
@ -1078,7 +1078,7 @@ func prepareSnapshotDataSourceForProvisioning(
|
||||
parameters := map[string]string{}
|
||||
snapshotResource := storageframework.CreateSnapshotResource(sDriver, perTestConfig, pattern, initClaim.GetName(), initClaim.GetNamespace(), f.Timeouts, parameters)
|
||||
group := "snapshot.storage.k8s.io"
|
||||
dataSourceRef := &v1.TypedLocalObjectReference{
|
||||
dataSourceRef := &v1.TypedObjectReference{
|
||||
APIGroup: &group,
|
||||
Kind: "VolumeSnapshot",
|
||||
Name: snapshotResource.Vs.GetName(),
|
||||
@ -1108,7 +1108,7 @@ func preparePVCDataSourceForProvisioning(
|
||||
class *storagev1.StorageClass,
|
||||
mode v1.PersistentVolumeMode,
|
||||
injectContent string,
|
||||
) *v1.TypedLocalObjectReference {
|
||||
) *v1.TypedObjectReference {
|
||||
SetupStorageClass(ctx, client, class)
|
||||
|
||||
if source.ResourceVersion != "" {
|
||||
@ -1130,7 +1130,7 @@ func preparePVCDataSourceForProvisioning(
|
||||
}
|
||||
e2evolume.InjectContent(f, config, nil, "", tests)
|
||||
|
||||
dataSourceRef := &v1.TypedLocalObjectReference{
|
||||
dataSourceRef := &v1.TypedObjectReference{
|
||||
Kind: "PersistentVolumeClaim",
|
||||
Name: source.GetName(),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user