From 95f6411d04345b5c7dd94614b34f6b9e8c73f000 Mon Sep 17 00:00:00 2001 From: Amarnath Valluri Date: Sat, 14 Nov 2020 08:59:23 +0200 Subject: [PATCH] operator: changes to support multiple api versions By moving the core deployment API fields that are expected to be supported by all future API versions, we could minimize the code duplication. Hence moved such fields into the `base` package that supposed to inherited by all the API versions. Made '{Controller,Node}Resources' specific to v1alpha1 api as upcoming v1beta1 version plans to deprecate them in favour of container specific resources. --- deploy/yamls.go | 6 +- pkg/apis/pmemcsi/base/base_types.go | 291 ++++++++++++++++ pkg/apis/pmemcsi/base/defaults.go | 57 ++++ pkg/apis/pmemcsi/base/doc.go | 11 + .../pmemcsi/base/zz_generated.deepcopy.go | 123 +++++++ pkg/apis/pmemcsi/v1alpha1/deployment_types.go | 323 +----------------- .../pmemcsi/v1alpha1/deployment_types_test.go | 28 +- .../pmemcsi/v1alpha1/zz_generated.deepcopy.go | 102 +----- pkg/deployments/load.go | 9 +- pkg/deployments/load_test.go | 3 +- pkg/pmem-csi-driver/main.go | 2 +- pkg/pmem-csi-driver/parameters/parameters.go | 12 +- pkg/pmem-csi-driver/pmem-csi-driver.go | 4 +- .../deployment/controller_driver.go | 17 +- .../deployment/deployment_controller.go | 15 +- .../deployment/deployment_controller_test.go | 161 ++++----- .../deployment/testcases/testcases.go | 31 +- pkg/pmem-device-manager/pmd-fake.go | 2 +- pkg/pmem-device-manager/pmd-lvm.go | 2 +- pkg/pmem-device-manager/pmd-manager.go | 2 +- pkg/pmem-device-manager/pmd-ndctl.go | 2 +- test/e2e/deploy/deploy.go | 27 +- test/e2e/deploy/volumeleaks.go | 6 +- test/e2e/operator/deployment_api.go | 69 ++-- test/e2e/storage/sanity.go | 4 +- 25 files changed, 711 insertions(+), 598 deletions(-) create mode 100644 pkg/apis/pmemcsi/base/base_types.go create mode 100644 pkg/apis/pmemcsi/base/defaults.go create mode 100644 pkg/apis/pmemcsi/base/doc.go create mode 100644 pkg/apis/pmemcsi/base/zz_generated.deepcopy.go diff --git a/deploy/yamls.go b/deploy/yamls.go index 071c850488..8d85dd5854 100644 --- a/deploy/yamls.go +++ b/deploy/yamls.go @@ -10,7 +10,7 @@ import ( "fmt" "regexp" - api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" + "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" "github.com/intel/pmem-csi/pkg/version" ) @@ -29,7 +29,7 @@ type YamlFile struct { // DeviceMode defines in which mode the deployed driver will // operate. - DeviceMode api.DeviceMode + DeviceMode base.DeviceMode } var yamls []YamlFile @@ -50,7 +50,7 @@ func init() { Name: file, Kubernetes: kubernetes, Flavor: parts[3], - DeviceMode: api.DeviceMode(parts[3]), + DeviceMode: base.DeviceMode(parts[3]), }) } } diff --git a/pkg/apis/pmemcsi/base/base_types.go b/pkg/apis/pmemcsi/base/base_types.go new file mode 100644 index 0000000000..256282f0cd --- /dev/null +++ b/pkg/apis/pmemcsi/base/base_types.go @@ -0,0 +1,291 @@ +/* +Copyright 2020 The Kubernetes Authors. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package base + +import ( + "errors" + "fmt" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// DeviceMode type decleration for allowed driver device managers +type DeviceMode string + +// +kubebuilder:validation:Enum=lvm,direct +const ( + // DeviceModeLVM represents 'lvm' device manager + DeviceModeLVM DeviceMode = "lvm" + // DeviceModeDirect represents 'direct' device manager + DeviceModeDirect DeviceMode = "direct" + // DeviceModeFake represents a device manager for testing: + // volume creation and deletion is just recorded in memory, + // without any actual backing store. Such fake volumes cannot + // be used for pods. + DeviceModeFake DeviceMode = "fake" +) + +// Set sets the value +func (mode *DeviceMode) Set(value string) error { + switch value { + case string(DeviceModeLVM), string(DeviceModeDirect), string(DeviceModeFake): + *mode = DeviceMode(value) + case "ndctl": + // For backwards-compatibility. + *mode = DeviceModeDirect + default: + return errors.New("invalid device manager mode") + } + return nil +} + +func (mode *DeviceMode) String() string { + return string(*mode) +} + +// DriverType type decleration for representing the type of driver instance +type DriverType int + +const ( + // ControllerDriver represents controller driver instance + ControllerDriver DriverType = iota + // NodeDriver represents driver instance running on worker nodes + NodeDriver +) + +func (t DriverType) String() string { + switch t { + case ControllerDriver: + return "Controller" + case NodeDriver: + return "Node" + } + return "" +} + +// NOTE(avalluri): Due to below errors we stop setting +// few CRD schema fields by prefixing those lines a '-'. +// Once the below issues go fixed replace those '-' with '+' +// Setting default(+kubebuilder:default=value) for v1beta1 CRD fails, only supports since v1 CRD. +// Related issue : https://github.com/kubernetes-sigs/controller-tools/issues/478 +// Fails setting min/max for integers: https://github.com/helm/helm/issues/5806 + +// DeploymentSpec defines the desired state of Deployment +// +k8s:deepcopy-gen=true +type DeploymentSpec struct { + // Important: Run "make operator-generate-k8s" to regenerate code after modifying this file + + // PMEM-CSI driver container image + Image string `json:"image,omitempty"` + // PullPolicy image pull policy one of Always, Never, IfNotPresent + PullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` + // ProvisionerImage CSI provisioner sidecar image + ProvisionerImage string `json:"provisionerImage,omitempty"` + // NodeRegistrarImage CSI node driver registrar sidecar image + NodeRegistrarImage string `json:"nodeRegistrarImage,omitempty"` + // DeviceMode to use to manage PMEM devices. One of lvm, direct + // +kubebuilder:default:lvm + DeviceMode DeviceMode `json:"deviceMode,omitempty"` + // LogLevel number for the log verbosity + // +kubebuilder:validation:Required + // kubebuilder:default=3 + LogLevel uint16 `json:"logLevel,omitempty"` + // RegistryCert encoded certificate signed by a CA for registry server authentication + // If not provided, provisioned one by the operator using self-signed CA + RegistryCert []byte `json:"registryCert,omitempty"` + // RegistryPrivateKey encoded private key used for registry server certificate + // If not provided, provisioned one by the operator + RegistryPrivateKey []byte `json:"registryKey,omitempty"` + // NodeControllerCert encoded certificate signed by a CA for node controller server authentication + // If not provided, provisioned one by the operator using self-signed CA + NodeControllerCert []byte `json:"nodeControllerCert,omitempty"` + // NodeControllerPrivateKey encoded private key used for node controller server certificate + // If not provided, provisioned one by the operator + NodeControllerPrivateKey []byte `json:"nodeControllerKey,omitempty"` + // CACert encoded root certificate of the CA by which the registry and node controller certificates are signed + // If not provided operator uses a self-signed CA certificate + CACert []byte `json:"caCert,omitempty"` + // NodeSelector node labels to use for selection of driver node + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + // PMEMPercentage represents the percentage of space to be used by the driver in each PMEM region + // on every node. + // This is only valid for driver in LVM mode. + // +kubebuilder:validation:Required + // -kubebuilder:validation:Minimum=1 + // -kubebuilder:validation:Maximum=100 + // -kubebuilder:default=100 + PMEMPercentage uint16 `json:"pmemPercentage,omitempty"` + // Labels contains additional labels for all objects created by the operator. + Labels map[string]string `json:"labels,omitempty"` + // KubeletDir kubelet's root directory path + KubeletDir string `json:"kubeletDir,omitempty"` +} + +const ( + // EventReasonNew new driver deployment found + EventReasonNew = "NewDeployment" + // EventReasonRunning driver has been successfully deployed + EventReasonRunning = "Running" + // EventReasonFailed driver deployment failed, Event.Message holds detailed information + EventReasonFailed = "Failed" +) + +// DeploymentPhase represents the status phase of a driver deployment +type DeploymentPhase string + +const ( + // DeploymentPhaseNew indicates a new deployment + DeploymentPhaseNew DeploymentPhase = "" + // DeploymentPhaseRunning indicates that the deployment was successful + DeploymentPhaseRunning DeploymentPhase = "Running" + // DeploymentPhaseFailed indicates that the deployment was failed + DeploymentPhaseFailed DeploymentPhase = "Failed" +) + +// DeploymentConditionType type for representing a deployment status condition +type DeploymentConditionType string + +const ( + // CertsVerified means the provided deployment secrets are verified and valid for usage + CertsVerified DeploymentConditionType = "CertsVerified" + // CertsReady means secrests/certificates required for running the PMEM-CSI driver + // are ready and the deployment could progress further + CertsReady DeploymentConditionType = "CertsReady" + // DriverDeployed means that the all the sub-resources required for the deployment CR + // got created + DriverDeployed DeploymentConditionType = "DriverDeployed" +) + +// DeploymentCondition type definition for driver deployment status conditions +// +k8s:deepcopy-gen=true +type DeploymentCondition struct { + // Type of condition. + Type DeploymentConditionType `json:"type"` + // Status of the condition, one of True, False, Unknown. + Status corev1.ConditionStatus `json:"status"` + // Message human readable text that explain why this condition is in this state + // +optional + Reason string `json:"reason,omitempty"` + // Last time the condition was probed. + // +optional + LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"` +} + +// DriverStatus type definition for representing deployed driver status +// +k8s:deepcopy-gen=true +type DriverStatus struct { + // DriverComponent represents type of the driver: controller or node + DriverComponent string `json:"component"` + // Status represents the state of the component; one of `Ready` or `NotReady`. + // Component becomes `Ready` if all the instances(Pods) of the driver component + // are in running state. Otherwise, `NotReady`. + Status string `json:"status"` + // Reason represents the human readable text that explains why the + // driver is in this state. + Reason string `json:"reason"` + // LastUpdated time of the driver status + LastUpdated metav1.Time `json:"lastUpdated,omitempty"` +} + +// DeploymentStatus defines the observed state of Deployment +// +k8s:deepcopy-gen=true +type DeploymentStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make operator-generate-k8s" to regenerate code after modifying this file + + // Phase indicates the state of the deployment + Phase DeploymentPhase `json:"phase,omitempty"` + Reason string `json:"reason,omitempty"` + // Conditions + Conditions []DeploymentCondition `json:"conditions,omitempty"` + Components []DriverStatus `json:"driverComponents,omitempty"` + // LastUpdated time of the deployment status + LastUpdated metav1.Time `json:"lastUpdated,omitempty"` +} + +// SetDriverStatus set/updates the deployment status for given driver component +func (s *DeploymentStatus) SetDriverStatus(t DriverType, status, reason string) { + if s.Components == nil { + s.Components = make([]DriverStatus, 2) + } + s.Components[t] = DriverStatus{ + DriverComponent: t.String(), + Status: status, + Reason: reason, + LastUpdated: metav1.Now(), + } +} + +// SetCondition set/updates the deployment status condition +func (s *DeploymentStatus) SetCondition(t DeploymentConditionType, state corev1.ConditionStatus, reason string) { + for _, c := range s.Conditions { + if c.Type == t { + c.Status = state + c.Reason = reason + c.LastUpdateTime = metav1.Now() + return + } + } + s.Conditions = append(s.Conditions, DeploymentCondition{ + Type: t, + Status: state, + Reason: reason, + LastUpdateTime: metav1.Now(), + }) +} + +// EnsureDefaults make sure that the deployment object has all defaults set properly +func (spec *DeploymentSpec) EnsureDefaults(operatorImage string) error { + // Validate the given driver mode. + // In a realistic case this check might not needed as it should be + // handled by JSON schema as we defined deviceMode as enumeration. + switch spec.DeviceMode { + case "": + spec.DeviceMode = DefaultDeviceMode + case DeviceModeDirect, DeviceModeLVM: + default: + return fmt.Errorf("invalid device mode %q", spec.DeviceMode) + } + + if spec.Image == "" { + // If provided use operatorImage + if operatorImage != "" { + spec.Image = operatorImage + } else { + spec.Image = DefaultDriverImage + } + } + if spec.PullPolicy == "" { + spec.PullPolicy = DefaultImagePullPolicy + } + if spec.LogLevel == 0 { + spec.LogLevel = DefaultLogLevel + } + + if spec.ProvisionerImage == "" { + spec.ProvisionerImage = DefaultProvisionerImage + } + + if spec.NodeRegistrarImage == "" { + spec.NodeRegistrarImage = DefaultRegistrarImage + } + + if spec.NodeSelector == nil { + spec.NodeSelector = DefaultNodeSelector + } + + if spec.PMEMPercentage == 0 { + spec.PMEMPercentage = DefaultPMEMPercentage + } + + if spec.KubeletDir == "" { + spec.KubeletDir = DefaultKubeletDir + } + + return nil +} diff --git a/pkg/apis/pmemcsi/base/defaults.go b/pkg/apis/pmemcsi/base/defaults.go new file mode 100644 index 0000000000..a0a6d04b9a --- /dev/null +++ b/pkg/apis/pmemcsi/base/defaults.go @@ -0,0 +1,57 @@ +/* +Copyright 2020 The Kubernetes Authors. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package base + +import ( + corev1 "k8s.io/api/core/v1" +) + +const ( + // DefaultLogLevel default logging level used for the driver + DefaultLogLevel = uint16(5) + // DefaultImagePullPolicy default image pull policy for all the images used by the deployment + DefaultImagePullPolicy = corev1.PullIfNotPresent + + defaultDriverImageName = "intel/pmem-csi-driver" + defaultDriverImageTag = "canary" + // DefaultDriverImage default PMEM-CSI driver docker image + DefaultDriverImage = defaultDriverImageName + ":" + defaultDriverImageTag + + // The sidecar versions must be kept in sync with the + // deploy/kustomize YAML files! + + defaultProvisionerImageName = "k8s.gcr.io/sig-storage/csi-provisioner" + defaultProvisionerImageTag = "v2.0.2" + // DefaultProvisionerImage default external provisioner image to use + DefaultProvisionerImage = defaultProvisionerImageName + ":" + defaultProvisionerImageTag + + defaultRegistrarImageName = "k8s.gcr.io/sig-storage/csi-node-driver-registrar" + defaultRegistrarImageTag = "v1.2.0" + // DefaultRegistrarImage default node driver registrar image to use + DefaultRegistrarImage = defaultRegistrarImageName + ":" + defaultRegistrarImageTag + + // DefaultControllerResourceLimitCPU default CPU resource limit used for controller driver container + DefaultControllerResourceLimitCPU = "500m" // MilliSeconds + // DefaultControllerResourceLimitMemory default memory resource limit used for controller driver container + DefaultControllerResourceLimitMemory = "250Mi" // MB + // DefaultNodeResourceLimitCPU default CPU resource limit used for node driver container + DefaultNodeResourceLimitCPU = "600m" // MilliSeconds + // DefaultNodeResourceLimitMemory default memory resource limit used for node driver container + DefaultNodeResourceLimitMemory = "500Mi" // MB + + // DefaultDeviceMode default device manger used for deployment + DefaultDeviceMode = DeviceModeLVM + // DefaultPMEMPercentage PMEM space to reserve for the driver + DefaultPMEMPercentage = 100 + // DefaultKubeletDir default kubelet's path + DefaultKubeletDir = "/var/lib/kubelet" +) + +var ( + // DefaultNodeSelector default node label used for node selection + DefaultNodeSelector = map[string]string{"storage": "pmem"} +) diff --git a/pkg/apis/pmemcsi/base/doc.go b/pkg/apis/pmemcsi/base/doc.go new file mode 100644 index 0000000000..e6644f233c --- /dev/null +++ b/pkg/apis/pmemcsi/base/doc.go @@ -0,0 +1,11 @@ +/* +Copyright 2020 The Kubernetes Authors. + +SPDX-License-Identifier: Apache-2.0 +*/ + +// Package base contains definitions for types and functions that are +// supposed to shared by all the operator API groups +// +k8s:deepcopy-gen=package,register +// +groupName=pmem-csi.intel.com +package base diff --git a/pkg/apis/pmemcsi/base/zz_generated.deepcopy.go b/pkg/apis/pmemcsi/base/zz_generated.deepcopy.go new file mode 100644 index 0000000000..fbdb319378 --- /dev/null +++ b/pkg/apis/pmemcsi/base/zz_generated.deepcopy.go @@ -0,0 +1,123 @@ +// +build !ignore_autogenerated + +// Code generated by controller-gen. DO NOT EDIT. + +package base + +import () + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeploymentCondition) DeepCopyInto(out *DeploymentCondition) { + *out = *in + in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentCondition. +func (in *DeploymentCondition) DeepCopy() *DeploymentCondition { + if in == nil { + return nil + } + out := new(DeploymentCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeploymentSpec) DeepCopyInto(out *DeploymentSpec) { + *out = *in + if in.RegistryCert != nil { + in, out := &in.RegistryCert, &out.RegistryCert + *out = make([]byte, len(*in)) + copy(*out, *in) + } + if in.RegistryPrivateKey != nil { + in, out := &in.RegistryPrivateKey, &out.RegistryPrivateKey + *out = make([]byte, len(*in)) + copy(*out, *in) + } + if in.NodeControllerCert != nil { + in, out := &in.NodeControllerCert, &out.NodeControllerCert + *out = make([]byte, len(*in)) + copy(*out, *in) + } + if in.NodeControllerPrivateKey != nil { + in, out := &in.NodeControllerPrivateKey, &out.NodeControllerPrivateKey + *out = make([]byte, len(*in)) + copy(*out, *in) + } + if in.CACert != nil { + in, out := &in.CACert, &out.CACert + *out = make([]byte, len(*in)) + copy(*out, *in) + } + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentSpec. +func (in *DeploymentSpec) DeepCopy() *DeploymentSpec { + if in == nil { + return nil + } + out := new(DeploymentSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DeploymentStatus) DeepCopyInto(out *DeploymentStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]DeploymentCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Components != nil { + in, out := &in.Components, &out.Components + *out = make([]DriverStatus, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.LastUpdated.DeepCopyInto(&out.LastUpdated) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentStatus. +func (in *DeploymentStatus) DeepCopy() *DeploymentStatus { + if in == nil { + return nil + } + out := new(DeploymentStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DriverStatus) DeepCopyInto(out *DriverStatus) { + *out = *in + in.LastUpdated.DeepCopyInto(&out.LastUpdated) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DriverStatus. +func (in *DriverStatus) DeepCopy() *DriverStatus { + if in == nil { + return nil + } + out := new(DriverStatus) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/apis/pmemcsi/v1alpha1/deployment_types.go b/pkg/apis/pmemcsi/v1alpha1/deployment_types.go index 58b5e830b0..deb2f5b09a 100644 --- a/pkg/apis/pmemcsi/v1alpha1/deployment_types.go +++ b/pkg/apis/pmemcsi/v1alpha1/deployment_types.go @@ -7,186 +7,26 @@ SPDX-License-Identifier: Apache-2.0 package v1alpha1 import ( - "errors" "fmt" "strings" + "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -// DeviceMode type decleration for allowed driver device managers -type DeviceMode string - -// Set sets the value -func (mode *DeviceMode) Set(value string) error { - switch value { - case string(DeviceModeLVM), string(DeviceModeDirect), string(DeviceModeFake): - *mode = DeviceMode(value) - case "ndctl": - // For backwards-compatibility. - *mode = DeviceModeDirect - default: - return errors.New("invalid device manager mode") - } - return nil -} - -func (mode *DeviceMode) String() string { - return string(*mode) -} - -// +kubebuilder:validation:Enum=lvm,direct -const ( - // DeviceModeLVM represents 'lvm' device manager - DeviceModeLVM DeviceMode = "lvm" - // DeviceModeDirect represents 'direct' device manager - DeviceModeDirect DeviceMode = "direct" - // DeviceModeFake represents a device manager for testing: - // volume creation and deletion is just recorded in memory, - // without any actual backing store. Such fake volumes cannot - // be used for pods. - DeviceModeFake DeviceMode = "fake" -) - -// NOTE(avalluri): Due to below errors we stop setting -// few CRD schema fields by prefixing those lines a '-'. -// Once the below issues go fixed replace those '-' with '+' -// Setting default(+kubebuilder:default=value) for v1beta1 CRD fails, only supports since v1 CRD. -// Related issue : https://github.com/kubernetes-sigs/controller-tools/issues/478 -// Fails setting min/max for integers: https://github.com/helm/helm/issues/5806 - // +k8s:deepcopy-gen=true // DeploymentSpec defines the desired state of Deployment type DeploymentSpec struct { // Important: Run "make operator-generate-k8s" to regenerate code after modifying this file - // PMEM-CSI driver container image - Image string `json:"image,omitempty"` - // PullPolicy image pull policy one of Always, Never, IfNotPresent - PullPolicy corev1.PullPolicy `json:"imagePullPolicy,omitempty"` - // ProvisionerImage CSI provisioner sidecar image - ProvisionerImage string `json:"provisionerImage,omitempty"` - // NodeRegistrarImage CSI node driver registrar sidecar image - NodeRegistrarImage string `json:"nodeRegistrarImage,omitempty"` + base.DeploymentSpec `json:",inline"` + // ControllerResources Compute resources required by Controller driver ControllerResources *corev1.ResourceRequirements `json:"controllerResources,omitempty"` // NodeResources Compute resources required by Node driver NodeResources *corev1.ResourceRequirements `json:"nodeResources,omitempty"` - // DeviceMode to use to manage PMEM devices. One of lvm, direct - // +kubebuilder:default:lvm - DeviceMode DeviceMode `json:"deviceMode,omitempty"` - // LogLevel number for the log verbosity - // +kubebuilder:validation:Required - // kubebuilder:default=3 - LogLevel uint16 `json:"logLevel,omitempty"` - // RegistryCert encoded certificate signed by a CA for registry server authentication - // If not provided, provisioned one by the operator using self-signed CA - RegistryCert []byte `json:"registryCert,omitempty"` - // RegistryPrivateKey encoded private key used for registry server certificate - // If not provided, provisioned one by the operator - RegistryPrivateKey []byte `json:"registryKey,omitempty"` - // NodeControllerCert encoded certificate signed by a CA for node controller server authentication - // If not provided, provisioned one by the operator using self-signed CA - NodeControllerCert []byte `json:"nodeControllerCert,omitempty"` - // NodeControllerPrivateKey encoded private key used for node controller server certificate - // If not provided, provisioned one by the operator - NodeControllerPrivateKey []byte `json:"nodeControllerKey,omitempty"` - // CACert encoded root certificate of the CA by which the registry and node controller certificates are signed - // If not provided operator uses a self-signed CA certificate - CACert []byte `json:"caCert,omitempty"` - // NodeSelector node labels to use for selection of driver node - NodeSelector map[string]string `json:"nodeSelector,omitempty"` - // PMEMPercentage represents the percentage of space to be used by the driver in each PMEM region - // on every node. - // This is only valid for driver in LVM mode. - // +kubebuilder:validation:Required - // -kubebuilder:validation:Minimum=1 - // -kubebuilder:validation:Maximum=100 - // -kubebuilder:default=100 - PMEMPercentage uint16 `json:"pmemPercentage,omitempty"` - // Labels contains additional labels for all objects created by the operator. - Labels map[string]string `json:"labels,omitempty"` - // KubeletDir kubelet's root directory path - KubeletDir string `json:"kubeletDir,omitempty"` -} - -// DeploymentConditionType type for representing a deployment status condition -type DeploymentConditionType string - -const ( - // CertsVerified means the provided deployment secrets are verified and valid for usage - CertsVerified DeploymentConditionType = "CertsVerified" - // CertsReady means secrests/certificates required for running the PMEM-CSI driver - // are ready and the deployment could progress further - CertsReady DeploymentConditionType = "CertsReady" - // DriverDeployed means that the all the sub-resources required for the deployment CR - // got created - DriverDeployed DeploymentConditionType = "DriverDeployed" -) - -// +k8s:deepcopy-gen=true -type DeploymentCondition struct { - // Type of condition. - Type DeploymentConditionType `json:"type"` - // Status of the condition, one of True, False, Unknown. - Status corev1.ConditionStatus `json:"status"` - // Message human readable text that explain why this condition is in this state - // +optional - Reason string `json:"reason,omitempty"` - // Last time the condition was probed. - // +optional - LastUpdateTime metav1.Time `json:"lastUpdateTime,omitempty"` -} - -type DriverType int - -const ( - ControllerDriver DriverType = iota - NodeDriver -) - -func (t DriverType) String() string { - switch t { - case ControllerDriver: - return "Controller" - case NodeDriver: - return "Node" - } - return "" -} - -// +k8s:deepcopy-gen=true -type DriverStatus struct { - // DriverComponent represents type of the driver: controller or node - DriverComponent string `json:"component"` - // Status represents the state of the component; one of `Ready` or `NotReady`. - // Component becomes `Ready` if all the instances(Pods) of the driver component - // are in running state. Otherwise, `NotReady`. - Status string `json:"status"` - // Reason represents the human readable text that explains why the - // driver is in this state. - Reason string `json:"reason"` - // LastUpdated time of the driver status - LastUpdated metav1.Time `json:"lastUpdated,omitempty"` -} - -// +k8s:deepcopy-gen=true - -// DeploymentStatus defines the observed state of Deployment -type DeploymentStatus struct { - // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - // Important: Run "make operator-generate-k8s" to regenerate code after modifying this file - - // Phase indicates the state of the deployment - Phase DeploymentPhase `json:"phase,omitempty"` - Reason string `json:"reason,omitempty"` - // Conditions - Conditions []DeploymentCondition `json:"conditions,omitempty"` - Components []DriverStatus `json:"driverComponents,omitempty"` - // LastUpdated time of the deployment status - LastUpdated metav1.Time `json:"lastUpdated,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -203,8 +43,8 @@ type Deployment struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec DeploymentSpec `json:"spec,omitempty"` - Status DeploymentStatus `json:"status,omitempty"` + Spec DeploymentSpec `json:"spec,omitempty"` + Status base.DeploymentStatus `json:"status,omitempty"` } // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -220,171 +60,38 @@ func init() { SchemeBuilder.Register(&Deployment{}, &DeploymentList{}) } -const ( - // EventReasonNew new driver deployment found - EventReasonNew = "NewDeployment" - // EventReasonRunning driver has been successfully deployed - EventReasonRunning = "Running" - // EventReasonFailed driver deployment failed, Event.Message holds detailed information - EventReasonFailed = "Failed" -) - -const ( - // DefaultLogLevel default logging level used for the driver - DefaultLogLevel = uint16(5) - // DefaultImagePullPolicy default image pull policy for all the images used by the deployment - DefaultImagePullPolicy = corev1.PullIfNotPresent - - defaultDriverImageName = "intel/pmem-csi-driver" - defaultDriverImageTag = "canary" - // DefaultDriverImage default PMEM-CSI driver docker image - DefaultDriverImage = defaultDriverImageName + ":" + defaultDriverImageTag - - // The sidecar versions must be kept in sync with the - // deploy/kustomize YAML files! - - defaultProvisionerImageName = "k8s.gcr.io/sig-storage/csi-provisioner" - defaultProvisionerImageTag = "v2.0.2" - // DefaultProvisionerImage default external provisioner image to use - DefaultProvisionerImage = defaultProvisionerImageName + ":" + defaultProvisionerImageTag - - defaultRegistrarImageName = "k8s.gcr.io/sig-storage/csi-node-driver-registrar" - defaultRegistrarImageTag = "v1.2.0" - // DefaultRegistrarImage default node driver registrar image to use - DefaultRegistrarImage = defaultRegistrarImageName + ":" + defaultRegistrarImageTag - - // DefaultControllerResourceCPU default CPU resource limit used for controller pod - DefaultControllerResourceCPU = "100m" // MilliSeconds - // DefaultControllerResourceMemory default memory resource limit used for controller pod - DefaultControllerResourceMemory = "250Mi" // MB - // DefaultNodeResourceCPU default CPU resource limit used for node driver pod - DefaultNodeResourceCPU = "100m" // MilliSeconds - // DefaultNodeResourceMemory default memory resource limit used for node driver pod - DefaultNodeResourceMemory = "250Mi" // MB - // DefaultDeviceMode default device manger used for deployment - DefaultDeviceMode = DeviceModeLVM - // DefaultPMEMPercentage PMEM space to reserve for the driver - DefaultPMEMPercentage = 100 - // DefaultKubeletDir default kubelet's path - DefaultKubeletDir = "/var/lib/kubelet" -) - -var ( - // DefaultNodeSelector default node label used for node selection - DefaultNodeSelector = map[string]string{"storage": "pmem"} -) - -// DeploymentPhase represents the status phase of a driver deployment -type DeploymentPhase string - -const ( - // DeploymentPhaseNew indicates a new deployment - DeploymentPhaseNew DeploymentPhase = "" - // DeploymentPhaseRunning indicates that the deployment was successful - DeploymentPhaseRunning DeploymentPhase = "Running" - // DeploymentPhaseFailed indicates that the deployment was failed - DeploymentPhaseFailed DeploymentPhase = "Failed" -) - -func (d *Deployment) SetCondition(t DeploymentConditionType, state corev1.ConditionStatus, reason string) { - for _, c := range d.Status.Conditions { - if c.Type == t { - c.Status = state - c.Reason = reason - c.LastUpdateTime = metav1.Now() - return - } - } - d.Status.Conditions = append(d.Status.Conditions, DeploymentCondition{ - Type: t, - Status: state, - Reason: reason, - LastUpdateTime: metav1.Now(), - }) +func (d *Deployment) SetCondition(t base.DeploymentConditionType, state corev1.ConditionStatus, reason string) { + d.Status.SetCondition(t, state, reason) } -func (d *Deployment) SetDriverStatus(t DriverType, status, reason string) { - if d.Status.Components == nil { - d.Status.Components = make([]DriverStatus, 2) - } - d.Status.Components[t] = DriverStatus{ - DriverComponent: t.String(), - Status: status, - Reason: reason, - LastUpdated: metav1.Now(), - } +func (d *Deployment) SetDriverStatus(t base.DriverType, status, reason string) { + d.Status.SetDriverStatus(t, status, reason) } // EnsureDefaults make sure that the deployment object has all defaults set properly func (d *Deployment) EnsureDefaults(operatorImage string) error { - if d.Spec.Image == "" { - // If provided use operatorImage - if operatorImage != "" { - d.Spec.Image = operatorImage - } else { - d.Spec.Image = DefaultDriverImage - } - } - if d.Spec.PullPolicy == "" { - d.Spec.PullPolicy = DefaultImagePullPolicy - } - if d.Spec.LogLevel == 0 { - d.Spec.LogLevel = DefaultLogLevel - } - - /* Controller Defaults */ - - if d.Spec.ProvisionerImage == "" { - d.Spec.ProvisionerImage = DefaultProvisionerImage + if err := d.Spec.EnsureDefaults(operatorImage); err != nil { + return err } if d.Spec.ControllerResources == nil { d.Spec.ControllerResources = &corev1.ResourceRequirements{ Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse(DefaultControllerResourceCPU), - corev1.ResourceMemory: resource.MustParse(DefaultControllerResourceMemory), + corev1.ResourceCPU: resource.MustParse(base.DefaultControllerResourceLimitCPU), + corev1.ResourceMemory: resource.MustParse(base.DefaultControllerResourceLimitMemory), }, } } - /* Node Defaults */ - - // Validate the given driver mode. - // In a realistic case this check might not needed as it should be - // handled by JSON schema as we defined deviceMode as enumeration. - switch d.Spec.DeviceMode { - case "": - d.Spec.DeviceMode = DefaultDeviceMode - case DeviceModeDirect, DeviceModeLVM: - default: - return fmt.Errorf("invalid device mode %q", d.Spec.DeviceMode) - } - - if d.Spec.NodeRegistrarImage == "" { - d.Spec.NodeRegistrarImage = DefaultRegistrarImage - } - if d.Spec.NodeResources == nil { d.Spec.NodeResources = &corev1.ResourceRequirements{ Limits: corev1.ResourceList{ - corev1.ResourceCPU: resource.MustParse(DefaultNodeResourceCPU), - corev1.ResourceMemory: resource.MustParse(DefaultNodeResourceMemory), + corev1.ResourceCPU: resource.MustParse(base.DefaultNodeResourceLimitCPU), + corev1.ResourceMemory: resource.MustParse(base.DefaultNodeResourceLimitMemory), }, } } - if d.Spec.NodeSelector == nil { - d.Spec.NodeSelector = DefaultNodeSelector - } - - if d.Spec.PMEMPercentage == 0 { - d.Spec.PMEMPercentage = DefaultPMEMPercentage - } - - if d.Spec.KubeletDir == "" { - d.Spec.KubeletDir = DefaultKubeletDir - } - return nil } diff --git a/pkg/apis/pmemcsi/v1alpha1/deployment_types_test.go b/pkg/apis/pmemcsi/v1alpha1/deployment_types_test.go index 0641621814..e6d70cacc0 100644 --- a/pkg/apis/pmemcsi/v1alpha1/deployment_types_test.go +++ b/pkg/apis/pmemcsi/v1alpha1/deployment_types_test.go @@ -11,6 +11,7 @@ import ( "testing" "github.com/intel/pmem-csi/pkg/apis" + "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -42,22 +43,22 @@ var _ = Describe("Operator", func() { err := d.EnsureDefaults("") Expect(err).ShouldNot(HaveOccurred(), "ensure defaults") - Expect(d.Spec.LogLevel).Should(BeEquivalentTo(api.DefaultLogLevel), "default logging level mismatch") - Expect(d.Spec.DeviceMode).Should(BeEquivalentTo(api.DefaultDeviceMode), "default driver mode mismatch") - Expect(d.Spec.Image).Should(BeEquivalentTo(api.DefaultDriverImage), "default driver image mismatch") - Expect(d.Spec.PullPolicy).Should(BeEquivalentTo(api.DefaultImagePullPolicy), "default image pull policy mismatch") - Expect(d.Spec.ProvisionerImage).Should(BeEquivalentTo(api.DefaultProvisionerImage), "default provisioner image mismatch") - Expect(d.Spec.NodeRegistrarImage).Should(BeEquivalentTo(api.DefaultRegistrarImage), "default node driver registrar image mismatch") + Expect(d.Spec.LogLevel).Should(BeEquivalentTo(base.DefaultLogLevel), "default logging level mismatch") + Expect(d.Spec.DeviceMode).Should(BeEquivalentTo(base.DefaultDeviceMode), "default driver mode mismatch") + Expect(d.Spec.Image).Should(BeEquivalentTo(base.DefaultDriverImage), "default driver image mismatch") + Expect(d.Spec.PullPolicy).Should(BeEquivalentTo(base.DefaultImagePullPolicy), "default image pull policy mismatch") + Expect(d.Spec.ProvisionerImage).Should(BeEquivalentTo(base.DefaultProvisionerImage), "default provisioner image mismatch") + Expect(d.Spec.NodeRegistrarImage).Should(BeEquivalentTo(base.DefaultRegistrarImage), "default node driver registrar image mismatch") Expect(d.Spec.ControllerResources).ShouldNot(BeNil(), "default controller resources not set") rs := d.Spec.ControllerResources.Limits - Expect(rs.Cpu().String()).Should(BeEquivalentTo(api.DefaultControllerResourceCPU), "controller driver 'cpu' resource mismatch") - Expect(rs.Memory().String()).Should(BeEquivalentTo(api.DefaultControllerResourceMemory), "controller driver 'memory' resource mismatch") + Expect(rs.Cpu().String()).Should(BeEquivalentTo(base.DefaultControllerResourceLimitCPU), "controller driver 'cpu' resource limit mismatch") + Expect(rs.Memory().String()).Should(BeEquivalentTo(base.DefaultControllerResourceLimitMemory), "controller driver 'memory' resource limit mismatch") Expect(d.Spec.NodeResources).ShouldNot(BeNil(), "default node resources not set") nrs := d.Spec.NodeResources.Limits - Expect(nrs.Cpu().String()).Should(BeEquivalentTo(api.DefaultNodeResourceCPU), "node driver 'cpu' resource mismatch") - Expect(nrs.Memory().String()).Should(BeEquivalentTo(api.DefaultNodeResourceMemory), "node driver 'cpu' resource mismatch") + Expect(nrs.Cpu().String()).Should(BeEquivalentTo(base.DefaultNodeResourceLimitCPU), "node driver 'cpu' resource limit mismatch") + Expect(nrs.Memory().String()).Should(BeEquivalentTo(base.DefaultNodeResourceLimitMemory), "node driver 'memory' resource limit mismatch") }) It("shall be able to set values", func() { @@ -120,7 +121,12 @@ spec: _, _, err = deserializer.Decode(data, nil, crd) Expect(err).ShouldNot(HaveOccurred(), "decode crd file") - crdProp := crd.Spec.Versions[0].Schema.OpenAPIV3Schema + var crdProp *apiextensions.JSONSchemaProps + for _, v := range crd.Spec.Versions { + if v.Name == api.SchemeBuilder.GroupVersion.Version { + crdProp = v.Schema.OpenAPIV3Schema + } + } Expect(crdProp).ShouldNot(BeNil(), "Nil CRD schmea") Expect(crdProp.Type).Should(BeEquivalentTo("object"), "Deployment JSON schema type mismatch") spec, ok := crdProp.Properties["spec"] diff --git a/pkg/apis/pmemcsi/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/pmemcsi/v1alpha1/zz_generated.deepcopy.go index b74a372963..556ed16ca2 100644 --- a/pkg/apis/pmemcsi/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/pmemcsi/v1alpha1/zz_generated.deepcopy.go @@ -36,22 +36,6 @@ func (in *Deployment) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DeploymentCondition) DeepCopyInto(out *DeploymentCondition) { - *out = *in - in.LastUpdateTime.DeepCopyInto(&out.LastUpdateTime) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentCondition. -func (in *DeploymentCondition) DeepCopy() *DeploymentCondition { - if in == nil { - return nil - } - out := new(DeploymentCondition) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DeploymentList) DeepCopyInto(out *DeploymentList) { *out = *in @@ -87,6 +71,7 @@ func (in *DeploymentList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *DeploymentSpec) DeepCopyInto(out *DeploymentSpec) { *out = *in + in.DeploymentSpec.DeepCopyInto(&out.DeploymentSpec) if in.ControllerResources != nil { in, out := &in.ControllerResources, &out.ControllerResources *out = new(v1.ResourceRequirements) @@ -97,45 +82,6 @@ func (in *DeploymentSpec) DeepCopyInto(out *DeploymentSpec) { *out = new(v1.ResourceRequirements) (*in).DeepCopyInto(*out) } - if in.RegistryCert != nil { - in, out := &in.RegistryCert, &out.RegistryCert - *out = make([]byte, len(*in)) - copy(*out, *in) - } - if in.RegistryPrivateKey != nil { - in, out := &in.RegistryPrivateKey, &out.RegistryPrivateKey - *out = make([]byte, len(*in)) - copy(*out, *in) - } - if in.NodeControllerCert != nil { - in, out := &in.NodeControllerCert, &out.NodeControllerCert - *out = make([]byte, len(*in)) - copy(*out, *in) - } - if in.NodeControllerPrivateKey != nil { - in, out := &in.NodeControllerPrivateKey, &out.NodeControllerPrivateKey - *out = make([]byte, len(*in)) - copy(*out, *in) - } - if in.CACert != nil { - in, out := &in.CACert, &out.CACert - *out = make([]byte, len(*in)) - copy(*out, *in) - } - if in.NodeSelector != nil { - in, out := &in.NodeSelector, &out.NodeSelector - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } - if in.Labels != nil { - in, out := &in.Labels, &out.Labels - *out = make(map[string]string, len(*in)) - for key, val := range *in { - (*out)[key] = val - } - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentSpec. @@ -147,49 +93,3 @@ func (in *DeploymentSpec) DeepCopy() *DeploymentSpec { in.DeepCopyInto(out) return out } - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DeploymentStatus) DeepCopyInto(out *DeploymentStatus) { - *out = *in - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]DeploymentCondition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.Components != nil { - in, out := &in.Components, &out.Components - *out = make([]DriverStatus, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - in.LastUpdated.DeepCopyInto(&out.LastUpdated) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeploymentStatus. -func (in *DeploymentStatus) DeepCopy() *DeploymentStatus { - if in == nil { - return nil - } - out := new(DeploymentStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DriverStatus) DeepCopyInto(out *DriverStatus) { - *out = *in - in.LastUpdated.DeepCopyInto(&out.LastUpdated) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DriverStatus. -func (in *DriverStatus) DeepCopy() *DriverStatus { - if in == nil { - return nil - } - out := new(DriverStatus) - in.DeepCopyInto(out) - return out -} diff --git a/pkg/deployments/load.go b/pkg/deployments/load.go index 48e0c799c2..39f2d65fe6 100644 --- a/pkg/deployments/load.go +++ b/pkg/deployments/load.go @@ -14,6 +14,7 @@ import ( "strings" "github.com/intel/pmem-csi/deploy" + "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" "github.com/intel/pmem-csi/pkg/version" @@ -23,7 +24,7 @@ import ( ) // LoadObjects reads all objects stored in a pmem-csi.yaml reference file. -func LoadObjects(kubernetes version.Version, deviceMode api.DeviceMode) ([]unstructured.Unstructured, error) { +func LoadObjects(kubernetes version.Version, deviceMode base.DeviceMode) ([]unstructured.Unstructured, error) { return loadObjects(kubernetes, deviceMode, nil, nil) } @@ -32,7 +33,7 @@ var nameRegex = regexp.MustCompile(`(name|app|secretName|serviceName|serviceAcco // LoadAndCustomizeObjects reads all objects stored in a pmem-csi.yaml reference file // and updates them on-the-fly according to the deployment spec, namespace and name. -func LoadAndCustomizeObjects(kubernetes version.Version, deviceMode api.DeviceMode, +func LoadAndCustomizeObjects(kubernetes version.Version, deviceMode base.DeviceMode, namespace string, deployment api.Deployment) ([]unstructured.Unstructured, error) { // Conceptually this function is similar to calling "kustomize" for @@ -49,7 +50,7 @@ func LoadAndCustomizeObjects(kubernetes version.Version, deviceMode api.DeviceMo *yaml = bytes.ReplaceAll(*yaml, []byte("path: /var/lib/kubelet/plugins/pmem-csi.intel.com"), []byte("path: /var/lib/kubelet/plugins/"+deployment.Name)) // Update kubelet path - if deployment.Spec.KubeletDir != api.DefaultKubeletDir { + if deployment.Spec.KubeletDir != base.DefaultKubeletDir { *yaml = bytes.ReplaceAll(*yaml, []byte("/var/lib/kubelet"), []byte(deployment.Spec.KubeletDir)) } @@ -189,7 +190,7 @@ func patchPodTemplate(obj *unstructured.Unstructured, deployment api.Deployment, return nil } -func loadObjects(kubernetes version.Version, deviceMode api.DeviceMode, +func loadObjects(kubernetes version.Version, deviceMode base.DeviceMode, patchYAML func(yaml *[]byte), patchUnstructured func(obj *unstructured.Unstructured)) ([]unstructured.Unstructured, error) { path := fmt.Sprintf("deploy/kubernetes-%s/%s/pmem-csi.yaml", kubernetes, deviceMode) diff --git a/pkg/deployments/load_test.go b/pkg/deployments/load_test.go index 5bbab95837..7dc4380f0c 100644 --- a/pkg/deployments/load_test.go +++ b/pkg/deployments/load_test.go @@ -14,13 +14,14 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/intel/pmem-csi/deploy" + "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" "github.com/intel/pmem-csi/pkg/deployments" "github.com/intel/pmem-csi/pkg/version" ) func TestLoadObjects(t *testing.T) { - _, err := deployments.LoadObjects(version.NewVersion(1, 0), api.DeviceModeDirect) + _, err := deployments.LoadObjects(version.NewVersion(1, 0), base.DeviceModeDirect) assert.Error(t, err, "load yaml for unsupported version") yamls := deploy.ListAll() diff --git a/pkg/pmem-csi-driver/main.go b/pkg/pmem-csi-driver/main.go index 498e3dd749..aa65337ca7 100644 --- a/pkg/pmem-csi-driver/main.go +++ b/pkg/pmem-csi-driver/main.go @@ -14,7 +14,7 @@ import ( "k8s.io/klog/v2" - api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" + api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" "github.com/intel/pmem-csi/pkg/k8sutil" pmemcommon "github.com/intel/pmem-csi/pkg/pmem-common" ) diff --git a/pkg/pmem-csi-driver/parameters/parameters.go b/pkg/pmem-csi-driver/parameters/parameters.go index 30ce350dd6..bfa79cc4e6 100644 --- a/pkg/pmem-csi-driver/parameters/parameters.go +++ b/pkg/pmem-csi-driver/parameters/parameters.go @@ -11,7 +11,7 @@ import ( "strconv" "strings" - api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" + api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" "k8s.io/apimachinery/pkg/api/resource" ) @@ -58,7 +58,7 @@ const ( // valid is a whitelist of which parameters are valid in which context. var valid = map[Origin][]string{ // Parameters from Kubernetes and users for a persistent volume. - CreateVolumeOrigin: []string{ + CreateVolumeOrigin: { CacheSize, EraseAfter, KataContainers, @@ -66,7 +66,7 @@ var valid = map[Origin][]string{ }, // These parameters are prepared by the master controller. - CreateVolumeInternalOrigin: []string{ + CreateVolumeInternalOrigin: { CacheSize, EraseAfter, KataContainers, @@ -76,7 +76,7 @@ var valid = map[Origin][]string{ }, // Parameters from Kubernetes and users. - EphemeralVolumeOrigin: []string{ + EphemeralVolumeOrigin: { EraseAfter, KataContainers, PodInfoPrefix, @@ -88,7 +88,7 @@ var valid = map[Origin][]string{ // version of PMEM-CSI might need them (the current one // doesn't) and add the volume name for logging purposes. // Kubernetes adds pod info and provisioner ID. - PersistentVolumeOrigin: []string{ + PersistentVolumeOrigin: { CacheSize, EraseAfter, KataContainers, @@ -101,7 +101,7 @@ var valid = map[Origin][]string{ // Internally we store everything except the volume ID, // which is handled separately. - NodeVolumeOrigin: []string{ + NodeVolumeOrigin: { CacheSize, EraseAfter, KataContainers, diff --git a/pkg/pmem-csi-driver/pmem-csi-driver.go b/pkg/pmem-csi-driver/pmem-csi-driver.go index a17e4d19b4..c6d1aac1b7 100644 --- a/pkg/pmem-csi-driver/pmem-csi-driver.go +++ b/pkg/pmem-csi-driver/pmem-csi-driver.go @@ -20,7 +20,7 @@ import ( "syscall" "time" - api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" + "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" grpcserver "github.com/intel/pmem-csi/pkg/grpc-server" pmdmanager "github.com/intel/pmem-csi/pkg/pmem-device-manager" pmemgrpc "github.com/intel/pmem-csi/pkg/pmem-grpc" @@ -141,7 +141,7 @@ type Config struct { //ControllerEndpoint exported node controller endpoint ControllerEndpoint string //DeviceManager device manager to use - DeviceManager api.DeviceMode + DeviceManager base.DeviceMode //Directory where to persist the node driver state StateBasePath string //Version driver release version diff --git a/pkg/pmem-csi-operator/controller/deployment/controller_driver.go b/pkg/pmem-csi-operator/controller/deployment/controller_driver.go index f113f40a36..475c21f873 100644 --- a/pkg/pmem-csi-operator/controller/deployment/controller_driver.go +++ b/pkg/pmem-csi-operator/controller/deployment/controller_driver.go @@ -16,6 +16,7 @@ import ( "path" "runtime" + "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" grpcserver "github.com/intel/pmem-csi/pkg/grpc-server" pmemtls "github.com/intel/pmem-csi/pkg/pmem-csi-operator/pmem-tls" @@ -253,11 +254,11 @@ func (d *PmemCSIDriver) Reconcile(r *ReconcileDeployment) error { } if err := redeployAll(); err != nil { - d.SetCondition(api.DriverDeployed, corev1.ConditionFalse, err.Error()) + d.SetCondition(base.DriverDeployed, corev1.ConditionFalse, err.Error()) return err } - d.SetCondition(api.DriverDeployed, corev1.ConditionTrue, "Driver deployed successfully.") + d.SetCondition(base.DriverDeployed, corev1.ConditionTrue, "Driver deployed successfully.") klog.Infof("Deployed '%d' objects.", len(allObjects)) // FIXME(avalluri): Limit the obsolete object deletion either only on version upgrades @@ -387,15 +388,15 @@ func (d *PmemCSIDriver) redeploySecrets(r *ReconcileDeployment) ([]*corev1.Secre if certsProvided { // Use provided certificates if err := d.validateCertificates(); err != nil { - d.SetCondition(api.CertsVerified, corev1.ConditionFalse, err.Error()) + d.SetCondition(base.CertsVerified, corev1.ConditionFalse, err.Error()) return nil, err } - d.SetCondition(api.CertsVerified, corev1.ConditionTrue, "Driver certificates validated.") + d.SetCondition(base.CertsVerified, corev1.ConditionTrue, "Driver certificates validated.") updateSecrets = true } else if rop.IsNew() || nop.IsNew() { // Provision new self-signed certificates if not already present if err := d.provisionCertificates(); err != nil { - d.SetCondition(api.CertsReady, corev1.ConditionFalse, err.Error()) + d.SetCondition(base.CertsReady, corev1.ConditionFalse, err.Error()) return nil, err } updateSecrets = true @@ -406,7 +407,7 @@ func (d *PmemCSIDriver) redeploySecrets(r *ReconcileDeployment) ([]*corev1.Secre return nil, err } } - d.SetCondition(api.CertsReady, corev1.ConditionTrue, "Driver certificates are available.") + d.SetCondition(base.CertsReady, corev1.ConditionTrue, "Driver certificates are available.") return []*corev1.Secret{rs, ns}, nil } @@ -437,7 +438,7 @@ func (d *PmemCSIDriver) redeployNodeDriver(r *ReconcileDeployment) (apiruntime.O } else { reason = fmt.Sprintf("%d out of %d driver pods are ready", ds.Status.NumberReady, ds.Status.NumberAvailable) } - d.SetDriverStatus(api.NodeDriver, status, reason) + d.SetDriverStatus(base.NodeDriver, status, reason) return nil }, }) @@ -470,7 +471,7 @@ func (d *PmemCSIDriver) redeployControllerDriver(r *ReconcileDeployment) (apirun reason = fmt.Sprintf("Waiting for stateful set to be ready: %d of %d replicas are ready", ss.Status.ReadyReplicas, ss.Status.Replicas) } - d.SetDriverStatus(api.ControllerDriver, status, reason) + d.SetDriverStatus(base.ControllerDriver, status, reason) return nil }, }) diff --git a/pkg/pmem-csi-operator/controller/deployment/deployment_controller.go b/pkg/pmem-csi-operator/controller/deployment/deployment_controller.go index 4529d51f01..a38212ebd8 100644 --- a/pkg/pmem-csi-operator/controller/deployment/deployment_controller.go +++ b/pkg/pmem-csi-operator/controller/deployment/deployment_controller.go @@ -14,6 +14,7 @@ import ( "sync" "time" + "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" pmemcsiv1alpha1 "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" "github.com/intel/pmem-csi/pkg/k8sutil" pmemcontroller "github.com/intel/pmem-csi/pkg/pmem-csi-operator/controller" @@ -282,9 +283,9 @@ func (r *ReconcileDeployment) Reconcile(request reconcile.Request) (reconcile.Re } } - if deployment.Status.Phase == pmemcsiv1alpha1.DeploymentPhaseNew { + if deployment.Status.Phase == base.DeploymentPhaseNew { /* New deployment */ - r.evRecorder.Event(deployment, corev1.EventTypeNormal, pmemcsiv1alpha1.EventReasonNew, "Processing new driver deployment") + r.evRecorder.Event(deployment, corev1.EventTypeNormal, base.EventReasonNew, "Processing new driver deployment") } // Cache the deployment @@ -311,16 +312,16 @@ func (r *ReconcileDeployment) Reconcile(request reconcile.Request) (reconcile.Re d := &PmemCSIDriver{dep, r.namespace, r.k8sVersion} if err := d.Reconcile(r); err != nil { klog.Infof("Reconcile error: %v", err) - dep.Status.Phase = pmemcsiv1alpha1.DeploymentPhaseFailed + dep.Status.Phase = base.DeploymentPhaseFailed dep.Status.Reason = err.Error() - r.evRecorder.Event(dep, corev1.EventTypeWarning, pmemcsiv1alpha1.EventReasonFailed, err.Error()) + r.evRecorder.Event(dep, corev1.EventTypeWarning, base.EventReasonFailed, err.Error()) return reconcile.Result{Requeue: true, RequeueAfter: requeueDelayOnError}, err } - dep.Status.Phase = pmemcsiv1alpha1.DeploymentPhaseRunning + dep.Status.Phase = base.DeploymentPhaseRunning dep.Status.Reason = "All driver components are deployed successfully" - r.evRecorder.Event(dep, corev1.EventTypeNormal, pmemcsiv1alpha1.EventReasonRunning, "Driver deployment successful") + r.evRecorder.Event(dep, corev1.EventTypeNormal, base.EventReasonRunning, "Driver deployment successful") return reconcile.Result{}, nil } @@ -393,7 +394,7 @@ func (r *ReconcileDeployment) deleteDeployment(name string) { delete(r.deployments, name) } -func (r *ReconcileDeployment) cacheDeploymentStatus(name string, status pmemcsiv1alpha1.DeploymentStatus) { +func (r *ReconcileDeployment) cacheDeploymentStatus(name string, status base.DeploymentStatus) { r.deploymentsMutex.Lock() defer r.deploymentsMutex.Unlock() if d, ok := r.deployments[name]; ok { diff --git a/pkg/pmem-csi-operator/controller/deployment/deployment_controller_test.go b/pkg/pmem-csi-operator/controller/deployment/deployment_controller_test.go index cdbb3bdbef..d225168c3c 100644 --- a/pkg/pmem-csi-operator/controller/deployment/deployment_controller_test.go +++ b/pkg/pmem-csi-operator/controller/deployment/deployment_controller_test.go @@ -16,6 +16,7 @@ import ( "github.com/intel/pmem-csi/deploy" "github.com/intel/pmem-csi/pkg/apis" + "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" pmemcontroller "github.com/intel/pmem-csi/pkg/pmem-csi-operator/controller" "github.com/intel/pmem-csi/pkg/pmem-csi-operator/controller/deployment" @@ -69,7 +70,7 @@ func getDeployment(d *pmemDeployment) *api.Deployment { dep.Spec = api.DeploymentSpec{} spec := &dep.Spec - spec.DeviceMode = api.DeviceMode(d.deviceMode) + spec.DeviceMode = base.DeviceMode(d.deviceMode) spec.LogLevel = d.logLevel spec.Image = d.image spec.PullPolicy = corev1.PullPolicy(d.pullPolicy) @@ -103,7 +104,7 @@ func getDeployment(d *pmemDeployment) *api.Deployment { return dep } -func testDeploymentPhase(t *testing.T, c client.Client, name string, expectedPhase api.DeploymentPhase) { +func testDeploymentPhase(t *testing.T, c client.Client, name string, expectedPhase base.DeploymentPhase) { depObject := &api.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -129,7 +130,7 @@ func testReconcile(t *testing.T, rc reconcile.Reconciler, name string, expectErr require.Equal(t, expectedRequeue, resp.Requeue, "expected requeue reconcile") } -func testReconcilePhase(t *testing.T, rc reconcile.Reconciler, c client.Client, name string, expectErr bool, expectedRequeue bool, expectedPhase api.DeploymentPhase) { +func testReconcilePhase(t *testing.T, rc reconcile.Reconciler, c client.Client, name string, expectErr bool, expectedRequeue bool, expectedPhase base.DeploymentPhase) { testReconcile(t, rc, name, expectErr, expectedRequeue) testDeploymentPhase(t, c, name, expectedPhase) } @@ -248,7 +249,7 @@ func TestDeploymentController(t *testing.T) { require.ElementsMatch(t, events, expectedEvents, "events must match") } - validateConditions := func(t *testing.T, tc *testContext, name string, expected map[api.DeploymentConditionType]corev1.ConditionStatus) { + validateConditions := func(t *testing.T, tc *testContext, name string, expected map[base.DeploymentConditionType]corev1.ConditionStatus) { dep := &api.Deployment{ ObjectMeta: metav1.ObjectMeta{ Name: name, @@ -294,11 +295,11 @@ func TestDeploymentController(t *testing.T) { err := tc.c.Create(context.TODO(), dep) require.NoError(t, err, "failed to create deployment") - testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning) - validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false) - validateConditions(t, tc, d.name, map[api.DeploymentConditionType]corev1.ConditionStatus{ - api.CertsReady: corev1.ConditionTrue, - api.DriverDeployed: corev1.ConditionTrue, + testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, base.DeploymentPhaseRunning) + validateDriver(t, tc, dep, []string{base.EventReasonNew, base.EventReasonRunning}, false) + validateConditions(t, tc, d.name, map[base.DeploymentConditionType]corev1.ConditionStatus{ + base.CertsReady: corev1.ConditionTrue, + base.DriverDeployed: corev1.ConditionTrue, }) }) @@ -324,11 +325,11 @@ func TestDeploymentController(t *testing.T) { require.NoError(t, err, "failed to create deployment") // Reconcile now should change Phase to running - testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning) - validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false) - validateConditions(t, tc, d.name, map[api.DeploymentConditionType]corev1.ConditionStatus{ - api.CertsReady: corev1.ConditionTrue, - api.DriverDeployed: corev1.ConditionTrue, + testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, base.DeploymentPhaseRunning) + validateDriver(t, tc, dep, []string{base.EventReasonNew, base.EventReasonRunning}, false) + validateConditions(t, tc, d.name, map[base.DeploymentConditionType]corev1.ConditionStatus{ + base.CertsReady: corev1.ConditionTrue, + base.DriverDeployed: corev1.ConditionTrue, }) }) @@ -351,16 +352,16 @@ func TestDeploymentController(t *testing.T) { err = tc.c.Create(context.TODO(), dep2) require.NoError(t, err, "failed to create deployment2") - conditions := map[api.DeploymentConditionType]corev1.ConditionStatus{ - api.CertsReady: corev1.ConditionTrue, - api.DriverDeployed: corev1.ConditionTrue, + conditions := map[base.DeploymentConditionType]corev1.ConditionStatus{ + base.CertsReady: corev1.ConditionTrue, + base.DriverDeployed: corev1.ConditionTrue, } - testReconcilePhase(t, tc.rc, tc.c, d1.name, false, false, api.DeploymentPhaseRunning) - validateDriver(t, tc, dep1, []string{api.EventReasonNew, api.EventReasonRunning}, false) + testReconcilePhase(t, tc.rc, tc.c, d1.name, false, false, base.DeploymentPhaseRunning) + validateDriver(t, tc, dep1, []string{base.EventReasonNew, base.EventReasonRunning}, false) validateConditions(t, tc, d1.name, conditions) - testReconcilePhase(t, tc.rc, tc.c, d2.name, false, false, api.DeploymentPhaseRunning) - validateDriver(t, tc, dep2, []string{api.EventReasonNew, api.EventReasonRunning}, false) + testReconcilePhase(t, tc.rc, tc.c, d2.name, false, false, base.DeploymentPhaseRunning) + validateDriver(t, tc, dep2, []string{base.EventReasonNew, base.EventReasonRunning}, false) validateConditions(t, tc, d2.name, conditions) }) @@ -377,9 +378,9 @@ func TestDeploymentController(t *testing.T) { err := tc.c.Create(context.TODO(), dep) require.NoError(t, err, "failed to create deployment") // Deployment should failed with an error - testReconcilePhase(t, tc.rc, tc.c, d.name, true, true, api.DeploymentPhaseFailed) - validateEvents(t, tc, dep, []string{api.EventReasonNew, api.EventReasonFailed}) - validateConditions(t, tc, d.name, map[api.DeploymentConditionType]corev1.ConditionStatus{}) + testReconcilePhase(t, tc.rc, tc.c, d.name, true, true, base.DeploymentPhaseFailed) + validateEvents(t, tc, dep, []string{base.EventReasonNew, base.EventReasonFailed}) + validateConditions(t, tc, d.name, map[base.DeploymentConditionType]corev1.ConditionStatus{}) }) t.Run("LVM mode", func(t *testing.T) { @@ -393,11 +394,11 @@ func TestDeploymentController(t *testing.T) { err := tc.c.Create(context.TODO(), dep) require.NoError(t, err, "failed to create deployment") - testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning) - validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false) - validateConditions(t, tc, d.name, map[api.DeploymentConditionType]corev1.ConditionStatus{ - api.CertsReady: corev1.ConditionTrue, - api.DriverDeployed: corev1.ConditionTrue, + testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, base.DeploymentPhaseRunning) + validateDriver(t, tc, dep, []string{base.EventReasonNew, base.EventReasonRunning}, false) + validateConditions(t, tc, d.name, map[base.DeploymentConditionType]corev1.ConditionStatus{ + base.CertsReady: corev1.ConditionTrue, + base.DriverDeployed: corev1.ConditionTrue, }) }) @@ -412,11 +413,11 @@ func TestDeploymentController(t *testing.T) { err := tc.c.Create(context.TODO(), dep) require.NoError(t, err, "failed to create deployment") - testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning) - validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false) - validateConditions(t, tc, d.name, map[api.DeploymentConditionType]corev1.ConditionStatus{ - api.CertsReady: corev1.ConditionTrue, - api.DriverDeployed: corev1.ConditionTrue, + testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, base.DeploymentPhaseRunning) + validateDriver(t, tc, dep, []string{base.EventReasonNew, base.EventReasonRunning}, false) + validateConditions(t, tc, d.name, map[base.DeploymentConditionType]corev1.ConditionStatus{ + base.CertsReady: corev1.ConditionTrue, + base.DriverDeployed: corev1.ConditionTrue, }) }) @@ -438,11 +439,11 @@ func TestDeploymentController(t *testing.T) { require.NoError(t, err, "failed to create deployment") // First deployment expected to be successful - testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning) - validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false) - validateConditions(t, tc, d.name, map[api.DeploymentConditionType]corev1.ConditionStatus{ - api.CertsReady: corev1.ConditionTrue, - api.DriverDeployed: corev1.ConditionTrue, + testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, base.DeploymentPhaseRunning) + validateDriver(t, tc, dep, []string{base.EventReasonNew, base.EventReasonRunning}, false) + validateConditions(t, tc, d.name, map[base.DeploymentConditionType]corev1.ConditionStatus{ + base.CertsReady: corev1.ConditionTrue, + base.DriverDeployed: corev1.ConditionTrue, }) }) @@ -475,12 +476,12 @@ func TestDeploymentController(t *testing.T) { require.NoError(t, err, "failed to create deployment") // First deployment expected to be successful - testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning) - validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false) - validateConditions(t, tc, d.name, map[api.DeploymentConditionType]corev1.ConditionStatus{ - api.CertsReady: corev1.ConditionTrue, - api.CertsVerified: corev1.ConditionTrue, - api.DriverDeployed: corev1.ConditionTrue, + testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, base.DeploymentPhaseRunning) + validateDriver(t, tc, dep, []string{base.EventReasonNew, base.EventReasonRunning}, false) + validateConditions(t, tc, d.name, map[base.DeploymentConditionType]corev1.ConditionStatus{ + base.CertsReady: corev1.ConditionTrue, + base.CertsVerified: corev1.ConditionTrue, + base.DriverDeployed: corev1.ConditionTrue, }) }) @@ -512,11 +513,11 @@ func TestDeploymentController(t *testing.T) { err = tc.c.Create(context.TODO(), dep) require.NoError(t, err, "failed to create deployment") - testReconcilePhase(t, tc.rc, tc.c, d.name, true, true, api.DeploymentPhaseFailed) - validateEvents(t, tc, dep, []string{api.EventReasonNew, api.EventReasonFailed}) - validateConditions(t, tc, d.name, map[api.DeploymentConditionType]corev1.ConditionStatus{ - api.CertsVerified: corev1.ConditionFalse, - api.DriverDeployed: corev1.ConditionFalse, + testReconcilePhase(t, tc.rc, tc.c, d.name, true, true, base.DeploymentPhaseFailed) + validateEvents(t, tc, dep, []string{base.EventReasonNew, base.EventReasonFailed}) + validateConditions(t, tc, d.name, map[base.DeploymentConditionType]corev1.ConditionStatus{ + base.CertsVerified: corev1.ConditionFalse, + base.DriverDeployed: corev1.ConditionFalse, }) }) @@ -551,11 +552,11 @@ func TestDeploymentController(t *testing.T) { err = tc.c.Create(context.TODO(), dep) require.NoError(t, err, "failed to create deployment") - testReconcilePhase(t, tc.rc, tc.c, d.name, true, true, api.DeploymentPhaseFailed) - validateEvents(t, tc, dep, []string{api.EventReasonNew, api.EventReasonFailed}) - validateConditions(t, tc, d.name, map[api.DeploymentConditionType]corev1.ConditionStatus{ - api.CertsVerified: corev1.ConditionFalse, - api.DriverDeployed: corev1.ConditionFalse, + testReconcilePhase(t, tc.rc, tc.c, d.name, true, true, base.DeploymentPhaseFailed) + validateEvents(t, tc, dep, []string{base.EventReasonNew, base.EventReasonFailed}) + validateConditions(t, tc, d.name, map[base.DeploymentConditionType]corev1.ConditionStatus{ + base.CertsVerified: corev1.ConditionFalse, + base.DriverDeployed: corev1.ConditionFalse, }) }) @@ -581,20 +582,20 @@ func TestDeploymentController(t *testing.T) { } tc.rc.(*deployment.ReconcileDeployment).AddHook(&hook) - conditions := map[api.DeploymentConditionType]corev1.ConditionStatus{ - api.CertsReady: corev1.ConditionTrue, - api.DriverDeployed: corev1.ConditionTrue, + conditions := map[base.DeploymentConditionType]corev1.ConditionStatus{ + base.CertsReady: corev1.ConditionTrue, + base.DriverDeployed: corev1.ConditionTrue, } - testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning) - validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false) + testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, base.DeploymentPhaseRunning) + validateDriver(t, tc, dep, []string{base.EventReasonNew, base.EventReasonRunning}, false) validateConditions(t, tc, d.name, conditions) tc.rc.(*deployment.ReconcileDeployment).RemoveHook(&hook) // Next reconcile phase should catch the deployment changes - testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning) - validateDriver(t, tc, updatedDep, []string{api.EventReasonNew, api.EventReasonRunning}, true) + testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, base.DeploymentPhaseRunning) + validateDriver(t, tc, updatedDep, []string{base.EventReasonNew, base.EventReasonRunning}, true) validateConditions(t, tc, d.name, conditions) }) @@ -609,12 +610,12 @@ func TestDeploymentController(t *testing.T) { dep := testcase.Deployment.DeepCopyObject().(*api.Deployment) // Assumption is that all the testcases are positive cases. - conditions := map[api.DeploymentConditionType]corev1.ConditionStatus{ - api.CertsReady: corev1.ConditionTrue, - api.DriverDeployed: corev1.ConditionTrue, + conditions := map[base.DeploymentConditionType]corev1.ConditionStatus{ + base.CertsReady: corev1.ConditionTrue, + base.DriverDeployed: corev1.ConditionTrue, } if yes, _ := dep.HaveCertificatesConfigured(); yes { - conditions[api.CertsVerified] = corev1.ConditionTrue + conditions[base.CertsVerified] = corev1.ConditionTrue } // When working with the fake client, we need to make up a UID. @@ -623,13 +624,13 @@ func TestDeploymentController(t *testing.T) { err := tc.c.Create(context.TODO(), dep) require.NoError(t, err, "create deployment") - testReconcilePhase(t, tc.rc, tc.c, dep.Name, false, false, api.DeploymentPhaseRunning) - validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false) + testReconcilePhase(t, tc.rc, tc.c, dep.Name, false, false, base.DeploymentPhaseRunning) + validateDriver(t, tc, dep, []string{base.EventReasonNew, base.EventReasonRunning}, false) // Reconcile now should keep phase as running. - testReconcilePhase(t, tc.rc, tc.c, dep.Name, false, false, api.DeploymentPhaseRunning) - validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false) - validateEvents(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}) + testReconcilePhase(t, tc.rc, tc.c, dep.Name, false, false, base.DeploymentPhaseRunning) + validateDriver(t, tc, dep, []string{base.EventReasonNew, base.EventReasonRunning}, false) + validateEvents(t, tc, dep, []string{base.EventReasonNew, base.EventReasonRunning}) validateConditions(t, tc, dep.Name, conditions) // Retrieve existing object before updating it. @@ -647,10 +648,10 @@ func TestDeploymentController(t *testing.T) { require.NoError(t, err, "update deployment") // Reconcile is expected to not fail. - testReconcilePhase(t, tc.rc, tc.c, dep.Name, false, false, api.DeploymentPhaseRunning) + testReconcilePhase(t, tc.rc, tc.c, dep.Name, false, false, base.DeploymentPhaseRunning) // Recheck the container resources are updated - validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, true) + validateDriver(t, tc, dep, []string{base.EventReasonNew, base.EventReasonRunning}, true) } t.Run("while running", func(t *testing.T) { @@ -675,11 +676,11 @@ func TestDeploymentController(t *testing.T) { err := tc.c.Create(context.TODO(), dep) require.NoError(t, err, "failed to create deployment") - testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning) - validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, false) - validateConditions(t, tc, d.name, map[api.DeploymentConditionType]corev1.ConditionStatus{ - api.CertsReady: corev1.ConditionTrue, - api.DriverDeployed: corev1.ConditionTrue, + testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, base.DeploymentPhaseRunning) + validateDriver(t, tc, dep, []string{base.EventReasonNew, base.EventReasonRunning}, false) + validateConditions(t, tc, d.name, map[base.DeploymentConditionType]corev1.ConditionStatus{ + base.CertsReady: corev1.ConditionTrue, + base.DriverDeployed: corev1.ConditionTrue, }) err = tc.c.Get(context.TODO(), client.ObjectKey{Name: d.name}, dep) @@ -720,12 +721,12 @@ func TestDeploymentController(t *testing.T) { tc.rc = newReconcileDeployment(tc.c, tc.cs) // A fresh reconcile should delete the newly created above ConfigMap - testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, api.DeploymentPhaseRunning) + testReconcilePhase(t, tc.rc, tc.c, d.name, false, false, base.DeploymentPhaseRunning) err = tc.c.Get(context.TODO(), client.ObjectKey{Name: d.name}, dep) require.NoError(t, err, "get deployment") // It is debatable whether the operator should update all objects after // a restart. Currently it does. - validateDriver(t, tc, dep, []string{api.EventReasonNew, api.EventReasonRunning}, true) + validateDriver(t, tc, dep, []string{base.EventReasonNew, base.EventReasonRunning}, true) cm := &corev1.ConfigMap{} err = tc.c.Get(context.TODO(), client.ObjectKey{Name: cm1.Name, Namespace: testNamespace}, cm) diff --git a/pkg/pmem-csi-operator/controller/deployment/testcases/testcases.go b/pkg/pmem-csi-operator/controller/deployment/testcases/testcases.go index 7831daf9ca..9ab08cd5ee 100644 --- a/pkg/pmem-csi-operator/controller/deployment/testcases/testcases.go +++ b/pkg/pmem-csi-operator/controller/deployment/testcases/testcases.go @@ -11,6 +11,7 @@ package testcases import ( "fmt" + "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" pmemtls "github.com/intel/pmem-csi/pkg/pmem-csi-operator/pmem-tls" @@ -87,10 +88,21 @@ func UpdateTests() []UpdateTest { Name: "pmem-csi-with-values", }, Spec: api.DeploymentSpec{ - Image: "base-image", - PullPolicy: corev1.PullIfNotPresent, - ProvisionerImage: "no-such-provisioner-image", - NodeRegistrarImage: "no-such-registrar-image", + DeploymentSpec: base.DeploymentSpec{ + Image: "base-image", + PullPolicy: corev1.PullIfNotPresent, + ProvisionerImage: "no-such-provisioner-image", + NodeRegistrarImage: "no-such-registrar-image", + DeviceMode: base.DeviceModeDirect, + LogLevel: 4, + NodeSelector: map[string]string{ + "no-such-label": "no-such-value", + }, + PMEMPercentage: 50, + Labels: map[string]string{ + "a": "b", + }, + }, ControllerResources: &corev1.ResourceRequirements{ Limits: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("200m"), @@ -103,21 +115,12 @@ func UpdateTests() []UpdateTest { corev1.ResourceMemory: resource.MustParse("500Mi"), }, }, - DeviceMode: api.DeviceModeDirect, - LogLevel: 4, - NodeSelector: map[string]string{ - "no-such-label": "no-such-value", - }, - PMEMPercentage: 50, - Labels: map[string]string{ - "a": "b", - }, }, } SetTLSOrDie(&full.Spec) baseDeployments := map[string]api.Deployment{ - "default deployment": api.Deployment{ + "default deployment": { ObjectMeta: metav1.ObjectMeta{ Name: "pmem-csi-with-defaults", }, diff --git a/pkg/pmem-device-manager/pmd-fake.go b/pkg/pmem-device-manager/pmd-fake.go index ce8a579b7e..6a791ea9d1 100644 --- a/pkg/pmem-device-manager/pmd-fake.go +++ b/pkg/pmem-device-manager/pmd-fake.go @@ -10,7 +10,7 @@ import ( "fmt" "sync" - api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" + api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" pmemerr "github.com/intel/pmem-csi/pkg/errors" ) diff --git a/pkg/pmem-device-manager/pmd-lvm.go b/pkg/pmem-device-manager/pmd-lvm.go index ceddab9feb..abbf5d99ed 100644 --- a/pkg/pmem-device-manager/pmd-lvm.go +++ b/pkg/pmem-device-manager/pmd-lvm.go @@ -7,7 +7,7 @@ import ( "strings" "sync" - api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" + api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" pmemerr "github.com/intel/pmem-csi/pkg/errors" pmemexec "github.com/intel/pmem-csi/pkg/exec" "github.com/intel/pmem-csi/pkg/ndctl" diff --git a/pkg/pmem-device-manager/pmd-manager.go b/pkg/pmem-device-manager/pmd-manager.go index f7e7343fb7..f8923d8aa1 100644 --- a/pkg/pmem-device-manager/pmd-manager.go +++ b/pkg/pmem-device-manager/pmd-manager.go @@ -3,7 +3,7 @@ package pmdmanager import ( "fmt" - api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" + api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" ) const ( diff --git a/pkg/pmem-device-manager/pmd-ndctl.go b/pkg/pmem-device-manager/pmd-ndctl.go index 7c9a7d4f33..12f43c746c 100644 --- a/pkg/pmem-device-manager/pmd-ndctl.go +++ b/pkg/pmem-device-manager/pmd-ndctl.go @@ -5,7 +5,7 @@ import ( "fmt" "sync" - api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" + api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" pmemerr "github.com/intel/pmem-csi/pkg/errors" "github.com/intel/pmem-csi/pkg/ndctl" "k8s.io/klog/v2" diff --git a/test/e2e/deploy/deploy.go b/test/e2e/deploy/deploy.go index b633a62a13..976e917fc5 100644 --- a/test/e2e/deploy/deploy.go +++ b/test/e2e/deploy/deploy.go @@ -30,6 +30,7 @@ import ( "k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework/skipper" + "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" pmemexec "github.com/intel/pmem-csi/pkg/exec" @@ -530,7 +531,7 @@ type Deployment struct { HasOLM bool // Mode is the driver mode of the deployment. - Mode api.DeviceMode + Mode base.DeviceMode // Namespace where the namespaced objects of the deployment // were created. @@ -930,17 +931,19 @@ func (d *Deployment) GetDriverDeployment() api.Deployment { }, }, Spec: api.DeploymentSpec{ - Labels: map[string]string{ - deploymentLabel: d.Label(), - }, - DeviceMode: d.Mode, - // As in setup-deployment.sh, only 50% of the available - // PMEM must be used for LVM, otherwise other tests cannot - // run after the LVM driver was deployed once. - PMEMPercentage: 50, - NodeSelector: map[string]string{ - // Provided by NFD. - "feature.node.kubernetes.io/memory-nv.dax": "true", + DeploymentSpec: base.DeploymentSpec{ + Labels: map[string]string{ + deploymentLabel: d.Label(), + }, + DeviceMode: d.Mode, + // As in setup-deployment.sh, only 50% of the available + // PMEM must be used for LVM, otherwise other tests cannot + // run after the LVM driver was deployed once. + PMEMPercentage: 50, + NodeSelector: map[string]string{ + // Provided by NFD. + "feature.node.kubernetes.io/memory-nv.dax": "true", + }, }, }, } diff --git a/test/e2e/deploy/volumeleaks.go b/test/e2e/deploy/volumeleaks.go index 3171f39358..7aeec8de77 100644 --- a/test/e2e/deploy/volumeleaks.go +++ b/test/e2e/deploy/volumeleaks.go @@ -13,7 +13,7 @@ import ( "os/exec" "strings" - api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" + "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -24,12 +24,12 @@ func GetHostVolumes(d *Deployment) map[string][]string { var cmd string var hdr string switch d.Mode { - case api.DeviceModeLVM: + case base.DeviceModeLVM: // lvs adds many space (0x20) chars at end, we could squeeze // repetitions using tr here, but TrimSpace() below strips those away cmd = "sudo lvs --foreign --noheadings" hdr = "LVM Volumes" - case api.DeviceModeDirect: + case base.DeviceModeDirect: // ndctl produces multiline block. We want one line per namespace. // Pick uuid, mode, size for comparison. Note that sorting changes the order so lines // are not grouped by volume, but keeping volume order would need more complex parsing diff --git a/test/e2e/operator/deployment_api.go b/test/e2e/operator/deployment_api.go index 86b2a1b8c8..4d94e097f0 100644 --- a/test/e2e/operator/deployment_api.go +++ b/test/e2e/operator/deployment_api.go @@ -13,6 +13,7 @@ import ( "strings" "time" + "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" "github.com/intel/pmem-csi/pkg/exec" "github.com/intel/pmem-csi/pkg/k8sutil" @@ -50,7 +51,9 @@ func getDeployment(name string) api.Deployment { Name: name, }, Spec: api.DeploymentSpec{ - Image: dummyImage, + DeploymentSpec: base.DeploymentSpec{ + Image: dummyImage, + }, }, } } @@ -113,7 +116,7 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool { framework.Logf("got expected driver deployment %s", deployment.Name) } - validateConditions := func(depName string, expected map[api.DeploymentConditionType]corev1.ConditionStatus, what ...interface{}) { + validateConditions := func(depName string, expected map[base.DeploymentConditionType]corev1.ConditionStatus, what ...interface{}) { if what == nil { what = []interface{}{"validate driver(%s) status conditions", depName} } @@ -145,9 +148,11 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool { Name: "test-deployment-with-explicit", }, Spec: api.DeploymentSpec{ - DeviceMode: api.DeviceModeDirect, - PullPolicy: corev1.PullNever, - Image: dummyImage, + DeploymentSpec: base.DeploymentSpec{ + DeviceMode: base.DeviceModeDirect, + PullPolicy: corev1.PullNever, + Image: dummyImage, + }, ControllerResources: &corev1.ResourceRequirements{ Limits: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("200m"), @@ -170,9 +175,9 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool { deployment = deploy.CreateDeploymentCR(f, deployment) defer deploy.DeleteDeploymentCR(f, deployment.Name) validateDriver(deployment) - validateConditions(deployment.Name, map[api.DeploymentConditionType]corev1.ConditionStatus{ - api.CertsReady: corev1.ConditionTrue, - api.DriverDeployed: corev1.ConditionTrue, + validateConditions(deployment.Name, map[base.DeploymentConditionType]corev1.ConditionStatus{ + base.CertsReady: corev1.ConditionTrue, + base.DriverDeployed: corev1.ConditionTrue, }) }) } @@ -184,7 +189,7 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool { // Only values that are visible in Deployment CR are shown in `kubectl get` // but, not the default values chosen by the operator. // So provide the values that are expected to list. - deployment.Spec.DeviceMode = api.DeviceModeDirect + deployment.Spec.DeviceMode = base.DeviceModeDirect deployment.Spec.PullPolicy = corev1.PullNever deployment.Spec.Image = dummyImage deployment.Spec.NodeSelector = map[string]string{ @@ -284,10 +289,10 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool { deployment = deploy.CreateDeploymentCR(f, deployment) defer deploy.DeleteDeploymentCR(f, deployment.Name) validateDriver(deployment, true) - validateConditions(deployment.Name, map[api.DeploymentConditionType]corev1.ConditionStatus{ - api.CertsReady: corev1.ConditionTrue, - api.CertsVerified: corev1.ConditionTrue, - api.DriverDeployed: corev1.ConditionTrue, + validateConditions(deployment.Name, map[base.DeploymentConditionType]corev1.ConditionStatus{ + base.CertsReady: corev1.ConditionTrue, + base.CertsVerified: corev1.ConditionTrue, + base.DriverDeployed: corev1.ConditionTrue, }) }) @@ -298,9 +303,9 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool { defer deploy.DeleteDeploymentCR(f, deployment.Name) validateDriver(deployment, true) - validateConditions(deployment.Name, map[api.DeploymentConditionType]corev1.ConditionStatus{ - api.CertsReady: corev1.ConditionTrue, - api.DriverDeployed: corev1.ConditionTrue, + validateConditions(deployment.Name, map[base.DeploymentConditionType]corev1.ConditionStatus{ + base.CertsReady: corev1.ConditionTrue, + base.DriverDeployed: corev1.ConditionTrue, }) // Stop the operator @@ -361,7 +366,7 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool { // exists and is owned by others. Eventually(func() bool { out := deploy.GetDeploymentCR(f, deployment.Name) - return out.Status.Phase == api.DeploymentPhaseFailed + return out.Status.Phase == base.DeploymentPhaseFailed }, "3m", "1s").Should(BeTrue(), "deployment should fail %q", deployment.Name) // Deleting the existing secret should make the deployment succeed. @@ -371,12 +376,12 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool { }) Context("switch device mode", func() { - postSwitchFuncs := map[string]func(from, to api.DeviceMode, depName string, pvc *corev1.PersistentVolumeClaim){ - "delete volume": func(from, to api.DeviceMode, depName string, pvc *corev1.PersistentVolumeClaim) { + postSwitchFuncs := map[string]func(from, to base.DeviceMode, depName string, pvc *corev1.PersistentVolumeClaim){ + "delete volume": func(from, to base.DeviceMode, depName string, pvc *corev1.PersistentVolumeClaim) { // Delete Volume created in `from` device mode deletePVC(f, pvc.Namespace, pvc.Name) }, - "use volume": func(from, to api.DeviceMode, depName string, pvc *corev1.PersistentVolumeClaim) { + "use volume": func(from, to base.DeviceMode, depName string, pvc *corev1.PersistentVolumeClaim) { // Switch back to original device mode switchDeploymentMode(c, f, depName, from) @@ -441,7 +446,7 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool { }, } - defineSwitchModeTests := func(ctx string, from, to api.DeviceMode) { + defineSwitchModeTests := func(ctx string, from, to base.DeviceMode) { for name, postSwitch := range postSwitchFuncs { Context(ctx, func() { name := name @@ -453,11 +458,13 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool { Name: driverName, }, Spec: api.DeploymentSpec{ - DeviceMode: from, - PMEMPercentage: 50, - NodeSelector: map[string]string{ - // Provided by NFD. - "feature.node.kubernetes.io/memory-nv.dax": "true", + DeploymentSpec: base.DeploymentSpec{ + DeviceMode: from, + PMEMPercentage: 50, + NodeSelector: map[string]string{ + // Provided by NFD. + "feature.node.kubernetes.io/memory-nv.dax": "true", + }, }, }, } @@ -503,8 +510,8 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool { } } - defineSwitchModeTests("lvm-to-direct", api.DeviceModeLVM, api.DeviceModeDirect) - defineSwitchModeTests("direct-to-lvm", api.DeviceModeDirect, api.DeviceModeLVM) + defineSwitchModeTests("lvm-to-direct", base.DeviceModeLVM, base.DeviceModeDirect) + defineSwitchModeTests("direct-to-lvm", base.DeviceModeDirect, base.DeviceModeLVM) }) Context("updating", func() { @@ -527,7 +534,7 @@ var _ = deploy.DescribeForSome("API", func(d *deploy.Deployment) bool { // operator should have modified the status, and only the status. modifiedDeployment := deploy.GetDeploymentCR(f, deployment.Name) Expect(modifiedDeployment.Spec).To(Equal(deployment.Spec), "spec unmodified") - Expect(modifiedDeployment.Status.Phase).To(Equal(api.DeploymentPhaseRunning), "deployment phase") + Expect(modifiedDeployment.Status.Phase).To(Equal(base.DeploymentPhaseRunning), "deployment phase") restored := false if restart { @@ -755,7 +762,7 @@ func validateDeploymentFailure(f *framework.Framework, name string) { deployment := deploy.DeploymentFromUnstructured(dep) framework.Logf("Deployment %q is in %q phase", deployment.Name, deployment.Status.Phase) - return deployment.Status.Phase == api.DeploymentPhaseFailed + return deployment.Status.Phase == base.DeploymentPhaseFailed }, "3m", "5s").Should(BeTrue(), "deployment %q not running", name) } @@ -821,7 +828,7 @@ func startOperator(c *deploy.Cluster, d *deploy.Deployment) { framework.Logf("Operator is restored!") } -func switchDeploymentMode(c *deploy.Cluster, f *framework.Framework, depName string, mode api.DeviceMode) api.Deployment { +func switchDeploymentMode(c *deploy.Cluster, f *framework.Framework, depName string, mode base.DeviceMode) api.Deployment { podNames := []string{} for i := 1; i < c.NumNodes(); i++ { diff --git a/test/e2e/storage/sanity.go b/test/e2e/storage/sanity.go index 265131d2e7..67136476f4 100644 --- a/test/e2e/storage/sanity.go +++ b/test/e2e/storage/sanity.go @@ -31,7 +31,6 @@ import ( "time" "github.com/container-storage-interface/spec/lib/go/csi" - api "github.com/intel/pmem-csi/pkg/apis/pmemcsi/v1alpha1" "github.com/kubernetes-csi/csi-test/v3/pkg/sanity" sanityutils "github.com/kubernetes-csi/csi-test/v3/utils" "google.golang.org/grpc" @@ -52,6 +51,7 @@ import ( "k8s.io/kubernetes/test/e2e/framework/skipper" testutils "k8s.io/kubernetes/test/utils" + "github.com/intel/pmem-csi/pkg/apis/pmemcsi/base" "github.com/intel/pmem-csi/test/e2e/deploy" . "github.com/onsi/ginkgo" @@ -511,7 +511,7 @@ var _ = deploy.DescribeForSome("sanity", func(d *deploy.Deployment) bool { sanityVolumes := *numSanityVolumes if sanityVolumes == 0 { switch d.Mode { - case api.DeviceModeDirect: + case base.DeviceModeDirect: // The minimum volume size in direct mode is 2GB, which makes // testing a lot slower than in LVM mode. Therefore we create less // volumes.