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.