Refactor CSI Translation Library into a struct that is injected into various components to simplify unit testing in future

This commit is contained in:
David Zhu
2019-09-12 17:59:06 -07:00
parent 67d928acdc
commit 92cb06a2e7
20 changed files with 168 additions and 94 deletions

View File

@@ -35,9 +35,20 @@ var (
}
)
// CSITranslator translates in-tree storage API objects to their equivalent CSI
// API objects. It also provides many helper functions to determine whether
// translation logic exists and the mappings between "in-tree plugin <-> csi driver"
type CSITranslator struct{}
// New creates a new CSITranslator which does real translation
// for "in-tree plugins <-> csi drivers"
func New() CSITranslator {
return CSITranslator{}
}
// TranslateInTreeStorageClassToCSI takes in-tree Storage Class
// and translates it to a set of parameters consumable by CSI plugin
func TranslateInTreeStorageClassToCSI(inTreePluginName string, sc *storage.StorageClass) (*storage.StorageClass, error) {
func (ctl CSITranslator) TranslateInTreeStorageClassToCSI(inTreePluginName string, sc *storage.StorageClass) (*storage.StorageClass, error) {
newSC := sc.DeepCopy()
for _, curPlugin := range inTreePlugins {
if inTreePluginName == curPlugin.GetInTreePluginName() {
@@ -50,7 +61,7 @@ func TranslateInTreeStorageClassToCSI(inTreePluginName string, sc *storage.Stora
// TranslateInTreeInlineVolumeToCSI takes a inline volume and will translate
// the in-tree volume source to a CSIPersistentVolumeSource (wrapped in a PV)
// if the translation logic has been implemented.
func TranslateInTreeInlineVolumeToCSI(volume *v1.Volume) (*v1.PersistentVolume, error) {
func (ctl CSITranslator) TranslateInTreeInlineVolumeToCSI(volume *v1.Volume) (*v1.PersistentVolume, error) {
if volume == nil {
return nil, fmt.Errorf("persistent volume was nil")
}
@@ -66,7 +77,7 @@ func TranslateInTreeInlineVolumeToCSI(volume *v1.Volume) (*v1.PersistentVolume,
// the in-tree source to a CSI Source if the translation logic
// has been implemented. The input persistent volume will not
// be modified
func TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
func (ctl CSITranslator) TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
if pv == nil {
return nil, errors.New("persistent volume was nil")
}
@@ -82,7 +93,7 @@ func TranslateInTreePVToCSI(pv *v1.PersistentVolume) (*v1.PersistentVolume, erro
// TranslateCSIPVToInTree takes a PV with a CSI PersistentVolume Source and will translate
// it to a in-tree Persistent Volume Source for the specific in-tree volume specified
// by the `Driver` field in the CSI Source. The input PV object will not be modified.
func TranslateCSIPVToInTree(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
func (ctl CSITranslator) TranslateCSIPVToInTree(pv *v1.PersistentVolume) (*v1.PersistentVolume, error) {
if pv == nil || pv.Spec.CSI == nil {
return nil, errors.New("CSI persistent volume was nil")
}
@@ -97,7 +108,7 @@ func TranslateCSIPVToInTree(pv *v1.PersistentVolume) (*v1.PersistentVolume, erro
// IsMigratableIntreePluginByName tests whether there is migration logic for the in-tree plugin
// whose name matches the given name
func IsMigratableIntreePluginByName(inTreePluginName string) bool {
func (ctl CSITranslator) IsMigratableIntreePluginByName(inTreePluginName string) bool {
for _, curPlugin := range inTreePlugins {
if curPlugin.GetInTreePluginName() == inTreePluginName {
return true
@@ -108,7 +119,7 @@ func IsMigratableIntreePluginByName(inTreePluginName string) bool {
// IsMigratedCSIDriverByName tests whether there exists an in-tree plugin with logic
// to migrate to the CSI driver with given name
func IsMigratedCSIDriverByName(csiPluginName string) bool {
func (ctl CSITranslator) IsMigratedCSIDriverByName(csiPluginName string) bool {
if _, ok := inTreePlugins[csiPluginName]; ok {
return true
}
@@ -116,7 +127,7 @@ func IsMigratedCSIDriverByName(csiPluginName string) bool {
}
// GetInTreePluginNameFromSpec returns the plugin name
func GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (string, error) {
func (ctl CSITranslator) GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (string, error) {
if pv != nil {
for _, curPlugin := range inTreePlugins {
if curPlugin.CanSupport(pv) {
@@ -138,7 +149,7 @@ func GetInTreePluginNameFromSpec(pv *v1.PersistentVolume, vol *v1.Volume) (strin
// GetCSINameFromInTreeName returns the name of a CSI driver that supersedes the
// in-tree plugin with the given name
func GetCSINameFromInTreeName(pluginName string) (string, error) {
func (ctl CSITranslator) GetCSINameFromInTreeName(pluginName string) (string, error) {
for csiDriverName, curPlugin := range inTreePlugins {
if curPlugin.GetInTreePluginName() == pluginName {
return csiDriverName, nil
@@ -149,7 +160,7 @@ func GetCSINameFromInTreeName(pluginName string) (string, error) {
// GetInTreeNameFromCSIName returns the name of the in-tree plugin superseded by
// a CSI driver with the given name
func GetInTreeNameFromCSIName(pluginName string) (string, error) {
func (ctl CSITranslator) GetInTreeNameFromCSIName(pluginName string) (string, error) {
if plugin, ok := inTreePlugins[pluginName]; ok {
return plugin.GetInTreePluginName(), nil
}
@@ -157,7 +168,7 @@ func GetInTreeNameFromCSIName(pluginName string) (string, error) {
}
// IsPVMigratable tests whether there is migration logic for the given Persistent Volume
func IsPVMigratable(pv *v1.PersistentVolume) bool {
func (ctl CSITranslator) IsPVMigratable(pv *v1.PersistentVolume) bool {
for _, curPlugin := range inTreePlugins {
if curPlugin.CanSupport(pv) {
return true
@@ -167,7 +178,7 @@ func IsPVMigratable(pv *v1.PersistentVolume) bool {
}
// IsInlineMigratable tests whether there is Migration logic for the given Inline Volume
func IsInlineMigratable(vol *v1.Volume) bool {
func (ctl CSITranslator) IsInlineMigratable(vol *v1.Volume) bool {
for _, curPlugin := range inTreePlugins {
if curPlugin.CanSupportInline(vol) {
return true

View File

@@ -61,12 +61,13 @@ func TestTranslationStability(t *testing.T) {
},
}
for _, test := range testCases {
ctl := New()
t.Logf("Testing %v", test.name)
csiSource, err := TranslateInTreePVToCSI(test.pv)
csiSource, err := ctl.TranslateInTreePVToCSI(test.pv)
if err != nil {
t.Errorf("Error when translating to CSI: %v", err)
}
newPV, err := TranslateCSIPVToInTree(csiSource)
newPV, err := ctl.TranslateCSIPVToInTree(csiSource)
if err != nil {
t.Errorf("Error when translating CSI Source to in tree volume: %v", err)
}
@@ -95,18 +96,19 @@ func TestPluginNameMappings(t *testing.T) {
}
for _, test := range testCases {
t.Logf("Testing %v", test.name)
csiPluginName, err := GetCSINameFromInTreeName(test.inTreePluginName)
ctl := New()
csiPluginName, err := ctl.GetCSINameFromInTreeName(test.inTreePluginName)
if err != nil {
t.Errorf("Error when mapping In-tree plugin name to CSI plugin name %s", err)
}
if !IsMigratedCSIDriverByName(csiPluginName) {
if !ctl.IsMigratedCSIDriverByName(csiPluginName) {
t.Errorf("%s expected to supersede an In-tree plugin", csiPluginName)
}
inTreePluginName, err := GetInTreeNameFromCSIName(csiPluginName)
inTreePluginName, err := ctl.GetInTreeNameFromCSIName(csiPluginName)
if err != nil {
t.Errorf("Error when mapping CSI plugin name to In-tree plugin name %s", err)
}
if !IsMigratableIntreePluginByName(inTreePluginName) {
if !ctl.IsMigratableIntreePluginByName(inTreePluginName) {
t.Errorf("%s expected to be migratable to a CSI name", inTreePluginName)
}
if inTreePluginName != test.inTreePluginName || csiPluginName != test.csiPluginName {