Unverified Commit 6c311012 authored by Kubernetes Prow Robot's avatar Kubernetes Prow Robot Committed by GitHub

Merge pull request #74283 from xing-yang/csi_crd_controller

CSINodeInfo and CSIDriver Controller Changes
parents 43616fc9 d69e0ff3
...@@ -134,7 +134,6 @@ go_library( ...@@ -134,7 +134,6 @@ go_library(
"//staging/src/k8s.io/cloud-provider:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library",
"//staging/src/k8s.io/component-base/cli/flag:go_default_library", "//staging/src/k8s.io/component-base/cli/flag:go_default_library",
"//staging/src/k8s.io/component-base/cli/globalflag:go_default_library", "//staging/src/k8s.io/component-base/cli/globalflag:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/client/clientset/versioned:go_default_library",
"//staging/src/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1:go_default_library", "//staging/src/k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1:go_default_library",
"//staging/src/k8s.io/metrics/pkg/client/custom_metrics:go_default_library", "//staging/src/k8s.io/metrics/pkg/client/custom_metrics:go_default_library",
"//staging/src/k8s.io/metrics/pkg/client/external_metrics:go_default_library", "//staging/src/k8s.io/metrics/pkg/client/external_metrics:go_default_library",
......
...@@ -37,7 +37,6 @@ import ( ...@@ -37,7 +37,6 @@ import (
"k8s.io/client-go/dynamic" "k8s.io/client-go/dynamic"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
csiclientset "k8s.io/csi-api/pkg/client/clientset/versioned"
"k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller"
cloudcontroller "k8s.io/kubernetes/pkg/controller/cloud" cloudcontroller "k8s.io/kubernetes/pkg/controller/cloud"
endpointcontroller "k8s.io/kubernetes/pkg/controller/endpoint" endpointcontroller "k8s.io/kubernetes/pkg/controller/endpoint"
...@@ -216,14 +215,10 @@ func startAttachDetachController(ctx ControllerContext) (http.Handler, bool, err ...@@ -216,14 +215,10 @@ func startAttachDetachController(ctx ControllerContext) (http.Handler, bool, err
if ctx.ComponentConfig.AttachDetachController.ReconcilerSyncLoopPeriod.Duration < time.Second { if ctx.ComponentConfig.AttachDetachController.ReconcilerSyncLoopPeriod.Duration < time.Second {
return nil, true, fmt.Errorf("duration time must be greater than one second as set via command line option reconcile-sync-loop-period") return nil, true, fmt.Errorf("duration time must be greater than one second as set via command line option reconcile-sync-loop-period")
} }
csiClientConfig := ctx.ClientBuilder.ConfigOrDie("attachdetach-controller")
// csiClient works with CRDs that support json only
csiClientConfig.ContentType = "application/json"
attachDetachController, attachDetachControllerErr := attachDetachController, attachDetachControllerErr :=
attachdetach.NewAttachDetachController( attachdetach.NewAttachDetachController(
ctx.ClientBuilder.ClientOrDie("attachdetach-controller"), ctx.ClientBuilder.ClientOrDie("attachdetach-controller"),
csiclientset.NewForConfigOrDie(csiClientConfig),
ctx.InformerFactory.Core().V1().Pods(), ctx.InformerFactory.Core().V1().Pods(),
ctx.InformerFactory.Core().V1().Nodes(), ctx.InformerFactory.Core().V1().Nodes(),
ctx.InformerFactory.Core().V1().PersistentVolumeClaims(), ctx.InformerFactory.Core().V1().PersistentVolumeClaims(),
......
...@@ -136,7 +136,6 @@ go_library( ...@@ -136,7 +136,6 @@ go_library(
"//staging/src/k8s.io/client-go/util/keyutil:go_default_library", "//staging/src/k8s.io/client-go/util/keyutil:go_default_library",
"//staging/src/k8s.io/cloud-provider:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library",
"//staging/src/k8s.io/component-base/cli/flag:go_default_library", "//staging/src/k8s.io/component-base/cli/flag:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/client/clientset/versioned:go_default_library",
"//staging/src/k8s.io/kubelet/config/v1beta1:go_default_library", "//staging/src/k8s.io/kubelet/config/v1beta1:go_default_library",
"//staging/src/k8s.io/node-api/pkg/client/clientset/versioned:go_default_library", "//staging/src/k8s.io/node-api/pkg/client/clientset/versioned:go_default_library",
"//vendor/github.com/coreos/go-systemd/daemon:go_default_library", "//vendor/github.com/coreos/go-systemd/daemon:go_default_library",
......
...@@ -57,7 +57,6 @@ import ( ...@@ -57,7 +57,6 @@ import (
"k8s.io/client-go/util/keyutil" "k8s.io/client-go/util/keyutil"
cloudprovider "k8s.io/cloud-provider" cloudprovider "k8s.io/cloud-provider"
cliflag "k8s.io/component-base/cli/flag" cliflag "k8s.io/component-base/cli/flag"
csiclientset "k8s.io/csi-api/pkg/client/clientset/versioned"
kubeletconfigv1beta1 "k8s.io/kubelet/config/v1beta1" kubeletconfigv1beta1 "k8s.io/kubelet/config/v1beta1"
"k8s.io/kubernetes/cmd/kubelet/app/options" "k8s.io/kubernetes/cmd/kubelet/app/options"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
...@@ -400,7 +399,6 @@ func UnsecuredDependencies(s *options.KubeletServer) (*kubelet.Dependencies, err ...@@ -400,7 +399,6 @@ func UnsecuredDependencies(s *options.KubeletServer) (*kubelet.Dependencies, err
DockerClientConfig: dockerClientConfig, DockerClientConfig: dockerClientConfig,
KubeClient: nil, KubeClient: nil,
HeartbeatClient: nil, HeartbeatClient: nil,
CSIClient: nil,
EventClient: nil, EventClient: nil,
Mounter: mounter, Mounter: mounter,
Subpather: subpather, Subpather: subpather,
...@@ -598,10 +596,6 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies, stopCh <-chan ...@@ -598,10 +596,6 @@ func run(s *options.KubeletServer, kubeDeps *kubelet.Dependencies, stopCh <-chan
// CRDs are JSON only, and client renegotiation for streaming is not correct as per #67803 // CRDs are JSON only, and client renegotiation for streaming is not correct as per #67803
crdClientConfig := restclient.CopyConfig(clientConfig) crdClientConfig := restclient.CopyConfig(clientConfig)
crdClientConfig.ContentType = "application/json" crdClientConfig.ContentType = "application/json"
kubeDeps.CSIClient, err = csiclientset.NewForConfig(crdClientConfig)
if err != nil {
return fmt.Errorf("failed to initialize kubelet storage client: %v", err)
}
kubeDeps.NodeAPIClient, err = nodeapiclientset.NewForConfig(crdClientConfig) kubeDeps.NodeAPIClient, err = nodeapiclientset.NewForConfig(crdClientConfig)
if err != nil { if err != nil {
......
...@@ -107,9 +107,9 @@ test/e2e/testing-manifests/rbd-storage-class.yaml,storageclasses,,slow,v1beta1,v ...@@ -107,9 +107,9 @@ test/e2e/testing-manifests/rbd-storage-class.yaml,storageclasses,,slow,v1beta1,v
) )
KUBE_OLD_API_VERSION="networking.k8s.io/v1,storage.k8s.io/v1beta1,extensions/v1beta1" KUBE_OLD_API_VERSION="networking.k8s.io/v1,storage.k8s.io/v1beta1,extensions/v1beta1"
KUBE_NEW_API_VERSION="networking.k8s.io/v1,storage.k8s.io/v1,extensions/v1beta1,policy/v1beta1" KUBE_NEW_API_VERSION="networking.k8s.io/v1,storage.k8s.io/v1beta1,storage.k8s.io/v1,extensions/v1beta1,policy/v1beta1"
KUBE_OLD_STORAGE_VERSIONS="storage.k8s.io/v1beta1" KUBE_OLD_STORAGE_VERSIONS="storage.k8s.io/v1beta1"
KUBE_NEW_STORAGE_VERSIONS="storage.k8s.io/v1" KUBE_NEW_STORAGE_VERSIONS="storage.k8s.io/v1beta1,storage.k8s.io/v1"
### END TEST DEFINITION CUSTOMIZATION ### ### END TEST DEFINITION CUSTOMIZATION ###
......
...@@ -142,6 +142,8 @@ func TestDefaulting(t *testing.T) { ...@@ -142,6 +142,8 @@ func TestDefaulting(t *testing.T) {
{Group: "networking.k8s.io", Version: "v1", Kind: "NetworkPolicyList"}: {}, {Group: "networking.k8s.io", Version: "v1", Kind: "NetworkPolicyList"}: {},
{Group: "storage.k8s.io", Version: "v1beta1", Kind: "StorageClass"}: {}, {Group: "storage.k8s.io", Version: "v1beta1", Kind: "StorageClass"}: {},
{Group: "storage.k8s.io", Version: "v1beta1", Kind: "StorageClassList"}: {}, {Group: "storage.k8s.io", Version: "v1beta1", Kind: "StorageClassList"}: {},
{Group: "storage.k8s.io", Version: "v1beta1", Kind: "CSIDriver"}: {},
{Group: "storage.k8s.io", Version: "v1beta1", Kind: "CSIDriverList"}: {},
{Group: "storage.k8s.io", Version: "v1", Kind: "StorageClass"}: {}, {Group: "storage.k8s.io", Version: "v1", Kind: "StorageClass"}: {},
{Group: "storage.k8s.io", Version: "v1", Kind: "StorageClassList"}: {}, {Group: "storage.k8s.io", Version: "v1", Kind: "StorageClassList"}: {},
{Group: "authentication.k8s.io", Version: "v1", Kind: "TokenRequest"}: {}, {Group: "authentication.k8s.io", Version: "v1", Kind: "TokenRequest"}: {},
......
...@@ -61,8 +61,6 @@ const isInvalidQuotaResource string = `must be a standard resource for quota` ...@@ -61,8 +61,6 @@ const isInvalidQuotaResource string = `must be a standard resource for quota`
const fieldImmutableErrorMsg string = apimachineryvalidation.FieldImmutableErrorMsg const fieldImmutableErrorMsg string = apimachineryvalidation.FieldImmutableErrorMsg
const isNotIntegerErrorMsg string = `must be an integer` const isNotIntegerErrorMsg string = `must be an integer`
const isNotPositiveErrorMsg string = `must be greater than zero` const isNotPositiveErrorMsg string = `must be greater than zero`
const csiDriverNameRexpErrMsg string = "must consist of alphanumeric characters, '-', '_' or '.', and must start and end with an alphanumeric character"
const csiDriverNameRexpFmt string = `^[a-zA-Z0-9][-a-zA-Z0-9_.]{0,61}[a-zA-Z-0-9]$`
var pdPartitionErrorMsg string = validation.InclusiveRangeError(1, 255) var pdPartitionErrorMsg string = validation.InclusiveRangeError(1, 255)
var fileModeErrorMsg string = "must be a number between 0 and 0777 (octal), both inclusive" var fileModeErrorMsg string = "must be a number between 0 and 0777 (octal), both inclusive"
...@@ -74,8 +72,6 @@ var iscsiInitiatorIqnRegex = regexp.MustCompile(`iqn\.\d{4}-\d{2}\.([[:alnum:]-. ...@@ -74,8 +72,6 @@ var iscsiInitiatorIqnRegex = regexp.MustCompile(`iqn\.\d{4}-\d{2}\.([[:alnum:]-.
var iscsiInitiatorEuiRegex = regexp.MustCompile(`^eui.[[:alnum:]]{16}$`) var iscsiInitiatorEuiRegex = regexp.MustCompile(`^eui.[[:alnum:]]{16}$`)
var iscsiInitiatorNaaRegex = regexp.MustCompile(`^naa.[[:alnum:]]{32}$`) var iscsiInitiatorNaaRegex = regexp.MustCompile(`^naa.[[:alnum:]]{32}$`)
var csiDriverNameRexp = regexp.MustCompile(csiDriverNameRexpFmt)
// ValidateHasLabel requires that metav1.ObjectMeta has a Label with key and expectedValue // ValidateHasLabel requires that metav1.ObjectMeta has a Label with key and expectedValue
func ValidateHasLabel(meta metav1.ObjectMeta, fldPath *field.Path, key, expectedValue string) field.ErrorList { func ValidateHasLabel(meta metav1.ObjectMeta, fldPath *field.Path, key, expectedValue string) field.ErrorList {
allErrs := field.ErrorList{} allErrs := field.ErrorList{}
...@@ -1446,9 +1442,10 @@ func ValidateCSIDriverName(driverName string, fldPath *field.Path) field.ErrorLi ...@@ -1446,9 +1442,10 @@ func ValidateCSIDriverName(driverName string, fldPath *field.Path) field.ErrorLi
allErrs = append(allErrs, field.TooLong(fldPath, driverName, 63)) allErrs = append(allErrs, field.TooLong(fldPath, driverName, 63))
} }
if !csiDriverNameRexp.MatchString(driverName) { for _, msg := range validation.IsDNS1123Subdomain(strings.ToLower(driverName)) {
allErrs = append(allErrs, field.Invalid(fldPath, driverName, validation.RegexError(csiDriverNameRexpErrMsg, csiDriverNameRexpFmt, "csi-hostpath"))) allErrs = append(allErrs, field.Invalid(fldPath, driverName, msg))
} }
return allErrs return allErrs
} }
......
...@@ -1775,24 +1775,30 @@ func TestValidateCSIVolumeSource(t *testing.T) { ...@@ -1775,24 +1775,30 @@ func TestValidateCSIVolumeSource(t *testing.T) {
csi: &core.CSIPersistentVolumeSource{Driver: "io-kubernetes-storage-csi-flex", VolumeHandle: "test-123"}, csi: &core.CSIPersistentVolumeSource{Driver: "io-kubernetes-storage-csi-flex", VolumeHandle: "test-123"},
}, },
{ {
name: "driver name: ok underscore only", name: "driver name: invalid underscore",
csi: &core.CSIPersistentVolumeSource{Driver: "io_kubernetes_storage_csi_flex", VolumeHandle: "test-123"}, csi: &core.CSIPersistentVolumeSource{Driver: "io_kubernetes_storage_csi_flex", VolumeHandle: "test-123"},
errtype: field.ErrorTypeInvalid,
errfield: "driver",
}, },
{ {
name: "driver name: ok dot underscores", name: "driver name: invalid dot underscores",
csi: &core.CSIPersistentVolumeSource{Driver: "io.kubernetes.storage_csi.flex", VolumeHandle: "test-123"}, csi: &core.CSIPersistentVolumeSource{Driver: "io.kubernetes.storage_csi.flex", VolumeHandle: "test-123"},
errtype: field.ErrorTypeInvalid,
errfield: "driver",
}, },
{ {
name: "driver name: ok beginnin with number", name: "driver name: ok beginnin with number",
csi: &core.CSIPersistentVolumeSource{Driver: "2io.kubernetes.storage_csi.flex", VolumeHandle: "test-123"}, csi: &core.CSIPersistentVolumeSource{Driver: "2io.kubernetes.storage-csi.flex", VolumeHandle: "test-123"},
}, },
{ {
name: "driver name: ok ending with number", name: "driver name: ok ending with number",
csi: &core.CSIPersistentVolumeSource{Driver: "io.kubernetes.storage_csi.flex2", VolumeHandle: "test-123"}, csi: &core.CSIPersistentVolumeSource{Driver: "io.kubernetes.storage-csi.flex2", VolumeHandle: "test-123"},
}, },
{ {
name: "driver name: ok dot dash underscores", name: "driver name: invalid dot dash underscores",
csi: &core.CSIPersistentVolumeSource{Driver: "io.kubernetes-storage.csi_flex", VolumeHandle: "test-123"}, csi: &core.CSIPersistentVolumeSource{Driver: "io.kubernetes-storage.csi_flex", VolumeHandle: "test-123"},
errtype: field.ErrorTypeInvalid,
errfield: "driver",
}, },
{ {
name: "driver name: invalid length 0", name: "driver name: invalid length 0",
...@@ -1801,10 +1807,8 @@ func TestValidateCSIVolumeSource(t *testing.T) { ...@@ -1801,10 +1807,8 @@ func TestValidateCSIVolumeSource(t *testing.T) {
errfield: "driver", errfield: "driver",
}, },
{ {
name: "driver name: invalid length 1", name: "driver name: ok length 1",
csi: &core.CSIPersistentVolumeSource{Driver: "a", VolumeHandle: "test-123"}, csi: &core.CSIPersistentVolumeSource{Driver: "a", VolumeHandle: "test-123"},
errtype: field.ErrorTypeInvalid,
errfield: "driver",
}, },
{ {
name: "driver name: invalid length > 63", name: "driver name: invalid length > 63",
......
...@@ -34,5 +34,18 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} { ...@@ -34,5 +34,18 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
bindingModes := []storage.VolumeBindingMode{storage.VolumeBindingImmediate, storage.VolumeBindingWaitForFirstConsumer} bindingModes := []storage.VolumeBindingMode{storage.VolumeBindingImmediate, storage.VolumeBindingWaitForFirstConsumer}
obj.VolumeBindingMode = &bindingModes[c.Rand.Intn(len(bindingModes))] obj.VolumeBindingMode = &bindingModes[c.Rand.Intn(len(bindingModes))]
}, },
func(obj *storage.CSIDriver, c fuzz.Continue) {
c.FuzzNoCustom(obj) // fuzz self without calling this function again
// match defaulting
if obj.Spec.AttachRequired == nil {
obj.Spec.AttachRequired = new(bool)
*(obj.Spec.AttachRequired) = true
}
if obj.Spec.PodInfoOnMount == nil {
obj.Spec.PodInfoOnMount = new(bool)
*(obj.Spec.PodInfoOnMount) = false
}
},
} }
} }
...@@ -48,6 +48,10 @@ func addKnownTypes(scheme *runtime.Scheme) error { ...@@ -48,6 +48,10 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&StorageClassList{}, &StorageClassList{},
&VolumeAttachment{}, &VolumeAttachment{},
&VolumeAttachmentList{}, &VolumeAttachmentList{},
&CSINode{},
&CSINodeList{},
&CSIDriver{},
&CSIDriverList{},
) )
return nil return nil
} }
...@@ -215,3 +215,160 @@ const ( ...@@ -215,3 +215,160 @@ const (
// binding will occur during Pod scheduing. // binding will occur during Pod scheduing.
VolumeBindingWaitForFirstConsumer VolumeBindingMode = "WaitForFirstConsumer" VolumeBindingWaitForFirstConsumer VolumeBindingMode = "WaitForFirstConsumer"
) )
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// CSIDriver captures information about a Container Storage Interface (CSI)
// volume driver deployed on the cluster.
// CSI drivers do not need to create the CSIDriver object directly. Instead they may use the
// cluster-driver-registrar sidecar container. When deployed with a CSI driver it automatically
// creates a CSIDriver object representing the driver.
// Kubernetes attach detach controller uses this object to determine whether attach is required.
// Kubelet uses this object to determine whether pod information needs to be passed on mount.
// CSIDriver objects are non-namespaced.
type CSIDriver struct {
metav1.TypeMeta
// Standard object metadata.
// metadata.Name indicates the name of the CSI driver that this object
// refers to; it MUST be the same name returned by the CSI GetPluginName()
// call for that driver.
// The driver name must be 63 characters or less, beginning and ending with
// an alphanumeric character ([a-z0-9A-Z]) with dashes (-), dots (.), and
// alphanumerics between.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
metav1.ObjectMeta
// Specification of the CSI Driver.
Spec CSIDriverSpec
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// CSIDriverList is a collection of CSIDriver objects.
type CSIDriverList struct {
metav1.TypeMeta
// Standard list metadata
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
// +optional
metav1.ListMeta
// items is the list of CSIDriver
Items []CSIDriver
}
// CSIDriverSpec is the specification of a CSIDriver.
type CSIDriverSpec struct {
// attachRequired indicates this CSI volume driver requires an attach
// operation (because it implements the CSI ControllerPublishVolume()
// method), and that the Kubernetes attach detach controller should call
// the attach volume interface which checks the volumeattachment status
// and waits until the volume is attached before proceeding to mounting.
// The CSI external-attacher coordinates with CSI volume driver and updates
// the volumeattachment status when the attach operation is complete.
// If the CSIDriverRegistry feature gate is enabled and the value is
// specified to false, the attach operation will be skipped.
// Otherwise the attach operation will be called.
// +optional
AttachRequired *bool
// If set to true, podInfoOnMount indicates this CSI volume driver
// requires additional pod information (like podName, podUID, etc.) during
// mount operations.
// If set to false, pod information will not be passed on mount.
// Default is false.
// The CSI driver specifies podInfoOnMount as part of driver deployment.
// If true, Kubelet will pass pod information as VolumeContext in the CSI
// NodePublishVolume() calls.
// The CSI driver is responsible for parsing and validating the information
// passed in as VolumeContext.
// The following VolumeConext will be passed if podInfoOnMount is set to true.
// This list might grow, but the prefix will be used.
// "csi.storage.k8s.io/pod.name": pod.Name
// "csi.storage.k8s.io/pod.namespace": pod.Namespace
// "csi.storage.k8s.io/pod.uid": string(pod.UID)
// +optional
PodInfoOnMount *bool
}
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// CSINode holds information about all CSI drivers installed on a node.
// CSI drivers do not need to create the CSINode object directly. As long as
// they use the node-driver-registrar sidecar container, the kubelet will
// automatically populate the CSINode object for the CSI driver as part of
// kubelet plugin registration.
// CSINode has the same name as a node. If the object is missing, it means either
// there are no CSI Drivers available on the node, or the Kubelet version is low
// enough that it doesn't create this object.
// CSINode has an OwnerReference that points to the corresponding node object.
type CSINode struct {
metav1.TypeMeta
// metadata.name must be the Kubernetes node name.
metav1.ObjectMeta
// spec is the specification of CSINode
Spec CSINodeSpec
}
// CSINodeSpec holds information about the specification of all CSI drivers installed on a node
type CSINodeSpec struct {
// drivers is a list of information of all CSI Drivers existing on a node.
// If all drivers in the list are uninstalled, this can become empty.
// +patchMergeKey=name
// +patchStrategy=merge
Drivers []CSINodeDriver
}
// CSINodeDriver holds information about the specification of one CSI driver installed on a node
type CSINodeDriver struct {
// This is the name of the CSI driver that this object refers to.
// This MUST be the same name returned by the CSI GetPluginName() call for
// that driver.
Name string
// nodeID of the node from the driver point of view.
// This field enables Kubernetes to communicate with storage systems that do
// not share the same nomenclature for nodes. For example, Kubernetes may
// refer to a given node as "node1", but the storage system may refer to
// the same node as "nodeA". When Kubernetes issues a command to the storage
// system to attach a volume to a specific node, it can use this field to
// refer to the node name using the ID that the storage system will
// understand, e.g. "nodeA" instead of "node1". This field is required.
NodeID string
// topologyKeys is the list of keys supported by the driver.
// When a driver is initialized on a cluster, it provides a set of topology
// keys that it understands (e.g. "company.com/zone", "company.com/region").
// When a driver is initialized on a node, it provides the same topology keys
// along with values. Kubelet will expose these topology keys as labels
// on its own node object.
// When Kubernetes does topology aware provisioning, it can use this list to
// determine which labels it should retrieve from the node object and pass
// back to the driver.
// It is possible for different nodes to use different topology keys.
// This can be empty if driver does not support topology.
// +optional
TopologyKeys []string
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// CSINodeList is a collection of CSINode objects.
type CSINodeList struct {
metav1.TypeMeta
// Standard list metadata
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
// +optional
metav1.ListMeta
// items is the list of CSINode
Items []CSINode
}
...@@ -37,3 +37,14 @@ func SetDefaults_StorageClass(obj *storagev1beta1.StorageClass) { ...@@ -37,3 +37,14 @@ func SetDefaults_StorageClass(obj *storagev1beta1.StorageClass) {
*obj.VolumeBindingMode = storagev1beta1.VolumeBindingImmediate *obj.VolumeBindingMode = storagev1beta1.VolumeBindingImmediate
} }
} }
func SetDefaults_CSIDriver(obj *storagev1beta1.CSIDriver) {
if obj.Spec.AttachRequired == nil {
obj.Spec.AttachRequired = new(bool)
*(obj.Spec.AttachRequired) = true
}
if obj.Spec.PodInfoOnMount == nil {
obj.Spec.PodInfoOnMount = new(bool)
*(obj.Spec.PodInfoOnMount) = false
}
}
...@@ -60,3 +60,24 @@ func TestSetDefaultVolumeBindingMode(t *testing.T) { ...@@ -60,3 +60,24 @@ func TestSetDefaultVolumeBindingMode(t *testing.T) {
t.Errorf("Expected VolumeBindingMode to be defaulted to: %+v, got: %+v", defaultMode, outMode) t.Errorf("Expected VolumeBindingMode to be defaulted to: %+v, got: %+v", defaultMode, outMode)
} }
} }
func TestSetDefaultAttachRequired(t *testing.T) {
driver := &storagev1beta1.CSIDriver{}
// field should be defaulted
defaultAttach := true
defaultPodInfo := false
output := roundTrip(t, runtime.Object(driver)).(*storagev1beta1.CSIDriver)
outAttach := output.Spec.AttachRequired
if outAttach == nil {
t.Errorf("Expected AttachRequired to be defaulted to: %+v, got: nil", defaultAttach)
} else if *outAttach != defaultAttach {
t.Errorf("Expected AttachRequired to be defaulted to: %+v, got: %+v", defaultAttach, outAttach)
}
outPodInfo := output.Spec.PodInfoOnMount
if outPodInfo == nil {
t.Errorf("Expected PodInfoOnMount to be defaulted to: %+v, got: nil", defaultPodInfo)
} else if *outPodInfo != defaultPodInfo {
t.Errorf("Expected PodInfoOnMount to be defaulted to: %+v, got: %+v", defaultPodInfo, outPodInfo)
}
}
...@@ -29,11 +29,24 @@ import ( ...@@ -29,11 +29,24 @@ import (
// Public to allow building arbitrary schemes. // Public to allow building arbitrary schemes.
// All generated defaulters are covering - they call all nested defaulters. // All generated defaulters are covering - they call all nested defaulters.
func RegisterDefaults(scheme *runtime.Scheme) error { func RegisterDefaults(scheme *runtime.Scheme) error {
scheme.AddTypeDefaultingFunc(&v1beta1.CSIDriver{}, func(obj interface{}) { SetObjectDefaults_CSIDriver(obj.(*v1beta1.CSIDriver)) })
scheme.AddTypeDefaultingFunc(&v1beta1.CSIDriverList{}, func(obj interface{}) { SetObjectDefaults_CSIDriverList(obj.(*v1beta1.CSIDriverList)) })
scheme.AddTypeDefaultingFunc(&v1beta1.StorageClass{}, func(obj interface{}) { SetObjectDefaults_StorageClass(obj.(*v1beta1.StorageClass)) }) scheme.AddTypeDefaultingFunc(&v1beta1.StorageClass{}, func(obj interface{}) { SetObjectDefaults_StorageClass(obj.(*v1beta1.StorageClass)) })
scheme.AddTypeDefaultingFunc(&v1beta1.StorageClassList{}, func(obj interface{}) { SetObjectDefaults_StorageClassList(obj.(*v1beta1.StorageClassList)) }) scheme.AddTypeDefaultingFunc(&v1beta1.StorageClassList{}, func(obj interface{}) { SetObjectDefaults_StorageClassList(obj.(*v1beta1.StorageClassList)) })
return nil return nil
} }
func SetObjectDefaults_CSIDriver(in *v1beta1.CSIDriver) {
SetDefaults_CSIDriver(in)
}
func SetObjectDefaults_CSIDriverList(in *v1beta1.CSIDriverList) {
for i := range in.Items {
a := &in.Items[i]
SetObjectDefaults_CSIDriver(a)
}
}
func SetObjectDefaults_StorageClass(in *v1beta1.StorageClass) { func SetObjectDefaults_StorageClass(in *v1beta1.StorageClass) {
SetDefaults_StorageClass(in) SetDefaults_StorageClass(in)
} }
......
...@@ -17,6 +17,7 @@ limitations under the License. ...@@ -17,6 +17,7 @@ limitations under the License.
package validation package validation
import ( import (
"fmt"
"reflect" "reflect"
"strings" "strings"
...@@ -36,6 +37,8 @@ const ( ...@@ -36,6 +37,8 @@ const (
maxAttachedVolumeMetadataSize = 256 * (1 << 10) // 256 kB maxAttachedVolumeMetadataSize = 256 * (1 << 10) // 256 kB
maxVolumeErrorMessageSize = 1024 maxVolumeErrorMessageSize = 1024
csiNodeIDMaxLength = 128
) )
// ValidateStorageClass validates a StorageClass. // ValidateStorageClass validates a StorageClass.
...@@ -266,3 +269,144 @@ func validateAllowedTopologies(topologies []api.TopologySelectorTerm, fldPath *f ...@@ -266,3 +269,144 @@ func validateAllowedTopologies(topologies []api.TopologySelectorTerm, fldPath *f
return allErrs return allErrs
} }
// ValidateCSINode validates a CSINode.
func ValidateCSINode(csiNode *storage.CSINode) field.ErrorList {
allErrs := apivalidation.ValidateObjectMeta(&csiNode.ObjectMeta, false, apivalidation.ValidateNodeName, field.NewPath("metadata"))
allErrs = append(allErrs, validateCSINodeSpec(&csiNode.Spec, field.NewPath("spec"))...)
return allErrs
}
// ValidateCSINodeUpdate validates a CSINode.
func ValidateCSINodeUpdate(new, old *storage.CSINode) field.ErrorList {
allErrs := ValidateCSINode(new)
// Validate modifying fields inside an existing CSINodeDriver entry is not allowed
for _, oldDriver := range old.Spec.Drivers {
for _, newDriver := range new.Spec.Drivers {
if oldDriver.Name == newDriver.Name {
if !apiequality.Semantic.DeepEqual(oldDriver, newDriver) {
allErrs = append(allErrs, field.Invalid(field.NewPath("CSINodeDriver"), newDriver, "field is immutable"))
}
}
}
}
return allErrs
}
// ValidateCSINodeSpec tests that the specified CSINodeSpec has valid data.
func validateCSINodeSpec(
spec *storage.CSINodeSpec, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, validateCSINodeDrivers(spec.Drivers, fldPath.Child("drivers"))...)
return allErrs
}
// ValidateCSINodeDrivers tests that the specified CSINodeDrivers have valid data.
func validateCSINodeDrivers(drivers []storage.CSINodeDriver, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
driverNamesInSpecs := make(sets.String)
for i, driver := range drivers {
idxPath := fldPath.Index(i)
allErrs = append(allErrs, validateCSINodeDriver(driver, driverNamesInSpecs, idxPath)...)
}
return allErrs
}
// validateCSINodeDriverNodeID tests if Name in CSINodeDriver is a valid node id.
func validateCSINodeDriverNodeID(nodeID string, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
// nodeID is always required
if len(nodeID) == 0 {
allErrs = append(allErrs, field.Required(fldPath, nodeID))
}
if len(nodeID) > csiNodeIDMaxLength {
allErrs = append(allErrs, field.Invalid(fldPath, nodeID, fmt.Sprintf("must be %d characters or less", csiNodeIDMaxLength)))
}
return allErrs
}
// validateCSINodeDriver tests if CSINodeDriver has valid entries
func validateCSINodeDriver(driver storage.CSINodeDriver, driverNamesInSpecs sets.String, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateCSIDriverName(driver.Name, fldPath.Child("name"))...)
allErrs = append(allErrs, validateCSINodeDriverNodeID(driver.NodeID, fldPath.Child("nodeID"))...)
// check for duplicate entries for the same driver in specs
if driverNamesInSpecs.Has(driver.Name) {
allErrs = append(allErrs, field.Duplicate(fldPath.Child("name"), driver.Name))
}
driverNamesInSpecs.Insert(driver.Name)
topoKeys := make(sets.String)
for _, key := range driver.TopologyKeys {
if len(key) == 0 {
allErrs = append(allErrs, field.Required(fldPath, key))
}
if topoKeys.Has(key) {
allErrs = append(allErrs, field.Duplicate(fldPath, key))
}
topoKeys.Insert(key)
for _, msg := range validation.IsQualifiedName(key) {
allErrs = append(allErrs, field.Invalid(fldPath, driver.TopologyKeys, msg))
}
}
return allErrs
}
// ValidateCSIDriver validates a CSIDriver.
func ValidateCSIDriver(csiDriver *storage.CSIDriver) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, apivalidation.ValidateCSIDriverName(csiDriver.Name, field.NewPath("name"))...)
allErrs = append(allErrs, validateCSIDriverSpec(&csiDriver.Spec, field.NewPath("spec"))...)
return allErrs
}
// ValidateCSIDriverUpdate validates a CSIDriver.
func ValidateCSIDriverUpdate(new, old *storage.CSIDriver) field.ErrorList {
allErrs := ValidateCSIDriver(new)
// Spec is read-only
// If this ever relaxes in the future, make sure to increment the Generation number in PrepareForUpdate
if !apiequality.Semantic.DeepEqual(old.Spec, new.Spec) {
allErrs = append(allErrs, field.Invalid(field.NewPath("spec"), new.Spec, "field is immutable"))
}
return allErrs
}
// ValidateCSIDriverSpec tests that the specified CSIDriverSpec
// has valid data.
func validateCSIDriverSpec(
spec *storage.CSIDriverSpec, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, validateAttachRequired(spec.AttachRequired, fldPath.Child("attachedRequired"))...)
allErrs = append(allErrs, validatePodInfoOnMount(spec.PodInfoOnMount, fldPath.Child("podInfoOnMount"))...)
return allErrs
}
// validateAttachRequired tests if attachRequired is set for CSIDriver.
func validateAttachRequired(attachRequired *bool, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if attachRequired == nil {
allErrs = append(allErrs, field.Required(fldPath, ""))
}
return allErrs
}
// validatePodInfoOnMount tests if podInfoOnMount is set for CSIDriver.
func validatePodInfoOnMount(podInfoOnMount *bool, fldPath *field.Path) field.ErrorList {
allErrs := field.ErrorList{}
if podInfoOnMount == nil {
allErrs = append(allErrs, field.Required(fldPath, ""))
}
return allErrs
}
...@@ -26,6 +26,196 @@ import ( ...@@ -26,6 +26,196 @@ import (
) )
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CSIDriver) DeepCopyInto(out *CSIDriver) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSIDriver.
func (in *CSIDriver) DeepCopy() *CSIDriver {
if in == nil {
return nil
}
out := new(CSIDriver)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *CSIDriver) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CSIDriverList) DeepCopyInto(out *CSIDriverList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]CSIDriver, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSIDriverList.
func (in *CSIDriverList) DeepCopy() *CSIDriverList {
if in == nil {
return nil
}
out := new(CSIDriverList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *CSIDriverList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CSIDriverSpec) DeepCopyInto(out *CSIDriverSpec) {
*out = *in
if in.AttachRequired != nil {
in, out := &in.AttachRequired, &out.AttachRequired
*out = new(bool)
**out = **in
}
if in.PodInfoOnMount != nil {
in, out := &in.PodInfoOnMount, &out.PodInfoOnMount
*out = new(bool)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSIDriverSpec.
func (in *CSIDriverSpec) DeepCopy() *CSIDriverSpec {
if in == nil {
return nil
}
out := new(CSIDriverSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CSINode) DeepCopyInto(out *CSINode) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSINode.
func (in *CSINode) DeepCopy() *CSINode {
if in == nil {
return nil
}
out := new(CSINode)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *CSINode) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CSINodeDriver) DeepCopyInto(out *CSINodeDriver) {
*out = *in
if in.TopologyKeys != nil {
in, out := &in.TopologyKeys, &out.TopologyKeys
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSINodeDriver.
func (in *CSINodeDriver) DeepCopy() *CSINodeDriver {
if in == nil {
return nil
}
out := new(CSINodeDriver)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CSINodeList) DeepCopyInto(out *CSINodeList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]CSINode, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSINodeList.
func (in *CSINodeList) DeepCopy() *CSINodeList {
if in == nil {
return nil
}
out := new(CSINodeList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *CSINodeList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CSINodeSpec) DeepCopyInto(out *CSINodeSpec) {
*out = *in
if in.Drivers != nil {
in, out := &in.Drivers, &out.Drivers
*out = make([]CSINodeDriver, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSINodeSpec.
func (in *CSINodeSpec) DeepCopy() *CSINodeSpec {
if in == nil {
return nil
}
out := new(CSINodeSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *StorageClass) DeepCopyInto(out *StorageClass) { func (in *StorageClass) DeepCopyInto(out *StorageClass) {
*out = *in *out = *in
out.TypeMeta = in.TypeMeta out.TypeMeta = in.TypeMeta
......
...@@ -8,6 +8,8 @@ load( ...@@ -8,6 +8,8 @@ load(
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
"csidriver.go",
"csinode.go",
"doc.go", "doc.go",
"generated_expansion.go", "generated_expansion.go",
"storage_client.go", "storage_client.go",
......
/*
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 client-gen. DO NOT EDIT.
package internalversion
import (
"time"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
storage "k8s.io/kubernetes/pkg/apis/storage"
scheme "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme"
)
// CSIDriversGetter has a method to return a CSIDriverInterface.
// A group's client should implement this interface.
type CSIDriversGetter interface {
CSIDrivers() CSIDriverInterface
}
// CSIDriverInterface has methods to work with CSIDriver resources.
type CSIDriverInterface interface {
Create(*storage.CSIDriver) (*storage.CSIDriver, error)
Update(*storage.CSIDriver) (*storage.CSIDriver, error)
Delete(name string, options *v1.DeleteOptions) error
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
Get(name string, options v1.GetOptions) (*storage.CSIDriver, error)
List(opts v1.ListOptions) (*storage.CSIDriverList, error)
Watch(opts v1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *storage.CSIDriver, err error)
CSIDriverExpansion
}
// cSIDrivers implements CSIDriverInterface
type cSIDrivers struct {
client rest.Interface
}
// newCSIDrivers returns a CSIDrivers
func newCSIDrivers(c *StorageClient) *cSIDrivers {
return &cSIDrivers{
client: c.RESTClient(),
}
}
// Get takes name of the cSIDriver, and returns the corresponding cSIDriver object, and an error if there is any.
func (c *cSIDrivers) Get(name string, options v1.GetOptions) (result *storage.CSIDriver, err error) {
result = &storage.CSIDriver{}
err = c.client.Get().
Resource("csidrivers").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do().
Into(result)
return
}
// List takes label and field selectors, and returns the list of CSIDrivers that match those selectors.
func (c *cSIDrivers) List(opts v1.ListOptions) (result *storage.CSIDriverList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &storage.CSIDriverList{}
err = c.client.Get().
Resource("csidrivers").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested cSIDrivers.
func (c *cSIDrivers) Watch(opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Resource("csidrivers").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch()
}
// Create takes the representation of a cSIDriver and creates it. Returns the server's representation of the cSIDriver, and an error, if there is any.
func (c *cSIDrivers) Create(cSIDriver *storage.CSIDriver) (result *storage.CSIDriver, err error) {
result = &storage.CSIDriver{}
err = c.client.Post().
Resource("csidrivers").
Body(cSIDriver).
Do().
Into(result)
return
}
// Update takes the representation of a cSIDriver and updates it. Returns the server's representation of the cSIDriver, and an error, if there is any.
func (c *cSIDrivers) Update(cSIDriver *storage.CSIDriver) (result *storage.CSIDriver, err error) {
result = &storage.CSIDriver{}
err = c.client.Put().
Resource("csidrivers").
Name(cSIDriver.Name).
Body(cSIDriver).
Do().
Into(result)
return
}
// Delete takes name of the cSIDriver and deletes it. Returns an error if one occurs.
func (c *cSIDrivers) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Resource("csidrivers").
Name(name).
Body(options).
Do().
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *cSIDrivers) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
var timeout time.Duration
if listOptions.TimeoutSeconds != nil {
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Resource("csidrivers").
VersionedParams(&listOptions, scheme.ParameterCodec).
Timeout(timeout).
Body(options).
Do().
Error()
}
// Patch applies the patch and returns the patched cSIDriver.
func (c *cSIDrivers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *storage.CSIDriver, err error) {
result = &storage.CSIDriver{}
err = c.client.Patch(pt).
Resource("csidrivers").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}
/*
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 client-gen. DO NOT EDIT.
package internalversion
import (
"time"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
storage "k8s.io/kubernetes/pkg/apis/storage"
scheme "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/scheme"
)
// CSINodesGetter has a method to return a CSINodeInterface.
// A group's client should implement this interface.
type CSINodesGetter interface {
CSINodes() CSINodeInterface
}
// CSINodeInterface has methods to work with CSINode resources.
type CSINodeInterface interface {
Create(*storage.CSINode) (*storage.CSINode, error)
Update(*storage.CSINode) (*storage.CSINode, error)
Delete(name string, options *v1.DeleteOptions) error
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
Get(name string, options v1.GetOptions) (*storage.CSINode, error)
List(opts v1.ListOptions) (*storage.CSINodeList, error)
Watch(opts v1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *storage.CSINode, err error)
CSINodeExpansion
}
// cSINodes implements CSINodeInterface
type cSINodes struct {
client rest.Interface
}
// newCSINodes returns a CSINodes
func newCSINodes(c *StorageClient) *cSINodes {
return &cSINodes{
client: c.RESTClient(),
}
}
// Get takes name of the cSINode, and returns the corresponding cSINode object, and an error if there is any.
func (c *cSINodes) Get(name string, options v1.GetOptions) (result *storage.CSINode, err error) {
result = &storage.CSINode{}
err = c.client.Get().
Resource("csinodes").
Name(name).
VersionedParams(&options, scheme.ParameterCodec).
Do().
Into(result)
return
}
// List takes label and field selectors, and returns the list of CSINodes that match those selectors.
func (c *cSINodes) List(opts v1.ListOptions) (result *storage.CSINodeList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &storage.CSINodeList{}
err = c.client.Get().
Resource("csinodes").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested cSINodes.
func (c *cSINodes) Watch(opts v1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Resource("csinodes").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch()
}
// Create takes the representation of a cSINode and creates it. Returns the server's representation of the cSINode, and an error, if there is any.
func (c *cSINodes) Create(cSINode *storage.CSINode) (result *storage.CSINode, err error) {
result = &storage.CSINode{}
err = c.client.Post().
Resource("csinodes").
Body(cSINode).
Do().
Into(result)
return
}
// Update takes the representation of a cSINode and updates it. Returns the server's representation of the cSINode, and an error, if there is any.
func (c *cSINodes) Update(cSINode *storage.CSINode) (result *storage.CSINode, err error) {
result = &storage.CSINode{}
err = c.client.Put().
Resource("csinodes").
Name(cSINode.Name).
Body(cSINode).
Do().
Into(result)
return
}
// Delete takes name of the cSINode and deletes it. Returns an error if one occurs.
func (c *cSINodes) Delete(name string, options *v1.DeleteOptions) error {
return c.client.Delete().
Resource("csinodes").
Name(name).
Body(options).
Do().
Error()
}
// DeleteCollection deletes a collection of objects.
func (c *cSINodes) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
var timeout time.Duration
if listOptions.TimeoutSeconds != nil {
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Resource("csinodes").
VersionedParams(&listOptions, scheme.ParameterCodec).
Timeout(timeout).
Body(options).
Do().
Error()
}
// Patch applies the patch and returns the patched cSINode.
func (c *cSINodes) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *storage.CSINode, err error) {
result = &storage.CSINode{}
err = c.client.Patch(pt).
Resource("csinodes").
SubResource(subresources...).
Name(name).
Body(data).
Do().
Into(result)
return
}
...@@ -9,6 +9,8 @@ go_library( ...@@ -9,6 +9,8 @@ go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
"doc.go", "doc.go",
"fake_csidriver.go",
"fake_csinode.go",
"fake_storage_client.go", "fake_storage_client.go",
"fake_storageclass.go", "fake_storageclass.go",
"fake_volumeattachment.go", "fake_volumeattachment.go",
......
/*
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 client-gen. DO NOT EDIT.
package fake
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
storage "k8s.io/kubernetes/pkg/apis/storage"
)
// FakeCSIDrivers implements CSIDriverInterface
type FakeCSIDrivers struct {
Fake *FakeStorage
}
var csidriversResource = schema.GroupVersionResource{Group: "storage.k8s.io", Version: "", Resource: "csidrivers"}
var csidriversKind = schema.GroupVersionKind{Group: "storage.k8s.io", Version: "", Kind: "CSIDriver"}
// Get takes name of the cSIDriver, and returns the corresponding cSIDriver object, and an error if there is any.
func (c *FakeCSIDrivers) Get(name string, options v1.GetOptions) (result *storage.CSIDriver, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootGetAction(csidriversResource, name), &storage.CSIDriver{})
if obj == nil {
return nil, err
}
return obj.(*storage.CSIDriver), err
}
// List takes label and field selectors, and returns the list of CSIDrivers that match those selectors.
func (c *FakeCSIDrivers) List(opts v1.ListOptions) (result *storage.CSIDriverList, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootListAction(csidriversResource, csidriversKind, opts), &storage.CSIDriverList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &storage.CSIDriverList{ListMeta: obj.(*storage.CSIDriverList).ListMeta}
for _, item := range obj.(*storage.CSIDriverList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested cSIDrivers.
func (c *FakeCSIDrivers) Watch(opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewRootWatchAction(csidriversResource, opts))
}
// Create takes the representation of a cSIDriver and creates it. Returns the server's representation of the cSIDriver, and an error, if there is any.
func (c *FakeCSIDrivers) Create(cSIDriver *storage.CSIDriver) (result *storage.CSIDriver, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootCreateAction(csidriversResource, cSIDriver), &storage.CSIDriver{})
if obj == nil {
return nil, err
}
return obj.(*storage.CSIDriver), err
}
// Update takes the representation of a cSIDriver and updates it. Returns the server's representation of the cSIDriver, and an error, if there is any.
func (c *FakeCSIDrivers) Update(cSIDriver *storage.CSIDriver) (result *storage.CSIDriver, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootUpdateAction(csidriversResource, cSIDriver), &storage.CSIDriver{})
if obj == nil {
return nil, err
}
return obj.(*storage.CSIDriver), err
}
// Delete takes name of the cSIDriver and deletes it. Returns an error if one occurs.
func (c *FakeCSIDrivers) Delete(name string, options *v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewRootDeleteAction(csidriversResource, name), &storage.CSIDriver{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeCSIDrivers) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
action := testing.NewRootDeleteCollectionAction(csidriversResource, listOptions)
_, err := c.Fake.Invokes(action, &storage.CSIDriverList{})
return err
}
// Patch applies the patch and returns the patched cSIDriver.
func (c *FakeCSIDrivers) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *storage.CSIDriver, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootPatchSubresourceAction(csidriversResource, name, pt, data, subresources...), &storage.CSIDriver{})
if obj == nil {
return nil, err
}
return obj.(*storage.CSIDriver), err
}
/*
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 client-gen. DO NOT EDIT.
package fake
import (
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
testing "k8s.io/client-go/testing"
storage "k8s.io/kubernetes/pkg/apis/storage"
)
// FakeCSINodes implements CSINodeInterface
type FakeCSINodes struct {
Fake *FakeStorage
}
var csinodesResource = schema.GroupVersionResource{Group: "storage.k8s.io", Version: "", Resource: "csinodes"}
var csinodesKind = schema.GroupVersionKind{Group: "storage.k8s.io", Version: "", Kind: "CSINode"}
// Get takes name of the cSINode, and returns the corresponding cSINode object, and an error if there is any.
func (c *FakeCSINodes) Get(name string, options v1.GetOptions) (result *storage.CSINode, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootGetAction(csinodesResource, name), &storage.CSINode{})
if obj == nil {
return nil, err
}
return obj.(*storage.CSINode), err
}
// List takes label and field selectors, and returns the list of CSINodes that match those selectors.
func (c *FakeCSINodes) List(opts v1.ListOptions) (result *storage.CSINodeList, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootListAction(csinodesResource, csinodesKind, opts), &storage.CSINodeList{})
if obj == nil {
return nil, err
}
label, _, _ := testing.ExtractFromListOptions(opts)
if label == nil {
label = labels.Everything()
}
list := &storage.CSINodeList{ListMeta: obj.(*storage.CSINodeList).ListMeta}
for _, item := range obj.(*storage.CSINodeList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
}
return list, err
}
// Watch returns a watch.Interface that watches the requested cSINodes.
func (c *FakeCSINodes) Watch(opts v1.ListOptions) (watch.Interface, error) {
return c.Fake.
InvokesWatch(testing.NewRootWatchAction(csinodesResource, opts))
}
// Create takes the representation of a cSINode and creates it. Returns the server's representation of the cSINode, and an error, if there is any.
func (c *FakeCSINodes) Create(cSINode *storage.CSINode) (result *storage.CSINode, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootCreateAction(csinodesResource, cSINode), &storage.CSINode{})
if obj == nil {
return nil, err
}
return obj.(*storage.CSINode), err
}
// Update takes the representation of a cSINode and updates it. Returns the server's representation of the cSINode, and an error, if there is any.
func (c *FakeCSINodes) Update(cSINode *storage.CSINode) (result *storage.CSINode, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootUpdateAction(csinodesResource, cSINode), &storage.CSINode{})
if obj == nil {
return nil, err
}
return obj.(*storage.CSINode), err
}
// Delete takes name of the cSINode and deletes it. Returns an error if one occurs.
func (c *FakeCSINodes) Delete(name string, options *v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewRootDeleteAction(csinodesResource, name), &storage.CSINode{})
return err
}
// DeleteCollection deletes a collection of objects.
func (c *FakeCSINodes) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
action := testing.NewRootDeleteCollectionAction(csinodesResource, listOptions)
_, err := c.Fake.Invokes(action, &storage.CSINodeList{})
return err
}
// Patch applies the patch and returns the patched cSINode.
func (c *FakeCSINodes) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *storage.CSINode, err error) {
obj, err := c.Fake.
Invokes(testing.NewRootPatchSubresourceAction(csinodesResource, name, pt, data, subresources...), &storage.CSINode{})
if obj == nil {
return nil, err
}
return obj.(*storage.CSINode), err
}
...@@ -28,6 +28,14 @@ type FakeStorage struct { ...@@ -28,6 +28,14 @@ type FakeStorage struct {
*testing.Fake *testing.Fake
} }
func (c *FakeStorage) CSIDrivers() internalversion.CSIDriverInterface {
return &FakeCSIDrivers{c}
}
func (c *FakeStorage) CSINodes() internalversion.CSINodeInterface {
return &FakeCSINodes{c}
}
func (c *FakeStorage) StorageClasses() internalversion.StorageClassInterface { func (c *FakeStorage) StorageClasses() internalversion.StorageClassInterface {
return &FakeStorageClasses{c} return &FakeStorageClasses{c}
} }
......
...@@ -18,6 +18,10 @@ limitations under the License. ...@@ -18,6 +18,10 @@ limitations under the License.
package internalversion package internalversion
type CSIDriverExpansion interface{}
type CSINodeExpansion interface{}
type StorageClassExpansion interface{} type StorageClassExpansion interface{}
type VolumeAttachmentExpansion interface{} type VolumeAttachmentExpansion interface{}
...@@ -25,6 +25,8 @@ import ( ...@@ -25,6 +25,8 @@ import (
type StorageInterface interface { type StorageInterface interface {
RESTClient() rest.Interface RESTClient() rest.Interface
CSIDriversGetter
CSINodesGetter
StorageClassesGetter StorageClassesGetter
VolumeAttachmentsGetter VolumeAttachmentsGetter
} }
...@@ -34,6 +36,14 @@ type StorageClient struct { ...@@ -34,6 +36,14 @@ type StorageClient struct {
restClient rest.Interface restClient rest.Interface
} }
func (c *StorageClient) CSIDrivers() CSIDriverInterface {
return newCSIDrivers(c)
}
func (c *StorageClient) CSINodes() CSINodeInterface {
return newCSINodes(c)
}
func (c *StorageClient) StorageClasses() StorageClassInterface { func (c *StorageClient) StorageClasses() StorageClassInterface {
return newStorageClasses(c) return newStorageClasses(c)
} }
......
...@@ -40,7 +40,6 @@ go_library( ...@@ -40,7 +40,6 @@ go_library(
"//staging/src/k8s.io/client-go/tools/record:go_default_library", "//staging/src/k8s.io/client-go/tools/record:go_default_library",
"//staging/src/k8s.io/client-go/util/workqueue:go_default_library", "//staging/src/k8s.io/client-go/util/workqueue:go_default_library",
"//staging/src/k8s.io/cloud-provider:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/client/clientset/versioned:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
], ],
) )
......
...@@ -39,7 +39,6 @@ import ( ...@@ -39,7 +39,6 @@ import (
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
"k8s.io/client-go/util/workqueue" "k8s.io/client-go/util/workqueue"
cloudprovider "k8s.io/cloud-provider" cloudprovider "k8s.io/cloud-provider"
csiclient "k8s.io/csi-api/pkg/client/clientset/versioned"
"k8s.io/klog" "k8s.io/klog"
"k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache" "k8s.io/kubernetes/pkg/controller/volume/attachdetach/cache"
...@@ -98,7 +97,6 @@ type AttachDetachController interface { ...@@ -98,7 +97,6 @@ type AttachDetachController interface {
// NewAttachDetachController returns a new instance of AttachDetachController. // NewAttachDetachController returns a new instance of AttachDetachController.
func NewAttachDetachController( func NewAttachDetachController(
kubeClient clientset.Interface, kubeClient clientset.Interface,
csiClient csiclient.Interface,
podInformer coreinformers.PodInformer, podInformer coreinformers.PodInformer,
nodeInformer coreinformers.NodeInformer, nodeInformer coreinformers.NodeInformer,
pvcInformer coreinformers.PersistentVolumeClaimInformer, pvcInformer coreinformers.PersistentVolumeClaimInformer,
...@@ -125,7 +123,6 @@ func NewAttachDetachController( ...@@ -125,7 +123,6 @@ func NewAttachDetachController(
// deleted (probably can't do this with sharedInformer), etc. // deleted (probably can't do this with sharedInformer), etc.
adc := &attachDetachController{ adc := &attachDetachController{
kubeClient: kubeClient, kubeClient: kubeClient,
csiClient: csiClient,
pvcLister: pvcInformer.Lister(), pvcLister: pvcInformer.Lister(),
pvcsSynced: pvcInformer.Informer().HasSynced, pvcsSynced: pvcInformer.Informer().HasSynced,
pvLister: pvInformer.Lister(), pvLister: pvInformer.Lister(),
...@@ -241,10 +238,6 @@ type attachDetachController struct { ...@@ -241,10 +238,6 @@ type attachDetachController struct {
// the API server. // the API server.
kubeClient clientset.Interface kubeClient clientset.Interface
// csiClient is the csi.storage.k8s.io API client used by volumehost to communicate with
// the API server.
csiClient csiclient.Interface
// pvcLister is the shared PVC lister used to fetch and store PVC // pvcLister is the shared PVC lister used to fetch and store PVC
// objects from the API server. It is shared with other controllers and // objects from the API server. It is shared with other controllers and
// therefore the PVC objects in its store should be treated as immutable. // therefore the PVC objects in its store should be treated as immutable.
...@@ -766,10 +759,6 @@ func (adc *attachDetachController) GetEventRecorder() record.EventRecorder { ...@@ -766,10 +759,6 @@ func (adc *attachDetachController) GetEventRecorder() record.EventRecorder {
return adc.recorder return adc.recorder
} }
func (adc *attachDetachController) GetCSIClient() csiclient.Interface {
return adc.csiClient
}
func (adc *attachDetachController) GetSubpather() subpath.Interface { func (adc *attachDetachController) GetSubpather() subpath.Interface {
// Subpaths not needed in attachdetach controller // Subpaths not needed in attachdetach controller
return nil return nil
......
...@@ -40,7 +40,6 @@ func Test_NewAttachDetachController_Positive(t *testing.T) { ...@@ -40,7 +40,6 @@ func Test_NewAttachDetachController_Positive(t *testing.T) {
// Act // Act
_, err := NewAttachDetachController( _, err := NewAttachDetachController(
fakeKubeClient, fakeKubeClient,
nil, /* csiClient */
informerFactory.Core().V1().Pods(), informerFactory.Core().V1().Pods(),
informerFactory.Core().V1().Nodes(), informerFactory.Core().V1().Nodes(),
informerFactory.Core().V1().PersistentVolumeClaims(), informerFactory.Core().V1().PersistentVolumeClaims(),
...@@ -215,7 +214,6 @@ func attachDetachRecoveryTestCase(t *testing.T, extraPods1 []*v1.Pod, extraPods2 ...@@ -215,7 +214,6 @@ func attachDetachRecoveryTestCase(t *testing.T, extraPods1 []*v1.Pod, extraPods2
// Create the controller // Create the controller
adcObj, err := NewAttachDetachController( adcObj, err := NewAttachDetachController(
fakeKubeClient, fakeKubeClient,
nil, /* csiClient */
informerFactory.Core().V1().Pods(), informerFactory.Core().V1().Pods(),
informerFactory.Core().V1().Nodes(), informerFactory.Core().V1().Nodes(),
informerFactory.Core().V1().PersistentVolumeClaims(), informerFactory.Core().V1().PersistentVolumeClaims(),
......
...@@ -36,7 +36,6 @@ go_library( ...@@ -36,7 +36,6 @@ go_library(
"//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library",
"//staging/src/k8s.io/client-go/tools/record:go_default_library", "//staging/src/k8s.io/client-go/tools/record:go_default_library",
"//staging/src/k8s.io/cloud-provider:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/client/clientset/versioned:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
], ],
) )
......
...@@ -38,7 +38,6 @@ import ( ...@@ -38,7 +38,6 @@ import (
kcache "k8s.io/client-go/tools/cache" kcache "k8s.io/client-go/tools/cache"
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
cloudprovider "k8s.io/cloud-provider" cloudprovider "k8s.io/cloud-provider"
csiclientset "k8s.io/csi-api/pkg/client/clientset/versioned"
"k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/controller/volume/events" "k8s.io/kubernetes/pkg/controller/volume/events"
"k8s.io/kubernetes/pkg/controller/volume/expand/cache" "k8s.io/kubernetes/pkg/controller/volume/expand/cache"
...@@ -336,11 +335,6 @@ func (expc *expandController) GetEventRecorder() record.EventRecorder { ...@@ -336,11 +335,6 @@ func (expc *expandController) GetEventRecorder() record.EventRecorder {
return expc.recorder return expc.recorder
} }
func (expc *expandController) GetCSIClient() csiclientset.Interface {
// No volume plugin in expand controller needs csi.storage.k8s.io
return nil
}
func (expc *expandController) GetSubpather() subpath.Interface { func (expc *expandController) GetSubpather() subpath.Interface {
// not needed for expand controller // not needed for expand controller
return nil return nil
......
...@@ -61,7 +61,6 @@ go_library( ...@@ -61,7 +61,6 @@ go_library(
"//staging/src/k8s.io/client-go/util/workqueue:go_default_library", "//staging/src/k8s.io/client-go/util/workqueue:go_default_library",
"//staging/src/k8s.io/cloud-provider:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library",
"//staging/src/k8s.io/cloud-provider/volume/errors:go_default_library", "//staging/src/k8s.io/cloud-provider/volume/errors:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/client/clientset/versioned:go_default_library",
"//staging/src/k8s.io/csi-translation-lib:go_default_library", "//staging/src/k8s.io/csi-translation-lib:go_default_library",
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library", "//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
......
...@@ -26,7 +26,6 @@ import ( ...@@ -26,7 +26,6 @@ import (
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
cloudprovider "k8s.io/cloud-provider" cloudprovider "k8s.io/cloud-provider"
csiclientset "k8s.io/csi-api/pkg/client/clientset/versioned"
"k8s.io/klog" "k8s.io/klog"
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
vol "k8s.io/kubernetes/pkg/volume" vol "k8s.io/kubernetes/pkg/volume"
...@@ -133,11 +132,6 @@ func (ctrl *PersistentVolumeController) GetEventRecorder() record.EventRecorder ...@@ -133,11 +132,6 @@ func (ctrl *PersistentVolumeController) GetEventRecorder() record.EventRecorder
return ctrl.eventRecorder return ctrl.eventRecorder
} }
func (ctrl *PersistentVolumeController) GetCSIClient() csiclientset.Interface {
// No volume plugin needs csi.storage.k8s.io client in PV controller.
return nil
}
func (ctrl *PersistentVolumeController) GetSubpather() subpath.Interface { func (ctrl *PersistentVolumeController) GetSubpather() subpath.Interface {
// No volume plugin needs Subpaths in PV controller. // No volume plugin needs Subpaths in PV controller.
return nil return nil
......
...@@ -195,12 +195,14 @@ const ( ...@@ -195,12 +195,14 @@ const (
// owner: @saad-ali // owner: @saad-ali
// alpha: v1.12 // alpha: v1.12
// Enable all logic related to the CSIDriver API object in csi.storage.k8s.io // beta: v1.14
// Enable all logic related to the CSIDriver API object in storage.k8s.io
CSIDriverRegistry utilfeature.Feature = "CSIDriverRegistry" CSIDriverRegistry utilfeature.Feature = "CSIDriverRegistry"
// owner: @verult // owner: @verult
// alpha: v1.12 // alpha: v1.12
// Enable all logic related to the CSINodeInfo API object in csi.storage.k8s.io // beta: v1.14
// Enable all logic related to the CSINode API object in storage.k8s.io
CSINodeInfo utilfeature.Feature = "CSINodeInfo" CSINodeInfo utilfeature.Feature = "CSINodeInfo"
// owner @MrHohn // owner @MrHohn
...@@ -448,8 +450,8 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS ...@@ -448,8 +450,8 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS
MountContainers: {Default: false, PreRelease: utilfeature.Alpha}, MountContainers: {Default: false, PreRelease: utilfeature.Alpha},
VolumeScheduling: {Default: true, PreRelease: utilfeature.GA, LockToDefault: true}, // remove in 1.16 VolumeScheduling: {Default: true, PreRelease: utilfeature.GA, LockToDefault: true}, // remove in 1.16
CSIPersistentVolume: {Default: true, PreRelease: utilfeature.GA}, CSIPersistentVolume: {Default: true, PreRelease: utilfeature.GA},
CSIDriverRegistry: {Default: false, PreRelease: utilfeature.Alpha}, CSIDriverRegistry: {Default: true, PreRelease: utilfeature.Beta},
CSINodeInfo: {Default: false, PreRelease: utilfeature.Alpha}, CSINodeInfo: {Default: true, PreRelease: utilfeature.Beta},
CustomPodDNS: {Default: true, PreRelease: utilfeature.GA, LockToDefault: true}, // remove in 1.16 CustomPodDNS: {Default: true, PreRelease: utilfeature.GA, LockToDefault: true}, // remove in 1.16
BlockVolume: {Default: true, PreRelease: utilfeature.Beta}, BlockVolume: {Default: true, PreRelease: utilfeature.Beta},
StorageObjectInUseProtection: {Default: true, PreRelease: utilfeature.GA}, StorageObjectInUseProtection: {Default: true, PreRelease: utilfeature.GA},
......
...@@ -21,6 +21,8 @@ go_library( ...@@ -21,6 +21,8 @@ go_library(
"//pkg/apis/extensions:go_default_library", "//pkg/apis/extensions:go_default_library",
"//pkg/apis/networking:go_default_library", "//pkg/apis/networking:go_default_library",
"//pkg/apis/policy:go_default_library", "//pkg/apis/policy:go_default_library",
"//pkg/apis/storage:go_default_library",
"//pkg/features:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/server/options:go_default_library", "//staging/src/k8s.io/apiserver/pkg/server/options:go_default_library",
...@@ -28,6 +30,7 @@ go_library( ...@@ -28,6 +30,7 @@ go_library(
"//staging/src/k8s.io/apiserver/pkg/server/resourceconfig:go_default_library", "//staging/src/k8s.io/apiserver/pkg/server/resourceconfig:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/server/storage:go_default_library", "//staging/src/k8s.io/apiserver/pkg/server/storage:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/storage/storagebackend:go_default_library", "//staging/src/k8s.io/apiserver/pkg/storage/storagebackend:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
], ],
) )
......
...@@ -26,6 +26,7 @@ import ( ...@@ -26,6 +26,7 @@ import (
"k8s.io/apiserver/pkg/server/resourceconfig" "k8s.io/apiserver/pkg/server/resourceconfig"
serverstorage "k8s.io/apiserver/pkg/server/storage" serverstorage "k8s.io/apiserver/pkg/server/storage"
"k8s.io/apiserver/pkg/storage/storagebackend" "k8s.io/apiserver/pkg/storage/storagebackend"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/apps" "k8s.io/kubernetes/pkg/apis/apps"
"k8s.io/kubernetes/pkg/apis/batch" "k8s.io/kubernetes/pkg/apis/batch"
...@@ -34,6 +35,8 @@ import ( ...@@ -34,6 +35,8 @@ import (
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/apis/networking" "k8s.io/kubernetes/pkg/apis/networking"
"k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/apis/policy"
apisstorage "k8s.io/kubernetes/pkg/apis/storage"
"k8s.io/kubernetes/pkg/features"
) )
// SpecialDefaultResourcePrefixes are prefixes compiled into Kubernetes. // SpecialDefaultResourcePrefixes are prefixes compiled into Kubernetes.
...@@ -48,12 +51,23 @@ var SpecialDefaultResourcePrefixes = map[schema.GroupResource]string{ ...@@ -48,12 +51,23 @@ var SpecialDefaultResourcePrefixes = map[schema.GroupResource]string{
} }
func NewStorageFactoryConfig() *StorageFactoryConfig { func NewStorageFactoryConfig() *StorageFactoryConfig {
resources := []schema.GroupVersionResource{
batch.Resource("cronjobs").WithVersion("v1beta1"),
}
// add csinodes if CSINodeInfo feature gate is enabled
if utilfeature.DefaultFeatureGate.Enabled(features.CSINodeInfo) {
resources = append(resources, apisstorage.Resource("csinodes").WithVersion("v1beta1"))
}
// add csidrivers if CSIDriverRegistry feature gate is enabled
if utilfeature.DefaultFeatureGate.Enabled(features.CSIDriverRegistry) {
resources = append(resources, apisstorage.Resource("csidrivers").WithVersion("v1beta1"))
}
return &StorageFactoryConfig{ return &StorageFactoryConfig{
Serializer: legacyscheme.Codecs, Serializer: legacyscheme.Codecs,
DefaultResourceEncoding: serverstorage.NewDefaultResourceEncodingConfig(legacyscheme.Scheme), DefaultResourceEncoding: serverstorage.NewDefaultResourceEncodingConfig(legacyscheme.Scheme),
ResourceEncodingOverrides: []schema.GroupVersionResource{ ResourceEncodingOverrides: resources,
batch.Resource("cronjobs").WithVersion("v1beta1"),
},
} }
} }
......
...@@ -140,7 +140,6 @@ go_library( ...@@ -140,7 +140,6 @@ go_library(
"//staging/src/k8s.io/client-go/util/certificate:go_default_library", "//staging/src/k8s.io/client-go/util/certificate:go_default_library",
"//staging/src/k8s.io/client-go/util/flowcontrol:go_default_library", "//staging/src/k8s.io/client-go/util/flowcontrol:go_default_library",
"//staging/src/k8s.io/cloud-provider:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/client/clientset/versioned:go_default_library",
"//staging/src/k8s.io/node-api/pkg/client/clientset/versioned:go_default_library", "//staging/src/k8s.io/node-api/pkg/client/clientset/versioned:go_default_library",
"//third_party/forked/golang/expansion:go_default_library", "//third_party/forked/golang/expansion:go_default_library",
"//vendor/github.com/golang/groupcache/lru:go_default_library", "//vendor/github.com/golang/groupcache/lru:go_default_library",
......
...@@ -51,7 +51,6 @@ import ( ...@@ -51,7 +51,6 @@ import (
"k8s.io/client-go/util/certificate" "k8s.io/client-go/util/certificate"
"k8s.io/client-go/util/flowcontrol" "k8s.io/client-go/util/flowcontrol"
cloudprovider "k8s.io/cloud-provider" cloudprovider "k8s.io/cloud-provider"
csiclientset "k8s.io/csi-api/pkg/client/clientset/versioned"
"k8s.io/klog" "k8s.io/klog"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
...@@ -249,7 +248,6 @@ type Dependencies struct { ...@@ -249,7 +248,6 @@ type Dependencies struct {
HeartbeatClient clientset.Interface HeartbeatClient clientset.Interface
OnHeartbeatFailure func() OnHeartbeatFailure func()
KubeClient clientset.Interface KubeClient clientset.Interface
CSIClient csiclientset.Interface
NodeAPIClient nodeapiclientset.Interface NodeAPIClient nodeapiclientset.Interface
Mounter mount.Interface Mounter mount.Interface
OOMAdjuster *oom.OOMAdjuster OOMAdjuster *oom.OOMAdjuster
...@@ -493,7 +491,6 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration, ...@@ -493,7 +491,6 @@ func NewMainKubelet(kubeCfg *kubeletconfiginternal.KubeletConfiguration,
hostnameOverridden: len(hostnameOverride) > 0, hostnameOverridden: len(hostnameOverride) > 0,
nodeName: nodeName, nodeName: nodeName,
kubeClient: kubeDeps.KubeClient, kubeClient: kubeDeps.KubeClient,
csiClient: kubeDeps.CSIClient,
heartbeatClient: kubeDeps.HeartbeatClient, heartbeatClient: kubeDeps.HeartbeatClient,
onRepeatedHeartbeatFailure: kubeDeps.OnHeartbeatFailure, onRepeatedHeartbeatFailure: kubeDeps.OnHeartbeatFailure,
rootDirectory: rootDirectory, rootDirectory: rootDirectory,
...@@ -898,7 +895,6 @@ type Kubelet struct { ...@@ -898,7 +895,6 @@ type Kubelet struct {
nodeName types.NodeName nodeName types.NodeName
runtimeCache kubecontainer.RuntimeCache runtimeCache kubecontainer.RuntimeCache
kubeClient clientset.Interface kubeClient clientset.Interface
csiClient csiclientset.Interface
heartbeatClient clientset.Interface heartbeatClient clientset.Interface
iptClient utilipt.Interface iptClient utilipt.Interface
rootDirectory string rootDirectory string
......
...@@ -30,7 +30,6 @@ import ( ...@@ -30,7 +30,6 @@ import (
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
cloudprovider "k8s.io/cloud-provider" cloudprovider "k8s.io/cloud-provider"
csiclientset "k8s.io/csi-api/pkg/client/clientset/versioned"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/kubelet/configmap" "k8s.io/kubernetes/pkg/kubelet/configmap"
"k8s.io/kubernetes/pkg/kubelet/container" "k8s.io/kubernetes/pkg/kubelet/container"
...@@ -123,10 +122,6 @@ func (kvh *kubeletVolumeHost) GetKubeClient() clientset.Interface { ...@@ -123,10 +122,6 @@ func (kvh *kubeletVolumeHost) GetKubeClient() clientset.Interface {
return kvh.kubelet.kubeClient return kvh.kubelet.kubeClient
} }
func (kvh *kubeletVolumeHost) GetCSIClient() csiclientset.Interface {
return kvh.kubelet.csiClient
}
func (kvh *kubeletVolumeHost) GetSubpather() subpath.Interface { func (kvh *kubeletVolumeHost) GetSubpather() subpath.Interface {
return kvh.kubelet.subpather return kvh.kubelet.subpather
} }
......
...@@ -85,6 +85,8 @@ filegroup( ...@@ -85,6 +85,8 @@ filegroup(
"//pkg/registry/scheduling/rest:all-srcs", "//pkg/registry/scheduling/rest:all-srcs",
"//pkg/registry/settings/podpreset:all-srcs", "//pkg/registry/settings/podpreset:all-srcs",
"//pkg/registry/settings/rest:all-srcs", "//pkg/registry/settings/rest:all-srcs",
"//pkg/registry/storage/csidriver:all-srcs",
"//pkg/registry/storage/csinode:all-srcs",
"//pkg/registry/storage/rest:all-srcs", "//pkg/registry/storage/rest:all-srcs",
"//pkg/registry/storage/storageclass:all-srcs", "//pkg/registry/storage/storageclass:all-srcs",
"//pkg/registry/storage/volumeattachment:all-srcs", "//pkg/registry/storage/volumeattachment:all-srcs",
......
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"strategy.go",
],
importpath = "k8s.io/kubernetes/pkg/registry/storage/csidriver",
visibility = ["//visibility:public"],
deps = [
"//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/storage:go_default_library",
"//pkg/apis/storage/validation:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//pkg/registry/storage/csidriver/storage:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = ["strategy_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/apis/storage:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
],
)
/*
Copyright 2019 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.
*/
// Package csidriver provides Registry interface and its REST
// implementation for storing csidriver api objects.
package csidriver
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["storage.go"],
importpath = "k8s.io/kubernetes/pkg/registry/storage/csidriver/storage",
visibility = ["//visibility:public"],
deps = [
"//pkg/apis/storage:go_default_library",
"//pkg/registry/storage/csidriver:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = ["storage_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/api/testapi:go_default_library",
"//pkg/apis/storage:go_default_library",
"//pkg/registry/registrytest:go_default_library",
"//staging/src/k8s.io/api/storage/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic/testing:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/storage/etcd/testing:go_default_library",
],
)
/*
Copyright 2019 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.
*/
package storage
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/generic"
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
storageapi "k8s.io/kubernetes/pkg/apis/storage"
"k8s.io/kubernetes/pkg/registry/storage/csidriver"
)
// CSIDriverStorage includes storage for CSIDrivers and all subresources
type CSIDriverStorage struct {
CSIDriver *REST
}
// REST object that will work for CSIDrivers
type REST struct {
*genericregistry.Store
}
// NewStorage returns a RESTStorage object that will work against CSIDrivers
func NewStorage(optsGetter generic.RESTOptionsGetter) *CSIDriverStorage {
store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &storageapi.CSIDriver{} },
NewListFunc: func() runtime.Object { return &storageapi.CSIDriverList{} },
DefaultQualifiedResource: storageapi.Resource("csidrivers"),
CreateStrategy: csidriver.Strategy,
UpdateStrategy: csidriver.Strategy,
DeleteStrategy: csidriver.Strategy,
ReturnDeletedObject: true,
}
options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up
}
return &CSIDriverStorage{
CSIDriver: &REST{store},
}
}
/*
Copyright 2019 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.
*/
package storage
import (
"testing"
storageapiv1beta1 "k8s.io/api/storage/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/generic"
genericregistrytest "k8s.io/apiserver/pkg/registry/generic/testing"
etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing"
"k8s.io/kubernetes/pkg/api/testapi"
storageapi "k8s.io/kubernetes/pkg/apis/storage"
"k8s.io/kubernetes/pkg/registry/registrytest"
)
func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) {
etcdStorage, server := registrytest.NewEtcdStorage(t, storageapi.GroupName)
restOptions := generic.RESTOptions{
StorageConfig: etcdStorage,
Decorator: generic.UndecoratedStorage,
DeleteCollectionWorkers: 1,
ResourcePrefix: "csidrivers",
}
csiDriverStorage := NewStorage(restOptions)
return csiDriverStorage.CSIDriver, server
}
func validNewCSIDriver(name string) *storageapi.CSIDriver {
attachRequired := true
podInfoOnMount := true
return &storageapi.CSIDriver{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: storageapi.CSIDriverSpec{
AttachRequired: &attachRequired,
PodInfoOnMount: &podInfoOnMount,
},
}
}
func TestCreate(t *testing.T) {
if *testapi.Storage.GroupVersion() != storageapiv1beta1.SchemeGroupVersion {
// skip the test for all versions exception v1beta1
return
}
storage, server := newStorage(t)
defer server.Terminate(t)
defer storage.Store.DestroyFunc()
test := genericregistrytest.New(t, storage.Store).ClusterScope()
csiDriver := validNewCSIDriver("foo")
csiDriver.ObjectMeta = metav1.ObjectMeta{GenerateName: "foo"}
attachNotRequired := false
notPodInfoOnMount := false
test.TestCreate(
// valid
csiDriver,
// invalid
&storageapi.CSIDriver{
ObjectMeta: metav1.ObjectMeta{Name: "*BadName!"},
Spec: storageapi.CSIDriverSpec{
AttachRequired: &attachNotRequired,
PodInfoOnMount: &notPodInfoOnMount,
},
},
)
}
func TestUpdate(t *testing.T) {
if *testapi.Storage.GroupVersion() != storageapiv1beta1.SchemeGroupVersion {
// skip the test for all versions exception v1beta1
return
}
storage, server := newStorage(t)
defer server.Terminate(t)
defer storage.Store.DestroyFunc()
test := genericregistrytest.New(t, storage.Store).ClusterScope()
notPodInfoOnMount := false
test.TestUpdate(
// valid
validNewCSIDriver("foo"),
//invalid update
func(obj runtime.Object) runtime.Object {
object := obj.(*storageapi.CSIDriver)
object.Spec.PodInfoOnMount = &notPodInfoOnMount
return object
},
)
}
func TestDelete(t *testing.T) {
if *testapi.Storage.GroupVersion() != storageapiv1beta1.SchemeGroupVersion {
// skip the test for all versions exception v1beta1
return
}
storage, server := newStorage(t)
defer server.Terminate(t)
defer storage.Store.DestroyFunc()
test := genericregistrytest.New(t, storage.Store).ClusterScope().ReturnDeletedObject()
test.TestDelete(validNewCSIDriver("foo"))
}
func TestGet(t *testing.T) {
if *testapi.Storage.GroupVersion() != storageapiv1beta1.SchemeGroupVersion {
// skip the test for all versions exception v1beta1
return
}
storage, server := newStorage(t)
defer server.Terminate(t)
defer storage.Store.DestroyFunc()
test := genericregistrytest.New(t, storage.Store).ClusterScope()
test.TestGet(validNewCSIDriver("foo"))
}
func TestList(t *testing.T) {
if *testapi.Storage.GroupVersion() != storageapiv1beta1.SchemeGroupVersion {
// skip the test for all versions exception v1beta1
return
}
storage, server := newStorage(t)
defer server.Terminate(t)
defer storage.Store.DestroyFunc()
test := genericregistrytest.New(t, storage.Store).ClusterScope()
test.TestList(validNewCSIDriver("foo"))
}
func TestWatch(t *testing.T) {
if *testapi.Storage.GroupVersion() != storageapiv1beta1.SchemeGroupVersion {
// skip the test for all versions exception v1beta1
return
}
storage, server := newStorage(t)
defer server.Terminate(t)
defer storage.Store.DestroyFunc()
test := genericregistrytest.New(t, storage.Store).ClusterScope()
test.TestWatch(
validNewCSIDriver("foo"),
// matching labels
[]labels.Set{},
// not matching labels
[]labels.Set{
{"foo": "bar"},
},
// matching fields
[]fields.Set{
{"metadata.name": "foo"},
},
// not matching fields
[]fields.Set{
{"metadata.name": "bar"},
},
)
}
/*
Copyright 2019 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.
*/
package csidriver
import (
"context"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/storage"
"k8s.io/kubernetes/pkg/apis/storage/validation"
)
// csiDriverStrategy implements behavior for CSIDriver objects
type csiDriverStrategy struct {
runtime.ObjectTyper
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating
// CSIDriver objects via the REST API.
var Strategy = csiDriverStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
func (csiDriverStrategy) NamespaceScoped() bool {
return false
}
// ResetBeforeCreate clears the Status field which is not allowed to be set by end users on creation.
func (csiDriverStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
}
func (csiDriverStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
csiDriver := obj.(*storage.CSIDriver)
errs := validation.ValidateCSIDriver(csiDriver)
errs = append(errs, validation.ValidateCSIDriver(csiDriver)...)
return errs
}
// Canonicalize normalizes the object after validation.
func (csiDriverStrategy) Canonicalize(obj runtime.Object) {
}
func (csiDriverStrategy) AllowCreateOnUpdate() bool {
return false
}
// PrepareForUpdate sets the Status fields which is not allowed to be set by an end user updating a CSIDriver
func (csiDriverStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
}
func (csiDriverStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
newCSIDriverObj := obj.(*storage.CSIDriver)
oldCSIDriverObj := old.(*storage.CSIDriver)
errorList := validation.ValidateCSIDriver(newCSIDriverObj)
return append(errorList, validation.ValidateCSIDriverUpdate(newCSIDriverObj, oldCSIDriverObj)...)
}
func (csiDriverStrategy) AllowUnconditionalUpdate() bool {
return false
}
/*
Copyright 2019 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.
*/
package csidriver
import (
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/validation/field"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/kubernetes/pkg/apis/storage"
)
func getValidCSIDriver(name string) *storage.CSIDriver {
attachRequired := true
podInfoOnMount := true
return &storage.CSIDriver{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: storage.CSIDriverSpec{
AttachRequired: &attachRequired,
PodInfoOnMount: &podInfoOnMount,
},
}
}
func TestCSIDriverStrategy(t *testing.T) {
ctx := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{
APIGroup: "storage.k8s.io",
APIVersion: "v1beta1",
Resource: "csidrivers",
})
if Strategy.NamespaceScoped() {
t.Errorf("CSIDriver must not be namespace scoped")
}
if Strategy.AllowCreateOnUpdate() {
t.Errorf("CSIDriver should not allow create on update")
}
csiDriver := getValidCSIDriver("valid-csidriver")
Strategy.PrepareForCreate(ctx, csiDriver)
errs := Strategy.Validate(ctx, csiDriver)
if len(errs) != 0 {
t.Errorf("unexpected error validating %v", errs)
}
// Update of spec is disallowed
newCSIDriver := csiDriver.DeepCopy()
attachNotRequired := false
newCSIDriver.Spec.AttachRequired = &attachNotRequired
Strategy.PrepareForUpdate(ctx, newCSIDriver, csiDriver)
errs = Strategy.ValidateUpdate(ctx, newCSIDriver, csiDriver)
if len(errs) == 0 {
t.Errorf("Expected a validation error")
}
}
func TestCSIDriverValidation(t *testing.T) {
attachRequired := true
notAttachRequired := false
podInfoOnMount := true
notPodInfoOnMount := false
tests := []struct {
name string
csiDriver *storage.CSIDriver
expectError bool
}{
{
"valid csidriver",
getValidCSIDriver("foo"),
false,
},
{
"true PodInfoOnMount and AttachRequired",
&storage.CSIDriver{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
Spec: storage.CSIDriverSpec{
AttachRequired: &attachRequired,
PodInfoOnMount: &podInfoOnMount,
},
},
false,
},
{
"false PodInfoOnMount and AttachRequired",
&storage.CSIDriver{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
Spec: storage.CSIDriverSpec{
AttachRequired: &notAttachRequired,
PodInfoOnMount: &notPodInfoOnMount,
},
},
false,
},
{
"invalid driver name",
&storage.CSIDriver{
ObjectMeta: metav1.ObjectMeta{
Name: "*foo#",
},
Spec: storage.CSIDriverSpec{
AttachRequired: &attachRequired,
PodInfoOnMount: &podInfoOnMount,
},
},
true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
testValidation := func(csiDriver *storage.CSIDriver, apiVersion string) field.ErrorList {
ctx := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{
APIGroup: "storage.k8s.io",
APIVersion: "v1beta1",
Resource: "csidrivers",
})
return Strategy.Validate(ctx, csiDriver)
}
betaErr := testValidation(test.csiDriver, "v1beta1")
if len(betaErr) > 0 && !test.expectError {
t.Errorf("Validation of v1beta1 object failed: %+v", betaErr)
}
if len(betaErr) == 0 && test.expectError {
t.Errorf("Validation of v1beta1 object unexpectedly succeeded")
}
})
}
}
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"strategy.go",
],
importpath = "k8s.io/kubernetes/pkg/registry/storage/csinode",
visibility = ["//visibility:public"],
deps = [
"//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/storage:go_default_library",
"//pkg/apis/storage/validation:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//pkg/registry/storage/csinode/storage:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = ["strategy_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/apis/storage:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
],
)
/*
Copyright 2019 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.
*/
// Package csinode provides Registry interface and its REST
// implementation for storing csinode api objects.
package csinode
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["storage.go"],
importpath = "k8s.io/kubernetes/pkg/registry/storage/csinode/storage",
visibility = ["//visibility:public"],
deps = [
"//pkg/apis/storage:go_default_library",
"//pkg/registry/storage/csinode:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
go_test(
name = "go_default_test",
srcs = ["storage_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/api/testapi:go_default_library",
"//pkg/apis/storage:go_default_library",
"//pkg/registry/registrytest:go_default_library",
"//staging/src/k8s.io/api/storage/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/fields:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/labels:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic/testing:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/storage/etcd/testing:go_default_library",
],
)
/*
Copyright 2019 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.
*/
package storage
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/generic"
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
storageapi "k8s.io/kubernetes/pkg/apis/storage"
"k8s.io/kubernetes/pkg/registry/storage/csinode"
)
// CSINodeStorage includes storage for CSINodes and all subresources
type CSINodeStorage struct {
CSINode *REST
}
// REST object that will work for CSINodes
type REST struct {
*genericregistry.Store
}
// NewStorage returns a RESTStorage object that will work against CSINodes
func NewStorage(optsGetter generic.RESTOptionsGetter) *CSINodeStorage {
store := &genericregistry.Store{
NewFunc: func() runtime.Object { return &storageapi.CSINode{} },
NewListFunc: func() runtime.Object { return &storageapi.CSINodeList{} },
DefaultQualifiedResource: storageapi.Resource("csinodes"),
CreateStrategy: csinode.Strategy,
UpdateStrategy: csinode.Strategy,
DeleteStrategy: csinode.Strategy,
ReturnDeletedObject: true,
}
options := &generic.StoreOptions{RESTOptions: optsGetter}
if err := store.CompleteWithOptions(options); err != nil {
panic(err) // TODO: Propagate error up
}
return &CSINodeStorage{
CSINode: &REST{store},
}
}
/*
Copyright 2019 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.
*/
package storage
import (
"testing"
storageapiv1beta1 "k8s.io/api/storage/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/registry/generic"
genericregistrytest "k8s.io/apiserver/pkg/registry/generic/testing"
etcdtesting "k8s.io/apiserver/pkg/storage/etcd/testing"
"k8s.io/kubernetes/pkg/api/testapi"
storageapi "k8s.io/kubernetes/pkg/apis/storage"
"k8s.io/kubernetes/pkg/registry/registrytest"
)
func newStorage(t *testing.T) (*REST, *etcdtesting.EtcdTestServer) {
etcdStorage, server := registrytest.NewEtcdStorage(t, storageapi.GroupName)
restOptions := generic.RESTOptions{
StorageConfig: etcdStorage,
Decorator: generic.UndecoratedStorage,
DeleteCollectionWorkers: 1,
ResourcePrefix: "csinodes",
}
csiNodeStorage := NewStorage(restOptions)
return csiNodeStorage.CSINode, server
}
func validNewCSINode(name string) *storageapi.CSINode {
return &storageapi.CSINode{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: storageapi.CSINodeSpec{
Drivers: []storageapi.CSINodeDriver{
{
Name: "valid-driver-name",
NodeID: "valid-node",
TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
},
},
},
}
}
func TestCreate(t *testing.T) {
if *testapi.Storage.GroupVersion() != storageapiv1beta1.SchemeGroupVersion {
// skip the test for all versions exception v1beta1
return
}
storage, server := newStorage(t)
defer server.Terminate(t)
defer storage.Store.DestroyFunc()
test := genericregistrytest.New(t, storage.Store).ClusterScope()
csiNode := validNewCSINode("foo")
csiNode.ObjectMeta = metav1.ObjectMeta{GenerateName: "foo"}
test.TestCreate(
// valid
csiNode,
// invalid
&storageapi.CSINode{
ObjectMeta: metav1.ObjectMeta{Name: "*BadName!"},
Spec: storageapi.CSINodeSpec{
Drivers: []storageapi.CSINodeDriver{
{
Name: "invalid-name-!@#$%^&*()",
NodeID: "invalid-node-!@#$%^&*()",
TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
},
},
},
},
)
}
func TestUpdate(t *testing.T) {
if *testapi.Storage.GroupVersion() != storageapiv1beta1.SchemeGroupVersion {
// skip the test for all versions exception v1beta1
return
}
storage, server := newStorage(t)
defer server.Terminate(t)
defer storage.Store.DestroyFunc()
test := genericregistrytest.New(t, storage.Store).ClusterScope()
test.TestUpdate(
// valid
validNewCSINode("foo"),
// we allow status field to be set in v1beta1
func(obj runtime.Object) runtime.Object {
object := obj.(*storageapi.CSINode)
//object.Status = *getCSINodeStatus()
return object
},
//invalid update
func(obj runtime.Object) runtime.Object {
object := obj.(*storageapi.CSINode)
object.Spec.Drivers[0].Name = "invalid-name-!@#$%^&*()"
return object
},
)
}
func TestDelete(t *testing.T) {
if *testapi.Storage.GroupVersion() != storageapiv1beta1.SchemeGroupVersion {
// skip the test for all versions exception v1beta1
return
}
storage, server := newStorage(t)
defer server.Terminate(t)
defer storage.Store.DestroyFunc()
test := genericregistrytest.New(t, storage.Store).ClusterScope().ReturnDeletedObject()
test.TestDelete(validNewCSINode("foo"))
}
func TestGet(t *testing.T) {
if *testapi.Storage.GroupVersion() != storageapiv1beta1.SchemeGroupVersion {
// skip the test for all versions exception v1beta1
return
}
storage, server := newStorage(t)
defer server.Terminate(t)
defer storage.Store.DestroyFunc()
test := genericregistrytest.New(t, storage.Store).ClusterScope()
test.TestGet(validNewCSINode("foo"))
}
func TestList(t *testing.T) {
if *testapi.Storage.GroupVersion() != storageapiv1beta1.SchemeGroupVersion {
// skip the test for all versions exception v1beta1
return
}
storage, server := newStorage(t)
defer server.Terminate(t)
defer storage.Store.DestroyFunc()
test := genericregistrytest.New(t, storage.Store).ClusterScope()
test.TestList(validNewCSINode("foo"))
}
func TestWatch(t *testing.T) {
if *testapi.Storage.GroupVersion() != storageapiv1beta1.SchemeGroupVersion {
// skip the test for all versions exception v1beta1
return
}
storage, server := newStorage(t)
defer server.Terminate(t)
defer storage.Store.DestroyFunc()
test := genericregistrytest.New(t, storage.Store).ClusterScope()
test.TestWatch(
validNewCSINode("foo"),
// matching labels
[]labels.Set{},
// not matching labels
[]labels.Set{
{"foo": "bar"},
},
// matching fields
[]fields.Set{
{"metadata.name": "foo"},
},
// not matching fields
[]fields.Set{
{"metadata.name": "bar"},
},
)
}
/*
Copyright 2019 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.
*/
package csinode
import (
"context"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/apiserver/pkg/storage/names"
"k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/apis/storage"
"k8s.io/kubernetes/pkg/apis/storage/validation"
)
// csiNodeStrategy implements behavior for CSINode objects
type csiNodeStrategy struct {
runtime.ObjectTyper
names.NameGenerator
}
// Strategy is the default logic that applies when creating and updating
// CSINode objects via the REST API.
var Strategy = csiNodeStrategy{legacyscheme.Scheme, names.SimpleNameGenerator}
func (csiNodeStrategy) NamespaceScoped() bool {
return false
}
// ResetBeforeCreate clears the Status field which is not allowed to be set by end users on creation.
func (csiNodeStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
}
func (csiNodeStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
csiNode := obj.(*storage.CSINode)
errs := validation.ValidateCSINode(csiNode)
errs = append(errs, validation.ValidateCSINode(csiNode)...)
return errs
}
// Canonicalize normalizes the object after validation.
func (csiNodeStrategy) Canonicalize(obj runtime.Object) {
}
func (csiNodeStrategy) AllowCreateOnUpdate() bool {
return false
}
// PrepareForUpdate sets the Status fields which is not allowed to be set by an end user updating a CSINode
func (csiNodeStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
}
func (csiNodeStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
newCSINodeObj := obj.(*storage.CSINode)
oldCSINodeObj := old.(*storage.CSINode)
errorList := validation.ValidateCSINode(newCSINodeObj)
return append(errorList, validation.ValidateCSINodeUpdate(newCSINodeObj, oldCSINodeObj)...)
}
func (csiNodeStrategy) AllowUnconditionalUpdate() bool {
return false
}
/*
Copyright 2019 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.
*/
package csinode
import (
"testing"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/validation/field"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/kubernetes/pkg/apis/storage"
)
func getValidCSINode(name string) *storage.CSINode {
return &storage.CSINode{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: storage.CSINodeSpec{
Drivers: []storage.CSINodeDriver{
{
Name: "valid-driver-name",
NodeID: "valid-node",
TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
},
},
},
}
}
func TestCSINodeStrategy(t *testing.T) {
ctx := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{
APIGroup: "storage.k8s.io",
APIVersion: "v1beta1",
Resource: "csinodes",
})
if Strategy.NamespaceScoped() {
t.Errorf("CSINode must not be namespace scoped")
}
if Strategy.AllowCreateOnUpdate() {
t.Errorf("CSINode should not allow create on update")
}
csiNode := getValidCSINode("valid-csinode")
Strategy.PrepareForCreate(ctx, csiNode)
errs := Strategy.Validate(ctx, csiNode)
if len(errs) != 0 {
t.Errorf("unexpected error validating %v", errs)
}
// Update of spec is allowed
newCSINode := csiNode.DeepCopy()
newCSINode.Spec.Drivers[0].NodeID = "valid-node-2"
Strategy.PrepareForUpdate(ctx, newCSINode, csiNode)
errs = Strategy.ValidateUpdate(ctx, newCSINode, csiNode)
if len(errs) == 0 {
t.Errorf("expected validation error")
}
}
func TestCSINodeValidation(t *testing.T) {
tests := []struct {
name string
csiNode *storage.CSINode
expectError bool
}{
{
"valid csinode",
getValidCSINode("foo"),
false,
},
{
"invalid driver name",
&storage.CSINode{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
Spec: storage.CSINodeSpec{
Drivers: []storage.CSINodeDriver{
{
Name: "$csi-driver@",
NodeID: "valid-node",
TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
},
},
},
},
true,
},
{
"empty node id",
&storage.CSINode{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
Spec: storage.CSINodeSpec{
Drivers: []storage.CSINodeDriver{
{
Name: "valid-driver-name",
NodeID: "",
TopologyKeys: []string{"company.com/zone1", "company.com/zone2"},
},
},
},
},
true,
},
{
"invalid topology keys",
&storage.CSINode{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
Spec: storage.CSINodeSpec{
Drivers: []storage.CSINodeDriver{
{
Name: "valid-driver-name",
NodeID: "valid-node",
TopologyKeys: []string{"company.com/zone1", ""},
},
},
},
},
true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
testValidation := func(csiNode *storage.CSINode, apiVersion string) field.ErrorList {
ctx := genericapirequest.WithRequestInfo(genericapirequest.NewContext(), &genericapirequest.RequestInfo{
APIGroup: "storage.k8s.io",
APIVersion: "v1beta1",
Resource: "csinodes",
})
return Strategy.Validate(ctx, csiNode)
}
betaErr := testValidation(test.csiNode, "v1beta1")
if len(betaErr) > 0 && !test.expectError {
t.Errorf("Validation of v1beta1 object failed: %+v", betaErr)
}
if len(betaErr) == 0 && test.expectError {
t.Errorf("Validation of v1beta1 object unexpectedly succeeded")
}
})
}
}
...@@ -12,6 +12,9 @@ go_library( ...@@ -12,6 +12,9 @@ go_library(
deps = [ deps = [
"//pkg/api/legacyscheme:go_default_library", "//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/storage:go_default_library", "//pkg/apis/storage:go_default_library",
"//pkg/features:go_default_library",
"//pkg/registry/storage/csidriver/storage:go_default_library",
"//pkg/registry/storage/csinode/storage:go_default_library",
"//pkg/registry/storage/storageclass/storage:go_default_library", "//pkg/registry/storage/storageclass/storage:go_default_library",
"//pkg/registry/storage/volumeattachment/storage:go_default_library", "//pkg/registry/storage/volumeattachment/storage:go_default_library",
"//staging/src/k8s.io/api/storage/v1:go_default_library", "//staging/src/k8s.io/api/storage/v1:go_default_library",
...@@ -21,6 +24,7 @@ go_library( ...@@ -21,6 +24,7 @@ go_library(
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library", "//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/server:go_default_library", "//staging/src/k8s.io/apiserver/pkg/server:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/server/storage:go_default_library", "//staging/src/k8s.io/apiserver/pkg/server/storage:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
], ],
) )
......
...@@ -24,8 +24,12 @@ import ( ...@@ -24,8 +24,12 @@ import (
"k8s.io/apiserver/pkg/registry/rest" "k8s.io/apiserver/pkg/registry/rest"
genericapiserver "k8s.io/apiserver/pkg/server" genericapiserver "k8s.io/apiserver/pkg/server"
serverstorage "k8s.io/apiserver/pkg/server/storage" serverstorage "k8s.io/apiserver/pkg/server/storage"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
storageapi "k8s.io/kubernetes/pkg/apis/storage" storageapi "k8s.io/kubernetes/pkg/apis/storage"
"k8s.io/kubernetes/pkg/features"
csidriverstore "k8s.io/kubernetes/pkg/registry/storage/csidriver/storage"
csinodestore "k8s.io/kubernetes/pkg/registry/storage/csinode/storage"
storageclassstore "k8s.io/kubernetes/pkg/registry/storage/storageclass/storage" storageclassstore "k8s.io/kubernetes/pkg/registry/storage/storageclass/storage"
volumeattachmentstore "k8s.io/kubernetes/pkg/registry/storage/volumeattachment/storage" volumeattachmentstore "k8s.io/kubernetes/pkg/registry/storage/volumeattachment/storage"
) )
...@@ -70,6 +74,18 @@ func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorag ...@@ -70,6 +74,18 @@ func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorag
volumeAttachmentStorage := volumeattachmentstore.NewStorage(restOptionsGetter) volumeAttachmentStorage := volumeattachmentstore.NewStorage(restOptionsGetter)
storage["volumeattachments"] = volumeAttachmentStorage.VolumeAttachment storage["volumeattachments"] = volumeAttachmentStorage.VolumeAttachment
// register csinodes if CSINodeInfo feature gate is enabled
if utilfeature.DefaultFeatureGate.Enabled(features.CSINodeInfo) {
csiNodeStorage := csinodestore.NewStorage(restOptionsGetter)
storage["csinodes"] = csiNodeStorage.CSINode
}
// register csidrivers if CSIDriverRegistry feature gate is enabled
if utilfeature.DefaultFeatureGate.Enabled(features.CSIDriverRegistry) {
csiDriverStorage := csidriverstore.NewStorage(restOptionsGetter)
storage["csidrivers"] = csiDriverStorage.CSIDriver
}
return storage return storage
} }
......
...@@ -32,7 +32,6 @@ go_library( ...@@ -32,7 +32,6 @@ go_library(
"//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/tools/record:go_default_library", "//staging/src/k8s.io/client-go/tools/record:go_default_library",
"//staging/src/k8s.io/cloud-provider:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/client/clientset/versioned:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
], ],
) )
......
...@@ -28,10 +28,10 @@ go_library( ...@@ -28,10 +28,10 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library",
"//staging/src/k8s.io/client-go/informers/storage/v1beta1:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/client/informers/externalversions:go_default_library", "//staging/src/k8s.io/client-go/listers/storage/v1beta1:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/client/informers/externalversions/csi/v1alpha1:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/client/listers/csi/v1alpha1:go_default_library",
"//vendor/github.com/container-storage-interface/spec/lib/go/csi:go_default_library", "//vendor/github.com/container-storage-interface/spec/lib/go/csi:go_default_library",
"//vendor/google.golang.org/grpc:go_default_library", "//vendor/google.golang.org/grpc:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
...@@ -58,6 +58,7 @@ go_test( ...@@ -58,6 +58,7 @@ go_test(
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/api/storage/v1:go_default_library", "//staging/src/k8s.io/api/storage/v1:go_default_library",
"//staging/src/k8s.io/api/storage/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
...@@ -71,8 +72,6 @@ go_test( ...@@ -71,8 +72,6 @@ go_test(
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
"//staging/src/k8s.io/client-go/testing:go_default_library", "//staging/src/k8s.io/client-go/testing:go_default_library",
"//staging/src/k8s.io/client-go/util/testing:go_default_library", "//staging/src/k8s.io/client-go/util/testing:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/apis/csi/v1alpha1:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/client/clientset/versioned/fake:go_default_library",
"//vendor/github.com/container-storage-interface/spec/lib/go/csi:go_default_library", "//vendor/github.com/container-storage-interface/spec/lib/go/csi:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
], ],
......
...@@ -37,7 +37,6 @@ import ( ...@@ -37,7 +37,6 @@ import (
fakeclient "k8s.io/client-go/kubernetes/fake" fakeclient "k8s.io/client-go/kubernetes/fake"
core "k8s.io/client-go/testing" core "k8s.io/client-go/testing"
utiltesting "k8s.io/client-go/util/testing" utiltesting "k8s.io/client-go/util/testing"
fakecsi "k8s.io/csi-api/pkg/client/clientset/versioned/fake"
"k8s.io/klog" "k8s.io/klog"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
...@@ -236,12 +235,12 @@ func TestAttacherWithCSIDriver(t *testing.T) { ...@@ -236,12 +235,12 @@ func TestAttacherWithCSIDriver(t *testing.T) {
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
fakeCSIClient := fakecsi.NewSimpleClientset( fakeClient := fakeclient.NewSimpleClientset(
getCSIDriver("not-attachable", nil, &bFalse), getCSIDriver("not-attachable", nil, &bFalse),
getCSIDriver("attachable", nil, &bTrue), getCSIDriver("attachable", nil, &bTrue),
getCSIDriver("nil", nil, nil), getCSIDriver("nil", nil, nil),
) )
plug, fakeWatcher, tmpDir, _ := newTestWatchPlugin(t, fakeCSIClient) plug, fakeWatcher, tmpDir, _ := newTestWatchPlugin(t, fakeClient)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
attacher, err := plug.NewAttacher() attacher, err := plug.NewAttacher()
...@@ -274,10 +273,10 @@ func TestAttacherWithCSIDriver(t *testing.T) { ...@@ -274,10 +273,10 @@ func TestAttacherWithCSIDriver(t *testing.T) {
t.Errorf("Attach() failed: %s", err) t.Errorf("Attach() failed: %s", err)
} }
if test.expectVolumeAttachment && attachID == "" { if test.expectVolumeAttachment && attachID == "" {
t.Errorf("Epected attachID, got nothing") t.Errorf("Expected attachID, got nothing")
} }
if !test.expectVolumeAttachment && attachID != "" { if !test.expectVolumeAttachment && attachID != "" {
t.Errorf("Epected empty attachID, got %q", attachID) t.Errorf("Expected empty attachID, got %q", attachID)
} }
}) })
} }
...@@ -318,12 +317,12 @@ func TestAttacherWaitForVolumeAttachmentWithCSIDriver(t *testing.T) { ...@@ -318,12 +317,12 @@ func TestAttacherWaitForVolumeAttachmentWithCSIDriver(t *testing.T) {
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
fakeCSIClient := fakecsi.NewSimpleClientset( fakeClient := fakeclient.NewSimpleClientset(
getCSIDriver("not-attachable", nil, &bFalse), getCSIDriver("not-attachable", nil, &bFalse),
getCSIDriver("attachable", nil, &bTrue), getCSIDriver("attachable", nil, &bTrue),
getCSIDriver("nil", nil, nil), getCSIDriver("nil", nil, nil),
) )
plug, tmpDir := newTestPlugin(t, nil, fakeCSIClient) plug, tmpDir := newTestPlugin(t, fakeClient)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
attacher, err := plug.NewAttacher() attacher, err := plug.NewAttacher()
...@@ -519,7 +518,7 @@ func TestAttacherWaitForVolumeAttachment(t *testing.T) { ...@@ -519,7 +518,7 @@ func TestAttacherWaitForVolumeAttachment(t *testing.T) {
} }
func TestAttacherVolumesAreAttached(t *testing.T) { func TestAttacherVolumesAreAttached(t *testing.T) {
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
attacher, err := plug.NewAttacher() attacher, err := plug.NewAttacher()
...@@ -981,23 +980,20 @@ func TestAttacherUnmountDevice(t *testing.T) { ...@@ -981,23 +980,20 @@ func TestAttacherUnmountDevice(t *testing.T) {
} }
// create a plugin mgr to load plugins and setup a fake client // create a plugin mgr to load plugins and setup a fake client
func newTestWatchPlugin(t *testing.T, csiClient *fakecsi.Clientset) (*csiPlugin, *watch.RaceFreeFakeWatcher, string, *fakeclient.Clientset) { func newTestWatchPlugin(t *testing.T, fakeClient *fakeclient.Clientset) (*csiPlugin, *watch.RaceFreeFakeWatcher, string, *fakeclient.Clientset) {
tmpDir, err := utiltesting.MkTmpdir("csi-test") tmpDir, err := utiltesting.MkTmpdir("csi-test")
if err != nil { if err != nil {
t.Fatalf("can't create temp dir: %v", err) t.Fatalf("can't create temp dir: %v", err)
} }
fakeClient := fakeclient.NewSimpleClientset() if fakeClient == nil {
fakeWatcher := watch.NewRaceFreeFake() fakeClient = fakeclient.NewSimpleClientset()
fakeClient.Fake.PrependWatchReactor("*", core.DefaultWatchReactor(fakeWatcher, nil))
fakeClient.Fake.WatchReactionChain = fakeClient.Fake.WatchReactionChain[:1]
if csiClient == nil {
csiClient = fakecsi.NewSimpleClientset()
} }
fakeWatcher := watch.NewRaceFreeFake()
fakeClient.Fake.AddWatchReactor("*", core.DefaultWatchReactor(fakeWatcher, nil))
host := volumetest.NewFakeVolumeHostWithCSINodeName( host := volumetest.NewFakeVolumeHostWithCSINodeName(
tmpDir, tmpDir,
fakeClient, fakeClient,
csiClient,
nil, nil,
"node", "node",
) )
......
...@@ -52,7 +52,7 @@ func prepareBlockMapperTest(plug *csiPlugin, specVolumeName string, t *testing.T ...@@ -52,7 +52,7 @@ func prepareBlockMapperTest(plug *csiPlugin, specVolumeName string, t *testing.T
func TestBlockMapperGetGlobalMapPath(t *testing.T) { func TestBlockMapperGetGlobalMapPath(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
// TODO (vladimirvivien) specName with slashes will not work // TODO (vladimirvivien) specName with slashes will not work
...@@ -93,7 +93,7 @@ func TestBlockMapperGetGlobalMapPath(t *testing.T) { ...@@ -93,7 +93,7 @@ func TestBlockMapperGetGlobalMapPath(t *testing.T) {
func TestBlockMapperGetStagingPath(t *testing.T) { func TestBlockMapperGetStagingPath(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
testCases := []struct { testCases := []struct {
...@@ -130,7 +130,7 @@ func TestBlockMapperGetStagingPath(t *testing.T) { ...@@ -130,7 +130,7 @@ func TestBlockMapperGetStagingPath(t *testing.T) {
func TestBlockMapperGetPublishPath(t *testing.T) { func TestBlockMapperGetPublishPath(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
testCases := []struct { testCases := []struct {
...@@ -167,7 +167,7 @@ func TestBlockMapperGetPublishPath(t *testing.T) { ...@@ -167,7 +167,7 @@ func TestBlockMapperGetPublishPath(t *testing.T) {
func TestBlockMapperGetDeviceMapPath(t *testing.T) { func TestBlockMapperGetDeviceMapPath(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
testCases := []struct { testCases := []struct {
...@@ -208,14 +208,13 @@ func TestBlockMapperGetDeviceMapPath(t *testing.T) { ...@@ -208,14 +208,13 @@ func TestBlockMapperGetDeviceMapPath(t *testing.T) {
func TestBlockMapperSetupDevice(t *testing.T) { func TestBlockMapperSetupDevice(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
fakeClient := fakeclient.NewSimpleClientset() fakeClient := fakeclient.NewSimpleClientset()
host := volumetest.NewFakeVolumeHostWithCSINodeName( host := volumetest.NewFakeVolumeHostWithCSINodeName(
tmpDir, tmpDir,
fakeClient, fakeClient,
nil, nil,
nil,
"fakeNode", "fakeNode",
) )
plug.host = host plug.host = host
...@@ -275,14 +274,13 @@ func TestBlockMapperSetupDevice(t *testing.T) { ...@@ -275,14 +274,13 @@ func TestBlockMapperSetupDevice(t *testing.T) {
func TestBlockMapperMapDevice(t *testing.T) { func TestBlockMapperMapDevice(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
fakeClient := fakeclient.NewSimpleClientset() fakeClient := fakeclient.NewSimpleClientset()
host := volumetest.NewFakeVolumeHostWithCSINodeName( host := volumetest.NewFakeVolumeHostWithCSINodeName(
tmpDir, tmpDir,
fakeClient, fakeClient,
nil, nil,
nil,
"fakeNode", "fakeNode",
) )
plug.host = host plug.host = host
...@@ -358,14 +356,13 @@ func TestBlockMapperMapDevice(t *testing.T) { ...@@ -358,14 +356,13 @@ func TestBlockMapperMapDevice(t *testing.T) {
func TestBlockMapperTearDownDevice(t *testing.T) { func TestBlockMapperTearDownDevice(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
fakeClient := fakeclient.NewSimpleClientset() fakeClient := fakeclient.NewSimpleClientset()
host := volumetest.NewFakeVolumeHostWithCSINodeName( host := volumetest.NewFakeVolumeHostWithCSINodeName(
tmpDir, tmpDir,
fakeClient, fakeClient,
nil, nil,
nil,
"fakeNode", "fakeNode",
) )
plug.host = host plug.host = host
......
...@@ -50,7 +50,6 @@ var ( ...@@ -50,7 +50,6 @@ var (
"nodeName", "nodeName",
"attachmentID", "attachmentID",
} }
currentPodInfoMountVersion = "v1"
) )
type csiMountMgr struct { type csiMountMgr struct {
...@@ -247,8 +246,8 @@ func (c *csiMountMgr) podAttributes() (map[string]string, error) { ...@@ -247,8 +246,8 @@ func (c *csiMountMgr) podAttributes() (map[string]string, error) {
return nil, err return nil, err
} }
// if PodInfoOnMountVersion is not set or not v1 we do not set pod attributes // if PodInfoOnMount is not set or false we do not set pod attributes
if csiDriver.Spec.PodInfoOnMountVersion == nil || *csiDriver.Spec.PodInfoOnMountVersion != currentPodInfoMountVersion { if csiDriver.Spec.PodInfoOnMount == nil || *csiDriver.Spec.PodInfoOnMount == false {
klog.V(4).Infof(log("CSIDriver %q does not require pod information", c.driverName)) klog.V(4).Infof(log("CSIDriver %q does not require pod information", c.driverName))
return nil, nil return nil, nil
} }
......
...@@ -29,14 +29,13 @@ import ( ...@@ -29,14 +29,13 @@ import (
api "k8s.io/api/core/v1" api "k8s.io/api/core/v1"
storage "k8s.io/api/storage/v1" storage "k8s.io/api/storage/v1"
storagev1beta1 "k8s.io/api/storage/v1beta1"
meta "k8s.io/apimachinery/pkg/apis/meta/v1" meta "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
fakeclient "k8s.io/client-go/kubernetes/fake" fakeclient "k8s.io/client-go/kubernetes/fake"
csiapi "k8s.io/csi-api/pkg/apis/csi/v1alpha1"
fakecsi "k8s.io/csi-api/pkg/client/clientset/versioned/fake"
"k8s.io/klog" "k8s.io/klog"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
...@@ -53,7 +52,7 @@ var ( ...@@ -53,7 +52,7 @@ var (
) )
func TestMounterGetPath(t *testing.T) { func TestMounterGetPath(t *testing.T) {
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
// TODO (vladimirvivien) specName with slashes will not work // TODO (vladimirvivien) specName with slashes will not work
...@@ -142,17 +141,17 @@ func MounterSetUpTests(t *testing.T, podInfoEnabled bool) { ...@@ -142,17 +141,17 @@ func MounterSetUpTests(t *testing.T, podInfoEnabled bool) {
}, },
} }
emptyPodMountInfoVersion := "" noPodMountInfo := false
currentPodInfoMount := true
for _, test := range tests { for _, test := range tests {
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
klog.Infof("Starting test %s", test.name) klog.Infof("Starting test %s", test.name)
fakeClient := fakeclient.NewSimpleClientset() fakeClient := fakeclient.NewSimpleClientset(
fakeCSIClient := fakecsi.NewSimpleClientset( getCSIDriver("no-info", &noPodMountInfo, nil),
getCSIDriver("no-info", &emptyPodMountInfoVersion, nil), getCSIDriver("info", &currentPodInfoMount, nil),
getCSIDriver("info", &currentPodInfoMountVersion, nil),
getCSIDriver("nil", nil, nil), getCSIDriver("nil", nil, nil),
) )
plug, tmpDir := newTestPlugin(t, fakeClient, fakeCSIClient) plug, tmpDir := newTestPlugin(t, fakeClient)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
if utilfeature.DefaultFeatureGate.Enabled(features.CSIDriverRegistry) { if utilfeature.DefaultFeatureGate.Enabled(features.CSIDriverRegistry) {
...@@ -269,7 +268,7 @@ func TestMounterSetUp(t *testing.T) { ...@@ -269,7 +268,7 @@ func TestMounterSetUp(t *testing.T) {
} }
func TestMounterSetUpWithFSGroup(t *testing.T) { func TestMounterSetUpWithFSGroup(t *testing.T) {
fakeClient := fakeclient.NewSimpleClientset() fakeClient := fakeclient.NewSimpleClientset()
plug, tmpDir := newTestPlugin(t, fakeClient, nil) plug, tmpDir := newTestPlugin(t, fakeClient)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
testCases := []struct { testCases := []struct {
...@@ -393,7 +392,7 @@ func TestMounterSetUpWithFSGroup(t *testing.T) { ...@@ -393,7 +392,7 @@ func TestMounterSetUpWithFSGroup(t *testing.T) {
} }
func TestUnmounterTeardown(t *testing.T) { func TestUnmounterTeardown(t *testing.T) {
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
registerFakePlugin(testDriver, "endpoint", []string{"1.0.0"}, t) registerFakePlugin(testDriver, "endpoint", []string{"1.0.0"}, t)
pv := makeTestPV("test-pv", 10, testDriver, testVol) pv := makeTestPV("test-pv", 10, testDriver, testVol)
...@@ -443,7 +442,7 @@ func TestUnmounterTeardown(t *testing.T) { ...@@ -443,7 +442,7 @@ func TestUnmounterTeardown(t *testing.T) {
} }
func TestSaveVolumeData(t *testing.T) { func TestSaveVolumeData(t *testing.T) {
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
testCases := []struct { testCases := []struct {
name string name string
...@@ -490,14 +489,14 @@ func TestSaveVolumeData(t *testing.T) { ...@@ -490,14 +489,14 @@ func TestSaveVolumeData(t *testing.T) {
} }
} }
func getCSIDriver(name string, podInfoMountVersion *string, attachable *bool) *csiapi.CSIDriver { func getCSIDriver(name string, podInfoMount *bool, attachable *bool) *storagev1beta1.CSIDriver {
return &csiapi.CSIDriver{ return &storagev1beta1.CSIDriver{
ObjectMeta: meta.ObjectMeta{ ObjectMeta: meta.ObjectMeta{
Name: name, Name: name,
}, },
Spec: csiapi.CSIDriverSpec{ Spec: storagev1beta1.CSIDriverSpec{
PodInfoOnMountVersion: podInfoMountVersion, PodInfoOnMount: podInfoMount,
AttachRequired: attachable, AttachRequired: attachable,
}, },
} }
} }
...@@ -36,10 +36,10 @@ import ( ...@@ -36,10 +36,10 @@ import (
utilversion "k8s.io/apimachinery/pkg/util/version" utilversion "k8s.io/apimachinery/pkg/util/version"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
csiapiinformer "k8s.io/client-go/informers"
csiinformer "k8s.io/client-go/informers/storage/v1beta1"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
csiapiinformer "k8s.io/csi-api/pkg/client/informers/externalversions" csilister "k8s.io/client-go/listers/storage/v1beta1"
csiinformer "k8s.io/csi-api/pkg/client/informers/externalversions/csi/v1alpha1"
csilister "k8s.io/csi-api/pkg/client/listers/csi/v1alpha1"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/csi/nodeinfomanager" "k8s.io/kubernetes/pkg/volume/csi/nodeinfomanager"
...@@ -205,16 +205,15 @@ func (p *csiPlugin) Init(host volume.VolumeHost) error { ...@@ -205,16 +205,15 @@ func (p *csiPlugin) Init(host volume.VolumeHost) error {
p.host = host p.host = host
if utilfeature.DefaultFeatureGate.Enabled(features.CSIDriverRegistry) { if utilfeature.DefaultFeatureGate.Enabled(features.CSIDriverRegistry) {
csiClient := host.GetCSIClient() csiClient := host.GetKubeClient()
if csiClient == nil { if csiClient == nil {
klog.Warning("The client for CSI Custom Resources is not available, skipping informer initialization") return errors.New("unable to get Kubernetes client")
} else {
// Start informer for CSIDrivers.
factory := csiapiinformer.NewSharedInformerFactory(csiClient, csiResyncPeriod)
p.csiDriverInformer = factory.Csi().V1alpha1().CSIDrivers()
p.csiDriverLister = p.csiDriverInformer.Lister()
go factory.Start(wait.NeverStop)
} }
// Start informer for CSIDrivers.
factory := csiapiinformer.NewSharedInformerFactory(csiClient, csiResyncPeriod)
p.csiDriverInformer = factory.Storage().V1beta1().CSIDrivers()
p.csiDriverLister = p.csiDriverInformer.Lister()
go factory.Start(wait.NeverStop)
} }
// Initializing the label management channels // Initializing the label management channels
......
...@@ -32,14 +32,13 @@ import ( ...@@ -32,14 +32,13 @@ import (
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing" utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
fakeclient "k8s.io/client-go/kubernetes/fake" fakeclient "k8s.io/client-go/kubernetes/fake"
utiltesting "k8s.io/client-go/util/testing" utiltesting "k8s.io/client-go/util/testing"
fakecsi "k8s.io/csi-api/pkg/client/clientset/versioned/fake"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
volumetest "k8s.io/kubernetes/pkg/volume/testing" volumetest "k8s.io/kubernetes/pkg/volume/testing"
) )
// create a plugin mgr to load plugins and setup a fake client // create a plugin mgr to load plugins and setup a fake client
func newTestPlugin(t *testing.T, client *fakeclient.Clientset, csiClient *fakecsi.Clientset) (*csiPlugin, string) { func newTestPlugin(t *testing.T, client *fakeclient.Clientset) (*csiPlugin, string) {
tmpDir, err := utiltesting.MkTmpdir("csi-test") tmpDir, err := utiltesting.MkTmpdir("csi-test")
if err != nil { if err != nil {
t.Fatalf("can't create temp dir: %v", err) t.Fatalf("can't create temp dir: %v", err)
...@@ -48,13 +47,9 @@ func newTestPlugin(t *testing.T, client *fakeclient.Clientset, csiClient *fakecs ...@@ -48,13 +47,9 @@ func newTestPlugin(t *testing.T, client *fakeclient.Clientset, csiClient *fakecs
if client == nil { if client == nil {
client = fakeclient.NewSimpleClientset() client = fakeclient.NewSimpleClientset()
} }
if csiClient == nil {
csiClient = fakecsi.NewSimpleClientset()
}
host := volumetest.NewFakeVolumeHostWithCSINodeName( host := volumetest.NewFakeVolumeHostWithCSINodeName(
tmpDir, tmpDir,
client, client,
csiClient,
nil, nil,
"fakeNode", "fakeNode",
) )
...@@ -120,7 +115,7 @@ func registerFakePlugin(pluginName, endpoint string, versions []string, t *testi ...@@ -120,7 +115,7 @@ func registerFakePlugin(pluginName, endpoint string, versions []string, t *testi
func TestPluginGetPluginName(t *testing.T) { func TestPluginGetPluginName(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
if plug.GetPluginName() != "kubernetes.io/csi" { if plug.GetPluginName() != "kubernetes.io/csi" {
t.Errorf("unexpected plugin name %v", plug.GetPluginName()) t.Errorf("unexpected plugin name %v", plug.GetPluginName())
...@@ -130,7 +125,7 @@ func TestPluginGetPluginName(t *testing.T) { ...@@ -130,7 +125,7 @@ func TestPluginGetPluginName(t *testing.T) {
func TestPluginGetVolumeName(t *testing.T) { func TestPluginGetVolumeName(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
testCases := []struct { testCases := []struct {
name string name string
...@@ -162,7 +157,7 @@ func TestPluginGetVolumeName(t *testing.T) { ...@@ -162,7 +157,7 @@ func TestPluginGetVolumeName(t *testing.T) {
func TestPluginCanSupport(t *testing.T) { func TestPluginCanSupport(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
registerFakePlugin(testDriver, "endpoint", []string{"1.0.0"}, t) registerFakePlugin(testDriver, "endpoint", []string{"1.0.0"}, t)
...@@ -177,7 +172,7 @@ func TestPluginCanSupport(t *testing.T) { ...@@ -177,7 +172,7 @@ func TestPluginCanSupport(t *testing.T) {
func TestPluginConstructVolumeSpec(t *testing.T) { func TestPluginConstructVolumeSpec(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
testCases := []struct { testCases := []struct {
...@@ -239,7 +234,7 @@ func TestPluginConstructVolumeSpec(t *testing.T) { ...@@ -239,7 +234,7 @@ func TestPluginConstructVolumeSpec(t *testing.T) {
func TestPluginNewMounter(t *testing.T) { func TestPluginNewMounter(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
registerFakePlugin(testDriver, "endpoint", []string{"1.2.0"}, t) registerFakePlugin(testDriver, "endpoint", []string{"1.2.0"}, t)
...@@ -290,7 +285,7 @@ func TestPluginNewMounter(t *testing.T) { ...@@ -290,7 +285,7 @@ func TestPluginNewMounter(t *testing.T) {
func TestPluginNewUnmounter(t *testing.T) { func TestPluginNewUnmounter(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
registerFakePlugin(testDriver, "endpoint", []string{"1.0.0"}, t) registerFakePlugin(testDriver, "endpoint", []string{"1.0.0"}, t)
...@@ -338,7 +333,7 @@ func TestPluginNewUnmounter(t *testing.T) { ...@@ -338,7 +333,7 @@ func TestPluginNewUnmounter(t *testing.T) {
func TestPluginNewAttacher(t *testing.T) { func TestPluginNewAttacher(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
attacher, err := plug.NewAttacher() attacher, err := plug.NewAttacher()
...@@ -358,7 +353,7 @@ func TestPluginNewAttacher(t *testing.T) { ...@@ -358,7 +353,7 @@ func TestPluginNewAttacher(t *testing.T) {
func TestPluginNewDetacher(t *testing.T) { func TestPluginNewDetacher(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
detacher, err := plug.NewDetacher() detacher, err := plug.NewDetacher()
...@@ -389,10 +384,8 @@ func TestPluginCanAttach(t *testing.T) { ...@@ -389,10 +384,8 @@ func TestPluginCanAttach(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
csiDriver := getCSIDriver(test.driverName, nil, &test.canAttach)
t.Run(test.name, func(t *testing.T) { t.Run(test.name, func(t *testing.T) {
fakeCSIClient := fakecsi.NewSimpleClientset(csiDriver) plug, tmpDir := newTestPlugin(t, nil)
plug, tmpDir := newTestPlugin(t, nil, fakeCSIClient)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
spec := volume.NewSpecFromPersistentVolume(makeTestPV("test-pv", 10, test.driverName, "test-vol"), false) spec := volume.NewSpecFromPersistentVolume(makeTestPV("test-pv", 10, test.driverName, "test-vol"), false)
...@@ -408,7 +401,7 @@ func TestPluginCanAttach(t *testing.T) { ...@@ -408,7 +401,7 @@ func TestPluginCanAttach(t *testing.T) {
func TestPluginNewBlockMapper(t *testing.T) { func TestPluginNewBlockMapper(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
registerFakePlugin(testDriver, "endpoint", []string{"1.0.0"}, t) registerFakePlugin(testDriver, "endpoint", []string{"1.0.0"}, t)
...@@ -456,7 +449,7 @@ func TestPluginNewBlockMapper(t *testing.T) { ...@@ -456,7 +449,7 @@ func TestPluginNewBlockMapper(t *testing.T) {
func TestPluginNewUnmapper(t *testing.T) { func TestPluginNewUnmapper(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
registerFakePlugin(testDriver, "endpoint", []string{"1.0.0"}, t) registerFakePlugin(testDriver, "endpoint", []string{"1.0.0"}, t)
...@@ -516,7 +509,7 @@ func TestPluginNewUnmapper(t *testing.T) { ...@@ -516,7 +509,7 @@ func TestPluginNewUnmapper(t *testing.T) {
func TestPluginConstructBlockVolumeSpec(t *testing.T) { func TestPluginConstructBlockVolumeSpec(t *testing.T) {
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)() defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIBlockVolume, true)()
plug, tmpDir := newTestPlugin(t, nil, nil) plug, tmpDir := newTestPlugin(t, nil)
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
testCases := []struct { testCases := []struct {
......
...@@ -11,6 +11,7 @@ go_library( ...@@ -11,6 +11,7 @@ go_library(
"//pkg/volume:go_default_library", "//pkg/volume:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/api/storage/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
...@@ -19,8 +20,7 @@ go_library( ...@@ -19,8 +20,7 @@ go_library(
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/apis/csi/v1alpha1:go_default_library", "//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/client/clientset/versioned:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
], ],
) )
...@@ -50,6 +50,8 @@ go_test( ...@@ -50,6 +50,8 @@ go_test(
"//pkg/volume/testing:go_default_library", "//pkg/volume/testing:go_default_library",
"//pkg/volume/util:go_default_library", "//pkg/volume/util:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library", "//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/api/storage/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library", "//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
...@@ -60,8 +62,6 @@ go_test( ...@@ -60,8 +62,6 @@ go_test(
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library", "//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
"//staging/src/k8s.io/client-go/testing:go_default_library", "//staging/src/k8s.io/client-go/testing:go_default_library",
"//staging/src/k8s.io/client-go/util/testing:go_default_library", "//staging/src/k8s.io/client-go/util/testing:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/apis/csi/v1alpha1:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/client/clientset/versioned/fake:go_default_library",
"//vendor/github.com/stretchr/testify/assert:go_default_library", "//vendor/github.com/stretchr/testify/assert:go_default_library",
], ],
) )
...@@ -32,7 +32,6 @@ import ( ...@@ -32,7 +32,6 @@ import (
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
cloudprovider "k8s.io/cloud-provider" cloudprovider "k8s.io/cloud-provider"
csiclientset "k8s.io/csi-api/pkg/client/clientset/versioned"
"k8s.io/klog" "k8s.io/klog"
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
"k8s.io/kubernetes/pkg/volume/util/recyclerclient" "k8s.io/kubernetes/pkg/volume/util/recyclerclient"
...@@ -318,9 +317,6 @@ type VolumeHost interface { ...@@ -318,9 +317,6 @@ type VolumeHost interface {
// GetKubeClient returns a client interface // GetKubeClient returns a client interface
GetKubeClient() clientset.Interface GetKubeClient() clientset.Interface
// GetCSIClient returns a client interface to csi.storage.k8s.io
GetCSIClient() csiclientset.Interface
// NewWrapperMounter finds an appropriate plugin with which to handle // NewWrapperMounter finds an appropriate plugin with which to handle
// the provided spec. This is used to implement volume plugins which // the provided spec. This is used to implement volume plugins which
// "wrap" other plugins. For example, the "secret" volume is // "wrap" other plugins. For example, the "secret" volume is
......
...@@ -29,7 +29,6 @@ go_library( ...@@ -29,7 +29,6 @@ go_library(
"//staging/src/k8s.io/client-go/tools/record:go_default_library", "//staging/src/k8s.io/client-go/tools/record:go_default_library",
"//staging/src/k8s.io/client-go/util/testing:go_default_library", "//staging/src/k8s.io/client-go/util/testing:go_default_library",
"//staging/src/k8s.io/cloud-provider:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/client/clientset/versioned:go_default_library",
"//vendor/github.com/stretchr/testify/mock:go_default_library", "//vendor/github.com/stretchr/testify/mock:go_default_library",
"//vendor/k8s.io/utils/strings:go_default_library", "//vendor/k8s.io/utils/strings:go_default_library",
], ],
......
...@@ -37,7 +37,6 @@ import ( ...@@ -37,7 +37,6 @@ import (
"k8s.io/client-go/tools/record" "k8s.io/client-go/tools/record"
utiltesting "k8s.io/client-go/util/testing" utiltesting "k8s.io/client-go/util/testing"
cloudprovider "k8s.io/cloud-provider" cloudprovider "k8s.io/cloud-provider"
csiclientset "k8s.io/csi-api/pkg/client/clientset/versioned"
"k8s.io/kubernetes/pkg/util/mount" "k8s.io/kubernetes/pkg/util/mount"
. "k8s.io/kubernetes/pkg/volume" . "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util"
...@@ -65,7 +64,6 @@ const ( ...@@ -65,7 +64,6 @@ const (
type fakeVolumeHost struct { type fakeVolumeHost struct {
rootDir string rootDir string
kubeClient clientset.Interface kubeClient clientset.Interface
csiClient csiclientset.Interface
pluginMgr VolumePluginMgr pluginMgr VolumePluginMgr
cloud cloudprovider.Interface cloud cloudprovider.Interface
mounter mount.Interface mounter mount.Interface
...@@ -89,10 +87,9 @@ func NewFakeVolumeHostWithNodeLabels(rootDir string, kubeClient clientset.Interf ...@@ -89,10 +87,9 @@ func NewFakeVolumeHostWithNodeLabels(rootDir string, kubeClient clientset.Interf
return volHost return volHost
} }
func NewFakeVolumeHostWithCSINodeName(rootDir string, kubeClient clientset.Interface, csiClient csiclientset.Interface, plugins []VolumePlugin, nodeName string) *fakeVolumeHost { func NewFakeVolumeHostWithCSINodeName(rootDir string, kubeClient clientset.Interface, plugins []VolumePlugin, nodeName string) *fakeVolumeHost {
volHost := newFakeVolumeHost(rootDir, kubeClient, plugins, nil, nil) volHost := newFakeVolumeHost(rootDir, kubeClient, plugins, nil, nil)
volHost.nodeName = nodeName volHost.nodeName = nodeName
volHost.csiClient = csiClient
return volHost return volHost
} }
...@@ -140,10 +137,6 @@ func (f *fakeVolumeHost) GetKubeClient() clientset.Interface { ...@@ -140,10 +137,6 @@ func (f *fakeVolumeHost) GetKubeClient() clientset.Interface {
return f.kubeClient return f.kubeClient
} }
func (f *fakeVolumeHost) GetCSIClient() csiclientset.Interface {
return f.csiClient
}
func (f *fakeVolumeHost) GetCloudProvider() cloudprovider.Interface { func (f *fakeVolumeHost) GetCloudProvider() cloudprovider.Interface {
return f.cloud return f.cloud
} }
......
...@@ -16,6 +16,7 @@ go_library( ...@@ -16,6 +16,7 @@ go_library(
"//pkg/apis/coordination:go_default_library", "//pkg/apis/coordination:go_default_library",
"//pkg/apis/core:go_default_library", "//pkg/apis/core:go_default_library",
"//pkg/apis/policy:go_default_library", "//pkg/apis/policy:go_default_library",
"//pkg/apis/storage:go_default_library",
"//pkg/auth/nodeidentifier:go_default_library", "//pkg/auth/nodeidentifier:go_default_library",
"//pkg/features:go_default_library", "//pkg/features:go_default_library",
"//pkg/kubelet/apis:go_default_library", "//pkg/kubelet/apis:go_default_library",
...@@ -30,7 +31,6 @@ go_library( ...@@ -30,7 +31,6 @@ go_library(
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/client-go/informers:go_default_library", "//staging/src/k8s.io/client-go/informers:go_default_library",
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library", "//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/apis/csi/v1alpha1:go_default_library",
"//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog:go_default_library",
], ],
) )
...@@ -44,6 +44,7 @@ go_test( ...@@ -44,6 +44,7 @@ go_test(
"//pkg/apis/coordination:go_default_library", "//pkg/apis/coordination:go_default_library",
"//pkg/apis/core:go_default_library", "//pkg/apis/core:go_default_library",
"//pkg/apis/policy:go_default_library", "//pkg/apis/policy:go_default_library",
"//pkg/apis/storage:go_default_library",
"//pkg/auth/nodeidentifier:go_default_library", "//pkg/auth/nodeidentifier:go_default_library",
"//pkg/features:go_default_library", "//pkg/features:go_default_library",
"//pkg/kubelet/apis:go_default_library", "//pkg/kubelet/apis:go_default_library",
...@@ -57,7 +58,6 @@ go_test( ...@@ -57,7 +58,6 @@ go_test(
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library", "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library", "//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
"//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/apis/csi/v1alpha1:go_default_library",
"//vendor/k8s.io/utils/pointer:go_default_library", "//vendor/k8s.io/utils/pointer:go_default_library",
], ],
) )
......
...@@ -32,13 +32,13 @@ import ( ...@@ -32,13 +32,13 @@ import (
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/informers" "k8s.io/client-go/informers"
corev1lister "k8s.io/client-go/listers/core/v1" corev1lister "k8s.io/client-go/listers/core/v1"
csiv1alpha1 "k8s.io/csi-api/pkg/apis/csi/v1alpha1"
"k8s.io/klog" "k8s.io/klog"
podutil "k8s.io/kubernetes/pkg/api/pod" podutil "k8s.io/kubernetes/pkg/api/pod"
authenticationapi "k8s.io/kubernetes/pkg/apis/authentication" authenticationapi "k8s.io/kubernetes/pkg/apis/authentication"
coordapi "k8s.io/kubernetes/pkg/apis/coordination" coordapi "k8s.io/kubernetes/pkg/apis/coordination"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/apis/policy"
storage "k8s.io/kubernetes/pkg/apis/storage"
"k8s.io/kubernetes/pkg/auth/nodeidentifier" "k8s.io/kubernetes/pkg/auth/nodeidentifier"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
...@@ -94,12 +94,12 @@ func (p *nodePlugin) ValidateInitialization() error { ...@@ -94,12 +94,12 @@ func (p *nodePlugin) ValidateInitialization() error {
} }
var ( var (
podResource = api.Resource("pods") podResource = api.Resource("pods")
nodeResource = api.Resource("nodes") nodeResource = api.Resource("nodes")
pvcResource = api.Resource("persistentvolumeclaims") pvcResource = api.Resource("persistentvolumeclaims")
svcacctResource = api.Resource("serviceaccounts") svcacctResource = api.Resource("serviceaccounts")
leaseResource = coordapi.Resource("leases") leaseResource = coordapi.Resource("leases")
csiNodeInfoResource = csiv1alpha1.Resource("csinodeinfos") csiNodeResource = storage.Resource("csinodes")
) )
func (c *nodePlugin) Admit(a admission.Attributes, o admission.ObjectInterfaces) error { func (c *nodePlugin) Admit(a admission.Attributes, o admission.ObjectInterfaces) error {
...@@ -151,9 +151,9 @@ func (c *nodePlugin) Admit(a admission.Attributes, o admission.ObjectInterfaces) ...@@ -151,9 +151,9 @@ func (c *nodePlugin) Admit(a admission.Attributes, o admission.ObjectInterfaces)
} }
return admission.NewForbidden(a, fmt.Errorf("disabled by feature gate %s", features.NodeLease)) return admission.NewForbidden(a, fmt.Errorf("disabled by feature gate %s", features.NodeLease))
case csiNodeInfoResource: case csiNodeResource:
if c.features.Enabled(features.KubeletPluginsWatcher) && c.features.Enabled(features.CSINodeInfo) { if c.features.Enabled(features.KubeletPluginsWatcher) && c.features.Enabled(features.CSINodeInfo) {
return c.admitCSINodeInfo(nodeName, a) return c.admitCSINode(nodeName, a)
} }
return admission.NewForbidden(a, fmt.Errorf("disabled by feature gates %s and %s", features.KubeletPluginsWatcher, features.CSINodeInfo)) return admission.NewForbidden(a, fmt.Errorf("disabled by feature gates %s and %s", features.KubeletPluginsWatcher, features.CSINodeInfo))
...@@ -530,8 +530,8 @@ func (r *nodePlugin) admitLease(nodeName string, a admission.Attributes) error { ...@@ -530,8 +530,8 @@ func (r *nodePlugin) admitLease(nodeName string, a admission.Attributes) error {
return nil return nil
} }
func (c *nodePlugin) admitCSINodeInfo(nodeName string, a admission.Attributes) error { func (c *nodePlugin) admitCSINode(nodeName string, a admission.Attributes) error {
// the request must come from a node with the same name as the CSINodeInfo object // the request must come from a node with the same name as the CSINode object
if a.GetOperation() == admission.Create { if a.GetOperation() == admission.Create {
// a.GetName() won't return the name on create, so we drill down to the proposed object // a.GetName() won't return the name on create, so we drill down to the proposed object
accessor, err := meta.Accessor(a.GetObject()) accessor, err := meta.Accessor(a.GetObject())
...@@ -539,11 +539,11 @@ func (c *nodePlugin) admitCSINodeInfo(nodeName string, a admission.Attributes) e ...@@ -539,11 +539,11 @@ func (c *nodePlugin) admitCSINodeInfo(nodeName string, a admission.Attributes) e
return admission.NewForbidden(a, fmt.Errorf("unable to access the object name")) return admission.NewForbidden(a, fmt.Errorf("unable to access the object name"))
} }
if accessor.GetName() != nodeName { if accessor.GetName() != nodeName {
return admission.NewForbidden(a, fmt.Errorf("can only access CSINodeInfo with the same name as the requesting node")) return admission.NewForbidden(a, fmt.Errorf("can only access CSINode with the same name as the requesting node"))
} }
} else { } else {
if a.GetName() != nodeName { if a.GetName() != nodeName {
return admission.NewForbidden(a, fmt.Errorf("can only access CSINodeInfo with the same name as the requesting node")) return admission.NewForbidden(a, fmt.Errorf("can only access CSINode with the same name as the requesting node"))
} }
} }
......
...@@ -33,11 +33,11 @@ import ( ...@@ -33,11 +33,11 @@ import (
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
corev1lister "k8s.io/client-go/listers/core/v1" corev1lister "k8s.io/client-go/listers/core/v1"
"k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/cache"
csiv1alpha1 "k8s.io/csi-api/pkg/apis/csi/v1alpha1"
authenticationapi "k8s.io/kubernetes/pkg/apis/authentication" authenticationapi "k8s.io/kubernetes/pkg/apis/authentication"
"k8s.io/kubernetes/pkg/apis/coordination" "k8s.io/kubernetes/pkg/apis/coordination"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/policy" "k8s.io/kubernetes/pkg/apis/policy"
storage "k8s.io/kubernetes/pkg/apis/storage"
"k8s.io/kubernetes/pkg/auth/nodeidentifier" "k8s.io/kubernetes/pkg/auth/nodeidentifier"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
...@@ -306,14 +306,14 @@ func Test_nodePlugin_Admit(t *testing.T) { ...@@ -306,14 +306,14 @@ func Test_nodePlugin_Admit(t *testing.T) {
}, },
} }
csiNodeInfoResource = csiv1alpha1.Resource("csinodeinfos").WithVersion("v1alpha1") csiNodeResource = storage.Resource("csinodes").WithVersion("v1beta1")
csiNodeInfoKind = schema.GroupVersionKind{Group: "csi.storage.k8s.io", Version: "v1alpha1", Kind: "CSINodeInfo"} csiNodeKind = schema.GroupVersionKind{Group: "storage.k8s.io", Version: "v1beta1", Kind: "CSINode"}
nodeInfo = &csiv1alpha1.CSINodeInfo{ nodeInfo = &storage.CSINode{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "mynode", Name: "mynode",
}, },
Spec: csiv1alpha1.CSINodeInfoSpec{ Spec: storage.CSINodeSpec{
Drivers: []csiv1alpha1.CSIDriverInfoSpec{ Drivers: []storage.CSINodeDriver{
{ {
Name: "com.example.csi/mydriver", Name: "com.example.csi/mydriver",
NodeID: "com.example.csi/mynode", NodeID: "com.example.csi/mynode",
...@@ -321,22 +321,13 @@ func Test_nodePlugin_Admit(t *testing.T) { ...@@ -321,22 +321,13 @@ func Test_nodePlugin_Admit(t *testing.T) {
}, },
}, },
}, },
Status: csiv1alpha1.CSINodeInfoStatus{
Drivers: []csiv1alpha1.CSIDriverInfoStatus{
{
Name: "com.example.csi/mydriver",
Available: true,
VolumePluginMechanism: csiv1alpha1.VolumePluginMechanismInTree,
},
},
},
} }
nodeInfoWrongName = &csiv1alpha1.CSINodeInfo{ nodeInfoWrongName = &storage.CSINode{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "foo", Name: "foo",
}, },
Spec: csiv1alpha1.CSINodeInfoSpec{ Spec: storage.CSINodeSpec{
Drivers: []csiv1alpha1.CSIDriverInfoSpec{ Drivers: []storage.CSINodeDriver{
{ {
Name: "com.example.csi/mydriver", Name: "com.example.csi/mydriver",
NodeID: "com.example.csi/foo", NodeID: "com.example.csi/foo",
...@@ -344,15 +335,6 @@ func Test_nodePlugin_Admit(t *testing.T) { ...@@ -344,15 +335,6 @@ func Test_nodePlugin_Admit(t *testing.T) {
}, },
}, },
}, },
Status: csiv1alpha1.CSINodeInfoStatus{
Drivers: []csiv1alpha1.CSIDriverInfoStatus{
{
Name: "com.example.csi/mydriver",
Available: true,
VolumePluginMechanism: csiv1alpha1.VolumePluginMechanismInTree,
},
},
},
} }
noExistingPodsIndex = cache.NewIndexer(cache.MetaNamespaceKeyFunc, nil) noExistingPodsIndex = cache.NewIndexer(cache.MetaNamespaceKeyFunc, nil)
...@@ -1183,46 +1165,46 @@ func Test_nodePlugin_Admit(t *testing.T) { ...@@ -1183,46 +1165,46 @@ func Test_nodePlugin_Admit(t *testing.T) {
features: leaseEnabledFeature, features: leaseEnabledFeature,
err: "", err: "",
}, },
// CSINodeInfo // CSINode
{ {
name: "disallowed create CSINodeInfo - feature disabled", name: "disallowed create CSINode - feature disabled",
attributes: admission.NewAttributesRecord(nodeInfo, nil, csiNodeInfoKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeInfoResource, "", admission.Create, false, mynode), attributes: admission.NewAttributesRecord(nodeInfo, nil, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Create, false, mynode),
features: csiNodeInfoDisabledFeature, features: csiNodeInfoDisabledFeature,
err: fmt.Sprintf("forbidden: disabled by feature gates %s and %s", features.KubeletPluginsWatcher, features.CSINodeInfo), err: fmt.Sprintf("forbidden: disabled by feature gates %s and %s", features.KubeletPluginsWatcher, features.CSINodeInfo),
}, },
{ {
name: "disallowed create another node's CSINodeInfo - feature enabled", name: "disallowed create another node's CSINode - feature enabled",
attributes: admission.NewAttributesRecord(nodeInfoWrongName, nil, csiNodeInfoKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeInfoResource, "", admission.Create, false, mynode), attributes: admission.NewAttributesRecord(nodeInfoWrongName, nil, csiNodeKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeResource, "", admission.Create, false, mynode),
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
err: "forbidden: ", err: "forbidden: ",
}, },
{ {
name: "disallowed update another node's CSINodeInfo - feature enabled", name: "disallowed update another node's CSINode - feature enabled",
attributes: admission.NewAttributesRecord(nodeInfoWrongName, nodeInfoWrongName, csiNodeInfoKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeInfoResource, "", admission.Update, false, mynode), attributes: admission.NewAttributesRecord(nodeInfoWrongName, nodeInfoWrongName, csiNodeKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeResource, "", admission.Update, false, mynode),
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
err: "forbidden: ", err: "forbidden: ",
}, },
{ {
name: "disallowed delete another node's CSINodeInfo - feature enabled", name: "disallowed delete another node's CSINode - feature enabled",
attributes: admission.NewAttributesRecord(nil, nil, csiNodeInfoKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeInfoResource, "", admission.Delete, false, mynode), attributes: admission.NewAttributesRecord(nil, nil, csiNodeKind, nodeInfoWrongName.Namespace, nodeInfoWrongName.Name, csiNodeResource, "", admission.Delete, false, mynode),
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
err: "forbidden: ", err: "forbidden: ",
}, },
{ {
name: "allowed create node CSINodeInfo - feature enabled", name: "allowed create node CSINode - feature enabled",
attributes: admission.NewAttributesRecord(nodeInfo, nil, csiNodeInfoKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeInfoResource, "", admission.Create, false, mynode), attributes: admission.NewAttributesRecord(nodeInfo, nil, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Create, false, mynode),
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
err: "", err: "",
}, },
{ {
name: "allowed update node CSINodeInfo - feature enabled", name: "allowed update node CSINode - feature enabled",
attributes: admission.NewAttributesRecord(nodeInfo, nodeInfo, csiNodeInfoKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeInfoResource, "", admission.Update, false, mynode), attributes: admission.NewAttributesRecord(nodeInfo, nodeInfo, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Update, false, mynode),
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
err: "", err: "",
}, },
{ {
name: "allowed delete node CSINodeInfo - feature enabled", name: "allowed delete node CSINode - feature enabled",
attributes: admission.NewAttributesRecord(nil, nil, csiNodeInfoKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeInfoResource, "", admission.Delete, false, mynode), attributes: admission.NewAttributesRecord(nil, nil, csiNodeKind, nodeInfo.Namespace, nodeInfo.Name, csiNodeResource, "", admission.Delete, false, mynode),
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
err: "", err: "",
}, },
......
...@@ -56,7 +56,6 @@ go_library( ...@@ -56,7 +56,6 @@ go_library(
"//staging/src/k8s.io/client-go/informers/core/v1:go_default_library", "//staging/src/k8s.io/client-go/informers/core/v1:go_default_library",
"//staging/src/k8s.io/client-go/informers/storage/v1:go_default_library", "//staging/src/k8s.io/client-go/informers/storage/v1:go_default_library",
"//staging/src/k8s.io/client-go/tools/cache:go_default_library", "//staging/src/k8s.io/client-go/tools/cache:go_default_library",
"//staging/src/k8s.io/csi-api/pkg/apis/csi/v1alpha1:go_default_library",
"//third_party/forked/gonum/graph:go_default_library", "//third_party/forked/gonum/graph:go_default_library",
"//third_party/forked/gonum/graph/simple:go_default_library", "//third_party/forked/gonum/graph/simple:go_default_library",
"//third_party/forked/gonum/graph/traverse:go_default_library", "//third_party/forked/gonum/graph/traverse:go_default_library",
......
...@@ -25,7 +25,6 @@ import ( ...@@ -25,7 +25,6 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apiserver/pkg/authorization/authorizer" "k8s.io/apiserver/pkg/authorization/authorizer"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
csiv1alpha1 "k8s.io/csi-api/pkg/apis/csi/v1alpha1"
coordapi "k8s.io/kubernetes/pkg/apis/coordination" coordapi "k8s.io/kubernetes/pkg/apis/coordination"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
storageapi "k8s.io/kubernetes/pkg/apis/storage" storageapi "k8s.io/kubernetes/pkg/apis/storage"
...@@ -68,14 +67,14 @@ func NewAuthorizer(graph *Graph, identifier nodeidentifier.NodeIdentifier, rules ...@@ -68,14 +67,14 @@ func NewAuthorizer(graph *Graph, identifier nodeidentifier.NodeIdentifier, rules
} }
var ( var (
configMapResource = api.Resource("configmaps") configMapResource = api.Resource("configmaps")
secretResource = api.Resource("secrets") secretResource = api.Resource("secrets")
pvcResource = api.Resource("persistentvolumeclaims") pvcResource = api.Resource("persistentvolumeclaims")
pvResource = api.Resource("persistentvolumes") pvResource = api.Resource("persistentvolumes")
vaResource = storageapi.Resource("volumeattachments") vaResource = storageapi.Resource("volumeattachments")
svcAcctResource = api.Resource("serviceaccounts") svcAcctResource = api.Resource("serviceaccounts")
leaseResource = coordapi.Resource("leases") leaseResource = coordapi.Resource("leases")
csiNodeInfoResource = csiv1alpha1.Resource("csinodeinfos") csiNodeResource = storageapi.Resource("csinodes")
) )
func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Decision, string, error) { func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Decision, string, error) {
...@@ -122,9 +121,9 @@ func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Deci ...@@ -122,9 +121,9 @@ func (r *NodeAuthorizer) Authorize(attrs authorizer.Attributes) (authorizer.Deci
return r.authorizeLease(nodeName, attrs) return r.authorizeLease(nodeName, attrs)
} }
return authorizer.DecisionNoOpinion, fmt.Sprintf("disabled by feature gate %s", features.NodeLease), nil return authorizer.DecisionNoOpinion, fmt.Sprintf("disabled by feature gate %s", features.NodeLease), nil
case csiNodeInfoResource: case csiNodeResource:
if r.features.Enabled(features.KubeletPluginsWatcher) && r.features.Enabled(features.CSINodeInfo) { if r.features.Enabled(features.KubeletPluginsWatcher) && r.features.Enabled(features.CSINodeInfo) {
return r.authorizeCSINodeInfo(nodeName, attrs) return r.authorizeCSINode(nodeName, attrs)
} }
return authorizer.DecisionNoOpinion, fmt.Sprintf("disabled by feature gates %s and %s", features.KubeletPluginsWatcher, features.CSINodeInfo), nil return authorizer.DecisionNoOpinion, fmt.Sprintf("disabled by feature gates %s and %s", features.KubeletPluginsWatcher, features.CSINodeInfo), nil
} }
...@@ -260,8 +259,8 @@ func (r *NodeAuthorizer) authorizeLease(nodeName string, attrs authorizer.Attrib ...@@ -260,8 +259,8 @@ func (r *NodeAuthorizer) authorizeLease(nodeName string, attrs authorizer.Attrib
return authorizer.DecisionAllow, "", nil return authorizer.DecisionAllow, "", nil
} }
// authorizeCSINodeInfo authorizes node requests to CSINodeInfo csi.storage.k8s.io/csinodeinfos // authorizeCSINode authorizes node requests to CSINode storage.k8s.io/csinodes
func (r *NodeAuthorizer) authorizeCSINodeInfo(nodeName string, attrs authorizer.Attributes) (authorizer.Decision, string, error) { func (r *NodeAuthorizer) authorizeCSINode(nodeName string, attrs authorizer.Attributes) (authorizer.Decision, string, error) {
// allowed verbs: get, create, update, patch, delete // allowed verbs: get, create, update, patch, delete
verb := attrs.GetVerb() verb := attrs.GetVerb()
if verb != "get" && if verb != "get" &&
...@@ -270,20 +269,20 @@ func (r *NodeAuthorizer) authorizeCSINodeInfo(nodeName string, attrs authorizer. ...@@ -270,20 +269,20 @@ func (r *NodeAuthorizer) authorizeCSINodeInfo(nodeName string, attrs authorizer.
verb != "patch" && verb != "patch" &&
verb != "delete" { verb != "delete" {
klog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs) klog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs)
return authorizer.DecisionNoOpinion, "can only get, create, update, patch, or delete a CSINodeInfo", nil return authorizer.DecisionNoOpinion, "can only get, create, update, patch, or delete a CSINode", nil
} }
if len(attrs.GetSubresource()) > 0 { if len(attrs.GetSubresource()) > 0 {
klog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs) klog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs)
return authorizer.DecisionNoOpinion, "cannot authorize CSINodeInfo subresources", nil return authorizer.DecisionNoOpinion, "cannot authorize CSINode subresources", nil
} }
// the request must come from a node with the same name as the CSINodeInfo // the request must come from a node with the same name as the CSINode
// note we skip this check for create, since the authorizer doesn't know the name on create // note we skip this check for create, since the authorizer doesn't know the name on create
// the noderestriction admission plugin is capable of performing this check at create time // the noderestriction admission plugin is capable of performing this check at create time
if verb != "create" && attrs.GetName() != nodeName { if verb != "create" && attrs.GetName() != nodeName {
klog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs) klog.V(2).Infof("NODE DENY: %s %#v", nodeName, attrs)
return authorizer.DecisionNoOpinion, "can only access CSINodeInfo with the same name as the requesting node", nil return authorizer.DecisionNoOpinion, "can only access CSINode with the same name as the requesting node", nil
} }
return authorizer.DecisionAllow, "", nil return authorizer.DecisionAllow, "", nil
......
...@@ -352,82 +352,82 @@ func TestAuthorizer(t *testing.T) { ...@@ -352,82 +352,82 @@ func TestAuthorizer(t *testing.T) {
features: leaseEnabledFeature, features: leaseEnabledFeature,
expect: authorizer.DecisionAllow, expect: authorizer.DecisionAllow,
}, },
// CSINodeInfo // CSINode
{ {
name: "disallowed CSINodeInfo - feature disabled", name: "disallowed CSINode - feature disabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node0"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node0"},
features: csiNodeInfoDisabledFeature, features: csiNodeInfoDisabledFeature,
expect: authorizer.DecisionNoOpinion, expect: authorizer.DecisionNoOpinion,
}, },
{ {
name: "disallowed CSINodeInfo with subresource - feature enabled", name: "disallowed CSINode with subresource - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "csinodeinfos", Subresource: "csiDrivers", APIGroup: "csi.storage.k8s.io", Name: "node0"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "csinodes", Subresource: "csiDrivers", APIGroup: "storage.k8s.io", Name: "node0"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionNoOpinion, expect: authorizer.DecisionNoOpinion,
}, },
{ {
name: "disallowed get another node's CSINodeInfo - feature enabled", name: "disallowed get another node's CSINode - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node1"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node1"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionNoOpinion, expect: authorizer.DecisionNoOpinion,
}, },
{ {
name: "disallowed update another node's CSINodeInfo - feature enabled", name: "disallowed update another node's CSINode - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "update", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node1"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "update", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node1"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionNoOpinion, expect: authorizer.DecisionNoOpinion,
}, },
{ {
name: "disallowed patch another node's CSINodeInfo - feature enabled", name: "disallowed patch another node's CSINode - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "patch", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node1"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "patch", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node1"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionNoOpinion, expect: authorizer.DecisionNoOpinion,
}, },
{ {
name: "disallowed delete another node's CSINodeInfo - feature enabled", name: "disallowed delete another node's CSINode - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "delete", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node1"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "delete", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node1"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionNoOpinion, expect: authorizer.DecisionNoOpinion,
}, },
{ {
name: "disallowed list CSINodeInfos - feature enabled", name: "disallowed list CSINodes - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "list", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "list", Resource: "csinodes", APIGroup: "storage.k8s.io"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionNoOpinion, expect: authorizer.DecisionNoOpinion,
}, },
{ {
name: "disallowed watch CSINodeInfos - feature enabled", name: "disallowed watch CSINodes - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "watch", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "watch", Resource: "csinodes", APIGroup: "storage.k8s.io"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionNoOpinion, expect: authorizer.DecisionNoOpinion,
}, },
{ {
name: "allowed get CSINodeInfo - feature enabled", name: "allowed get CSINode - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node0"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "get", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node0"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionAllow, expect: authorizer.DecisionAllow,
}, },
{ {
name: "allowed create CSINodeInfo - feature enabled", name: "allowed create CSINode - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "create", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node0"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "create", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node0"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionAllow, expect: authorizer.DecisionAllow,
}, },
{ {
name: "allowed update CSINodeInfo - feature enabled", name: "allowed update CSINode - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "update", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node0"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "update", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node0"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionAllow, expect: authorizer.DecisionAllow,
}, },
{ {
name: "allowed patch CSINodeInfo - feature enabled", name: "allowed patch CSINode - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "patch", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node0"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "patch", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node0"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionAllow, expect: authorizer.DecisionAllow,
}, },
{ {
name: "allowed delete CSINodeInfo - feature enabled", name: "allowed delete CSINode - feature enabled",
attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "delete", Resource: "csinodeinfos", APIGroup: "csi.storage.k8s.io", Name: "node0"}, attrs: authorizer.AttributesRecord{User: node0, ResourceRequest: true, Verb: "delete", Resource: "csinodes", APIGroup: "storage.k8s.io", Name: "node0"},
features: csiNodeInfoEnabledFeature, features: csiNodeInfoEnabledFeature,
expect: authorizer.DecisionAllow, expect: authorizer.DecisionAllow,
}, },
......
...@@ -74,7 +74,7 @@ func buildControllerRoles() ([]rbacv1.ClusterRole, []rbacv1.ClusterRoleBinding) ...@@ -74,7 +74,7 @@ func buildControllerRoles() ([]rbacv1.ClusterRole, []rbacv1.ClusterRoleBinding)
if utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) { if utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) {
role.Rules = append(role.Rules, rbacv1helpers.NewRule("get", "create", "delete", "list", "watch").Groups(storageGroup).Resources("volumeattachments").RuleOrDie()) role.Rules = append(role.Rules, rbacv1helpers.NewRule("get", "create", "delete", "list", "watch").Groups(storageGroup).Resources("volumeattachments").RuleOrDie())
if utilfeature.DefaultFeatureGate.Enabled(features.CSIDriverRegistry) { if utilfeature.DefaultFeatureGate.Enabled(features.CSIDriverRegistry) {
role.Rules = append(role.Rules, rbacv1helpers.NewRule("get", "watch", "list").Groups("csi.storage.k8s.io").Resources("csidrivers").RuleOrDie()) role.Rules = append(role.Rules, rbacv1helpers.NewRule("get", "watch", "list").Groups("storage.k8s.io").Resources("csidrivers").RuleOrDie())
} }
} }
......
...@@ -160,13 +160,13 @@ func NodeRules() []rbacv1.PolicyRule { ...@@ -160,13 +160,13 @@ func NodeRules() []rbacv1.PolicyRule {
volAttachRule := rbacv1helpers.NewRule("get").Groups(storageGroup).Resources("volumeattachments").RuleOrDie() volAttachRule := rbacv1helpers.NewRule("get").Groups(storageGroup).Resources("volumeattachments").RuleOrDie()
nodePolicyRules = append(nodePolicyRules, volAttachRule) nodePolicyRules = append(nodePolicyRules, volAttachRule)
if utilfeature.DefaultFeatureGate.Enabled(features.CSIDriverRegistry) { if utilfeature.DefaultFeatureGate.Enabled(features.CSIDriverRegistry) {
csiDriverRule := rbacv1helpers.NewRule("get", "watch", "list").Groups("csi.storage.k8s.io").Resources("csidrivers").RuleOrDie() csiDriverRule := rbacv1helpers.NewRule("get", "watch", "list").Groups("storage.k8s.io").Resources("csidrivers").RuleOrDie()
nodePolicyRules = append(nodePolicyRules, csiDriverRule) nodePolicyRules = append(nodePolicyRules, csiDriverRule)
} }
} }
if utilfeature.DefaultFeatureGate.Enabled(features.KubeletPluginsWatcher) && if utilfeature.DefaultFeatureGate.Enabled(features.KubeletPluginsWatcher) &&
utilfeature.DefaultFeatureGate.Enabled(features.CSINodeInfo) { utilfeature.DefaultFeatureGate.Enabled(features.CSINodeInfo) {
csiNodeInfoRule := rbacv1helpers.NewRule("get", "create", "update", "patch", "delete").Groups("csi.storage.k8s.io").Resources("csinodeinfos").RuleOrDie() csiNodeInfoRule := rbacv1helpers.NewRule("get", "create", "update", "patch", "delete").Groups("storage.k8s.io").Resources("csinodes").RuleOrDie()
nodePolicyRules = append(nodePolicyRules, csiNodeInfoRule) nodePolicyRules = append(nodePolicyRules, csiNodeInfoRule)
} }
...@@ -514,7 +514,7 @@ func ClusterRoles() []rbacv1.ClusterRole { ...@@ -514,7 +514,7 @@ func ClusterRoles() []rbacv1.ClusterRole {
rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(), rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
} }
if utilfeature.DefaultFeatureGate.Enabled(features.CSINodeInfo) { if utilfeature.DefaultFeatureGate.Enabled(features.CSINodeInfo) {
externalProvisionerRules = append(externalProvisionerRules, rbacv1helpers.NewRule("get", "watch", "list").Groups("csi.storage.k8s.io").Resources("csinodeinfos").RuleOrDie()) externalProvisionerRules = append(externalProvisionerRules, rbacv1helpers.NewRule("get", "watch", "list").Groups("storage.k8s.io").Resources("csinodes").RuleOrDie())
} }
roles = append(roles, rbacv1.ClusterRole{ roles = append(roles, rbacv1.ClusterRole{
// a role for the csi external provisioner // a role for the csi external provisioner
......
...@@ -534,6 +534,14 @@ items: ...@@ -534,6 +534,14 @@ items:
- get - get
- list - list
- watch - watch
- apiGroups:
- storage.k8s.io
resources:
- csinodes
verbs:
- get
- list
- watch
- apiVersion: rbac.authorization.k8s.io/v1 - apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
...@@ -988,6 +996,24 @@ items: ...@@ -988,6 +996,24 @@ items:
verbs: verbs:
- get - get
- apiGroups: - apiGroups:
- storage.k8s.io
resources:
- csidrivers
verbs:
- get
- list
- watch
- apiGroups:
- storage.k8s.io
resources:
- csinodes
verbs:
- create
- delete
- get
- patch
- update
- apiGroups:
- coordination.k8s.io - coordination.k8s.io
resources: resources:
- leases - leases
......
...@@ -58,6 +58,14 @@ items: ...@@ -58,6 +58,14 @@ items:
- get - get
- list - list
- watch - watch
- apiGroups:
- storage.k8s.io
resources:
- csidrivers
verbs:
- get
- list
- watch
- apiVersion: rbac.authorization.k8s.io/v1 - apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
......
...@@ -29,6 +29,143 @@ import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto"; ...@@ -29,6 +29,143 @@ import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto";
// Package-wide variables from generator "generated". // Package-wide variables from generator "generated".
option go_package = "v1beta1"; option go_package = "v1beta1";
// CSIDriver captures information about a Container Storage Interface (CSI)
// volume driver deployed on the cluster.
// CSI drivers do not need to create the CSIDriver object directly. Instead they may use the
// cluster-driver-registrar sidecar container. When deployed with a CSI driver it automatically
// creates a CSIDriver object representing the driver.
// Kubernetes attach detach controller uses this object to determine whether attach is required.
// Kubelet uses this object to determine whether pod information needs to be passed on mount.
// CSIDriver objects are non-namespaced.
message CSIDriver {
// Standard object metadata.
// metadata.Name indicates the name of the CSI driver that this object
// refers to; it MUST be the same name returned by the CSI GetPluginName()
// call for that driver.
// The driver name must be 63 characters or less, beginning and ending with
// an alphanumeric character ([a-z0-9A-Z]) with dashes (-), dots (.), and
// alphanumerics between.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1;
// Specification of the CSI Driver.
optional CSIDriverSpec spec = 2;
}
// CSIDriverList is a collection of CSIDriver objects.
message CSIDriverList {
// Standard list metadata
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1;
// items is the list of CSIDriver
repeated CSIDriver items = 2;
}
// CSIDriverSpec is the specification of a CSIDriver.
message CSIDriverSpec {
// attachRequired indicates this CSI volume driver requires an attach
// operation (because it implements the CSI ControllerPublishVolume()
// method), and that the Kubernetes attach detach controller should call
// the attach volume interface which checks the volumeattachment status
// and waits until the volume is attached before proceeding to mounting.
// The CSI external-attacher coordinates with CSI volume driver and updates
// the volumeattachment status when the attach operation is complete.
// If the CSIDriverRegistry feature gate is enabled and the value is
// specified to false, the attach operation will be skipped.
// Otherwise the attach operation will be called.
// +optional
optional bool attachRequired = 1;
// If set to true, podInfoOnMount indicates this CSI volume driver
// requires additional pod information (like podName, podUID, etc.) during
// mount operations.
// If set to false, pod information will not be passed on mount.
// Default is false.
// The CSI driver specifies podInfoOnMount as part of driver deployment.
// If true, Kubelet will pass pod information as VolumeContext in the CSI
// NodePublishVolume() calls.
// The CSI driver is responsible for parsing and validating the information
// passed in as VolumeContext.
// The following VolumeConext will be passed if podInfoOnMount is set to true.
// This list might grow, but the prefix will be used.
// "csi.storage.k8s.io/pod.name": pod.Name
// "csi.storage.k8s.io/pod.namespace": pod.Namespace
// "csi.storage.k8s.io/pod.uid": string(pod.UID)
// +optional
optional bool podInfoOnMount = 2;
}
// CSINode holds information about all CSI drivers installed on a node.
// CSI drivers do not need to create the CSINode object directly. As long as
// they use the node-driver-registrar sidecar container, the kubelet will
// automatically populate the CSINode object for the CSI driver as part of
// kubelet plugin registration.
// CSINode has the same name as a node. If the object is missing, it means either
// there are no CSI Drivers available on the node, or the Kubelet version is low
// enough that it doesn't create this object.
// CSINode has an OwnerReference that points to the corresponding node object.
message CSINode {
// metadata.name must be the Kubernetes node name.
optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1;
// spec is the specification of CSINode
optional CSINodeSpec spec = 2;
}
// CSINodeDriver holds information about the specification of one CSI driver installed on a node
message CSINodeDriver {
// This is the name of the CSI driver that this object refers to.
// This MUST be the same name returned by the CSI GetPluginName() call for
// that driver.
optional string name = 1;
// nodeID of the node from the driver point of view.
// This field enables Kubernetes to communicate with storage systems that do
// not share the same nomenclature for nodes. For example, Kubernetes may
// refer to a given node as "node1", but the storage system may refer to
// the same node as "nodeA". When Kubernetes issues a command to the storage
// system to attach a volume to a specific node, it can use this field to
// refer to the node name using the ID that the storage system will
// understand, e.g. "nodeA" instead of "node1". This field is required.
optional string nodeID = 2;
// topologyKeys is the list of keys supported by the driver.
// When a driver is initialized on a cluster, it provides a set of topology
// keys that it understands (e.g. "company.com/zone", "company.com/region").
// When a driver is initialized on a node, it provides the same topology keys
// along with values. Kubelet will expose these topology keys as labels
// on its own node object.
// When Kubernetes does topology aware provisioning, it can use this list to
// determine which labels it should retrieve from the node object and pass
// back to the driver.
// It is possible for different nodes to use different topology keys.
// This can be empty if driver does not support topology.
// +optional
repeated string topologyKeys = 3;
}
// CSINodeList is a collection of CSINode objects.
message CSINodeList {
// Standard list metadata
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
// +optional
optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1;
// items is the list of CSINode
repeated CSINode items = 2;
}
// CSINodeSpec holds information about the specification of all CSI drivers installed on a node
message CSINodeSpec {
// drivers is a list of information of all CSI Drivers existing on a node.
// If all drivers in the list are uninstalled, this can become empty.
// +patchMergeKey=name
// +patchStrategy=merge
repeated CSINodeDriver drivers = 1;
}
// StorageClass describes the parameters for a class of storage for // StorageClass describes the parameters for a class of storage for
// which PersistentVolumes can be dynamically provisioned. // which PersistentVolumes can be dynamically provisioned.
// //
......
...@@ -49,6 +49,12 @@ func addKnownTypes(scheme *runtime.Scheme) error { ...@@ -49,6 +49,12 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&VolumeAttachment{}, &VolumeAttachment{},
&VolumeAttachmentList{}, &VolumeAttachmentList{},
&CSIDriver{},
&CSIDriverList{},
&CSINode{},
&CSINodeList{},
) )
metav1.AddToGroupVersion(scheme, SchemeGroupVersion) metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
......
...@@ -209,3 +209,160 @@ type VolumeError struct { ...@@ -209,3 +209,160 @@ type VolumeError struct {
// +optional // +optional
Message string `json:"message,omitempty" protobuf:"bytes,2,opt,name=message"` Message string `json:"message,omitempty" protobuf:"bytes,2,opt,name=message"`
} }
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// CSIDriver captures information about a Container Storage Interface (CSI)
// volume driver deployed on the cluster.
// CSI drivers do not need to create the CSIDriver object directly. Instead they may use the
// cluster-driver-registrar sidecar container. When deployed with a CSI driver it automatically
// creates a CSIDriver object representing the driver.
// Kubernetes attach detach controller uses this object to determine whether attach is required.
// Kubelet uses this object to determine whether pod information needs to be passed on mount.
// CSIDriver objects are non-namespaced.
type CSIDriver struct {
metav1.TypeMeta `json:",inline"`
// Standard object metadata.
// metadata.Name indicates the name of the CSI driver that this object
// refers to; it MUST be the same name returned by the CSI GetPluginName()
// call for that driver.
// The driver name must be 63 characters or less, beginning and ending with
// an alphanumeric character ([a-z0-9A-Z]) with dashes (-), dots (.), and
// alphanumerics between.
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// Specification of the CSI Driver.
Spec CSIDriverSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// CSIDriverList is a collection of CSIDriver objects.
type CSIDriverList struct {
metav1.TypeMeta `json:",inline"`
// Standard list metadata
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
// +optional
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// items is the list of CSIDriver
Items []CSIDriver `json:"items" protobuf:"bytes,2,rep,name=items"`
}
// CSIDriverSpec is the specification of a CSIDriver.
type CSIDriverSpec struct {
// attachRequired indicates this CSI volume driver requires an attach
// operation (because it implements the CSI ControllerPublishVolume()
// method), and that the Kubernetes attach detach controller should call
// the attach volume interface which checks the volumeattachment status
// and waits until the volume is attached before proceeding to mounting.
// The CSI external-attacher coordinates with CSI volume driver and updates
// the volumeattachment status when the attach operation is complete.
// If the CSIDriverRegistry feature gate is enabled and the value is
// specified to false, the attach operation will be skipped.
// Otherwise the attach operation will be called.
// +optional
AttachRequired *bool `json:"attachRequired,omitempty" protobuf:"varint,1,opt,name=attachRequired"`
// If set to true, podInfoOnMount indicates this CSI volume driver
// requires additional pod information (like podName, podUID, etc.) during
// mount operations.
// If set to false, pod information will not be passed on mount.
// Default is false.
// The CSI driver specifies podInfoOnMount as part of driver deployment.
// If true, Kubelet will pass pod information as VolumeContext in the CSI
// NodePublishVolume() calls.
// The CSI driver is responsible for parsing and validating the information
// passed in as VolumeContext.
// The following VolumeConext will be passed if podInfoOnMount is set to true.
// This list might grow, but the prefix will be used.
// "csi.storage.k8s.io/pod.name": pod.Name
// "csi.storage.k8s.io/pod.namespace": pod.Namespace
// "csi.storage.k8s.io/pod.uid": string(pod.UID)
// +optional
PodInfoOnMount *bool `json:"podInfoOnMount,omitempty" protobuf:"bytes,2,opt,name=podInfoOnMount"`
}
// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// CSINode holds information about all CSI drivers installed on a node.
// CSI drivers do not need to create the CSINode object directly. As long as
// they use the node-driver-registrar sidecar container, the kubelet will
// automatically populate the CSINode object for the CSI driver as part of
// kubelet plugin registration.
// CSINode has the same name as a node. If the object is missing, it means either
// there are no CSI Drivers available on the node, or the Kubelet version is low
// enough that it doesn't create this object.
// CSINode has an OwnerReference that points to the corresponding node object.
type CSINode struct {
metav1.TypeMeta `json:",inline"`
// metadata.name must be the Kubernetes node name.
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// spec is the specification of CSINode
Spec CSINodeSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"`
}
// CSINodeSpec holds information about the specification of all CSI drivers installed on a node
type CSINodeSpec struct {
// drivers is a list of information of all CSI Drivers existing on a node.
// If all drivers in the list are uninstalled, this can become empty.
// +patchMergeKey=name
// +patchStrategy=merge
Drivers []CSINodeDriver `json:"drivers" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,1,rep,name=drivers"`
}
// CSINodeDriver holds information about the specification of one CSI driver installed on a node
type CSINodeDriver struct {
// This is the name of the CSI driver that this object refers to.
// This MUST be the same name returned by the CSI GetPluginName() call for
// that driver.
Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
// nodeID of the node from the driver point of view.
// This field enables Kubernetes to communicate with storage systems that do
// not share the same nomenclature for nodes. For example, Kubernetes may
// refer to a given node as "node1", but the storage system may refer to
// the same node as "nodeA". When Kubernetes issues a command to the storage
// system to attach a volume to a specific node, it can use this field to
// refer to the node name using the ID that the storage system will
// understand, e.g. "nodeA" instead of "node1". This field is required.
NodeID string `json:"nodeID" protobuf:"bytes,2,opt,name=nodeID"`
// topologyKeys is the list of keys supported by the driver.
// When a driver is initialized on a cluster, it provides a set of topology
// keys that it understands (e.g. "company.com/zone", "company.com/region").
// When a driver is initialized on a node, it provides the same topology keys
// along with values. Kubelet will expose these topology keys as labels
// on its own node object.
// When Kubernetes does topology aware provisioning, it can use this list to
// determine which labels it should retrieve from the node object and pass
// back to the driver.
// It is possible for different nodes to use different topology keys.
// This can be empty if driver does not support topology.
// +optional
TopologyKeys []string `json:"topologyKeys" protobuf:"bytes,3,rep,name=topologyKeys"`
}
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// CSINodeList is a collection of CSINode objects.
type CSINodeList struct {
metav1.TypeMeta `json:",inline"`
// Standard list metadata
// More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata
// +optional
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// items is the list of CSINode
Items []CSINode `json:"items" protobuf:"bytes,2,rep,name=items"`
}
...@@ -27,6 +27,76 @@ package v1beta1 ...@@ -27,6 +27,76 @@ package v1beta1
// Those methods can be generated by using hack/update-generated-swagger-docs.sh // Those methods can be generated by using hack/update-generated-swagger-docs.sh
// AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT. // AUTO-GENERATED FUNCTIONS START HERE. DO NOT EDIT.
var map_CSIDriver = map[string]string{
"": "CSIDriver captures information about a Container Storage Interface (CSI) volume driver deployed on the cluster. CSI drivers do not need to create the CSIDriver object directly. Instead they may use the cluster-driver-registrar sidecar container. When deployed with a CSI driver it automatically creates a CSIDriver object representing the driver. Kubernetes attach detach controller uses this object to determine whether attach is required. Kubelet uses this object to determine whether pod information needs to be passed on mount. CSIDriver objects are non-namespaced.",
"metadata": "Standard object metadata. metadata.Name indicates the name of the CSI driver that this object refers to; it MUST be the same name returned by the CSI GetPluginName() call for that driver. The driver name must be 63 characters or less, beginning and ending with an alphanumeric character ([a-z0-9A-Z]) with dashes (-), dots (.), and alphanumerics between. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata",
"spec": "Specification of the CSI Driver.",
}
func (CSIDriver) SwaggerDoc() map[string]string {
return map_CSIDriver
}
var map_CSIDriverList = map[string]string{
"": "CSIDriverList is a collection of CSIDriver objects.",
"metadata": "Standard list metadata More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata",
"items": "items is the list of CSIDriver",
}
func (CSIDriverList) SwaggerDoc() map[string]string {
return map_CSIDriverList
}
var map_CSIDriverSpec = map[string]string{
"": "CSIDriverSpec is the specification of a CSIDriver.",
"attachRequired": "attachRequired indicates this CSI volume driver requires an attach operation (because it implements the CSI ControllerPublishVolume() method), and that the Kubernetes attach detach controller should call the attach volume interface which checks the volumeattachment status and waits until the volume is attached before proceeding to mounting. The CSI external-attacher coordinates with CSI volume driver and updates the volumeattachment status when the attach operation is complete. If the CSIDriverRegistry feature gate is enabled and the value is specified to false, the attach operation will be skipped. Otherwise the attach operation will be called.",
"podInfoOnMount": "If set to true, podInfoOnMount indicates this CSI volume driver requires additional pod information (like podName, podUID, etc.) during mount operations. If set to false, pod information will not be passed on mount. Default is false. The CSI driver specifies podInfoOnMount as part of driver deployment. If true, Kubelet will pass pod information as VolumeContext in the CSI NodePublishVolume() calls. The CSI driver is responsible for parsing and validating the information passed in as VolumeContext. The following VolumeConext will be passed if podInfoOnMount is set to true. This list might grow, but the prefix will be used. \"csi.storage.k8s.io/pod.name\": pod.Name \"csi.storage.k8s.io/pod.namespace\": pod.Namespace \"csi.storage.k8s.io/pod.uid\": string(pod.UID)",
}
func (CSIDriverSpec) SwaggerDoc() map[string]string {
return map_CSIDriverSpec
}
var map_CSINode = map[string]string{
"": "CSINode holds information about all CSI drivers installed on a node. CSI drivers do not need to create the CSINode object directly. As long as they use the node-driver-registrar sidecar container, the kubelet will automatically populate the CSINode object for the CSI driver as part of kubelet plugin registration. CSINode has the same name as a node. If the object is missing, it means either there are no CSI Drivers available on the node, or the Kubelet version is low enough that it doesn't create this object. CSINode has an OwnerReference that points to the corresponding node object.",
"metadata": "metadata.name must be the Kubernetes node name.",
"spec": "spec is the specification of CSINode",
}
func (CSINode) SwaggerDoc() map[string]string {
return map_CSINode
}
var map_CSINodeDriver = map[string]string{
"": "CSINodeDriver holds information about the specification of one CSI driver installed on a node",
"name": "This is the name of the CSI driver that this object refers to. This MUST be the same name returned by the CSI GetPluginName() call for that driver.",
"nodeID": "nodeID of the node from the driver point of view. This field enables Kubernetes to communicate with storage systems that do not share the same nomenclature for nodes. For example, Kubernetes may refer to a given node as \"node1\", but the storage system may refer to the same node as \"nodeA\". When Kubernetes issues a command to the storage system to attach a volume to a specific node, it can use this field to refer to the node name using the ID that the storage system will understand, e.g. \"nodeA\" instead of \"node1\". This field is required.",
"topologyKeys": "topologyKeys is the list of keys supported by the driver. When a driver is initialized on a cluster, it provides a set of topology keys that it understands (e.g. \"company.com/zone\", \"company.com/region\"). When a driver is initialized on a node, it provides the same topology keys along with values. Kubelet will expose these topology keys as labels on its own node object. When Kubernetes does topology aware provisioning, it can use this list to determine which labels it should retrieve from the node object and pass back to the driver. It is possible for different nodes to use different topology keys. This can be empty if driver does not support topology.",
}
func (CSINodeDriver) SwaggerDoc() map[string]string {
return map_CSINodeDriver
}
var map_CSINodeList = map[string]string{
"": "CSINodeList is a collection of CSINode objects.",
"metadata": "Standard list metadata More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata",
"items": "items is the list of CSINode",
}
func (CSINodeList) SwaggerDoc() map[string]string {
return map_CSINodeList
}
var map_CSINodeSpec = map[string]string{
"": "CSINodeSpec holds information about the specification of all CSI drivers installed on a node",
"drivers": "drivers is a list of information of all CSI Drivers existing on a node. If all drivers in the list are uninstalled, this can become empty.",
}
func (CSINodeSpec) SwaggerDoc() map[string]string {
return map_CSINodeSpec
}
var map_StorageClass = map[string]string{ var map_StorageClass = map[string]string{
"": "StorageClass describes the parameters for a class of storage for which PersistentVolumes can be dynamically provisioned.\n\nStorageClasses are non-namespaced; the name of the storage class according to etcd is in ObjectMeta.Name.", "": "StorageClass describes the parameters for a class of storage for which PersistentVolumes can be dynamically provisioned.\n\nStorageClasses are non-namespaced; the name of the storage class according to etcd is in ObjectMeta.Name.",
"metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata",
......
...@@ -26,6 +26,196 @@ import ( ...@@ -26,6 +26,196 @@ import (
) )
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CSIDriver) DeepCopyInto(out *CSIDriver) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSIDriver.
func (in *CSIDriver) DeepCopy() *CSIDriver {
if in == nil {
return nil
}
out := new(CSIDriver)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *CSIDriver) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CSIDriverList) DeepCopyInto(out *CSIDriverList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]CSIDriver, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSIDriverList.
func (in *CSIDriverList) DeepCopy() *CSIDriverList {
if in == nil {
return nil
}
out := new(CSIDriverList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *CSIDriverList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CSIDriverSpec) DeepCopyInto(out *CSIDriverSpec) {
*out = *in
if in.AttachRequired != nil {
in, out := &in.AttachRequired, &out.AttachRequired
*out = new(bool)
**out = **in
}
if in.PodInfoOnMount != nil {
in, out := &in.PodInfoOnMount, &out.PodInfoOnMount
*out = new(bool)
**out = **in
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSIDriverSpec.
func (in *CSIDriverSpec) DeepCopy() *CSIDriverSpec {
if in == nil {
return nil
}
out := new(CSIDriverSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CSINode) DeepCopyInto(out *CSINode) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSINode.
func (in *CSINode) DeepCopy() *CSINode {
if in == nil {
return nil
}
out := new(CSINode)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *CSINode) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CSINodeDriver) DeepCopyInto(out *CSINodeDriver) {
*out = *in
if in.TopologyKeys != nil {
in, out := &in.TopologyKeys, &out.TopologyKeys
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSINodeDriver.
func (in *CSINodeDriver) DeepCopy() *CSINodeDriver {
if in == nil {
return nil
}
out := new(CSINodeDriver)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CSINodeList) DeepCopyInto(out *CSINodeList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]CSINode, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSINodeList.
func (in *CSINodeList) DeepCopy() *CSINodeList {
if in == nil {
return nil
}
out := new(CSINodeList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *CSINodeList) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *CSINodeSpec) DeepCopyInto(out *CSINodeSpec) {
*out = *in
if in.Drivers != nil {
in, out := &in.Drivers, &out.Drivers
*out = make([]CSINodeDriver, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CSINodeSpec.
func (in *CSINodeSpec) DeepCopy() *CSINodeSpec {
if in == nil {
return nil
}
out := new(CSINodeSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *StorageClass) DeepCopyInto(out *StorageClass) { func (in *StorageClass) DeepCopyInto(out *StorageClass) {
*out = *in *out = *in
out.TypeMeta = in.TypeMeta out.TypeMeta = in.TypeMeta
......
...@@ -280,6 +280,10 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource ...@@ -280,6 +280,10 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
return &genericInformer{resource: resource.GroupResource(), informer: f.Storage().V1alpha1().VolumeAttachments().Informer()}, nil return &genericInformer{resource: resource.GroupResource(), informer: f.Storage().V1alpha1().VolumeAttachments().Informer()}, nil
// Group=storage.k8s.io, Version=v1beta1 // Group=storage.k8s.io, Version=v1beta1
case storagev1beta1.SchemeGroupVersion.WithResource("csidrivers"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Storage().V1beta1().CSIDrivers().Informer()}, nil
case storagev1beta1.SchemeGroupVersion.WithResource("csinodes"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Storage().V1beta1().CSINodes().Informer()}, nil
case storagev1beta1.SchemeGroupVersion.WithResource("storageclasses"): case storagev1beta1.SchemeGroupVersion.WithResource("storageclasses"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Storage().V1beta1().StorageClasses().Informer()}, nil return &genericInformer{resource: resource.GroupResource(), informer: f.Storage().V1beta1().StorageClasses().Informer()}, nil
case storagev1beta1.SchemeGroupVersion.WithResource("volumeattachments"): case storagev1beta1.SchemeGroupVersion.WithResource("volumeattachments"):
......
...@@ -8,6 +8,8 @@ load( ...@@ -8,6 +8,8 @@ load(
go_library( go_library(
name = "go_default_library", name = "go_default_library",
srcs = [ srcs = [
"csidriver.go",
"csinode.go",
"interface.go", "interface.go",
"storageclass.go", "storageclass.go",
"volumeattachment.go", "volumeattachment.go",
......
/*
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 informer-gen. DO NOT EDIT.
package v1beta1
import (
time "time"
storagev1beta1 "k8s.io/api/storage/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
kubernetes "k8s.io/client-go/kubernetes"
v1beta1 "k8s.io/client-go/listers/storage/v1beta1"
cache "k8s.io/client-go/tools/cache"
)
// CSIDriverInformer provides access to a shared informer and lister for
// CSIDrivers.
type CSIDriverInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1beta1.CSIDriverLister
}
type cSIDriverInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// NewCSIDriverInformer constructs a new informer for CSIDriver type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewCSIDriverInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredCSIDriverInformer(client, resyncPeriod, indexers, nil)
}
// NewFilteredCSIDriverInformer constructs a new informer for CSIDriver type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredCSIDriverInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.StorageV1beta1().CSIDrivers().List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.StorageV1beta1().CSIDrivers().Watch(options)
},
},
&storagev1beta1.CSIDriver{},
resyncPeriod,
indexers,
)
}
func (f *cSIDriverInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredCSIDriverInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *cSIDriverInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&storagev1beta1.CSIDriver{}, f.defaultInformer)
}
func (f *cSIDriverInformer) Lister() v1beta1.CSIDriverLister {
return v1beta1.NewCSIDriverLister(f.Informer().GetIndexer())
}
/*
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 informer-gen. DO NOT EDIT.
package v1beta1
import (
time "time"
storagev1beta1 "k8s.io/api/storage/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
internalinterfaces "k8s.io/client-go/informers/internalinterfaces"
kubernetes "k8s.io/client-go/kubernetes"
v1beta1 "k8s.io/client-go/listers/storage/v1beta1"
cache "k8s.io/client-go/tools/cache"
)
// CSINodeInformer provides access to a shared informer and lister for
// CSINodes.
type CSINodeInformer interface {
Informer() cache.SharedIndexInformer
Lister() v1beta1.CSINodeLister
}
type cSINodeInformer struct {
factory internalinterfaces.SharedInformerFactory
tweakListOptions internalinterfaces.TweakListOptionsFunc
}
// NewCSINodeInformer constructs a new informer for CSINode type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewCSINodeInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
return NewFilteredCSINodeInformer(client, resyncPeriod, indexers, nil)
}
// NewFilteredCSINodeInformer constructs a new informer for CSINode type.
// Always prefer using an informer factory to get a shared informer instead of getting an independent
// one. This reduces memory footprint and number of connections to the server.
func NewFilteredCSINodeInformer(client kubernetes.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.StorageV1beta1().CSINodes().List(options)
},
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.StorageV1beta1().CSINodes().Watch(options)
},
},
&storagev1beta1.CSINode{},
resyncPeriod,
indexers,
)
}
func (f *cSINodeInformer) defaultInformer(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
return NewFilteredCSINodeInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
}
func (f *cSINodeInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&storagev1beta1.CSINode{}, f.defaultInformer)
}
func (f *cSINodeInformer) Lister() v1beta1.CSINodeLister {
return v1beta1.NewCSINodeLister(f.Informer().GetIndexer())
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment