From 4a0f015a57d68b72d9b26872c11f907958c84300 Mon Sep 17 00:00:00 2001 From: "Roussin, Jerome" Date: Wed, 11 May 2022 18:27:06 -0400 Subject: [PATCH 1/5] First attempt at autodoc for core/ and operator/controllers/ only --- core/core_test.go | 10 + core/orchestrator_core.go | 897 ++++++++ core/orchestrator_core_test.go | 1818 ++++++++--------- core/transaction_monitor_test.go | 61 +- .../orchestrator/apis/netapp/v1/register.go | 11 + .../orchestrator/apis/netapp/v1/types.go | 11 + .../versioned/fake/clientset_generated.go | 20 + .../netapp/v1/fake/fake_netapp_client.go | 5 + .../typed/netapp/v1/netapp_client.go | 16 + .../informers/externalversions/factory.go | 29 + .../netapp/v1/tridentorchestrator.go | 62 + .../controllers/orchestrator/controller.go | 86 + .../orchestrator/installer/installer.go | 227 ++ .../orchestrator/installer/installer_test.go | 44 + .../orchestrator/installer/k8s_client_test.go | 590 ++++++ .../orchestrator/installer/uninstaller.go | 29 + .../orchestrator/installer/utils.go | 69 + .../provisioner/apis/netapp/v1/register.go | 11 + .../versioned/fake/clientset_generated.go | 17 + .../netapp/v1/fake/fake_netapp_client.go | 11 + .../typed/netapp/v1/netapp_client.go | 17 + .../informers/externalversions/factory.go | 28 + .../netapp/v1/tridentprovisioner.go | 60 + 23 files changed, 3211 insertions(+), 918 deletions(-) diff --git a/core/core_test.go b/core/core_test.go index d4ad03858..eaa90dbf0 100644 --- a/core/core_test.go +++ b/core/core_test.go @@ -10,6 +10,16 @@ import ( log "github.com/sirupsen/logrus" ) +// TestMain is the entry point for all unit tests. +// It checks for any command line arguments and if none are found, +// it sets the log output to ioutil.Discard to disable any standard log output. +// Parameters: +// m: the testing.M object +// Returns: +// none +// Example: +// + func TestMain(m *testing.M) { // Disable any standard log output log.SetOutput(ioutil.Discard) diff --git a/core/orchestrator_core.go b/core/orchestrator_core.go index 261abc7d3..8baa56ef9 100644 --- a/core/orchestrator_core.go +++ b/core/orchestrator_core.go @@ -54,6 +54,14 @@ func recordTiming(operation string, err *error) func() { } } +// recordTransactionTiming records the time it took to complete a transaction +// in milliseconds. +// Parameters: +// txn: the transaction to record +// err: the error that occurred, if any +// Example: +// recordTransactionTiming(txn, err) + func recordTransactionTiming(txn *storage.VolumeTransaction, err *error) { if txn == nil || txn.VolumeCreatingConfig == nil { // for unit tests, there will be no txn to record @@ -108,6 +116,18 @@ func NewTridentOrchestrator(client persistentstore.Client) *TridentOrchestrator } } +// transformPersistentState transforms the persistent state to the current API version. +// Parameters: +// ctx - context +// Returns: +// error - any error encountered +// It returns an error if the persistent store version is not found. +// Example: +// err := o.transformPersistentState(ctx) +// if err != nil { +// return err +// } + func (o *TridentOrchestrator) transformPersistentState(ctx context.Context) error { version, err := o.storeClient.GetVersion(ctx) @@ -142,6 +162,13 @@ func (o *TridentOrchestrator) transformPersistentState(ctx context.Context) erro return nil } +// Bootstrap initializes the orchestrator. +// It returns an error if the orchestrator cannot be initialized. +// Example: +// if err := o.Bootstrap(); err != nil { +// log.Fatal(err) +// } + func (o *TridentOrchestrator) Bootstrap() error { ctx := GenerateRequestContext(context.Background(), "", ContextSourceInternal) var err error @@ -171,6 +198,18 @@ func (o *TridentOrchestrator) Bootstrap() error { return nil } +// bootstrapBackends is called during startup to load any backends that were +// previously configured. +// Parameters: +// ctx - context for logging +// Returns: +// error - if any errors occur +// It returns an error if it cannot load any backends. +// Example: +// if err := o.bootstrapBackends(ctx); err != nil { +// return err +// } + func (o *TridentOrchestrator) bootstrapBackends(ctx context.Context) error { persistentBackends, err := o.storeClient.GetBackends(ctx) @@ -263,6 +302,19 @@ func (o *TridentOrchestrator) bootstrapBackends(ctx context.Context) error { return nil } +// bootstrapStorageClasses loads storage classes from the backend store. +// Parameters: +// ctx - context for logging +// Returns: +// error - any error encountered +// It returns an error if the storage classes cannot be loaded from the backend store. +// Example: +// ctx := context.Background() +// err := o.bootstrapStorageClasses(ctx) +// if err != nil { +// return errors.Wrap(err, "error bootstrapping storage classes") +// } + func (o *TridentOrchestrator) bootstrapStorageClasses(ctx context.Context) error { persistentStorageClasses, err := o.storeClient.GetStorageClasses(ctx) @@ -286,6 +338,18 @@ func (o *TridentOrchestrator) bootstrapStorageClasses(ctx context.Context) error // Updates the o.volumes cache with the latest backend data. This function should only edit o.volumes in place to avoid // briefly losing track of volumes that do exist. +// bootstrapVolumes adds all volumes from the store to the orchestrator. +// Parameters: +// ctx - context for logging +// Returns: +// error - any error encountered +// It returns an error if the store cannot be read. +// Example: +// err := o.bootstrapVolumes(ctx) +// if err != nil { +// log.Errorf("Could not bootstrap volumes: %v", err) +// } + func (o *TridentOrchestrator) bootstrapVolumes(ctx context.Context) error { volumes, err := o.storeClient.GetVolumes(ctx) @@ -339,6 +403,15 @@ func (o *TridentOrchestrator) bootstrapVolumes(ctx context.Context) error { return nil } +// bootstrapSnapshots bootstraps the snapshot store with existing snapshots. +// Parameters: +// ctx - context for logging +// Returns: +// error - any error encountered +// It returns an error if the snapshot store cannot be queried. +// Example: +// error := o.bootstrapSnapshots(ctx) + func (o *TridentOrchestrator) bootstrapSnapshots(ctx context.Context) error { snapshots, err := o.storeClient.GetSnapshots(ctx) @@ -374,6 +447,19 @@ func (o *TridentOrchestrator) bootstrapSnapshots(ctx context.Context) error { return nil } +// bootstrapVolTxns reads all volume transaction logs from the persistent store and +// attempts to recover from any failed transactions. +// Parameters: +// ctx - context +// Returns: +// error - any error encountered +// It returns an error if it cannot read the volume transaction logs from the persistent store. +// Example: +// err := o.bootstrapVolTxns(ctx) +// if err != nil { +// return err +// } + func (o *TridentOrchestrator) bootstrapVolTxns(ctx context.Context) error { volTxns, err := o.storeClient.GetVolumeTransactions(ctx) @@ -391,6 +477,19 @@ func (o *TridentOrchestrator) bootstrapVolTxns(ctx context.Context) error { return nil } +// bootstrapNodes is called during startup to populate the node map with any +// existing nodes. +// Parameters: +// ctx - context +// Returns: +// error - any error encountered +// It returns an error if the node map could not be populated. +// Example: +// err := o.bootstrapNodes(ctx) +// if err != nil { +// return err +// } + func (o *TridentOrchestrator) bootstrapNodes(ctx context.Context) error { // Don't bootstrap nodes if we're not CSI @@ -417,6 +516,15 @@ func (o *TridentOrchestrator) bootstrapNodes(ctx context.Context) error { return nil } +// bootstrapVolumePublications bootstraps the volume publications from the backend store +// Parameters: +// ctx - context for logging +// Returns: +// error - any error encountered +// It returns an error if the backend store is unavailable. +// Example: +// err := o.bootstrapVolumePublications(ctx) + func (o *TridentOrchestrator) bootstrapVolumePublications(ctx context.Context) error { // Don't bootstrap volume publications if we're not CSI @@ -439,6 +547,22 @@ func (o *TridentOrchestrator) bootstrapVolumePublications(ctx context.Context) e return nil } +// addVolumePublicationToCache adds a volume publication to the orchestrator's cache +// Parameters: +// vp: the volume publication to add +// Return: +// none +// Example: +// o := NewTridentOrchestrator() +// vp := utils.VolumePublication{ +// VolumeName: "volume1", +// NodeName: "node1", +// DevicePath: "/dev/sda", +// Format: "ext4", +// MountPoint: "/mnt/trident", +// } +// o.addVolumePublicationToCache(vp) + func (o *TridentOrchestrator) addVolumePublicationToCache(vp *utils.VolumePublication) { // If the volume has no entry we need to initialize the inner map if o.volumePublications[vp.VolumeName] == nil { @@ -447,6 +571,21 @@ func (o *TridentOrchestrator) addVolumePublicationToCache(vp *utils.VolumePublic o.volumePublications[vp.VolumeName][vp.NodeName] = vp } +// bootstrap loads the state of the orchestrator from the persistent store. +// +// This is called at startup and after a connection to the persistent store is +// re-established. +// Parameters: +// ctx - context for the operation +// Returns: +// error - any error encountered +// It returns an error if the persistent store is not available. +// Example: +// err := o.bootstrap(ctx) +// if err != nil { +// // handle error +// } + func (o *TridentOrchestrator) bootstrap(ctx context.Context) error { // Fetching backend information @@ -560,6 +699,23 @@ func (o *TridentOrchestrator) updateMetrics() { } } +// handleFailedTransaction attempts to roll back a failed transaction. +// +// The rollback is performed by deleting the volume or snapshot from the backend +// and/or persistent store, as appropriate. +// +// If the transaction is successfully rolled back, the transaction object is +// deleted from persistent store. +// +// If the transaction is not successfully rolled back, the transaction object is +// left in persistent store, so that it can be retried on the next boot. +// It returns an error if the transaction could not be rolled back. +// Example: +// err := orchestrator.handleFailedTransaction(ctx, txn) +// if err != nil { +// log.Errorf("Failed to roll back transaction %s: %v", txn.ID, err) +// } + func (o *TridentOrchestrator) handleFailedTransaction(ctx context.Context, v *storage.VolumeTransaction) error { switch v.Op { @@ -798,6 +954,17 @@ func (o *TridentOrchestrator) handleFailedTransaction(ctx context.Context, v *st return nil } +// resetImportedVolumeName attempts to rename the volume back to its original name +// This is only used for imported volumes +// Parameters: +// ctx - context +// volume - volume to rename +// Returns: +// error - any error encountered +// It returns an error if the volume is not found in any backend +// Example: +// err := o.resetImportedVolumeName(ctx, volume) + func (o *TridentOrchestrator) resetImportedVolumeName(ctx context.Context, volume *storage.VolumeConfig) error { // The volume could be renamed (notManaged = false) without being persisted. @@ -815,6 +982,15 @@ func (o *TridentOrchestrator) resetImportedVolumeName(ctx context.Context, volum return nil } +// AddFrontend adds a frontend plugin to the orchestrator +// Parameters: +// f - the frontend plugin to add +// Returns: +// none +// Example: +// o := NewTridentOrchestrator() +// o.AddFrontend(frontend.NewKubernetes()) + func (o *TridentOrchestrator) AddFrontend(f frontend.Plugin) { name := f.GetName() if _, ok := o.frontends[name]; ok { @@ -825,6 +1001,16 @@ func (o *TridentOrchestrator) AddFrontend(f frontend.Plugin) { o.frontends[name] = f } +// GetFrontend returns a frontend plugin by name +// Parameters: +// ctx - context +// name - name of the frontend plugin +// Returns: +// frontend.Plugin - the frontend plugin +// error - error if any +// Example: +// frontend, err := GetFrontend(ctx, "iscsi") + func (o *TridentOrchestrator) GetFrontend(ctx context.Context, name string) (frontend.Plugin, error) { if fe, ok := o.frontends[name]; !ok { @@ -836,6 +1022,19 @@ func (o *TridentOrchestrator) GetFrontend(ctx context.Context, name string) (fro } } +// validateBackendUpdate validates that the backend update operation is valid. +// Parameters: +// oldBackend - the backend before the update +// newBackend - the backend after the update +// Returns: +// error - nil if the update is valid, otherwise an error describing why the update is invalid +// It returns an error if the backend type is being changed. +// Example: +// o := NewTridentOrchestrator(...) +// oldBackend := o.backendRegistry.GetBackend("oldBackend") +// newBackend := o.backendRegistry.GetBackend("newBackend") +// err := o.validateBackendUpdate(oldBackend, newBackend) + func (o *TridentOrchestrator) validateBackendUpdate(oldBackend, newBackend storage.Backend) error { // Validate that backend type isn't being changed as backend type has // implications for the internal volume names. @@ -848,6 +1047,15 @@ func (o *TridentOrchestrator) validateBackendUpdate(oldBackend, newBackend stora return nil } +// GetVersion returns the version of the orchestrator +// Parameters: +// ctx - context for the request +// Returns: +// version string +// error - if any +// Example: +// version, err := o.GetVersion(ctx) + func (o *TridentOrchestrator) GetVersion(context.Context) (string, error) { return config.OrchestratorVersion.String(), o.bootstrapError } @@ -1106,6 +1314,16 @@ func (o *TridentOrchestrator) UpdateBackendByBackendUUID( // TODO combine this one and the one above // updateBackendByBackendUUID updates an existing backend. It assumes the mutex lock is already held. +// updateBackendByBackendUUID updates an existing backend. +// Parameters: +// backendName - the name of the backend +// configJSON - the backend configuration +// backendUUID - the UUID of the backend +// callingConfigRef - the UID of the TridentBackendConfig CR that initiated this operation +// It returns the backend's external representation. +// Example: +// backendExternal, err := o.updateBackendByBackendUUID(ctx, "be-name", "config", "be-uuid", "tbc-uid") + func (o *TridentOrchestrator) updateBackendByBackendUUID( ctx context.Context, backendName, configJSON, backendUUID, callingConfigRef string, ) (backendExternal *storage.BackendExternal, err error) { @@ -1386,6 +1604,15 @@ func (o *TridentOrchestrator) updateBackendState( return backend.ConstructExternal(ctx), o.storeClient.UpdateBackend(ctx, backend) } +// getBackendUUIDByBackendName returns the backend UUID for a given backend name +// Parameters: +// backendName - the name of the backend +// Returns: +// string - the backend UUID +// error - any error encountered +// Example: +// backendUUID, err := o.getBackendUUIDByBackendName("backend1") + func (o *TridentOrchestrator) getBackendUUIDByBackendName(backendName string) (string, error) { backendUUID := "" for _, b := range o.backends { @@ -1397,6 +1624,15 @@ func (o *TridentOrchestrator) getBackendUUIDByBackendName(backendName string) (s return "", utils.NotFoundError(fmt.Sprintf("backend %v was not found", backendName)) } +// getBackendByBackendName returns the backend with the given name +// Parameters: +// backendName - the name of the backend to return +// Returns: +// storage.Backend - the backend with the given name +// error - nil if the backend was found, error otherwise +// Example: +// b, err := o.getBackendByBackendName("ontap-nas") + func (o *TridentOrchestrator) getBackendByBackendName(backendName string) (storage.Backend, error) { for _, b := range o.backends { if b.Name() == backendName { @@ -1406,6 +1642,15 @@ func (o *TridentOrchestrator) getBackendByBackendName(backendName string) (stora return nil, utils.NotFoundError(fmt.Sprintf("backend %v was not found", backendName)) } +// getBackendByConfigRef returns a backend based on the configRef +// Parameters: +// configRef - the configRef of the backend to return +// Returns: +// storage.Backend - the backend with the matching configRef +// error - nil if successful, error if not +// Example: +// b, err := o.getBackendByConfigRef("csi-volumes") + func (o *TridentOrchestrator) getBackendByConfigRef(configRef string) (storage.Backend, error) { for _, b := range o.backends { if b.ConfigRef() == configRef { @@ -1415,6 +1660,15 @@ func (o *TridentOrchestrator) getBackendByConfigRef(configRef string) (storage.B return nil, utils.NotFoundError(fmt.Sprintf("backend based on configRef '%v' was not found", configRef)) } +// getBackendByBackendUUID returns a backend by backendUUID +// Parameters: +// backendUUID - the backendUUID of the backend to return +// Return: +// storage.Backend - the backend +// error - any errors encountered +// Example: +// backend, err := o.getBackendByBackendUUID(backendUUID) + func (o *TridentOrchestrator) getBackendByBackendUUID(backendUUID string) (storage.Backend, error) { backend := o.backends[backendUUID] if backend != nil { @@ -1423,6 +1677,18 @@ func (o *TridentOrchestrator) getBackendByBackendUUID(backendUUID string) (stora return nil, utils.NotFoundError(fmt.Sprintf("backend uuid %v was not found", backendUUID)) } +// GetBackend returns the backend object for the specified backend name +// Parameters: +// backendName - name of the backend +// Returns: +// *storage.BackendExternal - backend object +// error - error if any +// Example: +// backendExternal, err := orchestrator.GetBackend(ctx, "backend1") +// if err != nil { +// log.Errorf("Could not retrieve backend: %v", err) +// } + func (o *TridentOrchestrator) GetBackend( ctx context.Context, backendName string, ) (backendExternal *storage.BackendExternal, err error) { @@ -1455,6 +1721,16 @@ func (o *TridentOrchestrator) GetBackend( return backendExternal, nil } +// GetBackendByBackendUUID returns a backend by its UUID +// Parameters: +// ctx - context for logging +// backendUUID - UUID of the backend +// Returns: +// *storage.BackendExternal - backend object +// error - error object, nil if no error +// Example: +// backendExternal, err := orchestrator.GetBackendByBackendUUID(context.TODO(), "12345678-1234-1234-1234-123456789012") + func (o *TridentOrchestrator) GetBackendByBackendUUID( ctx context.Context, backendUUID string, ) (backendExternal *storage.BackendExternal, err error) { @@ -1484,6 +1760,15 @@ func (o *TridentOrchestrator) GetBackendByBackendUUID( return backendExternal, nil } +// ListBackends returns a list of backends +// Parameters: +// ctx - context for logging +// Returns: +// backends - list of backends +// err - error, if any +// Example: +// backends, err := o.ListBackends(ctx) + func (o *TridentOrchestrator) ListBackends( ctx context.Context, ) (backendExternals []*storage.BackendExternal, err error) { @@ -1508,6 +1793,18 @@ func (o *TridentOrchestrator) ListBackends( return backends, nil } +// DeleteBackend deletes a backend from the orchestrator. +// Parameters: +// backendName - the name of the backend to delete +// Returns: +// error - any error encountered +// It returns an error if the backend does not exist. +// Example: +// err := orchestrator.DeleteBackend(ctx, "backend-1") +// if err != nil { +// fmt.Printf("Failed to delete backend: %v\n", err) +// } + func (o *TridentOrchestrator) DeleteBackend(ctx context.Context, backendName string) (err error) { if o.bootstrapError != nil { @@ -1530,6 +1827,16 @@ func (o *TridentOrchestrator) DeleteBackend(ctx context.Context, backendName str return o.deleteBackendByBackendUUID(ctx, backendName, backendUUID) } +// DeleteBackendByBackendUUID deletes a backend by its UUID +// Parameters: +// backendName - name of the backend to delete +// backendUUID - UUID of the backend to delete +// Returns: +// error - any error encountered +// It returns an error if the backend does not exist. +// Example: +// err := orchestrator.DeleteBackendByBackendUUID(ctx, "backend1", "12345678-1234-1234-1234-123456789012") + func (o *TridentOrchestrator) DeleteBackendByBackendUUID( ctx context.Context, backendName, backendUUID string, ) (err error) { @@ -1550,6 +1857,17 @@ func (o *TridentOrchestrator) DeleteBackendByBackendUUID( return o.deleteBackendByBackendUUID(ctx, backendName, backendUUID) } +// deleteBackendByBackendUUID deletes a backend by backend UUID +// Parameters: +// ctx - context +// backendName - name of the backend to delete +// backendUUID - UUID of the backend to delete +// Returns: +// error - error if any +// It returns an error if the backend is not found. +// Example: +// err := o.deleteBackendByBackendUUID(ctx, "myBackend", "myBackendUUID") + func (o *TridentOrchestrator) deleteBackendByBackendUUID(ctx context.Context, backendName, backendUUID string) error { Logc(ctx).WithFields(log.Fields{ @@ -1629,6 +1947,16 @@ func (o *TridentOrchestrator) RemoveBackendConfigRef(ctx context.Context, backen return o.storeClient.UpdateBackend(ctx, b) } +// AddVolume creates a new volume. +// Parameters: +// volumeConfig: The configuration for the new volume. +// Returns: +// externalVol: The new volume. +// err: Any errors encountered. +// It returns an error if the volume already exists. +// Example: +// vol, err := orchestrator.AddVolume(volumeConfig) + func (o *TridentOrchestrator) AddVolume( ctx context.Context, volumeConfig *storage.VolumeConfig, ) (externalVol *storage.VolumeExternal, err error) { @@ -1886,6 +2214,34 @@ func (o *TridentOrchestrator) addVolumeFinish( return externalVol, nil } +// CloneVolume clones a volume +// Parameters: +// volumeConfig - volume config +// backendUUID - backend UUID +// backendName - backend name +// backendState - backend state +// backend - backend +// backendPool - backend pool +// volumeContext - volume context +// cloneFromSnapshot - clone from snapshot +// cloneFromSnapshotName - clone from snapshot name +// cloneFromSnapshotID - clone from snapshot ID +// cloneFromSnapshotTimestamp - clone from snapshot timestamp +// cloneFromVolumeName - clone from volume name +// cloneFromVolumeID - clone from volume ID +// cloneFromVolumeTimestamp - clone from volume timestamp +// cloneFromVolume - clone from volume +// cloneFromVolumeSnapshot - clone from volume snapshot +// cloneFromVolumeSnapshotName - clone from volume snapshot name +// cloneFromVolumeSnapshotID - clone from volume snapshot ID +// cloneFromVolumeSnapshotTimestamp - clone from volume snapshot timestamp +// Returns: +// externalVol - external volume +// err - error +// It returns an error if the volume already exists. +// Example: +// externalVol, err := o.CloneVolume(ctx, volumeConfig) + func (o *TridentOrchestrator) CloneVolume( ctx context.Context, volumeConfig *storage.VolumeConfig, ) (externalVol *storage.VolumeExternal, err error) { @@ -1918,6 +2274,20 @@ func (o *TridentOrchestrator) CloneVolume( return o.cloneVolumeInitial(ctx, volumeConfig) } +// cloneVolumeInitial creates a clone of the specified volume. +// Parameters: +// volumeConfig: the configuration of the volume to be cloned +// Returns: +// externalVol: the external representation of the cloned volume +// err: any errors encountered +// It returns an error if the clone operation fails. +// Example: +// externalVol, err := o.cloneVolumeInitial(ctx, sourceVolume.Config, volumeConfig) +// if err != nil { +// return nil, err +// } +// // Do something with externalVol + func (o *TridentOrchestrator) cloneVolumeInitial( ctx context.Context, volumeConfig *storage.VolumeConfig, ) (externalVol *storage.VolumeExternal, err error) { @@ -2060,6 +2430,17 @@ func (o *TridentOrchestrator) cloneVolumeInitial( return o.addVolumeFinish(ctx, txn, vol, backend, pool) } +// cloneVolumeRetry is the retry function for cloneVolume. +// Parameters: +// ctx - context +// txn - transaction +// Returns: +// externalVol - volume +// err - error +// It returns an error if the volume could not be created. +// Example: +// externalVol, err := cloneVolumeRetry(ctx, txn) + func (o *TridentOrchestrator) cloneVolumeRetry( ctx context.Context, txn *storage.VolumeTransaction, ) (externalVol *storage.VolumeExternal, err error) { @@ -2193,6 +2574,22 @@ func (o *TridentOrchestrator) GetVolumeByInternalName( return "", utils.NotFoundError(fmt.Sprintf("volume %s not found", volumeInternal)) } +// validateImportVolume validates the volume +// Parameters: +// volumeConfig: volume config +// Return: +// error: error if any +// It returns error if +// - volume already exists +// - storage class is not found +// - storage class does not match any storage pools for backend +// - volume is not found in the backend +// - volume mode, access mode and protocol are incompatible with the backend +// Example: +// if err := o.validateImportVolume(ctx, volumeConfig); err != nil { +// return err +// } + func (o *TridentOrchestrator) validateImportVolume(ctx context.Context, volumeConfig *storage.VolumeConfig) error { backend, err := o.getBackendByBackendUUID(volumeConfig.ImportBackendUUID) @@ -2255,6 +2652,20 @@ func (o *TridentOrchestrator) validateImportVolume(ctx context.Context, volumeCo return nil } +// LegacyImportVolume imports a volume from a backend. +// Parameters: +// ctx - context for logging +// volumeConfig - volume configuration +// backendName - name of the backend +// notManaged - if true, the volume is not managed by Trident +// createPVandPVC - callback function to create a PV and PVC for the imported volume +// Returns: +// externalVol - external representation of the volume +// err - error, if any +// It returns an error if the volume cannot be imported. +// Example: +// externalVol, err := orchestrator.LegacyImportVolume(ctx, volumeConfig, backendName, notManaged, createPVandPVC) + func (o *TridentOrchestrator) LegacyImportVolume( ctx context.Context, volumeConfig *storage.VolumeConfig, backendName string, notManaged bool, createPVandPVC VolumeCallback, @@ -2346,6 +2757,22 @@ func (o *TridentOrchestrator) LegacyImportVolume( return volExternal, nil } +// ImportVolume imports a volume from an external backend +// Parameters: +// ctx - context for logging +// volumeConfig - volume config for the volume to be imported +// Returns: +// *storage.VolumeExternal - volume object for the imported volume +// error - error if any +// It returns error if the volume cannot be imported +// Example: +// volumeConfig := &storage.VolumeConfig{ +// Name: "volume1", +// ImportOriginalName: "vol1", +// ImportBackendUUID: "8f6c0f6e-b99a-11e8-8eb2-f2801f1b9fd1", +// } +// volExternal, err := orchestrator.ImportVolume(ctx, volumeConfig) + func (o *TridentOrchestrator) ImportVolume( ctx context.Context, volumeConfig *storage.VolumeConfig, ) (externalVol *storage.VolumeExternal, err error) { @@ -2478,6 +2905,16 @@ func (o *TridentOrchestrator) AddVolumeTransaction(ctx context.Context, volTxn * return o.storeClient.AddVolumeTransaction(ctx, volTxn) } +// GetVolumeCreatingTransaction returns a VolumeCreating transaction if one exists. +// Parameters: +// ctx - context +// config - volume config +// Returns: +// *storage.VolumeTransaction - volume transaction +// error - error +// Example: +// txn, err := o.GetVolumeCreatingTransaction(ctx, config) + func (o *TridentOrchestrator) GetVolumeCreatingTransaction( ctx context.Context, config *storage.VolumeConfig, ) (*storage.VolumeTransaction, error) { @@ -2498,6 +2935,17 @@ func (o *TridentOrchestrator) GetVolumeCreatingTransaction( } } +// GetVolumeTransaction retrieves a volume transaction from the backend +// Parameters: +// ctx - context for logging +// volTxn - volume transaction to retrieve +// Returns: +// *storage.VolumeTransaction - retrieved volume transaction +// error - error if any +// It returns an error if the volume transaction could not be retrieved +// Example: +// volTxn, err := o.GetVolumeTransaction(ctx, volTxn) + func (o *TridentOrchestrator) GetVolumeTransaction( ctx context.Context, volTxn *storage.VolumeTransaction, ) (*storage.VolumeTransaction, error) { @@ -2626,6 +3074,17 @@ func (o *TridentOrchestrator) addVolumeRetryCleanup( return err } +// importVolumeCleanup is a helper function to clean up the volume +// Parameters: +// err: the error that caused the cleanup +// volumeConfig: the volume config +// volTxn: the volume transaction +// Returns: +// error: any error encountered during cleanup +// It returns the error that caused the cleanup if there was one. +// Example: +// err := importVolumeCleanup(err, volumeConfig, volTxn) + func (o *TridentOrchestrator) importVolumeCleanup( ctx context.Context, err error, volumeConfig *storage.VolumeConfig, volTxn *storage.VolumeTransaction, ) error { @@ -2683,6 +3142,20 @@ func (o *TridentOrchestrator) importVolumeCleanup( return err } +// GetVolume retrieves a volume from the backend +// Parameters: +// volume - name of the volume to retrieve +// Returns: +// *storage.VolumeExternal - volume object +// error - error if any +// It returns an error if the volume does not exist. +// Example: +// vol, err := orchestrator.GetVolume("volume1") +// if err != nil { +// // handle error +// } +// fmt.Println(vol) + func (o *TridentOrchestrator) GetVolume( ctx context.Context, volume string, ) (volExternal *storage.VolumeExternal, err error) { @@ -2698,6 +3171,15 @@ func (o *TridentOrchestrator) GetVolume( return o.getVolume(ctx, volume) } +// getVolume returns a volume by name +// Parameters: +// volume - name of the volume +// Returns: +// *storage.VolumeExternal - volume object +// error - error if any +// Example: +// vol, err := tridentOrchestrator.getVolume(ctx, "volume1") + func (o *TridentOrchestrator) getVolume( _ context.Context, volume string, ) (volExternal *storage.VolumeExternal, err error) { @@ -2708,6 +3190,15 @@ func (o *TridentOrchestrator) getVolume( return vol.ConstructExternal(), nil } +// GetDriverTypeForVolume returns the driver type for the volume +// Parameters: +// vol - volume to get driver type for +// Returns: +// string - driver type +// error - any error encountered +// Example: +// driverType, err := o.GetDriverTypeForVolume(vol) + func (o *TridentOrchestrator) GetDriverTypeForVolume(_ context.Context, vol *storage.VolumeExternal) (string, error) { if o.bootstrapError != nil { return config.UnknownDriver, o.bootstrapError @@ -2730,6 +3221,17 @@ func (o *TridentOrchestrator) getDriverTypeForVolume(backendUUID string) (string return config.UnknownDriver, nil } +// GetVolumeType returns the volume type for a given volume. +// Parameters: +// vol *storage.VolumeExternal +// volume to get the type for +// Returns: +// volumeType config.VolumeType +// err error +// any error encountered +// Example: +// volumeType, err := core.GetVolumeType(vol) + func (o *TridentOrchestrator) GetVolumeType( _ context.Context, vol *storage.VolumeExternal, ) (volumeType config.VolumeType, err error) { @@ -2763,6 +3265,23 @@ func (o *TridentOrchestrator) GetVolumeType( return } +// ListVolumes lists all volumes that are currently known to the orchestrator. +// Parameters: +// context - The context for the request +// Returns: +// A list of volumes +// Any error encountered +// It returns an error if the orchestrator is not in a ready state. +// Example: +// volumes, err := c.ListVolumes(ctx) +// if err != nil { +// log.Errorf("Could not list volumes: %v", err) +// } else { +// for _, volume := range volumes { +// log.Infof("Volume %v", volume.Config.Name) +// } +// } + func (o *TridentOrchestrator) ListVolumes(context.Context) (volumes []*storage.VolumeExternal, err error) { if o.bootstrapError != nil { return nil, o.bootstrapError @@ -2881,6 +3400,20 @@ func (o *TridentOrchestrator) deleteVolume(ctx context.Context, volumeName strin return nil } +// deleteVolumeFromPersistentStoreIgnoreError deletes the volume from the persistent store, ignoring +// any errors that may occur. +// Parameters: +// ctx - context +// volume - volume to delete +// Returns: +// error - any error encountered +// It returns an error if the volume is not found in the persistent store. +// Example: +// err := o.deleteVolumeFromPersistentStoreIgnoreError(ctx, volume) +// if err != nil { +// log.Errorf("Unable to delete volume from persistent store: %v", err) +// } + func (o *TridentOrchestrator) deleteVolumeFromPersistentStoreIgnoreError( ctx context.Context, volume *storage.Volume, ) error { @@ -2956,6 +3489,16 @@ func (o *TridentOrchestrator) DeleteVolume(ctx context.Context, volumeName strin return o.deleteVolume(ctx, volumeName) } +// ListVolumesByPlugin lists all volumes for a given plugin +// Parameters: +// pluginName - name of the plugin +// Returns: +// volumes - list of volumes +// error - any error encountered +// It returns an error if the plugin is not found. +// Example: +// volumes, err := client.ListVolumesByPlugin("ontap-nas") + func (o *TridentOrchestrator) ListVolumesByPlugin( _ context.Context, pluginName string, ) (volumes []*storage.VolumeExternal, err error) { @@ -2980,6 +3523,25 @@ func (o *TridentOrchestrator) ListVolumesByPlugin( return volumes, nil } +// PublishVolume publishes the volume to the specified nodes. +// Parameters: +// volumeName: the name of the volume to publish +// publishInfo: information about the volume to publish +// Return: +// error: nil if successful, otherwise an error object is returned +// It returns an error if the volume is not found or is being deleted. +// Example: +// err := orchestrator.PublishVolume("volume1", &utils.VolumePublishInfo{ +// Nodes: []*utils.Node{ +// { +// Name: "node1", +// }, +// }, +// }) +// if err != nil { +// return err +// } + func (o *TridentOrchestrator) PublishVolume( ctx context.Context, volumeName string, publishInfo *utils.VolumePublishInfo, ) (err error) { @@ -3031,6 +3593,19 @@ func (o *TridentOrchestrator) PublishVolume( return nil } +// UnpublishVolume unpublishes a volume from a node +// Parameters: +// volumeName - name of the volume to unpublish +// nodeName - name of the node from which to unpublish the volume +// Returns: +// error - any error encountered +// It returns an error if the volume or node is not found, or if the volume is not published to the node. +// Example: +// err := orchestrator.UnpublishVolume("vol-001", "node-001") +// if err != nil { +// log.Error(err.Error()) +// } + func (o *TridentOrchestrator) UnpublishVolume(ctx context.Context, volumeName, nodeName string) (err error) { if o.bootstrapError != nil { @@ -3403,6 +3978,21 @@ func (o *TridentOrchestrator) addSnapshotCleanup( return err } +// GetSnapshot retrieves a snapshot from Trident's backend. +// Parameters: +// ctx - context for the request +// volumeName - name of the volume containing the snapshot +// snapshotName - name of the snapshot to retrieve +// Returns: +// snapshotExternal - a snapshot object +// err - error if any +// It returns an error if the snapshot does not exist. +// Example: +// snapshotExternal, err := orchestrator.GetSnapshot(ctx, "myvol", "mysnap") +// if err != nil { +// log.Fatal(err) +// } + func (o *TridentOrchestrator) GetSnapshot( ctx context.Context, volumeName, snapshotName string, ) (snapshotExternal *storage.SnapshotExternal, err error) { @@ -3419,6 +4009,19 @@ func (o *TridentOrchestrator) GetSnapshot( return o.getSnapshot(ctx, volumeName, snapshotName) } +// getSnapshot returns a snapshot object from the orchestrator's cache. +// If the snapshot is in a creating or uploading state, the orchestrator will +// attempt to update the snapshot's state. +// Parameters: +// ctx - context for logging +// volumeName - name of the volume the snapshot belongs to +// snapshotName - name of the snapshot to retrieve +// Returns: +// *storage.SnapshotExternal - snapshot object +// error - error if one occurred +// Example: +// snapshot, err := o.getSnapshot(ctx, "volume1", "snapshot1") + func (o *TridentOrchestrator) getSnapshot( ctx context.Context, volumeName, snapshotName string, ) (*storage.SnapshotExternal, error) { @@ -3438,6 +4041,21 @@ func (o *TridentOrchestrator) getSnapshot( } } +// updateSnapshot updates the snapshot state in the orchestrator and persistent store +// Parameters: +// ctx - context +// snapshot - snapshot to update +// Returns: +// updated snapshot +// error +// It returns the snapshot if it is known to be ready, otherwise it updates the snapshot state +// in the orchestrator and persistent store. +// Example: +// updatedSnapshot, err := o.updateSnapshot(ctx, snapshot) +// if err != nil { +// return err +// } + func (o *TridentOrchestrator) updateSnapshot( ctx context.Context, snapshot *storage.Snapshot, ) (*storage.Snapshot, error) { @@ -3537,6 +4155,20 @@ func (o *TridentOrchestrator) deleteSnapshot(ctx context.Context, snapshotConfig return nil } +// deleteSnapshotFromPersistentStoreIgnoreError is a wrapper for +// DeleteSnapshotIgnoreNotFound that logs errors. +// Parameters: +// ctx - context +// snapshot - snapshot to delete +// Returns: +// error - error if one occurred +// It returns an error if one occurred. +// Example: +// err := o.deleteSnapshotFromPersistentStoreIgnoreError(ctx, snapshot) +// if err != nil { +// return err +// } + func (o *TridentOrchestrator) deleteSnapshotFromPersistentStoreIgnoreError( ctx context.Context, snapshot *storage.Snapshot, ) error { @@ -3655,6 +4287,16 @@ func (o *TridentOrchestrator) DeleteSnapshot(ctx context.Context, volumeName, sn return o.deleteSnapshot(ctx, snapshot.Config) } +// ListSnapshots lists all snapshots in the orchestrator +// Parameters: +// context - context for the call +// Returns: +// []*storage.SnapshotExternal - list of snapshots +// error - error if any +// It returns an error if the orchestrator is not initialized. +// Example: +// snapshots, err := orchestrator.ListSnapshots(context.Background()) + func (o *TridentOrchestrator) ListSnapshots(context.Context) (snapshots []*storage.SnapshotExternal, err error) { if o.bootstrapError != nil { return nil, o.bootstrapError @@ -3673,6 +4315,15 @@ func (o *TridentOrchestrator) ListSnapshots(context.Context) (snapshots []*stora return snapshots, nil } +// ListSnapshotsByName returns a list of snapshots matching the given name +// Parameters: +// snapshotName - name of the snapshot +// Returns: +// []*storage.SnapshotExternal - list of snapshots +// error - error if any +// Example: +// snapshots, err := tridentOrchestrator.ListSnapshotsByName("trident") + func (o *TridentOrchestrator) ListSnapshotsByName( _ context.Context, snapshotName string, ) (snapshots []*storage.SnapshotExternal, err error) { @@ -3695,6 +4346,15 @@ func (o *TridentOrchestrator) ListSnapshotsByName( return snapshots, nil } +// ListSnapshotsForVolume returns a list of snapshots for the specified volume +// Parameters: +// volumeName - name of the volume +// Returns: +// snapshots - list of snapshots for the specified volume +// err - error, if any +// Example: +// snapshots, err := trident.ListSnapshotsForVolume("vol-01") + func (o *TridentOrchestrator) ListSnapshotsForVolume( _ context.Context, volumeName string, ) (snapshots []*storage.SnapshotExternal, err error) { @@ -3721,6 +4381,16 @@ func (o *TridentOrchestrator) ListSnapshotsForVolume( return snapshots, nil } +// ReadSnapshotsForVolume returns a list of snapshots for a given volume. +// Parameters: +// ctx - context for logging +// volumeName - name of the volume +// Returns: +// []*storage.SnapshotExternal - list of snapshots for the given volume +// error - error, if any +// Example: +// snapshots, err := o.ReadSnapshotsForVolume(ctx, volumeName) + func (o *TridentOrchestrator) ReadSnapshotsForVolume( ctx context.Context, volumeName string, ) (externalSnapshots []*storage.SnapshotExternal, err error) { @@ -3748,6 +4418,15 @@ func (o *TridentOrchestrator) ReadSnapshotsForVolume( return externalSnapshots, nil } +// ReloadVolumes reloads the volumes from the backend +// Parameters: +// ctx - context for logging +// Returns: +// error - any errors encountered +// It returns an error if the reload fails, in which case the original volume list is restored. +// Example: +// err := orchestrator.ReloadVolumes(context.Background()) + func (o *TridentOrchestrator) ReloadVolumes(ctx context.Context) (err error) { if o.bootstrapError != nil { @@ -4012,6 +4691,23 @@ func (o *TridentOrchestrator) getProtocol( return res.protocol, res.err } +// AddStorageClass adds a storage class to the orchestrator. +// Parameters: +// scConfig: configuration for the storage class to be added +// Returns: +// scExternal: the storage class that was added +// err: any errors encountered +// It returns an error if the storage class already exists. +// Example: +// scConfig := &storageclass.Config{ +// Name: "gold", +// Attributes: map[string]sa.Request{ +// sa.Media: "ssd", +// sa.ProvisioningType: "thin", +// }, +// } +// scExternal, err := o.AddStorageClass(ctx, scConfig) + func (o *TridentOrchestrator) AddStorageClass( ctx context.Context, scConfig *storageclass.Config, ) (scExternal *storageclass.External, err error) { @@ -4051,6 +4747,18 @@ func (o *TridentOrchestrator) AddStorageClass( return sc.ConstructExternal(ctx), nil } +// GetStorageClass returns the storage class with the given name +// Parameters: +// scName - name of the storage class +// Returns: +// *storageclass.External - the storage class +// error - nil if successful +// Example: +// sc, err := o.GetStorageClass(ctx, "default") +// if err != nil { +// return fmt.Errorf("error getting storage class %v: %v", "default", err) +// } + func (o *TridentOrchestrator) GetStorageClass( ctx context.Context, scName string, ) (scExternal *storageclass.External, err error) { @@ -4072,6 +4780,15 @@ func (o *TridentOrchestrator) GetStorageClass( return sc.ConstructExternal(ctx), nil } +// ListStorageClasses returns a list of storage classes +// Parameters: +// ctx - context for logging +// Returns: +// []*storageclass.External - list of storage classes +// error - error, if any +// Example: +// storageClasses, err := orchestrator.ListStorageClasses(ctx) + func (o *TridentOrchestrator) ListStorageClasses(ctx context.Context) ( scExternals []*storageclass.External, err error, ) { @@ -4091,6 +4808,16 @@ func (o *TridentOrchestrator) ListStorageClasses(ctx context.Context) ( return storageClasses, nil } +// DeleteStorageClass deletes a storage class +// Parameters: +// ctx - context for logging +// scName - name of the storage class to delete +// Returns: +// error - any error encountered +// It returns an error if the storage class is not found. +// Example: +// err := o.DeleteStorageClass(ctx, "gold") + func (o *TridentOrchestrator) DeleteStorageClass(ctx context.Context, scName string) (err error) { if o.bootstrapError != nil { return o.bootstrapError @@ -4122,6 +4849,15 @@ func (o *TridentOrchestrator) DeleteStorageClass(ctx context.Context, scName str return nil } +// reconcileNodeAccessOnAllBackends reconciles node access on all backends. +// Parameters: +// ctx - context +// Returns: +// error - any error encountered +// It returns an error if any of the backends fail to reconcile node access. +// Example: +// err := o.reconcileNodeAccessOnAllBackends(ctx) + func (o *TridentOrchestrator) reconcileNodeAccessOnAllBackends(ctx context.Context) error { if config.CurrentDriverContext != config.ContextCSI { @@ -4143,6 +4879,16 @@ func (o *TridentOrchestrator) reconcileNodeAccessOnAllBackends(ctx context.Conte return nil } +// reconcileNodeAccessOnBackend reconciles node access on the backend +// Parameters: +// ctx - context +// b - backend +// Returns: +// error - any error encountered +// It returns an error if it is unable to reconcile node access on the backend +// Example: +// error := o.reconcileNodeAccessOnBackend(ctx, backend) + func (o *TridentOrchestrator) reconcileNodeAccessOnBackend(ctx context.Context, b storage.Backend) error { if config.CurrentDriverContext != config.ContextCSI { @@ -4202,6 +4948,14 @@ func (o *TridentOrchestrator) PeriodicallyReconcileNodeAccessOnBackends() { } } +// AddNode adds a node to the orchestrator +// It returns an error if the node already exists +// Example: +// err := orchestrator.AddNode(ctx, node) +// if err != nil { +// log.Errorf("Could not add node %v: %v", node.Name, err) +// } + func (o *TridentOrchestrator) AddNode( ctx context.Context, node *utils.Node, nodeEventCallback NodeEventCallback, ) (err error) { @@ -4244,12 +4998,29 @@ func (o *TridentOrchestrator) AddNode( return nil } +// invalidateAllBackendNodeAccess invalidates the node access for all backends +// Example: +// o.invalidateAllBackendNodeAccess() + func (o *TridentOrchestrator) invalidateAllBackendNodeAccess() { for _, backend := range o.backends { backend.InvalidateNodeAccess() } } +// handleUpdatedNodePrep handles node prep status updates +// Parameters: +// ctx - context +// protocol - protocol for which node prep is being reported +// node - node object +// nodeEventCallback - callback to invoke when a node event is to be reported +// Example: +// o.handleUpdatedNodePrep(ctx, "NFS", node, func(nodeEventCallbackType helpers.EventType, nodeEventCallbackReason string, message string) { +// nodeEvent := helpers.NewNodeEvent(node.Name, nodeEventCallbackType, nodeEventCallbackReason, message) +// o.eventRecorder.Event(o.tridentOrchestrator, nodeEventCallbackType, nodeEventCallbackReason, message) +// o.nodeEvents.Add(nodeEvent) +// }) + func (o *TridentOrchestrator) handleUpdatedNodePrep( ctx context.Context, protocol string, node *utils.Node, nodeEventCallback NodeEventCallback, ) { @@ -4292,6 +5063,19 @@ func (o *TridentOrchestrator) handleUpdatedNodePrep( } } +// GetNode returns a node by name +// Parameters: +// ctx - context +// nName - name of node to retrieve +// Returns: +// *utils.Node - node object +// error - error object if any +// Example: +// node, err := o.GetNode(ctx, "node1") +// if err != nil { +// // handle error +// } + func (o *TridentOrchestrator) GetNode(ctx context.Context, nName string) (node *utils.Node, err error) { if o.bootstrapError != nil { return nil, o.bootstrapError @@ -4312,6 +5096,15 @@ func (o *TridentOrchestrator) GetNode(ctx context.Context, nName string) (node * return node, nil } +// ListNodes returns a list of all nodes in the cluster +// Parameters: +// context - context for the request +// Returns: +// nodes - list of nodes in the cluster +// err - error object +// Example: +// nodes, err := tridentOrchestrator.ListNodes(context.TODO()) + func (o *TridentOrchestrator) ListNodes(context.Context) (nodes []*utils.Node, err error) { if o.bootstrapError != nil { return nil, o.bootstrapError @@ -4329,6 +5122,17 @@ func (o *TridentOrchestrator) ListNodes(context.Context) (nodes []*utils.Node, e return nodes, nil } +// DeleteNode removes a node from the orchestrator. +// Parameters: +// nodeName: The name of the node to remove. +// force: If true, remove the node even if it still has volumes published to it. +// It returns an error if the node is not found, or if it still has volumes published to it. +// Example: +// err := orchestrator.DeleteNode(nodeName, false) +// if err != nil { +// t.Errorf("Failed to delete node %s: %+v", nodeName, err) +// } + func (o *TridentOrchestrator) DeleteNode(ctx context.Context, nodeName string) (err error) { if o.bootstrapError != nil { return o.bootstrapError @@ -4373,6 +5177,16 @@ func (o *TridentOrchestrator) DeleteNode(ctx context.Context, nodeName string) ( return nil } +// deleteNode deletes a node from the orchestrator +// Parameters: +// ctx - context +// nodeName - name of the node to delete +// Returns: +// error - error if any +// It returns an error if the node is not found +// Example: +// err := o.deleteNode(ctx, nodeName) + func (o *TridentOrchestrator) deleteNode(ctx context.Context, nodeName string) (err error) { node, found := o.nodes[nodeName] @@ -4471,6 +5285,14 @@ func (o *TridentOrchestrator) ListVolumePublicationsForVolume( return } +// listVolumePublicationsForVolume returns a list of volume publications for a given volume +// Parameters: +// volumeName: name of the volume +// Returns: +// []*utils.VolumePublication: list of volume publications +// Example: +// publications, err := o.listVolumePublicationsForVolume(volumeName) + func (o *TridentOrchestrator) listVolumePublicationsForVolume( _ context.Context, volumeName string, ) (publications []*utils.VolumePublication) { @@ -4499,6 +5321,14 @@ func (o *TridentOrchestrator) ListVolumePublicationsForNode( return } +// listVolumePublicationsForNode returns a list of all volume publications for the given node +// Parameters: +// nodeName - the name of the node +// Returns: +// a list of volume publications +// Example: +// publications, _ := o.listVolumePublicationsForNode(nodeName) + func (o *TridentOrchestrator) listVolumePublicationsForNode( _ context.Context, nodeName string, ) (publications []*utils.VolumePublication) { @@ -4538,6 +5368,13 @@ func (o *TridentOrchestrator) DeleteVolumePublication(ctx context.Context, volum return nil } +// removeVolumePublicationFromCache removes the volume publication from the cache +// Parameters: +// volumeID: the volume ID +// nodeID: the node ID +// Example: +// o.removeVolumePublicationFromCache("vol1", "node1") + func (o *TridentOrchestrator) removeVolumePublicationFromCache(volumeID string, nodeID string) { delete(o.volumePublications[volumeID], nodeID) // If there are no more nodes for this volume, remove the volume's entry @@ -4546,6 +5383,20 @@ func (o *TridentOrchestrator) removeVolumePublicationFromCache(volumeID string, } } +// updateBackendOnPersistentStore updates the backend information in the persistent store +// Parameters: +// ctx - context for logging +// backend - the backend to update +// newBackend - true if this is a new backend, false if it is an existing backend +// Returns: +// error - any error encountered +// It returns an error if the backend could not be updated in the persistent store +// Example: +// err := o.updateBackendOnPersistentStore(ctx, backend, true) +// if err != nil { +// return err +// } + func (o *TridentOrchestrator) updateBackendOnPersistentStore( ctx context.Context, backend storage.Backend, newBackend bool, ) error { @@ -4570,6 +5421,16 @@ func (o *TridentOrchestrator) updateBackendOnPersistentStore( return nil } +// updateVolumeOnPersistentStore updates the volume information in persistent store +// Parameters: +// ctx - context for logging +// vol - volume to update +// Returns: +// error - any error encountered +// It returns an error if the volume cannot be updated in persistent store +// Example: +// err := o.updateVolumeOnPersistentStore(ctx, vol) + func (o *TridentOrchestrator) updateVolumeOnPersistentStore(ctx context.Context, vol *storage.Volume) error { // Update the volume information in persistent store @@ -4582,6 +5443,16 @@ func (o *TridentOrchestrator) updateVolumeOnPersistentStore(ctx context.Context, return o.storeClient.UpdateVolume(ctx, vol) } +// replaceBackendAndUpdateVolumesOnPersistentStore updates both backend and volume information in persistent store +// Parameters: +// origBackend - the original backend +// newBackend - the new backend +// Returns: +// error - any error encountered +// It returns an error if the backend is not found in persistent store +// Example: +// err := o.replaceBackendAndUpdateVolumesOnPersistentStore(ctx, origBackend, newBackend) + func (o *TridentOrchestrator) replaceBackendAndUpdateVolumesOnPersistentStore( ctx context.Context, origBackend, newBackend storage.Backend, ) error { @@ -4594,6 +5465,13 @@ func (o *TridentOrchestrator) replaceBackendAndUpdateVolumesOnPersistentStore( return o.storeClient.ReplaceBackendAndUpdateVolumes(ctx, origBackend, newBackend) } +// isCRDContext returns true if the context was created by a CRD request. +// Parameters: +// ctx - the context to check +// Example: +// ctx := context.Background() +// isCRD := o.isCRDContext(ctx) + func (o *TridentOrchestrator) isCRDContext(ctx context.Context) bool { ctxSource := ctx.Value(ContextKeyRequestSource) return ctxSource != nil && ctxSource == ContextSourceCRD @@ -4695,6 +5573,15 @@ func (o *TridentOrchestrator) GetMirrorStatus( return mirrorBackend.GetMirrorStatus(ctx, localVolumeHandle, remoteVolumeHandle) } +// CanBackendMirror returns true if the backend supports mirroring +// Parameters: +// backendUUID - the backend UUID +// Returns: +// bool - true if the backend supports mirroring +// error - any error encountered +// Example: +// capable, err := orchestrator.CanBackendMirror(backendUUID) + func (o *TridentOrchestrator) CanBackendMirror(_ context.Context, backendUUID string) (capable bool, err error) { if o.bootstrapError != nil { @@ -4736,6 +5623,16 @@ func (o *TridentOrchestrator) ReleaseMirror( return mirrorBackend.ReleaseMirror(ctx, localVolumeHandle) } +// GetCHAP returns CHAP information for the specified volume +// Parameters: +// volumeName - name of the volume +// nodeName - name of the node +// Returns: +// chapInfo - CHAP information +// err - error object +// Example: +// chapInfo, err := orchestrator.GetCHAP(ctx, "myVolume", "myNode") + func (o *TridentOrchestrator) GetCHAP( ctx context.Context, volumeName, nodeName string, ) (chapInfo *utils.IscsiChapInfo, err error) { diff --git a/core/orchestrator_core_test.go b/core/orchestrator_core_test.go index f48aa5fab..690980a9e 100644 --- a/core/orchestrator_core_test.go +++ b/core/orchestrator_core_test.go @@ -40,14 +40,6 @@ var ( ctx = context.Background ) -func init() { - testing.Init() - if *debug { - log.SetLevel(log.DebugLevel) - } - - inMemoryClient = persistentstore.NewInMemoryClient() -} type deleteTest struct { name string @@ -61,6 +53,13 @@ type recoveryTest struct { expectDestroy bool } +// cleanup is a helper function to clean up the persistent store. +// Parameters: +// t - the test object +// o - the orchestrator object +// Example: +// defer cleanup(t, o) + func cleanup(t *testing.T, o *TridentOrchestrator) { err := o.storeClient.DeleteBackends(ctx()) if err != nil && !persistentstore.MatchKeyNotFoundErr(err) { @@ -94,6 +93,21 @@ func cleanup(t *testing.T, o *TridentOrchestrator) { } } +// diffConfig compares two structs, ignoring the fieldToSkip +// and returns a list of differences +// Parameters: +// expected: the expected struct +// got: the actual struct +// fieldToSkip: the name of a field to skip +// Returns: +// a list of differences +// It returns an empty list if there are no differences +// Example: +// diffs := diffConfig(expected, got, "") +// if len(diffs) > 0 { +// t.Errorf("Config differs: %v", diffs) +// } + func diffConfig(expected, got interface{}, fieldToSkip string) []string { diffs := make([]string, 0) @@ -121,6 +135,18 @@ func diffConfig(expected, got interface{}, fieldToSkip string) []string { } // To be called after reflect.DeepEqual has failed. +// diffExternalBackends compares two external backends and returns a list of differences +// Parameters: +// expected: the expected backend +// got: the backend to compare against +// Returns: +// A list of differences +// Example: +// diffs := diffExternalBackends(expected, got) +// if len(diffs) > 0 { +// t.Errorf("External backends differ:\n\t%s", strings.Join(diffs, "\n\t")) +// } + func diffExternalBackends(t *testing.T, expected, got *storage.BackendExternal) { diffs := make([]string, 0) @@ -169,931 +195,242 @@ func diffExternalBackends(t *testing.T, expected, got *storage.BackendExternal) expectedJSON, err := json.Marshal(expectedVC) if err != nil { t.Fatal("Unable to marshal expected JSON for VC ", name) - } - gotJSON, err := json.Marshal(gotVC) - if err != nil { - t.Fatal("Unable to marshal got JSON for VC ", name) - } - diffs = append( - diffs, fmt.Sprintf( - "Storage: pool %s differs:\n\t\t"+ - "Expected: %s\n\t\tGot: %s", name, string(expectedJSON), string(gotJSON), - ), - ) - } - } - for name := range got.Storage { - if _, ok := expected.Storage[name]; !ok { - diffs = append(diffs, fmt.Sprintf("Storage: got unexpected VC %s", name)) - } - } - - // Diff volumes - expectedVolMap := make(map[string]bool, len(expected.Volumes)) - gotVolMap := make(map[string]bool, len(got.Volumes)) - for _, v := range expected.Volumes { - expectedVolMap[v] = true - } - for _, v := range got.Volumes { - gotVolMap[v] = true - } - for name := range expectedVolMap { - if _, ok := gotVolMap[name]; !ok { - diffs = append(diffs, fmt.Sprintf("Volumes: did not get expected volume %s", name)) - } - } - for name := range gotVolMap { - if _, ok := expectedVolMap[name]; !ok { - diffs = append(diffs, fmt.Sprintf("Volumes: got unexpected volume %s", name)) - } - } - if len(diffs) > 0 { - t.Errorf("External backends differ:\n\t%s", strings.Join(diffs, "\n\t")) - } -} - -func runDeleteTest( - t *testing.T, d *deleteTest, orchestrator *TridentOrchestrator, -) { - var ( - backendUUID string - backend storage.Backend - found bool - ) - if d.expectedSuccess { - orchestrator.mutex.Lock() - - backendUUID = orchestrator.volumes[d.name].BackendUUID - backend, found = orchestrator.backends[backendUUID] - if !found { - t.Errorf("Backend %v isn't managed by the orchestrator!", backendUUID) - } - if _, found = backend.Volumes()[d.name]; !found { - t.Errorf("Volume %s doesn't exist on backend %s!", d.name, backendUUID) - } - orchestrator.mutex.Unlock() - } - err := orchestrator.DeleteVolume(ctx(), d.name) - if err == nil && !d.expectedSuccess { - t.Errorf("%s: volume delete succeeded when it should not have.", d.name) - } else if err != nil && d.expectedSuccess { - t.Errorf("%s: delete failed: %v", d.name, err) - } else if d.expectedSuccess { - volume, err := orchestrator.GetVolume(ctx(), d.name) - if volume != nil || err == nil { - t.Errorf("%s: got volume where none expected.", d.name) - } - orchestrator.mutex.Lock() - if _, found = backend.Volumes()[d.name]; found { - t.Errorf("Volume %s shouldn't exist on backend %s!", d.name, backendUUID) - } - externalVol, err := orchestrator.storeClient.GetVolume(ctx(), d.name) - if err != nil { - if !persistentstore.MatchKeyNotFoundErr(err) { - t.Errorf( - "%s: unable to communicate with backing store: "+ - "%v", d.name, err, - ) - } - // We're successful if we get to here; we expect an - // ErrorCodeKeyNotFound. - } else if externalVol != nil { - t.Errorf("%s: volume not properly deleted from backing store", d.name) - } - orchestrator.mutex.Unlock() - } -} - -type storageClassTest struct { - config *storageclass.Config - expected []*tu.PoolMatch -} - -func getOrchestrator(t *testing.T) *TridentOrchestrator { - var ( - storeClient persistentstore.Client - err error - ) - // This will have been created as not nil in init - // We can't create a new one here because tests that exercise - // bootstrapping need to have their data persist. - storeClient = inMemoryClient - - o := NewTridentOrchestrator(storeClient) - if err = o.Bootstrap(); err != nil { - t.Fatal("Failure occurred during bootstrapping: ", err) - } - return o -} - -func validateStorageClass( - t *testing.T, - o *TridentOrchestrator, - name string, - expected []*tu.PoolMatch, -) { - o.mutex.Lock() - defer o.mutex.Unlock() - sc, ok := o.storageClasses[name] - if !ok { - t.Errorf("%s: Storage class not found in backend.", name) - } - remaining := make([]*tu.PoolMatch, len(expected)) - copy(remaining, expected) - for _, protocol := range []config.Protocol{config.File, config.Block, config.BlockOnFile} { - for _, pool := range sc.GetStoragePoolsForProtocol(ctx(), protocol, config.ReadWriteOnce) { - nameFound := false - for _, scName := range pool.StorageClasses() { - if scName == name { - nameFound = true - break - } - } - if !nameFound { - t.Errorf("%s: Storage class name not found in storage pool %s", name, pool.Name()) - } - matchIndex := -1 - for i, r := range remaining { - if r.Matches(pool) { - matchIndex = i - break - } - } - if matchIndex >= 0 { - // If we match, remove the match from the potential matches. - remaining[matchIndex] = remaining[len(remaining)-1] - remaining[len(remaining)-1] = nil - remaining = remaining[:len(remaining)-1] - } else { - t.Errorf("%s: Found unexpected match for storage class: %s:%s", name, pool.Backend().Name(), - pool.Name()) - } - } - } - if len(remaining) > 0 { - remainingNames := make([]string, len(remaining)) - for i, r := range remaining { - remainingNames[i] = r.String() - } - t.Errorf("%s: Storage class failed to match storage pools %s", name, strings.Join(remainingNames, ", ")) - } - persistentSC, err := o.storeClient.GetStorageClass(ctx(), name) - if err != nil { - t.Fatalf("Unable to get storage class %s from backend: %v", name, err) - } - if !reflect.DeepEqual( - persistentSC, - sc.ConstructPersistent(), - ) { - gotSCJSON, err := json.Marshal(persistentSC) - if err != nil { - t.Fatalf("Unable to marshal persisted storage class %s: %v", name, err) - } - expectedSCJSON, err := json.Marshal(sc.ConstructPersistent()) - if err != nil { - t.Fatalf("Unable to marshal expected persistent storage class %s: %v", name, err) - } - t.Errorf("%s: Storage class persisted incorrectly.\n\tExpected %s\n\tGot %s", name, expectedSCJSON, gotSCJSON) - } -} - -// This test is fairly heavyweight, but, due to the need to accumulate state -// to run the later tests, it's easier to do this all in one go at the moment. -// Consider breaking this up if it gets unwieldy, though. -func TestAddStorageClassVolumes(t *testing.T) { - mockPools := tu.GetFakePools() - orchestrator := getOrchestrator(t) - - errored := false - for _, c := range []struct { - name string - protocol config.Protocol - poolNames []string - }{ - { - name: "fast-a", - protocol: config.File, - poolNames: []string{tu.FastSmall, tu.FastThinOnly}, - }, - { - name: "fast-b", - protocol: config.File, - poolNames: []string{tu.FastThinOnly, tu.FastUniqueAttr}, - }, - { - name: "slow-file", - protocol: config.File, - poolNames: []string{tu.SlowNoSnapshots, tu.SlowSnapshots}, - }, - { - name: "slow-block", - protocol: config.Block, - poolNames: []string{tu.SlowNoSnapshots, tu.SlowSnapshots, tu.MediumOverlap}, - }, - } { - pools := make(map[string]*fake.StoragePool, len(c.poolNames)) - for _, poolName := range c.poolNames { - pools[poolName] = mockPools[poolName] - } - volumes := make([]fake.Volume, 0) - fakeConfig, err := fakedriver.NewFakeStorageDriverConfigJSON(c.name, c.protocol, pools, volumes) - if err != nil { - t.Fatalf("Unable to generate config JSON for %s: %v", c.name, err) - } - _, err = orchestrator.AddBackend(ctx(), fakeConfig, "") - if err != nil { - t.Errorf("Unable to add backend %s: %v", c.name, err) - errored = true - } - orchestrator.mutex.Lock() - backend, err := orchestrator.getBackendByBackendName(c.name) - if err != nil { - t.Fatalf("Backend %s not stored in orchestrator, err %s", c.name, err) - } - persistentBackend, err := orchestrator.storeClient.GetBackend(ctx(), c.name) - if err != nil { - t.Fatalf("Unable to get backend %s from persistent store: %v", c.name, err) - } else if !reflect.DeepEqual(backend.ConstructPersistent(ctx()), persistentBackend) { - t.Error("Wrong data stored for backend ", c.name) - } - orchestrator.mutex.Unlock() - } - if errored { - t.Fatal("Failed to add all backends; aborting remaining tests.") - } - - // Add storage classes - scTests := []storageClassTest{ - { - config: &storageclass.Config{ - Name: "slow", - Attributes: map[string]sa.Request{ - sa.IOPS: sa.NewIntRequest(40), - sa.Snapshots: sa.NewBoolRequest(true), - sa.ProvisioningType: sa.NewStringRequest("thin"), - }, - }, - expected: []*tu.PoolMatch{ - {Backend: "slow-file", Pool: tu.SlowSnapshots}, - {Backend: "slow-block", Pool: tu.SlowSnapshots}, - }, - }, - { - config: &storageclass.Config{ - Name: "fast", - Attributes: map[string]sa.Request{ - sa.IOPS: sa.NewIntRequest(2000), - sa.Snapshots: sa.NewBoolRequest(true), - sa.ProvisioningType: sa.NewStringRequest("thin"), - }, - }, - expected: []*tu.PoolMatch{ - {Backend: "fast-a", Pool: tu.FastSmall}, - {Backend: "fast-a", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastUniqueAttr}, - }, - }, - { - config: &storageclass.Config{ - Name: "fast-unique", - Attributes: map[string]sa.Request{ - sa.IOPS: sa.NewIntRequest(2000), - sa.Snapshots: sa.NewBoolRequest(true), - sa.ProvisioningType: sa.NewStringRequest("thin"), - sa.UniqueOptions: sa.NewStringRequest("baz"), - }, - }, - expected: []*tu.PoolMatch{ - {Backend: "fast-b", Pool: tu.FastUniqueAttr}, - }, - }, - { - config: &storageclass.Config{ - Name: "pools", - Pools: map[string][]string{ - "fast-a": {tu.FastSmall}, - "slow-block": {tu.SlowNoSnapshots, tu.MediumOverlap}, - }, - }, - expected: []*tu.PoolMatch{ - {Backend: "fast-a", Pool: tu.FastSmall}, - {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, - {Backend: "slow-block", Pool: tu.MediumOverlap}, - }, - }, - { - config: &storageclass.Config{ - Name: "additionalPools", - AdditionalPools: map[string][]string{ - "fast-a": {tu.FastThinOnly}, - "slow-block": {tu.SlowNoSnapshots, tu.MediumOverlap}, - }, - }, - expected: []*tu.PoolMatch{ - {Backend: "fast-a", Pool: tu.FastThinOnly}, - {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, - {Backend: "slow-block", Pool: tu.MediumOverlap}, - }, - }, - { - config: &storageclass.Config{ - Name: "poolsWithAttributes", - Attributes: map[string]sa.Request{ - sa.IOPS: sa.NewIntRequest(2000), - sa.Snapshots: sa.NewBoolRequest(true), - }, - Pools: map[string][]string{ - "fast-a": {tu.FastThinOnly}, - "slow-block": {tu.SlowNoSnapshots, tu.MediumOverlap}, - }, - }, - expected: []*tu.PoolMatch{ - {Backend: "fast-a", Pool: tu.FastThinOnly}, - }, - }, - { - config: &storageclass.Config{ - Name: "additionalPoolsWithAttributes", - Attributes: map[string]sa.Request{ - sa.IOPS: sa.NewIntRequest(2000), - sa.Snapshots: sa.NewBoolRequest(true), - }, - AdditionalPools: map[string][]string{ - "fast-a": {tu.FastThinOnly}, - "slow-block": {tu.SlowNoSnapshots}, - }, - }, - expected: []*tu.PoolMatch{ - {Backend: "fast-a", Pool: tu.FastSmall}, - {Backend: "fast-a", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastUniqueAttr}, - {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, - }, - }, - { - config: &storageclass.Config{ - Name: "additionalPoolsWithAttributesAndPools", - Attributes: map[string]sa.Request{ - sa.IOPS: sa.NewIntRequest(2000), - sa.Snapshots: sa.NewBoolRequest(true), - }, - Pools: map[string][]string{ - "fast-a": {tu.FastThinOnly}, - "slow-block": {tu.SlowNoSnapshots, tu.MediumOverlap}, - }, - AdditionalPools: map[string][]string{ - "fast-b": {tu.FastThinOnly}, - "slow-block": {tu.SlowNoSnapshots}, - }, - }, - expected: []*tu.PoolMatch{ - {Backend: "fast-a", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastThinOnly}, - {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, - }, - }, - { - config: &storageclass.Config{ - Name: "additionalPoolsNoMatch", - AdditionalPools: map[string][]string{ - "unknown": {tu.FastThinOnly}, - }, - }, - expected: []*tu.PoolMatch{}, - }, - { - config: &storageclass.Config{ - Name: "mixed", - AdditionalPools: map[string][]string{ - "slow-file": {tu.SlowNoSnapshots}, - "fast-b": {tu.FastThinOnly, tu.FastUniqueAttr}, - }, - Attributes: map[string]sa.Request{ - sa.IOPS: sa.NewIntRequest(2000), - sa.Snapshots: sa.NewBoolRequest(true), - sa.ProvisioningType: sa.NewStringRequest("thin"), - }, - }, - expected: []*tu.PoolMatch{ - {Backend: "fast-a", Pool: tu.FastSmall}, - {Backend: "fast-a", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastUniqueAttr}, - {Backend: "slow-file", Pool: tu.SlowNoSnapshots}, - }, - }, - { - config: &storageclass.Config{ - Name: "emptyStorageClass", - }, - expected: []*tu.PoolMatch{ - {Backend: "fast-a", Pool: tu.FastSmall}, - {Backend: "fast-a", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastUniqueAttr}, - {Backend: "slow-file", Pool: tu.SlowNoSnapshots}, - {Backend: "slow-file", Pool: tu.SlowSnapshots}, - {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, - {Backend: "slow-block", Pool: tu.SlowSnapshots}, - {Backend: "slow-block", Pool: tu.MediumOverlap}, - }, - }, - } - for _, s := range scTests { - _, err := orchestrator.AddStorageClass(ctx(), s.config) - if err != nil { - t.Errorf("Unable to add storage class %s: %v", s.config.Name, err) - continue - } - validateStorageClass(t, orchestrator, s.config.Name, s.expected) - } - preSCDeleteTests := make([]*deleteTest, 0) - postSCDeleteTests := make([]*deleteTest, 0) - for _, s := range []struct { - name string - config *storage.VolumeConfig - expectedSuccess bool - expectedMatches []*tu.PoolMatch - expectedCount int - deleteAfterSC bool - }{ - { - name: "basic", - config: tu.GenerateVolumeConfig("basic", 1, "fast", config.File), - expectedSuccess: true, - expectedMatches: []*tu.PoolMatch{ - {Backend: "fast-a", Pool: tu.FastSmall}, - {Backend: "fast-a", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastUniqueAttr}, - }, - expectedCount: 1, - deleteAfterSC: false, - }, - { - name: "large", - config: tu.GenerateVolumeConfig("large", 100, "fast", config.File), - expectedSuccess: false, - expectedMatches: []*tu.PoolMatch{}, - expectedCount: 0, - deleteAfterSC: false, - }, - { - name: "block", - config: tu.GenerateVolumeConfig("block", 1, "pools", config.Block), - expectedSuccess: true, - expectedMatches: []*tu.PoolMatch{ - {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, - {Backend: "slow-block", Pool: tu.MediumOverlap}, - }, - expectedCount: 1, - deleteAfterSC: false, - }, - { - name: "block2", - config: tu.GenerateVolumeConfig("block2", 1, "additionalPools", config.Block), - expectedSuccess: true, - expectedMatches: []*tu.PoolMatch{ - {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, - {Backend: "slow-block", Pool: tu.MediumOverlap}, - }, - expectedCount: 1, - deleteAfterSC: false, - }, - { - name: "invalid-storage-class", - config: tu.GenerateVolumeConfig("invalid", 1, "nonexistent", config.File), - expectedSuccess: false, - expectedMatches: []*tu.PoolMatch{}, - expectedCount: 0, - deleteAfterSC: false, - }, - { - name: "repeated", - config: tu.GenerateVolumeConfig("basic", 20, "fast", config.File), - expectedSuccess: false, - expectedMatches: []*tu.PoolMatch{}, - expectedCount: 1, - deleteAfterSC: false, - }, - { - name: "postSCDelete", - config: tu.GenerateVolumeConfig("postSCDelete", 20, "fast", config.File), - expectedSuccess: true, - expectedMatches: []*tu.PoolMatch{ - {Backend: "fast-a", Pool: tu.FastSmall}, - {Backend: "fast-a", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastUniqueAttr}, - }, - expectedCount: 1, - deleteAfterSC: false, - }, - } { - vol, err := orchestrator.AddVolume(ctx(), s.config) - if err != nil && s.expectedSuccess { - t.Errorf("%s: got unexpected error %v", s.name, err) - continue - } else if err == nil && !s.expectedSuccess { - t.Errorf("%s: volume create succeeded unexpectedly.", s.name) - continue - } - orchestrator.mutex.Lock() - volume, found := orchestrator.volumes[s.config.Name] - if s.expectedCount == 1 && !found { - t.Errorf("%s: did not get volume where expected.", s.name) - } else if s.expectedCount == 0 && found { - t.Errorf("%s: got a volume where none expected.", s.name) - } - if !s.expectedSuccess { - deleteTest := &deleteTest{ - name: s.config.Name, - expectedSuccess: false, - } - if s.deleteAfterSC { - postSCDeleteTests = append(postSCDeleteTests, deleteTest) - } else { - preSCDeleteTests = append(preSCDeleteTests, deleteTest) - } - orchestrator.mutex.Unlock() - continue - } - matched := false - for _, potentialMatch := range s.expectedMatches { - volumeBackend, err := orchestrator.getBackendByBackendUUID(volume.BackendUUID) - if volumeBackend == nil || err != nil { - continue - } - if potentialMatch.Backend == volumeBackend.Name() && - potentialMatch.Pool == volume.Pool { - matched = true - deleteTest := &deleteTest{ - name: s.config.Name, - expectedSuccess: true, - } - if s.deleteAfterSC { - postSCDeleteTests = append(postSCDeleteTests, deleteTest) - } else { - preSCDeleteTests = append(preSCDeleteTests, deleteTest) - } - break - } - } - if !matched { - t.Errorf( - "%s: Volume placed on unexpected backend and storage pool: %s, %s", - s.name, - volume.BackendUUID, - volume.Pool, - ) - } - - externalVolume, err := orchestrator.storeClient.GetVolume(ctx(), s.config.Name) - if err != nil { - t.Errorf("%s: unable to communicate with backing store: %v", s.name, err) - } - if !reflect.DeepEqual(externalVolume, vol) { - t.Errorf("%s: external volume %s stored in backend does not match created volume.", s.name, - externalVolume.Config.Name) - externalVolJSON, err := json.Marshal(externalVolume) - if err != nil { - t.Fatal("Unable to remarshal JSON: ", err) - } - origVolJSON, err := json.Marshal(vol) - if err != nil { - t.Fatal("Unable to remarshal JSON: ", err) - } - t.Logf("\tExpected: %s\n\tGot: %s\n", string(externalVolJSON), string(origVolJSON)) - } - orchestrator.mutex.Unlock() - } - for _, d := range preSCDeleteTests { - runDeleteTest(t, d, orchestrator) - } - - // Delete storage classes. Note: there are currently no error cases. - for _, s := range scTests { - err := orchestrator.DeleteStorageClass(ctx(), s.config.Name) - if err != nil { - t.Errorf("%s delete: Unable to remove storage class: %v", s.config.Name, err) - } - orchestrator.mutex.Lock() - if _, ok := orchestrator.storageClasses[s.config.Name]; ok { - t.Errorf("%s delete: Storage class still found in map.", s.config.Name) - } - // Ensure that the storage class was cleared from its backends. - for _, poolMatch := range s.expected { - b, err := orchestrator.getBackendByBackendName(poolMatch.Backend) - if b == nil || err != nil { - t.Errorf("%s delete: backend %s not found in orchestrator.", s.config.Name, poolMatch.Backend) - continue - } - p, ok := b.Storage()[poolMatch.Pool] - if !ok { - t.Errorf("%s delete: storage pool %s not found for backend %s", s.config.Name, poolMatch.Pool, - poolMatch.Backend) - continue - } - for _, sc := range p.StorageClasses() { - if sc == s.config.Name { - t.Errorf("%s delete: storage class name not removed from backend %s, storage pool %s", - s.config.Name, poolMatch.Backend, poolMatch.Pool) - } - } - } - externalSC, err := orchestrator.storeClient.GetStorageClass(ctx(), s.config.Name) - if err != nil { - if !persistentstore.MatchKeyNotFoundErr(err) { - t.Errorf("%s: unable to communicate with backing store: %v", s.config.Name, err) - } - // We're successful if we get to here; we expect an - // ErrorCodeKeyNotFound. - } else if externalSC != nil { - t.Errorf("%s: storageClass not properly deleted from backing store", s.config.Name) - } - orchestrator.mutex.Unlock() - } - for _, d := range postSCDeleteTests { - runDeleteTest(t, d, orchestrator) - } - cleanup(t, orchestrator) -} - -// This test is modeled after TestAddStorageClassVolumes, but we don't need all the -// tests around storage class deletion, etc. -func TestCloneVolumes(t *testing.T) { - mockPools := tu.GetFakePools() - orchestrator := getOrchestrator(t) - - errored := false - for _, c := range []struct { - name string - protocol config.Protocol - poolNames []string - }{ - { - name: "fast-a", - protocol: config.File, - poolNames: []string{tu.FastSmall, tu.FastThinOnly}, - }, - { - name: "fast-b", - protocol: config.File, - poolNames: []string{tu.FastThinOnly, tu.FastUniqueAttr}, - }, - { - name: "slow-file", - protocol: config.File, - poolNames: []string{tu.SlowNoSnapshots, tu.SlowSnapshots}, - }, - { - name: "slow-block", - protocol: config.Block, - poolNames: []string{tu.SlowNoSnapshots, tu.SlowSnapshots, tu.MediumOverlap}, - }, - } { - pools := make(map[string]*fake.StoragePool, len(c.poolNames)) - for _, poolName := range c.poolNames { - pools[poolName] = mockPools[poolName] - } - - volumes := make([]fake.Volume, 0) - cfg, err := fakedriver.NewFakeStorageDriverConfigJSON( - c.name, c.protocol, - pools, volumes, - ) - if err != nil { - t.Fatalf("Unable to generate cfg JSON for %s: %v", c.name, err) - } - _, err = orchestrator.AddBackend(ctx(), cfg, "") - if err != nil { - t.Errorf("Unable to add backend %s: %v", c.name, err) - errored = true - } - orchestrator.mutex.Lock() - backend, err := orchestrator.getBackendByBackendName(c.name) - if backend == nil || err != nil { - t.Fatalf("Backend %s not stored in orchestrator", c.name) - } - persistentBackend, err := orchestrator.storeClient.GetBackend(ctx(), c.name) - if err != nil { - t.Fatalf("Unable to get backend %s from persistent store: %v", c.name, err) - } else if !reflect.DeepEqual(backend.ConstructPersistent(ctx()), persistentBackend) { - t.Error("Wrong data stored for backend ", c.name) - } - orchestrator.mutex.Unlock() - } - if errored { - t.Fatal("Failed to add all backends; aborting remaining tests.") - } - - // Add storage classes - storageClasses := []storageClassTest{ - { - config: &storageclass.Config{ - Name: "slow", - Attributes: map[string]sa.Request{ - sa.IOPS: sa.NewIntRequest(40), - sa.Snapshots: sa.NewBoolRequest(true), - sa.ProvisioningType: sa.NewStringRequest("thin"), - }, - }, - expected: []*tu.PoolMatch{ - {Backend: "slow-file", Pool: tu.SlowSnapshots}, - {Backend: "slow-block", Pool: tu.SlowSnapshots}, - }, - }, - { - config: &storageclass.Config{ - Name: "fast", - Attributes: map[string]sa.Request{ - sa.IOPS: sa.NewIntRequest(2000), - sa.Snapshots: sa.NewBoolRequest(true), - sa.ProvisioningType: sa.NewStringRequest("thin"), - }, - }, - expected: []*tu.PoolMatch{ - {Backend: "fast-a", Pool: tu.FastSmall}, - {Backend: "fast-a", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastUniqueAttr}, - }, - }, - { - config: &storageclass.Config{ - Name: "fast-unique", - Attributes: map[string]sa.Request{ - sa.IOPS: sa.NewIntRequest(2000), - sa.Snapshots: sa.NewBoolRequest(true), - sa.ProvisioningType: sa.NewStringRequest("thin"), - sa.UniqueOptions: sa.NewStringRequest("baz"), - }, - }, - expected: []*tu.PoolMatch{ - {Backend: "fast-b", Pool: tu.FastUniqueAttr}, - }, - }, - { - config: &storageclass.Config{ - Name: "specific", - AdditionalPools: map[string][]string{ - "fast-a": {tu.FastThinOnly}, - "slow-block": {tu.SlowNoSnapshots, tu.MediumOverlap}, - }, - }, - expected: []*tu.PoolMatch{ - {Backend: "fast-a", Pool: tu.FastThinOnly}, - {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, - {Backend: "slow-block", Pool: tu.MediumOverlap}, - }, - }, - { - config: &storageclass.Config{ - Name: "specificNoMatch", - AdditionalPools: map[string][]string{ - "unknown": {tu.FastThinOnly}, - }, - }, - expected: []*tu.PoolMatch{}, - }, - { - config: &storageclass.Config{ - Name: "mixed", - AdditionalPools: map[string][]string{ - "slow-file": {tu.SlowNoSnapshots}, - "fast-b": {tu.FastThinOnly, tu.FastUniqueAttr}, - }, - Attributes: map[string]sa.Request{ - sa.IOPS: sa.NewIntRequest(2000), - sa.Snapshots: sa.NewBoolRequest(true), - sa.ProvisioningType: sa.NewStringRequest("thin"), - }, - }, - expected: []*tu.PoolMatch{ - {Backend: "fast-a", Pool: tu.FastSmall}, - {Backend: "fast-a", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastUniqueAttr}, - {Backend: "slow-file", Pool: tu.SlowNoSnapshots}, - }, - }, - { - config: &storageclass.Config{ - Name: "emptyStorageClass", - }, - expected: []*tu.PoolMatch{ - {Backend: "fast-a", Pool: tu.FastSmall}, - {Backend: "fast-a", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastUniqueAttr}, - {Backend: "slow-file", Pool: tu.SlowNoSnapshots}, - {Backend: "slow-file", Pool: tu.SlowSnapshots}, - {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, - {Backend: "slow-block", Pool: tu.SlowSnapshots}, - {Backend: "slow-block", Pool: tu.MediumOverlap}, - }, - }, - } - for _, s := range storageClasses { - _, err := orchestrator.AddStorageClass(ctx(), s.config) - if err != nil { - t.Errorf("Unable to add storage class %s: %v", s.config.Name, err) - continue - } - validateStorageClass(t, orchestrator, s.config.Name, s.expected) - } - - for _, s := range []struct { - name string - config *storage.VolumeConfig - expectedSuccess bool - expectedMatches []*tu.PoolMatch - }{ - { - name: "file", - config: tu.GenerateVolumeConfig("file", 1, "fast", config.File), - expectedSuccess: true, - expectedMatches: []*tu.PoolMatch{ - {Backend: "fast-a", Pool: tu.FastSmall}, - {Backend: "fast-a", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastThinOnly}, - {Backend: "fast-b", Pool: tu.FastUniqueAttr}, - }, - }, - { - name: "block", - config: tu.GenerateVolumeConfig("block", 1, "specific", config.Block), - expectedSuccess: true, - expectedMatches: []*tu.PoolMatch{ - {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, - {Backend: "slow-block", Pool: tu.MediumOverlap}, - }, - }, - } { - // Create the source volume - _, err := orchestrator.AddVolume(ctx(), s.config) - if err != nil { - t.Errorf("%s: got unexpected error %v", s.name, err) - continue + } + gotJSON, err := json.Marshal(gotVC) + if err != nil { + t.Fatal("Unable to marshal got JSON for VC ", name) + } + diffs = append( + diffs, fmt.Sprintf( + "Storage: pool %s differs:\n\t\t"+ + "Expected: %s\n\t\tGot: %s", name, string(expectedJSON), string(gotJSON), + ), + ) + } + } + for name := range got.Storage { + if _, ok := expected.Storage[name]; !ok { + diffs = append(diffs, fmt.Sprintf("Storage: got unexpected VC %s", name)) } + } - // Now clone the volume and ensure everything looks fine - cloneName := s.config.Name + "_clone" - cloneConfig := &storage.VolumeConfig{ - Name: cloneName, - StorageClass: s.config.StorageClass, - CloneSourceVolume: s.config.Name, - VolumeMode: s.config.VolumeMode, + // Diff volumes + expectedVolMap := make(map[string]bool, len(expected.Volumes)) + gotVolMap := make(map[string]bool, len(got.Volumes)) + for _, v := range expected.Volumes { + expectedVolMap[v] = true + } + for _, v := range got.Volumes { + gotVolMap[v] = true + } + for name := range expectedVolMap { + if _, ok := gotVolMap[name]; !ok { + diffs = append(diffs, fmt.Sprintf("Volumes: did not get expected volume %s", name)) } - cloneResult, err := orchestrator.CloneVolume(ctx(), cloneConfig) - if err != nil { - t.Errorf("%s: got unexpected error %v", s.name, err) - continue + } + for name := range gotVolMap { + if _, ok := expectedVolMap[name]; !ok { + diffs = append(diffs, fmt.Sprintf("Volumes: got unexpected volume %s", name)) } + } + if len(diffs) > 0 { + t.Errorf("External backends differ:\n\t%s", strings.Join(diffs, "\n\t")) + } +} +// runDeleteTest runs a delete test. +// Parameters: +// t: the test object +// d: the delete test to run +// orchestrator: the orchestrator to use +// Example: +// d := &deleteTest{name: "test1", expectedSuccess: true} +// runDeleteTest(t, d, orchestrator) + +func runDeleteTest( + t *testing.T, d *deleteTest, orchestrator *TridentOrchestrator, +) { + var ( + backendUUID string + backend storage.Backend + found bool + ) + if d.expectedSuccess { orchestrator.mutex.Lock() - volume, found := orchestrator.volumes[s.config.Name] + backendUUID = orchestrator.volumes[d.name].BackendUUID + backend, found = orchestrator.backends[backendUUID] if !found { - t.Errorf("%s: did not get volume where expected.", s.name) + t.Errorf("Backend %v isn't managed by the orchestrator!", backendUUID) } - clone, found := orchestrator.volumes[cloneName] - if !found { - t.Errorf("%s: did not get volume clone where expected.", cloneName) + if _, found = backend.Volumes()[d.name]; !found { + t.Errorf("Volume %s doesn't exist on backend %s!", d.name, backendUUID) } - - // Clone must reside in the same place as the source - if clone.BackendUUID != volume.BackendUUID { - t.Errorf("%s: Clone placed on unexpected backend: %s", cloneName, clone.BackendUUID) + orchestrator.mutex.Unlock() + } + err := orchestrator.DeleteVolume(ctx(), d.name) + if err == nil && !d.expectedSuccess { + t.Errorf("%s: volume delete succeeded when it should not have.", d.name) + } else if err != nil && d.expectedSuccess { + t.Errorf("%s: delete failed: %v", d.name, err) + } else if d.expectedSuccess { + volume, err := orchestrator.GetVolume(ctx(), d.name) + if volume != nil || err == nil { + t.Errorf("%s: got volume where none expected.", d.name) } - - // Clone should be registered in the store just like any other volume - externalClone, err := orchestrator.storeClient.GetVolume(ctx(), cloneName) - if err != nil { - t.Errorf("%s: unable to communicate with backing store: %v", cloneName, err) + orchestrator.mutex.Lock() + if _, found = backend.Volumes()[d.name]; found { + t.Errorf("Volume %s shouldn't exist on backend %s!", d.name, backendUUID) } - if !reflect.DeepEqual(externalClone, cloneResult) { - t.Errorf("%s: external volume %s stored in backend does not match created volume.", cloneName, - externalClone.Config.Name) - externalCloneJSON, err := json.Marshal(externalClone) - if err != nil { - t.Fatal("Unable to remarshal JSON: ", err) - } - origCloneJSON, err := json.Marshal(cloneResult) - if err != nil { - t.Fatal("Unable to remarshal JSON: ", err) + externalVol, err := orchestrator.storeClient.GetVolume(ctx(), d.name) + if err != nil { + if !persistentstore.MatchKeyNotFoundErr(err) { + t.Errorf( + "%s: unable to communicate with backing store: "+ + "%v", d.name, err, + ) } - t.Logf("\tExpected: %s\n\tGot: %s\n", string(externalCloneJSON), string(origCloneJSON)) + // We're successful if we get to here; we expect an + // ErrorCodeKeyNotFound. + } else if externalVol != nil { + t.Errorf("%s: volume not properly deleted from backing store", d.name) } - orchestrator.mutex.Unlock() } +} - cleanup(t, orchestrator) +type storageClassTest struct { + config *storageclass.Config + expected []*tu.PoolMatch +} + +// getOrchestrator returns an orchestrator with a bootstrapped backend +// and a single node. +// Parameters: +// t - the test object +// Returns: +// *TridentOrchestrator - the orchestrator +// Example: +// o := getOrchestrator(t) +// defer o.Terminate() + +func getOrchestrator(t *testing.T) *TridentOrchestrator { + var ( + storeClient persistentstore.Client + err error + ) + // This will have been created as not nil in init + // We can't create a new one here because tests that exercise + // bootstrapping need to have their data persist. + storeClient = inMemoryClient + + o := NewTridentOrchestrator(storeClient) + if err = o.Bootstrap(); err != nil { + t.Fatal("Failure occurred during bootstrapping: ", err) + } + return o +} + +// validateStorageClass checks that the storage class matches the expected pools. +// Parameters: +// t: The test object. +// o: The orchestrator. +// name: The name of the storage class. +// expected: A list of expected pool matches. +// Example: +// validateStorageClass(t, o, "sc1", []*tu.PoolMatch{ +// {BackendName: "be1", PoolName: "pool1"}, +// {BackendName: "be2", PoolName: "pool2"}, +// }) + +func validateStorageClass( + t *testing.T, + o *TridentOrchestrator, + name string, + expected []*tu.PoolMatch, +) { + o.mutex.Lock() + defer o.mutex.Unlock() + sc, ok := o.storageClasses[name] + if !ok { + t.Errorf("%s: Storage class not found in backend.", name) + } + remaining := make([]*tu.PoolMatch, len(expected)) + copy(remaining, expected) + for _, protocol := range []config.Protocol{config.File, config.Block, config.BlockOnFile} { + for _, pool := range sc.GetStoragePoolsForProtocol(ctx(), protocol, config.ReadWriteOnce) { + nameFound := false + for _, scName := range pool.StorageClasses() { + if scName == name { + nameFound = true + break + } + } + if !nameFound { + t.Errorf("%s: Storage class name not found in storage pool %s", name, pool.Name()) + } + matchIndex := -1 + for i, r := range remaining { + if r.Matches(pool) { + matchIndex = i + break + } + } + if matchIndex >= 0 { + // If we match, remove the match from the potential matches. + remaining[matchIndex] = remaining[len(remaining)-1] + remaining[len(remaining)-1] = nil + remaining = remaining[:len(remaining)-1] + } else { + t.Errorf("%s: Found unexpected match for storage class: %s:%s", name, pool.Backend().Name(), + pool.Name()) + } + } + } + if len(remaining) > 0 { + remainingNames := make([]string, len(remaining)) + for i, r := range remaining { + remainingNames[i] = r.String() + } + t.Errorf("%s: Storage class failed to match storage pools %s", name, strings.Join(remainingNames, ", ")) + } + persistentSC, err := o.storeClient.GetStorageClass(ctx(), name) + if err != nil { + t.Fatalf("Unable to get storage class %s from backend: %v", name, err) + } + if !reflect.DeepEqual( + persistentSC, + sc.ConstructPersistent(), + ) { + gotSCJSON, err := json.Marshal(persistentSC) + if err != nil { + t.Fatalf("Unable to marshal persisted storage class %s: %v", name, err) + } + expectedSCJSON, err := json.Marshal(sc.ConstructPersistent()) + if err != nil { + t.Fatalf("Unable to marshal expected persistent storage class %s: %v", name, err) + } + t.Errorf("%s: Storage class persisted incorrectly.\n\tExpected %s\n\tGot %s", name, expectedSCJSON, gotSCJSON) + } } +// This test is fairly heavyweight, but, due to the need to accumulate state +// to run the later tests, it's easier to do this all in one go at the moment. +// Consider breaking this up if it gets unwieldy, though. + +// This test is modeled after TestAddStorageClassVolumes, but we don't need all the +// tests around storage class deletion, etc. + +// addBackend adds a backend to the orchestrator. +// Parameters: +// t: the test object +// orchestrator: the orchestrator to add the backend to +// backendName: the name of the backend to add +// backendProtocol: the protocol of the backend to add +// Example: +// addBackend(t, orchestrator, "fake", config.File) +// addBackend(t, orchestrator, "fake", config.Block) + func addBackend( t *testing.T, orchestrator *TridentOrchestrator, backendName string, backendProtocol config.Protocol, ) { @@ -1152,6 +489,17 @@ func addBackendStorageClass( } } +// captureOutput captures the output of the log package. +// It returns the captured output as a string. +// Parameters: +// f: function to execute +// It returns the captured output as a string. +// Example: +// output := captureOutput(func() { +// log.Println("Hello, world") +// }) +// fmt.Println(output) + func captureOutput(f func()) string { var buf bytes.Buffer log.SetOutput(&buf) @@ -1160,6 +508,44 @@ func captureOutput(f func()) string { return buf.String() } +// TestBackendUpdateAndDelete tests the update and delete functionality of the +// orchestrator. +// It checks that the orchestrator can update a backend with a non-conflicting +// change, and that the backend is correctly updated in the orchestrator and +// persistent store. +// It also checks that the orchestrator can offline a backend, and that the +// backend is correctly offlined in the orchestrator and persistent store. +// Parameters: +// - New pool: Add a new storage pool to the backend. +// - Removed pool: Remove a storage pool from the backend. +// - Expanded offer: Expand the offer of an existing storage pool. +// Example: +// - New pool: +// - Starting state: +// - Backend: +// - Storage pools: "primary" +// - Updated state: +// - Backend: +// - Storage pools: "primary", "secondary" +// - Removed pool: +// - Starting state: +// - Backend: +// - Storage pools: "primary", "secondary" +// - Updated state: +// - Backend: +// - Storage pools: "primary" +// - Expanded offer: +// - Starting state: +// - Backend: +// - Storage pools: "primary" +// - Storage pool "primary": +// - Offer: "hdd" +// - Updated state: +// - Backend: +// - Storage pools: "primary" +// - Storage pool "primary": +// - Offer: "hdd", "ssd" + func TestBackendUpdateAndDelete(t *testing.T) { const ( backendName = "updateBackend" @@ -1471,6 +857,16 @@ func TestBackendUpdateAndDelete(t *testing.T) { cleanup(t, orchestrator) } +// backendPasswordsInLogsHelper is a helper function for backendPasswordsInLogs +// and backendPasswordsInLogsWithDebugTraceFlags tests. +// Parameters: +// t: test object +// debugTraceFlags: map of debug trace flags +// Example: +// backendPasswordsInLogsHelper(t, map[string]bool{ +// "orchestrator": true, +// }) + func backendPasswordsInLogsHelper(t *testing.T, debugTraceFlags map[string]bool) { backendName := "passwordBackend" @@ -1518,11 +914,30 @@ func backendPasswordsInLogsHelper(t *testing.T, debugTraceFlags map[string]bool) cleanup(t, orchestrator) } +// TestBackendPasswordsInLogs tests that backend passwords are not logged +// when the "method" field is present in the config. +// It checks that backend passwords are logged when the "method" field is not present. +// Parameters: +// t: testing.T +// config: map[string]bool +// "method": true if the "method" field is present in the config +// Example: +// backendPasswordsInLogsHelper(t, map[string]bool{"method": true}) + func TestBackendPasswordsInLogs(t *testing.T) { backendPasswordsInLogsHelper(t, nil) backendPasswordsInLogsHelper(t, map[string]bool{"method": true}) } +// TestEmptyBackendDeletion tests that an empty backend can be deleted. +// It checks that the backend is removed from the orchestrator and the +// store client. +// Parameters: +// backendName: The name of the backend to be deleted. +// backendProtocol: The protocol of the backend to be deleted. +// Example: +// TestEmptyBackendDeletion(t, "emptyBackend", config.File) + func TestEmptyBackendDeletion(t *testing.T) { const ( backendName = "emptyBackend" @@ -1558,6 +973,17 @@ func TestEmptyBackendDeletion(t *testing.T) { cleanup(t, orchestrator) } +// TestBootstrapSnapshotMissingVolume tests that a snapshot in missing_volume state is bootstrapped correctly. +// It checks that the snapshot is in the correct state and that it can be deleted. +// Parameters: +// offlineBackendName: Name of the backend to use for the test +// scName: Name of the storage class to use for the test +// volumeName: Name of the volume to use for the test +// snapName: Name of the snapshot to use for the test +// backendProtocol: Protocol of the backend to use for the test +// Example: +// TestBootstrapSnapshotMissingVolume(t, "snapNoVolBackend", "snapNoVolSC", "snapNoVolVolume", "snapNoVolSnapshot", config.File) + func TestBootstrapSnapshotMissingVolume(t *testing.T) { const ( offlineBackendName = "snapNoVolBackend" @@ -1616,6 +1042,16 @@ func TestBootstrapSnapshotMissingVolume(t *testing.T) { } } +// TestBootstrapSnapshotMissingBackend tests that a snapshot in missing_backend state is bootstrapped correctly. +// It checks that the snapshot is bootstrapped and that it is in the correct state. +// Parameters: +// offlineBackendName - name of the backend that will be deleted +// scName - name of the storage class +// volumeName - name of the volume +// snapName - name of the snapshot +// Example: +// TestBootstrapSnapshotMissingBackend(t, "snapNoBackBackend", "snapNoBackSC", "snapNoBackVolume", "snapNoBackSnapshot") + func TestBootstrapSnapshotMissingBackend(t *testing.T) { const ( offlineBackendName = "snapNoBackBackend" @@ -1674,6 +1110,15 @@ func TestBootstrapSnapshotMissingBackend(t *testing.T) { } } +// TestBootstrapVolumeMissingBackend tests that a volume in missing_backend state is bootstrapped correctly +// It checks that the volume is in the correct state and can be deleted +// Parameters: +// offlineBackendName - name of the backend to be deleted +// scName - name of the storage class to be created +// volumeName - name of the volume to be created +// Example: +// TestBootstrapVolumeMissingBackend("bootstrapVolBackend", "bootstrapVolSC", "bootstrapVolVolume") + func TestBootstrapVolumeMissingBackend(t *testing.T) { const ( offlineBackendName = "bootstrapVolBackend" @@ -1726,6 +1171,17 @@ func TestBootstrapVolumeMissingBackend(t *testing.T) { } } +// TestBackendCleanup tests that empty offline backends are cleaned up during bootstrap. +// It checks that empty online backends are not cleaned up during bootstrap. +// Parameters: +// offlineBackendName: Name of the backend to be offlined. +// onlineBackendName: Name of the backend to be left online. +// scName: Name of the storage class to be used. +// volumeName: Name of the volume to be created. +// backendProtocol: Protocol of the backends to be created. +// Example: +// TestBackendCleanup(t, "cleanupBackend", "onlineBackend", "cleanupBackendTest", "cleanupVolume", config.File) + func TestBackendCleanup(t *testing.T) { const ( offlineBackendName = "cleanupBackend" @@ -1776,6 +1232,13 @@ func TestBackendCleanup(t *testing.T) { } } +// TestLoadBackend tests that a backend can be loaded from a config and that it matches the original. +// It checks that the backend is also loaded after bootstrapping. +// Parameters: +// t *testing.T +// Example: +// TestLoadBackend(t) + func TestLoadBackend(t *testing.T) { const ( backendName = "load-backend-test" @@ -1828,6 +1291,15 @@ func TestLoadBackend(t *testing.T) { cleanup(t, orchestrator) } +// prepRecoveryTest sets up a backend and storage class for testing recovery +// Parameters: +// t: test object +// orchestrator: orchestrator object +// backendName: name of backend to create +// scName: name of storage class to create +// Example: +// prepRecoveryTest(t, orchestrator, "ontap-nas-test", "ontap-nas-sc") + func prepRecoveryTest( t *testing.T, orchestrator *TridentOrchestrator, backendName, scName string, ) { @@ -1865,6 +1337,29 @@ func prepRecoveryTest( } } +// runRecoveryTests runs a set of tests to verify that the orchestrator +// recovers from a partially completed volume addition. +// Parameters: +// t: Test object +// orchestrator: The orchestrator to test +// backendName: The name of the backend to use +// op: The operation to test +// testCases: The set of test cases to run +// Example: +// runRecoveryTests(t, orchestrator, "fake", storage.AddVolume, +// []recoveryTest{ +// { +// "volumeConfig", +// &storage.VolumeConfig{ +// Name: "test", +// Size: "10GiB", +// Attributes: map[string]sa.Request{}, +// }, +// true, +// }, +// ... +// }) + func runRecoveryTests( t *testing.T, orchestrator *TridentOrchestrator, @@ -1921,6 +1416,18 @@ func runRecoveryTests( } } +// TestAddVolumeRecovery tests that adding a volume is properly recovered +// after a crash. +// It checks that the volume is properly destroyed if the transaction was +// not committed, and that the volume is properly created if the transaction +// was committed. +// Parameters: +// - full: the volume was created and the transaction was committed +// - txOnly: the volume was not created and the transaction was not committed +// Example: +// - TestAddVolumeRecovery(full) +// - TestAddVolumeRecovery(txOnly) + func TestAddVolumeRecovery(t *testing.T) { const ( backendName = "addRecoveryBackend" @@ -1949,6 +1456,16 @@ func TestAddVolumeRecovery(t *testing.T) { cleanup(t, orchestrator) } +// TestAddVolumeWithTMRNonONTAPNAS tests that a volume with a relationship +// annotation that is not ONTAP NAS is rejected +// It checks that the volume is rejected +// Parameters: +// backendName: name of the backend +// scName: name of the storage class +// fullVolumeName: name of the full volume +// Example: +// TestAddVolumeWithTMRNonONTAPNAS("be1", "sc1", "vol1") + func TestAddVolumeWithTMRNonONTAPNAS(t *testing.T) { // Add a single backend of fake // create volume with relationship annotation added @@ -1975,6 +1492,16 @@ func TestAddVolumeWithTMRNonONTAPNAS(t *testing.T) { cleanup(t, orchestrator) } +// TestDeleteVolumeRecovery tests the recovery of a volume delete operation. +// It checks that a volume that was deleted but not fully committed is +// recovered, and that a volume that was only created in the transaction +// is cleaned up. +// Parameters: +// backendName: The name of the backend to use for the test. +// scName: The name of the storage class to use for the test. +// Example: +// TestDeleteVolumeRecovery(t, "ontap-san", "ontap-san-sc") + func TestDeleteVolumeRecovery(t *testing.T) { const ( backendName = "deleteRecoveryBackend" @@ -2010,6 +1537,17 @@ func TestDeleteVolumeRecovery(t *testing.T) { cleanup(t, orchestrator) } +// generateSnapshotConfig generates a SnapshotConfig object +// Parameters: +// name - the name of the snapshot +// volumeName - the name of the volume +// volumeInternalName - the internal name of the volume +// Returns: +// a SnapshotConfig object +// It returns an error if the volume name is not set +// Example: +// config := generateSnapshotConfig("snap1", "vol1", "pvc-xxx-xx-xx") + func generateSnapshotConfig( name, volumeName, volumeInternalName string, ) *storage.SnapshotConfig { @@ -2021,6 +1559,43 @@ func generateSnapshotConfig( } } +// runSnapshotRecoveryTests runs a set of recovery tests. +// Parameters: +// t: the test object +// orchestrator: the orchestrator to use for the tests +// backendName: the name of the backend to use for the tests +// op: the operation to test +// testCases: the set of test cases to run +// Example: +// runSnapshotRecoveryTests( +// t, +// orchestrator, +// "ontap-nas", +// storage.AddSnapshot, +// []recoveryTest{ +// { +// name: "VolumePresent", +// volumeConfig: &storage.VolumeConfig{ +// Version: tridentconfig.OrchestratorAPIVersion, +// Name: "myvol", +// BackendUUID: "ontap-nas-0", +// Backend: "ontap-nas", +// Size: "1GiB", +// InternalName: "myvol", +// Attributes: map[string]sa.Request{}, +// }, +// snapshotConfig: &storage.SnapshotConfig{ +// Version: tridentconfig.OrchestratorAPIVersion, +// Name: "mysnap", +// VolumeName: "myvol", +// VolumeInternalName: "myvol", +// Attributes: map[string]sa.Request{}, +// }, +// expectDestroy: true, +// }, +// }, +// ) + func runSnapshotRecoveryTests( t *testing.T, orchestrator *TridentOrchestrator, @@ -2081,6 +1656,19 @@ func runSnapshotRecoveryTests( } } +// TestAddSnapshotRecovery tests that the orchestrator can recover from a failure +// during the AddSnapshot transaction. +// It checks that the snapshot is deleted if the transaction is complete, and that +// it is not deleted if the transaction is not complete. +// Parameters: +// backendName: Name of the backend to use for the test +// scName: Name of the storage class to use for the test +// volumeName: Name of the volume to use for the test +// fullSnapshotName: Name of the snapshot to use for the full test +// txOnlySnapshotName: Name of the snapshot to use for the partial test +// Example: +// TestAddSnapshotRecovery(t, "addSnapshotRecoveryBackend", "addSnapshotRecoveryBackendSC", "addSnapshotRecoveryVolume", "addSnapshotRecoverySnapshotFull", "addSnapshotRecoverySnapshotTxOnly") + func TestAddSnapshotRecovery(t *testing.T) { const ( backendName = "addSnapshotRecoveryBackend" @@ -2120,6 +1708,17 @@ func TestAddSnapshotRecovery(t *testing.T) { cleanup(t, orchestrator) } +// TestDeleteSnapshotRecovery tests that the orchestrator can recover from a delete snapshot +// transaction. +// It checks that the snapshot is deleted if the transaction was fully committed, and that +// the snapshot is not deleted if the transaction was only partially committed. +// Parameters: +// - full: the transaction was fully committed, so the snapshot should be deleted +// - txOnly: the transaction was only partially committed, so the snapshot should not be deleted +// Example: +// - TestDeleteSnapshotRecovery full +// - TestDeleteSnapshotRecovery txOnly + func TestDeleteSnapshotRecovery(t *testing.T) { const ( backendName = "deleteSnapshotRecoveryBackend" @@ -2166,6 +1765,14 @@ func TestDeleteSnapshotRecovery(t *testing.T) { // The next series of tests test that bootstrap doesn't exit early if it // encounters a key error for one of the main types of entries. +// TestStorageClassOnlyBootstrap tests that a storage class can be bootstrapped +// without any volumes. +// It checks that the storage class is bootstrapped correctly. +// Parameters: +// t *testing.T +// Example: +// TestStorageClassOnlyBootstrap(t) + func TestStorageClassOnlyBootstrap(t *testing.T) { const scName = "storageclass-only" @@ -2193,6 +1800,16 @@ func TestStorageClassOnlyBootstrap(t *testing.T) { cleanup(t, orchestrator) } +// TestFirstVolumeRecovery tests that the first volume added to a backend is +// recovered correctly. +// It checks that the volume is destroyed, and that the backend is not. +// Parameters: +// backendName: name of the backend to be used +// scName: name of the storage class to be used +// txOnlyVolumeName: name of the volume to be created +// Example: +// TestFirstVolumeRecovery(t, "firstRecoveryBackend", "firstRecoveryBackendSC", "firstRecoveryVolumeTxOnly") + func TestFirstVolumeRecovery(t *testing.T) { const ( backendName = "firstRecoveryBackend" @@ -2214,6 +1831,14 @@ func TestFirstVolumeRecovery(t *testing.T) { cleanup(t, orchestrator) } +// TestOrchestratorNotReady tests that the orchestrator returns an error when not ready. +// It checks that all orchestrator methods return an error. +// Parameters: +// t *testing.T : go test helper +// It returns nothing. +// Example: +// TestOrchestratorNotReady(t *testing.T) + func TestOrchestratorNotReady(t *testing.T) { var ( @@ -2353,6 +1978,22 @@ func TestOrchestratorNotReady(t *testing.T) { } } +// importVolumeSetup creates a backend, storage class, and volume config for +// Parameters: +// t - test object +// backendName - name of the backend to create +// scName - name of the storage class to create +// volumeName - name of the volume to create +// importOriginalName - original name of the volume to import +// backendProtocol - protocol of the backend to create +// Returns: +// *TridentOrchestrator - orchestrator object +// *storage.VolumeConfig - volume config object +// It returns the orchestrator and volume config objects. +// Example: +// orchestrator, volumeConfig := importVolumeSetup(t, "testBackend", "testSC", +// "testVolume", "testVolumeOrig", config.File) + func importVolumeSetup( t *testing.T, backendName string, scName string, volumeName string, importOriginalName string, backendProtocol config.Protocol, @@ -2386,6 +2027,18 @@ func importVolumeSetup( return orchestrator, volumeConfig } +// TestImportVolumeFailures tests the failure paths of importVolume +// It checks that the volume is renamed to the original name and that the persisted state is cleaned up +// Parameters: +// volumeName: the name of the volume to import +// originalName: the original name of the volume +// backendProtocol: the protocol of the backend +// createPVandPVCError: function to inject an error into the PV/PVC creation +// It returns the orchestrator and the volumeConfig +// Example: +// orchestrator, volumeConfig := importVolumeSetup(t, "backend82", "sc01", "volume82", "origVolume01", config.File) +// _, err := orchestrator.LegacyImportVolume(ctx(), volumeConfig, "backend82", false, createPVandPVCError) + func TestImportVolumeFailures(t *testing.T) { const ( backendName = "backend82" @@ -2425,6 +2078,19 @@ func TestImportVolumeFailures(t *testing.T) { cleanup(t, orchestrator) } +// TestLegacyImportVolume tests the legacy +// It checks that the volume is imported with the correct internal name. +// It checks that the volume is persisted if it is managed. +// It checks that the volume is not persisted if it is not managed. +// Parameters: +// volumeConfig: the volume config to use for the import +// notManaged: true if the volume is not managed +// createFunc: the function to use to create the PV and PVC +// expectedInternalName: the expected internal name of the volume +// It returns the volumeExternal returned by the import. +// Example: +// TestLegacyImportVolume(t, volumeConfig, false, createPVandPVCNoOp, volumeConfig.InternalName) + func TestLegacyImportVolume(t *testing.T) { const ( backendName = "backend02" @@ -2502,6 +2168,18 @@ func TestLegacyImportVolume(t *testing.T) { cleanup(t, orchestrator) } +// TestImportVolume tests the +// It checks that the volume is imported with the correct internal name +// and that the volume is persisted in the orchestrator. +// Parameters: +// backendName: name of the backend +// scName: name of the storage class +// volumeName: name of the volume to be imported +// originalName: original name of the volume to be imported +// backendProtocol: protocol of the backend +// Example: +// TestImportVolume(t, "backend02", "sc01", "volume01", "origVolume01", config.File) + func TestImportVolume(t *testing.T) { const ( backendName = "backend02" @@ -2559,6 +2237,28 @@ func TestImportVolume(t *testing.T) { cleanup(t, orchestrator) } +// TestValidateImportVolumeNasBackend tests the validateImportVolume function for NAS backends. +// It checks for the following error conditions: +// - The volume exists on the backend with the original name +// - The storage class is unknown +// - The volume does not exist on the backend +// - The access mode is incompatible with the backend +// - The volume mode is incompatible with the backend +// - The protocol is incompatible with the backend +// Parameters: +// backendName - the name of the backend +// scName - the name of the storage class +// volumeName - the name of the volume to import +// originalName - the original name of the volume to import +// backendProtocol - the protocol of the backend +// Example: +// backendName := "backend01" +// scName := "sc01" +// volumeName := "volume01" +// originalName := "origVolume01" +// backendProtocol := config.File +// TestValidateImportVolumeNasBackend(t, backendName, scName, volumeName, originalName, backendProtocol) + func TestValidateImportVolumeNasBackend(t *testing.T) { const ( backendName = "backend01" @@ -2637,6 +2337,20 @@ func TestValidateImportVolumeNasBackend(t *testing.T) { cleanup(t, orchestrator) } +// TestValidateImportVolumeSanBackend tests the validateImportVolume function for +// SAN backends. +// It checks for the following error conditions: +// - protocol mismatch +// - file system mismatch +// Parameters: +// - backendName: name of the backend to use +// - scName: name of the storage class to use +// - volumeName: name of the volume to create +// - originalName: name of the volume to import +// - backendProtocol: protocol of the backend to use +// Example: +// TestValidateImportVolumeSanBackend("backend01", "sc01", "volume01", "origVolume01", config.Block) + func TestValidateImportVolumeSanBackend(t *testing.T) { const ( backendName = "backend01" @@ -2698,6 +2412,16 @@ func TestValidateImportVolumeSanBackend(t *testing.T) { cleanup(t, orchestrator) } +// TestAddVolumePublication tests that the orchestrator correctly adds a volume publication +// to its cache and calls the store client to add the volume publication to the persistent store +// It checks that the orchestrator's cache is updated correctly +// Parameters: +// t *testing.T - test object +// Example: +// TestAddVolumePublication(t) +// Returns: +// None + func TestAddVolumePublication(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2730,6 +2454,16 @@ func TestAddVolumePublication(t *testing.T) { "volume publication was not correctly added") } +// TestAddVolumePublicationError tests the error path for AddVolumePublication +// It checks that the orchestrator does not add the volume publication to its cache +// when the store client returns an error +// Parameters: +// t *testing.T +// The test object +// It returns nothing +// Example: +// TestAddVolumePublicationError(t) + func TestAddVolumePublicationError(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2758,6 +2492,13 @@ func TestAddVolumePublicationError(t *testing.T) { "volume publication was added orchestrator's cache") } +// TestGetVolumePublication tests the GetVolumePublication method +// It checks that the volume publication is correctly retrieved from the cache +// Parameters: +// t *testing.T: go test helper +// Example: +// TestGetVolumePublication(t *testing.T) + func TestGetVolumePublication(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2783,6 +2524,14 @@ func TestGetVolumePublication(t *testing.T) { assert.Equal(t, fakePub, actualPub, "volume publication was not correctly retrieved") } +// TestGetVolumePublicationNotFound tests that a volume publication is not found +// when the volume is not found +// It checks that the correct error is returned +// Parameters: +// t *testing.T +// Example: +// TestGetVolumePublicationNotFound(t) + func TestGetVolumePublicationNotFound(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2800,6 +2549,14 @@ func TestGetVolumePublicationNotFound(t *testing.T) { assert.Empty(t, actualPub, "non-empty publication returned") } +// TestGetVolumePublicationError tests the GetVolumePublication function when +// there is an error during bootstrap +// It checks that the correct error is returned +// Parameters: +// t *testing.T - go test helper object +// Example: +// TestGetVolumePublicationError(t *testing.T) + func TestGetVolumePublicationError(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2829,6 +2586,15 @@ func TestGetVolumePublicationError(t *testing.T) { assert.Empty(t, actualPub, "non-empty publication returned") } +// TestListVolumePublications tests the ListVolumePublications method +// It checks that the correct list of publications is returned +// Parameters: +// t *testing.T : go test framework object used for setup, teardown, etc. +// Example: +// TestListVolumePublications(t) +// Returns: +// None + func TestListVolumePublications(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2872,6 +2638,13 @@ func TestListVolumePublications(t *testing.T) { assert.ElementsMatch(t, expectedPubs, actualPubs, "incorrect publication list returned") } +// TestListVolumePublicationsNotFound tests that ListVolumePublications returns an empty list when no publications are found +// It checks that the orchestrator does not return an error when no publications are found +// Parameters: +// t *testing.T : go test framework object used to generate test failures +// Example: +// TestListVolumePublicationsNotFound(t *testing.T) + func TestListVolumePublicationsNotFound(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2888,6 +2661,13 @@ func TestListVolumePublicationsNotFound(t *testing.T) { assert.Empty(t, actualPubs, "non-empty publication list returned") } +// TestListVolumePublicationsError tests the error path for ListVolumePublications +// It checks that the error is returned and the publication list is empty +// Parameters: +// t *testing.T - go test handler +// Example: +// TestListVolumePublicationsError(t) + func TestListVolumePublicationsError(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2917,6 +2697,13 @@ func TestListVolumePublicationsError(t *testing.T) { assert.Empty(t, actualPubs, "non-empty publication list returned") } +// TestListVolumePublicationsForVolume tests the ListVolumePublicationsForVolume method +// It checks that the correct list of publications is returned for a given volume +// Parameters: +// t *testing.T - test object +// Example: +// TestListVolumePublicationsForVolume(t) + func TestListVolumePublicationsForVolume(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2960,6 +2747,18 @@ func TestListVolumePublicationsForVolume(t *testing.T) { assert.ElementsMatch(t, expectedPubs, actualPubs, "incorrect publication list returned") } +// TestListVolumePublicationsForVolumeNotFound tests that ListVolumePublicationsForVolume +// returns an empty list when the volume is not found +// It checks that the orchestrator does not return an error +// Parameters: +// t *testing.T : go test helper +// Example: +// TestListVolumePublicationsForVolumeNotFound(t) +// Returns: +// nothing +// Side Effects: +// none + func TestListVolumePublicationsForVolumeNotFound(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2986,6 +2785,13 @@ func TestListVolumePublicationsForVolumeNotFound(t *testing.T) { assert.Empty(t, actualPubs, "non-empty publication list returned") } +// TestListVolumePublicationsForVolumeError tests the error path for ListVolumePublicationsForVolume +// It checks that the error is returned if the orchestrator is in an error state +// Parameters: +// t *testing.T : go test helper +// Example: +// TestListVolumePublicationsForVolumeError(t *testing.T) + func TestListVolumePublicationsForVolumeError(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3015,6 +2821,13 @@ func TestListVolumePublicationsForVolumeError(t *testing.T) { assert.Empty(t, actualPubs, "non-empty publication list returned") } +// TestListVolumePublicationsForNode tests the ListVolumePublicationsForNode method +// It checks that a list of publications for a given node is returned +// Parameters: +// t *testing.T - go test object +// Example: +// TestListVolumePublicationsForNode(t *testing.T) + func TestListVolumePublicationsForNode(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3058,6 +2871,14 @@ func TestListVolumePublicationsForNode(t *testing.T) { assert.ElementsMatch(t, expectedPubs, actualPubs, "incorrect publication list returned") } +// TestListVolumePublicationsForNodeNotFound tests the ListVolumePublicationsForNode function +// when the node is not found +// It checks that an empty list is returned +// Parameters: +// t *testing.T +// Example: +// TestListVolumePublicationsForNodeNotFound(t) + func TestListVolumePublicationsForNodeNotFound(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3084,6 +2905,14 @@ func TestListVolumePublicationsForNodeNotFound(t *testing.T) { assert.Empty(t, actualPubs, "non-empty publication list returned") } +// TestListVolumePublicationsForNodeError tests that ListVolumePublicationsForNode +// returns an error when the orchestrator is in an error state +// It checks that the error is returned and that the publication list is empty +// Parameters: +// t *testing.T : go test helper object +// Example: +// TestListVolumePublicationsForNodeError(t) + func TestListVolumePublicationsForNodeError(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3113,6 +2942,14 @@ func TestListVolumePublicationsForNodeError(t *testing.T) { assert.Empty(t, actualPubs, "non-empty publication list returned") } +// TestDeleteVolumePublication tests the DeleteVolumePublication method +// It checks that the volume publication is removed from the cache +// and that the volume entry is removed from the cache if this is the last nodeID for a given volume +// Parameters: +// t *testing.T: go test helper +// Example: +// TestDeleteVolumePublication(t) + func TestDeleteVolumePublication(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3169,6 +3006,14 @@ func TestDeleteVolumePublication(t *testing.T) { "publication not properly removed from cache") } +// TestDeleteVolumePublicationNotFound tests that the DeleteVolumePublication method returns a not found error +// when the volume publication is not found +// It checks that the volume publication is not deleted from the cache +// Parameters: +// t *testing.T : go test helper +// Example: +// TestDeleteVolumePublicationNotFound(t *testing.T) + func TestDeleteVolumePublicationNotFound(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3195,6 +3040,14 @@ func TestDeleteVolumePublicationNotFound(t *testing.T) { assert.True(t, utils.IsNotFoundError(err), "incorrect error type returned") } +// TestDeleteVolumePublicationNotFoundPersistence tests that delete volume publication is idempotent +// when the persistence object is missing +// It checks that the cache is updated and that the orchestrator does not panic +// Parameters: +// t *testing.T : go test framework object +// Example: +// TestDeleteVolumePublicationNotFoundPersistence(t *testing.T) + func TestDeleteVolumePublicationNotFoundPersistence(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3224,6 +3077,13 @@ func TestDeleteVolumePublicationNotFoundPersistence(t *testing.T) { "publication not properly removed from cache") } +// TestDeleteVolumePublicationError tests the error path of DeleteVolumePublication +// It checks that the orchestrator returns an error when the store client returns an error +// Parameters: +// t *testing.T : go test helper +// Example: +// TestDeleteVolumePublicationError(t) + func TestDeleteVolumePublicationError(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3254,6 +3114,14 @@ func TestDeleteVolumePublicationError(t *testing.T) { "publication improperly removed/updated in cache") } +// TestAddNode tests adding a node to the orchestrator +// It checks that the node is added to the orchestrator and that the orchestrator +// is able to retrieve the node +// Parameters: +// t *testing.T : go test helper object for running tests +// Example: +// TestAddNode(t *testing.T) + func TestAddNode(t *testing.T) { node := &utils.Node{ Name: "testNode", @@ -3268,6 +3136,13 @@ func TestAddNode(t *testing.T) { } } +// TestGetNode tests the GetNode method +// It checks that the correct node is returned +// Parameters: +// t *testing.T +// Example: +// TestGetNode(t) + func TestGetNode(t *testing.T) { orchestrator := getOrchestrator(t) expectedNode := &utils.Node{ @@ -3299,6 +3174,13 @@ func TestGetNode(t *testing.T) { } } +// TestListNodes tests the ListNodes function +// It checks that the list of nodes returned is the same as the list of nodes in the orchestrator +// Parameters: +// t *testing.T : go test framework object used for running the test +// Example: +// TestListNodes(t) + func TestListNodes(t *testing.T) { orchestrator := getOrchestrator(t) expectedNode1 := &utils.Node{ @@ -3329,6 +3211,18 @@ func TestListNodes(t *testing.T) { } } +// unorderedNodeSlicesEqual returns true if the two slices contain the same nodes, +// regardless of order. +// Parameters: +// x, y - the slices to compare +// Returns: +// bool - true if the slices contain the same nodes, regardless of order +// Example: +// x := []*utils.Node{&utils.Node{Name: "node1"}, &utils.Node{Name: "node2"}} +// y := []*utils.Node{&utils.Node{Name: "node2"}, &utils.Node{Name: "node1"}} +// unorderedNodeSlicesEqual(x, y) +// >> true + func unorderedNodeSlicesEqual(x, y []*utils.Node) bool { if len(x) != len(y) { return false @@ -3352,6 +3246,13 @@ func unorderedNodeSlicesEqual(x, y []*utils.Node) bool { return len(diff) == 0 } +// TestDeleteNode tests the deletion of a node +// It checks that the node is properly deleted from the orchestrator +// Parameters: +// t *testing.T : go testing object used to handle logging +// Example: +// TestDeleteNode(t *testing.T) + func TestDeleteNode(t *testing.T) { orchestrator := getOrchestrator(t) initialNode := &utils.Node{ @@ -3373,6 +3274,14 @@ func TestDeleteNode(t *testing.T) { } } +// TestSnapshotVolumes tests snapshotting of volumes +// It checks that the snapshot is created, and that it is stored in the persistent store +// It also checks that the snapshot can be deleted +// Parameters: +// t: the test object +// Example: +// TestSnapshotVolumes(t) + func TestSnapshotVolumes(t *testing.T) { mockPools := tu.GetFakePools() orchestrator := getOrchestrator(t) @@ -3578,6 +3487,19 @@ func TestSnapshotVolumes(t *testing.T) { cleanup(t, orchestrator) } +// TestGetProtocol tests the getProtocol function +// It checks for positive and negative cases +// Parameters: +// volumeMode: Filesystem or RawBlock +// accessMode: ReadWriteOnce, ReadOnlyMany, ReadWriteMany +// protocol: File, Block, BlockOnFile +// expected: File, Block, BlockOnFile +// Example: +// volumeMode: RawBlock +// accessMode: ReadWriteOnce +// protocol: File +// expected: ProtocolAny + func TestGetProtocol(t *testing.T) { orchestrator := getOrchestrator(t) @@ -3647,6 +3569,14 @@ func TestGetProtocol(t *testing.T) { } } +// TestGetBackend tests the GetBackend function +// It checks that the expected object is returned +// Parameters: +// t *testing.T: The test object +// It returns nothing +// Example: +// TestGetBackend(t) + func TestGetBackend(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -3681,6 +3611,15 @@ func TestGetBackend(t *testing.T) { assert.Equal(t, expectedBackendExternal, actualBackendExternal, "Did not get the expected backend object") } +// TestGetBackendByBackendUUID tests the GetBackendByBackendUUID method +// It checks that the correct backend is returned +// Parameters: +// backendName: Name of the backend to return +// backendUUID: UUID of the backend to return +// It returns the expected backend object +// Example: +// backend:=TestGetBackendByBackendUUID("foobar","1234") + func TestGetBackendByBackendUUID(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -3711,6 +3650,14 @@ func TestGetBackendByBackendUUID(t *testing.T) { assert.Equal(t, expectedBackendExternal, actualBackendExternal, "Did not get the expected backend object") } +// TestListBackends tests the ListBackends function +// It checks that the function returns a list of backends that matches the list of backends that were added to the orchestrator +// Parameters: +// t *testing.T : go testing object used to control test flow +// It returns nothing +// Example: +// TestListBackends(t *testing.T) + func TestListBackends(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -3747,6 +3694,14 @@ func TestListBackends(t *testing.T) { assert.ElementsMatch(t, expectedBackendList, actualBackendList, "Did not get expected list of backends") } +// TestDeleteBackend tests the DeleteBackend method +// It checks that the backend is properly deleted from the orchestrator +// Parameters: +// t *testing.T - test object +// It returns nothing +// Example: +// TestDeleteBackend(t *testing.T) + func TestDeleteBackend(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -3791,6 +3746,13 @@ func TestDeleteBackend(t *testing.T) { assert.False(t, ok, "Backend was not properly deleted") } +// TestPublishVolume tests the PublishVolume method +// It checks that the correct backend method is called +// Parameters: +// t *testing.T +// Example: +// TestPublishVolume(t) + func TestPublishVolume(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -3822,6 +3784,18 @@ func TestPublishVolume(t *testing.T) { assert.Nilf(t, err, "Error publishing volume; %v", err) } +// TestPublishVolumeFailedToUpdatePersistentStore tests the case where the +// orchestrator fails to update the persistent store after a successful +// publish operation. +// It checks that the orchestrator returns the error from the persistent +// store client. +// Parameters: +// mockCtrl - the mocked controller +// backendUUID - the UUID of the backend to use for the test +// expectedError - the error expected from the persistent store client +// Example: +// TestPublishVolumeFailedToUpdatePersistentStore(t, "1234", fmt.Errorf("failure")) + func TestPublishVolumeFailedToUpdatePersistentStore(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -3857,6 +3831,15 @@ func TestPublishVolumeFailedToUpdatePersistentStore(t *testing.T) { } } +// TestGetCHAP tests the GetCHAP method of the orchestrator +// It checks that the orchestrator calls the correct backend method +// and returns the expected result +// Parameters: +// volumeName: the name of the volume to get CHAP info for +// nodeName: the name of the node to get CHAP info for +// Example: +// TestGetCHAP("foobar", "foobar") + func TestGetCHAP(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -3889,6 +3872,13 @@ func TestGetCHAP(t *testing.T) { assert.Equal(t, expectedChapInfo, actualChapInfo, "Unexpected chap info returned.") } +// TestGetCHAPFailure tests the failure path of GetCHAP +// It checks that the orchestrator returns an error when the backend returns an error +// Parameters: +// t *testing.T: go test helper +// Example: +// TestGetCHAPFailure(t *testing.T) + func TestGetCHAPFailure(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) diff --git a/core/transaction_monitor_test.go b/core/transaction_monitor_test.go index 469cb3818..f15452b47 100644 --- a/core/transaction_monitor_test.go +++ b/core/transaction_monitor_test.go @@ -24,10 +24,13 @@ const ( maxAge = 3 * time.Second ) -func init() { - testing.Init() - log.SetLevel(log.DebugLevel) -} + +// waitForTransactionMontitorToStart waits for the transaction monitor to start +// before proceeding with tests. +// Parameters: +// o - the orchestrator +// Example: +// waitForTransactionMontitorToStart(o) func waitForTransactionMontitorToStart(o *TridentOrchestrator) { if o.txnMonitorChannel == nil { @@ -35,6 +38,14 @@ func waitForTransactionMontitorToStart(o *TridentOrchestrator) { } } +// TestStartStop tests the start and stop of the transaction monitor +// It checks that the transaction monitor is started and stopped correctly +// It also checks that the transaction monitor channel is set correctly +// Parameters: +// t *testing.T : go test framework object used for running the test +// Example: +// TestStartStop(t) + func TestStartStop(t *testing.T) { storeClient := persistentstore.NewInMemoryClient() @@ -121,6 +132,15 @@ func TestCancelledLongRunningTransaction(t *testing.T) { } // TestUpdateTransactionVolumeCreatingTransaction tests that a VolumeCreatingTransaction can be updated. +// TestUpdateVolumeCreatingTransaction tests the ability to update a volume creating transaction +// in the store. +// It checks that the transaction is created, then updates the size and checks that the size +// was updated. +// Parameters: +// t *testing.T +// Example: +// TestUpdateVolumeCreatingTransaction(t) + func TestUpdateVolumeCreatingTransaction(t *testing.T) { o, storeClient := setupOrchestratorAndBackend(t) restartTransactionMonitor(o) @@ -194,6 +214,17 @@ func TestErrorVolumeCreatingTransaction(t *testing.T) { } // TestVolumeCreatingTwoTransaction tests that two volumeCreatingTransactions work as expected +// TestVolumeCreatingTwoTransactions tests that two volume creating transactions can be created +// and that the second one is not deleted until the first one is completed. +// It checks that the second transaction is not deleted when the first one is completed. +// Parameters: +// volName - name of the volume to create +// cloneName - name of the volume to clone +// volName02 - name of the second volume to create +// cloneName02 - name of the second volume to clone +// Example: +// TestVolumeCreatingTwoTransactions(t, "volToClone_01", "volToClone_02") + func TestVolumeCreatingTwoTransactions(t *testing.T) { o, storeClient := setupOrchestratorAndBackend(t) restartTransactionMonitor(o) @@ -258,6 +289,20 @@ func TestVolumeCreatingTwoTransactions(t *testing.T) { assert.Equal(t, volName02, volTxns[0].VolumeCreatingConfig.InternalName, "failed to find matching transaction") } +// setupOrchestratorAndBackend sets up an orchestrator and a backend +// for use in tests. +// Parameters: +// t: the test object +// Returns: +// o: the orchestrator +// storeClient: the persistent store client +// It returns an error if the setup fails. +// Example: +// o, storeClient, err := setupOrchestratorAndBackend(t) +// if err != nil { +// t.Errorf("Unable to setup orchestrator and backend: %v", err) +// } + func setupOrchestratorAndBackend(t *testing.T) (*TridentOrchestrator, *persistentstore.InMemoryClient) { storeClient := persistentstore.NewInMemoryClient() o := NewTridentOrchestrator(storeClient) @@ -298,6 +343,14 @@ func setupOrchestratorAndBackend(t *testing.T) (*TridentOrchestrator, *persisten return o, storeClient } +// restartTransactionMonitor stops and restarts the transaction monitor. +// Parameters: +// o - the orchestrator +// period - the period between transaction monitor runs +// maxAge - the maximum age of a transaction before it is considered abandoned +// Example: +// restartTransactionMonitor(o, 1*time.Second, 30*time.Minute) + func restartTransactionMonitor(o *TridentOrchestrator) { // Bootstrap starts the transaction monitor. diff --git a/operator/controllers/orchestrator/apis/netapp/v1/register.go b/operator/controllers/orchestrator/apis/netapp/v1/register.go index be3dc5d02..4e53446e9 100644 --- a/operator/controllers/orchestrator/apis/netapp/v1/register.go +++ b/operator/controllers/orchestrator/apis/netapp/v1/register.go @@ -30,6 +30,17 @@ var ( ) // Adds the list of known types to the given scheme. +// addKnownTypes adds the set of types defined in this +// Parameters: +// scheme - the scheme to add the types to +// version - the version of the API +// addTo - the map of group and version to add the types to +// It returns the scheme with the types added. +// Example: +// scheme := runtime.NewScheme() +// addKnownTypes(scheme) +// addToGroupVersion(scheme, SchemeGroupVersion) + func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &TridentOrchestrator{}, diff --git a/operator/controllers/orchestrator/apis/netapp/v1/types.go b/operator/controllers/orchestrator/apis/netapp/v1/types.go index 9f16d2a07..f00267318 100644 --- a/operator/controllers/orchestrator/apis/netapp/v1/types.go +++ b/operator/controllers/orchestrator/apis/netapp/v1/types.go @@ -67,6 +67,17 @@ type Toleration struct { TolerationSeconds int `json:"tolerationSeconds,omitempty"` } +// GetMap returns a map of the toleration +// Example: +// toleration := &Toleration{ +// Key: "key", +// Operator: "Equal", +// Value: "value", +// Effect: "NoSchedule", +// TolerationSeconds: 10, +// } +// tolerationMap := toleration.GetMap() + func (t *Toleration) GetMap() map[string]string { toleration := map[string]string{} diff --git a/operator/controllers/orchestrator/client/clientset/versioned/fake/clientset_generated.go b/operator/controllers/orchestrator/client/clientset/versioned/fake/clientset_generated.go index 749ecc720..f6ea4e298 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/fake/clientset_generated.go +++ b/operator/controllers/orchestrator/client/clientset/versioned/fake/clientset_generated.go @@ -52,10 +52,30 @@ type Clientset struct { tracker testing.ObjectTracker } +// Discovery retrieves the DiscoveryClient +// It returns a fake if the fake flag is set +// Example: +// clientset := fake.Clientset{} +// clientset.fakeDiscovery = true +// discoveryClient := clientset.Discovery() + func (c *Clientset) Discovery() discovery.DiscoveryInterface { return c.discovery } +// Tracker is a fake implementation of the ObjectTracker interface. +type Tracker struct { + objects map[string]interface{} +} + +// NewTracker returns a new Tracker. +// It returns an error if the tracker could not be created. +// Example: +// tracker, err := fake.NewTracker() +// if err != nil { +// panic(err) +// } + func (c *Clientset) Tracker() testing.ObjectTracker { return c.tracker } diff --git a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go b/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go index d254eadac..b01ad8751 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go +++ b/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go @@ -14,6 +14,11 @@ type FakeTridentV1 struct { *testing.Fake } +// TridentOrchestrators returns a TridentOrchestratorInterface. +// Example: +// c := fake.NewSimpleClientset() +// c.TridentV1().TridentOrchestrators() + func (c *FakeTridentV1) TridentOrchestrators() v1.TridentOrchestratorInterface { return &FakeTridentOrchestrators{c} } diff --git a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/netapp_client.go b/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/netapp_client.go index b491fbc82..069403804 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/netapp_client.go +++ b/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/netapp_client.go @@ -20,6 +20,12 @@ type TridentV1Client struct { restClient rest.Interface } +// TridentOrchestrators returns a TridentOrchestratorInterface. +// Example: +// myClient := v1.NewTridentV1Client(c) +// ctx := context.TODO() +// myClient.TridentOrchestrators().Version(ctx) + func (c *TridentV1Client) TridentOrchestrators() TridentOrchestratorInterface { return newTridentOrchestrators(c) } @@ -52,6 +58,16 @@ func New(c rest.Interface) *TridentV1Client { return &TridentV1Client{c} } +// setConfigDefaults sets the default values for the provided config. +// Parameters: +// config - the config to set the default values for +// Return: +// error - nil if successful, error if not +// It returns an error if the config is nil. +// Example: +// config := &rest.Config{} +// err := setConfigDefaults(config) + func setConfigDefaults(config *rest.Config) error { gv := v1.SchemeGroupVersion config.GroupVersion = &gv diff --git a/operator/controllers/orchestrator/client/informers/externalversions/factory.go b/operator/controllers/orchestrator/client/informers/externalversions/factory.go index ec1297632..7ec775063 100644 --- a/operator/controllers/orchestrator/client/informers/externalversions/factory.go +++ b/operator/controllers/orchestrator/client/informers/externalversions/factory.go @@ -130,6 +130,24 @@ func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[ref // InternalInformerFor returns the SharedIndexInformer for obj using an internal // client. +// InformerFor is a function that returns a SharedIndexInformer for a given object and namespace. +type InformerFor func(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer + +// SharedInformerFactory is type of SharedInformerFactory interface. +type SharedInformerFactory interface { + Start(stopCh <-chan struct{}) + InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. +// Parameters: +// - client - kubernetes client +// - defaultResync - default resync period for informers created by this factory +// It returns a new instance of SharedInformerFactory. +// Example: +// kubeClient := kubernetes.NewForConfigOrDie(c) +// kubeInformerFactory := externalversions.NewSharedInformerFactory(kubeClient, 30*time.Second) + func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { f.lock.Lock() defer f.lock.Unlock() @@ -161,6 +179,17 @@ type SharedInformerFactory interface { Trident() netapp.Interface } +// Trident is the external version of the API. +type Trident struct { + groupVersion string +} + +// NewTrident returns a new Trident. +// It returns nil if the version is not known. +// Example: +// trident := externalversions.NewTrident("trident.netapp.io", "v1alpha1") +// clientset, err := trident.ClientsetForVersion("v1alpha1") + func (f *sharedInformerFactory) Trident() netapp.Interface { return netapp.New(f, f.namespace, f.tweakListOptions) } diff --git a/operator/controllers/orchestrator/client/informers/externalversions/netapp/v1/tridentorchestrator.go b/operator/controllers/orchestrator/client/informers/externalversions/netapp/v1/tridentorchestrator.go index 728cffdd9..fdf533667 100644 --- a/operator/controllers/orchestrator/client/informers/externalversions/netapp/v1/tridentorchestrator.go +++ b/operator/controllers/orchestrator/client/informers/externalversions/netapp/v1/tridentorchestrator.go @@ -62,14 +62,76 @@ func NewFilteredTridentOrchestratorInformer(client versioned.Interface, resyncPe ) } +// defaultInformer is used to informer for TridentOrchestrator types. +type tridentOrchestratorInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewTridentOrchestratorInformer constructs a new informer for TridentOrchestrator type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +// Parameters: +// resyncPeriod - the period at which the informer should re-list the resources. +// tweakListOptions - the function to tweak the list options. +// It returns a shared informer for TridentOrchestrator type. +// Example: +// // Get a shared informer for the resource. +// informer := NewTridentOrchestratorInformer( +// resyncPeriod, +// tweakListOptions, +// ) +// // Register the resource with the shared informer. +// informer.AddEventHandler( +// cache.ResourceEventHandlerFuncs{ +// AddFunc: func(obj interface{}) {}, +// UpdateFunc: func(oldObj, newObj interface{}) {}, +// DeleteFunc: func(obj interface{}) {}, +// }, +// ) + func (f *tridentOrchestratorInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { return NewFilteredTridentOrchestratorInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) } +// Informer is used to obtain a shared index informer for TridentOrchestrator objects. +type tridentOrchestratorInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string + tenant string +} + +// NewTridentOrchestratorInformer constructs a new informer for TridentOrchestrator type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +// It returns a SharedIndexInformer. +// Example: +// tridentOrchestratorInformer := v1.NewTridentOrchestratorInformer(client, namespace, resyncPeriod, indexers) + func (f *tridentOrchestratorInformer) Informer() cache.SharedIndexInformer { return f.factory.InformerFor(&netappv1.TridentOrchestrator{}, f.defaultInformer) } +// Lister implements the TridentOrchestratorLister interface. +type tridentOrchestratorInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewTridentOrchestratorInformer constructs a new informer for TridentOrchestrator type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +// It returns a TridentOrchestratorInformer. +// Example: +// // Create a new controller +// ctrl := NewController(... +// // Create a new informer +// informer := ctrl.Informer() +// // Create a new lister +// lister := ctrl.Lister() + func (f *tridentOrchestratorInformer) Lister() v1.TridentOrchestratorLister { return v1.NewTridentOrchestratorLister(f.Informer().GetIndexer()) } diff --git a/operator/controllers/orchestrator/controller.go b/operator/controllers/orchestrator/controller.go index cd80b9d5f..104d0c1d6 100644 --- a/operator/controllers/orchestrator/controller.go +++ b/operator/controllers/orchestrator/controller.go @@ -107,6 +107,21 @@ type Controller struct { workqueue workqueue.RateLimitingInterface } +// NewController creates a new TridentOrchestrator controller +// Parameters: +// clients - Trident clients +// stopChan - channel to signal controller shutdown +// workqueue - work queue for the controller +// It returns a pointer to the controller +// Example: +// c, err := NewController(clients, stopChan, workqueue) +// if err != nil { +// log.Fatal(err) +// } +// if err = c.Run(2, stopChan); err != nil { +// log.Fatal(err) +// } + func NewController(clients *clients.Clients) (*Controller, error) { log.WithField("Controller", ControllerName).Info("Initializing controller.") @@ -215,6 +230,17 @@ func NewController(clients *clients.Clients) (*Controller, error) { return c, nil } +// Activate starts the controller +// It returns an error if the controller is already active +// Example: +// controller, err := NewController(client, kubeClient, "namespace", "trident", config) +// if err != nil { +// return err +// } +// if err := controller.Activate(); err != nil { +// return err +// } + func (c *Controller) Activate() error { log.WithField("Controller", ControllerName).Infof("Activating controller.") @@ -236,6 +262,15 @@ func (c *Controller) Activate() error { return nil } +// Deactivate stops the controller +// It returns an error if the controller could not be stopped +// Example: +// c := NewController(...) +// err := c.Deactivate() +// if err != nil { +// return err +// } + func (c *Controller) Deactivate() error { log.WithField("Controller", ControllerName).Infof("Deactivating controller.") @@ -246,10 +281,18 @@ func (c *Controller) Deactivate() error { return nil } +// GetName returns the name of the controller +// Example: +// name := c.GetName() + func (c *Controller) GetName() string { return ControllerName } +// Version returns the current version of the orchestrator +// Example: +// v := Version() + func (c *Controller) Version() string { return ControllerVersion } @@ -923,6 +966,15 @@ func (c *Controller) reconcile(key KeyItem) error { } } +// reconcileTridentNotPresent reconciles the state when Trident is not present +// in the cluster. +// It returns an error if the reconciliation failed. +// Example: +// err := c.reconcileTridentNotPresent() +// if err != nil { +// return err +// } + func (c *Controller) reconcileTridentNotPresent() error { log.Info("Reconciler found no operator-based Trident installation.") @@ -1007,6 +1059,22 @@ func (c *Controller) reconcileTridentNotPresent() error { return err } +// reconcileTridentPresent reconciles the state of the operator when Trident is present +// Parameters: +// key: KeyItem containing the namespace and name of the calling CR +// operatorCSIDeployments: List of all operator based Trident CSI deployments +// deploymentNamespace: Namespace where Trident is deployed +// isCSI: True if Trident is deployed as CSI, false if Trident is deployed as in-tree +// controllingCRBasedOnStatus: Controlling CR based on status field of the calling CR +// Return: +// error: Any error encountered +// It returns an error if it encounters an error condition. +// Example: +// err := c.reconcileTridentPresent(key, operatorCSIDeployments, deploymentNamespace, isCSI, controllingCRBasedOnStatus) +// if err != nil { +// return err +// } + func (c *Controller) reconcileTridentPresent(key KeyItem, operatorCSIDeployments []appsv1.Deployment, deploymentNamespace string, isCSI bool, controllingCRBasedOnStatus *netappv1.TridentOrchestrator) error { @@ -1592,6 +1660,11 @@ func (c *Controller) updateOtherCRs(controllingCRName string) error { } // updateLogAndStatus updates the event logs and status of a TridentOrchestrator CR (if required) +// updateTorcEventAndStatus updates the status of the TridentOrchestrator CR and logs an event +// Example: +// torcCR, err := c.updateTorcEventAndStatus(tridentCR, debugMessage, message, status, version, namespace, +// corev1.EventTypeNormal, specValues) + func (c *Controller) updateTorcEventAndStatus( tridentCR *netappv1.TridentOrchestrator, debugMessage, message, status, version, namespace, eventType string, specValues *netappv1.TridentOrchestratorSpecValues) (torcCR *netappv1.TridentOrchestrator, err error) { @@ -1774,6 +1847,14 @@ func (c *Controller) deleteTridentTprovCRAll() error { return nil } +// cleanupTridentProvisioner cleans up the Trident provisioner resources. +// It returns an error if any of the operations fail. +// Example: +// err := cleanupTridentProvisioner() +// if err != nil { +// return err +// } + func (c *Controller) cleanupTridentProvisioner() error { if err := c.deleteTridentTprovCRAll(); err != nil { return err @@ -2065,6 +2146,11 @@ func (c *Controller) doesCRDExist(crdName string) (bool, error) { return crdExist, returnError } +// isNotFoundError returns true if the error is an API not found error. +// Example: +// err := errors.NewNotFound(schema.GroupResource{Resource: "pods"}, "123") +// isNotFoundError(err) // true + func isNotFoundError(err error) bool { if statusErr, ok := err.(*apierrors.StatusError); ok && statusErr.Status().Reason == metav1.StatusReasonNotFound { return true diff --git a/operator/controllers/orchestrator/installer/installer.go b/operator/controllers/orchestrator/installer/installer.go index cd802b6f1..a1affa5ad 100644 --- a/operator/controllers/orchestrator/installer/installer.go +++ b/operator/controllers/orchestrator/installer/installer.go @@ -109,6 +109,19 @@ type Installer struct { namespace string } +// NewInstaller creates a new Trident installer +// Parameters: +// kubeConfig: Kubernetes client configuration +// namespace: Kubernetes namespace +// timeout: Timeout for Kubernetes operations +// It returns a Trident installer and error +// Example: +// installer, err := installer.NewInstaller(kubeConfig, namespace, timeout) +// if err != nil { +// return nil, err +// } +// defer installer.Close() + func NewInstaller(kubeConfig *rest.Config, namespace string, timeout int) (TridentInstaller, error) { if timeout <= 0 { @@ -138,6 +151,14 @@ func NewInstaller(kubeConfig *rest.Config, namespace string, timeout int) (Tride }, nil } +// logFormatPrechecks performs pre-checks on the logFormat +// It returns an error if the logFormat is not valid +// Example: +// err := i.logFormatPrechecks() +// if err != nil { +// return err +// } + func (i *Installer) logFormatPrechecks() (returnError error) { switch logFormat { case "text", "json": @@ -413,6 +434,19 @@ func (i *Installer) setInstallationParams( return controllingCRDetails, labels, tridentUpdateNeeded, nil } +// InstallOrPatchTrident installs or updates Trident +// Parameters: +// cr - the controlling CR +// currentInstallationVersion - the current version of Trident installed +// k8sUpdateNeeded - true if the Kubernetes version has changed +// Returns: +// *netappv1.TridentOrchestratorSpecValues - the values from the CR spec +// string - the version of Trident installed +// error - any error encountered +// It returns the values from the CR spec, the version of Trident installed, and any error encountered. +// Example: +// values, version, err := i.InstallOrPatchTrident(cr, currentInstallationVersion, k8sUpdateNeeded) + func (i *Installer) InstallOrPatchTrident( cr netappv1.TridentOrchestrator, currentInstallationVersion string, k8sUpdateNeeded bool, ) (*netappv1.TridentOrchestratorSpecValues, string, error) { @@ -683,6 +717,12 @@ func (i *Installer) ensureCRDEstablished(crdName string) error { return nil } +// createOrPatchK8sBetaCSIDriver creates or patches the K8s (beta) CSI driver +// It returns an error if the operation fails +// Example: +// installer := installer.NewInstaller(k8sClient, k8sVersion) +// err := installer.createOrPatchK8sBetaCSIDriver(controllingCRDetails, labels, shouldUpdate) + func (i *Installer) createOrPatchK8sBetaCSIDriver( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -711,6 +751,20 @@ func (i *Installer) createOrPatchK8sBetaCSIDriver( return nil } +// createOrPatchK8sCSIDriver creates or patches the K8s CSI driver +// Parameters: +// controllingCRDetails: map of controlling CR details +// labels: map of labels +// shouldUpdate: boolean to indicate if the CSI driver should be updated +// Return: +// error: error if any +// It returns error if it fails to create or patch the K8s CSI driver +// Example: +// err := createOrPatchK8sCSIDriver(controllingCRDetails, labels, shouldUpdate) +// if err != nil { +// log.Errorf("failed to create or patch K8s CSI driver; %v", err) +// } + func (i *Installer) createOrPatchK8sCSIDriver(controllingCRDetails, labels map[string]string, shouldUpdate bool) error { CSIDriverName := getCSIDriverName() @@ -736,6 +790,21 @@ func (i *Installer) createOrPatchK8sCSIDriver(controllingCRDetails, labels map[s return nil } +// createRBACObjects creates the RBAC objects for Trident. +// Parameters: +// controllingCRDetails - a map of labels and annotations to be applied to the RBAC objects +// labels - a map of labels to be applied to the RBAC objects +// shouldUpdate - whether or not to update the RBAC objects if they already exist +// Returns: +// newServiceAccount - whether or not a new service account was created +// returnError - any error encountered +// Example: +// newServiceAccount, returnError := createRBACObjects(controllingCRDetails, labels, false) +// if returnError != nil { +// log.Errorf("Failed to create RBAC objects for Trident; %v", returnError) +// return returnError +// } + func (i *Installer) createRBACObjects( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) (newServiceAccount bool, returnError error) { @@ -774,6 +843,14 @@ func (i *Installer) createRBACObjects( return } +// createTridentInstallationNamespace creates the Trident installation namespace +// It returns an error if the namespace could not be created. +// Example: +// err := installer.createTridentInstallationNamespace() +// if err != nil { +// return fmt.Errorf("failed to create Trident installation namespace; %v", err) +// } + func (i *Installer) createTridentInstallationNamespace() error { createNamespace := true @@ -803,6 +880,18 @@ func (i *Installer) createTridentInstallationNamespace() error { return nil } +// createOrPatchTridentServiceAccount creates or patches the Trident service account +// Parameters: +// controllingCRDetails - a map of labels and values that will be applied to the Trident service account +// labels - a map of labels and values that will be applied to the Trident service account +// shouldUpdate - true if the Trident service account should be updated +// Return values: +// bool - true if the Trident service account was created +// error - nil if the Trident service account was created or patched successfully, or an error if it failed +// It returns an error if the Trident service account could not be created or patched. +// Example: +// created, err := createOrPatchTridentServiceAccount(controllingCRDetails, labels, shouldUpdate) + func (i *Installer) createOrPatchTridentServiceAccount( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) (bool, error) { @@ -830,6 +919,20 @@ func (i *Installer) createOrPatchTridentServiceAccount( return newServiceAccount, nil } +// createOrPatchTridentClusterRole creates or patches the Trident cluster role +// Parameters: +// controllingCRDetails - details of the controlling CR +// labels - labels to apply to the Trident cluster role +// shouldUpdate - whether the Trident cluster role should be updated +// Return: +// error - error if any +// It returns error if it fails to create or patch the Trident cluster role. +// Example: +// err := i.createOrPatchTridentClusterRole(controllingCRDetails, labels, shouldUpdate) +// if err != nil { +// return err +// } + func (i *Installer) createOrPatchTridentClusterRole( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -858,6 +961,21 @@ func (i *Installer) createOrPatchTridentClusterRole( return nil } +// createOrPatchTridentClusterRoleBinding creates or patches the Trident cluster role binding. +// Parameters: +// controllingCRDetails: map of controlling CR details +// labels: map of labels +// shouldUpdate: true if the cluster role binding should be updated +// It returns an error if the operation fails. +// Example: +// controllingCRDetails := map[string]string{ +// "name": "trident-csi-driver", +// "kind": "CSIDriver", +// } +// labels := map[string]string{"app": "trident"} +// shouldUpdate = true +// err = i.createOrPatchTridentClusterRoleBinding(controllingCRDetails, labels, shouldUpdate) + func (i *Installer) createOrPatchTridentClusterRoleBinding( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -887,6 +1005,20 @@ func (i *Installer) createOrPatchTridentClusterRoleBinding( return nil } +// createOrPatchTridentOpenShiftSCC creates or patches the Trident OpenShift SCC +// Parameters: +// controllingCRDetails - a map of the controlling CR's details +// labels - a map of labels to apply to the OpenShift SCC +// shouldUpdate - true if the SCC should be updated, false if it should be created +// Returns: +// error - error if any +// It returns an error if it fails to create or patch the OpenShift SCC +// Example: +// err := i.createOrPatchTridentOpenShiftSCC(controllingCRDetails, labels, shouldUpdate) +// if err != nil { +// return fmt.Errorf("failed to create or patch Trident OpenShift SCC; %v", err) +// } + func (i *Installer) createOrPatchTridentOpenShiftSCC( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -928,6 +1060,12 @@ func (i *Installer) createOrPatchTridentOpenShiftSCC( return nil } +// createAndEnsureCRDs creates the Trident CRDs. +// Example: +// if err := i.createAndEnsureCRDs(); err != nil { +// return err +// } + func (i *Installer) createAndEnsureCRDs() (returnError error) { returnError = i.createCRDs() @@ -937,6 +1075,20 @@ func (i *Installer) createAndEnsureCRDs() (returnError error) { return } +// createOrPatchTridentPodSecurityPolicy creates or patches the Trident pod security policy +// Parameters: +// controllingCRDetails - a map of the controlling CR's details +// labels - a map of labels to apply to the Trident pod security policy +// shouldUpdate - indicates whether the Trident pod security policy should be updated +// Return: +// error - error if any +// It returns an error if it fails to create or patch the Trident pod security policy +// Example: +// err := i.createOrPatchTridentPodSecurityPolicy(controllingCRDetails, labels, true) +// if err != nil { +// return err +// } + func (i *Installer) createOrPatchTridentPodSecurityPolicy( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -962,6 +1114,20 @@ func (i *Installer) createOrPatchTridentPodSecurityPolicy( return nil } +// createOrPatchTridentService creates or patches the Trident service. +// Parameters: +// controllingCRDetails - map of controlling CR details +// labels - map of labels +// shouldUpdate - true if the service should be updated, false otherwise +// Returns: +// error - error, if any +// It returns an error if it fails to create or patch the Trident service. +// Example: +// err := installer.createOrPatchTridentService(controllingCRDetails, labels, shouldUpdate) +// if err != nil { +// return err +// } + func (i *Installer) createOrPatchTridentService( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -987,6 +1153,17 @@ func (i *Installer) createOrPatchTridentService( return nil } +// createOrPatchTridentProtocolSecret creates or patches the Trident protocol secret +// Parameters: +// controllingCRDetails - the controlling CR's details +// labels - the labels to apply to the secret +// shouldUpdate - whether the secret should be updated if it already exists +// Return: +// error - error if any +// It returns an error if the secret cannot be created or patched. +// Example: +// err := i.createOrPatchTridentProtocolSecret(controllingCRDetails, labels, shouldUpdate) + func (i *Installer) createOrPatchTridentProtocolSecret( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -1081,6 +1258,22 @@ func (i *Installer) createOrConsumeTridentEncryptionSecret( return nil } +// createOrPatchTridentDeployment creates or patches the Trident deployment +// Parameters: +// controllingCRDetails - the labels and annotations to add to the Trident deployment +// labels - the labels to add to the Trident deployment +// shouldUpdate - whether or not to update the Trident deployment +// newServiceAccount - whether or not a new service account should be created +// Returns: +// error - error if there was a problem creating or patching the Trident deployment +// It returns an error if there was a problem creating or patching the Trident deployment. +// Example: +// i := installer.NewInstaller(client) +// err := i.createOrPatchTridentDeployment(controllingCRDetails, labels, false, false) +// if err != nil { +// return err +// } + func (i *Installer) createOrPatchTridentDeployment( controllingCRDetails, labels map[string]string, shouldUpdate, newServiceAccount bool, ) error { @@ -1163,6 +1356,18 @@ func (i *Installer) TridentDeploymentInformation( return i.client.GetDeploymentInformation(getDeploymentName(true), deploymentLabel, i.namespace) } +// createOrPatchTridentDaemonSet creates or patches the Trident daemonset +// Parameters: +// controllingCRDetails - map of details about the controlling CR +// labels - map of labels to add to the daemonset +// shouldUpdate - true if the daemonset should be updated +// newServiceAccount - true if a new service account should be created +// Return: +// error - error if any +// It returns an error if it fails to create or patch the daemonset +// Example: +// err := i.createOrPatchTridentDaemonSet(controllingCRDetails, labels, shouldUpdate, newServiceAccount) + func (i *Installer) createOrPatchTridentDaemonSet( controllingCRDetails, labels map[string]string, shouldUpdate, newServiceAccount bool, ) error { @@ -1235,6 +1440,15 @@ func (i *Installer) TridentDaemonSetInformation() (*appsv1.DaemonSet, return i.client.GetDaemonSetInformation(daemonSetName, nodeLabel, i.namespace) } +// waitForTridentPod waits for the Trident pod to start. +// It returns the pod object if successful. +// Example: +// pod, err := waitForTridentPod() +// if err != nil { +// log.Error(err) +// return err +// } + func (i *Installer) waitForTridentPod() (*v1.Pod, error) { var pod *v1.Pod @@ -1346,6 +1560,19 @@ func (i *Installer) waitForTridentPod() (*v1.Pod, error) { return pod, nil } +// waitForRESTInterface waits for the Trident REST interface to become available. +// Parameters: +// tridentPodName - the name of the Trident pod +// Returns: +// error - nil if the REST interface is available, error otherwise +// It returns an error if the REST interface is not available after 30 seconds. +// Example: +// err := waitForRESTInterface("trident-csi-trident-0") +// if err != nil { +// return err +// } +// fmt.Println("Trident REST interface is up.") + func (i *Installer) waitForRESTInterface(tridentPodName string) error { var version, versionWithMetadata string diff --git a/operator/controllers/orchestrator/installer/installer_test.go b/operator/controllers/orchestrator/installer/installer_test.go index b527e108b..c0518c691 100644 --- a/operator/controllers/orchestrator/installer/installer_test.go +++ b/operator/controllers/orchestrator/installer/installer_test.go @@ -19,12 +19,29 @@ var ( k8sClientError = fmt.Errorf("k8s error") ) +// newMockKubeClient creates a new mock kubernetes client +// Parameters: +// t *testing.T - test object +// Returns: +// *mockExtendedK8sClient.MockExtendedK8sClient - mock kubernetes client +// It returns a mock kubernetes client +// Example: +// mockK8sClient := newMockKubeClient(t) + func newMockKubeClient(t *testing.T) *mockExtendedK8sClient.MockExtendedK8sClient { mockCtrl := gomock.NewController(t) mockK8sClient := mockExtendedK8sClient.NewMockExtendedK8sClient(mockCtrl) return mockK8sClient } +// newTestInstaller creates a new Installer for testing purposes. +// Parameters: +// client - a mock client for the installer to use +// It returns the new Installer. +// Example: +// client := mockExtendedK8sClient.NewMockClient() +// installer := newTestInstaller(client) + func newTestInstaller(client *mockExtendedK8sClient.MockExtendedK8sClient) *Installer { return &Installer{ @@ -34,6 +51,15 @@ func newTestInstaller(client *mockExtendedK8sClient.MockExtendedK8sClient) *Inst } } +// createTestControllingCRDetails creates a map of the controlling CR details +// It returns a map of the controlling CR details +// Example: +// controllingCRDetails := createTestControllingCRDetails() +// fmt.Println(controllingCRDetails) +// +// Output: +// map[trident.netapp.io/apiVersion:v01.01.01 trident.netapp.io/controller:trident-orchestrator trident.netapp.io/kind:deployment trident.netapp.io/name:trident-csi trident.netapp.io/uid:1] + func createTestControllingCRDetails() map[string]string { controllingCRDetails := make(map[string]string) @@ -46,6 +72,11 @@ func createTestControllingCRDetails() map[string]string { return controllingCRDetails } +// createTestLabels creates a set of labels for testing +// It returns a map of labels +// Example: +// labels := createTestLabels() + func createTestLabels() map[string]string { labels := make(map[string]string) @@ -56,6 +87,19 @@ func createTestLabels() map[string]string { return labels } +// TestInstaller_createOrConsumeTridentEncryptionSecret tests the creation of the Trident encryption secret +// It checks for the following conditions: +// 1. K8s error at CheckSecretExists +// 2. Secret already exists and no K8s error +// 3. Create secret with no failure at PutSecret +// 4. Create secret with a failure at PutSecret +// Parameters: +// t *testing.T +// Returns: +// none +// Example: +// TestInstaller_createOrConsumeTridentEncryptionSecret(t) + func TestInstaller_createOrConsumeTridentEncryptionSecret(t *testing.T) { mockK8sClient := newMockKubeClient(t) diff --git a/operator/controllers/orchestrator/installer/k8s_client_test.go b/operator/controllers/orchestrator/installer/k8s_client_test.go index a347c9c9e..48a2a20ce 100644 --- a/operator/controllers/orchestrator/installer/k8s_client_test.go +++ b/operator/controllers/orchestrator/installer/k8s_client_test.go @@ -29,6 +29,14 @@ import ( "github.com/netapp/trident/utils" ) +// TestMain is the entry point for all tests. +// It checks for the presence of the KUBECONFIG environment variable. +// If it is not set, the tests are skipped. +// Parameters: +// m: the test suite +// Example: +// $ KUBECONFIG= go test ./... + func TestMain(m *testing.M) { // Disable any standard log output log.SetOutput(ioutil.Discard) @@ -60,10 +68,24 @@ func (m *JSONMatcher) Matches(x interface{}) bool { return reflect.DeepEqual(actual, expected) } +// String returns a string representation of the matcher. +// Example: +// json.String() + func (m *JSONMatcher) String() string { return "" } +// TestCreateCustomResourceDefinition tests the CreateCustomResourceDefinition function +// It checks that the function returns the expected error +// Parameters: +// crdName: the name of the CRD to create +// crdYAML: the YAML of the CRD to create +// Example: +// TestCreateCustomResourceDefinition("crd-name", "crd-yaml") +// Expected Results: +// The function should return an error if the K8s client returns an error + func TestCreateCustomResourceDefinition(t *testing.T) { crdName := "crd-name" @@ -123,6 +145,14 @@ func TestCreateCustomResourceDefinition(t *testing.T) { } } +// TestDeleteCustomResourceDefinition tests the DeleteCustomResourceDefinition function +// It checks that the function returns the expected error +// Parameters: +// crdName: the name of the CRD to delete +// crdYAML: the YAML of the CRD to delete +// Example: +// TestDeleteCustomResourceDefinition("test-crd", "test-crd-yaml") + func TestDeleteCustomResourceDefinition(t *testing.T) { crdName := "crd-name" @@ -182,6 +212,20 @@ func TestDeleteCustomResourceDefinition(t *testing.T) { } } +// TestWaitForCRDEstablished tests the WaitForCRDEstablished function +// It checks for the following conditions: +// - CRD is not found +// - CRD is found but not in the expected state +// - CRD is found and in the expected state +// Parameters: +// - crdName: the name of the CRD to wait for +// - timeout: the time to wait for the CRD to be established +// Returns: +// - error: nil if the CRD is found and in the expected state, otherwise an error +// It returns an error if the CRD is not found or is not in the expected state +// Example: +// err := WaitForCRDEstablished("trident-crd", 5 * time.Second) + func TestWaitForCRDEstablished(t *testing.T) { var validCRD, invalidCRD *v1.CustomResourceDefinition @@ -283,6 +327,19 @@ func TestWaitForCRDEstablished(t *testing.T) { } } +// TestDeleteTransientVersionPod tests the DeleteTransientVersionPod function +// It checks for the following cases: +// 1. k8s client error during GetPodsByLabel +// 2. no k8s client error and no transient pods found +// 3. no k8s client error and transient pods found but not removed +// 4. no k8s client error and transient pods found and removed +// Parameters: +// t *testing.T : go testing framework +// Example: +// TestDeleteTransientVersionPod(t) +// Output: +// asserts that the expected output is equal to the actual output + func TestDeleteTransientVersionPod(t *testing.T) { // declare and initialize variables used throughout the test cases var versionPodLabel, name, invalidName, namespace string @@ -392,6 +449,16 @@ func TestDeleteTransientVersionPod(t *testing.T) { } } +// TestGetBetaCSIDriverInformation tests the GetBetaCSIDriverInformation function +// It checks the following cases: +// - k8s error +// - no beta CSI driver found and no k8s error +// - valid current beta CSI driver found and no k8s error +// Parameters: +// - t: test object +// Example: +// - installer.TestGetBetaCSIDriverInformation(t) + func TestGetBetaCSIDriverInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -528,6 +595,17 @@ func TestGetBetaCSIDriverInformation(t *testing.T) { } } +// TestPutBetaCSIDriver tests the PutBetaCSIDriver function +// It checks that the function returns the correct error +// It also checks that the function calls the correct k8s client functions +// Parameters: +// currentBetaCSIDriver: the current beta CSI driver +// createBetaCSIDriver: whether or not to create the beta CSI driver +// newBetaCSIDriverYAML: the YAML for the new beta CSI driver +// appLabel: the app label to use for the beta CSI driver +// Example: +// TestPutBetaCSIDriver(&storagev1beta1.CSIDriver{}, false, "", "") + func TestPutBetaCSIDriver(t *testing.T) { driverName := getCSIDriverName() @@ -672,6 +750,18 @@ func TestPutBetaCSIDriver(t *testing.T) { } } +// TestDeleteTridentBetaCSIDriverCR tests the DeleteTridentBetaCSIDriverCR method +// It checks that the correct error is returned when the method fails +// Parameters: +// secretName: the name of the secret to delete +// appLabel: the label to use to find the secret +// It returns the error returned by the method +// Example: +// err := TestDeleteTridentBetaCSIDriverCR(secretName, appLabel) +// if err != nil { +// // handle error +// } + func TestDeleteTridentBetaCSIDriverCR(t *testing.T) { // arrange variables for the tests var emptyBetaCSIDriverList, unwantedBetaCSIDrivers []storagev1beta1.CSIDriver @@ -770,6 +860,16 @@ func TestDeleteTridentBetaCSIDriverCR(t *testing.T) { } } +// TestRemoveMultipleBetaCSIDriverCRs tests the RemoveMultipleBetaCSIDriverCRs function +// It checks the following cases: +// 1. No beta csi driver crs +// 2. K8s call error +// 3. Valid beta csi driver crs +// Parameters: +// t *testing.T - go test handler +// Example: +// TestRemoveMultipleBetaCSIDriverCRs(t) + func TestRemoveMultipleBetaCSIDriverCRs(t *testing.T) { // arrange variables for the tests var emptyCSIDriversCRs, undeletedCSIDriverCRs, unwantedCSIDriverCRs []storagev1beta1.CSIDriver @@ -850,6 +950,16 @@ func TestRemoveMultipleBetaCSIDriverCRs(t *testing.T) { } } +// TestGetCSIDriverInformation tests the GetCSIDriverInformation function +// It checks for the following conditions: +// 1. If the function returns an error when it is unable to get a list of CSI driver custom resources by label +// 2. If the function returns no error when there are no CSI driver custom resources found by label +// 3. If the function returns no error when there are valid CSI driver custom resources found by label +// Parameters: +// t *testing.T - go testing object +// Example: +// TestGetCSIDriverInformation(t) + func TestGetCSIDriverInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -986,6 +1096,28 @@ func TestGetCSIDriverInformation(t *testing.T) { } } +// TestPutCSIDriver tests the PutCSIDriver method +// It checks to make sure the correct k8s client calls are made +// It also checks to make sure the correct errors are returned +// Parameters: +// currentCSIDriver: the current CSI driver +// createCSIDriver: whether or not to create the CSI driver +// newCSIDriverYAML: the new CSI driver YAML +// appLabel: the app label +// Returns: +// error: the error returned by PutCSIDriver +// Example: +// TestPutCSIDriver(t, +// &storagev1.CSIDriver{ +// ObjectMeta: metav1.ObjectMeta{ +// Name: driverName, +// }, +// }, +// false, +// newCSIDriverYAML, +// appLabel, +// ) + func TestPutCSIDriver(t *testing.T) { var validCSIDriver *storagev1.CSIDriver @@ -1131,6 +1263,19 @@ func TestPutCSIDriver(t *testing.T) { } } +// TestDeleteTridentCSIDriverCR tests the DeleteTridentCSIDriverCR function +// It checks the following cases: +// - GetCSIDriversByLabel fails +// - GetCSIDriversByLabel returns no services +// - GetCSIDriversByLabel succeeds but RemoveMultipleCSIDriverCRs fails +// - GetCSIDriversByLabel succeeds and RemoveMultipleCSIDriverCRs succeeds +// Parameters: +// csiDriverName - the name of the CSI driver to delete +// appLabel - the label to use to find the CSI driver CRs to delete +// It returns an error if any of the above cases fail +// Example: +// err := DeleteTridentCSIDriverCR("trident-csi-driver", "app=trident") + func TestDeleteTridentCSIDriverCR(t *testing.T) { // arrange variables for the tests var emptyCSIDriverList, unwantedCSIDrivers []storagev1.CSIDriver @@ -1229,6 +1374,16 @@ func TestDeleteTridentCSIDriverCR(t *testing.T) { } } +// TestRemoveMultipleCSIDriverCRs tests the RemoveMultipleCSIDriverCRs function +// It checks the following cases: +// - no CSI driver CRs +// - k8s call error +// - valid CSI driver CRs +// Parameters: +// t *testing.T - go test helper +// Example: +// TestRemoveMultipleCSIDriverCRs(t) + func TestRemoveMultipleCSIDriverCRs(t *testing.T) { // arrange variables for the tests var emptyCSIDriversCRs, undeletedCSIDriverCRs, unwantedCSIDriverCRs []storagev1.CSIDriver @@ -1309,6 +1464,14 @@ func TestRemoveMultipleCSIDriverCRs(t *testing.T) { } } +// TestGetClusterRoleInformation tests the GetClusterRoleInformation function +// It checks that the function returns the correct currentClusterRole, unwantedClusterRoles, +// createClusterRole, and error based on the input and mock k8s client +// Parameters: +// t *testing.T: go testing framework object used to manage test flow +// Example: +// TestGetClusterRoleInformation(t) + func TestGetClusterRoleInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -1445,6 +1608,17 @@ func TestGetClusterRoleInformation(t *testing.T) { } } +// TestPutClusterRole tests the PutClusterRole function +// It checks the following cases: +// - creating a ClusterRole and no k8s error occurs +// - creating a ClusterRole and a k8s error occurs +// - updating a ClusterRole and no k8s error occurs +// - updating a ClusterRole and a k8s error occurs +// Parameters: +// t *testing.T +// Example: +// TestPutClusterRole(t) + func TestPutClusterRole(t *testing.T) { var validClusterRole *rbacv1.ClusterRole @@ -1587,6 +1761,17 @@ func TestPutClusterRole(t *testing.T) { } } +// TestDeleteTridentClusterRole tests the DeleteTridentClusterRole function +// It checks the following cases: +// 1. GetClusterRolesByLabel fails +// 2. GetClusterRolesByLabel returns no cluster roles +// 3. GetClusterRolesByLabel succeeds but RemoveMultipleClusterRoles fails +// 4. GetClusterRolesByLabel succeeds and RemoveMultipleClusterRoles succeeds +// Parameters: +// t *testing.T - go test handler +// Example: +// TestDeleteTridentClusterRole(t) + func TestDeleteTridentClusterRole(t *testing.T) { // arrange variables for the tests var emptyClusterRoleList, unwantedClusterRoles []rbacv1.ClusterRole @@ -1684,6 +1869,16 @@ func TestDeleteTridentClusterRole(t *testing.T) { } } +// TestRemoveMultipleClusterRoles tests the RemoveMultipleClusterRoles function +// It checks to see if the correct error is returned when the k8s client returns an error +// It also checks to see if the correct error is returned when the k8s client does not return an error +// Parameters: +// t *testing.T : go test helper +// Example: +// TestRemoveMultipleClusterRoles(t) +// Returns: +// nothing + func TestRemoveMultipleClusterRoles(t *testing.T) { // arrange variables for the tests var emptyClusterRoles, unwantedClusterRoles, undeletedClusterRoles []rbacv1.ClusterRole @@ -1764,6 +1959,16 @@ func TestRemoveMultipleClusterRoles(t *testing.T) { } } +// TestGetClusterRoleBindingInformation tests the GetClusterRoleBindingInformation function +// It checks for the following conditions: +// 1. k8s error +// 2. no cluster role binding found and no k8s error +// 3. valid current cluster role binding found and no k8s error +// Parameters: +// t *testing.T - go test handler +// Example: +// TestGetClusterRoleBindingInformation(t) + func TestGetClusterRoleBindingInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -1904,6 +2109,16 @@ func TestGetClusterRoleBindingInformation(t *testing.T) { } } +// TestPutClusterRoleBinding tests the PutClusterRoleBinding function +// It checks for error conditions and also for the correct patching of the ClusterRoleBinding +// Parameters: +// currentClusterRoleBinding: the current ClusterRoleBinding +// createClusterRoleBinding: whether to create or update the ClusterRoleBinding +// newClusterRoleBindingYAML: the new ClusterRoleBinding YAML +// appLabel: the app label to use for patching +// Example: +// TestPutClusterRoleBinding(t, nil, true, "", "trident") + func TestPutClusterRoleBinding(t *testing.T) { var validClusterRoleBinding *rbacv1.ClusterRoleBinding @@ -2048,6 +2263,14 @@ func TestPutClusterRoleBinding(t *testing.T) { } } +// TestDeleteTridentClusterRoleBinding tests the DeleteTridentClusterRoleBinding function +// It checks that the function returns the expected error +// Parameters: +// clusterRoleBindingName: the name of the cluster role binding to delete +// appLabel: the label of the cluster role bindings to delete +// Example: +// TestDeleteTridentClusterRoleBinding("clusterRoleBindingName", "appLabel") + func TestDeleteTridentClusterRoleBinding(t *testing.T) { // arrange variables for the tests var emptyClusterRoleBindingList, unwantedClusterRoleBindings []rbacv1.ClusterRoleBinding @@ -2145,6 +2368,16 @@ func TestDeleteTridentClusterRoleBinding(t *testing.T) { } } +// TestRemoveMultipleClusterRoleBindings tests the RemoveMultipleClusterRoleBindings function +// It checks the following cases: +// - no cluster role bindings +// - k8s call error +// - valid cluster role bindings +// Parameters: +// t *testing.T : go test helper +// Example: +// TestRemoveMultipleClusterRoleBindings(t *testing.T) + func TestRemoveMultipleClusterRoleBindings(t *testing.T) { // arrange variables for the tests var emptyClusterRoleBindings, unwantedClusterRoleBindings, undeletedClusterRoleBindings []rbacv1.ClusterRoleBinding @@ -2227,6 +2460,16 @@ func TestRemoveMultipleClusterRoleBindings(t *testing.T) { } } +// TestGetDaemonSetInformation tests the GetDaemonSetInformation function +// It checks the following cases: +// 1. Expect to fail with k8s error +// 2. Expect to pass with no daemonset found and no k8s error +// 3. Expect to pass with current daemonset found and no k8s error +// Parameters: +// t *testing.T : go test helper type +// Example: +// TestGetDaemonSetInformation(t *testing.T) + func TestGetDaemonSetInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -2359,6 +2602,18 @@ func TestGetDaemonSetInformation(t *testing.T) { } } +// TestPutDaemonSet tests the PutDaemonSet function +// It checks that the correct k8s client calls are made and that the correct errors are returned +// Parameters: +// currentDaemonSet: the current Trident DaemonSet +// createDaemonSet: whether or not to create a DaemonSet +// newDaemonSetYAML: the YAML for the new Trident DaemonSet +// nodeLabel: the label to use for the DaemonSet +// Expected Results: +// The correct k8s client calls are made and the correct errors are returned +// Example: +// TestPutDaemonSet(nil, true, "newDaemonSetYAML", "nodeLabel") + func TestPutDaemonSet(t *testing.T) { daemonSetName := TridentCSILabel @@ -2506,6 +2761,14 @@ func TestPutDaemonSet(t *testing.T) { } } +// TestDeleteTridentDaemonSet tests the DeleteTridentDaemonSet function +// It checks that the function returns the expected error when the k8s client returns an error +// It also checks that the function returns nil when the k8s client returns no error +// Parameters: +// t *testing.T: go test helper +// Example: +// TestDeleteTridentDaemonSet(t) + func TestDeleteTridentDaemonSet(t *testing.T) { // arrange variables for the tests var emptyDaemonSetList, unwantedDaemonSets []appsv1.DaemonSet @@ -2588,6 +2851,14 @@ func TestDeleteTridentDaemonSet(t *testing.T) { } } +// TestRemoveMultipleDaemonSets tests the RemoveMultipleDaemonSets function +// It checks that the correct error is returned when the k8s client returns an error +// It also checks that the correct error is returned when the k8s client does not return an error +// Parameters: +// t *testing.T : go test helper +// Example: +// TestRemoveMultipleDaemonSets(t *testing.T) + func TestRemoveMultipleDaemonSets(t *testing.T) { // arrange variables for the tests var emptyDaemonSets, unwantedDaemonSets []appsv1.DaemonSet @@ -2666,6 +2937,16 @@ func TestRemoveMultipleDaemonSets(t *testing.T) { } } +// TestGetDeploymentInformation tests the GetDeploymentInformation function +// It checks the following cases: +// - k8s error +// - no daemonset found +// - current daemonset found +// Parameters: +// t *testing.T - go testing object +// Example: +// TestGetDeploymentInformation(t) + func TestGetDeploymentInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -2798,6 +3079,17 @@ func TestGetDeploymentInformation(t *testing.T) { } } +// TestPutDeployment tests the PutDeployment function +// It checks for the following: +// - creating a Deployment when one does not exist +// - updating a Deployment when one does exist +// - error handling +// Parameters: +// t *testing.T +// Example: +// t := &testing.T{} +// TestPutDeployment(t) + func TestPutDeployment(t *testing.T) { deploymentName := getDeploymentName(true) @@ -2947,6 +3239,13 @@ func TestPutDeployment(t *testing.T) { } } +// TestDeleteTridentDeployment tests the DeleteTridentDeployment function +// It checks that the function returns the expected error codes +// Parameters: +// t: the test object +// Example: +// TestDeleteTridentDeployment(t) + func TestDeleteTridentDeployment(t *testing.T) { // arrange variables for the tests var emptyDeploymentList, unwantedDeployments []appsv1.Deployment @@ -3029,6 +3328,16 @@ func TestDeleteTridentDeployment(t *testing.T) { } } +// TestRemoveMultipleDeployments tests the RemoveMultipleDeployments function +// It checks for the following cases: +// 1. No deployments to remove +// 2. Error from k8s client call +// 3. Valid deployments to remove +// Parameters: +// t *testing.T : go test handler +// Example: +// TestRemoveMultipleDeployments(t *testing.T) + func TestRemoveMultipleDeployments(t *testing.T) { // arrange variables for the tests var emptyDeploymentList, unwantedDeployments []appsv1.Deployment @@ -3107,6 +3416,18 @@ func TestRemoveMultipleDeployments(t *testing.T) { } } +// TestGetPodSecurityPolicyInformation tests the GetPodSecurityPolicyInformation function +// It checks the following cases: +// - k8s error +// - no pod security policies found +// - valid pod security policies found +// Parameters: +// t *testing.T +// Example: +// TestGetPodSecurityPolicyInformation(t) +// Returns: +// nil + func TestGetPodSecurityPolicyInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -3245,6 +3566,31 @@ func TestGetPodSecurityPolicyInformation(t *testing.T) { } } +// TestPutPodSecurityPolicy tests the PutPodSecurityPolicy function +// It checks that the correct k8s client calls are made and that the correct error is returned +// Parameters: +// currentPSP: the current PSP +// createPSP: whether to create a new PSP or update an existing one +// newPSPYAML: the YAML for the new PSP +// appLabel: the label to use for the PSP +// Expected results: +// err: the expected error +// Example: +// TestPutPodSecurityPolicy( +// &policyv1beta1.PodSecurityPolicy{ +// ObjectMeta: metav1.ObjectMeta{ +// Name: "trident", +// }, +// }, +// false, +// k8sclient.GetPrivilegedPodSecurityPolicyYAML( +// "trident", +// make(map[string]string), +// make(map[string]string), +// ), +// "trident", +// ) + func TestPutPodSecurityPolicy(t *testing.T) { pspName := getPSPName() @@ -3382,6 +3728,16 @@ func TestPutPodSecurityPolicy(t *testing.T) { } } +// TestDeleteTridentPodSecurityPolicy tests the DeleteTridentPodSecurityPolicy function +// It checks that the function returns the expected error when the k8s client returns an error +// It checks that the function returns nil when the k8s client returns no policies +// It checks that the function returns the expected error when the k8s client returns policies but fails to delete them +// It checks that the function returns nil when the k8s client returns policies and deletes them successfully +// Parameters: +// t *testing.T - go test handler +// Example: +// TestDeleteTridentPodSecurityPolicy(t) + func TestDeleteTridentPodSecurityPolicy(t *testing.T) { // arrange variables for the tests var emptyPSPList, unwantedPSPs []policyv1beta1.PodSecurityPolicy @@ -3479,6 +3835,14 @@ func TestDeleteTridentPodSecurityPolicy(t *testing.T) { } } +// TestRemoveMultiplePodSecurityPolicies tests the RemoveMultiplePodSecurityPolicies function +// It checks that the function returns the expected error when given a list of pod security policies +// It also checks that the function returns nil when given an empty list of pod security policies +// Parameters: +// t *testing.T - go test handler +// Example: +// TestRemoveMultiplePodSecurityPolicies(t) + func TestRemoveMultiplePodSecurityPolicies(t *testing.T) { // arrange variables for the tests var emptyPodSecurityPolicyList, undeletedPodSecurityPolicies, unwantedPodSecurityPolicies []policyv1beta1.PodSecurityPolicy @@ -3560,6 +3924,14 @@ func TestRemoveMultiplePodSecurityPolicies(t *testing.T) { } } +// TestGetSecretInformation tests the GetSecretInformation function +// It checks to make sure that the function returns the correct values +// for the current secret, unwanted secrets, create secret, and error +// Parameters: +// t *testing.T: go testing object that manages the test lifecycle +// Example: +// TestGetSecretInformation(t) + func TestGetSecretInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -3703,6 +4075,18 @@ func TestGetSecretInformation(t *testing.T) { } } +// TestPutSecret tests the PutSecret method +// It checks for the following conditions: +// - createSecret is true and no k8s error occurs +// - createSecret is false +// - createSecret is true and a k8s error occurs +// Parameters: +// createSecret: true if the Secret should be created, false if it should be updated +// newSecretYAML: the YAML for the Secret to be created or updated +// secretName: the name of the Secret to be created or updated +// Example: +// TestPutSecret(true, secretYAML, "test-secret") + func TestPutSecret(t *testing.T) { secretName := getProtocolSecretName() @@ -3797,6 +4181,16 @@ func TestPutSecret(t *testing.T) { } } +// TestDeleteTridentSecret tests the DeleteTridentSecret function +// It checks that the function returns an error when the k8s client returns an error +// It checks that the function returns nil when the k8s client returns no secrets +// It checks that the function returns an error when the k8s client returns secrets but fails to delete them +// It checks that the function returns nil when the k8s client returns secrets and deletes them successfully +// Parameters: +// t *testing.T: go test helper +// Example: +// TestDeleteTridentSecret(t) + func TestDeleteTridentSecret(t *testing.T) { // arrange variables for the tests var emptySecretList, unwantedSecrets []corev1.Secret @@ -3903,6 +4297,14 @@ func TestDeleteTridentSecret(t *testing.T) { } } +// TestRemoveMultipleSecrets tests the RemoveMultipleSecrets function +// It checks that the function returns the correct error when the k8s client returns an error +// It also checks that the function returns nil when the k8s client does not return an error +// Parameters: +// t *testing.T : go test helper +// Example: +// TestRemoveMultipleSecrets(t) + func TestRemoveMultipleSecrets(t *testing.T) { // arrange variables for the tests var emptySecretList, undeletedSecrets, unwantedSecrets []corev1.Secret @@ -3990,6 +4392,17 @@ func TestRemoveMultipleSecrets(t *testing.T) { } } +// TestGetServiceInformation tests the GetServiceInformation function +// It checks the following cases: +// - k8s error +// - no services found +// - valid current services found +// Parameters: +// - t: test object +// Example: +// - t := new(testing.T) +// - TestGetServiceInformation(t) + func TestGetServiceInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -4132,6 +4545,16 @@ func TestGetServiceInformation(t *testing.T) { } } +// TestPutService tests the PutService function +// It checks that the correct k8s client calls are made and that the correct errors are returned +// Parameters: +// currentService: the current service object +// createService: whether to create a new service or update an existing one +// newServiceYAML: the new service YAML +// appLabel: the app label +// Example: +// TestPutService(t, service, true, newServiceYAML, TridentCSILabel) + func TestPutService(t *testing.T) { serviceName := getServiceName() @@ -4271,6 +4694,15 @@ func TestPutService(t *testing.T) { } } +// TestDeleteTridentService tests the DeleteTridentService function +// It checks that the function returns the correct error when the +// k8s client returns an error, and that the function returns no error +// when the k8s client returns no error +// Parameters: +// t *testing.T : go test helper object +// Example: +// TestDeleteTridentService(t *testing.T) + func TestDeleteTridentService(t *testing.T) { // arrange variables for the tests var emptyServiceList, unwantedServices []corev1.Service @@ -4378,6 +4810,15 @@ func TestDeleteTridentService(t *testing.T) { } } +// TestRemoveMultipleServices tests the RemoveMultipleServices function +// It checks that the function returns the correct error when the k8s client +// returns an error and that it returns nil when the k8s client does not return +// an error +// Parameters: +// t *testing.T : go test helper +// Example: +// TestRemoveMultipleServices(t) + func TestRemoveMultipleServices(t *testing.T) { // arrange variables for the tests var emptyServiceList, unwantedServices []corev1.Service @@ -4456,6 +4897,16 @@ func TestRemoveMultipleServices(t *testing.T) { } } +// TestGetServiceAccountInformation tests the GetServiceAccountInformation function +// It checks for the following: +// 1. k8s error +// 2. no service accounts found +// 3. valid service accounts found +// Parameters: +// t *testing.T - go test framework object used for running the test +// Example: +// TestGetServiceAccountInformation(t *testing.T) + func TestGetServiceAccountInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -4622,6 +5073,17 @@ func TestGetServiceAccountInformation(t *testing.T) { } } +// TestPutServiceAccount tests the PutServiceAccount function +// It checks the following cases: +// - when creating a service account, it should return a new service account and no error +// - when creating a service account, it should return an error if a k8s error occurs +// - when updating a service account, it should return no new service account and no error +// - when updating a service account, it should return an error if a k8s error occurs +// Parameters: +// t *testing.T +// Example: +// TestPutServiceAccount(t) + func TestPutServiceAccount(t *testing.T) { serviceAccountName := getServiceAccountName(true) @@ -4785,6 +5247,15 @@ func TestPutServiceAccount(t *testing.T) { } } +// TestDeleteTridentServiceAccount tests the DeleteTridentServiceAccount function +// It checks that the function returns the expected error when the k8s client +// returns an error and that it returns nil when the k8s client does not return +// an error +// Parameters: +// t *testing.T: go testing framework object used to control test flow +// Example: +// TestDeleteTridentServiceAccount(t) + func TestDeleteTridentServiceAccount(t *testing.T) { // arrange variables for the tests var emptyServiceAccountList, unwantedServiceAccounts []corev1.ServiceAccount @@ -4892,6 +5363,14 @@ func TestDeleteTridentServiceAccount(t *testing.T) { } } +// TestRemoveMultipleServiceAccounts tests the RemoveMultipleServiceAccounts function +// It checks that the function returns the correct error codes and that the correct +// k8s calls are made +// Parameters: +// t *testing.T : go test handler +// Example: +// TestRemoveMultipleServiceAccounts(t *testing.T) + func TestRemoveMultipleServiceAccounts(t *testing.T) { // arrange variables for the tests var emptyServiceAccountList, undeletedServiceAccounts, unwantedServiceAccounts []corev1.ServiceAccount @@ -4979,6 +5458,17 @@ func TestRemoveMultipleServiceAccounts(t *testing.T) { } } +// TestGetTridentOpenShiftSCCInformation tests the GetTridentOpenShiftSCCInformation function +// It checks the following cases: +// - k8s error +// - no openshift scc found, no k8s error, and an scc user does not exist +// - no openshift scc found, no k8s error, and a it should update +// - valid current services found and no k8s error +// Parameters: +// t *testing.T: the test object +// Example: +// TestGetTridentOpenShiftSCCInformation(t *testing.T) + func TestGetTridentOpenShiftSCCInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var name, username string @@ -5124,6 +5614,16 @@ func TestGetTridentOpenShiftSCCInformation(t *testing.T) { } } +// TestExecPodForVersionInformation tests the ExecPodForVersionInformation function +// It checks the following cases: +// - no supplied cmd to exec +// - k8s error when exec the supplied cmd +// - no error when exec the supplied cmd +// Parameters: +// t *testing.T - go test handler +// Example: +// TestExecPodForVersionInformation(t *testing.T) + func TestExecPodForVersionInformation(t *testing.T) { podName := "trident-transient-pod" @@ -5218,6 +5718,23 @@ func TestExecPodForVersionInformation(t *testing.T) { } } +// TestGetCSISnapshotterVersion tests the GetCSISnapshotterVersion function +// It checks the following cases: +// 1. When the deployment is empty, it should return the snapshot CRD version +// 2. When the deployment has a snapshotter container with a version tag, it should return the snapshot CRD version +// 3. When the deployment has a snapshotter container without a version tag, it should return an empty string +// Parameters: +// deployment: The deployment to check +// Returns: +// string: The snapshot CRD version +// Example: +// snapshotCRDName := GetCSISnapshotterVersion(deployment) +// if snapshotCRDName == "" { +// fmt.Println("Snapshot CRD name is empty") +// } else { +// fmt.Println("Snapshot CRD name is: " + snapshotCRDName) +// } + func TestGetCSISnapshotterVersion(t *testing.T) { var emptyDeployment, validDeployment, invalidDeployment *appsv1.Deployment @@ -5299,6 +5816,18 @@ func TestGetCSISnapshotterVersion(t *testing.T) { } } +// TestDeleteTridentStatefulSet tests the DeleteTridentStatefulSet function +// It checks that the correct error is returned when the k8s client returns an error +// It also checks that the correct error is returned when the k8s client returns no statefulsets +// It also checks that the correct error is returned when the k8s client returns statefulsets but +// the delete fails +// It also checks that no error is returned when the k8s client returns statefulsets and +// the delete succeeds +// Parameters: +// t *testing.T +// Example: +// TestDeleteTridentStatefulSet(t) + func TestDeleteTridentStatefulSet(t *testing.T) { // arrange variables for the tests var emptyStatefulSets, unwantedStatefulSets []appsv1.StatefulSet @@ -5381,6 +5910,37 @@ func TestDeleteTridentStatefulSet(t *testing.T) { } } +// TestPutOpenShiftSCC tests the PutOpenShiftSCC function +// It checks the following cases: +// - create OpenShift SCCs and no k8s error occurs when removing Trident users from OpenShiftSCC +// - create OpenShift SCCs and a k8s error occurs when removing Trident users from OpenShiftSCC +// - create OpenShift SCCs and no k8s error occurs +// - create OpenShift SCCs and a k8s error occurs +// - update OpenShift SCCs and no k8s error occurs +// - update OpenShift SCCs and a k8s error occurs +// Parameters: +// currentOpenShiftSCCJSON: the current OpenShift SCC in JSON format +// createOpenShiftSCC: whether to create or update the OpenShift SCC +// newOpenShiftSCCYAML: the new OpenShift SCC in YAML format +// Example: +// currentOpenShiftSCCJSON, err := yaml.YAMLToJSON([]byte(k8sclient.GetOpenShiftSCCYAML( +// openShiftSCCUserName+"old", +// openShiftSCCName+"old", +// "trident", +// make(map[string]string), +// make(map[string]string)), +// )) +// if err != nil { +// t.Fatal("GetOpenShiftSCCYAML() returned invalid YAML") +// } +// newOpenShiftSCCYAML := k8sclient.GetOpenShiftSCCYAML( +// openShiftSCCUserName, +// openShiftSCCName, +// "trident", +// make(map[string]string), +// make(map[string]string)) +// err = extendedK8sClient.PutOpenShiftSCC(currentOpenShiftSCCJSON, createOpenShiftSCC, newOpenShiftSCCYAML) + func TestPutOpenShiftSCC(t *testing.T) { // arrange variables for the tests openShiftSCCUserName := getOpenShiftSCCUserName() @@ -5574,6 +6134,16 @@ func TestPutOpenShiftSCC(t *testing.T) { } } +// TestDeleteOpenShiftSCC tests the DeleteOpenShiftSCC function +// It checks the following cases: +// 1. GetOpenShiftSCCByName fails +// 2. GetOpenShiftSCCByName succeeds but DeleteObjectByYAML fails +// 3. GetOpenShiftSCCByName succeeds and RemoveTridentUserFromOpenShiftSCC is called +// Parameters: +// t *testing.T - the test object +// Example: +// TestDeleteOpenShiftSCC(t *testing.T) + func TestDeleteOpenShiftSCC(t *testing.T) { // arrange variables for the tests openShiftSCCName := "trident" @@ -5667,6 +6237,16 @@ func TestDeleteOpenShiftSCC(t *testing.T) { } } +// TestRemoveMultiplePods tests the RemoveMultiplePods function +// It checks the following cases: +// - no pods to delete +// - k8s call error +// - valid pods +// Parameters: +// t *testing.T : go test framework object +// Example: +// TestRemoveMultiplePods(t) + func TestRemoveMultiplePods(t *testing.T) { // arrange variables for the tests var emptyPodList, undeletedPods, unwantedPods []corev1.Pod @@ -5754,6 +6334,16 @@ func TestRemoveMultiplePods(t *testing.T) { } } +// TestRemoveMultipleStatefulSets tests the RemoveMultipleStatefulSets function +// It checks the following cases: +// 1. No stateful sets to remove +// 2. Error from k8s call +// 3. Successful removal of stateful sets +// Parameters: +// t *testing.T : go test helper +// Example: +// TestRemoveMultipleStatefulSets(t) + func TestRemoveMultipleStatefulSets(t *testing.T) { // arrange variables for the tests var emptyStatefulSetList, unwantedStatefulSets []appsv1.StatefulSet diff --git a/operator/controllers/orchestrator/installer/uninstaller.go b/operator/controllers/orchestrator/installer/uninstaller.go index e70682883..4fd8be595 100644 --- a/operator/controllers/orchestrator/installer/uninstaller.go +++ b/operator/controllers/orchestrator/installer/uninstaller.go @@ -11,6 +11,14 @@ import ( k8sclient "github.com/netapp/trident/cli/k8s_client" ) +// UninstallTrident uninstalls Trident from the Kubernetes cluster. +// It returns an error if the uninstallation fails. +// Example: +// err := installer.UninstallTrident() +// if err != nil { +// log.Errorf("Could not uninstall Trident: %v", err) +// } + func (i *Installer) UninstallTrident() error { // 1. preview CSI Trident --> uninstall preview CSI Trident @@ -107,6 +115,14 @@ func (i *Installer) UninstallTrident() error { return nil } +// UninstallCSIPreviewTrident uninstalls Trident CSI Preview +// It returns an error if the uninstall fails. +// Example: +// err := installer.UninstallCSIPreviewTrident() +// if err != nil { +// panic(err) +// } + func (i *Installer) UninstallCSIPreviewTrident() error { appLabel = TridentCSILabel appLabelKey = TridentCSILabelKey @@ -115,6 +131,11 @@ func (i *Installer) UninstallCSIPreviewTrident() error { return i.client.DeleteTridentStatefulSet(appLabel) } +// UninstallLegacyTrident uninstalls legacy Trident +// It returns an error if the uninstall fails. +// Example: +// err := installer.UninstallLegacyTrident() + func (i *Installer) UninstallLegacyTrident() error { appLabel = TridentLegacyLabel appLabelKey = TridentLegacyLabelKey @@ -159,6 +180,14 @@ func (i *Installer) removeRBACObjects(csi bool) error { return nil } +// ObliviateCRDs removes all Trident CRDs from the cluster. +// It returns an error if the CRDs cannot be removed. +// Example: +// err := installer.ObliviateCRDs() +// if err != nil { +// log.Fatalf("Could not remove Trident CRDs: %v", err) +// } + func (i *Installer) ObliviateCRDs() error { return cmd.ObliviateCRDs(i.client, i.tridentCRDClient, k8sTimeout) } diff --git a/operator/controllers/orchestrator/installer/utils.go b/operator/controllers/orchestrator/installer/utils.go index f5f1d75bc..1ba9e3a96 100644 --- a/operator/controllers/orchestrator/installer/utils.go +++ b/operator/controllers/orchestrator/installer/utils.go @@ -1,5 +1,13 @@ package installer +// getServiceAccountName returns the name of the service account to use for Trident +// Parameters: +// csi - if true, use the Trident CSI service account name; otherwise, use the legacy Trident service account name +// Example: +// getServiceAccountName(true) +// Returns: +// string - the service account name to use for Trident + func getServiceAccountName(csi bool) string { if csi { return TridentCSI @@ -8,6 +16,14 @@ func getServiceAccountName(csi bool) string { } } +// getClusterRoleName returns the name of the cluster role to use for the given CSI flag +// Parameters: +// csi - true if Trident should use the CSI driver +// Returns: +// string - the name of the cluster role to use +// Example: +// name := getClusterRoleName(true) + func getClusterRoleName(csi bool) string { if csi { return TridentCSI @@ -16,6 +32,13 @@ func getClusterRoleName(csi bool) string { } } +// getClusterRoleBindingName returns the name of the cluster role binding to use +// Parameters: +// csi - true if Trident should use the CSI driver +// Example: +// getClusterRoleBindingName(true) +// returns "trident-csi" + func getClusterRoleBindingName(csi bool) string { if csi { return TridentCSI @@ -24,22 +47,50 @@ func getClusterRoleBindingName(csi bool) string { } } +// getPSPName returns the name of the PSP to use for Trident +// Example: +// trident-psp + func getPSPName() string { return TridentPSP } +// getServiceName returns the name of the service +// Example: +// kubectl get service +// NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE +// trident-csi NodePort 10.100.200.1 8080/TCP 1d + func getServiceName() string { return TridentCSI } +// getProtocolSecretName returns the name of the secret that contains the protocol +// information for the Trident CSI driver. +// Example: +// trident-csi-secret + func getProtocolSecretName() string { return TridentCSI } +// getEncryptionSecretName returns the name of the encryption secret +// Example: +// getEncryptionSecretName() +// -> "trident-encryption-keys" + func getEncryptionSecretName() string { return TridentEncryptionKeys } +// getDeploymentName returns the name of the Trident deployment +// Parameters: +// csi - true if the deployment is for the CSI driver +// Returns: +// string - the name of the Trident deployment +// Example: +// deploymentName := getDeploymentName(true) + func getDeploymentName(csi bool) string { if csi { return TridentCSI @@ -48,14 +99,28 @@ func getDeploymentName(csi bool) string { } } +// getDaemonSetName returns the name of the Trident CSI DaemonSet. +// Example: +// - trident-csi + func getDaemonSetName() string { return TridentCSI } +// getCSIDriverName returns the name of the CSI driver +// Example: +// getCSIDriverName() returns "trident" + func getCSIDriverName() string { return CSIDriver } +// getOpenShiftSCCUserName returns the name of the SCC user that Trident should be +// added to. +// Example: +// TridentCSI +// TridentLegacy + func getOpenShiftSCCUserName() string { if csi { return TridentCSI @@ -64,6 +129,10 @@ func getOpenShiftSCCUserName() string { } } +// getOpenShiftSCCName returns the name of the OpenShift SCC +// Example: +// getOpenShiftSCCName() -> "privileged" + func getOpenShiftSCCName() string { return OpenShiftSCCName } diff --git a/operator/controllers/provisioner/apis/netapp/v1/register.go b/operator/controllers/provisioner/apis/netapp/v1/register.go index bdcc4c5c0..ce9b955f1 100644 --- a/operator/controllers/provisioner/apis/netapp/v1/register.go +++ b/operator/controllers/provisioner/apis/netapp/v1/register.go @@ -30,6 +30,17 @@ var ( ) // Adds the list of known types to the given scheme. +// addKnownTypes adds the set of types defined in this +// Parameters: +// scheme *runtime.Scheme +// +// Returns: +// error +// +// It returns an error if there was an issue with adding the types. +// Example: +// addKnownTypes(s) + func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &TridentProvisioner{}, diff --git a/operator/controllers/provisioner/client/clientset/versioned/fake/clientset_generated.go b/operator/controllers/provisioner/client/clientset/versioned/fake/clientset_generated.go index f2d4769ac..164d56e68 100644 --- a/operator/controllers/provisioner/client/clientset/versioned/fake/clientset_generated.go +++ b/operator/controllers/provisioner/client/clientset/versioned/fake/clientset_generated.go @@ -52,10 +52,27 @@ type Clientset struct { tracker testing.ObjectTracker } +// Discovery retrieves the DiscoveryClient +// It returns a fake DiscoveryClient +// Example: +// clientset := fake.NewSimpleClientset() +// clientset.Discovery().RESTClient() + func (c *Clientset) Discovery() discovery.DiscoveryInterface { return c.discovery } +// Tracker is a fake implementation of the Tracker interface +type Tracker struct { + objects map[string]interface{} +} + +// NewTracker returns a new Tracker +// It returns a pointer to the Tracker +// Example: +// tracker := NewTracker() +// tracker.Add("foo", "bar") + func (c *Clientset) Tracker() testing.ObjectTracker { return c.tracker } diff --git a/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go b/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go index 59fa6e60d..18dc72689 100644 --- a/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go +++ b/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go @@ -14,6 +14,17 @@ type FakeTridentV1 struct { *testing.Fake } +// TridentProvisioners implements TridentProvisionerInterface +type FakeTridentProvisioners struct { + *FakeTridentV1 + namespace string +} +// Parameters: +// namespace - name of the Namespace +// It returns a TridentProvisionerInterface +// Example: +// tridentProvisioners, err := client.TridentV1().TridentProvisioners("default") + func (c *FakeTridentV1) TridentProvisioners(namespace string) v1.TridentProvisionerInterface { return &FakeTridentProvisioners{c, namespace} } diff --git a/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/netapp_client.go b/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/netapp_client.go index 832d7ecd9..464fdd9aa 100644 --- a/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/netapp_client.go +++ b/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/netapp_client.go @@ -20,6 +20,12 @@ type TridentV1Client struct { restClient rest.Interface } +// TridentProvisioners returns a TridentProvisionerInterface. +// Parameters: +// namespace - the namespace where Trident is installed +// Example: +// tridentProvisioners := tridentV1Client.TridentProvisioners("trident") + func (c *TridentV1Client) TridentProvisioners(namespace string) TridentProvisionerInterface { return newTridentProvisioners(c, namespace) } @@ -52,6 +58,17 @@ func New(c rest.Interface) *TridentV1Client { return &TridentV1Client{c} } +// setConfigDefaults sets the default values for the provided config +// Parameters: +// config - config to set defaults on +// It returns an error if the config is nil +// Example: +// config := k8sclient.NewConfig() +// err := setConfigDefaults(config) +// if err != nil { +// // handle error +// } + func setConfigDefaults(config *rest.Config) error { gv := v1.SchemeGroupVersion config.GroupVersion = &gv diff --git a/operator/controllers/provisioner/client/informers/externalversions/factory.go b/operator/controllers/provisioner/client/informers/externalversions/factory.go index 4a863e53d..f88a9e68f 100644 --- a/operator/controllers/provisioner/client/informers/externalversions/factory.go +++ b/operator/controllers/provisioner/client/informers/externalversions/factory.go @@ -130,6 +130,29 @@ func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[ref // InternalInformerFor returns the SharedIndexInformer for obj using an internal // client. +// InformerFor is the same as InformerFor without the lock. +// Parameters: +// obj - the object type to register the informer for +// newFunc - a function that returns a new informer for the given type +// resyncPeriod - resync period for the informer +// It returns the registered SharedIndexInformer for the given type. +// Example: +// lister := factory.InformerFor(&v1.Pod{}, func(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { +// return cache.NewSharedIndexInformer( +// &cache.ListWatch{ +// ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { +// return client.CoreV1().Pods(metav1.NamespaceAll).List(options) +// }, +// WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { +// return client.CoreV1().Pods(metav1.NamespaceAll).Watch(options) +// }, +// }, +// &v1.Pod{}, +// resyncPeriod, +// cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, +// ) +// }, 0) + func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { f.lock.Lock() defer f.lock.Unlock() @@ -161,6 +184,11 @@ type SharedInformerFactory interface { Trident() netapp.Interface } +// Trident returns a new Interface. +// Example: +// f := externalversions.NewSharedInformerFactory(cSharedClient, resyncPeriod) +// i := f.Trident().V1alpha1().Tridents() + func (f *sharedInformerFactory) Trident() netapp.Interface { return netapp.New(f, f.namespace, f.tweakListOptions) } diff --git a/operator/controllers/provisioner/client/informers/externalversions/netapp/v1/tridentprovisioner.go b/operator/controllers/provisioner/client/informers/externalversions/netapp/v1/tridentprovisioner.go index 766e4c0f4..1587fbca3 100644 --- a/operator/controllers/provisioner/client/informers/externalversions/netapp/v1/tridentprovisioner.go +++ b/operator/controllers/provisioner/client/informers/externalversions/netapp/v1/tridentprovisioner.go @@ -63,14 +63,74 @@ func NewFilteredTridentProvisionerInformer(client versioned.Interface, namespace ) } +// defaultInformer is used to informer for TridentProvisioner types. +type tridentProvisionerInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewTridentProvisionerInformer constructs a new informer for TridentProvisioner type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +// Parameters: +// namespace: The namespace of the TridentProvisioner. +// resyncPeriod: The resync period to use for this informer. +// tweakListOptions: The tweak list options for this informer. +// It returns a new informer for TridentProvisioner type. +// Example: +// // create the informer for TridentProvisioner +// informer := v1.NewTridentProvisionerInformer( +// kubeClient, +// resyncPeriod, +// cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, +// ) + func (f *tridentProvisionerInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { return NewFilteredTridentProvisionerInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) } +// Informer is used to fetch and store TridentProvisioner objects from the API server. +type TridentProvisionerInformer interface { + Informer() cache.SharedIndexInformer + Lister() *TridentProvisionerLister +} + +type tridentProvisionerInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewTridentProvisionerInformer constructs a new informer for TridentProvisioner type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +// It returns a TridentProvisionerInformer. +// Example: +// // obtain a shared informer for the deployment object +// deploymentInformer := NewTridentProvisionerInformer(client, namespace) +// // obtain a shared informer for the pod object +// podInformer := NewTridentProvisionerInformer(client, namespace) + func (f *tridentProvisionerInformer) Informer() cache.SharedIndexInformer { return f.factory.InformerFor(&netappv1.TridentProvisioner{}, f.defaultInformer) } +// Lister implements the TridentProvisionerLister interface. +type tridentProvisionerInformer struct { + factory InternalInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewTridentProvisionerInformer constructs a new informer for TridentProvisioner type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +// It returns a TridentProvisionerInformer. +// Example: +// lis, err := factory.NetAppV1().TridentProvisioners().Lister() +// ... +// lis.List(namespace).Items + func (f *tridentProvisionerInformer) Lister() v1.TridentProvisionerLister { return v1.NewTridentProvisionerLister(f.Informer().GetIndexer()) } From 1c46a7146a18b9695eb9e84bacc5dc42bf97425f Mon Sep 17 00:00:00 2001 From: "Roussin, Jerome" Date: Thu, 12 May 2022 15:52:52 -0400 Subject: [PATCH 2/5] Added doc for utils/ tree --- utils/crypto.go | 87 +++++++ utils/crypto_test.go | 20 ++ utils/errors.go | 497 +++++++++++++++++++++++++++++++----- utils/errors_test.go | 7 + utils/k8s_utils.go | 42 +++ utils/k8s_utils_test.go | 9 + utils/locks_test.go | 61 +++++ utils/osutils.go | 351 +++++++++++++++++++++++++ utils/osutils_darwin.go | 153 +++++++++++ utils/osutils_linux.go | 143 +++++++++++ utils/osutils_linux_test.go | 21 ++ utils/osutils_test.go | 42 +++ utils/utils.go | 190 ++++++++++++++ utils/utils_test.go | 181 +++++++++++++ utils/version.go | 90 +++++++ utils/version_test.go | 55 ++++ 16 files changed, 1889 insertions(+), 60 deletions(-) diff --git a/utils/crypto.go b/utils/crypto.go index 9624c546f..bc37ee207 100644 --- a/utils/crypto.go +++ b/utils/crypto.go @@ -36,6 +36,19 @@ type CertInfo struct { // the parameters are configurable...the serial numbers and principal names are // hardcoded, the validity period is hardcoded to 1970-2070, and the algorithm // and key size are hardcoded to 521-bit elliptic curve. +// MakeHTTPCertInfo creates a CA, server, and client certificate for use with HTTPS +// It returns a CertInfo struct with the base64 encoded certificates and keys +// Parameters: +// caCertName: The name to use for the CA certificate +// serverCertName: The name to use for the server certificate +// clientCertName: The name to use for the client certificate +// Returns: +// *CertInfo: A struct with the base64 encoded certificates and keys +// error: An error if one occurred +// Example: +// certInfo, err := MakeHTTPCertInfo("my-ca", "my-server", "my-client") +// +// -- Doc autogenerated on 2022-05-12 14:15:35.781744 -- func MakeHTTPCertInfo(caCertName, serverCertName, clientCertName string) (*CertInfo, error) { certInfo := &CertInfo{} @@ -155,6 +168,21 @@ func MakeHTTPCertInfo(caCertName, serverCertName, clientCertName string) (*CertI return certInfo, nil } +// makeSubject creates a pkix.Name for the given common name +// It returns a pkix.Name with the following fields: +// Country: []string{"US"} +// Locality: []string{"RTP"} +// Organization: []string{"NetApp"} +// Province: []string{"NC"} +// CommonName: cn +// Parameters: +// cn: the common name to use +// Returns: +// a pkix.Name with the above fields +// Example: +// makeSubject("test") +// +// -- Doc autogenerated on 2022-05-12 14:15:35.781744 -- func makeSubject(cn string) pkix.Name { return pkix.Name{ Country: []string{"US"}, @@ -165,6 +193,18 @@ func makeSubject(cn string) pkix.Name { } } +// makeSerial creates a random serial number for a certificate +// It returns a big.Int and an error +// Returns: +// *big.Int: the serial number +// error: if any +// Example: +// serial, err := makeSerial() +// if nil != err { +// // handle error +// } +// +// -- Doc autogenerated on 2022-05-12 14:15:35.781744 -- func makeSerial() (*big.Int, error) { maxSerial := big.NewInt(math.MaxInt64) serial, err := rand.Int(rand.Reader, maxSerial) @@ -174,6 +214,24 @@ func makeSerial() (*big.Int, error) { return serial, nil } +// keyToBase64String converts an ECDSA private key to a base64 encoded string +// It returns an error if the key cannot be marshaled +// Parameters: +// key - the ECDSA private key to convert +// Returns: +// string - the base64 encoded string +// error - any error encountered +// Example: +// key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader) +// if err != nil { +// return +// } +// keyString, err := keyToBase64String(key) +// if err != nil { +// return +// } +// +// -- Doc autogenerated on 2022-05-12 14:15:35.781744 -- func keyToBase64String(key *ecdsa.PrivateKey) (string, error) { b, err := x509.MarshalECPrivateKey(key) if err != nil { @@ -183,6 +241,20 @@ func keyToBase64String(key *ecdsa.PrivateKey) (string, error) { return base64.StdEncoding.EncodeToString(keyBytes), nil } +// certToBase64String converts a DER encoded certificate to a base64 encoded string +// It returns an empty string if the input is not a valid DER encoded certificate +// Parameters: +// derBytes: DER encoded certificate +// Returns: +// base64 encoded string +// Example: +// derBytes, err := ioutil.ReadFile("cert.der") +// if err != nil { +// return err +// } +// base64Cert := certToBase64String(derBytes) +// +// -- Doc autogenerated on 2022-05-12 14:15:35.781744 -- func certToBase64String(derBytes []byte) string { certBytes := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) return base64.StdEncoding.EncodeToString(certBytes) @@ -279,6 +351,21 @@ func PKCS7Pad(input []byte, blockSize int) []byte { } // PKCS7Pad will remove the padding from input according to PKCS#7 standard +// PKCS7Unpad removes the padding from the input. +// It returns an error if the padding is invalid. +// Parameters: +// input - the input to be unpadded +// Returns: +// the unpadded input +// an error if the padding is invalid +// Example: +// input := []byte("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") +// unpadded, err := PKCS7Unpad(input) +// if err != nil { +// panic("bad padding") +// } +// +// -- Doc autogenerated on 2022-05-12 14:15:35.781744 -- func PKCS7Unpad(input []byte) ([]byte, error) { inputLength := len(input) paddingLength := int(input[inputLength-1]) diff --git a/utils/crypto_test.go b/utils/crypto_test.go index e26264483..57b434ec2 100644 --- a/utils/crypto_test.go +++ b/utils/crypto_test.go @@ -8,6 +8,11 @@ import ( "testing" ) +// TestGenerateAESKey tests the GenerateAESKey function +// It checks that the key is 32 bytes long, and that it is base64-encoded. +// It also checks that the key is random by generating two keys and comparing them. +// +// -- Doc autogenerated on 2022-05-12 14:17:58.986546 -- func TestGenerateAESKey(t *testing.T) { var ( key1, key2 string @@ -39,6 +44,11 @@ func TestGenerateAESKey(t *testing.T) { } } +// TestEncryptStringWithAES tests the EncryptStringWithAES and DecryptStringWithAES functions. +// It checks that the returned string is base64-encoded, and that the decrypted string matches +// the original string. +// +// -- Doc autogenerated on 2022-05-12 14:17:58.986546 -- func TestEncryptStringWithAES(t *testing.T) { var ( encodedKey, encryptedText, decryptedText string @@ -107,6 +117,11 @@ func TestEncryptStringWithAES(t *testing.T) { } } +// TestPKCS7Pad tests the PKCS7Pad function +// It checks that padding is added, that the padded result is a multiple of the block size, +// that the pad bytes are correct, and that the padding can be removed +// +// -- Doc autogenerated on 2022-05-12 14:17:58.986546 -- func TestPKCS7Pad(t *testing.T) { blockSize := 16 // aes block size is 16 inputSizes := []int{ @@ -148,6 +163,11 @@ func TestPKCS7Pad(t *testing.T) { } } +// TestBigIntHash tests the bigIntHash function +// It checks that the function returns a hash that is different from the input +// and that it returns different hashes for different inputs +// +// -- Doc autogenerated on 2022-05-12 14:17:58.986546 -- func TestBigIntHash(t *testing.T) { var n big.Int h, err := bigIntHash(&n) diff --git a/utils/errors.go b/utils/errors.go index 90804971e..03ba98d21 100644 --- a/utils/errors.go +++ b/utils/errors.go @@ -15,15 +15,34 @@ import ( type bootstrapError struct { message string } - -func (e *bootstrapError) Error() string { return e.message } - +// BootstrapError is a special error +// It returns a string with the error message +// and is used to indicate that Trident failed to initialize +// Parameters: +// err - the error message +// Returns: +// a bootstrapError +// Example: +// err := utils.BootstrapError(errors.New("Something went wrong")) +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func BootstrapError(err error) error { return &bootstrapError{ fmt.Sprintf("Trident initialization failed; %s", err.Error()), } } +// IsBootstrapError returns true if the error is a bootstrap error +// Parameters: +// err: error +// Returns: +// true if the error is a bootstrap error +// Example: +// if IsBootstrapError(err) { +// // do stuff +// } +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsBootstrapError(err error) bool { if err == nil { return false @@ -39,13 +58,32 @@ func IsBootstrapError(err error) bool { type foundError struct { message string } - -func (e *foundError) Error() string { return e.message } - +// FoundError is an error +// It returns true for IsFoundError +// Parameters: +// message - the error message +// Return: +// error - the error +// Example: +// err := FoundError("found") +// if IsFoundError(err) { +// // handle found error +// } +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func FoundError(message string) error { return &foundError{message} } +// IsFoundError returns true if the error is a foundError +// Parameters: +// err: the error to check +// Returns: +// true if the error is a foundError, false otherwise +// Example: +// isFound := utils.IsFoundError(err) +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsFoundError(err error) bool { if err == nil { return false @@ -61,13 +99,31 @@ func IsFoundError(err error) bool { type notFoundError struct { message string } - -func (e *notFoundError) Error() string { return e.message } - +// NotFoundError is a custom error +// It returns a 404 status code +// Parameters: +// message - the message to return +// Returns: +// error - the error +// Example: +// err := NotFoundError("The requested volume does not exist") +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func NotFoundError(message string) error { return ¬FoundError{message} } +// IsNotFoundError returns true if the error is a not found error +// Parameters: +// err: the error to check +// Returns: +// true if the error is a not found error +// Example: +// if utils.IsNotFoundError(err) { +// // handle error +// } +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsNotFoundError(err error) bool { if err == nil { return false @@ -80,6 +136,15 @@ func IsNotFoundError(err error) bool { // resourceNotFoundError - To identify external not found errors // /////////////////////////////////////////////////////////////////////////// +// IsResourceNotFoundError returns true if the error is a resource not found error +// Parameters: +// err: the error to check +// Returns: +// true if the error is a resource not found error +// Example: +// IsResourceNotFoundError(errors.New("Not Found")) +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsResourceNotFoundError(err error) bool { if err == nil { return false @@ -94,15 +159,31 @@ func IsResourceNotFoundError(err error) bool { type notReadyError struct { message string } - -func (e *notReadyError) Error() string { return e.message } - +// NotReadyError is returned when Trident is initializing. +// It returns a string that can be used in an HTTP response. +// Returns: +// *notReadyError +// Example: +// if err := utils.NotReadyError(); err != nil { +// return err +// } +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func NotReadyError() error { return ¬ReadyError{ "Trident is initializing, please try again later", } } +// IsNotReadyError returns true if the error is a not ready error +// Parameters: +// err - error to check +// Returns: +// true if the error is a not ready error +// Example: +// utils.IsNotReadyError(err) +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsNotReadyError(err error) bool { if err == nil { return false @@ -118,13 +199,30 @@ func IsNotReadyError(err error) bool { type unsupportedError struct { message string } - -func (e *unsupportedError) Error() string { return e.message } - +// UnsupportedError is an error that indicates that a feature is not supported. +// It returns a string that can be used to display the error to the user. +// Parameters: +// message - the error message +// Returns: +// an error object +// Example: +// err := utils.UnsupportedError("This feature is not supported") +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func UnsupportedError(message string) error { return &unsupportedError{message} } +// IsUnsupportedError returns true if the error is an unsupportedError +// Parameters: +// err - the error to check +// Returns: +// true if the error is an unsupportedError +// Example: +// err := utils.UnsupportedError("test") +// utils.IsUnsupportedError(err) // returns true +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsUnsupportedError(err error) bool { if err == nil { return false @@ -140,13 +238,31 @@ func IsUnsupportedError(err error) bool { type volumeCreatingError struct { message string } - -func (e *volumeCreatingError) Error() string { return e.message } - +// VolumeCreatingError is an error +// It returns a message +// Parameters: +// message string +// Returns: +// error +// Example: +// myError := utils.VolumeCreatingError("error message") +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func VolumeCreatingError(message string) error { return &volumeCreatingError{message} } +// IsVolumeCreatingError returns true if the error is a volumeCreatingError +// Parameters: +// err - the error to check +// Return: +// true if the error is a volumeCreatingError +// Example: +// if IsVolumeCreatingError(err) { +// // do something +// } +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsVolumeCreatingError(err error) bool { if err == nil { return false @@ -162,13 +278,29 @@ func IsVolumeCreatingError(err error) bool { type volumeDeletingError struct { message string } - -func (e *volumeDeletingError) Error() string { return e.message } - +// VolumeDeletingError is an error +// It returns the message +// Parameters: +// message string +// Returns: +// error +// Example: +// err := utils.VolumeDeletingError("message") +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func VolumeDeletingError(message string) error { return &volumeDeletingError{message} } +// IsVolumeDeletingError returns true if the error is a volumeDeletingError +// Parameters: +// err - the error to check +// Returns: +// true if the error is a volumeDeletingError +// Example: +// IsVolumeDeletingError(err) +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsVolumeDeletingError(err error) bool { if err == nil { return false @@ -184,13 +316,30 @@ func IsVolumeDeletingError(err error) bool { type timeoutError struct { message string } - -func (e *timeoutError) Error() string { return e.message } - +// TimeoutError is a custom error +// It returns a string message +// Parameters: +// message string +// Return: +// error +// Example: +// err := utils.TimeoutError("My error message") +// fmt.Println(err) +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func TimeoutError(message string) error { return &timeoutError{message} } +// IsTimeoutError returns true if the error is a timeout error +// Parameters: +// err: the error to check +// Returns: +// true if the error is a timeout error +// Example: +// IsTimeoutError(errors.New("timeout")) +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsTimeoutError(err error) bool { if err == nil { return false @@ -206,15 +355,36 @@ func IsTimeoutError(err error) bool { type unsupportedKubernetesVersionError struct { message string } - -func (e *unsupportedKubernetesVersionError) Error() string { return e.message } - +// UnsupportedKubernetesVersionError is returned when the Kubernetes version is not supported +// It returns a string that can be used to display the error message +// Parameters: +// err: the error message +// Returns: +// error: the error message +// Example: +// err := utils.UnsupportedKubernetesVersionError(err) +// if err != nil { +// return fmt.Errorf("%s", err) +// } +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func UnsupportedKubernetesVersionError(err error) error { return &unsupportedKubernetesVersionError{ message: fmt.Sprintf("unsupported Kubernetes version; %s", err.Error()), } } +// IsUnsupportedKubernetesVersionError returns true if the error is an unsupportedKubernetesVersionError +// Parameters: +// err - the error to check +// Return: +// true if the error is an unsupportedKubernetesVersionError, false otherwise +// Example: +// if IsUnsupportedKubernetesVersionError(err) { +// log.Error("Unsupported Kubernetes version") +// } +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsUnsupportedKubernetesVersionError(err error) bool { if err == nil { return false @@ -230,15 +400,33 @@ func IsUnsupportedKubernetesVersionError(err error) bool { type reconcileDeferredError struct { message string } - -func (e *reconcileDeferredError) Error() string { return e.message } - +// ReconcileDeferredError is an error +// It returns a message and a boolean +// Parameters: +// err - the error to return +// Returns: +// the error +// Example: +// err := utils.ReconcileDeferredError(errors.New("Some error")) +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func ReconcileDeferredError(err error) error { return &reconcileDeferredError{ message: err.Error(), } } +// IsReconcileDeferredError returns true if the error is a ReconcileDeferredError +// Parameters: +// err - error to check +// Return: +// true if the error is a ReconcileDeferredError, false otherwise +// Example: +// if utils.IsReconcileDeferredError(err) { +// // ... +// } +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsReconcileDeferredError(err error) bool { if err == nil { return false @@ -254,21 +442,49 @@ func IsReconcileDeferredError(err error) bool { type reconcileIncompleteError struct { message string } - -func (e *reconcileIncompleteError) Error() string { return e.message } - +// ReconcileIncompleteError is an error that indicates that a reconciliation is not complete. +// It returns true for IsReconcileIncompleteError. +// Returns: +// true +// Example: +// if err := reconciler.Reconcile(request); err != nil && IsReconcileIncompleteError(err) { +// return reconcile.Result{}, nil +// } +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func ReconcileIncompleteError() error { return &reconcileIncompleteError{ message: "reconcile incomplete", } } +// ConvertToReconcileIncompleteError converts an error to a reconcileIncompleteError +// It returns the original error if it is already a reconcileIncompleteError +// Parameters: +// err: the error to convert +// Returns: +// the converted error +// Example: +// reconcileIncompleteError := ConvertToReconcileIncompleteError(err) +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func ConvertToReconcileIncompleteError(err error) error { return &reconcileIncompleteError{ message: err.Error(), } } +// IsReconcileIncompleteError returns true if the error is a reconcileIncompleteError +// Parameters: +// err - the error to check +// Returns: +// true if the error is a reconcileIncompleteError, false otherwise +// Example: +// if IsReconcileIncompleteError(err) { +// log.Errorf("reconcile error: %v", err) +// } +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsReconcileIncompleteError(err error) bool { if err == nil { return false @@ -284,15 +500,36 @@ func IsReconcileIncompleteError(err error) bool { type reconcileFailedError struct { message string } - -func (e *reconcileFailedError) Error() string { return e.message } - +// ReconcileFailedError is an error that is returned when a reconcile fails. +// It returns a message that includes the error that caused the reconcile to fail. +// Parameters: +// err - the error that caused the reconcile to fail +// Returns: +// a new error that includes the error that caused the reconcile to fail +// Example: +// if err := r.Reconcile(request); err != nil { +// return utils.ReconcileFailedError(err) +// } +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func ReconcileFailedError(err error) error { return &reconcileFailedError{ message: fmt.Sprintf("reconcile failed; %s", err.Error()), } } +// IsReconcileFailedError returns true if the error is a reconcileFailedError +// Parameters: +// err: the error to check +// Returns: +// true if the error is a reconcileFailedError +// Example: +// _, err := utils.ReconcileFailedError() +// if utils.IsReconcileFailedError(err) { +// ... +// } +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsReconcileFailedError(err error) bool { if err == nil { return false @@ -308,15 +545,32 @@ func IsReconcileFailedError(err error) bool { type unsupportedConfigError struct { message string } - -func (e *unsupportedConfigError) Error() string { return e.message } - +// UnsupportedConfigError returns an error indicating that the provided configuration is not supported +// Parameters: +// err - the error to wrap +// Returns: +// an error indicating that the provided configuration is not supported +// Example: +// err := utils.UnsupportedConfigError(errors.New("custom error message")) +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func UnsupportedConfigError(err error) error { return &unsupportedConfigError{ message: fmt.Sprintf("unsupported configuration; %s", err.Error()), } } +// IsUnsupportedConfigError returns true if the error is an unsupportedConfigError. +// Parameters: +// err: the error to check +// Returns: +// true if the error is an unsupportedConfigError +// Example: +// if utils.IsUnsupportedConfigError(err) { +// ... +// } +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsUnsupportedConfigError(err error) bool { if err == nil { return false @@ -332,15 +586,33 @@ func IsUnsupportedConfigError(err error) bool { type tempOperatorError struct { message string } - -func (e *tempOperatorError) Error() string { return e.message } - +// TempOperatorError returns a temporary operator error +// Parameters: +// err - error +// Returns: +// error +// Example: +// err := TempOperatorError(err) +// if err != nil { +// panic(err) +// } +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func TempOperatorError(err error) error { return &tempOperatorError{ message: fmt.Sprintf("temporary operator error; %s", err.Error()), } } +// IsTempOperatorError returns true if the error is a temporary operator error +// Parameters: +// err - the error to check +// Returns: +// true if the error is a temporary operator error +// Example: +// found := utils.IsTempOperatorError(err) +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsTempOperatorError(err error) bool { if err == nil { return false @@ -356,13 +628,29 @@ func IsTempOperatorError(err error) bool { type invalidInputError struct { message string } - -func (e *invalidInputError) Error() string { return e.message } - +// InvalidInputError is an error that is returned when the input is invalid. +// It returns a message that is useful to the user. +// Parameters: +// message - the message to return +// Return: +// an error object +// Example: +// err := utils.InvalidInputError("The input is invalid") +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func InvalidInputError(message string) error { return &invalidInputError{message} } +// IsInvalidInputError returns true if the error is an invalid input error. +// Parameters: +// err: the error to check +// Returns: +// true if the error is an invalid input error, false otherwise +// Example: +// IsInvalidInputError(errors.New("Invalid input")) +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsInvalidInputError(err error) bool { if err == nil { return false @@ -378,12 +666,16 @@ func IsInvalidInputError(err error) bool { type unsupportedCapacityRangeError struct { err error message string -} - -func (e *unsupportedCapacityRangeError) Unwrap() error { return e.err } - -func (e *unsupportedCapacityRangeError) Error() string { return e.message } - +// UnsupportedCapacityRangeError is returned when the capacity range is not supported +// It returns the error message and the error +// Parameters: +// err - the error message +// Return: +// the error +// Example: +// err := utils.UnsupportedCapacityRangeError(errors.New("capacity range is not supported")) +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func UnsupportedCapacityRangeError(err error) error { return &unsupportedCapacityRangeError{ err, fmt.Sprintf("unsupported capacity range; %s", @@ -391,6 +683,16 @@ func UnsupportedCapacityRangeError(err error) error { } } +// HasUnsupportedCapacityRangeError returns true if the error is an unsupportedCapacityRangeError +// Parameters: +// err: the error to check +// Returns: +// bool: true if the error is an unsupportedCapacityRangeError +// *unsupportedCapacityRangeError: the unsupportedCapacityRangeError if it is one, otherwise nil +// Example: +// ok, unsupportedCapacityRangeError := utils.HasUnsupportedCapacityRangeError(err) +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func HasUnsupportedCapacityRangeError(err error) (bool, *unsupportedCapacityRangeError) { if err == nil { return false, nil @@ -407,13 +709,31 @@ func HasUnsupportedCapacityRangeError(err error) (bool, *unsupportedCapacityRang type maxLimitReachedError struct { message string } - -func (e *maxLimitReachedError) Error() string { return e.message } - +// MaxLimitReachedError is returned when the maximum limit has been reached +// It returns a string message +// Parameters: +// message - the message to return +// Returns: +// the error +// Example: +// err := utils.MaxLimitReachedError("Maximum size reached") +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func MaxLimitReachedError(message string) error { return &maxLimitReachedError{message} } +// IsMaxLimitReachedError returns true if the error is a maxLimitReachedError +// Parameters: +// err: the error to check +// Returns: +// true if the error is a maxLimitReachedError +// Example: +// if utils.IsMaxLimitReachedError(err) { +// // handle error +// } +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsMaxLimitReachedError(err error) bool { if err == nil { return false @@ -430,10 +750,30 @@ type typeAssertionError struct { assertion string } +// Error types +// It returns a string representation of the error. +// Returns: +// string representation of the error +// Example: +// err := NewTypeAssertionError("this is the error") +// fmt.Println(err.Error()) +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func (e *typeAssertionError) Error() string { return fmt.Sprintf("could not perform assertion: %s", e.assertion) } +// TypeAssertionError is a +// It returns a new error with the given assertion. +// Parameters: +// assertion - the assertion that failed +// Returns: +// a new error with the given assertion +// Example: +// err := TypeAssertionError("assertion") +// fmt.Println(err) +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func TypeAssertionError(assertion string) error { return &typeAssertionError{assertion} } @@ -445,13 +785,29 @@ func TypeAssertionError(assertion string) error { type authError struct { message string } - -func (e *authError) Error() string { return e.message } - +// AuthError is an error +// It returns an error with a message +// Parameters: +// message string +// Returns: +// error +// Example: +// err := AuthError("error message") +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func AuthError(message string) error { return &authError{message} } +// IsAuthError returns true if the error is an auth error +// Parameters: +// err: the error to check +// Returns: +// true if the error is an auth error, false otherwise +// Example: +// ok := IsAuthError(err) +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsAuthError(err error) bool { if err == nil { return false @@ -467,13 +823,34 @@ func IsAuthError(err error) bool { type tooManyRequestsError struct { message string } - -func (e *tooManyRequestsError) Error() string { return e.message } - +// TooManyRequestsError is an error that indicates that the request was rejected due to rate limiting. +// It returns a 429 status code. +// Parameters: +// message - the error message +// Returns: +// an error +// Example: +// if err := utils.TooManyRequestsError("Too many requests"); err != nil { +// return err +// } +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func TooManyRequestsError(message string) error { return &tooManyRequestsError{message} } +// IsTooManyRequestsError returns true if the error is a TooManyRequestsError +// Parameters: +// err: the error to check +// Returns: +// true if the error is a TooManyRequestsError +// Example: +// err := utils.TooManyRequestsError("too many requests") +// if utils.IsTooManyRequestsError(err) { +// log.Println("too many requests") +// } +// +// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- func IsTooManyRequestsError(err error) bool { if err == nil { return false diff --git a/utils/errors_test.go b/utils/errors_test.go index 84931bb00..cd989d588 100644 --- a/utils/errors_test.go +++ b/utils/errors_test.go @@ -9,6 +9,13 @@ import ( "github.com/stretchr/testify/assert" ) +// TestUnsupportedCapacityRangeError tests the UnsupportedCapacityRangeError +// function. +// It checks that the function correctly identifies an UnsupportedCapacityRangeError +// and that it correctly identifies an UnsupportedCapacityRangeError within a +// wrapped error. +// +// -- Doc autogenerated on 2022-05-12 14:35:56.524034 -- func TestUnsupportedCapacityRangeError(t *testing.T) { // test setup err := fmt.Errorf("a generic error") diff --git a/utils/k8s_utils.go b/utils/k8s_utils.go index 45ef5fcd6..b8b51c43a 100644 --- a/utils/k8s_utils.go +++ b/utils/k8s_utils.go @@ -98,6 +98,17 @@ func IsLikelyNotMountPoint(ctx context.Context, mountpoint string) (bool, error) return true, nil } +// GetDeviceNameFromMount returns the device name and reference count for a given mount path. +// Parameters: +// mountpath: The mount path to look up. +// Returns: +// device: The device name. +// refCount: The number of references to the device. +// err: Any error encountered. +// Example: +// device, refCount, err := GetDeviceNameFromMount("/mnt/foo") +// +// -- Doc autogenerated on 2022-05-12 14:36:06.472497 -- func GetDeviceNameFromMount(ctx context.Context, mountpath string) (string, int, error) { fields := log.Fields{"mountpath": mountpath} @@ -207,6 +218,16 @@ func parseProcSelfMountinfo(content []byte) ([]MountInfo, error) { return out, nil } +// listProcMounts returns a list of all current mounts on the system. +// Parameters: +// mountFilePath: The path to the file to read (/proc/mounts) +// Returns: +// A slice of MountPoint structs containing information about each mount point +// An error if one occurred +// Example: +// mountPoints, err := listProcMounts("/proc/mounts") +// +// -- Doc autogenerated on 2022-05-12 14:36:06.472497 -- func listProcMounts(mountFilePath string) ([]MountPoint, error) { content, err := ConsistentRead(mountFilePath, maxListTries) if err != nil { @@ -215,6 +236,27 @@ func listProcMounts(mountFilePath string) ([]MountPoint, error) { return parseProcMounts(content) } +// parseProcMounts parses the content of /proc/mounts and returns a slice of MountPoint structs +// See 'man proc' for more details on the file format +// It returns an error if the file content does not have the expected format +// Parameters: +// content: the content of the /proc/mounts file +// Returns: +// a slice of MountPoint structs, or an error if the file content does not have the expected format +// Example: +// content, err := ioutil.ReadFile("/proc/mounts") +// if err != nil { +// return err +// } +// mounts, err := parseProcMounts(content) +// if err != nil { +// return err +// } +// for _, mount := range mounts { +// fmt.Printf("%s %s %s %v %d %d\n", mount.Device, mount.Path, mount.Type, mount.Opts, mount.Freq, mount.Pass) +// } +// +// -- Doc autogenerated on 2022-05-12 14:36:06.472497 -- func parseProcMounts(content []byte) ([]MountPoint, error) { out := make([]MountPoint, 0) lines := strings.Split(string(content), "\n") diff --git a/utils/k8s_utils_test.go b/utils/k8s_utils_test.go index b66596415..dec080bf4 100644 --- a/utils/k8s_utils_test.go +++ b/utils/k8s_utils_test.go @@ -7,6 +7,15 @@ import ( "github.com/stretchr/testify/assert" ) +// TestParseProcSelfMountinfo tests the parseProcSelfMountinfo function +// It checks for the following cases: +// - 10-13 fields +// - one valid one invalid +// - too few fields +// - separator in 5th position +// - no separator +// +// -- Doc autogenerated on 2022-05-12 14:37:23.777213 -- func TestParseProcSelfMountinfo(t *testing.T) { tests := []struct { name string diff --git a/utils/locks_test.go b/utils/locks_test.go index 8a4e6642c..72b24d931 100644 --- a/utils/locks_test.go +++ b/utils/locks_test.go @@ -10,6 +10,10 @@ import ( var ctx = context.Background +// TestLockCreated tests that a lock is created when it is locked. +// It checks that the lock is not created when it is not locked. +// +// -- Doc autogenerated on 2022-05-12 14:37:31.818596 -- func TestLockCreated(t *testing.T) { Lock(ctx(), "testContext", "myLock") @@ -24,6 +28,10 @@ func TestLockCreated(t *testing.T) { } } +// TestLockReused tests that the same lock is reused +// It checks that the lock is not created twice +// +// -- Doc autogenerated on 2022-05-12 14:37:31.818596 -- func TestLockReused(t *testing.T) { Lock(ctx(), "testContext", "reuseLock") @@ -41,6 +49,22 @@ func TestLockReused(t *testing.T) { } } +// acquire1 acquires a lock and then releases it +// Parameters: +// m1 - channel for commands +// r - channel for results +// Returns: +// none +// Example: +// m1 := make(chan string, 3) +// r := make(chan string) +// go acquire1(m1, r) +// m1 <- "lock" +// m1 <- "unlock" +// m1 <- "done" +// <-r +// +// -- Doc autogenerated on 2022-05-12 14:37:31.818596 -- func acquire1(m1, r chan string) { for i := 0; i < 3; i++ { op := <-m1 @@ -57,6 +81,27 @@ func acquire1(m1, r chan string) { } } +// acquire2 is a helper function for testing the behavior of the lock manager. +// It acquires a lock, then releases it, then acquires it again. +// Parameters: +// m2: a channel for receiving commands from the test +// r: a channel for sending a response to the test +// Returns: +// nothing +// Example: +// r := make(chan string) +// m2 := make(chan string) +// go acquire2(m2, r) +// m2 <- "lock" +// <-r +// m2 <- "unlock" +// <-r +// m2 <- "lock" +// <-r +// m2 <- "done" +// <-r +// +// -- Doc autogenerated on 2022-05-12 14:37:31.818596 -- func acquire2(m2, r chan string) { for i := 0; i < 3; i++ { op := <-m2 @@ -73,10 +118,26 @@ func acquire2(m2, r chan string) { } } +// snooze is a no-op function that sleeps for 1 millisecond. +// It is used to prevent the scheduler from spinning too fast. +// Returns: +// None +// Example: +// snooze() +// +// -- Doc autogenerated on 2022-05-12 14:37:31.818596 -- func snooze() { time.Sleep(1 * time.Millisecond) } +// TestLockBehavior tests the behavior of the Lock and Unlock methods. +// It is not a unit test, but rather a functional test. +// It checks that the lock is acquired by the first caller and that +// the second caller blocks until the first caller releases the lock. +// It also checks that the second caller can acquire the lock after +// the first caller releases it. +// +// -- Doc autogenerated on 2022-05-12 14:37:31.818596 -- func TestLockBehavior(t *testing.T) { r := make(chan string, 2) m1 := make(chan string, 3) diff --git a/utils/osutils.go b/utils/osutils.go index 68a927b61..478222614 100644 --- a/utils/osutils.go +++ b/utils/osutils.go @@ -54,6 +54,15 @@ var ( chrootPathPrefix string ) +// IPv6Check returns true if the IP is IPv6 +// Parameters: +// ip - IP address +// Returns: +// true if the IP is IPv6 +// Example: +// IPv6Check("fe80::f816:3eff:fe20:57c3") +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func IPv6Check(ip string) bool { return strings.Count(ip, ":") >= 2 } @@ -66,6 +75,15 @@ func init() { } } +// SetChrootPathPrefix sets the chroot path prefix +// Parameters: +// prefix - the chroot path prefix +// Returns: +// none +// Example: +// SetChrootPathPrefix("/var/lib/trident") +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func SetChrootPathPrefix(prefix string) { Logc(context.Background()).Debugf("SetChrootPathPrefix = '%s'", prefix) chrootPathPrefix = prefix @@ -73,6 +91,22 @@ func SetChrootPathPrefix(prefix string) { // Attach the volume to the local host. This method must be able to accomplish its task using only the data passed in. // It may be assumed that this method always runs on the host to which the volume will be attached. +// AttachNFSVolume publishes an NFS volume to the host +// It returns an error if the volume could not be published. +// Parameters: +// name: the volume name +// mountpoint: the directory where the volume will be mounted +// publishInfo: the volume publish information +// Returns: +// error: nil if successful, or an error if the volume could not be published +// Example: +// err := utils.AttachNFSVolume(ctx, "vol1", "/mnt/vol1", &utils.VolumePublishInfo{ +// NfsServerIP: "10.63.0.1", +// NfsPath: "/nfsvol1", +// MountOptions: "rw", +// }) +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func AttachNFSVolume(ctx context.Context, name, mountpoint string, publishInfo *VolumePublishInfo) error { Logc(ctx).Debug(">>>> osutils.AttachNFSVolume") @@ -91,6 +125,23 @@ func AttachNFSVolume(ctx context.Context, name, mountpoint string, publishInfo * return mountNFSPath(ctx, exportPath, mountpoint, options) } +// AttachBlockOnFileVolume attaches a block-on-file volume to the host. +// +// If a mountPath is specified, the device will be mounted at mountPath/volumeMountDir. +// If a mountPath is not specified, the device will not be mounted. +// It returns the device name and the mountpoint. +// Parameters: +// ctx - context +// mountPath - the path to mount the device +// publishInfo - the volume publish information +// Returns: +// deviceName - the device name +// deviceMountpoint - the device mountpoint +// err - error if any +// Example: +// deviceName, deviceMountpoint, err := AttachBlockOnFileVolume(ctx, "", &VolumePublishInfo{...}) +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func AttachBlockOnFileVolume( ctx context.Context, mountPath string, publishInfo *VolumePublishInfo, ) (string, string, error) { @@ -207,6 +258,18 @@ func AttachBlockOnFileVolume( return loopDevice.Name, deviceMountpoint, nil } +// DetachBlockOnFileVolume detaches a loop device from a file +// It returns an error if the loop device is not attached to the file +// Parameters: +// ctx - the context +// loopDevice - the loop device to detach +// loopFile - the file to detach from +// Returns: +// error - any error encountered +// Example: +// err := DetachBlockOnFileVolume(ctx, "/dev/loop0", "/var/lib/trident/block-volumes/test-volume") +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func DetachBlockOnFileVolume(ctx context.Context, loopDevice, loopFile string) error { Logc(ctx).Debug(">>>> osutils.DetachBlockOnFileVolume") @@ -418,6 +481,19 @@ func AttachISCSIVolume(ctx context.Context, name, mountpoint string, publishInfo return nil } +// logInToPortals logs in to the specified portals using CHAP. +// It returns true if it was able to log in to at least one portal. +// Parameters: +// ctx - context +// bkPortalsToLogin - list of portals to login to +// publishInfo - volume publish information +// loggedIn - true if already logged in to at least one portal +// Returns: +// loggedIn - true if logged in to at least one portal +// Example: +// loggedIn := logInToPortals(ctx, bkPortalsToLogin, publishInfo, loggedIn) +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func logInToPortals( ctx context.Context, bkPortalsToLogin []string, publishInfo *VolumePublishInfo, loggedIn bool, ) bool { @@ -1554,6 +1630,20 @@ func ExpandFilesystemOnNode( return size, nil } +// expandFilesystem expands the filesystem on the given mount point +// It returns the new size of the filesystem +// Parameters: +// ctx: context +// cmd: command to execute +// cmdArguments: arguments to the command +// tmpMountPoint: mount point of the filesystem to expand +// Returns: +// int64: size of the filesystem after expansion +// error: any error encountered +// Example: +// newSize, err := osutils.expandFilesystem(ctx, "resize2fs", "/dev/sdb1", "/tmp/foo") +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func expandFilesystem(ctx context.Context, cmd string, cmdArguments string, tmpMountPoint string) (int64, error) { logFields := log.Fields{ @@ -1742,6 +1832,19 @@ func formatPortal(portal string) string { } } +// ISCSIRescanDevices rescan iSCSI devices +// It returns an error if the device is not large enough after rescanning +// Parameters: +// ctx: context +// targetIQN: the IQN of the iSCSI target +// lunID: the LUN ID of the iSCSI target +// minSize: the minimum size of the iSCSI device +// Returns: +// error: nil if no error occurred +// Example: +// err := ISCSIRescanDevices(ctx, "iqn.2010-10.org.openstack:volume-ebd8e5f7-e0e3-4f9b-8c1d-e1a5d20f5d2f", 0, 10737418240) +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func ISCSIRescanDevices(ctx context.Context, targetIQN string, lunID int32, minSize int64) error { fields := log.Fields{"targetIQN": targetIQN, "lunID": lunID} @@ -1819,6 +1922,17 @@ func ISCSIRescanDevices(ctx context.Context, targetIQN string, lunID int32, minS return nil } +// reloadMultipathDevice reloads a multipath device. +// It returns an error if the reload fails. +// Parameters: +// ctx - context for logging +// multipathDevice - the multipath device to reload +// Returns: +// error - error if the reload fails +// Example: +// err := reloadMultipathDevice(ctx, "3600a098038303837b000000000000001") +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func reloadMultipathDevice(ctx context.Context, multipathDevice string) error { fields := log.Fields{"multipathDevice": multipathDevice} @@ -2319,6 +2433,26 @@ func GetISCSIDevices(ctx context.Context) ([]*ScsiDeviceInfo, error) { return devices, nil } +// IsNFSShareMounted checks if the given NFS export is mounted at the given mountpoint +// It returns true if the export is mounted at the given mountpoint +// Parameters: +// exportPath: the NFS export to check +// mountpoint: the mountpoint to check +// Returns: +// bool: true if the export is mounted at the given mountpoint +// error: any error encountered +// Example: +// mounted, err := IsNFSShareMounted(ctx, "server:/vol/vol1", "/mnt/vol1") +// if err != nil { +// log.Fatal(err) +// } +// if mounted { +// log.Printf("NFS Share is mounted.") +// } else { +// log.Printf("NFS Share is not mounted.") +// } +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func IsNFSShareMounted(ctx context.Context, exportPath, mountpoint string) (bool, error) { fields := log.Fields{ @@ -3066,6 +3200,20 @@ func getTargets(ctx context.Context, tp string) ([]string, error) { return filterTargets(string(output), tp), nil } +// updateDiscoveryDb updates the discovery database with the given key and value +// It returns an error if the discovery database could not be updated +// Parameters: +// ctx - context +// tp - portal +// iface - interface +// key - key +// value - value +// Returns: +// error - error if the discovery database could not be updated +// Example: +// err := updateDiscoveryDb(ctx, "192.168.0.1:3260", "default", "iface.iscsi_ifacename", "eth0") +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func updateDiscoveryDb(ctx context.Context, tp, iface, key, value string) error { Logc(ctx).WithFields(log.Fields{ "Key": key, @@ -3209,6 +3357,16 @@ type LoopDevice struct { BackFile string `json:"back-file"` } +// getLoopDeviceInfo returns a list of loop devices +// Parameters: +// ctx: The context for the request +// Returns: +// []LoopDevice: A list of loop devices +// error: Any error encountered +// Example: +// loopDevices, err := getLoopDeviceInfo() +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func getLoopDeviceInfo(ctx context.Context) ([]LoopDevice, error) { Logc(ctx).Debug(">>>> osutils.getLoopDeviceInfo") @@ -3233,6 +3391,26 @@ func getLoopDeviceInfo(ctx context.Context) ([]LoopDevice, error) { return loopDevicesResponse.LoopDevices, nil } +// GetLoopDeviceAttachedToFile returns the loop device attached to the specified file +// Parameters: +// ctx - context +// loopFile - path to the loop file +// Returns: +// bool - true if the loop device is attached to the specified file +// *LoopDevice - the loop device +// error - any error encountered +// Example: +// attached, device, err := GetLoopDeviceAttachedToFile(ctx, "/dev/loop0") +// if err != nil { +// return err +// } +// if attached { +// fmt.Printf("Loop device %s is attached to file %s\n", device.Name, device.BackFile) +// } else { +// fmt.Printf("No loop device is attached to file %s\n", loopFile) +// } +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func GetLoopDeviceAttachedToFile(ctx context.Context, loopFile string) (bool, *LoopDevice, error) { Logc(ctx).WithField("loopFile", loopFile).Debug(">>>> osutils.GetLoopDeviceAttachedToFile") @@ -3260,6 +3438,19 @@ func GetLoopDeviceAttachedToFile(ctx context.Context, loopFile string) (bool, *L return false, nil, nil } +// GetAllLoopDeviceBackFiles returns a list of all loop device back-files +// Parameters: +// ctx - logging context +// Returns: +// []string - list of all loop device back-files +// error - any error encountered +// Example: +// deviceBackFiles, err := utils.GetAllLoopDeviceBackFiles(ctx) +// if err != nil { +// return err +// } +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func GetAllLoopDeviceBackFiles(ctx context.Context) ([]string, error) { Logc(ctx).Debug(">>>> osutils.GetAllLoopDeviceBackFiles") @@ -3282,6 +3473,31 @@ func GetAllLoopDeviceBackFiles(ctx context.Context) ([]string, error) { return deviceBackFiles, nil } +// IsLoopDeviceAttachedToFile checks if a loop device is attached to a file +// It returns true if the loop device is attached to the file +// Parameters: +// ctx: context.Context object +// loopDevice: loop device name +// loopFile: file name +// Returns: +// bool: true if the loop device is attached to the file +// error: error object if an error occurred +// Example: +// loopDevices, err := osutils.GetLoopDeviceInfo(ctx) +// if err != nil { +// return err +// } +// for _, loopDevice := range loopDevices { +// isAttached, err := osutils.IsLoopDeviceAttachedToFile(ctx, loopDevice.Name, loopFile) +// if err != nil { +// return err +// } +// if isAttached { +// return true +// } +// } +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func IsLoopDeviceAttachedToFile(ctx context.Context, loopDevice, loopFile string) (bool, error) { Logc(ctx).WithFields(log.Fields{ "loopFile": loopFile, @@ -3311,6 +3527,22 @@ func IsLoopDeviceAttachedToFile(ctx context.Context, loopDevice, loopFile string return false, nil } +// ResizeLoopDevice resizes the loop device to the required size +// It returns an error if the loop device is not resized to the required size +// Parameters: +// ctx: context.Context object +// loopDevice: the loop device to resize +// loopFile: the loop file to resize +// requiredBytes: the required size in bytes +// Returns: +// error: nil if successful, error if not +// Example: +// err := ResizeLoopDevice(ctx, "/dev/loop0", "/tmp/iscsi-test.img", 10737418240) +// if err != nil { +// fmt.Println("Failed to resize loop device") +// } +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func ResizeLoopDevice(ctx context.Context, loopDevice, loopFile string, requiredBytes int64) error { Logc(ctx).WithFields(log.Fields{ @@ -3567,6 +3799,20 @@ func SafeToRemoveNFSMount(ctx context.Context, nfsMountPoint string) bool { } // loginISCSITarget logs in to an iSCSI target. +// configureISCSITarget configures the iSCSI target with the specified name and value +// It returns an error if the command fails +// Parameters: +// ctx - context for logging +// iqn - IQN of the target +// portal - portal of the target +// name - name of the target configuration +// value - value of the target configuration +// Returns: +// error - error if the command fails +// Example: +// err := configureISCSITarget(ctx, iqn, portal, "node.conn[0].startup", "automatic") +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func configureISCSITarget(ctx context.Context, iqn, portal, name, value string) error { Logc(ctx).WithFields(log.Fields{ @@ -3683,6 +3929,19 @@ func loginWithChap( return nil } +// EnsureISCSISessions ensures that the iSCSI target is logged in to all portals +// It returns true if a session was established with at least one portal +// Parameters: +// targetIQN: the IQN of the iSCSI target +// portalsIps: the IP addresses of the iSCSI portals +// iface: the interface to use for iSCSI +// Returns: +// bool: true if a session was established with at least one portal +// Example: +// EnsureISCSISessions(ctx, "iqn.2003-01.org.linux-iscsi.target1", []string{"192.168.1.10", "192.168.1.11"}, "eth0") +// EnsureISCSISessions(ctx, "iqn.2003-01.org.linux-iscsi.target1", []string{"192.168.1.10", "192.168.1.11"}, "") +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func EnsureISCSISessions(ctx context.Context, targetIQN, iface string, portalsIps []string) bool { logFields := log.Fields{ "targetIQN": targetIQN, @@ -3764,6 +4023,19 @@ func EnsureISCSISessions(ctx context.Context, targetIQN, iface string, portalsIp return successfulLogin } +// EnsureISCSISessionsWithPortalDiscovery ensures that all the hostDataIPs have an iSCSI session +// with the portal discovery +// It returns an error if any of the hostDataIPs fail to have an iSCSI session +// Parameters: +// hostDataIPs: list of host data IPs +// Returns: +// error: nil if all the hostDataIPs have an iSCSI session with the portal discovery +// Example: +// if err := utils.EnsureISCSISessionsWithPortalDiscovery(ctx, []string{"10.63.11.1", "10.63.11.2"}); nil != err { +// return err +// } +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func EnsureISCSISessionsWithPortalDiscovery(ctx context.Context, hostDataIPs []string) error { for _, ip := range hostDataIPs { @@ -3774,6 +4046,18 @@ func EnsureISCSISessionsWithPortalDiscovery(ctx context.Context, hostDataIPs []s return nil } +// EnsureISCSISessionWithPortalDiscovery ensures that an iSCSI session exists for the specified portal +// If no session exists, it will run discovery and log in to the target +// It returns an error if the session could not be established +// Parameters: +// ctx - context +// hostDataIP - IP address of the iSCSI portal +// Returns: +// error - error if session could not be established +// Example: +// err := utils.EnsureISCSISessionWithPortalDiscovery(ctx, "192.168.1.2") +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func EnsureISCSISessionWithPortalDiscovery(ctx context.Context, hostDataIP string) error { Logc(ctx).WithField("hostDataIP", hostDataIP).Debug(">>>> osutils.EnsureISCSISessionWithPortalDiscovery") @@ -3855,6 +4139,21 @@ func EnsureISCSISessionWithPortalDiscovery(ctx context.Context, hostDataIP strin } // execIscsiadmCommand uses the 'iscsiadm' command to perform operations without logging specified secrets +// execIscsiadmCommandRedacted executes an iscsiadm command with the provided args, +// and redacts any secrets in the output. +// It returns the output of the command and any error encountered. +// Parameters: +// ctx: context for the command +// args: arguments to the command +// secretsToRedact: map of secrets to redact from the output +// Returns: +// output of the command +// error encountered +// Example: +// output, err := execIscsiadmCommandRedacted(ctx, []string{"-m", "session", "-P", "3"}, +// map[string]string{"password": "secret"}) +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func execIscsiadmCommandRedacted(ctx context.Context, args []string, secretsToRedact map[string]string) ([]byte, error) { return execCommandRedacted(ctx, "iscsiadm", args, secretsToRedact) } @@ -3889,6 +4188,21 @@ func execCommand(ctx context.Context, name string, args ...string) ([]byte, erro } // execCommand invokes an external process, and redacts sensitive arguments +// execCommandRedacted executes a command and returns the output. +// It also redacts any secrets passed in the args. +// It returns the output and error. +// Parameters: +// ctx - context +// name - name of the command to execute +// args - arguments to the command +// secretsToRedact - map of secrets to redact +// Returns: +// []byte - output of the command +// error - error +// Example: +// output, err := execCommandRedacted(ctx, "ls", []string{"-l"}, nil) +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func execCommandRedacted(ctx context.Context, name string, args []string, secretsToRedact map[string]string) ([]byte, error) { @@ -3927,6 +4241,22 @@ type execCommandResult struct { } // execCommand invokes an external shell command +// execCommandWithTimeout executes a command with a timeout. +// If the command times out, the process is killed and an error is returned. +// It returns the output of the command and an error. +// Parameters: +// ctx: context +// name: command name +// timeoutSeconds: timeout in seconds +// logOutput: whether to log the output +// args: command arguments +// Returns: +// output: command output +// error: error +// Example: +// out, err := execCommandWithTimeout(ctx, "ls", 10, true, "-l", "/tmp") +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func execCommandWithTimeout( ctx context.Context, name string, timeoutSeconds time.Duration, logOutput bool, args ...string, ) ([]byte, error) { @@ -3982,6 +4312,18 @@ func execCommandWithTimeout( return result.Output, result.Error } +// sanitizeString removes xterm control characters and trailing newlines +// It returns a sanitized string +// Parameters: +// s: string to sanitize +// Returns: +// sanitized string +// Example: +// s := "this is a string\n" +// sanitizeString(s) +// // returns "this is a string" +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func sanitizeString(s string) string { // Strip xterm color & movement characters s = xtermControlRegex.ReplaceAllString(s, "") @@ -4026,6 +4368,15 @@ func SafeToLogOut(ctx context.Context, hostNumber, sessionNumber int) bool { } // In the case of a iscsi trace debug, log info about session and what devices are present +// listAllISCSIDevices lists all iSCSI devices +// Parameters: +// ctx - context +// Returns: +// none +// Example: +// listAllISCSIDevices(ctx) +// +// -- Doc autogenerated on 2022-05-12 14:39:06.443870 -- func listAllISCSIDevices(ctx context.Context) { if !Logc(ctx).Logger.IsLevelEnabled(log.TraceLevel) { diff --git a/utils/osutils_darwin.go b/utils/osutils_darwin.go index 9f3cb7695..3e21651dc 100644 --- a/utils/osutils_darwin.go +++ b/utils/osutils_darwin.go @@ -14,6 +14,16 @@ import ( // At compile time golang will type checks the entire code base. Since the CLI is part // of the Trident code base this file exists to handle darwin specific code. +// getIPAddresses returns the IP addresses of the host. +// Parameters: +// ctx - context +// Returns: +// []net.Addr - the IP addresses of the host +// error - error if any +// Example: +// []net.Addr, err := utils.getIPAddresses(ctx) +// +// -- Doc autogenerated on 2022-05-12 14:49:46.905128 -- func getIPAddresses(ctx context.Context) ([]net.Addr, error) { Logc(ctx).Debug(">>>> osutils_darwin.getIPAddresses") @@ -21,6 +31,16 @@ func getIPAddresses(ctx context.Context) ([]net.Addr, error) { return nil, errors.New("getIPAddresses is not supported for darwin") } +// getFilesystemSize returns the size of the filesystem containing the given path. +// Parameters: +// path - path to a file or directory +// Returns: +// size of the filesystem in bytes +// error - nil if successful +// Example: +// size, err := getFilesystemSize("/tmp") +// +// -- Doc autogenerated on 2022-05-12 14:49:46.905128 -- func getFilesystemSize(ctx context.Context, _ string) (int64, error) { Logc(ctx).Debug(">>>> osutils_darwin.getFilesystemSize") @@ -28,6 +48,22 @@ func getFilesystemSize(ctx context.Context, _ string) (int64, error) { return 0, errors.New("getFilesystemSize is not supported for darwin") } +// GetFilesystemStats returns the filesystem stats for the given path +// Parameters: +// ctx - context for logging +// path - the path to get the stats for +// Returns: +// total - total size of the filesystem +// free - free space on the filesystem +// avail - available space on the filesystem +// files - number of files on the filesystem +// ffree - number of free files on the filesystem +// fsid - filesystem id +// err - any error encountered +// Example: +// total, free, avail, files, ffree, fsid, err := GetFilesystemStats(ctx, "/") +// +// -- Doc autogenerated on 2022-05-12 14:49:46.905128 -- func GetFilesystemStats(ctx context.Context, _ string) (int64, int64, int64, int64, int64, int64, error) { Logc(ctx).Debug(">>>> osutils_darwin.GetFilesystemStats") @@ -35,6 +71,20 @@ func GetFilesystemStats(ctx context.Context, _ string) (int64, int64, int64, int return 0, 0, 0, 0, 0, 0, errors.New("GetFilesystemStats is not supported for darwin") } +// getISCSIDiskSize returns the size of the iSCSI disk +// Parameters: +// ctx - context for logging +// device - the device name +// Returns: +// size - the size of the iSCSI disk +// err - any error encountered +// Example: +// size, err := getISCSIDiskSize(context.Background(), "/dev/disk2") +// if err != nil { +// return err +// } +// +// -- Doc autogenerated on 2022-05-12 14:49:46.905128 -- func getISCSIDiskSize(ctx context.Context, _ string) (int64, error) { Logc(ctx).Debug(">>>> osutils_darwin.getISCSIDiskSize") @@ -42,12 +92,34 @@ func getISCSIDiskSize(ctx context.Context, _ string) (int64, error) { return 0, errors.New("getBlockSize is not supported for darwin") } +// flushOneDevice is not supported for darwin +// It returns an error +// Parameters: +// ctx - logging context +// devicePath - the device to flush +// Returns: +// error - any error encountered +// Example: +// err := flushOneDevice(ctx, devicePath) +// +// -- Doc autogenerated on 2022-05-12 14:49:46.905128 -- func flushOneDevice(ctx context.Context, devicePath string) error { Logc(ctx).Debug(">>>> osutils_darwin.flushOneDevice") defer Logc(ctx).Debug("<<<< osutils_darwin.flushOneDevice") return errors.New("flushOneDevice is not supported for darwin") } +// GetHostSystemInfo is not supported for darwin +// It returns an error +// Parameters: +// ctx - logging context +// Returns: +// *HostSystem - host system information +// error - error object if any +// Example: +// hs, err := GetHostSystemInfo(ctx) +// +// -- Doc autogenerated on 2022-05-12 14:49:46.905128 -- func GetHostSystemInfo(ctx context.Context) (*HostSystem, error) { Logc(ctx).Debug(">>>> osutils_darwin.GetHostSystemInfo") @@ -56,6 +128,17 @@ func GetHostSystemInfo(ctx context.Context) (*HostSystem, error) { return nil, UnsupportedError(msg) } +// PrepareNFSPackagesOnHost is not is not supported for darwin +// It returns an UnsupportedError +// Parameters: +// ctx - context for logging +// host - host system +// Returns: +// error - error if any +// Example: +// err := osutils_darwin.PrepareNFSPackagesOnHost(ctx, host) +// +// -- Doc autogenerated on 2022-05-12 14:49:46.905128 -- func PrepareNFSPackagesOnHost(ctx context.Context, host HostSystem) error { Logc(ctx).Debug(">>>> osutils_darwin.PrepareNFSPackagesOnHost") @@ -64,6 +147,16 @@ func PrepareNFSPackagesOnHost(ctx context.Context, host HostSystem) error { return UnsupportedError(msg) } +// PrepareNFSServicesOnHost is not supported for darwin +// It returns an UnsupportedError +// Parameters: +// ctx - context for logging +// Returns: +// error - an error if one occurred +// Example: +// err := utils.PrepareNFSServicesOnHost(ctx) +// +// -- Doc autogenerated on 2022-05-12 14:49:46.905128 -- func PrepareNFSServicesOnHost(ctx context.Context) error { Logc(ctx).Debug(">>>> osutils_darwin.PrepareNFSServicesOnHost") defer Logc(ctx).Debug("<<<< osutils_darwin.PrepareNFSServicesOnHost") @@ -71,6 +164,18 @@ func PrepareNFSServicesOnHost(ctx context.Context) error { return UnsupportedError(msg) } +// ServiceActiveOnHost checks if a service is active on the host +// It returns true if the service is active, false if not, and an error if there was a problem +// Parameters: +// ctx - context for logging +// service - the service to check +// Returns: +// bool - true if the service is active, false if not +// error - an error if there was a problem +// Example: +// active, err := utils.ServiceActiveOnHost(ctx, "iscsi") +// +// -- Doc autogenerated on 2022-05-12 14:49:46.905128 -- func ServiceActiveOnHost(ctx context.Context, service string) (bool, error) { Logc(ctx).Debug(">>>> osutils_darwin.ServiceActiveOnHost") defer Logc(ctx).Debug("<<<< osutils_darwin.ServiceActiveOnHost") @@ -78,6 +183,18 @@ func ServiceActiveOnHost(ctx context.Context, service string) (bool, error) { return false, UnsupportedError(msg) } +// ServiceEnabledOnHost checks if a service is enabled on the host +// It returns true if the service is enabled, false if not, and an error +// Parameters: +// ctx - context for logging +// service - the service to check +// Returns: +// bool - true if the service is enabled, false if not +// error - any error encountered +// Example: +// enabled, err := ServiceEnabledOnHost(ctx, "glusterd") +// +// -- Doc autogenerated on 2022-05-12 14:49:46.905128 -- func ServiceEnabledOnHost(ctx context.Context, service string) (bool, error) { Logc(ctx).Debug(">>>> osutils_darwin.ServiceEnabledOnHost") defer Logc(ctx).Debug("<<<< osutils_darwin.ServiceEnabledOnHost") @@ -85,6 +202,16 @@ func ServiceEnabledOnHost(ctx context.Context, service string) (bool, error) { return false, UnsupportedError(msg) } +// ISCSIActiveOnHost returns true if iSCSI is active on the host +// Parameters: +// host - host system +// Returns: +// bool - true if iSCSI is active on the host +// error - any error encountered +// Example: +// isActive, err := ISCSIActiveOnHost(host) +// +// -- Doc autogenerated on 2022-05-12 14:49:46.905128 -- func ISCSIActiveOnHost(ctx context.Context, host HostSystem) (bool, error) { Logc(ctx).Debug(">>>> osutils_darwin.ISCSIActiveOnHost") defer Logc(ctx).Debug("<<<< osutils_darwin.ISCSIActiveOnHost") @@ -92,6 +219,18 @@ func ISCSIActiveOnHost(ctx context.Context, host HostSystem) (bool, error) { return false, UnsupportedError(msg) } +// PrepareISCSIPackagesOnHost is not supported on darwin +// It returns an UnsupportedError +// Parameters: +// ctx - context for logging +// host - host system +// iscsiPreconfigured - true if the host is already configured for iSCSI +// Returns: +// error - an error if one occurred +// Example: +// err := PrepareISCSIPackagesOnHost(ctx, host, iscsiPreconfigured) +// +// -- Doc autogenerated on 2022-05-12 14:49:46.905128 -- func PrepareISCSIPackagesOnHost(ctx context.Context, host HostSystem, iscsiPreconfigured bool) error { Logc(ctx).Debug(">>>> osutils_darwin.PrepareISCSIPackagesOnHost") defer Logc(ctx).Debug("<<<< osutils_darwin.PrepareISCSIPackagesOnHost") @@ -99,6 +238,20 @@ func PrepareISCSIPackagesOnHost(ctx context.Context, host HostSystem, iscsiPreco return UnsupportedError(msg) } +// PrepareISCSIServicesOnHost is not supported for darwin +// It returns an UnsupportedError +// Parameters: +// ctx - context for logging +// host - the host to prepare +// Returns: +// error - an error if one occurred, otherwise nil +// Example: +// err := PrepareISCSIServicesOnHost(ctx, host) +// if err != nil { +// // Handle error +// } +// +// -- Doc autogenerated on 2022-05-12 14:49:46.905128 -- func PrepareISCSIServicesOnHost(ctx context.Context, host HostSystem) error { Logc(ctx).Debug(">>>> osutils_darwin.PrepareISCSIServicesOnHost") defer Logc(ctx).Debug("<<<< osutils_darwin.PrepareISCSIServicesOnHost") diff --git a/utils/osutils_linux.go b/utils/osutils_linux.go index 34558679c..e06f3eeea 100644 --- a/utils/osutils_linux.go +++ b/utils/osutils_linux.go @@ -31,6 +31,22 @@ type statFSResult struct { // getFilesystemSize returns the size of the filesystem for the given path. // The caller of the func is responsible for verifying the mountPoint existence and readiness. +// GetFilesystemStats returns the filesystem stats for the given path. +// The returned values are in bytes. +// Parameters: +// path: the path to get filesystem stats for +// Returns: +// available: the number of bytes available on the filesystem +// capacity: the total number of bytes on the filesystem +// usage: the number of bytes used on the filesystem +// inodes: the total number of inodes on the filesystem +// inodesFree: the number of free inodes on the filesystem +// inodesUsed: the number of used inodes on the filesystem +// err: an error if one occurred +// Example: +// available, capacity, usage, inodes, inodesFree, inodesUsed, err := utils.GetFilesystemStats("/") +// +// -- Doc autogenerated on 2022-05-12 14:56:13.838311 -- func GetFilesystemStats( ctx context.Context, path string, ) (available, capacity, usage, inodes, inodesFree, inodesUsed int64, err error) { @@ -149,6 +165,17 @@ func flushOneDevice(ctx context.Context, devicePath string) error { return nil } +// determineNFSPackages returns the list of packages to install for NFS support based on the host's OS. +// Parameters: +// ctx - context +// host - host system +// Returns: +// list of packages to install for NFS support +// error - error if any +// Example: +// packages, err := determineNFSPackages(ctx, host) +// +// -- Doc autogenerated on 2022-05-12 14:56:13.838311 -- func determineNFSPackages(ctx context.Context, host HostSystem) ([]string, error) { var packages []string @@ -172,6 +199,18 @@ func determineNFSPackages(ctx context.Context, host HostSystem) ([]string, error return packages, nil } +// determineISCSIPackages returns a list of packages to install for the given host +// If iscsiPreconfigured is true, then iscsi and multipath packages are not included +// Parameters: +// host: host system +// iscsiPreconfigured: true if iscsi is already configured +// Return: +// list of packages to install +// error: error if any +// Example: +// packages, err := determineISCSIPackages(host, false) +// +// -- Doc autogenerated on 2022-05-12 14:56:13.838311 -- func determineISCSIPackages(ctx context.Context, host HostSystem, iscsiPreconfigured bool) ([]string, error) { packages := make([]string, 0) @@ -198,6 +237,18 @@ func determineISCSIPackages(ctx context.Context, host HostSystem, iscsiPreconfig return packages, nil } +// PrepareNFSPackagesOnHost installs NFS packages on the host +// It returns an error if the packages could not be installed +// Parameters: +// ctx - context for logging +// host - host to install NFS packages on +// Returns: +// error - error if the packages could not be installed +// Example: +// ctx := context.Background() +// err := PrepareNFSPackagesOnHost(ctx, host) +// +// -- Doc autogenerated on 2022-05-12 14:56:13.838311 -- func PrepareNFSPackagesOnHost(ctx context.Context, host HostSystem) error { Logc(ctx).Debug(">>>> osutils_linux.PrepareNFSPackagesOnHost") @@ -249,6 +300,19 @@ func installMissingPackagesOnHost(ctx context.Context, packages []string, host H return nil } +// checkPackagesOnHost checks if the packages are installed on the host +// Parameters: +// ctx - context for logging +// packages - list of packages to check +// host - host to check +// Returns: +// list of packages not installed on the host +// error +// Example: +// notInstalled, err := checkPackagesOnHost(ctx, []string{"python", "python-pip"}, host) +// +// +// -- Doc autogenerated on 2022-05-12 14:56:13.838311 -- func checkPackagesOnHost(ctx context.Context, packages []string, host HostSystem) (notInstalled []string, err error) { for _, pkg := range packages { @@ -265,6 +329,17 @@ func checkPackagesOnHost(ctx context.Context, packages []string, host HostSystem return } +// packageInstalledOnHost checks if a +// It returns true if the +// Parameters: +// ctx - context +// pkg - +// Returns: +// bool - true if the +// Example: +// installed, err := packageInstalledOnHost(ctx, "vim", host) +// +// -- Doc autogenerated on 2022-05-12 14:56:13.838311 -- func packageInstalledOnHost(ctx context.Context, pkg string, host HostSystem) (bool, error) { // Determine command to use @@ -332,6 +407,15 @@ func packageInstalledOnHost(ctx context.Context, pkg string, host HostSystem) (b return true, nil } +// getPackageManagerForHost returns the +// Parameters: +// host - host system +// Returns: +// string - +// Example: +// packageManager, err := getPackageManagerForHost(host) +// +// -- Doc autogenerated on 2022-05-12 14:56:13.838311 -- func getPackageManagerForHost(ctx context.Context, host HostSystem) (string, error) { switch host.OS.Distro { case Centos, RHEL: @@ -355,6 +439,18 @@ func getPackageManagerForHost(ctx context.Context, host HostSystem) (string, err } } +// installPackagesOnHost installs the specified packages on the specified host. +// It returns an error if any of the packages fail to install. +// Parameters: +// ctx - context for logging +// packages - list of packages to install +// host - host to install packages on +// Returns: +// error - error if any of the packages fail to install +// Example: +// err := installPackagesOnHost(ctx, []string{"package1", "package2"}, host) +// +// -- Doc autogenerated on 2022-05-12 14:56:13.838311 -- func installPackagesOnHost(ctx context.Context, packages []string, host HostSystem) error { if len(packages) == 0 { @@ -416,6 +512,19 @@ func installPackagesOnHost(ctx context.Context, packages []string, host HostSyst return nil } +// PrepareNFSServicesOnHost prepares the NFS services on the host +// It returns an error if any of the services fail to start +// Parameters: +// ctx - context for logging +// Returns: +// error - any error encountered +// Example: +// err := PrepareNFSServicesOnHost(ctx) +// if err != nil { +// // handle error +// } +// +// -- Doc autogenerated on 2022-05-12 14:56:13.838311 -- func PrepareNFSServicesOnHost(ctx context.Context) error { Logc(ctx).Debug(">>>> osutils_linux.PrepareNFSServicesOnHost") @@ -443,6 +552,16 @@ func PrepareNFSServicesOnHost(ctx context.Context) error { return nil } +// determineISCSIServices returns the list of ISCSI services for the given host +// Parameters: +// host - host system +// Returns: +// list of ISCSI services +// error - error if any +// Example: +// services, err := utils.determineISCSIServices(host) +// +// -- Doc autogenerated on 2022-05-12 14:56:13.838311 -- func determineISCSIServices(host HostSystem) ([]string, error) { services := make([]string, 0) @@ -492,6 +611,19 @@ func PrepareISCSIServicesOnHost(ctx context.Context, host HostSystem) error { return nil } +// configureMultipathServiceOnHost configures multipath service on the given host +// Parameters: +// ctx - context +// host - host to configure +// Returns: +// error - error if any +// Example: +// err := configureMultipathServiceOnHost(ctx, host) +// if err != nil { +// log.Error(err) +// } +// +// -- Doc autogenerated on 2022-05-12 14:56:13.838311 -- func configureMultipathServiceOnHost(ctx context.Context, host HostSystem) error { var err error @@ -538,6 +670,17 @@ func ISCSIActiveOnHost(ctx context.Context, host HostSystem) (bool, error) { return ServiceActiveOnHost(ctx, serviceName) } +// enableAndStartServiceOnHost enables and starts a service on the host +// It returns an error if the service is not enabled or started +// Parameters: +// ctx - context for logging +// service - the service to enable and start +// Returns: +// error - error if the service is not enabled or started +// Example: +// err := enableAndStartServiceOnHost(ctx, "iscsi.service") +// +// -- Doc autogenerated on 2022-05-12 14:56:13.838311 -- func enableAndStartServiceOnHost(ctx context.Context, service string) error { var ( diff --git a/utils/osutils_linux_test.go b/utils/osutils_linux_test.go index 161bbbbc5..385e1ad6c 100644 --- a/utils/osutils_linux_test.go +++ b/utils/osutils_linux_test.go @@ -14,6 +14,10 @@ import ( "github.com/stretchr/testify/assert" ) +// TestDetermineNFSPackages tests the determineNFSPackages function +// It checks the packages returned for a variety of distros +// +// -- Doc autogenerated on 2022-05-12 15:01:28.925004 -- func TestDetermineNFSPackages(t *testing.T) { log.Debug("Running TestDetermineNFSPackages...") @@ -68,6 +72,10 @@ func TestDetermineNFSPackages(t *testing.T) { } } +// TestGetPackageManagerForHost tests the getPackageManagerForHost function +// It checks that the correct +// +// -- Doc autogenerated on 2022-05-12 15:01:28.925004 -- func TestGetPackageManagerForHost(t *testing.T) { log.Debug("Running TestGetPackageManagerForHost...") @@ -139,6 +147,10 @@ func TestGetPackageManagerForHost(t *testing.T) { assert.Equal(t, test.expectedPM, pm, "Incorrect package manager returned") } } +// TestGetIPAddresses tests the getIPAddresses function +// It checks that the returned addresses are not loopback and are global unicast +// +// -- Doc autogenerated on 2022-05-12 15:01:28.925004 -- func TestGetIPAddresses(t *testing.T) { addrs, err := getIPAddresses(context.TODO()) @@ -156,6 +168,11 @@ func TestGetIPAddresses(t *testing.T) { } } +// TestGetIPAddressesExceptingDummyInterfaces tests the getIPAddressesExceptingDummyInterfaces function +// It checks that the function returns at least one address, and that all addresses are global unicast +// and not loopback +// +// -- Doc autogenerated on 2022-05-12 15:01:28.925004 -- func TestGetIPAddressesExceptingDummyInterfaces(t *testing.T) { addrs, err := getIPAddressesExceptingDummyInterfaces(context.TODO()) @@ -173,6 +190,10 @@ func TestGetIPAddressesExceptingDummyInterfaces(t *testing.T) { } } +// TestGetIPAddressesExceptingNondefaultRoutes tests the getIPAddressesExceptingNondefaultRoutes function +// It checks that the function returns at least one IP address and that the IP addresses returned are valid +// +// -- Doc autogenerated on 2022-05-12 15:01:28.925004 -- func TestGetIPAddressesExceptingNondefaultRoutes(t *testing.T) { addrs, err := getIPAddressesExceptingNondefaultRoutes(context.TODO()) diff --git a/utils/osutils_test.go b/utils/osutils_test.go index bceb71b17..00b00e671 100644 --- a/utils/osutils_test.go +++ b/utils/osutils_test.go @@ -11,6 +11,11 @@ import ( "github.com/stretchr/testify/assert" ) +// TestParseIPv6Valid tests valid IPv6 addresses +// It checks that the IPv6Check function returns true for valid IPv6 addresses +// It returns false for invalid IPv6 addresses +// +// -- Doc autogenerated on 2022-05-12 15:02:24.480017 -- func TestParseIPv6Valid(t *testing.T) { tests := map[string]struct { input string @@ -74,6 +79,11 @@ func TestParseIPv6Valid(t *testing.T) { } } +// TestParseIPv4Valid tests that the IPv6Check function returns false for valid IPv4 addresses +// It checks that the IPv6Check function returns false for valid IPv4 addresses +// It returns true for invalid IPv4 addresses +// +// -- Doc autogenerated on 2022-05-12 15:02:24.480017 -- func TestParseIPv4Valid(t *testing.T) { tests := map[string]struct { input string @@ -116,6 +126,10 @@ func TestParseIPv4Valid(t *testing.T) { } } +// TestSanitizeString tests the sanitizeString function +// It checks that the function strips out xterm control characters and trailing newlines +// +// -- Doc autogenerated on 2022-05-12 15:02:24.480017 -- func TestSanitizeString(t *testing.T) { tests := map[string]struct { input string @@ -138,6 +152,10 @@ func TestSanitizeString(t *testing.T) { } } +// TestPidRunningOrIdleRegex tests the pidRunningOrIdleRegex +// It checks for both positive and negative matches +// +// -- Doc autogenerated on 2022-05-12 15:02:24.480017 -- func TestPidRunningOrIdleRegex(t *testing.T) { log.Debug("Running TestPidRegexes...") @@ -177,6 +195,11 @@ func TestPidRunningOrIdleRegex(t *testing.T) { } } +// TestGetHostportIP tests the getHostportIP function +// It checks that the function returns the correct IP address +// for various inputs +// +// -- Doc autogenerated on 2022-05-12 15:02:24.480017 -- func TestGetHostportIP(t *testing.T) { type IPAddresses struct { InputIP string @@ -219,6 +242,11 @@ func TestGetHostportIP(t *testing.T) { } } +// TestEnsureHostportFormatted tests ensureHostportFormatted +// It checks that the function correctly formats IP addresses +// with and without ports +// +// -- Doc autogenerated on 2022-05-12 15:02:24.480017 -- func TestEnsureHostportFormatted(t *testing.T) { type IPAddresses struct { InputIP string @@ -266,6 +294,12 @@ func TestEnsureHostportFormatted(t *testing.T) { } } +// TestFormatPortal tests the formatPortal function +// It checks that the function correctly adds the default iSCSI port to an IP address +// It also checks that the function does not add the default iSCSI port to an IP address that already has a port +// It also checks that the function does not add the default iSCSI port to an IP address that already has a non-default port +// +// -- Doc autogenerated on 2022-05-12 15:02:24.480017 -- func TestFormatPortal(t *testing.T) { type IPAddresses struct { InputPortal string @@ -304,6 +338,10 @@ func TestFormatPortal(t *testing.T) { } } +// TestFilterTargets tests the filterTargets function +// It checks that the correct IQNs are returned for a given portal +// +// -- Doc autogenerated on 2022-05-12 15:02:24.480017 -- func TestFilterTargets(t *testing.T) { type FilterCase struct { CommandOutput string @@ -381,6 +419,10 @@ func TestFilterTargets(t *testing.T) { } } +// TestParseInitiatorIQNs tests the parseInitiatorIQNs function +// It checks that the function returns the expected initiator IQNs +// +// -- Doc autogenerated on 2022-05-12 15:02:24.480017 -- func TestParseInitiatorIQNs(t *testing.T) { ctx := context.TODO() tests := map[string]struct { diff --git a/utils/utils.go b/utils/utils.go index 008c6ffd0..57c9c22ea 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -58,12 +58,45 @@ var NFSVersionMinorRegex = regexp.MustCompile(`^minorversion=(?P\d)$`) type sizeUnit2 []string +// Len implements sort.Interface. +// It returns the length of the slice. +// Returns: +// int +// Example: +// s := sizeUnit2{} +// s.Len() +// >> 0 +// +// -- Doc autogenerated on 2022-05-12 15:04:08.156871 -- func (s sizeUnit2) Len() int { return len(s) } +// Swap implements the Swap method in sort.Interface +// Parameters: +// i: index of first element to swap +// j: index of second element to swap +// Returns: +// none +// Example: +// sizeUnit2 := []SizeUnit{SizeUnit{Size: 1}, SizeUnit{Size: 2}} +// sizeUnit2.Swap(0,1) +// +// -- Doc autogenerated on 2022-05-12 15:04:08.156871 -- func (s sizeUnit2) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +// Less is used to sort the sizeUnit2 slice +// It returns true if the length of the first string is greater than the length of the second string +// Parameters: +// i: index of the first string +// j: index of the second string +// Returns: +// true if the length of the first string is greater than the length of the second string +// Example: +// Less(2, 3) +// returns true if the length of the string at index 2 is greater than the length of the string at index 3 +// +// -- Doc autogenerated on 2022-05-12 15:04:08.156871 -- func (s sizeUnit2) Less(i, j int) bool { return len(s[i]) > len(s[j]) } @@ -114,12 +147,43 @@ func init() { type sizeUnit10 []string +// Len returns the length of the sizeUnit10 +// Returns: +// int: the length of the sizeUnit10 +// Example: +// s := sizeUnit10{1,2,3} +// fmt.Println(s.Len()) +// +// -- Doc autogenerated on 2022-05-12 15:04:08.156871 -- func (s sizeUnit10) Len() int { return len(s) } +// Swap implements the sort.Interface +// Parameters: +// i: index of the first element to swap +// j: index of the second element to swap +// Returns: +// none +// Example: +// s := []int{1,2,3} +// s.Swap(0,2) +// +// -- Doc autogenerated on 2022-05-12 15:04:08.156871 -- func (s sizeUnit10) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +// Less is used to sort the sizeUnit10 slice +// It returns true if the length of the first string is greater than the length of the second string +// Parameters: +// i - index of the first string +// j - index of the second string +// Returns: +// true if the length of the first string is greater than the length of the second string +// Example: +// sizeUnit10{ "1", "10", "100", "1000" }.Less(2, 3) +// returns true +// +// -- Doc autogenerated on 2022-05-12 15:04:08.156871 -- func (s sizeUnit10) Less(i, j int) bool { return len(s[i]) > len(s[j]) } @@ -317,6 +381,17 @@ func StringInSlice(s string, list []string) bool { return false } +// LogHTTPRequest logs an HTTP request +// Parameters: +// request: the HTTP request +// requestBody: the body of the HTTP request +// redactBody: whether to redact the body of the HTTP request +// Returns: +// None +// Example: +// LogHTTPRequest(request, requestBody, true) +// +// -- Doc autogenerated on 2022-05-12 15:04:08.156871 -- func LogHTTPRequest(request *http.Request, requestBody []byte, redactBody bool) { header := ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" footer := "--------------------------------------------------------------------------------" @@ -347,6 +422,18 @@ func LogHTTPRequest(request *http.Request, requestBody []byte, redactBody bool) header, request.Method, requestURL, headers, body, footer) } +// LogHTTPResponse logs the HTTP response +// Parameters: +// ctx - context +// response - HTTP response +// responseBody - HTTP response body +// redactBody - if true, the body will be redacted +// Returns: +// none +// Example: +// LogHTTPResponse(ctx, response, responseBody, true) +// +// -- Doc autogenerated on 2022-05-12 15:04:08.156871 -- func LogHTTPResponse(ctx context.Context, response *http.Response, responseBody []byte, redactBody bool) { header := "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" footer := "================================================================================" @@ -376,10 +463,28 @@ type HTTPError struct { StatusCode int } +// Error types +// It returns the error message as a string +// Returns: +// string: error message +// Example: +// e := utils.HTTPError{Status: "400 Bad Request"} +// fmt.Println(e.Error()) +// +// -- Doc autogenerated on 2022-05-12 15:04:08.156871 -- func (e HTTPError) Error() string { return fmt.Sprintf("HTTP error: %s", e.Status) } +// NewHTTPError returns an HTTPError if the response status code is >= 300 +// Parameters: +// response *http.Response +// Returns: +// *HTTPError +// Example: +// err := NewHTTPError(response) +// +// -- Doc autogenerated on 2022-05-12 15:04:08.156871 -- func NewHTTPError(response *http.Response) *HTTPError { if response.StatusCode < 300 { return nil @@ -562,6 +667,18 @@ func FilterIPs(ctx context.Context, ips, cidrs []string) ([]string, error) { return filteredIPs, nil } +// GetYAMLTagWithSpaceCount returns the indentation of a tag in a YAML file. +// It returns the tag with the indentation and the number of spaces. +// Parameters: +// text: The text of the YAML file. +// tagName: The name of the tag to search for. +// Returns: +// string: The tag with the indentation. +// int: The number of spaces in the indentation. +// Example: +// tag, indentation := utils.GetYAMLTagWithSpaceCount(text, "tagName") +// +// -- Doc autogenerated on 2022-05-12 15:04:08.156871 -- func GetYAMLTagWithSpaceCount(text, tagName string) (string, int) { // This matches pattern in a multiline string of type " {something}\n" @@ -579,6 +696,16 @@ func GetYAMLTagWithSpaceCount(text, tagName string) (string, int) { return "", 0 } +// CountSpacesBeforeText counts the number of spaces before the text +// It returns the number of spaces before the text +// Parameters: +// text: the text to count spaces before +// Returns: +// the number of spaces before the text +// Example: +// CountSpacesBeforeText(" Hello") returns 3 +// +// -- Doc autogenerated on 2022-05-12 15:04:08.156871 -- func CountSpacesBeforeText(text string) int { return len(text) - len(strings.TrimLeft(text, " \t")) } @@ -770,10 +897,27 @@ func GetRegexSubmatches(r *regexp.Regexp, s string) map[string]string { } // Detect if code is running in a container or not +// RunningInContainer returns true if the code is running in a container +// Returns: +// bool +// Example: +// utils.RunningInContainer() +// +// -- Doc autogenerated on 2022-05-12 15:04:08.156871 -- func RunningInContainer() bool { return os.Getenv("CSI_ENDPOINT") != "" } +// Max returns the larger of x or y. +// Parameters: +// x: first value +// y: second value +// Returns: +// the larger of x or y +// Example: +// Max(1, 2) => 2 +// +// -- Doc autogenerated on 2022-05-12 15:04:08.156871 -- func Max(x, y int64) int64 { if x > y { return x @@ -809,6 +953,19 @@ func MinInt64(a, b int64) int64 { return b } +// ValidateOctalUnixPermissions validates that the given string is a valid octal unix permissions value +// It returns an error if the given string is not a valid octal unix permissions value +// Parameters: +// perms: string to validate +// Returns: +// error: nil if the given string is a valid octal unix permissions value, otherwise an error +// Example: +// err := utils.ValidateOctalUnixPermissions("0755") +// if err != nil { +// handle error +// } +// +// -- Doc autogenerated on 2022-05-12 15:04:08.156871 -- func ValidateOctalUnixPermissions(perms string) error { permsRegex := regexp.MustCompile(`^[0-7]{4}$`) @@ -820,6 +977,20 @@ func ValidateOctalUnixPermissions(perms string) error { return nil } +// GenerateVolumePublishName generates the volume publish name +// It returns the volumeID.nodeID +// Parameters: +// volumeID: the volume ID +// nodeID: the node ID +// Returns: +// string: the volume publish name +// Example: +// volumeID := "8e0f9c1c-b3ac-40f5-8c7a-d9b68a9a95a2" +// nodeID := "node1" +// volumePublishName := utils.GenerateVolumePublishName(volumeID, nodeID) +// // volumePublishName is "8e0f9c1c-b3ac-40f5-8c7a-d9b68a9a95a2.node1" +// +// -- Doc autogenerated on 2022-05-12 15:04:08.156871 -- func GenerateVolumePublishName(volumeID, nodeID string) string { return fmt.Sprintf(volumeID + "." + nodeID) } @@ -855,6 +1026,25 @@ func ToStringRedacted(structPointer interface{}, redactList []string, configVal return } +// RedactSecretsFromString redacts secrets from a string +// It returns a string with the secrets redacted +// Parameters: +// stringToSanitize - the string to sanitize +// replacements - a map of secrets to redact and their replacement values +// useRegex - whether or not to use regex to redact the secrets +// Returns: +// string - the sanitized string +// Example: +// stringToSanitize := "secret1=foo secret2=bar" +// replacements := map[string]string{ +// "secret1=.*": "secret1=********", +// "secret2=.*": "secret2=********", +// } +// useRegex := true +// RedactSecretsFromString(stringToSanitize, replacements, useRegex) +// // secret1=******** secret2=******** +// +// -- Doc autogenerated on 2022-05-12 15:04:08.156871 -- func RedactSecretsFromString(stringToSanitize string, replacements map[string]string, useRegex bool) string { compileError := "regex matching the secret could not compile, so the entire string has been redacted" diff --git a/utils/utils_test.go b/utils/utils_test.go index 3280e62c9..c94f2c791 100644 --- a/utils/utils_test.go +++ b/utils/utils_test.go @@ -50,12 +50,24 @@ var testCustomStringSlice = []CustomString{ "superbingstring", } +// TestMain is the main function for the test suite +// It checks for any errors and exits with the appropriate status code +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestMain(m *testing.M) { // Disable any standard log output log.SetOutput(ioutil.Discard) os.Exit(m.Run()) } +// TestPow tests the Pow function +// It checks the following cases: +// 1024^0 == 1 +// 1024^1 == 1024 +// 1024^2 == 1048576 +// 1024^3 == 1073741824 +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestPow(t *testing.T) { log.Debug("Running TestPow...") @@ -76,6 +88,20 @@ func TestPow(t *testing.T) { } } +// TestConvertSizeToBytes tests the ConvertSizeToBytes function +// It checks the following: +// - 512 == 512 +// - 1KB == 1000 +// - 1Ki == 1024 +// - 1KiB == 1024 +// - 4k == 4096 +// - 1gi == 1073741824 +// - 1Gi == 1073741824 +// - 1GiB == 1073741824 +// - 1gb == 1000000000 +// - 1g == 1073741824 +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestConvertSizeToBytes(t *testing.T) { log.Debug("Running TestConvertSizeToBytes...") @@ -101,6 +127,10 @@ func TestConvertSizeToBytes(t *testing.T) { } } +// TestGetV tests the GetV function +// It checks that the correct value is returned when the key is present and when it is not +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestGetV(t *testing.T) { log.Debug("Running TestGetV...") @@ -116,6 +146,13 @@ func TestGetV(t *testing.T) { } } +// TestVolumeSizeWithinTolerance tests the VolumeSizeWithinTolerance function +// It checks the following cases: +// 1. Requested size is within delta of current size +// 2. Requested size is exactly the same as current size +// 3. Requested size is outside of delta of current size +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestVolumeSizeWithinTolerance(t *testing.T) { log.Debug("Running TestVolumeSizeWithinTolerance...") @@ -148,6 +185,10 @@ func TestVolumeSizeWithinTolerance(t *testing.T) { } +// TestSliceContainsString tests the SliceContainsString function +// It checks for both positive and negative cases +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestSliceContainsString(t *testing.T) { log.Debug("Running TestSliceContainsString...") @@ -173,6 +214,12 @@ func TestSliceContainsString(t *testing.T) { } } +// TestSliceContains tests the SliceContains function +// It checks the following: +// - Positive cases +// - Negative cases +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestSliceContains(t *testing.T) { log.Debug("Running TestSliceContains...") @@ -215,6 +262,10 @@ func TestSliceContains(t *testing.T) { } } +// TestSliceContainElements tests the SliceContainsElements function +// It checks for both ContainsAll and ContainsSome +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestSliceContainElements(t *testing.T) { log.Debug("Running TestSliceContainElements...") @@ -320,6 +371,11 @@ func TestSliceContainElements(t *testing.T) { } } +// TestRemoveStringFromSlice tests the RemoveStringFromSlice function +// It checks that the string is removed from the slice and that the slice is not modified +// if the string is not in the slice +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestRemoveStringFromSlice(t *testing.T) { log.Debug("Running TestRemoveStringFromSlice...") @@ -350,6 +406,11 @@ func TestRemoveStringFromSlice(t *testing.T) { } } +// TestRemoveStringFromSliceConditionally tests the RemoveStringFromSliceConditionally function +// It checks that the function removes the correct elements from the slice +// It returns an error if the function does not remove the correct elements +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestRemoveStringFromSliceConditionally(t *testing.T) { log.Debug("Running TestRemoveStringFromSlice...") @@ -402,6 +463,10 @@ func TestRemoveStringFromSliceConditionally(t *testing.T) { } } +// TestSliceContainsStringCaseInsensitive tests the SliceContainsStringCaseInsensitive function +// It checks both positive and negative cases +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestSliceContainsStringCaseInsensitive(t *testing.T) { log.Debug("Running TestSliceContainsStringCaseInsensitive...") @@ -427,6 +492,11 @@ func TestSliceContainsStringCaseInsensitive(t *testing.T) { } } +// TestSliceContainsStringConditionally tests the SliceContainsStringConditionally function +// It checks that the function returns the expected result for a variety of inputs +// It returns an error if the function does not return the expected result +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestSliceContainsStringConditionally(t *testing.T) { log.Debug("Running TestSliceContainsStringConditionally...") @@ -456,6 +526,10 @@ func TestSliceContainsStringConditionally(t *testing.T) { } } +// TestSplitImageDomain tests the SplitImageDomain function. +// It checks that the domain and remainder are split correctly. +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestSplitImageDomain(t *testing.T) { log.Debug("Running TestSplitImageDomain...") @@ -472,6 +546,11 @@ func TestSplitImageDomain(t *testing.T) { assert.Equal(t, "k8scsi/csi-node-driver-registrar:v1.0.2", remainder) } +// TestReplaceImageRegistry tests the ReplaceImageRegistry function +// It checks that the image is not changed if the registry is empty +// It checks that the image is changed if the registry is not empty +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestReplaceImageRegistry(t *testing.T) { log.Debug("Running ReplaceImageRegistry...") @@ -485,6 +564,10 @@ func TestReplaceImageRegistry(t *testing.T) { assert.Equal(t, "mydomain:5000/k8scsi/csi-node-driver-registrar:v1.0.2", image) } +// TestFilterIPs tests the FilterIPs function +// It checks that the function returns the correct IPs for a variety of inputs +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestFilterIPs(t *testing.T) { log.Debug("Running TestFilterIPs...") @@ -566,6 +649,10 @@ text {REPLACE-4} ` +// TestGetYAMLTagWithSpaceCount tests the GetYAMLTagWithSpaceCount function +// It checks that the correct tag is returned and that the correct number of spaces is returned +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestGetYAMLTagWithSpaceCount(t *testing.T) { log.Debug("Running TestGetYAMLTagWithSpaceCount...") @@ -592,6 +679,10 @@ func TestGetYAMLTagWithSpaceCount(t *testing.T) { assert.Equal(t, spaces, 4) } +// TestCountSpacesBeforeText tests the CountSpacesBeforeText function. +// It checks that the function returns the correct number of spaces before the text. +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestCountSpacesBeforeText(t *testing.T) { log.Debug("Running TestCountSpacesBeforeText...") @@ -614,6 +705,10 @@ func TestCountSpacesBeforeText(t *testing.T) { } } +// TestGetNFSVersionFromMountOptions tests the GetNFSVersionFromMountOptions function +// It checks that the correct version is returned for different mount options +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestGetNFSVersionFromMountOptions(t *testing.T) { log.Debug("Running TestGetNFSVersionFromMountOptions...") @@ -658,6 +753,10 @@ func TestGetNFSVersionFromMountOptions(t *testing.T) { } } +// TestGetNFSVersionMountOptions tests the GetNFSVersionMountOptions function +// It checks that the correct NFS version is returned from the mount options +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestGetNFSVersionMountOptions(t *testing.T) { log.Debug("Running TestGetNFSVersionMountOptions...") @@ -691,6 +790,10 @@ func TestGetNFSVersionMountOptions(t *testing.T) { } } +// TestSetNFSVersionMountOptions tests the SetNFSVersionMountOptions function +// It checks that the correct mount options are returned for the given input +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestSetNFSVersionMountOptions(t *testing.T) { log.Debug("Running TestSetNFSVersionMountOptions...") @@ -735,6 +838,19 @@ defaults { ` +// TestGetFindMultipathValue tests the GetFindMultipathValue function +// It checks the following cases: +// 1. find_multipaths is set to no +// 2. find_multipaths is commented out +// 3. find_multipaths is set to yes +// 4. find_multipaths is set to on +// 5. find_multipaths is set to off +// 6. find_multipaths is set to random +// 7. find_multipaths is set to smart +// 8. find_multipaths is set to greedy +// 9. find_multipaths is set to 'no' +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestGetFindMultipathValue(t *testing.T) { log.Debug("Running TestGetFindMultipathValue...") @@ -802,6 +918,19 @@ func TestGetFindMultipathValue(t *testing.T) { assert.Equal(t, "no", findMultipathsValue) } +// TestSplitString tests the SplitString function. +// It checks the following cases: +// - a,b,c +// - a,b, c +// - a,b,c +// - a,b,c +// - a,b,c +// - "" +// - "" +// - " " +// - ;a;b +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestSplitString(t *testing.T) { log.Debug("Running TestSplitString...") @@ -832,6 +961,11 @@ func TestSplitString(t *testing.T) { assert.Equal(t, []string{"", "a", "b"}, stringList) } +// TestReplaceAtIndex tests the ReplaceAtIndex function +// It checks that the function returns the expected string +// and error for various inputs +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestReplaceAtIndex(t *testing.T) { actual, err := ReplaceAtIndex("foo", 'f', 0) assert.Nil(t, err) @@ -858,6 +992,10 @@ func TestReplaceAtIndex(t *testing.T) { assert.Equal(t, "boo", actual) } +// TestMinInt64 tests the MinInt64 function +// It checks that the minimum value is returned for a variety of inputs +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestMinInt64(t *testing.T) { log.Debug("Running TestMinInt64...") assert.Equal(t, int64(2), MinInt64(2, 3)) @@ -870,6 +1008,15 @@ func TestMinInt64(t *testing.T) { assert.Equal(t, int64(2), MinInt64(2, 2)) } +// TestValidateCIDRSet tests the ValidateCIDRSet function +// It checks the following: +// 1. A set of valid CIDR blocks does not return an error +// 2. An error is returned when a set of invalid CIDR blocks is passed in +// 3. An error is returned when a set of valid and invalid CIDR blocks is passed in +// 4. The error contains the invalid CIDR blocks +// It returns an error if any of the tests fail +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestValidateCIDRSet(t *testing.T) { ctx := context.TODO() @@ -939,6 +1086,10 @@ func TestValidateCIDRSet(t *testing.T) { } } +// TestValidateOctalUnixPermissions tests the ValidateOctalUnixPermissions function +// It checks that the function returns the expected error for a variety of inputs +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestValidateOctalUnixPermissions(t *testing.T) { var tests = []struct { @@ -967,6 +1118,10 @@ func TestValidateOctalUnixPermissions(t *testing.T) { } } +// TestMustParseMajorMinorVersion tests the MustParseMajorMinorVersion function +// It checks that it returns the expected value for a valid input and panics for invalid inputs +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestMustParseMajorMinorVersion(t *testing.T) { majorMinor := "v1.23" majorMinorVersion := MustParseSemantic(majorMinor + ".0").ToMajorMinorVersion() @@ -980,6 +1135,11 @@ func TestMustParseMajorMinorVersion(t *testing.T) { " major version should cause a panic") } +// TestRedactSecretsFromString tests the RedactSecretsFromString function +// It checks that the function properly redacts secrets from a string +// It also checks that the function returns a safe string when the regex cannot be compiled +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestRedactSecretsFromString(t *testing.T) { passphrase := "chap-initiator-secret" outboundPassphrase := "chap-target-initiator-secret" @@ -1057,6 +1217,10 @@ func TestRedactSecretsFromString(t *testing.T) { } } +// TestGetVerifiedBlockFsType tests the GetVerifiedBlockFsType function. +// It checks that the function returns the expected fsType and error. +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestGetVerifiedBlockFsType(t *testing.T) { log.Debug("Running TestGetVerifiedBlockFsType...") @@ -1087,6 +1251,10 @@ func TestGetVerifiedBlockFsType(t *testing.T) { } } +// TestVerifyFilesystemSupport verifies the VerifyFilesystemSupport function +// It checks for supported filesystems and unsupported filesystems +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestVerifyFilesystemSupport(t *testing.T) { log.Debug("Running TestVerifyFilesystemSupport...") @@ -1121,6 +1289,10 @@ func TestVerifyFilesystemSupport(t *testing.T) { } } +// TestAppendToStringList tests the AppendToStringList function. +// It checks that the function correctly appends a new item to a string list. +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestAppendToStringList(t *testing.T) { log.Debug("Running TestAppendToStringList...") @@ -1163,6 +1335,10 @@ func TestAppendToStringList(t *testing.T) { } } +// TestSanitizeMountOptions tests the SanitizeMountOptions function +// It checks that the correct mount options are removed +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestSanitizeMountOptions(t *testing.T) { log.Debug("Running TestSanitizeMountOptions...") @@ -1189,6 +1365,11 @@ func TestSanitizeMountOptions(t *testing.T) { } } +// TestAreMountOptionsInList tests the AreMountOptionsInList function +// It checks that the function returns true if the mount options are in the list +// and false if they are not. +// +// -- Doc autogenerated on 2022-05-12 15:10:00.616723 -- func TestAreMountOptionsInList(t *testing.T) { log.Debug("Running TestAreMountOptionsInList...") diff --git a/utils/version.go b/utils/version.go index 9741894fa..925f18211 100644 --- a/utils/version.go +++ b/utils/version.go @@ -45,6 +45,27 @@ var ( extraMatchRE = regexp.MustCompile(`^(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?\s*$`) ) +// parse parses a version string. +// +// If semver is true, the version must be a semantic version. +// If datever is true, the version must be a date version. +// If neither is true, the version must be at least a major.minor version. +// It returns an error if the version string is invalid. +// Parameters: +// str: the version string to parse +// semver: whether to parse as a semantic version +// datever: whether to parse as a date version +// Returns: +// *Version: the parsed version +// error: an error if the version string is invalid +// Example: +// version, err := parse("1.2.3", true, false) +// if err != nil { +// fmt.Println(err) +// } +// fmt.Println(version) +// +// -- Doc autogenerated on 2022-05-12 15:16:15.188335 -- func parse(str string, semver bool, datever bool) (*Version, error) { parts := versionMatchRE.FindStringSubmatch(str) if parts == nil { @@ -157,22 +178,66 @@ func MustParseDate(str string) *Version { return v } +// MajorVersion returns the major version of the version string +// Returns: +// uint: The major version +// Example: +// v := &Version{components: []uint{1, 2, 3, 4}} +// v.MajorVersion() returns 1 +// +// -- Doc autogenerated on 2022-05-12 15:16:15.188335 -- func (v *Version) MajorVersion() uint { return v.components[0] } +// MajorVersionString returns the major version as a string +// Returns: +// string - major version +// Example: +// version := NewVersion("1.2.3") +// version.MajorVersionString() // "1" +// +// -- Doc autogenerated on 2022-05-12 15:16:15.188335 -- func (v *Version) MajorVersionString() string { return strconv.FormatUint(uint64(v.components[0]), 10) } +// MinorVersion returns the minor version of the version string +// Returns: +// uint - minor version +// Example: +// v := NewVersion("1.2.3") +// v.MinorVersion() +// // Output: 2 +// +// -- Doc autogenerated on 2022-05-12 15:16:15.188335 -- func (v *Version) MinorVersion() uint { return v.components[1] } +// MinorVersionString returns the minor version as a string +// Returns: +// string: minor version +// Example: +// v := utils.NewVersion("3.5.0") +// v.MinorVersionString() +// Returns: +// "5" +// +// -- Doc autogenerated on 2022-05-12 15:16:15.188335 -- func (v *Version) MinorVersionString() string { return strconv.FormatUint(uint64(v.components[1]), 10) } +// PatchVersion returns the patch version of the version. +// Returns: +// 0 if the version is not in the form of major.minor.patch +// Example: +// v := Version{[]uint{1, 2, 3}} +// v.PatchVersion() +// Output: 3 +// +// -- Doc autogenerated on 2022-05-12 15:16:15.188335 -- func (v *Version) PatchVersion() uint { if len(v.components) < 3 { return 0 @@ -180,6 +245,15 @@ func (v *Version) PatchVersion() uint { return v.components[2] } +// PreRelease returns the pre-release string of the version. +// Returns: +// string: the pre-release string of the version +// Example: +// v := NewVersion("1.0.0-alpha") +// fmt.Println(v.PreRelease()) +// // Output: alpha +// +// -- Doc autogenerated on 2022-05-12 15:16:15.188335 -- func (v *Version) PreRelease() string { return v.preRelease } @@ -348,10 +422,26 @@ func (v *Version) Compare(other string) (int, error) { return v.compareInternal(ov), nil } +// ToMajorMinorVersion returns a new Version with the patch version set to 0. +// Returns: +// *Version: A new Version with the patch version set to 0. +// Example: +// version := MustParseGeneric("1.2.3") +// version.ToMajorMinorVersion() // Returns 1.2.0 +// +// -- Doc autogenerated on 2022-05-12 15:16:15.188335 -- func (v *Version) ToMajorMinorVersion() *Version { return MustParseGeneric(fmt.Sprintf("%d.%d", v.MajorVersion(), v.MinorVersion())) } +// ToMajorMinorString returns a string representation of the major and minor version +// Returns: +// "major.minor" +// Example: +// v := NewVersion("1.2.3") +// v.ToMajorMinorString() // "1.2" +// +// -- Doc autogenerated on 2022-05-12 15:16:15.188335 -- func (v *Version) ToMajorMinorString() string { return fmt.Sprintf("%d.%d", v.MajorVersion(), v.MinorVersion()) } diff --git a/utils/version_test.go b/utils/version_test.go index ff9c0fab8..ac115254e 100644 --- a/utils/version_test.go +++ b/utils/version_test.go @@ -27,6 +27,27 @@ type testItem struct { equalsPrev bool } +// testOne tests a single version string. +// It returns an error if the version string does not round-trip, +// or if it is not ordered correctly relative to the previous version string. +// Parameters: +// v: the version to test +// item: the test item for the version +// prev: the previous test item +// Returns: +// error: an error if the version does not round-trip or is not ordered correctly +// Example: +// var v *Version +// var err error +// for _, item := range testItems { +// err = testOne(v, item, prev) +// if err != nil { +// return err +// } +// prev = item +// } +// +// -- Doc autogenerated on 2022-05-12 15:19:23.516989 -- func testOne(v *Version, item, prev testItem) error { str := v.String() if item.unparsed == "" { @@ -57,6 +78,11 @@ func testOne(v *Version, item, prev testItem) error { return nil } +// TestSemanticVersions tests the ParseSemantic function. +// It checks that the parsed version is correct, and that +// the ordering of the versions is correct. +// +// -- Doc autogenerated on 2022-05-12 15:19:23.516989 -- func TestSemanticVersions(t *testing.T) { tests := []testItem{ // This is every version string that appears in the 2.0 semver spec, @@ -112,6 +138,11 @@ func TestSemanticVersions(t *testing.T) { } } +// TestBadSemanticVersions tests that invalid semver strings are rejected. +// It checks that the parser is not too permissive, and that it rejects +// invalid semver strings. +// +// -- Doc autogenerated on 2022-05-12 15:19:23.516989 -- func TestBadSemanticVersions(t *testing.T) { tests := []string{ // "MUST take the form X.Y.Z" @@ -168,6 +199,11 @@ func TestBadSemanticVersions(t *testing.T) { } } +// TestDateVersions tests the date version parsing +// It checks that the parsed version is correct, and that +// it is ordered correctly. +// +// -- Doc autogenerated on 2022-05-12 15:19:23.516989 -- func TestDateVersions(t *testing.T) { tests := []testItem{ // This is every version string that appears in the 2.0 semver spec, @@ -221,6 +257,16 @@ func TestDateVersions(t *testing.T) { } } +// TestBadDateVersions tests that invalid date versions are rejected. +// It checks that all of the following are rejected: +// - invalid format +// - invalid month +// - invalid pre-release +// - invalid build metadata +// - whitespace +// - "v"-prefix +// +// -- Doc autogenerated on 2022-05-12 15:19:23.516989 -- func TestBadDateVersions(t *testing.T) { tests := []string{ // "MUST take the form X.Y.Z" @@ -280,6 +326,11 @@ func TestBadDateVersions(t *testing.T) { } } +// TestGenericVersions tests that the generic version parser works as expected. +// It checks that the generic parser parses the same strings as the semantic +// parser, and that it parses some additional strings. +// +// -- Doc autogenerated on 2022-05-12 15:19:23.516989 -- func TestGenericVersions(t *testing.T) { tests := []testItem{ // This is all of the strings from TestSemanticVersions, plus some strings @@ -350,6 +401,10 @@ func TestGenericVersions(t *testing.T) { } } +// TestBadGenericVersions tests that invalid versions fail to parse +// It checks that the error is not nil +// +// -- Doc autogenerated on 2022-05-12 15:19:23.516989 -- func TestBadGenericVersions(t *testing.T) { tests := []string{ "1", From 8b0626d4c6024a8152bbd42e833267d7588182c9 Mon Sep 17 00:00:00 2001 From: "Roussin, Jerome" Date: Thu, 12 May 2022 16:53:16 -0400 Subject: [PATCH 3/5] Fixed bug that removed one-line functions --- utils/errors.go | 529 +++++++++++++++++++++++++++--------------------- 1 file changed, 297 insertions(+), 232 deletions(-) diff --git a/utils/errors.go b/utils/errors.go index 03ba98d21..c0dd532ed 100644 --- a/utils/errors.go +++ b/utils/errors.go @@ -15,17 +15,22 @@ import ( type bootstrapError struct { message string } -// BootstrapError is a special error -// It returns a string with the error message -// and is used to indicate that Trident failed to initialize + +func (e *bootstrapError) Error() string { return e.message } + +// BootstrapError is a wrapper for errors that occur during Trident bootstrap. +// It returns a string that can be used to display the error to the user. // Parameters: -// err - the error message +// err - the error that occurred // Returns: -// a bootstrapError +// error - the bootstrap error // Example: -// err := utils.BootstrapError(errors.New("Something went wrong")) +// err := utils.BootstrapError(err) +// log.WithFields(log.Fields{ +// "error": err.Error(), +// }).Error("Trident initialization failed.") // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func BootstrapError(err error) error { return &bootstrapError{ fmt.Sprintf("Trident initialization failed; %s", err.Error()), @@ -36,13 +41,13 @@ func BootstrapError(err error) error { // Parameters: // err: error // Returns: -// true if the error is a bootstrap error +// bool // Example: -// if IsBootstrapError(err) { -// // do stuff +// if utils.IsBootstrapError(err) { +// log.Error("Bootstrap error") // } // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsBootstrapError(err error) bool { if err == nil { return false @@ -58,32 +63,34 @@ func IsBootstrapError(err error) bool { type foundError struct { message string } -// FoundError is an error -// It returns true for IsFoundError + +func (e *foundError) Error() string { return e.message } + +// FoundError is a custom error +// It returns a string message // Parameters: -// message - the error message -// Return: -// error - the error +// message string +// Returns: +// error // Example: -// err := FoundError("found") -// if IsFoundError(err) { -// // handle found error +// if err := FoundError("not found"); err != nil { +// fmt.Println(err) // } // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func FoundError(message string) error { return &foundError{message} } // IsFoundError returns true if the error is a foundError // Parameters: -// err: the error to check +// err - error to check // Returns: -// true if the error is a foundError, false otherwise +// true if the error is a foundError // Example: -// isFound := utils.IsFoundError(err) +// foundError := IsFoundError(err) // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsFoundError(err error) bool { if err == nil { return false @@ -99,31 +106,32 @@ func IsFoundError(err error) bool { type notFoundError struct { message string } + +func (e *notFoundError) Error() string { return e.message } + // NotFoundError is a custom error -// It returns a 404 status code +// It returns a 404 error // Parameters: -// message - the message to return +// message (string) - the error message // Returns: // error - the error // Example: -// err := NotFoundError("The requested volume does not exist") +// err := utils.NotFoundError("The resource could not be found") // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func NotFoundError(message string) error { return ¬FoundError{message} } -// IsNotFoundError returns true if the error is a not found error +// IsNotFoundError returns true if the error is a not found error. // Parameters: // err: the error to check // Returns: // true if the error is a not found error // Example: -// if utils.IsNotFoundError(err) { -// // handle error -// } +// IsNotFoundError(fmt.Errorf("not found")) // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsNotFoundError(err error) bool { if err == nil { return false @@ -136,15 +144,17 @@ func IsNotFoundError(err error) bool { // resourceNotFoundError - To identify external not found errors // /////////////////////////////////////////////////////////////////////////// -// IsResourceNotFoundError returns true if the error is a resource not found error +// IsResourceNotFoundError returns true if the error is a resource not found error. // Parameters: -// err: the error to check -// Returns: -// true if the error is a resource not found error +// err: the error to check +// Return: +// true if the error is a resource not found error, false otherwise // Example: -// IsResourceNotFoundError(errors.New("Not Found")) +// if IsResourceNotFoundError(err) { +// // handle resource not found error +// } // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsResourceNotFoundError(err error) bool { if err == nil { return false @@ -159,16 +169,19 @@ func IsResourceNotFoundError(err error) bool { type notReadyError struct { message string } -// NotReadyError is returned when Trident is initializing. -// It returns a string that can be used in an HTTP response. + +func (e *notReadyError) Error() string { return e.message } + +// NotReadyError is an error +// It returns a string that Trident is initializing, please try again later // Returns: // *notReadyError // Example: // if err := utils.NotReadyError(); err != nil { -// return err +// fmt.Println(err.Error()) // } // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func NotReadyError() error { return ¬ReadyError{ "Trident is initializing, please try again later", @@ -177,13 +190,13 @@ func NotReadyError() error { // IsNotReadyError returns true if the error is a not ready error // Parameters: -// err - error to check +// err - the error to check // Returns: -// true if the error is a not ready error +// true if the error is a not ready error, false otherwise // Example: -// utils.IsNotReadyError(err) +// err := utils.IsNotReadyError(err) // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsNotReadyError(err error) bool { if err == nil { return false @@ -199,30 +212,34 @@ func IsNotReadyError(err error) bool { type unsupportedError struct { message string } -// UnsupportedError is an error that indicates that a feature is not supported. -// It returns a string that can be used to display the error to the user. + +func (e *unsupportedError) Error() string { return e.message } + +// UnsupportedError is an error that is returned when a feature is not supported +// It returns a message that can be displayed to the user // Parameters: -// message - the error message +// message - the message to be displayed // Returns: -// an error object +// error - the error object // Example: -// err := utils.UnsupportedError("This feature is not supported") +// err := UnsupportedError("Snapshot creation is not supported on this storage driver") // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func UnsupportedError(message string) error { return &unsupportedError{message} } // IsUnsupportedError returns true if the error is an unsupportedError // Parameters: -// err - the error to check +// err - error to check // Returns: -// true if the error is an unsupportedError +// true if the error is an unsupportedError // Example: -// err := utils.UnsupportedError("test") -// utils.IsUnsupportedError(err) // returns true +// if IsUnsupportedError(err) { +// // handle unsupported error +// } // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsUnsupportedError(err error) bool { if err == nil { return false @@ -238,31 +255,32 @@ func IsUnsupportedError(err error) bool { type volumeCreatingError struct { message string } -// VolumeCreatingError is an error -// It returns a message + +func (e *volumeCreatingError) Error() string { return e.message } + +// VolumeCreatingError is returned when a volume is being created +// It returns a message that can be used to describe the error // Parameters: -// message string +// message: the message to be returned // Returns: -// error +// error: an error object // Example: -// myError := utils.VolumeCreatingError("error message") +// err := utils.VolumeCreatingError("Error creating volume") // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func VolumeCreatingError(message string) error { return &volumeCreatingError{message} } // IsVolumeCreatingError returns true if the error is a volumeCreatingError // Parameters: -// err - the error to check -// Return: +// err - error to check +// Returns: // true if the error is a volumeCreatingError // Example: -// if IsVolumeCreatingError(err) { -// // do something -// } +// utils.IsVolumeCreatingError(err) // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsVolumeCreatingError(err error) bool { if err == nil { return false @@ -278,29 +296,34 @@ func IsVolumeCreatingError(err error) bool { type volumeDeletingError struct { message string } + +func (e *volumeDeletingError) Error() string { return e.message } + // VolumeDeletingError is an error -// It returns the message +// It returns a message // Parameters: -// message string -// Returns: +// message: the error message +// Return: // error // Example: -// err := utils.VolumeDeletingError("message") +// err := utils.VolumeDeletingError("volume deleting error") // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func VolumeDeletingError(message string) error { return &volumeDeletingError{message} } // IsVolumeDeletingError returns true if the error is a volumeDeletingError // Parameters: -// err - the error to check -// Returns: +// err: error to check +// Return: // true if the error is a volumeDeletingError // Example: -// IsVolumeDeletingError(err) +// if IsVolumeDeletingError(err) { +// // do something +// } // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsVolumeDeletingError(err error) bool { if err == nil { return false @@ -316,30 +339,37 @@ func IsVolumeDeletingError(err error) bool { type timeoutError struct { message string } + +func (e *timeoutError) Error() string { return e.message } + // TimeoutError is a custom error -// It returns a string message +// It returns a string with the error message // Parameters: -// message string -// Return: -// error +// message - error message +// Returns: +// error - error object // Example: -// err := utils.TimeoutError("My error message") -// fmt.Println(err) +// err := utils.TimeoutError("error message") +// if err != nil { +// fmt.Println(err) +// } // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func TimeoutError(message string) error { return &timeoutError{message} } // IsTimeoutError returns true if the error is a timeout error // Parameters: -// err: the error to check +// err: error // Returns: -// true if the error is a timeout error +// bool // Example: -// IsTimeoutError(errors.New("timeout")) +// if IsTimeoutError(err) { +// ... +// } // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsTimeoutError(err error) bool { if err == nil { return false @@ -355,19 +385,21 @@ func IsTimeoutError(err error) bool { type unsupportedKubernetesVersionError struct { message string } -// UnsupportedKubernetesVersionError is returned when the Kubernetes version is not supported -// It returns a string that can be used to display the error message + +func (e *unsupportedKubernetesVersionError) Error() string { return e.message } + +// UnsupportedKubernetesVersionError is an error that is returned when the Kubernetes version is not supported +// It returns a message that includes the original error message // Parameters: -// err: the error message +// err - the original error message // Returns: -// error: the error message +// an error that includes the original error message // Example: -// err := utils.UnsupportedKubernetesVersionError(err) -// if err != nil { -// return fmt.Errorf("%s", err) -// } +// err := utils.UnsupportedKubernetesVersionError(errors.New("unsupported Kubernetes version")) +// fmt.Println(err.Error()) +// // Output: unsupported Kubernetes version; unsupported Kubernetes version // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func UnsupportedKubernetesVersionError(err error) error { return &unsupportedKubernetesVersionError{ message: fmt.Sprintf("unsupported Kubernetes version; %s", err.Error()), @@ -376,15 +408,15 @@ func UnsupportedKubernetesVersionError(err error) error { // IsUnsupportedKubernetesVersionError returns true if the error is an unsupportedKubernetesVersionError // Parameters: -// err - the error to check -// Return: -// true if the error is an unsupportedKubernetesVersionError, false otherwise +// err: the error to check +// Returns: +// true if the error is an unsupportedKubernetesVersionError // Example: -// if IsUnsupportedKubernetesVersionError(err) { -// log.Error("Unsupported Kubernetes version") -// } +// if utils.IsUnsupportedKubernetesVersionError(err) { +// // error is an unsupportedKubernetesVersionError +// } // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsUnsupportedKubernetesVersionError(err error) bool { if err == nil { return false @@ -400,16 +432,19 @@ func IsUnsupportedKubernetesVersionError(err error) bool { type reconcileDeferredError struct { message string } -// ReconcileDeferredError is an error -// It returns a message and a boolean + +func (e *reconcileDeferredError) Error() string { return e.message } + +// ReconcileDeferredError is a special error +// It returns a special error that can be used to defer reconciliation // Parameters: -// err - the error to return +// err - error message // Returns: -// the error +// error - error object // Example: -// err := utils.ReconcileDeferredError(errors.New("Some error")) +// err := ReconcileDeferredError(errors.New("deferred")) // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func ReconcileDeferredError(err error) error { return &reconcileDeferredError{ message: err.Error(), @@ -418,15 +453,15 @@ func ReconcileDeferredError(err error) error { // IsReconcileDeferredError returns true if the error is a ReconcileDeferredError // Parameters: -// err - error to check -// Return: -// true if the error is a ReconcileDeferredError, false otherwise +// err - the error to check +// Returns: +// true if the error is a ReconcileDeferredError // Example: -// if utils.IsReconcileDeferredError(err) { -// // ... -// } +// if utils.IsReconcileDeferredError(err) { +// // do something +// } // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsReconcileDeferredError(err error) bool { if err == nil { return false @@ -442,32 +477,33 @@ func IsReconcileDeferredError(err error) bool { type reconcileIncompleteError struct { message string } -// ReconcileIncompleteError is an error that indicates that a reconciliation is not complete. -// It returns true for IsReconcileIncompleteError. + +func (e *reconcileIncompleteError) Error() string { return e.message } + +// ReconcileIncompleteError is an error that indicates that the reconcile is incomplete +// It returns true for IsReconcileIncompleteError // Returns: // true // Example: -// if err := reconciler.Reconcile(request); err != nil && IsReconcileIncompleteError(err) { -// return reconcile.Result{}, nil -// } +// err := ReconcileIncompleteError() // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func ReconcileIncompleteError() error { return &reconcileIncompleteError{ message: "reconcile incomplete", } } -// ConvertToReconcileIncompleteError converts an error to a reconcileIncompleteError -// It returns the original error if it is already a reconcileIncompleteError +// ConvertToReconcileIncompleteError returns a new error that indicates the reconcile is incomplete // Parameters: -// err: the error to convert +// err - the original error // Returns: -// the converted error +// a new error that indicates the reconcile is incomplete // Example: -// reconcileIncompleteError := ConvertToReconcileIncompleteError(err) +// err := errors.New("Incomplete") +// newErr := ConvertToReconcileIncompleteError(err) // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func ConvertToReconcileIncompleteError(err error) error { return &reconcileIncompleteError{ message: err.Error(), @@ -480,11 +516,10 @@ func ConvertToReconcileIncompleteError(err error) error { // Returns: // true if the error is a reconcileIncompleteError, false otherwise // Example: -// if IsReconcileIncompleteError(err) { -// log.Errorf("reconcile error: %v", err) -// } +// err := errors.New("error") +// IsReconcileIncompleteError(err) // false // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsReconcileIncompleteError(err error) bool { if err == nil { return false @@ -500,18 +535,19 @@ func IsReconcileIncompleteError(err error) bool { type reconcileFailedError struct { message string } -// ReconcileFailedError is an error that is returned when a reconcile fails. -// It returns a message that includes the error that caused the reconcile to fail. + +func (e *reconcileFailedError) Error() string { return e.message } + +// ReconcileFailedError is an error +// It returns a string with the error message // Parameters: -// err - the error that caused the reconcile to fail +// err: the error message // Returns: -// a new error that includes the error that caused the reconcile to fail +// error: the error // Example: -// if err := r.Reconcile(request); err != nil { -// return utils.ReconcileFailedError(err) -// } +// err := utils.ReconcileFailedError(err) // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func ReconcileFailedError(err error) error { return &reconcileFailedError{ message: fmt.Sprintf("reconcile failed; %s", err.Error()), @@ -520,16 +556,15 @@ func ReconcileFailedError(err error) error { // IsReconcileFailedError returns true if the error is a reconcileFailedError // Parameters: -// err: the error to check +// err: error to check // Returns: // true if the error is a reconcileFailedError // Example: -// _, err := utils.ReconcileFailedError() -// if utils.IsReconcileFailedError(err) { -// ... +// if IsReconcileFailedError(err) { +// // handle error // } // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsReconcileFailedError(err error) bool { if err == nil { return false @@ -545,15 +580,18 @@ func IsReconcileFailedError(err error) bool { type unsupportedConfigError struct { message string } -// UnsupportedConfigError returns an error indicating that the provided configuration is not supported + +func (e *unsupportedConfigError) Error() string { return e.message } + +// UnsupportedConfigError returns an error indicating that the supplied configuration is not supported // Parameters: -// err - the error to wrap +// err - the error that caused the configuration to be unsupported // Returns: -// an error indicating that the provided configuration is not supported +// error - an error indicating that the supplied configuration is not supported // Example: -// err := utils.UnsupportedConfigError(errors.New("custom error message")) +// err := utils.UnsupportedConfigError(fmt.Errorf("unsupported feature")) // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func UnsupportedConfigError(err error) error { return &unsupportedConfigError{ message: fmt.Sprintf("unsupported configuration; %s", err.Error()), @@ -564,13 +602,11 @@ func UnsupportedConfigError(err error) error { // Parameters: // err: the error to check // Returns: -// true if the error is an unsupportedConfigError +// true if the error is an unsupportedConfigError, false otherwise // Example: -// if utils.IsUnsupportedConfigError(err) { -// ... -// } +// IsUnsupportedConfigError(errors.New("unsupported config")) // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsUnsupportedConfigError(err error) bool { if err == nil { return false @@ -586,18 +622,21 @@ func IsUnsupportedConfigError(err error) bool { type tempOperatorError struct { message string } -// TempOperatorError returns a temporary operator error + +func (e *tempOperatorError) Error() string { return e.message } + +// TempOperatorError is a temporary error that should be retried +// It returns a temporary error that should be retried // Parameters: -// err - error +// err: the error to wrap // Returns: -// error +// a temporary error that should be retried // Example: -// err := TempOperatorError(err) -// if err != nil { -// panic(err) +// if err := doSomething(); err != nil { +// return utils.TempOperatorError(err) // } // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func TempOperatorError(err error) error { return &tempOperatorError{ message: fmt.Sprintf("temporary operator error; %s", err.Error()), @@ -606,13 +645,15 @@ func TempOperatorError(err error) error { // IsTempOperatorError returns true if the error is a temporary operator error // Parameters: -// err - the error to check +// err - error to check // Returns: // true if the error is a temporary operator error // Example: -// found := utils.IsTempOperatorError(err) +// if utils.IsTempOperatorError(err) { +// // handle temporary operator error +// } // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsTempOperatorError(err error) bool { if err == nil { return false @@ -628,29 +669,34 @@ func IsTempOperatorError(err error) bool { type invalidInputError struct { message string } -// InvalidInputError is an error that is returned when the input is invalid. -// It returns a message that is useful to the user. + +func (e *invalidInputError) Error() string { return e.message } + +// InvalidInputError is a custom error +// It returns a message // Parameters: -// message - the message to return -// Return: -// an error object +// message: string +// Returns: +// error // Example: -// err := utils.InvalidInputError("The input is invalid") +// err := utils.InvalidInputError("This is an error") // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func InvalidInputError(message string) error { return &invalidInputError{message} } -// IsInvalidInputError returns true if the error is an invalid input error. +// IsInvalidInputError returns true if the error is an invalid input error // Parameters: -// err: the error to check +// err - the error to check // Returns: -// true if the error is an invalid input error, false otherwise +// true if the error is an invalid input error // Example: -// IsInvalidInputError(errors.New("Invalid input")) +// if IsInvalidInputError(err) { +// // err was an invalid input error +// } // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsInvalidInputError(err error) bool { if err == nil { return false @@ -666,16 +712,24 @@ func IsInvalidInputError(err error) bool { type unsupportedCapacityRangeError struct { err error message string -// UnsupportedCapacityRangeError is returned when the capacity range is not supported -// It returns the error message and the error +} + +func (e *unsupportedCapacityRangeError) Unwrap() error { return e.err } + +func (e *unsupportedCapacityRangeError) Error() string { return e.message } + +// UnsupportedCapacityRangeError is an error that is returned when a capacity +// range is not supported by the storage driver. +// It returns an error with the message: +// "unsupported capacity range; " // Parameters: // err - the error message -// Return: -// the error +// Returns: +// an error // Example: -// err := utils.UnsupportedCapacityRangeError(errors.New("capacity range is not supported")) +// err := UnsupportedCapacityRangeError(errors.New("invalid capacity range")) // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func UnsupportedCapacityRangeError(err error) error { return &unsupportedCapacityRangeError{ err, fmt.Sprintf("unsupported capacity range; %s", @@ -685,14 +739,14 @@ func UnsupportedCapacityRangeError(err error) error { // HasUnsupportedCapacityRangeError returns true if the error is an unsupportedCapacityRangeError // Parameters: -// err: the error to check +// err - the error to check // Returns: -// bool: true if the error is an unsupportedCapacityRangeError -// *unsupportedCapacityRangeError: the unsupportedCapacityRangeError if it is one, otherwise nil +// bool - true if the error is an unsupportedCapacityRangeError +// *unsupportedCapacityRangeError - the error if it is an unsupportedCapacityRangeError, nil otherwise // Example: -// ok, unsupportedCapacityRangeError := utils.HasUnsupportedCapacityRangeError(err) +// _, ok := HasUnsupportedCapacityRangeError(err) // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func HasUnsupportedCapacityRangeError(err error) (bool, *unsupportedCapacityRangeError) { if err == nil { return false, nil @@ -709,31 +763,35 @@ func HasUnsupportedCapacityRangeError(err error) (bool, *unsupportedCapacityRang type maxLimitReachedError struct { message string } -// MaxLimitReachedError is returned when the maximum limit has been reached + +func (e *maxLimitReachedError) Error() string { return e.message } + +// MaxLimitReachedError is an error that is returned when the maximum limit for a resource has been reached // It returns a string message // Parameters: -// message - the message to return +// message - the error message // Returns: -// the error +// error - the error // Example: -// err := utils.MaxLimitReachedError("Maximum size reached") +// if err := utils.MaxLimitReachedError("Maximum limit of volumes has been reached"); err != nil { +// log.Errorf("Error: %v\n", err) +// return +// } // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func MaxLimitReachedError(message string) error { return &maxLimitReachedError{message} } // IsMaxLimitReachedError returns true if the error is a maxLimitReachedError // Parameters: -// err: the error to check +// err - the error to check // Returns: // true if the error is a maxLimitReachedError // Example: -// if utils.IsMaxLimitReachedError(err) { -// // handle error -// } +// result := utils.IsMaxLimitReachedError(err) // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsMaxLimitReachedError(err error) bool { if err == nil { return false @@ -750,30 +808,34 @@ type typeAssertionError struct { assertion string } -// Error types -// It returns a string representation of the error. +// Error returned when a +// It returns a string representation of the assertion that failed. // Returns: -// string representation of the error +// string representation of the assertion that failed // Example: -// err := NewTypeAssertionError("this is the error") +// err := utils.TypeAssertionError{assertion: "slice"} // fmt.Println(err.Error()) +// Output: +// could not perform assertion: slice // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func (e *typeAssertionError) Error() string { return fmt.Sprintf("could not perform assertion: %s", e.assertion) } // TypeAssertionError is a -// It returns a new error with the given assertion. +// It returns an error with the given assertion string. // Parameters: -// assertion - the assertion that failed +// assertion: the assertion string // Returns: -// a new error with the given assertion +// an error with the given assertion string // Example: -// err := TypeAssertionError("assertion") -// fmt.Println(err) +// err := utils.TypeAssertionError("a.b.c") +// fmt.Printf("%v", err) +// // Output: +// // Type assertion error: a.b.c // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func TypeAssertionError(assertion string) error { return &typeAssertionError{assertion} } @@ -785,16 +847,19 @@ func TypeAssertionError(assertion string) error { type authError struct { message string } -// AuthError is an error -// It returns an error with a message + +func (e *authError) Error() string { return e.message } + +// AuthError is an error that can be returned from the auth package +// It returns a message that can be displayed to the user // Parameters: -// message string +// message (string) - the message to display to the user // Returns: -// error +// error - an error that can be returned from the auth package // Example: -// err := AuthError("error message") +// err := auth.AuthError("There was an error authenticating") // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func AuthError(message string) error { return &authError{message} } @@ -803,11 +868,11 @@ func AuthError(message string) error { // Parameters: // err: the error to check // Returns: -// true if the error is an auth error, false otherwise +// true if the error is an auth error // Example: -// ok := IsAuthError(err) +// IsAuthError(err) // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsAuthError(err error) bool { if err == nil { return false @@ -823,34 +888,34 @@ func IsAuthError(err error) bool { type tooManyRequestsError struct { message string } -// TooManyRequestsError is an error that indicates that the request was rejected due to rate limiting. + +func (e *tooManyRequestsError) Error() string { return e.message } + +// TooManyRequestsError is an error that indicates that the client has sent too many requests in a given amount of time. // It returns a 429 status code. // Parameters: -// message - the error message +// message: the error message // Returns: // an error // Example: -// if err := utils.TooManyRequestsError("Too many requests"); err != nil { -// return err -// } +// err := utils.TooManyRequestsError("Too many requests") // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func TooManyRequestsError(message string) error { return &tooManyRequestsError{message} } // IsTooManyRequestsError returns true if the error is a TooManyRequestsError // Parameters: -// err: the error to check +// err - the error to check // Returns: -// true if the error is a TooManyRequestsError +// true if the error is a TooManyRequestsError, false otherwise // Example: -// err := utils.TooManyRequestsError("too many requests") // if utils.IsTooManyRequestsError(err) { -// log.Println("too many requests") +// // handle error // } // -// -- Doc autogenerated on 2022-05-12 14:18:50.293039 -- +// -- Doc autogenerated on 2022-05-12 16:29:59.146129 -- func IsTooManyRequestsError(err error) bool { if err == nil { return false From 35bc9e6f3dafd6b8c4a4665f4cf0027871b13ab2 Mon Sep 17 00:00:00 2001 From: "Roussin, Jerome" Date: Thu, 12 May 2022 19:33:58 -0400 Subject: [PATCH 4/5] Reprocessed core/ and operator/controllers with latest chances --- core/core_test.go | 15 +- core/orchestrator_core.go | 1244 +++++------ core/orchestrator_core_test.go | 1847 +++++++++++------ core/transaction_monitor_test.go | 90 +- .../orchestrator/apis/netapp/v1/register.go | 19 +- .../orchestrator/apis/netapp/v1/types.go | 18 +- .../versioned/fake/clientset_generated.go | 34 +- .../netapp/v1/fake/fake_netapp_client.go | 8 +- .../typed/netapp/v1/netapp_client.go | 28 +- .../informers/externalversions/factory.go | 62 +- .../netapp/v1/tridentorchestrator.go | 85 +- .../controllers/orchestrator/controller.go | 195 +- .../orchestrator/installer/installer.go | 378 ++-- .../orchestrator/installer/installer_test.go | 55 +- .../orchestrator/installer/k8s_client_test.go | 782 +++---- .../orchestrator/installer/uninstaller.go | 41 +- .../orchestrator/installer/utils.go | 112 +- .../provisioner/apis/netapp/v1/register.go | 20 +- .../versioned/fake/clientset_generated.go | 30 +- .../netapp/v1/fake/fake_netapp_client.go | 17 +- .../typed/netapp/v1/netapp_client.go | 32 +- .../informers/externalversions/factory.go | 52 +- .../netapp/v1/tridentprovisioner.go | 83 +- 23 files changed, 2872 insertions(+), 2375 deletions(-) diff --git a/core/core_test.go b/core/core_test.go index eaa90dbf0..bde9af169 100644 --- a/core/core_test.go +++ b/core/core_test.go @@ -10,16 +10,11 @@ import ( log "github.com/sirupsen/logrus" ) -// TestMain is the entry point for all unit tests. -// It checks for any command line arguments and if none are found, -// it sets the log output to ioutil.Discard to disable any standard log output. -// Parameters: -// m: the testing.M object -// Returns: -// none -// Example: -// - +// TestMain is the entry point for all unit tests +// It checks for the environment variable TRACE and if set, +// enables debug logging. +// +// -- Doc autogenerated on 2022-05-12 17:31:05.128674 -- func TestMain(m *testing.M) { // Disable any standard log output log.SetOutput(ioutil.Discard) diff --git a/core/orchestrator_core.go b/core/orchestrator_core.go index 8baa56ef9..99b04aa27 100644 --- a/core/orchestrator_core.go +++ b/core/orchestrator_core.go @@ -54,14 +54,18 @@ func recordTiming(operation string, err *error) func() { } } +func recordTransactionTiming(txn *storage.VolumeTransaction, err *error) { // recordTransactionTiming records the time it took to complete a transaction -// in milliseconds. +// to the operationDurationInMsSummary metric. // Parameters: -// txn: the transaction to record -// err: the error that occurred, if any +// txn: the transaction +// err: the error returned by the transaction +// Returns: +// None // Example: -// recordTransactionTiming(txn, err) - +// recordTransactionTiming(txn, &err) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func recordTransactionTiming(txn *storage.VolumeTransaction, err *error) { if txn == nil || txn.VolumeCreatingConfig == nil { // for unit tests, there will be no txn to record @@ -116,18 +120,20 @@ func NewTridentOrchestrator(client persistentstore.Client) *TridentOrchestrator } } -// transformPersistentState transforms the persistent state to the current API version. +func (o *TridentOrchestrator) transformPersistentState(ctx context.Context) error { +// transformPersistentState transforms the persistent state to the current version. +// It returns an error if the transformation fails. // Parameters: -// ctx - context +// ctx - context for the operation // Returns: -// error - any error encountered -// It returns an error if the persistent store version is not found. +// error - error if the transformation fails // Example: // err := o.transformPersistentState(ctx) // if err != nil { // return err // } - +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) transformPersistentState(ctx context.Context) error { version, err := o.storeClient.GetVersion(ctx) @@ -163,12 +169,17 @@ func (o *TridentOrchestrator) transformPersistentState(ctx context.Context) erro } // Bootstrap initializes the orchestrator. -// It returns an error if the orchestrator cannot be initialized. +// It returns an error if the orchestrator is already bootstrapped. +// Returns: +// - BootstrapError if the orchestrator is already bootstrapped +// - InternalError if the orchestrator fails to bootstrap // Example: -// if err := o.Bootstrap(); err != nil { -// log.Fatal(err) +// - err := orchestrator.Bootstrap() +// - if err != nil { +// log.Errorf("Failed to bootstrap orchestrator: %v", err) // } - +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) Bootstrap() error { ctx := GenerateRequestContext(context.Background(), "", ContextSourceInternal) var err error @@ -198,18 +209,19 @@ func (o *TridentOrchestrator) Bootstrap() error { return nil } -// bootstrapBackends is called during startup to load any backends that were -// previously configured. +// bootstrapBackends is called during startup to load backends from the persistent store. +// It returns an error if any backends fail to initialize. // Parameters: -// ctx - context for logging +// ctx - context for logging // Returns: -// error - if any errors occur -// It returns an error if it cannot load any backends. +// error - error if any backends fail to initialize // Example: -// if err := o.bootstrapBackends(ctx); err != nil { -// return err -// } - +// err := o.bootstrapBackends(ctx) +// if err != nil { +// return err +// } +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) bootstrapBackends(ctx context.Context) error { persistentBackends, err := o.storeClient.GetBackends(ctx) @@ -302,19 +314,16 @@ func (o *TridentOrchestrator) bootstrapBackends(ctx context.Context) error { return nil } -// bootstrapStorageClasses loads storage classes from the backend store. +// bootstrapStorageClasses is called during startup to load persistent storage classes from the backend. +// It returns an error if the persistent storage classes cannot be loaded. // Parameters: -// ctx - context for logging +// ctx - context // Returns: -// error - any error encountered -// It returns an error if the storage classes cannot be loaded from the backend store. +// error - error if the persistent storage classes cannot be loaded // Example: -// ctx := context.Background() -// err := o.bootstrapStorageClasses(ctx) -// if err != nil { -// return errors.Wrap(err, "error bootstrapping storage classes") -// } - +// err := o.bootstrapStorageClasses(ctx) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) bootstrapStorageClasses(ctx context.Context) error { persistentStorageClasses, err := o.storeClient.GetStorageClasses(ctx) @@ -338,18 +347,19 @@ func (o *TridentOrchestrator) bootstrapStorageClasses(ctx context.Context) error // Updates the o.volumes cache with the latest backend data. This function should only edit o.volumes in place to avoid // briefly losing track of volumes that do exist. -// bootstrapVolumes adds all volumes from the store to the orchestrator. +// bootstrapVolumes adds existing volumes to the orchestrator. +// It returns an error if the volumes cannot be retrieved from the store. // Parameters: -// ctx - context for logging +// ctx - context for logging // Returns: -// error - any error encountered -// It returns an error if the store cannot be read. +// error - error if the volumes cannot be retrieved from the store // Example: -// err := o.bootstrapVolumes(ctx) -// if err != nil { -// log.Errorf("Could not bootstrap volumes: %v", err) -// } - +// err := o.bootstrapVolumes(ctx) +// if err != nil { +// return err +// } +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) bootstrapVolumes(ctx context.Context) error { volumes, err := o.storeClient.GetVolumes(ctx) @@ -403,15 +413,16 @@ func (o *TridentOrchestrator) bootstrapVolumes(ctx context.Context) error { return nil } -// bootstrapSnapshots bootstraps the snapshot store with existing snapshots. +// bootstrapSnapshots adds existing snapshots to the orchestrator's snapshot map. +// It returns an error if the snapshot cannot be added. // Parameters: -// ctx - context for logging +// ctx - context // Returns: -// error - any error encountered -// It returns an error if the snapshot store cannot be queried. +// error - error if the snapshot cannot be added // Example: -// error := o.bootstrapSnapshots(ctx) - +// err := o.bootstrapSnapshots(ctx) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) bootstrapSnapshots(ctx context.Context) error { snapshots, err := o.storeClient.GetSnapshots(ctx) @@ -447,19 +458,16 @@ func (o *TridentOrchestrator) bootstrapSnapshots(ctx context.Context) error { return nil } -// bootstrapVolTxns reads all volume transaction logs from the persistent store and -// attempts to recover from any failed transactions. +// bootstrapVolTxns bootstraps volume transaction logs from persistent store +// It returns an error if it fails to bootstrap any volume transaction log // Parameters: // ctx - context // Returns: -// error - any error encountered -// It returns an error if it cannot read the volume transaction logs from the persistent store. +// error - error if any // Example: // err := o.bootstrapVolTxns(ctx) -// if err != nil { -// return err -// } - +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) bootstrapVolTxns(ctx context.Context) error { volTxns, err := o.storeClient.GetVolumeTransactions(ctx) @@ -477,19 +485,16 @@ func (o *TridentOrchestrator) bootstrapVolTxns(ctx context.Context) error { return nil } -// bootstrapNodes is called during startup to populate the node map with any -// existing nodes. +// bootstrapNodes bootstraps the orchestrator with existing nodes +// It returns an error if it fails to bootstrap // Parameters: // ctx - context // Returns: -// error - any error encountered -// It returns an error if the node map could not be populated. +// error - error if it fails to bootstrap // Example: // err := o.bootstrapNodes(ctx) -// if err != nil { -// return err -// } - +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) bootstrapNodes(ctx context.Context) error { // Don't bootstrap nodes if we're not CSI @@ -516,15 +521,17 @@ func (o *TridentOrchestrator) bootstrapNodes(ctx context.Context) error { return nil } -// bootstrapVolumePublications bootstraps the volume publications from the backend store +// bootstrapVolumePublications loads all existing volume publications from the backend +// and adds them to the orchestrator's cache. +// It returns an error if the backend could not be contacted. // Parameters: // ctx - context for logging // Returns: -// error - any error encountered -// It returns an error if the backend store is unavailable. +// error - error if the backend could not be contacted // Example: // err := o.bootstrapVolumePublications(ctx) - +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) bootstrapVolumePublications(ctx context.Context) error { // Don't bootstrap volume publications if we're not CSI @@ -547,22 +554,15 @@ func (o *TridentOrchestrator) bootstrapVolumePublications(ctx context.Context) e return nil } -// addVolumePublicationToCache adds a volume publication to the orchestrator's cache +// addVolumePublicationToCache adds a volume publication to the cache // Parameters: -// vp: the volume publication to add -// Return: +// vp - volume publication to add +// Returns: // none // Example: -// o := NewTridentOrchestrator() -// vp := utils.VolumePublication{ -// VolumeName: "volume1", -// NodeName: "node1", -// DevicePath: "/dev/sda", -// Format: "ext4", -// MountPoint: "/mnt/trident", -// } -// o.addVolumePublicationToCache(vp) - +// orchestrator.addVolumePublicationToCache(vp) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) addVolumePublicationToCache(vp *utils.VolumePublication) { // If the volume has no entry we need to initialize the inner map if o.volumePublications[vp.VolumeName] == nil { @@ -571,21 +571,20 @@ func (o *TridentOrchestrator) addVolumePublicationToCache(vp *utils.VolumePublic o.volumePublications[vp.VolumeName][vp.NodeName] = vp } -// bootstrap loads the state of the orchestrator from the persistent store. -// -// This is called at startup and after a connection to the persistent store is -// re-established. +// bootstrap loads all persistent data from the store and initializes the +// orchestrator's internal state. +// It returns an error if the bootstrap fails. // Parameters: -// ctx - context for the operation +// ctx - context for the operation // Returns: -// error - any error encountered -// It returns an error if the persistent store is not available. +// error - any error encountered during bootstrap // Example: -// err := o.bootstrap(ctx) -// if err != nil { -// // handle error -// } - +// err := o.bootstrap(ctx) +// if err != nil { +// // handle error +// } +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) bootstrap(ctx context.Context) error { // Fetching backend information @@ -648,6 +647,7 @@ func (o *TridentOrchestrator) Stop() { // updateMetrics updates the metrics that track the core objects. // The caller should hold the orchestrator lock. func (o *TridentOrchestrator) updateMetrics() { +func (o *TridentOrchestrator) Stop() { tridentBuildInfo.WithLabelValues(config.BuildHash, config.OrchestratorVersion.ShortString(), @@ -699,23 +699,25 @@ func (o *TridentOrchestrator) updateMetrics() { } } -// handleFailedTransaction attempts to roll back a failed transaction. -// -// The rollback is performed by deleting the volume or snapshot from the backend -// and/or persistent store, as appropriate. -// -// If the transaction is successfully rolled back, the transaction object is -// deleted from persistent store. +func (o *TridentOrchestrator) handleFailedTransaction(ctx context.Context, v *storage.VolumeTransaction) error { +// handleFailedTransaction attempts to clean up after a failed transaction. +// It is called when a transaction is found in the persistent store that +// doesn't have a corresponding transaction object in memory. // -// If the transaction is not successfully rolled back, the transaction object is -// left in persistent store, so that it can be retried on the next boot. -// It returns an error if the transaction could not be rolled back. +// This function is called with the orchestrator lock held. +// It returns an error if it is unable to clean up the transaction. +// Parameters: +// ctx - context for logging +// v - the volume transaction to clean up +// Returns: +// error - an error if the transaction could not be cleaned up // Example: -// err := orchestrator.handleFailedTransaction(ctx, txn) +// err := handleFailedTransaction(ctx, v) // if err != nil { -// log.Errorf("Failed to roll back transaction %s: %v", txn.ID, err) +// log.Errorf("Unable to clean up transaction %v: %v", v.ID(), err) // } - +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) handleFailedTransaction(ctx context.Context, v *storage.VolumeTransaction) error { switch v.Op { @@ -954,17 +956,18 @@ func (o *TridentOrchestrator) handleFailedTransaction(ctx context.Context, v *st return nil } -// resetImportedVolumeName attempts to rename the volume back to its original name -// This is only used for imported volumes +// resetImportedVolumeName resets the name of a volume that was imported. +// It returns an error if the volume was not found. // Parameters: // ctx - context -// volume - volume to rename +// volume - volume to reset // Returns: -// error - any error encountered -// It returns an error if the volume is not found in any backend +// error - error if the volume was not found // Example: +// Reset the volume name for a volume that was imported // err := o.resetImportedVolumeName(ctx, volume) - +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) resetImportedVolumeName(ctx context.Context, volume *storage.VolumeConfig) error { // The volume could be renamed (notManaged = false) without being persisted. @@ -982,15 +985,15 @@ func (o *TridentOrchestrator) resetImportedVolumeName(ctx context.Context, volum return nil } -// AddFrontend adds a frontend plugin to the orchestrator +// AddFrontend adds a frontend to the orchestrator // Parameters: -// f - the frontend plugin to add +// f - frontend to add // Returns: // none // Example: -// o := NewTridentOrchestrator() -// o.AddFrontend(frontend.NewKubernetes()) - +// orchestrator.AddFrontend(f) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) AddFrontend(f frontend.Plugin) { name := f.GetName() if _, ok := o.frontends[name]; ok { @@ -1001,16 +1004,20 @@ func (o *TridentOrchestrator) AddFrontend(f frontend.Plugin) { o.frontends[name] = f } -// GetFrontend returns a frontend plugin by name +// GetFrontend returns the frontend plugin for the specified name // Parameters: -// ctx - context +// ctx - context for logging // name - name of the frontend plugin // Returns: // frontend.Plugin - the frontend plugin -// error - error if any +// error - error if one occurred // Example: -// frontend, err := GetFrontend(ctx, "iscsi") - +// frontend, err := o.GetFrontend(ctx, "nfs") +// if err != nil { +// // handle error +// } +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) GetFrontend(ctx context.Context, name string) (frontend.Plugin, error) { if fe, ok := o.frontends[name]; !ok { @@ -1022,19 +1029,20 @@ func (o *TridentOrchestrator) GetFrontend(ctx context.Context, name string) (fro } } -// validateBackendUpdate validates that the backend update operation is valid. +// validateBackendUpdate validates that a backend update is allowed. +// It returns an error if the update is not allowed. // Parameters: // oldBackend - the backend before the update // newBackend - the backend after the update // Returns: -// error - nil if the update is valid, otherwise an error describing why the update is invalid -// It returns an error if the backend type is being changed. +// error - an error if the update is not allowed // Example: -// o := NewTridentOrchestrator(...) -// oldBackend := o.backendRegistry.GetBackend("oldBackend") -// newBackend := o.backendRegistry.GetBackend("newBackend") -// err := o.validateBackendUpdate(oldBackend, newBackend) - +// err := validateBackendUpdate(oldBackend, newBackend) +// if err != nil { +// return err +// } +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) validateBackendUpdate(oldBackend, newBackend storage.Backend) error { // Validate that backend type isn't being changed as backend type has // implications for the internal volume names. @@ -1047,15 +1055,21 @@ func (o *TridentOrchestrator) validateBackendUpdate(oldBackend, newBackend stora return nil } -// GetVersion returns the version of the orchestrator +// GetVersion returns the version of the orchestrator. // Parameters: -// ctx - context for the request +// context - context for the request // Returns: -// version string -// error - if any +// version - version of the orchestrator +// error - any error encountered // Example: -// version, err := o.GetVersion(ctx) - +// version, err := orchestrator.GetVersion(context) +// if err != nil { +// log.Error(err) +// } else { +// log.Infof("Orchestrator version is %s", version) +// } +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) GetVersion(context.Context) (string, error) { return config.OrchestratorVersion.String(), o.bootstrapError } @@ -1094,6 +1108,7 @@ func (o *TridentOrchestrator) AddBackend( // addBackend creates a new storage backend. It assumes the mutex lock is // already held or not required (e.g., during bootstrapping). func (o *TridentOrchestrator) addBackend( +func (o *TridentOrchestrator) AddBackend( ctx context.Context, configJSON, backendUUID, configRef string, ) (backendExternal *storage.BackendExternal, err error) { @@ -1197,6 +1212,7 @@ func (o *TridentOrchestrator) addBackend( // validateAndCreateBackendFromConfig validates config and creates backend based on Config func (o *TridentOrchestrator) validateAndCreateBackendFromConfig( +func (o *TridentOrchestrator) addBackend( ctx context.Context, configJSON string, configRef string, backendUUID string, ) (backendExternal storage.Backend, err error) { @@ -1235,6 +1251,7 @@ func (o *TridentOrchestrator) validateAndCreateBackendFromConfig( // UpdateBackend updates an existing backend. func (o *TridentOrchestrator) UpdateBackend( +func (o *TridentOrchestrator) validateAndCreateBackendFromConfig( ctx context.Context, backendName, configJSON, configRef string, ) (backendExternal *storage.BackendExternal, err error) { if o.bootstrapError != nil { @@ -1268,6 +1285,7 @@ func (o *TridentOrchestrator) UpdateBackend( // updateBackend updates an existing backend. It assumes the mutex lock is already held. func (o *TridentOrchestrator) updateBackend( +func (o *TridentOrchestrator) UpdateBackend( ctx context.Context, backendName, configJSON, configRef string, ) (backendExternal *storage.BackendExternal, err error) { backendToUpdate, err := o.getBackendByBackendName(backendName) @@ -1281,6 +1299,7 @@ func (o *TridentOrchestrator) updateBackend( // UpdateBackendByBackendUUID updates an existing backend. func (o *TridentOrchestrator) UpdateBackendByBackendUUID( +func (o *TridentOrchestrator) updateBackend( ctx context.Context, backendName, configJSON, backendUUID, configRef string, ) (backend *storage.BackendExternal, err error) { if o.bootstrapError != nil { @@ -1314,17 +1333,8 @@ func (o *TridentOrchestrator) UpdateBackendByBackendUUID( // TODO combine this one and the one above // updateBackendByBackendUUID updates an existing backend. It assumes the mutex lock is already held. -// updateBackendByBackendUUID updates an existing backend. -// Parameters: -// backendName - the name of the backend -// configJSON - the backend configuration -// backendUUID - the UUID of the backend -// callingConfigRef - the UID of the TridentBackendConfig CR that initiated this operation -// It returns the backend's external representation. -// Example: -// backendExternal, err := o.updateBackendByBackendUUID(ctx, "be-name", "config", "be-uuid", "tbc-uid") - func (o *TridentOrchestrator) updateBackendByBackendUUID( +func (o *TridentOrchestrator) UpdateBackendByBackendUUID( ctx context.Context, backendName, configJSON, backendUUID, callingConfigRef string, ) (backendExternal *storage.BackendExternal, err error) { @@ -1550,6 +1560,7 @@ func (o *TridentOrchestrator) updateBackendByBackendUUID( // UpdateBackendState updates an existing backend's state. func (o *TridentOrchestrator) UpdateBackendState( +func (o *TridentOrchestrator) updateBackendByBackendUUID( ctx context.Context, backendName, backendState string, ) (backendExternal *storage.BackendExternal, err error) { if o.bootstrapError != nil { @@ -1567,6 +1578,7 @@ func (o *TridentOrchestrator) UpdateBackendState( // updateBackendState updates an existing backend's state. It assumes the mutex lock is already held. func (o *TridentOrchestrator) updateBackendState( +func (o *TridentOrchestrator) UpdateBackendState( ctx context.Context, backendName, backendState string, ) (backendExternal *storage.BackendExternal, err error) { @@ -1604,15 +1616,17 @@ func (o *TridentOrchestrator) updateBackendState( return backend.ConstructExternal(ctx), o.storeClient.UpdateBackend(ctx, backend) } -// getBackendUUIDByBackendName returns the backend UUID for a given backend name +func (o *TridentOrchestrator) getBackendUUIDByBackendName(backendName string) (string, error) { +// getBackendUUIDByBackendName returns the UUID of a backend given its name // Parameters: -// backendName - the name of the backend +// backendName - name of the backend // Returns: -// string - the backend UUID -// error - any error encountered +// backendUUID - UUID of the backend +// error - error if any // Example: -// backendUUID, err := o.getBackendUUIDByBackendName("backend1") - +// backendUUID, err := o.getBackendUUIDByBackendName(backendName) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) getBackendUUIDByBackendName(backendName string) (string, error) { backendUUID := "" for _, b := range o.backends { @@ -1624,15 +1638,16 @@ func (o *TridentOrchestrator) getBackendUUIDByBackendName(backendName string) (s return "", utils.NotFoundError(fmt.Sprintf("backend %v was not found", backendName)) } -// getBackendByBackendName returns the backend with the given name +// getBackendByBackendName returns a backend by name // Parameters: // backendName - the name of the backend to return // Returns: -// storage.Backend - the backend with the given name -// error - nil if the backend was found, error otherwise +// storage.Backend - the backend object +// error - any error encountered // Example: -// b, err := o.getBackendByBackendName("ontap-nas") - +// backend, err := o.getBackendByBackendName(backendName) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) getBackendByBackendName(backendName string) (storage.Backend, error) { for _, b := range o.backends { if b.Name() == backendName { @@ -1642,15 +1657,16 @@ func (o *TridentOrchestrator) getBackendByBackendName(backendName string) (stora return nil, utils.NotFoundError(fmt.Sprintf("backend %v was not found", backendName)) } -// getBackendByConfigRef returns a backend based on the configRef +// getBackendByConfigRef returns a backend based on its configRef // Parameters: // configRef - the configRef of the backend to return // Returns: -// storage.Backend - the backend with the matching configRef -// error - nil if successful, error if not +// storage.Backend - the backend with the specified configRef +// error - nil if the backend was found, or an error if the backend was not found // Example: -// b, err := o.getBackendByConfigRef("csi-volumes") - +// backend, err := getBackendByConfigRef("backend1") +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) getBackendByConfigRef(configRef string) (storage.Backend, error) { for _, b := range o.backends { if b.ConfigRef() == configRef { @@ -1660,15 +1676,16 @@ func (o *TridentOrchestrator) getBackendByConfigRef(configRef string) (storage.B return nil, utils.NotFoundError(fmt.Sprintf("backend based on configRef '%v' was not found", configRef)) } -// getBackendByBackendUUID returns a backend by backendUUID +// getBackendByBackendUUID returns a backend by its UUID // Parameters: -// backendUUID - the backendUUID of the backend to return -// Return: -// storage.Backend - the backend -// error - any errors encountered +// backendUUID - the UUID of the backend to retrieve +// Returns: +// storage.Backend - the backend with the specified UUID +// error - nil if no error occurred // Example: -// backend, err := o.getBackendByBackendUUID(backendUUID) - +// backend, err := orchestrator.getBackendByBackendUUID("be-12345678-1234-1234-1234-123456789012") +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) getBackendByBackendUUID(backendUUID string) (storage.Backend, error) { backend := o.backends[backendUUID] if backend != nil { @@ -1677,18 +1694,20 @@ func (o *TridentOrchestrator) getBackendByBackendUUID(backendUUID string) (stora return nil, utils.NotFoundError(fmt.Sprintf("backend uuid %v was not found", backendUUID)) } -// GetBackend returns the backend object for the specified backend name +// GetBackend returns the backend object for the given backend name. // Parameters: -// backendName - name of the backend +// ctx - context for logging +// backendName - name of the backend // Returns: -// *storage.BackendExternal - backend object -// error - error if any +// *storage.BackendExternal - backend object +// error - error object // Example: -// backendExternal, err := orchestrator.GetBackend(ctx, "backend1") -// if err != nil { -// log.Errorf("Could not retrieve backend: %v", err) -// } - +// backendExternal, err := orchestrator.GetBackend(ctx, "backend1") +// if err != nil { +// // handle error +// } +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) GetBackend( ctx context.Context, backendName string, ) (backendExternal *storage.BackendExternal, err error) { @@ -1721,16 +1740,17 @@ func (o *TridentOrchestrator) GetBackend( return backendExternal, nil } -// GetBackendByBackendUUID returns a backend by its UUID +// GetBackendByBackendUUID returns the backend object for the given backend UUID // Parameters: // ctx - context for logging // backendUUID - UUID of the backend // Returns: // *storage.BackendExternal - backend object -// error - error object, nil if no error +// error - error object // Example: -// backendExternal, err := orchestrator.GetBackendByBackendUUID(context.TODO(), "12345678-1234-1234-1234-123456789012") - +// backendExternal, err := o.GetBackendByBackendUUID(ctx, backendUUID) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) GetBackendByBackendUUID( ctx context.Context, backendUUID string, ) (backendExternal *storage.BackendExternal, err error) { @@ -1760,15 +1780,16 @@ func (o *TridentOrchestrator) GetBackendByBackendUUID( return backendExternal, nil } -// ListBackends returns a list of backends +// ListBackends returns a list of all backends known to the orchestrator. // Parameters: -// ctx - context for logging +// ctx - the context for the operation // Returns: -// backends - list of backends -// err - error, if any +// a list of backends +// an error object if the operation failed // Example: -// backends, err := o.ListBackends(ctx) - +// backends, err := tridentOrchestrator.ListBackends(ctx) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) ListBackends( ctx context.Context, ) (backendExternals []*storage.BackendExternal, err error) { @@ -1793,18 +1814,20 @@ func (o *TridentOrchestrator) ListBackends( return backends, nil } -// DeleteBackend deletes a backend from the orchestrator. +// DeleteBackend deletes a backend from the orchestrator +// It returns an error if the backend does not exist // Parameters: // backendName - the name of the backend to delete +// ctx - the context for the operation // Returns: -// error - any error encountered -// It returns an error if the backend does not exist. +// error - nil if successful, non-nil if an error occurred // Example: -// err := orchestrator.DeleteBackend(ctx, "backend-1") +// err := o.DeleteBackend("backend1", ctx) // if err != nil { -// fmt.Printf("Failed to delete backend: %v\n", err) +// log.Errorf("DeleteBackend failed: %v", err) // } - +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) DeleteBackend(ctx context.Context, backendName string) (err error) { if o.bootstrapError != nil { @@ -1827,16 +1850,17 @@ func (o *TridentOrchestrator) DeleteBackend(ctx context.Context, backendName str return o.deleteBackendByBackendUUID(ctx, backendName, backendUUID) } -// DeleteBackendByBackendUUID deletes a backend by its UUID +// DeleteBackendByBackendUUID deletes a backend by its UUID. +// It returns an error if the backend does not exist. // Parameters: -// backendName - name of the backend to delete -// backendUUID - UUID of the backend to delete +// backendName - the name of the backend to delete +// backendUUID - the UUID of the backend to delete // Returns: -// error - any error encountered -// It returns an error if the backend does not exist. +// error - nil if successful // Example: -// err := orchestrator.DeleteBackendByBackendUUID(ctx, "backend1", "12345678-1234-1234-1234-123456789012") - +// err := orchestrator.DeleteBackendByBackendUUID(ctx, "backend1", "6e0c6e1e-b5d0-11e7-9598-080027d29755") +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) DeleteBackendByBackendUUID( ctx context.Context, backendName, backendUUID string, ) (err error) { @@ -1857,17 +1881,18 @@ func (o *TridentOrchestrator) DeleteBackendByBackendUUID( return o.deleteBackendByBackendUUID(ctx, backendName, backendUUID) } -// deleteBackendByBackendUUID deletes a backend by backend UUID +// deleteBackendByBackendUUID deletes a backend by backendUUID +// It returns an error if the backend is not found // Parameters: // ctx - context // backendName - name of the backend to delete // backendUUID - UUID of the backend to delete // Returns: -// error - error if any -// It returns an error if the backend is not found. +// error - if the backend is not found // Example: -// err := o.deleteBackendByBackendUUID(ctx, "myBackend", "myBackendUUID") - +// err := o.deleteBackendByBackendUUID(ctx, "ontap-nas", "12345678-1234-1234-1234-123456789012") +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) deleteBackendByBackendUUID(ctx context.Context, backendName, backendUUID string) error { Logc(ctx).WithFields(log.Fields{ @@ -1947,16 +1972,29 @@ func (o *TridentOrchestrator) RemoveBackendConfigRef(ctx context.Context, backen return o.storeClient.UpdateBackend(ctx, b) } -// AddVolume creates a new volume. +func (o *TridentOrchestrator) AddVolume( +// AddVolume adds a new volume to the system. +// It returns the volume's external representation. // Parameters: -// volumeConfig: The configuration for the new volume. +// volumeConfig: the volume configuration +// backendUUID: the UUID of the backend to use for this volume +// backend: the backend to use for this volume +// backendState: the state of the backend to use for this volume +// backendName: the name of the backend to use for this volume +// backendFilesystem: the filesystem of the backend to use for this volume +// backendPool: the pool of the backend to use for this volume +// backendInternal: whether or not the backend is internal +// backendAccessInfo: the access info of the backend to use for this volume +// backendBlockSizeBytes: the block size of the backend to use for this volume +// backendStoragePrefix: the storage prefix of the backend to use for this volume +// backendStorageClasses: the storage classes of the backend to use for this volume // Returns: -// externalVol: The new volume. -// err: Any errors encountered. -// It returns an error if the volume already exists. +// externalVol: the volume's external representation +// err: any errors encountered // Example: -// vol, err := orchestrator.AddVolume(volumeConfig) - +// externalVol, err := o.AddVolume(volumeConfig) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) AddVolume( ctx context.Context, volumeConfig *storage.VolumeConfig, ) (externalVol *storage.VolumeExternal, err error) { @@ -2121,6 +2159,7 @@ func (o *TridentOrchestrator) addVolumeInitial( // This method should only be called from AddVolume, as it does not take locks or otherwise do much validation // of the volume config. func (o *TridentOrchestrator) addVolumeRetry( +func (o *TridentOrchestrator) addVolumeInitial( ctx context.Context, txn *storage.VolumeTransaction, ) (externalVol *storage.VolumeExternal, err error) { @@ -2186,6 +2225,7 @@ func (o *TridentOrchestrator) addVolumeRetry( // addVolumeFinish is called after successful completion of a volume create/clone operation // to save the volume in the persistent store as well as Trident's in-memory cache. func (o *TridentOrchestrator) addVolumeFinish( +func (o *TridentOrchestrator) addVolumeRetry( ctx context.Context, txn *storage.VolumeTransaction, vol *storage.Volume, backend storage.Backend, pool storage.Pool, ) (externalVol *storage.VolumeExternal, err error) { @@ -2214,34 +2254,19 @@ func (o *TridentOrchestrator) addVolumeFinish( return externalVol, nil } +func (o *TridentOrchestrator) CloneVolume( // CloneVolume clones a volume +// It returns the volume spec and a transaction ID // Parameters: -// volumeConfig - volume config -// backendUUID - backend UUID -// backendName - backend name -// backendState - backend state -// backend - backend -// backendPool - backend pool -// volumeContext - volume context -// cloneFromSnapshot - clone from snapshot -// cloneFromSnapshotName - clone from snapshot name -// cloneFromSnapshotID - clone from snapshot ID -// cloneFromSnapshotTimestamp - clone from snapshot timestamp -// cloneFromVolumeName - clone from volume name -// cloneFromVolumeID - clone from volume ID -// cloneFromVolumeTimestamp - clone from volume timestamp -// cloneFromVolume - clone from volume -// cloneFromVolumeSnapshot - clone from volume snapshot -// cloneFromVolumeSnapshotName - clone from volume snapshot name -// cloneFromVolumeSnapshotID - clone from volume snapshot ID -// cloneFromVolumeSnapshotTimestamp - clone from volume snapshot timestamp +// ctx - context +// volumeConfig - the volume config // Returns: -// externalVol - external volume -// err - error -// It returns an error if the volume already exists. +// *storage.VolumeExternal - the volume spec +// error - any error encountered // Example: -// externalVol, err := o.CloneVolume(ctx, volumeConfig) - +// volumeSpec, err := orchestrator.CloneVolume(ctx, volumeConfig) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) CloneVolume( ctx context.Context, volumeConfig *storage.VolumeConfig, ) (externalVol *storage.VolumeExternal, err error) { @@ -2274,20 +2299,19 @@ func (o *TridentOrchestrator) CloneVolume( return o.cloneVolumeInitial(ctx, volumeConfig) } -// cloneVolumeInitial creates a clone of the specified volume. +// cloneVolumeInitial creates a new volume by cloning an existing volume. +// It returns the new volume and a transaction ID that can be used to roll back +// the operation. // Parameters: -// volumeConfig: the configuration of the volume to be cloned +// ctx - the context for the operation +// volumeConfig - the configuration for the new volume // Returns: -// externalVol: the external representation of the cloned volume -// err: any errors encountered -// It returns an error if the clone operation fails. +// externalVol - the new volume +// err - any error encountered // Example: -// externalVol, err := o.cloneVolumeInitial(ctx, sourceVolume.Config, volumeConfig) -// if err != nil { -// return nil, err -// } -// // Do something with externalVol - +// externalVol, txnID, err := orch.cloneVolumeInitial(ctx, volumeConfig) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) cloneVolumeInitial( ctx context.Context, volumeConfig *storage.VolumeConfig, ) (externalVol *storage.VolumeExternal, err error) { @@ -2430,17 +2454,18 @@ func (o *TridentOrchestrator) cloneVolumeInitial( return o.addVolumeFinish(ctx, txn, vol, backend, pool) } -// cloneVolumeRetry is the retry function for cloneVolume. +// cloneVolumeRetry is called to retry a volume clone operation. +// It returns the volume and any error encountered. // Parameters: -// ctx - context -// txn - transaction +// ctx - context +// txn - transaction // Returns: -// externalVol - volume -// err - error -// It returns an error if the volume could not be created. +// externalVol - volume +// err - error // Example: -// externalVol, err := cloneVolumeRetry(ctx, txn) - +// externalVol, err := cloneVolumeRetry(ctx, txn) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) cloneVolumeRetry( ctx context.Context, txn *storage.VolumeTransaction, ) (externalVol *storage.VolumeExternal, err error) { @@ -2557,6 +2582,7 @@ func (o *TridentOrchestrator) GetVolumeExternal( // GetVolumeByInternalName returns a volume by the given internal name func (o *TridentOrchestrator) GetVolumeByInternalName( +func (o *TridentOrchestrator) GetVolumeExternal( volumeInternal string, _ context.Context, ) (volume string, err error) { @@ -2574,22 +2600,20 @@ func (o *TridentOrchestrator) GetVolumeByInternalName( return "", utils.NotFoundError(fmt.Sprintf("volume %s not found", volumeInternal)) } +func (o *TridentOrchestrator) validateImportVolume(ctx context.Context, volumeConfig *storage.VolumeConfig) error { // validateImportVolume validates the volume +// It returns an error if the volume is not valid // Parameters: -// volumeConfig: volume config -// Return: -// error: error if any -// It returns error if -// - volume already exists -// - storage class is not found -// - storage class does not match any storage pools for backend -// - volume is not found in the backend -// - volume mode, access mode and protocol are incompatible with the backend +// volumeConfig - volume configuration +// Returns: +// error - error if any // Example: -// if err := o.validateImportVolume(ctx, volumeConfig); err != nil { -// return err -// } - +// err := o.validateImportVolume(ctx, volumeConfig) +// if err != nil { +// return nil, err +// } +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) validateImportVolume(ctx context.Context, volumeConfig *storage.VolumeConfig) error { backend, err := o.getBackendByBackendUUID(volumeConfig.ImportBackendUUID) @@ -2652,20 +2676,20 @@ func (o *TridentOrchestrator) validateImportVolume(ctx context.Context, volumeCo return nil } -// LegacyImportVolume imports a volume from a backend. +// LegacyImportVolume imports a volume that was created outside of Trident. +// It returns an error if the volume already exists. // Parameters: -// ctx - context for logging -// volumeConfig - volume configuration -// backendName - name of the backend -// notManaged - if true, the volume is not managed by Trident -// createPVandPVC - callback function to create a PV and PVC for the imported volume +// volumeConfig: the configuration for the volume to be imported +// backendName: the name of the backend on which the volume will be imported +// notManaged: if true, the volume will not be managed by Trident +// createPVandPVC: a callback function that creates a PV and PVC for the imported volume // Returns: -// externalVol - external representation of the volume -// err - error, if any -// It returns an error if the volume cannot be imported. +// externalVol: the volume that was imported +// err: any error encountered // Example: -// externalVol, err := orchestrator.LegacyImportVolume(ctx, volumeConfig, backendName, notManaged, createPVandPVC) - +// externalVol, err := o.LegacyImportVolume(ctx, volumeConfig, backendName, notManaged, createPVandPVC) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) LegacyImportVolume( ctx context.Context, volumeConfig *storage.VolumeConfig, backendName string, notManaged bool, createPVandPVC VolumeCallback, @@ -2757,22 +2781,18 @@ func (o *TridentOrchestrator) LegacyImportVolume( return volExternal, nil } -// ImportVolume imports a volume from an external backend +// ImportVolume imports a volume from a backend. +// It returns the volume's external representation. // Parameters: -// ctx - context for logging -// volumeConfig - volume config for the volume to be imported +// ctx - context for logging +// volumeConfig - volume configuration // Returns: -// *storage.VolumeExternal - volume object for the imported volume -// error - error if any -// It returns error if the volume cannot be imported +// *storage.VolumeExternal - volume's external representation +// error - error, if any // Example: -// volumeConfig := &storage.VolumeConfig{ -// Name: "volume1", -// ImportOriginalName: "vol1", -// ImportBackendUUID: "8f6c0f6e-b99a-11e8-8eb2-f2801f1b9fd1", -// } -// volExternal, err := orchestrator.ImportVolume(ctx, volumeConfig) - +// volExternal, err := orchestrator.ImportVolume(ctx, volumeConfig) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) ImportVolume( ctx context.Context, volumeConfig *storage.VolumeConfig, ) (externalVol *storage.VolumeExternal, err error) { @@ -2905,16 +2925,18 @@ func (o *TridentOrchestrator) AddVolumeTransaction(ctx context.Context, volTxn * return o.storeClient.AddVolumeTransaction(ctx, volTxn) } -// GetVolumeCreatingTransaction returns a VolumeCreating transaction if one exists. +func (o *TridentOrchestrator) GetVolumeCreatingTransaction( +// GetVolumeCreatingTransaction returns the volume transaction for a volume that is being created. // Parameters: -// ctx - context +// ctx - context for the operation // config - volume config // Returns: // *storage.VolumeTransaction - volume transaction -// error - error +// error - error, if any // Example: -// txn, err := o.GetVolumeCreatingTransaction(ctx, config) - +// volTxn, err := o.GetVolumeCreatingTransaction(ctx, config) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) GetVolumeCreatingTransaction( ctx context.Context, config *storage.VolumeConfig, ) (*storage.VolumeTransaction, error) { @@ -2936,16 +2958,21 @@ func (o *TridentOrchestrator) GetVolumeCreatingTransaction( } // GetVolumeTransaction retrieves a volume transaction from the backend +// It returns an error if the transaction does not exist // Parameters: -// ctx - context for logging -// volTxn - volume transaction to retrieve +// ctx - context for the request +// volTxn - volume transaction to retrieve // Returns: -// *storage.VolumeTransaction - retrieved volume transaction -// error - error if any -// It returns an error if the volume transaction could not be retrieved +// *storage.VolumeTransaction - retrieved volume transaction +// error - error if any // Example: -// volTxn, err := o.GetVolumeTransaction(ctx, volTxn) - +// volTxn, err := orchestrator.GetVolumeTransaction(ctx, &storage.VolumeTransaction{ +// Config: &storage.VolumeConfig{ +// Name: "vol1", +// }, +// }) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) GetVolumeTransaction( ctx context.Context, volTxn *storage.VolumeTransaction, ) (*storage.VolumeTransaction, error) { @@ -2961,6 +2988,7 @@ func (o *TridentOrchestrator) DeleteVolumeTransaction(ctx context.Context, volTx // addVolumeCleanup is used as a deferred method from the volume create/clone methods // to clean up in case anything goes wrong during the operation. func (o *TridentOrchestrator) addVolumeCleanup( +func (o *TridentOrchestrator) DeleteVolumeTransaction(ctx context.Context, volTxn *storage.VolumeTransaction) error { ctx context.Context, err error, backend storage.Backend, vol *storage.Volume, volTxn *storage.VolumeTransaction, volumeConfig *storage.VolumeConfig, ) error { @@ -3023,6 +3051,7 @@ func (o *TridentOrchestrator) addVolumeCleanup( // to handles the case where a volume creation took too long, is still ongoing, and must be // preserved in a transaction. func (o *TridentOrchestrator) addVolumeRetryCleanup( +func (o *TridentOrchestrator) addVolumeCleanup( ctx context.Context, err error, backend storage.Backend, pool storage.Pool, volTxn *storage.VolumeTransaction, volumeConfig *storage.VolumeConfig, ) error { @@ -3074,17 +3103,19 @@ func (o *TridentOrchestrator) addVolumeRetryCleanup( return err } -// importVolumeCleanup is a helper function to clean up the volume +func (o *TridentOrchestrator) importVolumeCleanup( +// importVolumeCleanup is called when an error is encountered during the +// It returns an error if it is unable to clean up the volume. // Parameters: -// err: the error that caused the cleanup -// volumeConfig: the volume config -// volTxn: the volume transaction +// err: error encountered during import +// volumeConfig: volume config of the volume being imported +// volTxn: volume transaction of the volume being imported // Returns: -// error: any error encountered during cleanup -// It returns the error that caused the cleanup if there was one. +// error: error encountered during cleanup // Example: -// err := importVolumeCleanup(err, volumeConfig, volTxn) - +// err := importVolumeCleanup(ctx, err, volConfig, volTxn) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) importVolumeCleanup( ctx context.Context, err error, volumeConfig *storage.VolumeConfig, volTxn *storage.VolumeTransaction, ) error { @@ -3142,20 +3173,16 @@ func (o *TridentOrchestrator) importVolumeCleanup( return err } -// GetVolume retrieves a volume from the backend +// GetVolume returns a volume by name // Parameters: -// volume - name of the volume to retrieve +// volume - name of the volume to return // Returns: // *storage.VolumeExternal - volume object -// error - error if any -// It returns an error if the volume does not exist. +// error - error, if any // Example: -// vol, err := orchestrator.GetVolume("volume1") -// if err != nil { -// // handle error -// } -// fmt.Println(vol) - +// vol, err := tridentOrchestrator.GetVolume(context.Background(), "myvol") +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) GetVolume( ctx context.Context, volume string, ) (volExternal *storage.VolumeExternal, err error) { @@ -3176,10 +3203,11 @@ func (o *TridentOrchestrator) GetVolume( // volume - name of the volume // Returns: // *storage.VolumeExternal - volume object -// error - error if any +// error - error object // Example: -// vol, err := tridentOrchestrator.getVolume(ctx, "volume1") - +// volume, err := tridentOrchestrator.getVolume("volume1") +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) getVolume( _ context.Context, volume string, ) (volExternal *storage.VolumeExternal, err error) { @@ -3190,15 +3218,16 @@ func (o *TridentOrchestrator) getVolume( return vol.ConstructExternal(), nil } -// GetDriverTypeForVolume returns the driver type for the volume +// GetDriverTypeForVolume returns the driver // Parameters: -// vol - volume to get driver type for +// vol *storage.VolumeExternal - volume to query // Returns: -// string - driver type -// error - any error encountered +// string - driver type +// error - any error // Example: -// driverType, err := o.GetDriverTypeForVolume(vol) - +// type, err := o.GetDriverTypeForVolume(vol) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) GetDriverTypeForVolume(_ context.Context, vol *storage.VolumeExternal) (string, error) { if o.bootstrapError != nil { return config.UnknownDriver, o.bootstrapError @@ -3221,17 +3250,18 @@ func (o *TridentOrchestrator) getDriverTypeForVolume(backendUUID string) (string return config.UnknownDriver, nil } -// GetVolumeType returns the volume type for a given volume. +func (o *TridentOrchestrator) GetVolumeType( +// GetVolumeType returns the volume // Parameters: // vol *storage.VolumeExternal -// volume to get the type for +// volume to get the // Returns: -// volumeType config.VolumeType -// err error -// any error encountered +// config.VolumeType +// error // Example: -// volumeType, err := core.GetVolumeType(vol) - +// volumeType, err := orchestrator.GetVolumeType(vol) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) GetVolumeType( _ context.Context, vol *storage.VolumeExternal, ) (volumeType config.VolumeType, err error) { @@ -3265,23 +3295,16 @@ func (o *TridentOrchestrator) GetVolumeType( return } -// ListVolumes lists all volumes that are currently known to the orchestrator. +// ListVolumes returns a list of volumes // Parameters: -// context - The context for the request +// context - context for logging // Returns: -// A list of volumes -// Any error encountered -// It returns an error if the orchestrator is not in a ready state. +// volumes - list of volumes +// error - error if any // Example: -// volumes, err := c.ListVolumes(ctx) -// if err != nil { -// log.Errorf("Could not list volumes: %v", err) -// } else { -// for _, volume := range volumes { -// log.Infof("Volume %v", volume.Config.Name) -// } -// } - +// volumes, err := orchestrator.ListVolumes(context.Background()) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) ListVolumes(context.Context) (volumes []*storage.VolumeExternal, err error) { if o.bootstrapError != nil { return nil, o.bootstrapError @@ -3323,6 +3346,7 @@ func (o *TridentOrchestrator) volumeSnapshots(volumeName string) ([]*storage.Sna // caller will take care of both of these. It also assumes that the volume // exists in memory. func (o *TridentOrchestrator) deleteVolume(ctx context.Context, volumeName string) error { +func (o *TridentOrchestrator) volumeSnapshots(volumeName string) ([]*storage.Snapshot, error) { volume := o.volumes[volumeName] volumeBackend := o.backends[volume.BackendUUID] @@ -3400,20 +3424,23 @@ func (o *TridentOrchestrator) deleteVolume(ctx context.Context, volumeName strin return nil } -// deleteVolumeFromPersistentStoreIgnoreError deletes the volume from the persistent store, ignoring -// any errors that may occur. +func (o *TridentOrchestrator) deleteVolumeFromPersistentStoreIgnoreError( +// deleteVolumeFromPersistentStoreIgnoreError deletes a volume from the persistent store, ignoring +// errors if the volume is not found. +// It returns an error if the volume is found but cannot be deleted. // Parameters: // ctx - context // volume - volume to delete // Returns: -// error - any error encountered -// It returns an error if the volume is not found in the persistent store. +// error - error if the volume is found but cannot be deleted // Example: +// volume := &storage.Volume{...} // err := o.deleteVolumeFromPersistentStoreIgnoreError(ctx, volume) // if err != nil { -// log.Errorf("Unable to delete volume from persistent store: %v", err) +// return err // } - +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) deleteVolumeFromPersistentStoreIgnoreError( ctx context.Context, volume *storage.Volume, ) error { @@ -3489,16 +3516,17 @@ func (o *TridentOrchestrator) DeleteVolume(ctx context.Context, volumeName strin return o.deleteVolume(ctx, volumeName) } -// ListVolumesByPlugin lists all volumes for a given plugin +func (o *TridentOrchestrator) ListVolumesByPlugin( +// ListVolumesByPlugin returns a list of volumes for the specified plugin. // Parameters: -// pluginName - name of the plugin +// pluginName - the name of the plugin // Returns: -// volumes - list of volumes +// []*storage.VolumeExternal - a list of volumes // error - any error encountered -// It returns an error if the plugin is not found. // Example: -// volumes, err := client.ListVolumesByPlugin("ontap-nas") - +// volumes, err := c.ListVolumesByPlugin("ontap-nas") +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) ListVolumesByPlugin( _ context.Context, pluginName string, ) (volumes []*storage.VolumeExternal, err error) { @@ -3523,25 +3551,18 @@ func (o *TridentOrchestrator) ListVolumesByPlugin( return volumes, nil } -// PublishVolume publishes the volume to the specified nodes. +// PublishVolume publishes a volume to a set of nodes +// It returns an error if the volume is not found or is being deleted // Parameters: -// volumeName: the name of the volume to publish -// publishInfo: information about the volume to publish -// Return: -// error: nil if successful, otherwise an error object is returned -// It returns an error if the volume is not found or is being deleted. +// ctx - context for logging +// volumeName - name of the volume to publish +// publishInfo - information about the nodes to publish to +// Returns: +// error - error if the operation fails // Example: -// err := orchestrator.PublishVolume("volume1", &utils.VolumePublishInfo{ -// Nodes: []*utils.Node{ -// { -// Name: "node1", -// }, -// }, -// }) -// if err != nil { -// return err -// } - +// err := orchestrator.PublishVolume(ctx, volumeName, publishInfo) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) PublishVolume( ctx context.Context, volumeName string, publishInfo *utils.VolumePublishInfo, ) (err error) { @@ -3594,18 +3615,17 @@ func (o *TridentOrchestrator) PublishVolume( } // UnpublishVolume unpublishes a volume from a node +// It returns an error if the volume is not published to the node // Parameters: -// volumeName - name of the volume to unpublish -// nodeName - name of the node from which to unpublish the volume +// ctx - context +// volumeName - name of the volume +// nodeName - name of the node // Returns: // error - any error encountered -// It returns an error if the volume or node is not found, or if the volume is not published to the node. // Example: -// err := orchestrator.UnpublishVolume("vol-001", "node-001") -// if err != nil { -// log.Error(err.Error()) -// } - +// err := orchestrator.UnpublishVolume(context.Background(), "vol1", "node1") +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) UnpublishVolume(ctx context.Context, volumeName, nodeName string) (err error) { if o.bootstrapError != nil { @@ -3768,6 +3788,7 @@ func (o *TridentOrchestrator) AttachVolume( // which the volume will be attached. It ensures the volume is already mounted, and it attempts to // delete the mount point. func (o *TridentOrchestrator) DetachVolume(ctx context.Context, volumeName, mountpoint string) (err error) { +func (o *TridentOrchestrator) AttachVolume( if o.bootstrapError != nil { return o.bootstrapError @@ -3807,6 +3828,7 @@ func (o *TridentOrchestrator) DetachVolume(ctx context.Context, volumeName, moun // SetVolumeState sets the state of a volume to a given value func (o *TridentOrchestrator) SetVolumeState( +func (o *TridentOrchestrator) DetachVolume(ctx context.Context, volumeName, mountpoint string) (err error) { ctx context.Context, volumeName string, state storage.VolumeState, ) (err error) { @@ -3840,6 +3862,7 @@ func (o *TridentOrchestrator) SetVolumeState( // CreateSnapshot creates a snapshot of the given volume func (o *TridentOrchestrator) CreateSnapshot( +func (o *TridentOrchestrator) SetVolumeState( ctx context.Context, snapshotConfig *storage.SnapshotConfig, ) (externalSnapshot *storage.SnapshotExternal, err error) { @@ -3928,6 +3951,7 @@ func (o *TridentOrchestrator) CreateSnapshot( // addSnapshotCleanup is used as a deferred method from the snapshot create method // to clean up in case anything goes wrong during the operation. func (o *TridentOrchestrator) addSnapshotCleanup( +func (o *TridentOrchestrator) CreateSnapshot( ctx context.Context, err error, backend storage.Backend, snapshot *storage.Snapshot, volTxn *storage.VolumeTransaction, snapConfig *storage.SnapshotConfig, ) error { @@ -3978,21 +4002,20 @@ func (o *TridentOrchestrator) addSnapshotCleanup( return err } -// GetSnapshot retrieves a snapshot from Trident's backend. +func (o *TridentOrchestrator) GetSnapshot( +// GetSnapshot retrieves the snapshot object for a given volume and snapshot name. +// It returns a SnapshotExternal object. // Parameters: -// ctx - context for the request -// volumeName - name of the volume containing the snapshot -// snapshotName - name of the snapshot to retrieve +// ctx - context for logging +// volumeName - name of the volume +// snapshotName - name of the snapshot // Returns: -// snapshotExternal - a snapshot object -// err - error if any -// It returns an error if the snapshot does not exist. +// SnapshotExternal object +// error - non-nil if an error occurred // Example: -// snapshotExternal, err := orchestrator.GetSnapshot(ctx, "myvol", "mysnap") -// if err != nil { -// log.Fatal(err) -// } - +// snapshot, err := tridentOrchestrator.GetSnapshot(ctx, "foo", "snapshot1") +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) GetSnapshot( ctx context.Context, volumeName, snapshotName string, ) (snapshotExternal *storage.SnapshotExternal, err error) { @@ -4009,19 +4032,23 @@ func (o *TridentOrchestrator) GetSnapshot( return o.getSnapshot(ctx, volumeName, snapshotName) } -// getSnapshot returns a snapshot object from the orchestrator's cache. -// If the snapshot is in a creating or uploading state, the orchestrator will -// attempt to update the snapshot's state. +// getSnapshot retrieves a snapshot from the orchestrator's cache. +// It returns a NotFoundError if the snapshot is not found. +// If the snapshot is in the process of being created or uploaded, +// it will attempt to update the snapshot's state from Trident. // Parameters: -// ctx - context for logging -// volumeName - name of the volume the snapshot belongs to -// snapshotName - name of the snapshot to retrieve +// volumeName - the name of the volume the snapshot belongs to +// snapshotName - the name of the snapshot // Returns: -// *storage.SnapshotExternal - snapshot object -// error - error if one occurred +// *storage.SnapshotExternal - the snapshot object +// error - any error encountered // Example: -// snapshot, err := o.getSnapshot(ctx, "volume1", "snapshot1") - +// snapshot, err := o.getSnapshot(ctx, "my-volume", "my-snapshot") +// if err != nil { +// // handle error +// } +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) getSnapshot( ctx context.Context, volumeName, snapshotName string, ) (*storage.SnapshotExternal, error) { @@ -4041,21 +4068,18 @@ func (o *TridentOrchestrator) getSnapshot( } } -// updateSnapshot updates the snapshot state in the orchestrator and persistent store +// updateSnapshot updates the snapshot's state in the orchestrator and persistent store +// It returns the updated snapshot and any error encountered // Parameters: // ctx - context -// snapshot - snapshot to update +// snapshot - the snapshot to update // Returns: -// updated snapshot -// error -// It returns the snapshot if it is known to be ready, otherwise it updates the snapshot state -// in the orchestrator and persistent store. +// *storage.Snapshot - the updated snapshot +// error - any error encountered // Example: // updatedSnapshot, err := o.updateSnapshot(ctx, snapshot) -// if err != nil { -// return err -// } - +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) updateSnapshot( ctx context.Context, snapshot *storage.Snapshot, ) (*storage.Snapshot, error) { @@ -4155,20 +4179,21 @@ func (o *TridentOrchestrator) deleteSnapshot(ctx context.Context, snapshotConfig return nil } -// deleteSnapshotFromPersistentStoreIgnoreError is a wrapper for -// DeleteSnapshotIgnoreNotFound that logs errors. +func (o *TridentOrchestrator) deleteSnapshotFromPersistentStoreIgnoreError( +// deleteSnapshotFromPersistentStoreIgnoreError deletes a snapshot from the persistent store, ignoring +// errors if the snapshot is not found. +// It returns an error if the snapshot is found but cannot be deleted. // Parameters: -// ctx - context -// snapshot - snapshot to delete +// snapshot - the snapshot to delete // Returns: -// error - error if one occurred -// It returns an error if one occurred. +// error - any error encountered // Example: // err := o.deleteSnapshotFromPersistentStoreIgnoreError(ctx, snapshot) // if err != nil { -// return err +// return fmt.Errorf("error deleting snapshot %v: %v", snapshot.Config.Name, err) // } - +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) deleteSnapshotFromPersistentStoreIgnoreError( ctx context.Context, snapshot *storage.Snapshot, ) error { @@ -4287,16 +4312,17 @@ func (o *TridentOrchestrator) DeleteSnapshot(ctx context.Context, volumeName, sn return o.deleteSnapshot(ctx, snapshot.Config) } -// ListSnapshots lists all snapshots in the orchestrator +func (o *TridentOrchestrator) ListSnapshots(context.Context) (snapshots []*storage.SnapshotExternal, err error) { +// ListSnapshots returns a list of snapshots // Parameters: // context - context for the call // Returns: // []*storage.SnapshotExternal - list of snapshots // error - error if any -// It returns an error if the orchestrator is not initialized. // Example: -// snapshots, err := orchestrator.ListSnapshots(context.Background()) - +// snapshotList, err := orchestrator.ListSnapshots(context.Background()) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) ListSnapshots(context.Context) (snapshots []*storage.SnapshotExternal, err error) { if o.bootstrapError != nil { return nil, o.bootstrapError @@ -4315,15 +4341,17 @@ func (o *TridentOrchestrator) ListSnapshots(context.Context) (snapshots []*stora return snapshots, nil } -// ListSnapshotsByName returns a list of snapshots matching the given name +// ListSnapshotsByName lists all snapshots with the given name +// It returns a list of SnapshotExternal objects // Parameters: -// snapshotName - name of the snapshot +// snapshotName - the name of the snapshot to list // Returns: -// []*storage.SnapshotExternal - list of snapshots -// error - error if any +// []*storage.SnapshotExternal - a list of SnapshotExternal objects +// error - any error encountered // Example: -// snapshots, err := tridentOrchestrator.ListSnapshotsByName("trident") - +// snapshots, err := orchestrator.ListSnapshotsByName("mySnapshot") +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) ListSnapshotsByName( _ context.Context, snapshotName string, ) (snapshots []*storage.SnapshotExternal, err error) { @@ -4346,15 +4374,17 @@ func (o *TridentOrchestrator) ListSnapshotsByName( return snapshots, nil } -// ListSnapshotsForVolume returns a list of snapshots for the specified volume +// ListSnapshotsForVolume returns a list of snapshots for a given volume // Parameters: -// volumeName - name of the volume +// ctx - context for logging +// volumeName - name of the volume // Returns: -// snapshots - list of snapshots for the specified volume -// err - error, if any +// list of snapshots for the given volume +// error - non-nil if an error occurred // Example: -// snapshots, err := trident.ListSnapshotsForVolume("vol-01") - +// snapshots, err := orchestrator.ListSnapshotsForVolume(ctx, "volume1") +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) ListSnapshotsForVolume( _ context.Context, volumeName string, ) (snapshots []*storage.SnapshotExternal, err error) { @@ -4381,16 +4411,17 @@ func (o *TridentOrchestrator) ListSnapshotsForVolume( return snapshots, nil } -// ReadSnapshotsForVolume returns a list of snapshots for a given volume. +// ReadSnapshotsForVolume returns a list of snapshots for the specified volume // Parameters: // ctx - context for logging // volumeName - name of the volume // Returns: -// []*storage.SnapshotExternal - list of snapshots for the given volume -// error - error, if any +// []*storage.SnapshotExternal - list of snapshots +// error - any error encountered // Example: -// snapshots, err := o.ReadSnapshotsForVolume(ctx, volumeName) - +// snapshots, err := orchestrator.ReadSnapshotsForVolume(ctx, volumeName) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) ReadSnapshotsForVolume( ctx context.Context, volumeName string, ) (externalSnapshots []*storage.SnapshotExternal, err error) { @@ -4418,15 +4449,20 @@ func (o *TridentOrchestrator) ReadSnapshotsForVolume( return externalSnapshots, nil } -// ReloadVolumes reloads the volumes from the backend +// ReloadVolumes re-reads the list of volumes from the backend and updates the +// orchestrator's internal state. +// It returns an error if the volume list could not be retrieved. // Parameters: // ctx - context for logging // Returns: -// error - any errors encountered -// It returns an error if the reload fails, in which case the original volume list is restored. +// error - nil if successful, otherwise an error // Example: -// err := orchestrator.ReloadVolumes(context.Background()) - +// err := o.ReloadVolumes(ctx) +// if err != nil { +// // handle error +// } +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) ReloadVolumes(ctx context.Context) (err error) { if o.bootstrapError != nil { @@ -4528,6 +4564,7 @@ func (o *TridentOrchestrator) ResizeVolume(ctx context.Context, volumeName, newS // caller will take care of both of these. It also assumes that the volume // exists in memory. func (o *TridentOrchestrator) resizeVolume(ctx context.Context, volume *storage.Volume, newSize string) error { +func (o *TridentOrchestrator) ResizeVolume(ctx context.Context, volumeName, newSize string) (err error) { volumeBackend, found := o.backends[volume.BackendUUID] if !found { @@ -4568,6 +4605,7 @@ func (o *TridentOrchestrator) resizeVolume(ctx context.Context, volume *storage. // resizeVolumeCleanup is used to clean up artifacts of volume resize in case // anything goes wrong during the operation. func (o *TridentOrchestrator) resizeVolumeCleanup( +func (o *TridentOrchestrator) resizeVolume(ctx context.Context, volume *storage.Volume, newSize string) error { ctx context.Context, err error, vol *storage.Volume, volTxn *storage.VolumeTransaction, ) error { @@ -4610,6 +4648,7 @@ func (o *TridentOrchestrator) resizeVolumeCleanup( // 2. 'BlockOnFile' protocol set via the PVC annotation with multi-node access mode // 3. We do not support raw block volumes with block on file or NFS protocol. func (o *TridentOrchestrator) getProtocol( +func (o *TridentOrchestrator) resizeVolumeCleanup( ctx context.Context, volumeMode config.VolumeMode, accessMode config.AccessMode, protocol config.Protocol, ) (config.Protocol, error) { @@ -4691,23 +4730,19 @@ func (o *TridentOrchestrator) getProtocol( return res.protocol, res.err } -// AddStorageClass adds a storage class to the orchestrator. +func (o *TridentOrchestrator) AddStorageClass( +// AddStorageClass adds a storage class to the orchestrator +// It returns the storage class and an error if one occurred // Parameters: -// scConfig: configuration for the storage class to be added +// ctx - context for logging +// scConfig - storage class configuration // Returns: -// scExternal: the storage class that was added -// err: any errors encountered -// It returns an error if the storage class already exists. +// *storageclass.External - storage class +// error - error if one occurred // Example: -// scConfig := &storageclass.Config{ -// Name: "gold", -// Attributes: map[string]sa.Request{ -// sa.Media: "ssd", -// sa.ProvisioningType: "thin", -// }, -// } // scExternal, err := o.AddStorageClass(ctx, scConfig) - +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) AddStorageClass( ctx context.Context, scConfig *storageclass.Config, ) (scExternal *storageclass.External, err error) { @@ -4749,16 +4784,15 @@ func (o *TridentOrchestrator) AddStorageClass( // GetStorageClass returns the storage class with the given name // Parameters: -// scName - name of the storage class +// ctx - context for logging +// scName - name of the storage class to retrieve // Returns: // *storageclass.External - the storage class -// error - nil if successful +// error - any error encountered // Example: -// sc, err := o.GetStorageClass(ctx, "default") -// if err != nil { -// return fmt.Errorf("error getting storage class %v: %v", "default", err) -// } - +// sc, err := tridentOrchestrator.GetStorageClass(ctx, "sc1") +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) GetStorageClass( ctx context.Context, scName string, ) (scExternal *storageclass.External, err error) { @@ -4780,15 +4814,16 @@ func (o *TridentOrchestrator) GetStorageClass( return sc.ConstructExternal(ctx), nil } -// ListStorageClasses returns a list of storage classes +// ListStorageClasses returns a list of all storage classes // Parameters: // ctx - context for logging // Returns: -// []*storageclass.External - list of storage classes +// []*storageclass.External - a list of storage classes // error - error, if any // Example: -// storageClasses, err := orchestrator.ListStorageClasses(ctx) - +// scExternals, err := o.ListStorageClasses(ctx) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) ListStorageClasses(ctx context.Context) ( scExternals []*storageclass.External, err error, ) { @@ -4809,15 +4844,18 @@ func (o *TridentOrchestrator) ListStorageClasses(ctx context.Context) ( } // DeleteStorageClass deletes a storage class +// It returns an error if the storage class does not exist // Parameters: -// ctx - context for logging // scName - name of the storage class to delete // Returns: // error - any error encountered -// It returns an error if the storage class is not found. // Example: -// err := o.DeleteStorageClass(ctx, "gold") - +// err := orchestrator.DeleteStorageClass(ctx, "my-storage-class") +// if err != nil { +// log.Error("Error deleting storage class: ", err) +// } +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) DeleteStorageClass(ctx context.Context, scName string) (err error) { if o.bootstrapError != nil { return o.bootstrapError @@ -4849,15 +4887,16 @@ func (o *TridentOrchestrator) DeleteStorageClass(ctx context.Context, scName str return nil } -// reconcileNodeAccessOnAllBackends reconciles node access on all backends. +// reconcileNodeAccessOnAllBackends reconciles node access on all backends +// It returns an error if any backend fails to reconcile // Parameters: // ctx - context // Returns: -// error - any error encountered -// It returns an error if any of the backends fail to reconcile node access. +// error - error if any backend fails to reconcile // Example: // err := o.reconcileNodeAccessOnAllBackends(ctx) - +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) reconcileNodeAccessOnAllBackends(ctx context.Context) error { if config.CurrentDriverContext != config.ContextCSI { @@ -4879,16 +4918,20 @@ func (o *TridentOrchestrator) reconcileNodeAccessOnAllBackends(ctx context.Conte return nil } -// reconcileNodeAccessOnBackend reconciles node access on the backend +// reconcileNodeAccessOnBackend reconciles node access on the backend. +// It returns an error if the operation fails. // Parameters: // ctx - context // b - backend // Returns: // error - any error encountered -// It returns an error if it is unable to reconcile node access on the backend // Example: -// error := o.reconcileNodeAccessOnBackend(ctx, backend) - +// err := o.reconcileNodeAccessOnBackend(ctx, b) +// if err != nil { +// return err +// } +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) reconcileNodeAccessOnBackend(ctx context.Context, b storage.Backend) error { if config.CurrentDriverContext != config.ContextCSI { @@ -4915,6 +4958,7 @@ func (o *TridentOrchestrator) safeReconcileNodeAccessOnBackend(ctx context.Conte // PeriodicallyReconcileNodeAccessOnBackends is intended to be run as a goroutine and will periodically run // safeReconcileNodeAccessOnBackend for each backend in the orchestrator func (o *TridentOrchestrator) PeriodicallyReconcileNodeAccessOnBackends() { +func (o *TridentOrchestrator) safeReconcileNodeAccessOnBackend(ctx context.Context, b storage.Backend) error { o.stopNodeAccessLoop = make(chan bool) ctx := GenerateRequestContext(context.Background(), "", ContextSourcePeriodic) @@ -4948,14 +4992,22 @@ func (o *TridentOrchestrator) PeriodicallyReconcileNodeAccessOnBackends() { } } +func (o *TridentOrchestrator) AddNode( // AddNode adds a node to the orchestrator -// It returns an error if the node already exists +// It returns an error if the node could not be added +// Parameters: +// ctx - context +// node - the node to add +// nodeEventCallback - callback function to be invoked when a node event occurs +// Return: +// error - error if the node could not be added // Example: -// err := orchestrator.AddNode(ctx, node) -// if err != nil { -// log.Errorf("Could not add node %v: %v", node.Name, err) -// } - +// err := o.AddNode(ctx, node, nodeEventCallback) +// if err != nil { +// return err +// } +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) AddNode( ctx context.Context, node *utils.Node, nodeEventCallback NodeEventCallback, ) (err error) { @@ -4998,29 +5050,32 @@ func (o *TridentOrchestrator) AddNode( return nil } -// invalidateAllBackendNodeAccess invalidates the node access for all backends +// invalidateAllBackendNodeAccess invalidates the node access cache for all backends. +// Returns: +// - nil if successful +// - error if unsuccessful // Example: -// o.invalidateAllBackendNodeAccess() - +// - err := o.invalidateAllBackendNodeAccess() +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) invalidateAllBackendNodeAccess() { for _, backend := range o.backends { backend.InvalidateNodeAccess() } } -// handleUpdatedNodePrep handles node prep status updates +// handleUpdatedNodePrep handles node prep updates from the backend // Parameters: // ctx - context // protocol - protocol for which node prep is being reported -// node - node object -// nodeEventCallback - callback to invoke when a node event is to be reported +// node - node for which node prep is being reported +// nodeEventCallback - callback to invoke to report node events +// Returns: +// none // Example: -// o.handleUpdatedNodePrep(ctx, "NFS", node, func(nodeEventCallbackType helpers.EventType, nodeEventCallbackReason string, message string) { -// nodeEvent := helpers.NewNodeEvent(node.Name, nodeEventCallbackType, nodeEventCallbackReason, message) -// o.eventRecorder.Event(o.tridentOrchestrator, nodeEventCallbackType, nodeEventCallbackReason, message) -// o.nodeEvents.Add(nodeEvent) -// }) - +// handleUpdatedNodePrep(ctx, "NFS", node, nodeEventCallback) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) handleUpdatedNodePrep( ctx context.Context, protocol string, node *utils.Node, nodeEventCallback NodeEventCallback, ) { @@ -5063,19 +5118,17 @@ func (o *TridentOrchestrator) handleUpdatedNodePrep( } } -// GetNode returns a node by name +// GetNode returns the node object for the specified node name // Parameters: -// ctx - context -// nName - name of node to retrieve +// ctx - context for logging +// nName - name of the node // Returns: -// *utils.Node - node object -// error - error object if any +// *utils.Node - the node object +// error - error if any // Example: -// node, err := o.GetNode(ctx, "node1") -// if err != nil { -// // handle error -// } - +// node, err := GetNode(context.TODO(), "localhost") +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) GetNode(ctx context.Context, nName string) (node *utils.Node, err error) { if o.bootstrapError != nil { return nil, o.bootstrapError @@ -5099,12 +5152,14 @@ func (o *TridentOrchestrator) GetNode(ctx context.Context, nName string) (node * // ListNodes returns a list of all nodes in the cluster // Parameters: // context - context for the request +// filter - filter to apply to the list // Returns: -// nodes - list of nodes in the cluster -// err - error object +// []*utils.Node - list of nodes +// error - error if any // Example: -// nodes, err := tridentOrchestrator.ListNodes(context.TODO()) - +// nodes, err := core.ListNodes(context, nil) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) ListNodes(context.Context) (nodes []*utils.Node, err error) { if o.bootstrapError != nil { return nil, o.bootstrapError @@ -5122,17 +5177,17 @@ func (o *TridentOrchestrator) ListNodes(context.Context) (nodes []*utils.Node, e return nodes, nil } -// DeleteNode removes a node from the orchestrator. +// DeleteNode removes the node from the orchestrator. +// It returns an error if the node does not exist. // Parameters: -// nodeName: The name of the node to remove. -// force: If true, remove the node even if it still has volumes published to it. -// It returns an error if the node is not found, or if it still has volumes published to it. +// nodeName - name of the node to delete +// force - if true, delete the node even if volumes are published to it +// Returns: +// error - error if the node could not be deleted // Example: -// err := orchestrator.DeleteNode(nodeName, false) -// if err != nil { -// t.Errorf("Failed to delete node %s: %+v", nodeName, err) -// } - +// error := orchestrator.DeleteNode(ctx, "node1") +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) DeleteNode(ctx context.Context, nodeName string) (err error) { if o.bootstrapError != nil { return o.bootstrapError @@ -5178,15 +5233,16 @@ func (o *TridentOrchestrator) DeleteNode(ctx context.Context, nodeName string) ( } // deleteNode deletes a node from the orchestrator +// It returns an error if the node is not found // Parameters: // ctx - context // nodeName - name of the node to delete // Returns: -// error - error if any -// It returns an error if the node is not found +// error - error if the node is not found // Example: -// err := o.deleteNode(ctx, nodeName) - +// err := o.deleteNode(ctx, "node1") +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) deleteNode(ctx context.Context, nodeName string) (err error) { node, found := o.nodes[nodeName] @@ -5227,6 +5283,7 @@ func (o *TridentOrchestrator) AddVolumePublication( // GetVolumePublication returns the volume publication for a given volume/node pair func (o *TridentOrchestrator) GetVolumePublication( +func (o *TridentOrchestrator) AddVolumePublication( _ context.Context, volumeName, nodeName string, ) (publication *utils.VolumePublication, err error) { if o.bootstrapError != nil { @@ -5248,6 +5305,7 @@ func (o *TridentOrchestrator) GetVolumePublication( // ListVolumePublications returns a list of all volume publications func (o *TridentOrchestrator) ListVolumePublications( +func (o *TridentOrchestrator) GetVolumePublication( context.Context, ) (publications []*utils.VolumePublication, err error) { if o.bootstrapError != nil { @@ -5270,6 +5328,7 @@ func (o *TridentOrchestrator) ListVolumePublications( // ListVolumePublicationsForVolume returns a list of all volume publications for a given volume func (o *TridentOrchestrator) ListVolumePublicationsForVolume( +func (o *TridentOrchestrator) ListVolumePublications( ctx context.Context, volumeName string, ) (publications []*utils.VolumePublication, err error) { if o.bootstrapError != nil { @@ -5285,14 +5344,16 @@ func (o *TridentOrchestrator) ListVolumePublicationsForVolume( return } -// listVolumePublicationsForVolume returns a list of volume publications for a given volume +func (o *TridentOrchestrator) listVolumePublicationsForVolume( +// listVolumePublicationsForVolume returns a list of publications for the given volume // Parameters: -// volumeName: name of the volume +// volumeName - name of the volume // Returns: -// []*utils.VolumePublication: list of volume publications +// list of publications for the given volume // Example: -// publications, err := o.listVolumePublicationsForVolume(volumeName) - +// publications := o.listVolumePublicationsForVolume(volumeName) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) listVolumePublicationsForVolume( _ context.Context, volumeName string, ) (publications []*utils.VolumePublication) { @@ -5321,14 +5382,16 @@ func (o *TridentOrchestrator) ListVolumePublicationsForNode( return } -// listVolumePublicationsForNode returns a list of all volume publications for the given node +func (o *TridentOrchestrator) listVolumePublicationsForNode( +// listVolumePublicationsForNode returns the list of published volumes for a given node // Parameters: // nodeName - the name of the node // Returns: -// a list of volume publications +// []*utils.VolumePublication - the list of published volumes for the node // Example: -// publications, _ := o.listVolumePublicationsForNode(nodeName) - +// volumes, err := o.listVolumePublicationsForNode(ctx, "kube-node-1") +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) listVolumePublicationsForNode( _ context.Context, nodeName string, ) (publications []*utils.VolumePublication) { @@ -5368,13 +5431,17 @@ func (o *TridentOrchestrator) DeleteVolumePublication(ctx context.Context, volum return nil } +func (o *TridentOrchestrator) removeVolumePublicationFromCache(volumeID string, nodeID string) { // removeVolumePublicationFromCache removes the volume publication from the cache // Parameters: // volumeID: the volume ID // nodeID: the node ID +// Returns: +// None // Example: -// o.removeVolumePublicationFromCache("vol1", "node1") - +// o.removeVolumePublicationFromCache(volumeID, nodeID) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) removeVolumePublicationFromCache(volumeID string, nodeID string) { delete(o.volumePublications[volumeID], nodeID) // If there are no more nodes for this volume, remove the volume's entry @@ -5383,20 +5450,21 @@ func (o *TridentOrchestrator) removeVolumePublicationFromCache(volumeID string, } } -// updateBackendOnPersistentStore updates the backend information in the persistent store +// updateBackendOnPersistentStore updates the backend information on the persistent store +// It returns an error if the update fails // Parameters: // ctx - context for logging // backend - the backend to update // newBackend - true if this is a new backend, false if it is an existing backend -// Returns: -// error - any error encountered -// It returns an error if the backend could not be updated in the persistent store +// Return: +// error - error if the update fails // Example: -// err := o.updateBackendOnPersistentStore(ctx, backend, true) +// err := updateBackendOnPersistentStore(ctx, backend, true) // if err != nil { -// return err +// return err // } - +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) updateBackendOnPersistentStore( ctx context.Context, backend storage.Backend, newBackend bool, ) error { @@ -5422,15 +5490,16 @@ func (o *TridentOrchestrator) updateBackendOnPersistentStore( } // updateVolumeOnPersistentStore updates the volume information in persistent store +// It returns an error if the update fails // Parameters: -// ctx - context for logging -// vol - volume to update +// ctx - context for logging +// vol - volume to update // Returns: -// error - any error encountered -// It returns an error if the volume cannot be updated in persistent store +// error - error if the update fails // Example: -// err := o.updateVolumeOnPersistentStore(ctx, vol) - +// err := o.updateVolumeOnPersistentStore(ctx, vol) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) updateVolumeOnPersistentStore(ctx context.Context, vol *storage.Volume) error { // Update the volume information in persistent store @@ -5443,16 +5512,17 @@ func (o *TridentOrchestrator) updateVolumeOnPersistentStore(ctx context.Context, return o.storeClient.UpdateVolume(ctx, vol) } -// replaceBackendAndUpdateVolumesOnPersistentStore updates both backend and volume information in persistent store +// replaceBackendAndUpdateVolumesOnPersistentStore updates the backend and volume information in persistent store +// It returns an error if the backend or volume information could not be updated // Parameters: // origBackend - the original backend // newBackend - the new backend // Returns: -// error - any error encountered -// It returns an error if the backend is not found in persistent store +// error - an error if the backend or volume information could not be updated // Example: -// err := o.replaceBackendAndUpdateVolumesOnPersistentStore(ctx, origBackend, newBackend) - +// error := o.replaceBackendAndUpdateVolumesOnPersistentStore(ctx, oldBackend, newBackend) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) replaceBackendAndUpdateVolumesOnPersistentStore( ctx context.Context, origBackend, newBackend storage.Backend, ) error { @@ -5465,13 +5535,16 @@ func (o *TridentOrchestrator) replaceBackendAndUpdateVolumesOnPersistentStore( return o.storeClient.ReplaceBackendAndUpdateVolumes(ctx, origBackend, newBackend) } -// isCRDContext returns true if the context was created by a CRD request. +// isCRDContext returns true if the context is from a CRD request // Parameters: -// ctx - the context to check +// ctx - the context +// Returns: +// true if the context is from a CRD request, false otherwise // Example: -// ctx := context.Background() -// isCRD := o.isCRDContext(ctx) - +// ctx := context.WithValue(context.Background(), ContextKeyRequestSource, ContextSourceCRD) +// isCRD := isCRDContext(ctx) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) isCRDContext(ctx context.Context) bool { ctxSource := ctx.Value(ContextKeyRequestSource) return ctxSource != nil && ctxSource == ContextSourceCRD @@ -5503,6 +5576,7 @@ func (o *TridentOrchestrator) EstablishMirror( // ReestablishMirror recreates a previously existing replication mirror relationship between 2 volumes on a backend func (o *TridentOrchestrator) ReestablishMirror( +func (o *TridentOrchestrator) EstablishMirror( ctx context.Context, backendUUID, localVolumeHandle, remoteVolumeHandle string, ) (err error) { @@ -5527,6 +5601,7 @@ func (o *TridentOrchestrator) ReestablishMirror( // PromoteMirror makes the local volume the primary func (o *TridentOrchestrator) PromoteMirror( +func (o *TridentOrchestrator) ReestablishMirror( ctx context.Context, backendUUID, localVolumeHandle, remoteVolumeHandle, snapshotHandle string, ) (waitingForSnapshot bool, err error) { @@ -5551,6 +5626,7 @@ func (o *TridentOrchestrator) PromoteMirror( // GetMirrorStatus returns the current status of the mirror relationship func (o *TridentOrchestrator) GetMirrorStatus( +func (o *TridentOrchestrator) PromoteMirror( ctx context.Context, backendUUID, localVolumeHandle, remoteVolumeHandle string, ) (status string, err error) { @@ -5573,15 +5649,18 @@ func (o *TridentOrchestrator) GetMirrorStatus( return mirrorBackend.GetMirrorStatus(ctx, localVolumeHandle, remoteVolumeHandle) } -// CanBackendMirror returns true if the backend supports mirroring +func (o *TridentOrchestrator) CanBackendMirror(_ context.Context, backendUUID string) (capable bool, err error) { +// CanBackendMirror checks if the backend can mirror +// It returns true if the backend can mirror and false otherwise // Parameters: // backendUUID - the backend UUID // Returns: -// bool - true if the backend supports mirroring -// error - any error encountered +// capable - true if the backend can mirror, false otherwise +// err - any error encountered // Example: -// capable, err := orchestrator.CanBackendMirror(backendUUID) - +// capable, err := o.CanBackendMirror(ctx, backendUUID) +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) CanBackendMirror(_ context.Context, backendUUID string) (capable bool, err error) { if o.bootstrapError != nil { @@ -5623,16 +5702,19 @@ func (o *TridentOrchestrator) ReleaseMirror( return mirrorBackend.ReleaseMirror(ctx, localVolumeHandle) } -// GetCHAP returns CHAP information for the specified volume +func (o *TridentOrchestrator) GetCHAP( +// GetCHAP returns the CHAP information for a volume // Parameters: +// ctx - context // volumeName - name of the volume // nodeName - name of the node // Returns: -// chapInfo - CHAP information -// err - error object +// chapInfo - CHAP information for the volume +// err - error, if any // Example: -// chapInfo, err := orchestrator.GetCHAP(ctx, "myVolume", "myNode") - +// chapInfo, err := orchestrator.GetCHAP(ctx, "volume1", "node1") +// +// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- func (o *TridentOrchestrator) GetCHAP( ctx context.Context, volumeName, nodeName string, ) (chapInfo *utils.IscsiChapInfo, err error) { diff --git a/core/orchestrator_core_test.go b/core/orchestrator_core_test.go index 690980a9e..836d170aa 100644 --- a/core/orchestrator_core_test.go +++ b/core/orchestrator_core_test.go @@ -40,6 +40,14 @@ var ( ctx = context.Background ) +func init() { + testing.Init() + if *debug { + log.SetLevel(log.DebugLevel) + } + + inMemoryClient = persistentstore.NewInMemoryClient() +} type deleteTest struct { name string @@ -53,13 +61,16 @@ type recoveryTest struct { expectDestroy bool } -// cleanup is a helper function to clean up the persistent store. +// cleanup cleans up the persistent store and the in-memory client. // Parameters: -// t - the test object -// o - the orchestrator object +// t: the test object +// o: the orchestrator to clean up +// Returns: +// None // Example: -// defer cleanup(t, o) - +// cleanup(t, o) +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func cleanup(t *testing.T, o *TridentOrchestrator) { err := o.storeClient.DeleteBackends(ctx()) if err != nil && !persistentstore.MatchKeyNotFoundErr(err) { @@ -93,21 +104,23 @@ func cleanup(t *testing.T, o *TridentOrchestrator) { } } -// diffConfig compares two structs, ignoring the fieldToSkip -// and returns a list of differences +// diffConfig compares two structs and returns a list of differences +// between them. +// It returns an empty list if there are no differences. +// +// The fieldToSkip parameter is optional and can be used to skip a field +// in the comparison. // Parameters: // expected: the expected struct // got: the actual struct -// fieldToSkip: the name of a field to skip +// fieldToSkip: the name of a field to skip in the comparison // Returns: // a list of differences -// It returns an empty list if there are no differences // Example: // diffs := diffConfig(expected, got, "") -// if len(diffs) > 0 { -// t.Errorf("Config differs: %v", diffs) -// } - +// diffs := diffConfig(expected, got, "FieldToSkip") +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func diffConfig(expected, got interface{}, fieldToSkip string) []string { diffs := make([]string, 0) @@ -135,18 +148,17 @@ func diffConfig(expected, got interface{}, fieldToSkip string) []string { } // To be called after reflect.DeepEqual has failed. -// diffExternalBackends compares two external backends and returns a list of differences +// diffExternalBackends compares two external backends and logs any differences // Parameters: -// expected: the expected backend -// got: the backend to compare against +// t: testing.T object +// expected: expected backend +// got: got backend // Returns: -// A list of differences +// None // Example: -// diffs := diffExternalBackends(expected, got) -// if len(diffs) > 0 { -// t.Errorf("External backends differ:\n\t%s", strings.Join(diffs, "\n\t")) -// } - +// diffExternalBackends(t, expected, got) +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func diffExternalBackends(t *testing.T, expected, got *storage.BackendExternal) { diffs := make([]string, 0) @@ -238,15 +250,17 @@ func diffExternalBackends(t *testing.T, expected, got *storage.BackendExternal) } } -// runDeleteTest runs a delete test. +// runDeleteTest runs a single test from the deleteTest suite. // Parameters: -// t: the test object -// d: the delete test to run -// orchestrator: the orchestrator to use +// t: the test object +// d: the deleteTest to run +// orchestrator: the orchestrator to use +// Returns: +// nothing // Example: -// d := &deleteTest{name: "test1", expectedSuccess: true} -// runDeleteTest(t, d, orchestrator) - +// runDeleteTest(t, tests[0], orchestrator) +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func runDeleteTest( t *testing.T, d *deleteTest, orchestrator *TridentOrchestrator, ) { @@ -304,16 +318,18 @@ type storageClassTest struct { expected []*tu.PoolMatch } -// getOrchestrator returns an orchestrator with a bootstrapped backend -// and a single node. +// getOrchestrator is a helper function for tests that need to create an orchestrator. +// It will create a new orchestrator, bootstrap it, and return it. +// It returns the orchestrator and a cleanup function that should be called when the test is done. // Parameters: -// t - the test object +// t: the test object // Returns: -// *TridentOrchestrator - the orchestrator +// o: the orchestrator // Example: // o := getOrchestrator(t) // defer o.Terminate() - +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func getOrchestrator(t *testing.T) *TridentOrchestrator { var ( storeClient persistentstore.Client @@ -331,18 +347,20 @@ func getOrchestrator(t *testing.T) *TridentOrchestrator { return o } -// validateStorageClass checks that the storage class matches the expected pools. +// validateStorageClass validates that the storage class has the expected pools. // Parameters: // t: The test object. // o: The orchestrator. // name: The name of the storage class. -// expected: A list of expected pool matches. +// expected: The expected pools. +// Returns: +// None. // Example: // validateStorageClass(t, o, "sc1", []*tu.PoolMatch{ -// {BackendName: "be1", PoolName: "pool1"}, -// {BackendName: "be2", PoolName: "pool2"}, +// tu.NewPoolMatch("be1", "pool1"), // }) - +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func validateStorageClass( t *testing.T, o *TridentOrchestrator, @@ -386,51 +404,788 @@ func validateStorageClass( pool.Name()) } } - } - if len(remaining) > 0 { - remainingNames := make([]string, len(remaining)) - for i, r := range remaining { - remainingNames[i] = r.String() + } + if len(remaining) > 0 { + remainingNames := make([]string, len(remaining)) + for i, r := range remaining { + remainingNames[i] = r.String() + } + t.Errorf("%s: Storage class failed to match storage pools %s", name, strings.Join(remainingNames, ", ")) + } + persistentSC, err := o.storeClient.GetStorageClass(ctx(), name) + if err != nil { + t.Fatalf("Unable to get storage class %s from backend: %v", name, err) + } + if !reflect.DeepEqual( + persistentSC, + sc.ConstructPersistent(), + ) { + gotSCJSON, err := json.Marshal(persistentSC) + if err != nil { + t.Fatalf("Unable to marshal persisted storage class %s: %v", name, err) + } + expectedSCJSON, err := json.Marshal(sc.ConstructPersistent()) + if err != nil { + t.Fatalf("Unable to marshal expected persistent storage class %s: %v", name, err) + } + t.Errorf("%s: Storage class persisted incorrectly.\n\tExpected %s\n\tGot %s", name, expectedSCJSON, gotSCJSON) + } +} + +// This test is fairly heavyweight, but, due to the need to accumulate state +// to run the later tests, it's easier to do this all in one go at the moment. +// Consider breaking this up if it gets unwieldy, though. +func TestAddStorageClassVolumes(t *testing.T) { + mockPools := tu.GetFakePools() + orchestrator := getOrchestrator(t) + + errored := false + for _, c := range []struct { + name string + protocol config.Protocol + poolNames []string + }{ + { + name: "fast-a", + protocol: config.File, + poolNames: []string{tu.FastSmall, tu.FastThinOnly}, + }, + { + name: "fast-b", + protocol: config.File, + poolNames: []string{tu.FastThinOnly, tu.FastUniqueAttr}, + }, + { + name: "slow-file", + protocol: config.File, + poolNames: []string{tu.SlowNoSnapshots, tu.SlowSnapshots}, + }, + { + name: "slow-block", + protocol: config.Block, + poolNames: []string{tu.SlowNoSnapshots, tu.SlowSnapshots, tu.MediumOverlap}, + }, + } { + pools := make(map[string]*fake.StoragePool, len(c.poolNames)) + for _, poolName := range c.poolNames { + pools[poolName] = mockPools[poolName] + } + volumes := make([]fake.Volume, 0) + fakeConfig, err := fakedriver.NewFakeStorageDriverConfigJSON(c.name, c.protocol, pools, volumes) + if err != nil { + t.Fatalf("Unable to generate config JSON for %s: %v", c.name, err) + } + _, err = orchestrator.AddBackend(ctx(), fakeConfig, "") + if err != nil { + t.Errorf("Unable to add backend %s: %v", c.name, err) + errored = true + } + orchestrator.mutex.Lock() + backend, err := orchestrator.getBackendByBackendName(c.name) + if err != nil { + t.Fatalf("Backend %s not stored in orchestrator, err %s", c.name, err) + } + persistentBackend, err := orchestrator.storeClient.GetBackend(ctx(), c.name) + if err != nil { + t.Fatalf("Unable to get backend %s from persistent store: %v", c.name, err) + } else if !reflect.DeepEqual(backend.ConstructPersistent(ctx()), persistentBackend) { + t.Error("Wrong data stored for backend ", c.name) + } + orchestrator.mutex.Unlock() + } + if errored { + t.Fatal("Failed to add all backends; aborting remaining tests.") + } + + // Add storage classes + scTests := []storageClassTest{ + { + config: &storageclass.Config{ + Name: "slow", + Attributes: map[string]sa.Request{ + sa.IOPS: sa.NewIntRequest(40), + sa.Snapshots: sa.NewBoolRequest(true), + sa.ProvisioningType: sa.NewStringRequest("thin"), + }, + }, + expected: []*tu.PoolMatch{ + {Backend: "slow-file", Pool: tu.SlowSnapshots}, + {Backend: "slow-block", Pool: tu.SlowSnapshots}, + }, + }, + { + config: &storageclass.Config{ + Name: "fast", + Attributes: map[string]sa.Request{ + sa.IOPS: sa.NewIntRequest(2000), + sa.Snapshots: sa.NewBoolRequest(true), + sa.ProvisioningType: sa.NewStringRequest("thin"), + }, + }, + expected: []*tu.PoolMatch{ + {Backend: "fast-a", Pool: tu.FastSmall}, + {Backend: "fast-a", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastUniqueAttr}, + }, + }, + { + config: &storageclass.Config{ + Name: "fast-unique", + Attributes: map[string]sa.Request{ + sa.IOPS: sa.NewIntRequest(2000), + sa.Snapshots: sa.NewBoolRequest(true), + sa.ProvisioningType: sa.NewStringRequest("thin"), + sa.UniqueOptions: sa.NewStringRequest("baz"), + }, + }, + expected: []*tu.PoolMatch{ + {Backend: "fast-b", Pool: tu.FastUniqueAttr}, + }, + }, + { + config: &storageclass.Config{ + Name: "pools", + Pools: map[string][]string{ + "fast-a": {tu.FastSmall}, + "slow-block": {tu.SlowNoSnapshots, tu.MediumOverlap}, + }, + }, + expected: []*tu.PoolMatch{ + {Backend: "fast-a", Pool: tu.FastSmall}, + {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, + {Backend: "slow-block", Pool: tu.MediumOverlap}, + }, + }, + { + config: &storageclass.Config{ + Name: "additionalPools", + AdditionalPools: map[string][]string{ + "fast-a": {tu.FastThinOnly}, + "slow-block": {tu.SlowNoSnapshots, tu.MediumOverlap}, + }, + }, + expected: []*tu.PoolMatch{ + {Backend: "fast-a", Pool: tu.FastThinOnly}, + {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, + {Backend: "slow-block", Pool: tu.MediumOverlap}, + }, + }, + { + config: &storageclass.Config{ + Name: "poolsWithAttributes", + Attributes: map[string]sa.Request{ + sa.IOPS: sa.NewIntRequest(2000), + sa.Snapshots: sa.NewBoolRequest(true), + }, + Pools: map[string][]string{ + "fast-a": {tu.FastThinOnly}, + "slow-block": {tu.SlowNoSnapshots, tu.MediumOverlap}, + }, + }, + expected: []*tu.PoolMatch{ + {Backend: "fast-a", Pool: tu.FastThinOnly}, + }, + }, + { + config: &storageclass.Config{ + Name: "additionalPoolsWithAttributes", + Attributes: map[string]sa.Request{ + sa.IOPS: sa.NewIntRequest(2000), + sa.Snapshots: sa.NewBoolRequest(true), + }, + AdditionalPools: map[string][]string{ + "fast-a": {tu.FastThinOnly}, + "slow-block": {tu.SlowNoSnapshots}, + }, + }, + expected: []*tu.PoolMatch{ + {Backend: "fast-a", Pool: tu.FastSmall}, + {Backend: "fast-a", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastUniqueAttr}, + {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, + }, + }, + { + config: &storageclass.Config{ + Name: "additionalPoolsWithAttributesAndPools", + Attributes: map[string]sa.Request{ + sa.IOPS: sa.NewIntRequest(2000), + sa.Snapshots: sa.NewBoolRequest(true), + }, + Pools: map[string][]string{ + "fast-a": {tu.FastThinOnly}, + "slow-block": {tu.SlowNoSnapshots, tu.MediumOverlap}, + }, + AdditionalPools: map[string][]string{ + "fast-b": {tu.FastThinOnly}, + "slow-block": {tu.SlowNoSnapshots}, + }, + }, + expected: []*tu.PoolMatch{ + {Backend: "fast-a", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastThinOnly}, + {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, + }, + }, + { + config: &storageclass.Config{ + Name: "additionalPoolsNoMatch", + AdditionalPools: map[string][]string{ + "unknown": {tu.FastThinOnly}, + }, + }, + expected: []*tu.PoolMatch{}, + }, + { + config: &storageclass.Config{ + Name: "mixed", + AdditionalPools: map[string][]string{ + "slow-file": {tu.SlowNoSnapshots}, + "fast-b": {tu.FastThinOnly, tu.FastUniqueAttr}, + }, + Attributes: map[string]sa.Request{ + sa.IOPS: sa.NewIntRequest(2000), + sa.Snapshots: sa.NewBoolRequest(true), + sa.ProvisioningType: sa.NewStringRequest("thin"), + }, + }, + expected: []*tu.PoolMatch{ + {Backend: "fast-a", Pool: tu.FastSmall}, + {Backend: "fast-a", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastUniqueAttr}, + {Backend: "slow-file", Pool: tu.SlowNoSnapshots}, + }, + }, + { + config: &storageclass.Config{ + Name: "emptyStorageClass", + }, + expected: []*tu.PoolMatch{ + {Backend: "fast-a", Pool: tu.FastSmall}, + {Backend: "fast-a", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastUniqueAttr}, + {Backend: "slow-file", Pool: tu.SlowNoSnapshots}, + {Backend: "slow-file", Pool: tu.SlowSnapshots}, + {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, + {Backend: "slow-block", Pool: tu.SlowSnapshots}, + {Backend: "slow-block", Pool: tu.MediumOverlap}, + }, + }, + } + for _, s := range scTests { + _, err := orchestrator.AddStorageClass(ctx(), s.config) + if err != nil { + t.Errorf("Unable to add storage class %s: %v", s.config.Name, err) + continue + } + validateStorageClass(t, orchestrator, s.config.Name, s.expected) + } + preSCDeleteTests := make([]*deleteTest, 0) + postSCDeleteTests := make([]*deleteTest, 0) + for _, s := range []struct { + name string + config *storage.VolumeConfig + expectedSuccess bool + expectedMatches []*tu.PoolMatch + expectedCount int + deleteAfterSC bool + }{ + { + name: "basic", + config: tu.GenerateVolumeConfig("basic", 1, "fast", config.File), + expectedSuccess: true, + expectedMatches: []*tu.PoolMatch{ + {Backend: "fast-a", Pool: tu.FastSmall}, + {Backend: "fast-a", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastUniqueAttr}, + }, + expectedCount: 1, + deleteAfterSC: false, + }, + { + name: "large", + config: tu.GenerateVolumeConfig("large", 100, "fast", config.File), + expectedSuccess: false, + expectedMatches: []*tu.PoolMatch{}, + expectedCount: 0, + deleteAfterSC: false, + }, + { + name: "block", + config: tu.GenerateVolumeConfig("block", 1, "pools", config.Block), + expectedSuccess: true, + expectedMatches: []*tu.PoolMatch{ + {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, + {Backend: "slow-block", Pool: tu.MediumOverlap}, + }, + expectedCount: 1, + deleteAfterSC: false, + }, + { + name: "block2", + config: tu.GenerateVolumeConfig("block2", 1, "additionalPools", config.Block), + expectedSuccess: true, + expectedMatches: []*tu.PoolMatch{ + {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, + {Backend: "slow-block", Pool: tu.MediumOverlap}, + }, + expectedCount: 1, + deleteAfterSC: false, + }, + { + name: "invalid-storage-class", + config: tu.GenerateVolumeConfig("invalid", 1, "nonexistent", config.File), + expectedSuccess: false, + expectedMatches: []*tu.PoolMatch{}, + expectedCount: 0, + deleteAfterSC: false, + }, + { + name: "repeated", + config: tu.GenerateVolumeConfig("basic", 20, "fast", config.File), + expectedSuccess: false, + expectedMatches: []*tu.PoolMatch{}, + expectedCount: 1, + deleteAfterSC: false, + }, + { + name: "postSCDelete", + config: tu.GenerateVolumeConfig("postSCDelete", 20, "fast", config.File), + expectedSuccess: true, + expectedMatches: []*tu.PoolMatch{ + {Backend: "fast-a", Pool: tu.FastSmall}, + {Backend: "fast-a", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastUniqueAttr}, + }, + expectedCount: 1, + deleteAfterSC: false, + }, + } { + vol, err := orchestrator.AddVolume(ctx(), s.config) + if err != nil && s.expectedSuccess { + t.Errorf("%s: got unexpected error %v", s.name, err) + continue + } else if err == nil && !s.expectedSuccess { + t.Errorf("%s: volume create succeeded unexpectedly.", s.name) + continue + } + orchestrator.mutex.Lock() + volume, found := orchestrator.volumes[s.config.Name] + if s.expectedCount == 1 && !found { + t.Errorf("%s: did not get volume where expected.", s.name) + } else if s.expectedCount == 0 && found { + t.Errorf("%s: got a volume where none expected.", s.name) + } + if !s.expectedSuccess { + deleteTest := &deleteTest{ + name: s.config.Name, + expectedSuccess: false, + } + if s.deleteAfterSC { + postSCDeleteTests = append(postSCDeleteTests, deleteTest) + } else { + preSCDeleteTests = append(preSCDeleteTests, deleteTest) + } + orchestrator.mutex.Unlock() + continue + } + matched := false + for _, potentialMatch := range s.expectedMatches { + volumeBackend, err := orchestrator.getBackendByBackendUUID(volume.BackendUUID) + if volumeBackend == nil || err != nil { + continue + } + if potentialMatch.Backend == volumeBackend.Name() && + potentialMatch.Pool == volume.Pool { + matched = true + deleteTest := &deleteTest{ + name: s.config.Name, + expectedSuccess: true, + } + if s.deleteAfterSC { + postSCDeleteTests = append(postSCDeleteTests, deleteTest) + } else { + preSCDeleteTests = append(preSCDeleteTests, deleteTest) + } + break + } + } + if !matched { + t.Errorf( + "%s: Volume placed on unexpected backend and storage pool: %s, %s", + s.name, + volume.BackendUUID, + volume.Pool, + ) + } + + externalVolume, err := orchestrator.storeClient.GetVolume(ctx(), s.config.Name) + if err != nil { + t.Errorf("%s: unable to communicate with backing store: %v", s.name, err) + } + if !reflect.DeepEqual(externalVolume, vol) { + t.Errorf("%s: external volume %s stored in backend does not match created volume.", s.name, + externalVolume.Config.Name) + externalVolJSON, err := json.Marshal(externalVolume) + if err != nil { + t.Fatal("Unable to remarshal JSON: ", err) + } + origVolJSON, err := json.Marshal(vol) + if err != nil { + t.Fatal("Unable to remarshal JSON: ", err) + } + t.Logf("\tExpected: %s\n\tGot: %s\n", string(externalVolJSON), string(origVolJSON)) + } + orchestrator.mutex.Unlock() + } + for _, d := range preSCDeleteTests { + runDeleteTest(t, d, orchestrator) + } + + // Delete storage classes. Note: there are currently no error cases. + for _, s := range scTests { + err := orchestrator.DeleteStorageClass(ctx(), s.config.Name) + if err != nil { + t.Errorf("%s delete: Unable to remove storage class: %v", s.config.Name, err) + } + orchestrator.mutex.Lock() + if _, ok := orchestrator.storageClasses[s.config.Name]; ok { + t.Errorf("%s delete: Storage class still found in map.", s.config.Name) + } + // Ensure that the storage class was cleared from its backends. + for _, poolMatch := range s.expected { + b, err := orchestrator.getBackendByBackendName(poolMatch.Backend) + if b == nil || err != nil { + t.Errorf("%s delete: backend %s not found in orchestrator.", s.config.Name, poolMatch.Backend) + continue + } + p, ok := b.Storage()[poolMatch.Pool] + if !ok { + t.Errorf("%s delete: storage pool %s not found for backend %s", s.config.Name, poolMatch.Pool, + poolMatch.Backend) + continue + } + for _, sc := range p.StorageClasses() { + if sc == s.config.Name { + t.Errorf("%s delete: storage class name not removed from backend %s, storage pool %s", + s.config.Name, poolMatch.Backend, poolMatch.Pool) + } + } + } + externalSC, err := orchestrator.storeClient.GetStorageClass(ctx(), s.config.Name) + if err != nil { + if !persistentstore.MatchKeyNotFoundErr(err) { + t.Errorf("%s: unable to communicate with backing store: %v", s.config.Name, err) + } + // We're successful if we get to here; we expect an + // ErrorCodeKeyNotFound. + } else if externalSC != nil { + t.Errorf("%s: storageClass not properly deleted from backing store", s.config.Name) + } + orchestrator.mutex.Unlock() + } + for _, d := range postSCDeleteTests { + runDeleteTest(t, d, orchestrator) + } + cleanup(t, orchestrator) +} + +// This test is modeled after TestAddStorageClassVolumes, but we don't need all the +// tests around storage class deletion, etc. +// TestCloneVolumes tests the CloneVolume functionality. +// It checks that the clone is placed in the same backend as the source volume, +// and that the clone is registered in the store. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +func TestCloneVolumes(t *testing.T) { + mockPools := tu.GetFakePools() + orchestrator := getOrchestrator(t) + + errored := false + for _, c := range []struct { + name string + protocol config.Protocol + poolNames []string + }{ + { + name: "fast-a", + protocol: config.File, + poolNames: []string{tu.FastSmall, tu.FastThinOnly}, + }, + { + name: "fast-b", + protocol: config.File, + poolNames: []string{tu.FastThinOnly, tu.FastUniqueAttr}, + }, + { + name: "slow-file", + protocol: config.File, + poolNames: []string{tu.SlowNoSnapshots, tu.SlowSnapshots}, + }, + { + name: "slow-block", + protocol: config.Block, + poolNames: []string{tu.SlowNoSnapshots, tu.SlowSnapshots, tu.MediumOverlap}, + }, + } { + pools := make(map[string]*fake.StoragePool, len(c.poolNames)) + for _, poolName := range c.poolNames { + pools[poolName] = mockPools[poolName] + } + + volumes := make([]fake.Volume, 0) + cfg, err := fakedriver.NewFakeStorageDriverConfigJSON( + c.name, c.protocol, + pools, volumes, + ) + if err != nil { + t.Fatalf("Unable to generate cfg JSON for %s: %v", c.name, err) + } + _, err = orchestrator.AddBackend(ctx(), cfg, "") + if err != nil { + t.Errorf("Unable to add backend %s: %v", c.name, err) + errored = true + } + orchestrator.mutex.Lock() + backend, err := orchestrator.getBackendByBackendName(c.name) + if backend == nil || err != nil { + t.Fatalf("Backend %s not stored in orchestrator", c.name) + } + persistentBackend, err := orchestrator.storeClient.GetBackend(ctx(), c.name) + if err != nil { + t.Fatalf("Unable to get backend %s from persistent store: %v", c.name, err) + } else if !reflect.DeepEqual(backend.ConstructPersistent(ctx()), persistentBackend) { + t.Error("Wrong data stored for backend ", c.name) + } + orchestrator.mutex.Unlock() + } + if errored { + t.Fatal("Failed to add all backends; aborting remaining tests.") + } + + // Add storage classes + storageClasses := []storageClassTest{ + { + config: &storageclass.Config{ + Name: "slow", + Attributes: map[string]sa.Request{ + sa.IOPS: sa.NewIntRequest(40), + sa.Snapshots: sa.NewBoolRequest(true), + sa.ProvisioningType: sa.NewStringRequest("thin"), + }, + }, + expected: []*tu.PoolMatch{ + {Backend: "slow-file", Pool: tu.SlowSnapshots}, + {Backend: "slow-block", Pool: tu.SlowSnapshots}, + }, + }, + { + config: &storageclass.Config{ + Name: "fast", + Attributes: map[string]sa.Request{ + sa.IOPS: sa.NewIntRequest(2000), + sa.Snapshots: sa.NewBoolRequest(true), + sa.ProvisioningType: sa.NewStringRequest("thin"), + }, + }, + expected: []*tu.PoolMatch{ + {Backend: "fast-a", Pool: tu.FastSmall}, + {Backend: "fast-a", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastUniqueAttr}, + }, + }, + { + config: &storageclass.Config{ + Name: "fast-unique", + Attributes: map[string]sa.Request{ + sa.IOPS: sa.NewIntRequest(2000), + sa.Snapshots: sa.NewBoolRequest(true), + sa.ProvisioningType: sa.NewStringRequest("thin"), + sa.UniqueOptions: sa.NewStringRequest("baz"), + }, + }, + expected: []*tu.PoolMatch{ + {Backend: "fast-b", Pool: tu.FastUniqueAttr}, + }, + }, + { + config: &storageclass.Config{ + Name: "specific", + AdditionalPools: map[string][]string{ + "fast-a": {tu.FastThinOnly}, + "slow-block": {tu.SlowNoSnapshots, tu.MediumOverlap}, + }, + }, + expected: []*tu.PoolMatch{ + {Backend: "fast-a", Pool: tu.FastThinOnly}, + {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, + {Backend: "slow-block", Pool: tu.MediumOverlap}, + }, + }, + { + config: &storageclass.Config{ + Name: "specificNoMatch", + AdditionalPools: map[string][]string{ + "unknown": {tu.FastThinOnly}, + }, + }, + expected: []*tu.PoolMatch{}, + }, + { + config: &storageclass.Config{ + Name: "mixed", + AdditionalPools: map[string][]string{ + "slow-file": {tu.SlowNoSnapshots}, + "fast-b": {tu.FastThinOnly, tu.FastUniqueAttr}, + }, + Attributes: map[string]sa.Request{ + sa.IOPS: sa.NewIntRequest(2000), + sa.Snapshots: sa.NewBoolRequest(true), + sa.ProvisioningType: sa.NewStringRequest("thin"), + }, + }, + expected: []*tu.PoolMatch{ + {Backend: "fast-a", Pool: tu.FastSmall}, + {Backend: "fast-a", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastUniqueAttr}, + {Backend: "slow-file", Pool: tu.SlowNoSnapshots}, + }, + }, + { + config: &storageclass.Config{ + Name: "emptyStorageClass", + }, + expected: []*tu.PoolMatch{ + {Backend: "fast-a", Pool: tu.FastSmall}, + {Backend: "fast-a", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastUniqueAttr}, + {Backend: "slow-file", Pool: tu.SlowNoSnapshots}, + {Backend: "slow-file", Pool: tu.SlowSnapshots}, + {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, + {Backend: "slow-block", Pool: tu.SlowSnapshots}, + {Backend: "slow-block", Pool: tu.MediumOverlap}, + }, + }, + } + for _, s := range storageClasses { + _, err := orchestrator.AddStorageClass(ctx(), s.config) + if err != nil { + t.Errorf("Unable to add storage class %s: %v", s.config.Name, err) + continue + } + validateStorageClass(t, orchestrator, s.config.Name, s.expected) + } + + for _, s := range []struct { + name string + config *storage.VolumeConfig + expectedSuccess bool + expectedMatches []*tu.PoolMatch + }{ + { + name: "file", + config: tu.GenerateVolumeConfig("file", 1, "fast", config.File), + expectedSuccess: true, + expectedMatches: []*tu.PoolMatch{ + {Backend: "fast-a", Pool: tu.FastSmall}, + {Backend: "fast-a", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastThinOnly}, + {Backend: "fast-b", Pool: tu.FastUniqueAttr}, + }, + }, + { + name: "block", + config: tu.GenerateVolumeConfig("block", 1, "specific", config.Block), + expectedSuccess: true, + expectedMatches: []*tu.PoolMatch{ + {Backend: "slow-block", Pool: tu.SlowNoSnapshots}, + {Backend: "slow-block", Pool: tu.MediumOverlap}, + }, + }, + } { + // Create the source volume + _, err := orchestrator.AddVolume(ctx(), s.config) + if err != nil { + t.Errorf("%s: got unexpected error %v", s.name, err) + continue + } + + // Now clone the volume and ensure everything looks fine + cloneName := s.config.Name + "_clone" + cloneConfig := &storage.VolumeConfig{ + Name: cloneName, + StorageClass: s.config.StorageClass, + CloneSourceVolume: s.config.Name, + VolumeMode: s.config.VolumeMode, } - t.Errorf("%s: Storage class failed to match storage pools %s", name, strings.Join(remainingNames, ", ")) - } - persistentSC, err := o.storeClient.GetStorageClass(ctx(), name) - if err != nil { - t.Fatalf("Unable to get storage class %s from backend: %v", name, err) - } - if !reflect.DeepEqual( - persistentSC, - sc.ConstructPersistent(), - ) { - gotSCJSON, err := json.Marshal(persistentSC) + cloneResult, err := orchestrator.CloneVolume(ctx(), cloneConfig) if err != nil { - t.Fatalf("Unable to marshal persisted storage class %s: %v", name, err) + t.Errorf("%s: got unexpected error %v", s.name, err) + continue } - expectedSCJSON, err := json.Marshal(sc.ConstructPersistent()) + + orchestrator.mutex.Lock() + + volume, found := orchestrator.volumes[s.config.Name] + if !found { + t.Errorf("%s: did not get volume where expected.", s.name) + } + clone, found := orchestrator.volumes[cloneName] + if !found { + t.Errorf("%s: did not get volume clone where expected.", cloneName) + } + + // Clone must reside in the same place as the source + if clone.BackendUUID != volume.BackendUUID { + t.Errorf("%s: Clone placed on unexpected backend: %s", cloneName, clone.BackendUUID) + } + + // Clone should be registered in the store just like any other volume + externalClone, err := orchestrator.storeClient.GetVolume(ctx(), cloneName) if err != nil { - t.Fatalf("Unable to marshal expected persistent storage class %s: %v", name, err) + t.Errorf("%s: unable to communicate with backing store: %v", cloneName, err) + } + if !reflect.DeepEqual(externalClone, cloneResult) { + t.Errorf("%s: external volume %s stored in backend does not match created volume.", cloneName, + externalClone.Config.Name) + externalCloneJSON, err := json.Marshal(externalClone) + if err != nil { + t.Fatal("Unable to remarshal JSON: ", err) + } + origCloneJSON, err := json.Marshal(cloneResult) + if err != nil { + t.Fatal("Unable to remarshal JSON: ", err) + } + t.Logf("\tExpected: %s\n\tGot: %s\n", string(externalCloneJSON), string(origCloneJSON)) } - t.Errorf("%s: Storage class persisted incorrectly.\n\tExpected %s\n\tGot %s", name, expectedSCJSON, gotSCJSON) - } -} -// This test is fairly heavyweight, but, due to the need to accumulate state -// to run the later tests, it's easier to do this all in one go at the moment. -// Consider breaking this up if it gets unwieldy, though. + orchestrator.mutex.Unlock() + } -// This test is modeled after TestAddStorageClassVolumes, but we don't need all the -// tests around storage class deletion, etc. + cleanup(t, orchestrator) +} -// addBackend adds a backend to the orchestrator. +// addBackend adds a backend with the specified name and protocol. // Parameters: -// t: the test object -// orchestrator: the orchestrator to add the backend to -// backendName: the name of the backend to add -// backendProtocol: the protocol of the backend to add +// t *testing.T: the test object +// orchestrator *TridentOrchestrator: the orchestrator object +// backendName string: the name of the backend to add +// backendProtocol config.Protocol: the protocol of the backend to add +// Returns: +// None // Example: -// addBackend(t, orchestrator, "fake", config.File) -// addBackend(t, orchestrator, "fake", config.Block) - +// addBackend(t, orchestrator, "mockBackend", config.File) +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func addBackend( t *testing.T, orchestrator *TridentOrchestrator, backendName string, backendProtocol config.Protocol, ) { @@ -489,17 +1244,20 @@ func addBackendStorageClass( } } -// captureOutput captures the output of the log package. -// It returns the captured output as a string. +func captureOutput(f func()) string { +// captureOutput captures the output of the provided function and returns it as a string +// It returns an empty string if the function doesn't log anything // Parameters: -// f: function to execute -// It returns the captured output as a string. +// f - function to capture output of +// Returns: +// string - captured output // Example: -// output := captureOutput(func() { -// log.Println("Hello, world") -// }) -// fmt.Println(output) - +// output := captureOutput(func() { +// log.Printf("foo") +// }) +// log.Printf("Output: %s", output) +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func captureOutput(f func()) string { var buf bytes.Buffer log.SetOutput(&buf) @@ -508,44 +1266,12 @@ func captureOutput(f func()) string { return buf.String() } -// TestBackendUpdateAndDelete tests the update and delete functionality of the -// orchestrator. -// It checks that the orchestrator can update a backend with a non-conflicting -// change, and that the backend is correctly updated in the orchestrator and -// persistent store. -// It also checks that the orchestrator can offline a backend, and that the -// backend is correctly offlined in the orchestrator and persistent store. -// Parameters: -// - New pool: Add a new storage pool to the backend. -// - Removed pool: Remove a storage pool from the backend. -// - Expanded offer: Expand the offer of an existing storage pool. -// Example: -// - New pool: -// - Starting state: -// - Backend: -// - Storage pools: "primary" -// - Updated state: -// - Backend: -// - Storage pools: "primary", "secondary" -// - Removed pool: -// - Starting state: -// - Backend: -// - Storage pools: "primary", "secondary" -// - Updated state: -// - Backend: -// - Storage pools: "primary" -// - Expanded offer: -// - Starting state: -// - Backend: -// - Storage pools: "primary" -// - Storage pool "primary": -// - Offer: "hdd" -// - Updated state: -// - Backend: -// - Storage pools: "primary" -// - Storage pool "primary": -// - Offer: "hdd", "ssd" - +// TestBackendUpdateAndDelete tests the ability to update and delete backends. +// It checks that the orchestrator correctly updates storage classes and +// volumes when a backend is updated. It also checks that the orchestrator +// correctly offlines a backend when it is deleted. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestBackendUpdateAndDelete(t *testing.T) { const ( backendName = "updateBackend" @@ -858,15 +1584,16 @@ func TestBackendUpdateAndDelete(t *testing.T) { } // backendPasswordsInLogsHelper is a helper function for backendPasswordsInLogs -// and backendPasswordsInLogsWithDebugTraceFlags tests. +// and backendPasswordsInLogsWithDebugTraceFlags. // Parameters: -// t: test object -// debugTraceFlags: map of debug trace flags +// t: the test object +// debugTraceFlags: a map of debug trace flags to enable +// Returns: +// nothing // Example: -// backendPasswordsInLogsHelper(t, map[string]bool{ -// "orchestrator": true, -// }) - +// backendPasswordsInLogsHelper(t, map[string]bool{"backend": true}) +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func backendPasswordsInLogsHelper(t *testing.T, debugTraceFlags map[string]bool) { backendName := "passwordBackend" @@ -915,29 +1642,20 @@ func backendPasswordsInLogsHelper(t *testing.T, debugTraceFlags map[string]bool) } // TestBackendPasswordsInLogs tests that backend passwords are not logged -// when the "method" field is present in the config. -// It checks that backend passwords are logged when the "method" field is not present. -// Parameters: -// t: testing.T -// config: map[string]bool -// "method": true if the "method" field is present in the config -// Example: -// backendPasswordsInLogsHelper(t, map[string]bool{"method": true}) - +// when the method is not specified. +// It checks that backend passwords are logged when the method is specified. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestBackendPasswordsInLogs(t *testing.T) { backendPasswordsInLogsHelper(t, nil) backendPasswordsInLogsHelper(t, map[string]bool{"method": true}) } // TestEmptyBackendDeletion tests that an empty backend can be deleted. -// It checks that the backend is removed from the orchestrator and the -// store client. -// Parameters: -// backendName: The name of the backend to be deleted. -// backendProtocol: The protocol of the backend to be deleted. -// Example: -// TestEmptyBackendDeletion(t, "emptyBackend", config.File) - +// It checks that the backend is removed from the orchestrator's memory, +// and that the backend is removed from the store client. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestEmptyBackendDeletion(t *testing.T) { const ( backendName = "emptyBackend" @@ -973,17 +1691,11 @@ func TestEmptyBackendDeletion(t *testing.T) { cleanup(t, orchestrator) } -// TestBootstrapSnapshotMissingVolume tests that a snapshot in missing_volume state is bootstrapped correctly. -// It checks that the snapshot is in the correct state and that it can be deleted. -// Parameters: -// offlineBackendName: Name of the backend to use for the test -// scName: Name of the storage class to use for the test -// volumeName: Name of the volume to use for the test -// snapName: Name of the snapshot to use for the test -// backendProtocol: Protocol of the backend to use for the test -// Example: -// TestBootstrapSnapshotMissingVolume(t, "snapNoVolBackend", "snapNoVolSC", "snapNoVolVolume", "snapNoVolSnapshot", config.File) - +// TestBootstrapSnapshotMissingVolume tests that a snapshot in the missing_volume state is bootstrapped +// correctly and can be deleted. +// It checks that the snapshot is in the missing_volume state and that it can be deleted. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestBootstrapSnapshotMissingVolume(t *testing.T) { const ( offlineBackendName = "snapNoVolBackend" @@ -1042,16 +1754,11 @@ func TestBootstrapSnapshotMissingVolume(t *testing.T) { } } -// TestBootstrapSnapshotMissingBackend tests that a snapshot in missing_backend state is bootstrapped correctly. -// It checks that the snapshot is bootstrapped and that it is in the correct state. -// Parameters: -// offlineBackendName - name of the backend that will be deleted -// scName - name of the storage class -// volumeName - name of the volume -// snapName - name of the snapshot -// Example: -// TestBootstrapSnapshotMissingBackend(t, "snapNoBackBackend", "snapNoBackSC", "snapNoBackVolume", "snapNoBackSnapshot") - +// TestBootstrapSnapshotMissingBackend tests that a snapshot in the missing_backend state is +// bootstrapped correctly. +// It checks that the snapshot is bootstrapped with the correct state and that it can be deleted. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestBootstrapSnapshotMissingBackend(t *testing.T) { const ( offlineBackendName = "snapNoBackBackend" @@ -1110,15 +1817,11 @@ func TestBootstrapSnapshotMissingBackend(t *testing.T) { } } -// TestBootstrapVolumeMissingBackend tests that a volume in missing_backend state is bootstrapped correctly -// It checks that the volume is in the correct state and can be deleted -// Parameters: -// offlineBackendName - name of the backend to be deleted -// scName - name of the storage class to be created -// volumeName - name of the volume to be created -// Example: -// TestBootstrapVolumeMissingBackend("bootstrapVolBackend", "bootstrapVolSC", "bootstrapVolVolume") - +// TestBootstrapVolumeMissingBackend tests that a volume in the missing_backend state can be +// bootstrapped and deleted. +// It checks that the volume is in the missing_backend state and that it can be deleted. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestBootstrapVolumeMissingBackend(t *testing.T) { const ( offlineBackendName = "bootstrapVolBackend" @@ -1171,17 +1874,10 @@ func TestBootstrapVolumeMissingBackend(t *testing.T) { } } -// TestBackendCleanup tests that empty offline backends are cleaned up during bootstrap. -// It checks that empty online backends are not cleaned up during bootstrap. -// Parameters: -// offlineBackendName: Name of the backend to be offlined. -// onlineBackendName: Name of the backend to be left online. -// scName: Name of the storage class to be used. -// volumeName: Name of the volume to be created. -// backendProtocol: Protocol of the backends to be created. -// Example: -// TestBackendCleanup(t, "cleanupBackend", "onlineBackend", "cleanupBackendTest", "cleanupVolume", config.File) - +// TestBackendCleanup tests that offline backends are cleaned up during bootstrap. +// It checks that online backends are not cleaned up during bootstrap. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestBackendCleanup(t *testing.T) { const ( offlineBackendName = "cleanupBackend" @@ -1232,13 +1928,11 @@ func TestBackendCleanup(t *testing.T) { } } -// TestLoadBackend tests that a backend can be loaded from a config and that it matches the original. -// It checks that the backend is also loaded after bootstrapping. -// Parameters: -// t *testing.T -// Example: -// TestLoadBackend(t) - +// TestLoadBackend tests that a backend can be loaded from a config file. +// It checks that the backend is loaded correctly and that it can be loaded +// after a restart. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestLoadBackend(t *testing.T) { const ( backendName = "load-backend-test" @@ -1291,15 +1985,19 @@ func TestLoadBackend(t *testing.T) { cleanup(t, orchestrator) } -// prepRecoveryTest sets up a backend and storage class for testing recovery +// prepRecoveryTest prepares a backend and storage class for testing +// recovery test functionality. // Parameters: -// t: test object -// orchestrator: orchestrator object -// backendName: name of backend to create -// scName: name of storage class to create +// t: Test object +// orchestrator: Trident orchestrator +// backendName: Name of the backend to create +// scName: Name of the storage class to create +// Returns: +// None // Example: -// prepRecoveryTest(t, orchestrator, "ontap-nas-test", "ontap-nas-sc") - +// prepRecoveryTest(t, orchestrator, "backend", "sc") +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func prepRecoveryTest( t *testing.T, orchestrator *TridentOrchestrator, backendName, scName string, ) { @@ -1337,29 +2035,37 @@ func prepRecoveryTest( } } -// runRecoveryTests runs a set of tests to verify that the orchestrator -// recovers from a partially completed volume addition. +// runRecoveryTests runs a set of recovery tests. +// +// Each test is a volume transaction that's been partially completed. +// The test is run by creating a new orchestrator, which should +// recover from the transaction and then clean up after itself. // Parameters: -// t: Test object -// orchestrator: The orchestrator to test -// backendName: The name of the backend to use -// op: The operation to test -// testCases: The set of test cases to run +// t: the test object +// orchestrator: the orchestrator to use for the test +// backendName: the name of the backend to use for the test +// op: the operation to perform +// testCases: a list of recoveryTest objects, each of which contains +// a VolumeConfig and a name for the test. +// Returns: +// nothing // Example: -// runRecoveryTests(t, orchestrator, "fake", storage.AddVolume, -// []recoveryTest{ -// { -// "volumeConfig", -// &storage.VolumeConfig{ -// Name: "test", -// Size: "10GiB", -// Attributes: map[string]sa.Request{}, +// runRecoveryTests(t, orchestrator, "be-1", storage.AddVolume, []recoveryTest{ +// { +// name: "Test 1", +// volumeConfig: &storage.VolumeConfig{ +// Name: "vol-1", +// Size: "1GiB", +// Attributes: map[string]sa.Request{ +// "fakeattrib": sa.NewStringRequest("fakeval"), // }, -// true, +// Internal: true, +// AccessMode: tridentconfig.ReadWriteOnce, // }, -// ... -// }) - +// }, +// }) +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func runRecoveryTests( t *testing.T, orchestrator *TridentOrchestrator, @@ -1417,17 +2123,10 @@ func runRecoveryTests( } // TestAddVolumeRecovery tests that adding a volume is properly recovered -// after a crash. -// It checks that the volume is properly destroyed if the transaction was -// not committed, and that the volume is properly created if the transaction -// was committed. -// Parameters: -// - full: the volume was created and the transaction was committed -// - txOnly: the volume was not created and the transaction was not committed -// Example: -// - TestAddVolumeRecovery(full) -// - TestAddVolumeRecovery(txOnly) - +// from a transaction failure. +// It checks that the volume is properly created and destroyed. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestAddVolumeRecovery(t *testing.T) { const ( backendName = "addRecoveryBackend" @@ -1456,16 +2155,11 @@ func TestAddVolumeRecovery(t *testing.T) { cleanup(t, orchestrator) } -// TestAddVolumeWithTMRNonONTAPNAS tests that a volume with a relationship -// annotation that is not ONTAP NAS is rejected -// It checks that the volume is rejected -// Parameters: -// backendName: name of the backend -// scName: name of the storage class -// fullVolumeName: name of the full volume -// Example: -// TestAddVolumeWithTMRNonONTAPNAS("be1", "sc1", "vol1") - +// TestAddVolumeWithTMRNonONTAPNAS tests that a volume with a TMR relationship +// to a non-ONTAP NAS backend fails to be added +// It checks that the error message is as expected +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestAddVolumeWithTMRNonONTAPNAS(t *testing.T) { // Add a single backend of fake // create volume with relationship annotation added @@ -1492,16 +2186,10 @@ func TestAddVolumeWithTMRNonONTAPNAS(t *testing.T) { cleanup(t, orchestrator) } -// TestDeleteVolumeRecovery tests the recovery of a volume delete operation. -// It checks that a volume that was deleted but not fully committed is -// recovered, and that a volume that was only created in the transaction -// is cleaned up. -// Parameters: -// backendName: The name of the backend to use for the test. -// scName: The name of the storage class to use for the test. -// Example: -// TestDeleteVolumeRecovery(t, "ontap-san", "ontap-san-sc") - +// TestDeleteVolumeRecovery tests the recovery of a volume delete. +// It checks that the volume is removed from the orchestrator, but not destroyed. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestDeleteVolumeRecovery(t *testing.T) { const ( backendName = "deleteRecoveryBackend" @@ -1537,17 +2225,17 @@ func TestDeleteVolumeRecovery(t *testing.T) { cleanup(t, orchestrator) } -// generateSnapshotConfig generates a SnapshotConfig object +// generateSnapshotConfig returns a SnapshotConfig object with the specified name and volume // Parameters: // name - the name of the snapshot -// volumeName - the name of the volume -// volumeInternalName - the internal name of the volume +// volumeName - the name of the volume to snapshot +// volumeInternalName - the internal name of the volume to snapshot // Returns: -// a SnapshotConfig object -// It returns an error if the volume name is not set +// SnapshotConfig object // Example: -// config := generateSnapshotConfig("snap1", "vol1", "pvc-xxx-xx-xx") - +// snapshotConfig := generateSnapshotConfig("snapshot-name", "volume-name", "volume-internal-name") +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func generateSnapshotConfig( name, volumeName, volumeInternalName string, ) *storage.SnapshotConfig { @@ -1559,43 +2247,28 @@ func generateSnapshotConfig( } } -// runSnapshotRecoveryTests runs a set of recovery tests. +// runSnapshotRecoveryTests runs a set of tests to verify that the orchestrator +// is able to recover from a partially completed snapshot addition. // Parameters: -// t: the test object -// orchestrator: the orchestrator to use for the tests -// backendName: the name of the backend to use for the tests -// op: the operation to test -// testCases: the set of test cases to run +// t: The test object +// orchestrator: The orchestrator object to use for the tests +// backendName: The name of the backend to use for the tests +// op: The operation to test (AddSnapshot or DeleteSnapshot) +// testCases: A slice of recoveryTest objects describing the tests to run +// Returns: +// None // Example: -// runSnapshotRecoveryTests( -// t, -// orchestrator, -// "ontap-nas", -// storage.AddSnapshot, -// []recoveryTest{ -// { -// name: "VolumePresent", -// volumeConfig: &storage.VolumeConfig{ -// Version: tridentconfig.OrchestratorAPIVersion, -// Name: "myvol", -// BackendUUID: "ontap-nas-0", -// Backend: "ontap-nas", -// Size: "1GiB", -// InternalName: "myvol", -// Attributes: map[string]sa.Request{}, -// }, -// snapshotConfig: &storage.SnapshotConfig{ -// Version: tridentconfig.OrchestratorAPIVersion, -// Name: "mysnap", -// VolumeName: "myvol", -// VolumeInternalName: "myvol", -// Attributes: map[string]sa.Request{}, -// }, -// expectDestroy: true, -// }, -// }, -// ) - +// runSnapshotRecoveryTests(t, orchestrator, "fake", storage.DeleteSnapshot, +// []recoveryTest{ +// { +// name: "SnapshotDeleted", +// volumeConfig: &storage.VolumeConfig{}, +// snapshotConfig: &storage.SnapshotConfig{}, +// expectDestroy: true, +// }, +// }) +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func runSnapshotRecoveryTests( t *testing.T, orchestrator *TridentOrchestrator, @@ -1656,19 +2329,11 @@ func runSnapshotRecoveryTests( } } -// TestAddSnapshotRecovery tests that the orchestrator can recover from a failure -// during the AddSnapshot transaction. -// It checks that the snapshot is deleted if the transaction is complete, and that -// it is not deleted if the transaction is not complete. -// Parameters: -// backendName: Name of the backend to use for the test -// scName: Name of the storage class to use for the test -// volumeName: Name of the volume to use for the test -// fullSnapshotName: Name of the snapshot to use for the full test -// txOnlySnapshotName: Name of the snapshot to use for the partial test -// Example: -// TestAddSnapshotRecovery(t, "addSnapshotRecoveryBackend", "addSnapshotRecoveryBackendSC", "addSnapshotRecoveryVolume", "addSnapshotRecoverySnapshotFull", "addSnapshotRecoverySnapshotTxOnly") - +// TestAddSnapshotRecovery tests the recovery of AddSnapshot transactions. +// It checks that the snapshot is deleted if the transaction was fully committed, +// and that the snapshot is not deleted if the transaction was only partially committed. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestAddSnapshotRecovery(t *testing.T) { const ( backendName = "addSnapshotRecoveryBackend" @@ -1708,17 +2373,12 @@ func TestAddSnapshotRecovery(t *testing.T) { cleanup(t, orchestrator) } -// TestDeleteSnapshotRecovery tests that the orchestrator can recover from a delete snapshot -// transaction. -// It checks that the snapshot is deleted if the transaction was fully committed, and that -// the snapshot is not deleted if the transaction was only partially committed. -// Parameters: -// - full: the transaction was fully committed, so the snapshot should be deleted -// - txOnly: the transaction was only partially committed, so the snapshot should not be deleted -// Example: -// - TestDeleteSnapshotRecovery full -// - TestDeleteSnapshotRecovery txOnly - +// TestDeleteSnapshotRecovery tests that snapshot delete transactions are properly +// recovered. +// It checks that the snapshot is not deleted if the snapshot exists, and that the +// snapshot is deleted if the snapshot does not exist. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestDeleteSnapshotRecovery(t *testing.T) { const ( backendName = "deleteSnapshotRecoveryBackend" @@ -1766,13 +2426,11 @@ func TestDeleteSnapshotRecovery(t *testing.T) { // The next series of tests test that bootstrap doesn't exit early if it // encounters a key error for one of the main types of entries. // TestStorageClassOnlyBootstrap tests that a storage class can be bootstrapped -// without any volumes. -// It checks that the storage class is bootstrapped correctly. -// Parameters: -// t *testing.T -// Example: -// TestStorageClassOnlyBootstrap(t) - +// without any other objects. +// It checks that the storage class is bootstrapped and that it matches the +// original storage class. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestStorageClassOnlyBootstrap(t *testing.T) { const scName = "storageclass-only" @@ -1800,16 +2458,10 @@ func TestStorageClassOnlyBootstrap(t *testing.T) { cleanup(t, orchestrator) } -// TestFirstVolumeRecovery tests that the first volume added to a backend is -// recovered correctly. -// It checks that the volume is destroyed, and that the backend is not. -// Parameters: -// backendName: name of the backend to be used -// scName: name of the storage class to be used -// txOnlyVolumeName: name of the volume to be created -// Example: -// TestFirstVolumeRecovery(t, "firstRecoveryBackend", "firstRecoveryBackendSC", "firstRecoveryVolumeTxOnly") - +// TestFirstVolumeRecovery tests that the first volume in a backend is recovered correctly +// It checks that the volume is destroyed and recreated +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestFirstVolumeRecovery(t *testing.T) { const ( backendName = "firstRecoveryBackend" @@ -1831,14 +2483,11 @@ func TestFirstVolumeRecovery(t *testing.T) { cleanup(t, orchestrator) } -// TestOrchestratorNotReady tests that the orchestrator returns an error when not ready. -// It checks that all orchestrator methods return an error. -// Parameters: -// t *testing.T : go test helper -// It returns nothing. -// Example: -// TestOrchestratorNotReady(t *testing.T) - +// TestOrchestratorNotReady tests the behavior of the orchestrator when it is not ready. +// It checks that all the orchestrator methods return an error. +// It returns an error if any of the methods do not return an error. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestOrchestratorNotReady(t *testing.T) { var ( @@ -1978,22 +2627,22 @@ func TestOrchestratorNotReady(t *testing.T) { } } -// importVolumeSetup creates a backend, storage class, and volume config for +// importVolumeSetup is a helper function for tests that need to +// It returns an orchestrator and a volume config // Parameters: -// t - test object -// backendName - name of the backend to create -// scName - name of the storage class to create -// volumeName - name of the volume to create -// importOriginalName - original name of the volume to import -// backendProtocol - protocol of the backend to create +// t - the test object +// backendName - the name of the backend to create +// scName - the name of the storage class to create +// volumeName - the name of the volume to create +// importOriginalName - the original name of the volume to import +// backendProtocol - the protocol of the backend to create // Returns: -// *TridentOrchestrator - orchestrator object -// *storage.VolumeConfig - volume config object -// It returns the orchestrator and volume config objects. +// *TridentOrchestrator - the orchestrator object +// *storage.VolumeConfig - the volume config object // Example: -// orchestrator, volumeConfig := importVolumeSetup(t, "testBackend", "testSC", -// "testVolume", "testVolumeOrig", config.File) - +// orchestrator, volumeConfig := importVolumeSetup(t, "backend1", "sc1", "vol1", "originalVolName", config.File) +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func importVolumeSetup( t *testing.T, backendName string, scName string, volumeName string, importOriginalName string, backendProtocol config.Protocol, @@ -2027,18 +2676,14 @@ func importVolumeSetup( return orchestrator, volumeConfig } -// TestImportVolumeFailures tests the failure paths of importVolume -// It checks that the volume is renamed to the original name and that the persisted state is cleaned up -// Parameters: -// volumeName: the name of the volume to import -// originalName: the original name of the volume -// backendProtocol: the protocol of the backend -// createPVandPVCError: function to inject an error into the PV/PVC creation -// It returns the orchestrator and the volumeConfig -// Example: -// orchestrator, volumeConfig := importVolumeSetup(t, "backend82", "sc01", "volume82", "origVolume01", config.File) -// _, err := orchestrator.LegacyImportVolume(ctx(), volumeConfig, "backend82", false, createPVandPVCError) - +// TestImportVolumeFailures tests that importVolumeCleanup is called when +// importVolumeSetup fails +// It checks that the volume is renamed to the original name and that the +// persisted state is cleaned up +// It returns an error if the volume is not renamed or if the persisted state +// is not cleaned up +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestImportVolumeFailures(t *testing.T) { const ( backendName = "backend82" @@ -2079,18 +2724,11 @@ func TestImportVolumeFailures(t *testing.T) { } // TestLegacyImportVolume tests the legacy -// It checks that the volume is imported with the correct internal name. -// It checks that the volume is persisted if it is managed. -// It checks that the volume is not persisted if it is not managed. -// Parameters: -// volumeConfig: the volume config to use for the import -// notManaged: true if the volume is not managed -// createFunc: the function to use to create the PV and PVC -// expectedInternalName: the expected internal name of the volume -// It returns the volumeExternal returned by the import. -// Example: -// TestLegacyImportVolume(t, volumeConfig, false, createPVandPVCNoOp, volumeConfig.InternalName) - +// It checks that the volume is imported with the expected name and that it is persisted +// if it is managed. +// It returns the volumeExternal and the volumeConfig. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestLegacyImportVolume(t *testing.T) { const ( backendName = "backend02" @@ -2168,18 +2806,10 @@ func TestLegacyImportVolume(t *testing.T) { cleanup(t, orchestrator) } -// TestImportVolume tests the -// It checks that the volume is imported with the correct internal name -// and that the volume is persisted in the orchestrator. -// Parameters: -// backendName: name of the backend -// scName: name of the storage class -// volumeName: name of the volume to be imported -// originalName: original name of the volume to be imported -// backendProtocol: protocol of the backend -// Example: -// TestImportVolume(t, "backend02", "sc01", "volume01", "origVolume01", config.File) - +// TestImportVolume tests the ImportVolume method +// It checks that the volume is persisted and that the internal name is correct +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestImportVolume(t *testing.T) { const ( backendName = "backend02" @@ -2239,26 +2869,14 @@ func TestImportVolume(t *testing.T) { // TestValidateImportVolumeNasBackend tests the validateImportVolume function for NAS backends. // It checks for the following error conditions: -// - The volume exists on the backend with the original name +// - The volume already exists // - The storage class is unknown // - The volume does not exist on the backend -// - The access mode is incompatible with the backend -// - The volume mode is incompatible with the backend -// - The protocol is incompatible with the backend -// Parameters: -// backendName - the name of the backend -// scName - the name of the storage class -// volumeName - the name of the volume to import -// originalName - the original name of the volume to import -// backendProtocol - the protocol of the backend -// Example: -// backendName := "backend01" -// scName := "sc01" -// volumeName := "volume01" -// originalName := "origVolume01" -// backendProtocol := config.File -// TestValidateImportVolumeNasBackend(t, backendName, scName, volumeName, originalName, backendProtocol) - +// - The volume is not compatible with the access mode +// - The volume is not compatible with the volume mode +// - The volume is not compatible with the protocol +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestValidateImportVolumeNasBackend(t *testing.T) { const ( backendName = "backend01" @@ -2337,20 +2955,12 @@ func TestValidateImportVolumeNasBackend(t *testing.T) { cleanup(t, orchestrator) } -// TestValidateImportVolumeSanBackend tests the validateImportVolume function for -// SAN backends. +// TestValidateImportVolumeSanBackend tests the validateImportVolume function for SAN backends. // It checks for the following error conditions: -// - protocol mismatch -// - file system mismatch -// Parameters: -// - backendName: name of the backend to use -// - scName: name of the storage class to use -// - volumeName: name of the volume to create -// - originalName: name of the volume to import -// - backendProtocol: protocol of the backend to use -// Example: -// TestValidateImportVolumeSanBackend("backend01", "sc01", "volume01", "origVolume01", config.Block) - +// - Protocol is not compatible with the backend +// - FileSystem is not compatible with the backend +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestValidateImportVolumeSanBackend(t *testing.T) { const ( backendName = "backend01" @@ -2412,16 +3022,11 @@ func TestValidateImportVolumeSanBackend(t *testing.T) { cleanup(t, orchestrator) } -// TestAddVolumePublication tests that the orchestrator correctly adds a volume publication -// to its cache and calls the store client to add the volume publication to the persistent store -// It checks that the orchestrator's cache is updated correctly -// Parameters: -// t *testing.T - test object -// Example: -// TestAddVolumePublication(t) -// Returns: -// None - +// TestAddVolumePublication tests adding a volume publication to the orchestrator +// It checks that the orchestrator calls the store client with the correct object, +// and that the orchestrator's cache is updated correctly +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestAddVolumePublication(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2454,16 +3059,12 @@ func TestAddVolumePublication(t *testing.T) { "volume publication was not correctly added") } -// TestAddVolumePublicationError tests the error path for AddVolumePublication -// It checks that the orchestrator does not add the volume publication to its cache -// when the store client returns an error -// Parameters: -// t *testing.T -// The test object -// It returns nothing -// Example: -// TestAddVolumePublicationError(t) - +// TestAddVolumePublicationError tests that the orchestrator returns an error when the store client returns an error +// when adding a volume publication +// It checks that the orchestrator's cache is not updated +// It returns an error +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestAddVolumePublicationError(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2493,12 +3094,9 @@ func TestAddVolumePublicationError(t *testing.T) { } // TestGetVolumePublication tests the GetVolumePublication method -// It checks that the volume publication is correctly retrieved from the cache -// Parameters: -// t *testing.T: go test helper -// Example: -// TestGetVolumePublication(t *testing.T) - +// It checks that the correct volume publication is returned +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestGetVolumePublication(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2527,11 +3125,8 @@ func TestGetVolumePublication(t *testing.T) { // TestGetVolumePublicationNotFound tests that a volume publication is not found // when the volume is not found // It checks that the correct error is returned -// Parameters: -// t *testing.T -// Example: -// TestGetVolumePublicationNotFound(t) - +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestGetVolumePublicationNotFound(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2549,14 +3144,10 @@ func TestGetVolumePublicationNotFound(t *testing.T) { assert.Empty(t, actualPub, "non-empty publication returned") } -// TestGetVolumePublicationError tests the GetVolumePublication function when -// there is an error during bootstrap +// TestGetVolumePublicationError tests the GetVolumePublication function when an error is returned // It checks that the correct error is returned -// Parameters: -// t *testing.T - go test helper object -// Example: -// TestGetVolumePublicationError(t *testing.T) - +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestGetVolumePublicationError(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2588,13 +3179,8 @@ func TestGetVolumePublicationError(t *testing.T) { // TestListVolumePublications tests the ListVolumePublications method // It checks that the correct list of publications is returned -// Parameters: -// t *testing.T : go test framework object used for setup, teardown, etc. -// Example: -// TestListVolumePublications(t) -// Returns: -// None - +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestListVolumePublications(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2638,13 +3224,11 @@ func TestListVolumePublications(t *testing.T) { assert.ElementsMatch(t, expectedPubs, actualPubs, "incorrect publication list returned") } -// TestListVolumePublicationsNotFound tests that ListVolumePublications returns an empty list when no publications are found -// It checks that the orchestrator does not return an error when no publications are found -// Parameters: -// t *testing.T : go test framework object used to generate test failures -// Example: -// TestListVolumePublicationsNotFound(t *testing.T) - +// TestListVolumePublicationsNotFound tests the case where there are no volume publications +// in the persistent store +// It checks that the returned list is empty and that there is no error +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestListVolumePublicationsNotFound(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2661,13 +3245,12 @@ func TestListVolumePublicationsNotFound(t *testing.T) { assert.Empty(t, actualPubs, "non-empty publication list returned") } -// TestListVolumePublicationsError tests the error path for ListVolumePublications -// It checks that the error is returned and the publication list is empty -// Parameters: -// t *testing.T - go test handler -// Example: -// TestListVolumePublicationsError(t) - +// TestListVolumePublicationsError tests that ListVolumePublications returns an error if the +// orchestrator is in an error state +// It checks that the orchestrator returns an error if it is in an error state +// It checks that the orchestrator returns an empty list of publications +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestListVolumePublicationsError(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2697,13 +3280,10 @@ func TestListVolumePublicationsError(t *testing.T) { assert.Empty(t, actualPubs, "non-empty publication list returned") } -// TestListVolumePublicationsForVolume tests the ListVolumePublicationsForVolume method -// It checks that the correct list of publications is returned for a given volume -// Parameters: -// t *testing.T - test object -// Example: -// TestListVolumePublicationsForVolume(t) - +// TestListVolumePublicationsForVolume tests the ListVolumePublicationsForVolume function +// It checks that the correct list of publications is returned +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestListVolumePublicationsForVolume(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2747,18 +3327,11 @@ func TestListVolumePublicationsForVolume(t *testing.T) { assert.ElementsMatch(t, expectedPubs, actualPubs, "incorrect publication list returned") } -// TestListVolumePublicationsForVolumeNotFound tests that ListVolumePublicationsForVolume -// returns an empty list when the volume is not found -// It checks that the orchestrator does not return an error -// Parameters: -// t *testing.T : go test helper -// Example: -// TestListVolumePublicationsForVolumeNotFound(t) -// Returns: -// nothing -// Side Effects: -// none - +// TestListVolumePublicationsForVolumeNotFound tests the ListVolumePublicationsForVolume method +// when the volume is not found +// It checks that an empty list is returned +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestListVolumePublicationsForVolumeNotFound(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2785,13 +3358,10 @@ func TestListVolumePublicationsForVolumeNotFound(t *testing.T) { assert.Empty(t, actualPubs, "non-empty publication list returned") } -// TestListVolumePublicationsForVolumeError tests the error path for ListVolumePublicationsForVolume -// It checks that the error is returned if the orchestrator is in an error state -// Parameters: -// t *testing.T : go test helper -// Example: -// TestListVolumePublicationsForVolumeError(t *testing.T) - +// TestListVolumePublicationsForVolumeError tests the error path of ListVolumePublicationsForVolume +// It checks that the orchestrator returns an error when it is in a bootstrap error state +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestListVolumePublicationsForVolumeError(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2822,12 +3392,9 @@ func TestListVolumePublicationsForVolumeError(t *testing.T) { } // TestListVolumePublicationsForNode tests the ListVolumePublicationsForNode method -// It checks that a list of publications for a given node is returned -// Parameters: -// t *testing.T - go test object -// Example: -// TestListVolumePublicationsForNode(t *testing.T) - +// It checks that the correct publications are returned for a given node +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestListVolumePublicationsForNode(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2871,14 +3438,11 @@ func TestListVolumePublicationsForNode(t *testing.T) { assert.ElementsMatch(t, expectedPubs, actualPubs, "incorrect publication list returned") } -// TestListVolumePublicationsForNodeNotFound tests the ListVolumePublicationsForNode function -// when the node is not found -// It checks that an empty list is returned -// Parameters: -// t *testing.T -// Example: -// TestListVolumePublicationsForNodeNotFound(t) - +// TestListVolumePublicationsForNodeNotFound tests that ListVolumePublicationsForNode returns an empty list when +// the node is not found. +// It checks that the orchestrator does not return an error when the node is not found. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestListVolumePublicationsForNodeNotFound(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2905,14 +3469,11 @@ func TestListVolumePublicationsForNodeNotFound(t *testing.T) { assert.Empty(t, actualPubs, "non-empty publication list returned") } -// TestListVolumePublicationsForNodeError tests that ListVolumePublicationsForNode -// returns an error when the orchestrator is in an error state -// It checks that the error is returned and that the publication list is empty -// Parameters: -// t *testing.T : go test helper object -// Example: -// TestListVolumePublicationsForNodeError(t) - +// TestListVolumePublicationsForNodeError tests the case where there is an error +// during bootstrap. +// It checks that the error is returned to the caller. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestListVolumePublicationsForNodeError(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -2945,11 +3506,8 @@ func TestListVolumePublicationsForNodeError(t *testing.T) { // TestDeleteVolumePublication tests the DeleteVolumePublication method // It checks that the volume publication is removed from the cache // and that the volume entry is removed from the cache if this is the last nodeID for a given volume -// Parameters: -// t *testing.T: go test helper -// Example: -// TestDeleteVolumePublication(t) - +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestDeleteVolumePublication(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3006,14 +3564,10 @@ func TestDeleteVolumePublication(t *testing.T) { "publication not properly removed from cache") } -// TestDeleteVolumePublicationNotFound tests that the DeleteVolumePublication method returns a not found error -// when the volume publication is not found -// It checks that the volume publication is not deleted from the cache -// Parameters: -// t *testing.T : go test helper -// Example: -// TestDeleteVolumePublicationNotFound(t *testing.T) - +// TestDeleteVolumePublicationNotFound tests that an error is returned when a volume publication is not found +// It checks that the correct error +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestDeleteVolumePublicationNotFound(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3040,14 +3594,13 @@ func TestDeleteVolumePublicationNotFound(t *testing.T) { assert.True(t, utils.IsNotFoundError(err), "incorrect error type returned") } -// TestDeleteVolumePublicationNotFoundPersistence tests that delete volume publication is idempotent -// when the persistence object is missing -// It checks that the cache is updated and that the orchestrator does not panic -// Parameters: -// t *testing.T : go test framework object -// Example: -// TestDeleteVolumePublicationNotFoundPersistence(t *testing.T) - +// TestDeleteVolumePublicationNotFoundPersistence tests that the orchestrator +// handles the case where a volume publication is not found in the persistence +// layer. +// It checks that the orchestrator does not return an error and that the +// publication is removed from the cache. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestDeleteVolumePublicationNotFoundPersistence(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3077,13 +3630,10 @@ func TestDeleteVolumePublicationNotFoundPersistence(t *testing.T) { "publication not properly removed from cache") } -// TestDeleteVolumePublicationError tests the error path of DeleteVolumePublication -// It checks that the orchestrator returns an error when the store client returns an error -// Parameters: -// t *testing.T : go test helper -// Example: -// TestDeleteVolumePublicationError(t) - +// TestDeleteVolumePublicationError tests the error path for deleting a volume publication +// It checks that the error is returned and that the cache is not updated +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestDeleteVolumePublicationError(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3115,13 +3665,9 @@ func TestDeleteVolumePublicationError(t *testing.T) { } // TestAddNode tests adding a node to the orchestrator -// It checks that the node is added to the orchestrator and that the orchestrator -// is able to retrieve the node -// Parameters: -// t *testing.T : go test helper object for running tests -// Example: -// TestAddNode(t *testing.T) - +// It checks that the node is added to the orchestrator +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestAddNode(t *testing.T) { node := &utils.Node{ Name: "testNode", @@ -3137,12 +3683,10 @@ func TestAddNode(t *testing.T) { } // TestGetNode tests the GetNode method -// It checks that the correct node is returned -// Parameters: -// t *testing.T -// Example: -// TestGetNode(t) - +// It checks that the expected node is returned +// It checks that an error is returned if the node does not exist +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestGetNode(t *testing.T) { orchestrator := getOrchestrator(t) expectedNode := &utils.Node{ @@ -3174,13 +3718,10 @@ func TestGetNode(t *testing.T) { } } -// TestListNodes tests the ListNodes function -// It checks that the list of nodes returned is the same as the list of nodes in the orchestrator -// Parameters: -// t *testing.T : go test framework object used for running the test -// Example: -// TestListNodes(t) - +// TestListNodes tests that the orchestrator can list nodes +// It checks that the orchestrator returns the correct nodes +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestListNodes(t *testing.T) { orchestrator := getOrchestrator(t) expectedNode1 := &utils.Node{ @@ -3211,18 +3752,19 @@ func TestListNodes(t *testing.T) { } } -// unorderedNodeSlicesEqual returns true if the two slices contain the same nodes, -// regardless of order. +// unorderedNodeSlicesEqual compares two slices of nodes for equality. +// The order of the nodes in the slices is not considered. +// It returns true if the slices contain the same nodes. // Parameters: -// x, y - the slices to compare +// x, y - the slices to compare // Returns: -// bool - true if the slices contain the same nodes, regardless of order +// bool - true if the slices contain the same nodes // Example: -// x := []*utils.Node{&utils.Node{Name: "node1"}, &utils.Node{Name: "node2"}} -// y := []*utils.Node{&utils.Node{Name: "node2"}, &utils.Node{Name: "node1"}} -// unorderedNodeSlicesEqual(x, y) -// >> true - +// x := []*utils.Node{n1, n2, n3} +// y := []*utils.Node{n3, n2, n1} +// unorderedNodeSlicesEqual(x, y) // returns true +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func unorderedNodeSlicesEqual(x, y []*utils.Node) bool { if len(x) != len(y) { return false @@ -3246,13 +3788,10 @@ func unorderedNodeSlicesEqual(x, y []*utils.Node) bool { return len(diff) == 0 } -// TestDeleteNode tests the deletion of a node -// It checks that the node is properly deleted from the orchestrator -// Parameters: -// t *testing.T : go testing object used to handle logging -// Example: -// TestDeleteNode(t *testing.T) - +// TestDeleteNode tests the DeleteNode method +// It checks that the node is properly deleted +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestDeleteNode(t *testing.T) { orchestrator := getOrchestrator(t) initialNode := &utils.Node{ @@ -3274,14 +3813,10 @@ func TestDeleteNode(t *testing.T) { } } -// TestSnapshotVolumes tests snapshotting of volumes -// It checks that the snapshot is created, and that it is stored in the persistent store -// It also checks that the snapshot can be deleted -// Parameters: -// t: the test object -// Example: -// TestSnapshotVolumes(t) - +// TestSnapshotVolumes tests snapshotting volumes. +// It checks that the snapshot is created and deleted correctly. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestSnapshotVolumes(t *testing.T) { mockPools := tu.GetFakePools() orchestrator := getOrchestrator(t) @@ -3488,18 +4023,9 @@ func TestSnapshotVolumes(t *testing.T) { } // TestGetProtocol tests the getProtocol function -// It checks for positive and negative cases -// Parameters: -// volumeMode: Filesystem or RawBlock -// accessMode: ReadWriteOnce, ReadOnlyMany, ReadWriteMany -// protocol: File, Block, BlockOnFile -// expected: File, Block, BlockOnFile -// Example: -// volumeMode: RawBlock -// accessMode: ReadWriteOnce -// protocol: File -// expected: ProtocolAny - +// It checks for all the valid and invalid combinations of volumeMode, accessMode and protocol +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestGetProtocol(t *testing.T) { orchestrator := getOrchestrator(t) @@ -3570,13 +4096,10 @@ func TestGetProtocol(t *testing.T) { } // TestGetBackend tests the GetBackend function -// It checks that the expected object is returned -// Parameters: -// t *testing.T: The test object -// It returns nothing -// Example: -// TestGetBackend(t) - +// It checks that the correct object is returned +// It returns an error if the backend does not exist +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestGetBackend(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -3611,15 +4134,11 @@ func TestGetBackend(t *testing.T) { assert.Equal(t, expectedBackendExternal, actualBackendExternal, "Did not get the expected backend object") } -// TestGetBackendByBackendUUID tests the GetBackendByBackendUUID method +// TestGetBackendByBackendUUID tests the GetBackendByBackendUUID function // It checks that the correct backend is returned -// Parameters: -// backendName: Name of the backend to return -// backendUUID: UUID of the backend to return -// It returns the expected backend object -// Example: -// backend:=TestGetBackendByBackendUUID("foobar","1234") - +// It returns an error if the backend does not exist +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestGetBackendByBackendUUID(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -3651,13 +4170,10 @@ func TestGetBackendByBackendUUID(t *testing.T) { } // TestListBackends tests the ListBackends function -// It checks that the function returns a list of backends that matches the list of backends that were added to the orchestrator -// Parameters: -// t *testing.T : go testing object used to control test flow -// It returns nothing -// Example: -// TestListBackends(t *testing.T) - +// It checks that the expected list of backends is returned +// It returns an error if the list of backends is not as expected +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestListBackends(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -3695,13 +4211,11 @@ func TestListBackends(t *testing.T) { } // TestDeleteBackend tests the DeleteBackend method -// It checks that the backend is properly deleted from the orchestrator -// Parameters: -// t *testing.T - test object -// It returns nothing -// Example: -// TestDeleteBackend(t *testing.T) - +// It checks that the backend is set to deleting, set offline, and terminated +// It also checks that the backend is removed from the orchestrator's backend map +// It returns an error if the backend is not found +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestDeleteBackend(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -3746,13 +4260,10 @@ func TestDeleteBackend(t *testing.T) { assert.False(t, ok, "Backend was not properly deleted") } -// TestPublishVolume tests the PublishVolume method -// It checks that the correct backend method is called -// Parameters: -// t *testing.T -// Example: -// TestPublishVolume(t) - +// TestPublishVolume tests the PublishVolume function +// It checks that the correct backend is called and that the volume is updated in the persistent store +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestPublishVolume(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -3785,17 +4296,12 @@ func TestPublishVolume(t *testing.T) { } // TestPublishVolumeFailedToUpdatePersistentStore tests the case where the -// orchestrator fails to update the persistent store after a successful -// publish operation. -// It checks that the orchestrator returns the error from the persistent -// store client. -// Parameters: -// mockCtrl - the mocked controller -// backendUUID - the UUID of the backend to use for the test -// expectedError - the error expected from the persistent store client -// Example: -// TestPublishVolumeFailedToUpdatePersistentStore(t, "1234", fmt.Errorf("failure")) - +// orchestrator fails to update the persistent store after a successful publish +// operation. +// It checks that the orchestrator returns the error from the persistent store +// client. +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestPublishVolumeFailedToUpdatePersistentStore(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -3832,14 +4338,10 @@ func TestPublishVolumeFailedToUpdatePersistentStore(t *testing.T) { } // TestGetCHAP tests the GetCHAP method of the orchestrator -// It checks that the orchestrator calls the correct backend method -// and returns the expected result -// Parameters: -// volumeName: the name of the volume to get CHAP info for -// nodeName: the name of the node to get CHAP info for -// Example: -// TestGetCHAP("foobar", "foobar") - +// It checks that the correct backend is called and that the +// returned chap info is correct +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestGetCHAP(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -3872,13 +4374,10 @@ func TestGetCHAP(t *testing.T) { assert.Equal(t, expectedChapInfo, actualChapInfo, "Unexpected chap info returned.") } -// TestGetCHAPFailure tests the failure path of GetCHAP -// It checks that the orchestrator returns an error when the backend returns an error -// Parameters: -// t *testing.T: go test helper -// Example: -// TestGetCHAPFailure(t *testing.T) - +// TestGetCHAPFailure tests the failure path of the GetCHAP function +// It checks that the correct error is returned +// +// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- func TestGetCHAPFailure(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) diff --git a/core/transaction_monitor_test.go b/core/transaction_monitor_test.go index f15452b47..1e03b29c6 100644 --- a/core/transaction_monitor_test.go +++ b/core/transaction_monitor_test.go @@ -24,14 +24,20 @@ const ( maxAge = 3 * time.Second ) +func init() { + testing.Init() + log.SetLevel(log.DebugLevel) +} // waitForTransactionMontitorToStart waits for the transaction monitor to start -// before proceeding with tests. // Parameters: -// o - the orchestrator +// o: the orchestrator +// Returns: +// none // Example: // waitForTransactionMontitorToStart(o) - +// +// -- Doc autogenerated on 2022-05-12 18:37:26.431118 -- func waitForTransactionMontitorToStart(o *TridentOrchestrator) { if o.txnMonitorChannel == nil { time.Sleep(1 * time.Second) @@ -40,12 +46,8 @@ func waitForTransactionMontitorToStart(o *TridentOrchestrator) { // TestStartStop tests the start and stop of the transaction monitor // It checks that the transaction monitor is started and stopped correctly -// It also checks that the transaction monitor channel is set correctly -// Parameters: -// t *testing.T : go test framework object used for running the test -// Example: -// TestStartStop(t) - +// +// -- Doc autogenerated on 2022-05-12 18:37:26.431118 -- func TestStartStop(t *testing.T) { storeClient := persistentstore.NewInMemoryClient() @@ -103,6 +105,7 @@ func TestLongRunningTransaction(t *testing.T) { // TestCancelledLongRunningTransaction tests that a transaction older than the max age is cancelled. func TestCancelledLongRunningTransaction(t *testing.T) { +func TestLongRunningTransaction(t *testing.T) { o, storeClient := setupOrchestratorAndBackend(t) restartTransactionMonitor(o) @@ -132,15 +135,13 @@ func TestCancelledLongRunningTransaction(t *testing.T) { } // TestUpdateTransactionVolumeCreatingTransaction tests that a VolumeCreatingTransaction can be updated. -// TestUpdateVolumeCreatingTransaction tests the ability to update a volume creating transaction -// in the store. -// It checks that the transaction is created, then updates the size and checks that the size -// was updated. -// Parameters: -// t *testing.T -// Example: -// TestUpdateVolumeCreatingTransaction(t) - +func TestUpdateVolumeCreatingTransaction(t *testing.T) { +// TestUpdateVolumeCreatingTransaction tests that we can update a volume creating transaction +// and that the updated transaction is persisted. +// It checks that the transaction is created, then updates the transaction and checks that the +// update is persisted. +// +// -- Doc autogenerated on 2022-05-12 18:37:26.431118 -- func TestUpdateVolumeCreatingTransaction(t *testing.T) { o, storeClient := setupOrchestratorAndBackend(t) restartTransactionMonitor(o) @@ -214,17 +215,13 @@ func TestErrorVolumeCreatingTransaction(t *testing.T) { } // TestVolumeCreatingTwoTransaction tests that two volumeCreatingTransactions work as expected -// TestVolumeCreatingTwoTransactions tests that two volume creating transactions can be created -// and that the second one is not deleted until the first one is completed. -// It checks that the second transaction is not deleted when the first one is completed. -// Parameters: -// volName - name of the volume to create -// cloneName - name of the volume to clone -// volName02 - name of the second volume to create -// cloneName02 - name of the second volume to clone -// Example: -// TestVolumeCreatingTwoTransactions(t, "volToClone_01", "volToClone_02") - +func TestVolumeCreatingTwoTransactions(t *testing.T) { +// TestVolumeCreatingTwoTransactions tests that the orchestrator can handle two volume creating transactions. +// This is a regression test for BUG-724 +// It checks that the orchestrator can handle two volume creating transactions. +// It also checks that the orchestrator can handle a volume creating transaction and a clone transaction. +// +// -- Doc autogenerated on 2022-05-12 18:37:26.431118 -- func TestVolumeCreatingTwoTransactions(t *testing.T) { o, storeClient := setupOrchestratorAndBackend(t) restartTransactionMonitor(o) @@ -289,20 +286,24 @@ func TestVolumeCreatingTwoTransactions(t *testing.T) { assert.Equal(t, volName02, volTxns[0].VolumeCreatingConfig.InternalName, "failed to find matching transaction") } -// setupOrchestratorAndBackend sets up an orchestrator and a backend -// for use in tests. +// setupOrchestratorAndBackend creates a new orchestrator and backend +// and returns them. +// It returns the orchestrator and the backend. +// It also returns the backend name and the storage class name. // Parameters: // t: the test object +// backendName: the name of the backend to create +// storageClassName: the name of the storage class to create +// provisioningType: the provisioning // Returns: // o: the orchestrator // storeClient: the persistent store client -// It returns an error if the setup fails. +// backendName: the name of the backend +// storageClassName: the name of the storage class // Example: -// o, storeClient, err := setupOrchestratorAndBackend(t) -// if err != nil { -// t.Errorf("Unable to setup orchestrator and backend: %v", err) -// } - +// o, _, _, _ := setupOrchestratorAndBackend(t, "fakeOne", "slow", "thin") +// +// -- Doc autogenerated on 2022-05-12 18:37:26.431118 -- func setupOrchestratorAndBackend(t *testing.T) (*TridentOrchestrator, *persistentstore.InMemoryClient) { storeClient := persistentstore.NewInMemoryClient() o := NewTridentOrchestrator(storeClient) @@ -343,14 +344,17 @@ func setupOrchestratorAndBackend(t *testing.T) (*TridentOrchestrator, *persisten return o, storeClient } -// restartTransactionMonitor stops and restarts the transaction monitor. +// restartTransactionMonitor is a helper function to restart the transaction monitor +// with testable limits. // Parameters: -// o - the orchestrator -// period - the period between transaction monitor runs -// maxAge - the maximum age of a transaction before it is considered abandoned +// o - TridentOrchestrator instance +// Returns: +// None // Example: -// restartTransactionMonitor(o, 1*time.Second, 30*time.Minute) - +// o := NewTridentOrchestrator(...) +// restartTransactionMonitor(o) +// +// -- Doc autogenerated on 2022-05-12 18:37:26.431118 -- func restartTransactionMonitor(o *TridentOrchestrator) { // Bootstrap starts the transaction monitor. diff --git a/operator/controllers/orchestrator/apis/netapp/v1/register.go b/operator/controllers/orchestrator/apis/netapp/v1/register.go index 4e53446e9..d3e708ca1 100644 --- a/operator/controllers/orchestrator/apis/netapp/v1/register.go +++ b/operator/controllers/orchestrator/apis/netapp/v1/register.go @@ -21,6 +21,7 @@ func Kind(kind string) schema.GroupKind { // Resource takes an unqualified resource and returns back a Group qualified GroupResource func Resource(resource string) schema.GroupResource { +func Kind(kind string) schema.GroupKind { return SchemeGroupVersion.WithResource(resource).GroupResource() } @@ -30,17 +31,19 @@ var ( ) // Adds the list of known types to the given scheme. +func addKnownTypes(scheme *runtime.Scheme) error { // addKnownTypes adds the set of types defined in this +// It returns the SchemeBuilder // Parameters: -// scheme - the scheme to add the types to -// version - the version of the API -// addTo - the map of group and version to add the types to -// It returns the scheme with the types added. +// scheme: the SchemeBuilder instance +// addToScheme: the function to add the types to the scheme +// Returns: +// the SchemeBuilder instance // Example: -// scheme := runtime.NewScheme() -// addKnownTypes(scheme) -// addToGroupVersion(scheme, SchemeGroupVersion) - +// s := runtime.NewScheme() +// addKnownTypes(s) +// +// -- Doc autogenerated on 2022-05-12 18:41:46.879131 -- func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &TridentOrchestrator{}, diff --git a/operator/controllers/orchestrator/apis/netapp/v1/types.go b/operator/controllers/orchestrator/apis/netapp/v1/types.go index f00267318..0999e78ce 100644 --- a/operator/controllers/orchestrator/apis/netapp/v1/types.go +++ b/operator/controllers/orchestrator/apis/netapp/v1/types.go @@ -67,17 +67,15 @@ type Toleration struct { TolerationSeconds int `json:"tolerationSeconds,omitempty"` } -// GetMap returns a map of the toleration +// GetMap returns a map of toleration +// Returns: +// map[string]string // Example: -// toleration := &Toleration{ -// Key: "key", -// Operator: "Equal", -// Value: "value", -// Effect: "NoSchedule", -// TolerationSeconds: 10, -// } -// tolerationMap := toleration.GetMap() - +// toleration := v1.Toleration{"key": "app", "operator": "Equal", "value": "abc"} +// toleration.GetMap() +// => map[string]string{"key": "app", "operator": "Equal", "value": "abc"} +// +// -- Doc autogenerated on 2022-05-12 18:42:04.843308 -- func (t *Toleration) GetMap() map[string]string { toleration := map[string]string{} diff --git a/operator/controllers/orchestrator/client/clientset/versioned/fake/clientset_generated.go b/operator/controllers/orchestrator/client/clientset/versioned/fake/clientset_generated.go index f6ea4e298..1d7ec805b 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/fake/clientset_generated.go +++ b/operator/controllers/orchestrator/client/clientset/versioned/fake/clientset_generated.go @@ -52,30 +52,30 @@ type Clientset struct { tracker testing.ObjectTracker } +func (c *Clientset) Discovery() discovery.DiscoveryInterface { // Discovery retrieves the DiscoveryClient -// It returns a fake if the fake flag is set +// It returns a fake implementation of the DiscoveryClient +// Returns: +// *discovery.DiscoveryClient // Example: -// clientset := fake.Clientset{} -// clientset.fakeDiscovery = true -// discoveryClient := clientset.Discovery() - +// discoveryClient := fake.Clientset{}.Discovery() +// +// -- Doc autogenerated on 2022-05-12 18:42:24.343390 -- func (c *Clientset) Discovery() discovery.DiscoveryInterface { return c.discovery } -// Tracker is a fake implementation of the ObjectTracker interface. -type Tracker struct { - objects map[string]interface{} -} - -// NewTracker returns a new Tracker. -// It returns an error if the tracker could not be created. +// Tracker is a fake implementation of a Tracker. +// It returns fake objects. +// Returns: +// * fake.Clientset +// * fake.Tracker // Example: -// tracker, err := fake.NewTracker() -// if err != nil { -// panic(err) -// } - +// clientset, tracker := testing.NewClientsetTracker() +// k8sclient := clientset.Kubernetes() +// tracker.AddObj(k8sclient.Core().Services("ns1").Get("svc1", metav1.GetOptions{})) +// +// -- Doc autogenerated on 2022-05-12 18:42:24.343390 -- func (c *Clientset) Tracker() testing.ObjectTracker { return c.tracker } diff --git a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go b/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go index b01ad8751..8e7c07378 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go +++ b/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go @@ -15,10 +15,12 @@ type FakeTridentV1 struct { } // TridentOrchestrators returns a TridentOrchestratorInterface. +// Returns: +// * FakeTridentOrchestrators // Example: -// c := fake.NewSimpleClientset() -// c.TridentV1().TridentOrchestrators() - +// * tridentOrchestrators := fake.TridentOrchestrators() +// +// -- Doc autogenerated on 2022-05-12 18:43:38.177255 -- func (c *FakeTridentV1) TridentOrchestrators() v1.TridentOrchestratorInterface { return &FakeTridentOrchestrators{c} } diff --git a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/netapp_client.go b/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/netapp_client.go index 069403804..a52de5ac1 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/netapp_client.go +++ b/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/netapp_client.go @@ -21,11 +21,12 @@ type TridentV1Client struct { } // TridentOrchestrators returns a TridentOrchestratorInterface. +// Returns: +// * TridentOrchestratorInterface // Example: -// myClient := v1.NewTridentV1Client(c) -// ctx := context.TODO() -// myClient.TridentOrchestrators().Version(ctx) - +// trident, err := client.TridentV1().TridentOrchestrators() +// +// -- Doc autogenerated on 2022-05-12 18:43:04.890052 -- func (c *TridentV1Client) TridentOrchestrators() TridentOrchestratorInterface { return newTridentOrchestrators(c) } @@ -46,6 +47,7 @@ func NewForConfig(c *rest.Config) (*TridentV1Client, error) { // NewForConfigOrDie creates a new TridentV1Client for the given config and // panics if there is an error in the config. func NewForConfigOrDie(c *rest.Config) *TridentV1Client { +func NewForConfig(c *rest.Config) (*TridentV1Client, error) { client, err := NewForConfig(c) if err != nil { panic(err) @@ -55,19 +57,25 @@ func NewForConfigOrDie(c *rest.Config) *TridentV1Client { // New creates a new TridentV1Client for the given RESTClient. func New(c rest.Interface) *TridentV1Client { +func NewForConfigOrDie(c *rest.Config) *TridentV1Client { return &TridentV1Client{c} } -// setConfigDefaults sets the default values for the provided config. +func setConfigDefaults(config *rest.Config) error { +// setConfigDefaults sets default values for rest.Config +// It returns an error if the supplied config is invalid. // Parameters: -// config - the config to set the default values for -// Return: -// error - nil if successful, error if not -// It returns an error if the config is nil. +// config - the rest.Config object to set defaults for +// Returns: +// error - an error if the supplied config is invalid // Example: // config := &rest.Config{} // err := setConfigDefaults(config) - +// if err != nil { +// return err +// } +// +// -- Doc autogenerated on 2022-05-12 18:43:04.890052 -- func setConfigDefaults(config *rest.Config) error { gv := v1.SchemeGroupVersion config.GroupVersion = &gv diff --git a/operator/controllers/orchestrator/client/informers/externalversions/factory.go b/operator/controllers/orchestrator/client/informers/externalversions/factory.go index 7ec775063..c6f5ac746 100644 --- a/operator/controllers/orchestrator/client/informers/externalversions/factory.go +++ b/operator/controllers/orchestrator/client/informers/externalversions/factory.go @@ -47,6 +47,7 @@ func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInfo // WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { return func(factory *sharedInformerFactory) *sharedInformerFactory { factory.tweakListOptions = tweakListOptions return factory @@ -55,6 +56,7 @@ func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFu // WithNamespace limits the SharedInformerFactory to the specified namespace. func WithNamespace(namespace string) SharedInformerOption { +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { return func(factory *sharedInformerFactory) *sharedInformerFactory { factory.namespace = namespace return factory @@ -63,6 +65,7 @@ func WithNamespace(namespace string) SharedInformerOption { // NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { +func WithNamespace(namespace string) SharedInformerOption { return NewSharedInformerFactoryWithOptions(client, defaultResync) } @@ -71,11 +74,13 @@ func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Dur // as specified here. // Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { +func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) } // NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { +func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { factory := &sharedInformerFactory{ client: client, namespace: v1.NamespaceAll, @@ -95,6 +100,7 @@ func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResy // Start initializes all requested informers. func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { f.lock.Lock() defer f.lock.Unlock() @@ -108,6 +114,7 @@ func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { // WaitForCacheSync waits for all started informers' cache were synced. func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { +func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { informers := func() map[reflect.Type]cache.SharedIndexInformer { f.lock.Lock() defer f.lock.Unlock() @@ -130,24 +137,30 @@ func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[ref // InternalInformerFor returns the SharedIndexInformer for obj using an internal // client. -// InformerFor is a function that returns a SharedIndexInformer for a given object and namespace. -type InformerFor func(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer - -// SharedInformerFactory is type of SharedInformerFactory interface. -type SharedInformerFactory interface { - Start(stopCh <-chan struct{}) - InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer -} - -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. +func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { +// InformerFor returns the SharedIndexInformer for obj using an external client. // Parameters: -// - client - kubernetes client -// - defaultResync - default resync period for informers created by this factory -// It returns a new instance of SharedInformerFactory. +// obj - the object +// Returns: +// SharedIndexInformer // Example: -// kubeClient := kubernetes.NewForConfigOrDie(c) -// kubeInformerFactory := externalversions.NewSharedInformerFactory(kubeClient, 30*time.Second) - +// lister := f.InformerFor(&v1.Pod{}, func(client clientset.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { +// return cache.NewSharedIndexInformer( +// &cache.ListWatch{ +// ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { +// return client.CoreV1().Pods(api.NamespaceAll).List(options) +// }, +// WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { +// return client.CoreV1().Pods(api.NamespaceAll).Watch(options) +// }, +// }, +// &v1.Pod{}, +// resyncPeriod, +// cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, +// ) +// } +// +// -- Doc autogenerated on 2022-05-12 18:43:51.155916 -- func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { f.lock.Lock() defer f.lock.Unlock() @@ -179,17 +192,14 @@ type SharedInformerFactory interface { Trident() netapp.Interface } -// Trident is the external version of the API. -type Trident struct { - groupVersion string -} - -// NewTrident returns a new Trident. -// It returns nil if the version is not known. +// Trident returns a new Interface. +// Returns: +// - a new Interface +// - error if there is an error initializing the client // Example: -// trident := externalversions.NewTrident("trident.netapp.io", "v1alpha1") -// clientset, err := trident.ClientsetForVersion("v1alpha1") - +// - tridentClient, err := Trident(config) +// +// -- Doc autogenerated on 2022-05-12 18:43:51.155916 -- func (f *sharedInformerFactory) Trident() netapp.Interface { return netapp.New(f, f.namespace, f.tweakListOptions) } diff --git a/operator/controllers/orchestrator/client/informers/externalversions/netapp/v1/tridentorchestrator.go b/operator/controllers/orchestrator/client/informers/externalversions/netapp/v1/tridentorchestrator.go index fdf533667..804ede7ef 100644 --- a/operator/controllers/orchestrator/client/informers/externalversions/netapp/v1/tridentorchestrator.go +++ b/operator/controllers/orchestrator/client/informers/externalversions/netapp/v1/tridentorchestrator.go @@ -41,6 +41,7 @@ func NewTridentOrchestratorInformer(client versioned.Interface, resyncPeriod tim // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. func NewFilteredTridentOrchestratorInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { +func NewTridentOrchestratorInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { return cache.NewSharedIndexInformer( &cache.ListWatch{ ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { @@ -62,76 +63,46 @@ func NewFilteredTridentOrchestratorInformer(client versioned.Interface, resyncPe ) } -// defaultInformer is used to informer for TridentOrchestrator types. -type tridentOrchestratorInformer struct { - factory internalinterfaces.SharedInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc -} - -// NewTridentOrchestratorInformer constructs a new informer for TridentOrchestrator type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. +func (f *tridentOrchestratorInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { +// defaultInformer is used to informer for TridentOrchestrator resources. +// It returns a SharedIndexInformer which can be used to list and get TridentOrchestrator resources. // Parameters: -// resyncPeriod - the period at which the informer should re-list the resources. -// tweakListOptions - the function to tweak the list options. -// It returns a shared informer for TridentOrchestrator type. +// client - the kubernetes client +// resyncPeriod - the resync period +// indexers - the indexers for the TridentOrchestrator resources +// Returns: +// A SharedIndexInformer // Example: -// // Get a shared informer for the resource. -// informer := NewTridentOrchestratorInformer( -// resyncPeriod, -// tweakListOptions, -// ) -// // Register the resource with the shared informer. -// informer.AddEventHandler( -// cache.ResourceEventHandlerFuncs{ -// AddFunc: func(obj interface{}) {}, -// UpdateFunc: func(oldObj, newObj interface{}) {}, -// DeleteFunc: func(obj interface{}) {}, -// }, -// ) - +// lw := cache.NewListWatchFromClient(client, "tridentOrchestrator", v1.NamespaceAll, fields.Everything()) +// i := tridentOrchestrator.NewTridentOrchestratorInformer(lw, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) +// +// -- Doc autogenerated on 2022-05-12 18:44:26.289244 -- func (f *tridentOrchestratorInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { return NewFilteredTridentOrchestratorInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) } -// Informer is used to obtain a shared index informer for TridentOrchestrator objects. -type tridentOrchestratorInformer struct { - factory internalinterfaces.SharedInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc - namespace string - tenant string -} - -// NewTridentOrchestratorInformer constructs a new informer for TridentOrchestrator type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -// It returns a SharedIndexInformer. +// Informer for TridentOrchestrator objects. +// It returns a cache.SharedIndexInformer for the TridentOrchestrator type. +// Returns: +// * cache.SharedIndexInformer // Example: -// tridentOrchestratorInformer := v1.NewTridentOrchestratorInformer(client, namespace, resyncPeriod, indexers) - +// tridentOrchestratorInformer := informers.NewTridentOrchestratorInformer(...) +// ... +// tridentOrchestrator := tridentOrchestratorInformer.Lister().ByIndex(...) +// +// -- Doc autogenerated on 2022-05-12 18:44:26.289244 -- func (f *tridentOrchestratorInformer) Informer() cache.SharedIndexInformer { return f.factory.InformerFor(&netappv1.TridentOrchestrator{}, f.defaultInformer) } // Lister implements the TridentOrchestratorLister interface. -type tridentOrchestratorInformer struct { - factory internalinterfaces.SharedInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc - namespace string -} - -// NewTridentOrchestratorInformer constructs a new informer for TridentOrchestrator type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -// It returns a TridentOrchestratorInformer. +// It returns TridentOrchestratorLister. +// Returns: +// * TridentOrchestratorLister // Example: -// // Create a new controller -// ctrl := NewController(... -// // Create a new informer -// informer := ctrl.Informer() -// // Create a new lister -// lister := ctrl.Lister() - +// lister := listers.NewTridentOrchestratorLister() +// +// -- Doc autogenerated on 2022-05-12 18:44:26.289244 -- func (f *tridentOrchestratorInformer) Lister() v1.TridentOrchestratorLister { return v1.NewTridentOrchestratorLister(f.Informer().GetIndexer()) } diff --git a/operator/controllers/orchestrator/controller.go b/operator/controllers/orchestrator/controller.go index 104d0c1d6..fc7e74a94 100644 --- a/operator/controllers/orchestrator/controller.go +++ b/operator/controllers/orchestrator/controller.go @@ -108,20 +108,19 @@ type Controller struct { } // NewController creates a new TridentOrchestrator controller +// It returns a pointer to the controller and an error if one occurred // Parameters: -// clients - Trident clients -// stopChan - channel to signal controller shutdown -// workqueue - work queue for the controller -// It returns a pointer to the controller +// clients - a pointer to the clients struct +// Returns: +// *Controller - a pointer to the controller +// error - an error if one occurred // Example: -// c, err := NewController(clients, stopChan, workqueue) +// c, err := NewController(clients) // if err != nil { // log.Fatal(err) // } -// if err = c.Run(2, stopChan); err != nil { -// log.Fatal(err) -// } - +// +// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- func NewController(clients *clients.Clients) (*Controller, error) { log.WithField("Controller", ControllerName).Info("Initializing controller.") @@ -231,16 +230,15 @@ func NewController(clients *clients.Clients) (*Controller, error) { } // Activate starts the controller -// It returns an error if the controller is already active +// It returns an error if the controller fails to start. +// Returns: +// error: error starting the controller // Example: -// controller, err := NewController(client, kubeClient, "namespace", "trident", config) -// if err != nil { -// return err +// if err := c.Activate(); err != nil { +// log.Fatalf("Failed to start controller: %v", err) // } -// if err := controller.Activate(); err != nil { -// return err -// } - +// +// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- func (c *Controller) Activate() error { log.WithField("Controller", ControllerName).Infof("Activating controller.") @@ -264,13 +262,15 @@ func (c *Controller) Activate() error { // Deactivate stops the controller // It returns an error if the controller could not be stopped +// Returns: +// error: an error if the controller could not be stopped // Example: -// c := NewController(...) // err := c.Deactivate() // if err != nil { // return err // } - +// +// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- func (c *Controller) Deactivate() error { log.WithField("Controller", ControllerName).Infof("Deactivating controller.") @@ -282,17 +282,23 @@ func (c *Controller) Deactivate() error { } // GetName returns the name of the controller +// Returns: +// string: name of the controller // Example: -// name := c.GetName() - +// name := c.GetName() +// +// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- func (c *Controller) GetName() string { return ControllerName } // Version returns the current version of the orchestrator +// Returns: +// string: the current version of the orchestrator // Example: -// v := Version() - +// version := orchestrator.Version() +// +// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- func (c *Controller) Version() string { return ControllerVersion } @@ -308,6 +314,7 @@ func (c *Controller) runWorker() { // processNextWorkItem will read a single work item off the workqueue and // attempt to process it, by calling the syncHandler. func (c *Controller) processNextWorkItem() bool { +func (c *Controller) runWorker() { obj, shutdown := c.workqueue.Get() if shutdown { @@ -385,6 +392,7 @@ func (c *Controller) processNextWorkItem() bool { // addOrchestrator is the add handler for the TridentOrchestrator watcher. func (c *Controller) addOrchestrator(obj interface{}) { +func (c *Controller) processNextWorkItem() bool { var key string var err error @@ -415,6 +423,7 @@ func (c *Controller) addOrchestrator(obj interface{}) { // updateOrchestrator is the update handler for the TridentOrchestrator watcher. func (c *Controller) updateOrchestrator(oldObj, newObj interface{}) { +func (c *Controller) addOrchestrator(obj interface{}) { _, ok := oldObj.(*netappv1.TridentOrchestrator) if !ok { @@ -459,6 +468,7 @@ func (c *Controller) updateOrchestrator(oldObj, newObj interface{}) { // deleteOrchestrator is the delete handler for the TridentOrchestrator watcher. func (c *Controller) deleteOrchestrator(obj interface{}) { +func (c *Controller) updateOrchestrator(oldObj, newObj interface{}) { var key string var err error @@ -489,6 +499,7 @@ func (c *Controller) deleteOrchestrator(obj interface{}) { // deploymentAddedOrDeleted is a handler for the trident-csi deployment watcher. func (c *Controller) deploymentAddedOrDeleted(obj interface{}) { +func (c *Controller) deleteOrchestrator(obj interface{}) { var key string var err error @@ -519,6 +530,7 @@ func (c *Controller) deploymentAddedOrDeleted(obj interface{}) { // deploymentUpdated is the handler for the trident-csi deployment watcher. func (c *Controller) deploymentUpdated(oldObj interface{}, newObj interface{}) { +func (c *Controller) deploymentAddedOrDeleted(obj interface{}) { var key string var err error @@ -574,6 +586,7 @@ func (c *Controller) deploymentUpdated(oldObj interface{}, newObj interface{}) { // daemonsetAddedOrDeleted is the handler for the trident-csi daemonset watcher. func (c *Controller) daemonsetAddedOrDeleted(obj interface{}) { +func (c *Controller) deploymentUpdated(oldObj interface{}, newObj interface{}) { var key string var err error @@ -604,6 +617,7 @@ func (c *Controller) daemonsetAddedOrDeleted(obj interface{}) { // daemonsetUpdated is the handler for the trident-csi daemonset watcher. func (c *Controller) daemonsetUpdated(_ interface{}, newObj interface{}) { +func (c *Controller) daemonsetAddedOrDeleted(obj interface{}) { var key string var err error @@ -641,6 +655,7 @@ func (c *Controller) daemonsetUpdated(_ interface{}, newObj interface{}) { // 2. However, if legacy, CSI Preview or tridentctl based Trident are installed after installing the // operator, these will be removed eventually. func (c *Controller) unsupportedInstallationsPrechecks(controllingCRBasedOnStatusExists, +func (c *Controller) daemonsetUpdated(_ interface{}, newObj interface{}) { operatorCSIDeploymentFound bool) error { // CSI Preview Trident should not be present @@ -698,6 +713,7 @@ func (c *Controller) unsupportedInstallationsPrechecks(controllingCRBasedOnStatu // alphaSnapshotCRDsExist identifies if the alpha snapshot CRDs not present func (c *Controller) alphaSnapshotCRDsExist() (bool, []string, error) { +func (c *Controller) unsupportedInstallationsPrechecks(controllingCRBasedOnStatusExists, var alphaSnapshotCRDsExist bool var alphaSnapshotCRDsList []string @@ -734,6 +750,7 @@ func (c *Controller) alphaSnapshotCRDsExist() (bool, []string, error) { // alphaSnapshotCRDsPreinstallationCheck identifies if the alpha snapshot CRDs are present before any Trident // installation by the operator func (c *Controller) alphaSnapshotCRDsPreinstallationCheck() error { +func (c *Controller) alphaSnapshotCRDsExist() (bool, []string, error) { alphaSnapshotCRDsExist, alphaSnapshotCRDsList, err := c.alphaSnapshotCRDsExist() if err != nil { @@ -759,6 +776,7 @@ func (c *Controller) alphaSnapshotCRDsPreinstallationCheck() error { // installation by the operator, this should only be called once controllingCR has been identified and before // installing, patching, updating the Trident func (c *Controller) alphaSnapshotCRDsPostinstallationCheck(tridentCR *netappv1.TridentOrchestrator, +func (c *Controller) alphaSnapshotCRDsPreinstallationCheck() error { currentInstalledTridentVersion string) error { alphaSnapshotCRDsExist, alphaSnapshotCRDsList, err := c.alphaSnapshotCRDsExist() @@ -791,6 +809,7 @@ func (c *Controller) alphaSnapshotCRDsPostinstallationCheck(tridentCR *netappv1. // k8sVersionPreinstallationCheck identifies if K8s version is valid or not func (c *Controller) k8sVersionPreinstallationCheck() error { +func (c *Controller) alphaSnapshotCRDsPostinstallationCheck(tridentCR *netappv1.TridentOrchestrator, isCurrentK8sVersionValid, warningMessage := c.validateCurrentK8sVersion() @@ -809,6 +828,7 @@ func (c *Controller) k8sVersionPreinstallationCheck() error { // handleMigrationScenario identifies if there is a valid Tprov CR with `Installed` status and // if true then operator copies its config to a new Torc CR. func (c *Controller) handleMigrationScenario() error { +func (c *Controller) k8sVersionPreinstallationCheck() error { log.Debug("Verify migration from TridentProvisioner to TridentOrchestrator required.") @@ -899,6 +919,7 @@ func (c *Controller) handleMigrationScenario() error { // reconcile runs the reconcile logic and ensures we move to the desired state and the desired state is // maintained func (c *Controller) reconcile(key KeyItem) error { +func (c *Controller) handleMigrationScenario() error { // Check if there already exists a controllingCR - if deployment is deleted it is possible that we may run // into a situation where there is no deployment but there is a controlling CR @@ -966,15 +987,20 @@ func (c *Controller) reconcile(key KeyItem) error { } } -// reconcileTridentNotPresent reconciles the state when Trident is not present -// in the cluster. -// It returns an error if the reconciliation failed. +func (c *Controller) reconcileTridentNotPresent() error { +// reconcileTridentNotPresent reconciles the state of the cluster when Trident is not installed. +// +// This method will identify a valid TridentOrchestrator CR and install Trident using that CR. +// It returns an error if it fails to install Trident. +// Returns: +// error: any error encountered // Example: -// err := c.reconcileTridentNotPresent() -// if err != nil { -// return err -// } - +// err := c.reconcileTridentNotPresent() +// if err != nil { +// return err +// } +// +// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- func (c *Controller) reconcileTridentNotPresent() error { log.Info("Reconciler found no operator-based Trident installation.") @@ -1059,22 +1085,24 @@ func (c *Controller) reconcileTridentNotPresent() error { return err } -// reconcileTridentPresent reconciles the state of the operator when Trident is present +// reconcileTridentPresent reconciles the Trident installation when Trident is present +// +// This function is called when Trident is present, i.e. Trident deployment(s) exist. +// This function identifies the controlling CR for the Trident installation and then +// performs reconcile based on the controlling CR. +// It returns an error if the reconcile fails. // Parameters: -// key: KeyItem containing the namespace and name of the calling CR -// operatorCSIDeployments: List of all operator based Trident CSI deployments -// deploymentNamespace: Namespace where Trident is deployed -// isCSI: True if Trident is deployed as CSI, false if Trident is deployed as in-tree -// controllingCRBasedOnStatus: Controlling CR based on status field of the calling CR -// Return: -// error: Any error encountered -// It returns an error if it encounters an error condition. +// key: the key of the calling CR +// operatorCSIDeployments: the list of Trident CSI deployments +// deploymentNamespace: the namespace of the calling CR +// isCSI: whether the calling CR is CSI based +// controllingCRBasedOnStatus: the controlling CR based on status +// Returns: +// error: error if reconcile fails // Example: // err := c.reconcileTridentPresent(key, operatorCSIDeployments, deploymentNamespace, isCSI, controllingCRBasedOnStatus) -// if err != nil { -// return err -// } - +// +// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- func (c *Controller) reconcileTridentPresent(key KeyItem, operatorCSIDeployments []appsv1.Deployment, deploymentNamespace string, isCSI bool, controllingCRBasedOnStatus *netappv1.TridentOrchestrator) error { @@ -1351,6 +1379,7 @@ func (c *Controller) controllingCRBasedReconcile(controllingCR *netappv1.Trident // installTridentAndUpdateStatus installs Trident and updates status of the ControllingCR accordingly // based on success or failure func (c *Controller) installTridentAndUpdateStatus(tridentCR netappv1.TridentOrchestrator, +func (c *Controller) controllingCRBasedReconcile(controllingCR *netappv1.TridentOrchestrator, currentInstalledTridentVersion, warningMessage string, shouldUpdate bool) error { var identifiedTridentVersion string @@ -1402,6 +1431,7 @@ func (c *Controller) installTridentAndUpdateStatus(tridentCR netappv1.TridentOrc // uninstallTridentAndUpdateStatus uninstalls Trident and updates status of the ControllingCR accordingly // based on success or failure func (c *Controller) uninstallTridentAndUpdateStatus(tridentCR netappv1.TridentOrchestrator, +func (c *Controller) installTridentAndUpdateStatus(tridentCR netappv1.TridentOrchestrator, currentInstalledTridentVersion string) (*netappv1. TridentOrchestrator, error) { @@ -1452,6 +1482,7 @@ func (c *Controller) uninstallTridentAndUpdateStatus(tridentCR netappv1.TridentO // uninstallTridentAll uninstalls Trident CSI, Trident CSI Preview, Trident Legacy func (c *Controller) uninstallTridentAll(namespace string) error { +func (c *Controller) uninstallTridentAndUpdateStatus(tridentCR netappv1.TridentOrchestrator, i, err := installer.NewInstaller(c.KubeConfig, namespace, 0) if err != nil { return err @@ -1468,6 +1499,7 @@ func (c *Controller) uninstallTridentAll(namespace string) error { // wipeout removes Trident object specifies in the wipeout list func (c *Controller) wipeout(tridentCR netappv1.TridentOrchestrator) (bool, error) { +func (c *Controller) uninstallTridentAll(namespace string) error { var deletedCRDs bool if len(tridentCR.Spec.Wipeout) > 0 { @@ -1498,6 +1530,7 @@ func (c *Controller) wipeout(tridentCR netappv1.TridentOrchestrator) (bool, erro // obliviateCRDs calls obliviate functionality, equivalent to: // $ tridentctl obliviate crds func (c *Controller) obliviateCRDs(tridentCR netappv1.TridentOrchestrator) error { +func (c *Controller) wipeout(tridentCR netappv1.TridentOrchestrator) (bool, error) { // Obliviate CRDs Trident i, err := installer.NewInstaller(c.KubeConfig, tridentCR.Status.Namespace, tridentCR.Spec.K8sTimeout) if err != nil { @@ -1517,6 +1550,7 @@ func (c *Controller) obliviateCRDs(tridentCR netappv1.TridentOrchestrator) error ************************************************/ // ensureTridentOrchestratorCRDExist ensures TridentOrchestrator CRD exist func (c *Controller) ensureTridentOrchestratorCRDExist() error { +func (c *Controller) obliviateCRDs(tridentCR netappv1.TridentOrchestrator) error { i, err := installer.NewInstaller(c.KubeConfig, metav1.NamespaceDefault, 0) if err != nil { @@ -1528,6 +1562,7 @@ func (c *Controller) ensureTridentOrchestratorCRDExist() error { // createTridentOrchestratorCR creates a new TridentOrchestrator CR func (c *Controller) createTridentOrchestratorCR(tridentCR *netappv1.TridentOrchestrator) error { +func (c *Controller) ensureTridentOrchestratorCRDExist() error { _, err := c.CRDClient.TridentV1().TridentOrchestrators().Create(ctx(), tridentCR, createOpts) if err != nil { return err @@ -1537,6 +1572,7 @@ func (c *Controller) createTridentOrchestratorCR(tridentCR *netappv1.TridentOrch // getTridentOrchestratorCRsAll gets all the TridentOrchestrator CRs across all namespaces func (c *Controller) getTridentOrchestratorCRsAll() ([]netappv1.TridentOrchestrator, error) { +func (c *Controller) createTridentOrchestratorCR(tridentCR *netappv1.TridentOrchestrator) error { list, err := c.CRDClient.TridentV1().TridentOrchestrators().List(ctx(), listOpts) if err != nil { return nil, err @@ -1547,6 +1583,7 @@ func (c *Controller) getTridentOrchestratorCRsAll() ([]netappv1.TridentOrchestra // identifyControllingCRBasedOnStatus identified the controllingCR purely on status and independent of any deployment // logic involved func (c *Controller) identifyControllingCRBasedOnStatus() (bool, *netappv1.TridentOrchestrator, error) { +func (c *Controller) getTridentOrchestratorCRsAll() ([]netappv1.TridentOrchestrator, error) { // Get all TridentOrchestrator CRs tridentCRs, err := c.getTridentOrchestratorCRsAll() @@ -1572,6 +1609,7 @@ func (c *Controller) identifyControllingCRBasedOnStatus() (bool, *netappv1.Tride // identifyControllingCRForTridentDeployments identifies controllingCR for deployment and reports nil if length of the // operatorCSIDeployments is more than 1 func (c *Controller) identifyControllingCRForTridentDeployments(operatorCSIDeployments []appsv1.Deployment) (*netappv1. +func (c *Controller) identifyControllingCRBasedOnStatus() (bool, *netappv1.TridentOrchestrator, error) { TridentOrchestrator, error) { @@ -1616,6 +1654,7 @@ func (c *Controller) identifyControllingCRForTridentDeployments(operatorCSIDeplo // updateAllCRs get called only when no ControllingCR exist to report a configuration error func (c *Controller) updateAllCRs(message string) error { +func (c *Controller) identifyControllingCRForTridentDeployments(operatorCSIDeployments []appsv1.Deployment) (*netappv1. allCRs, err := c.getTridentOrchestratorCRsAll() if err != nil { @@ -1636,6 +1675,7 @@ func (c *Controller) updateAllCRs(message string) error { // updateOtherCRs get called only when a ControllingCR exist to set error state on the non-ControllingCRs func (c *Controller) updateOtherCRs(controllingCRName string) error { +func (c *Controller) updateAllCRs(message string) error { allCRs, err := c.getTridentOrchestratorCRsAll() if err != nil { @@ -1660,11 +1700,23 @@ func (c *Controller) updateOtherCRs(controllingCRName string) error { } // updateLogAndStatus updates the event logs and status of a TridentOrchestrator CR (if required) +func (c *Controller) updateTorcEventAndStatus( // updateTorcEventAndStatus updates the status of the TridentOrchestrator CR and logs an event +// Parameters: +// tridentCR - the TridentOrchestrator CR +// debugMessage - the message to be logged as debug +// message - the message to be logged as info +// status - the status to be updated in the CR +// version - the version of the CR +// namespace - the namespace of the CR +// eventType - the +// Returns: +// torcCR - the updated TridentOrchestrator CR +// err - error if any // Example: -// torcCR, err := c.updateTorcEventAndStatus(tridentCR, debugMessage, message, status, version, namespace, -// corev1.EventTypeNormal, specValues) - +// torcCR, err := c.updateTorcEventAndStatus(tridentCR, "", "", "", "", "", corev1.EventTypeNormal) +// +// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- func (c *Controller) updateTorcEventAndStatus( tridentCR *netappv1.TridentOrchestrator, debugMessage, message, status, version, namespace, eventType string, specValues *netappv1.TridentOrchestratorSpecValues) (torcCR *netappv1.TridentOrchestrator, err error) { @@ -1734,6 +1786,7 @@ func (c *Controller) updateTridentOrchestratorCRStatus( ***********************************************/ // getTridentTprovCRsAll gets all the TridentProvisioner CRs across all namespaces func (c *Controller) getTridentTprovCRsAll() ([]tprovv1.TridentProvisioner, error) { +func (c *Controller) updateTridentOrchestratorCRStatus( list, err := c.CRDTprovClient.TridentV1().TridentProvisioners(corev1.NamespaceAll).List(ctx(), listOpts) if err != nil { return nil, err @@ -1743,6 +1796,7 @@ func (c *Controller) getTridentTprovCRsAll() ([]tprovv1.TridentProvisioner, erro // identifyTprovCRWithInstalledStatus identified the controllingCR with installed status func (c *Controller) identifyTprovCRWithInstalledStatus() (*tprovv1.TridentProvisioner, error) { +func (c *Controller) getTridentTprovCRsAll() ([]tprovv1.TridentProvisioner, error) { // Get all TridentOrchestrator CRs tridentTprovCRs, err := c.getTridentTprovCRsAll() @@ -1764,6 +1818,7 @@ func (c *Controller) identifyTprovCRWithInstalledStatus() (*tprovv1.TridentProvi // deleteTridentTprovCRD deletes TridentProvisioner CRD func (c *Controller) deleteTridentTprovCRD() error { +func (c *Controller) identifyTprovCRWithInstalledStatus() (*tprovv1.TridentProvisioner, error) { log.Debug("Starting TridentProvisioner CRD cleanup.") logFields := log.Fields{"CRD": TridentProvisionersCRDName} @@ -1812,11 +1867,13 @@ func (c *Controller) deleteTridentTprovCRD() error { // deleteTridentTprovCR deletes TridentProvisioner CR func (c *Controller) deleteTridentTprovCR(name, namespace string) error { +func (c *Controller) deleteTridentTprovCRD() error { return c.CRDTprovClient.TridentV1().TridentProvisioners(namespace).Delete(ctx(), name, deleteOpts) } // deleteTridentTprovCRAll deletes all the TridentProvisioner CRs func (c *Controller) deleteTridentTprovCRAll() error { +func (c *Controller) deleteTridentTprovCR(name, namespace string) error { log.Debug("Starting TridentProvisioner CR cleanup.") // See if CRD exists @@ -1847,14 +1904,18 @@ func (c *Controller) deleteTridentTprovCRAll() error { return nil } -// cleanupTridentProvisioner cleans up the Trident provisioner resources. +func (c *Controller) cleanupTridentProvisioner() error { +// cleanupTridentProvisioner deletes the Trident provisioner CRD and all CRs. // It returns an error if any of the operations fail. +// Returns: +// - error: nil if all operations succeed, otherwise an error // Example: -// err := cleanupTridentProvisioner() -// if err != nil { -// return err -// } - +// - err := c.cleanupTridentProvisioner() +// - if err != nil { +// - log.Errorf("Failed to clean up Trident provisioner: %v", err) +// - } +// +// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- func (c *Controller) cleanupTridentProvisioner() error { if err := c.deleteTridentTprovCRAll(); err != nil { return err @@ -1877,6 +1938,7 @@ func (c *Controller) getTridentOrchestratorCSIDeployments() ([]appsv1.Deployment // getCRDBasedCSIDeployments returns CSI Trident deployments (if any) created by CR based of crdName func (c *Controller) getCRDBasedCSIDeployments(crdName string) ([]appsv1.Deployment, string, error) { +func (c *Controller) getTridentOrchestratorCSIDeployments() ([]appsv1.Deployment, string, error) { var tridentCSIDeployments []appsv1.Deployment var tridentCSIExist bool var tridentCSINamespace string @@ -1918,6 +1980,7 @@ func (c *Controller) getCRDBasedCSIDeployments(crdName string) ([]appsv1.Deploym // matchDeploymentControllingCR identified the controllingCR for an operator based deployment from the list of CRs func (c *Controller) matchDeploymentControllingCR(tridentCRs []netappv1.TridentOrchestrator, +func (c *Controller) getCRDBasedCSIDeployments(crdName string) ([]appsv1.Deployment, string, error) { operatorCSIDeployment appsv1.Deployment) (*netappv1.TridentOrchestrator, error) { // Identify Trident CR that controls the deployment @@ -1941,21 +2004,25 @@ func (c *Controller) matchDeploymentControllingCR(tridentCRs []netappv1.TridentO **************************/ // isLegacyTridentInstalled identifies if legacy Trident is installed func (c *Controller) isLegacyTridentInstalled() (installed bool, namespace string, err error) { +func (c *Controller) matchDeploymentControllingCR(tridentCRs []netappv1.TridentOrchestrator, return c.K8SClient.CheckDeploymentExistsByLabel(installer.TridentLegacyLabel, true) } // isPreviewCSITridentInstalled identifies if CSI Preview Trident is installed func (c *Controller) isPreviewCSITridentInstalled() (installed bool, namespace string, err error) { +func (c *Controller) isLegacyTridentInstalled() (installed bool, namespace string, err error) { return c.K8SClient.CheckStatefulSetExistsByLabel(installer.TridentCSILabel, true) } // isCSITridentInstalled identifies if CSI Trident is installed func (c *Controller) isCSITridentInstalled() (installed bool, namespace string, err error) { +func (c *Controller) isPreviewCSITridentInstalled() (installed bool, namespace string, err error) { return c.K8SClient.CheckDeploymentExistsByLabel(installer.TridentCSILabel, true) } // uninstallCSIPreviewTrident uninstalls Trident CSI Preview func (c *Controller) uninstallCSIPreviewTrident(namespace string) error { +func (c *Controller) isCSITridentInstalled() (installed bool, namespace string, err error) { i, err := installer.NewInstaller(c.KubeConfig, namespace, 0) if err != nil { return err @@ -1973,6 +2040,7 @@ func (c *Controller) uninstallCSIPreviewTrident(namespace string) error { // uninstallLegacyTrident uninstalls Trident CSI Legacy func (c *Controller) uninstallLegacyTrident(namespace string) error { +func (c *Controller) uninstallCSIPreviewTrident(namespace string) error { i, err := installer.NewInstaller(c.KubeConfig, namespace, 0) if err != nil { return err @@ -1990,6 +2058,7 @@ func (c *Controller) uninstallLegacyTrident(namespace string) error { // removeNonTorcBasedCSIInstallation identifies if the Tprov-based or tridentctl-based CSI Trident is installed, // if it is installed it will be uninstalled. func (c *Controller) removeNonTorcBasedCSIInstallation(tridentCR *netappv1.TridentOrchestrator) error { +func (c *Controller) uninstallLegacyTrident(namespace string) error { var uninstallRequired bool // Check for the CSI based Trident installation @@ -2040,6 +2109,7 @@ func (c *Controller) removeNonTorcBasedCSIInstallation(tridentCR *netappv1.Tride // getCurrentTridentAndK8sVersion reports current Trident version installed and K8s version according // to which Trident was installed func (c *Controller) getCurrentTridentAndK8sVersion(tridentCR *netappv1.TridentOrchestrator) (string, string, error) { +func (c *Controller) removeNonTorcBasedCSIInstallation(tridentCR *netappv1.TridentOrchestrator) error { var currentTridentVersionString string var currentK8sVersionString string @@ -2075,6 +2145,7 @@ func (c *Controller) getCurrentTridentAndK8sVersion(tridentCR *netappv1.TridentO // validateCurrentK8sVersion identifies any changes in the K8s version, if it is valid, and if not valid should // user be warned about it func (c *Controller) validateCurrentK8sVersion() (bool, string) { +func (c *Controller) getCurrentTridentAndK8sVersion(tridentCR *netappv1.TridentOrchestrator) (string, string, error) { var isValid bool var warning string @@ -2108,6 +2179,7 @@ func (c *Controller) validateCurrentK8sVersion() (bool, string) { // tridentUpgradeNeeded compares the K8's version as per which Trident is installed with the current K8s version, // if it has changed we need to update Trident as well func (c *Controller) tridentUpgradeNeeded(tridentK8sConfigVersion string) bool { +func (c *Controller) validateCurrentK8sVersion() (bool, string) { var shouldUpdate bool @@ -2136,6 +2208,7 @@ func (c *Controller) tridentUpgradeNeeded(tridentK8sConfigVersion string) bool { ************************/ // doesCRDExist checks if the given CRD exist func (c *Controller) doesCRDExist(crdName string) (bool, error) { +func (c *Controller) tridentUpgradeNeeded(tridentK8sConfigVersion string) bool { // Discover CRD data crdExist, returnError := c.K8SClient.CheckCRDExists(crdName) @@ -2146,11 +2219,19 @@ func (c *Controller) doesCRDExist(crdName string) (bool, error) { return crdExist, returnError } -// isNotFoundError returns true if the error is an API not found error. +func isNotFoundError(err error) bool { +// isNotFoundError returns true if the error is an API not found error +// Parameters: +// err: the error to check +// Returns: +// true if the error is an API not found error // Example: -// err := errors.NewNotFound(schema.GroupResource{Resource: "pods"}, "123") -// isNotFoundError(err) // true - +// err := ... +// if isNotFoundError(err) { +// // do something +// } +// +// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- func isNotFoundError(err error) bool { if statusErr, ok := err.(*apierrors.StatusError); ok && statusErr.Status().Reason == metav1.StatusReasonNotFound { return true diff --git a/operator/controllers/orchestrator/installer/installer.go b/operator/controllers/orchestrator/installer/installer.go index a1affa5ad..327acf7d6 100644 --- a/operator/controllers/orchestrator/installer/installer.go +++ b/operator/controllers/orchestrator/installer/installer.go @@ -109,19 +109,23 @@ type Installer struct { namespace string } -// NewInstaller creates a new Trident installer +// NewInstaller creates a new installer +// It returns a TridentInstaller interface +// It returns an error if the installer cannot be created // Parameters: -// kubeConfig: Kubernetes client configuration -// namespace: Kubernetes namespace -// timeout: Timeout for Kubernetes operations -// It returns a Trident installer and error +// kubeConfig - Kubernetes config +// namespace - Kubernetes namespace +// timeout - timeout for Kubernetes operations +// Returns: +// TridentInstaller - Trident installer +// error - error if the installer cannot be created // Example: -// installer, err := installer.NewInstaller(kubeConfig, namespace, timeout) -// if err != nil { -// return nil, err -// } -// defer installer.Close() - +// installer, err := installer.NewInstaller(kubeConfig, namespace, timeout) +// if err != nil { +// return err +// } +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func NewInstaller(kubeConfig *rest.Config, namespace string, timeout int) (TridentInstaller, error) { if timeout <= 0 { @@ -151,14 +155,18 @@ func NewInstaller(kubeConfig *rest.Config, namespace string, timeout int) (Tride }, nil } -// logFormatPrechecks performs pre-checks on the logFormat -// It returns an error if the logFormat is not valid +// logFormatPrechecks checks that the log format is valid +// It returns an error if the log format is not valid +// Returns: +// error: if the log format is not valid // Example: -// err := i.logFormatPrechecks() -// if err != nil { -// return err -// } - +// returnError := i.logFormatPrechecks() +// if returnError != nil { +// log.Error(returnError) +// return returnError +// } +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func (i *Installer) logFormatPrechecks() (returnError error) { switch logFormat { case "text", "json": @@ -277,6 +285,7 @@ func (i *Installer) imagePrechecks(labels, controllingCRDetails map[string]strin // setInstallationParams identifies the correct parameters for the Trident installation func (i *Installer) setInstallationParams( +func (i *Installer) imagePrechecks(labels, controllingCRDetails map[string]string) (string, error) { cr netappv1.TridentOrchestrator, currentInstallationVersion string, ) (map[string]string, map[string]string, bool, error) { @@ -434,19 +443,24 @@ func (i *Installer) setInstallationParams( return controllingCRDetails, labels, tridentUpdateNeeded, nil } -// InstallOrPatchTrident installs or updates Trident +func (i *Installer) InstallOrPatchTrident( +// InstallOrPatchTrident installs or patches Trident +// It returns the TridentOrchestratorSpecValues, the version of Trident installed, and an error // Parameters: -// cr - the controlling CR -// currentInstallationVersion - the current version of Trident installed -// k8sUpdateNeeded - true if the Kubernetes version has changed +// cr - the TridentOrchestrator CR +// currentInstallationVersion - the version of Trident currently installed +// k8sUpdateNeeded - true if the K8s version has changed since the last installation // Returns: -// *netappv1.TridentOrchestratorSpecValues - the values from the CR spec +// TridentOrchestratorSpecValues - the values from the CR that were used to install Trident // string - the version of Trident installed // error - any error encountered -// It returns the values from the CR spec, the version of Trident installed, and any error encountered. // Example: -// values, version, err := i.InstallOrPatchTrident(cr, currentInstallationVersion, k8sUpdateNeeded) - +// specValues, version, err := i.InstallOrPatchTrident(cr, currentInstallationVersion, k8sUpdateNeeded) +// if err != nil { +// // Handle error +// } +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func (i *Installer) InstallOrPatchTrident( cr netappv1.TridentOrchestrator, currentInstallationVersion string, k8sUpdateNeeded bool, ) (*netappv1.TridentOrchestratorSpecValues, string, error) { @@ -637,6 +651,7 @@ func (i *Installer) createCRDs() error { // CreateCRD creates and establishes the CRD func (i *Installer) CreateCRD(crdName, crdYAML string) error { +func (i *Installer) createCRDs() error { // Discover CRD data crdExist, returnError := i.client.CheckCRDExists(crdName) @@ -677,6 +692,7 @@ func (i *Installer) CreateCRD(crdName, crdYAML string) error { // ensureCRDEstablished waits until a CRD is Established. func (i *Installer) ensureCRDEstablished(crdName string) error { +func (i *Installer) CreateCRD(crdName, crdYAML string) error { checkCRDEstablished := func() error { crd, err := i.client.GetCRD(crdName) @@ -717,12 +733,20 @@ func (i *Installer) ensureCRDEstablished(crdName string) error { return nil } +func (i *Installer) createOrPatchK8sBetaCSIDriver( // createOrPatchK8sBetaCSIDriver creates or patches the K8s (beta) CSI driver -// It returns an error if the operation fails +// TODO (cknight): remove when 1.18 is our minimum version +// It returns an error if the operation fails. +// Parameters: +// controllingCRDetails - map of the controlling CR's details +// labels - map of labels to apply to the K8s (beta) CSI driver +// shouldUpdate - whether or not to update the K8s (beta) CSI driver +// Returns: +// error - if the operation fails // Example: -// installer := installer.NewInstaller(k8sClient, k8sVersion) // err := installer.createOrPatchK8sBetaCSIDriver(controllingCRDetails, labels, shouldUpdate) - +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func (i *Installer) createOrPatchK8sBetaCSIDriver( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -752,19 +776,17 @@ func (i *Installer) createOrPatchK8sBetaCSIDriver( } // createOrPatchK8sCSIDriver creates or patches the K8s CSI driver +// It returns an error if the operation fails // Parameters: -// controllingCRDetails: map of controlling CR details -// labels: map of labels -// shouldUpdate: boolean to indicate if the CSI driver should be updated -// Return: -// error: error if any -// It returns error if it fails to create or patch the K8s CSI driver +// controllingCRDetails: map of the controlling CR details +// labels: map of labels to be applied to the CSI driver +// shouldUpdate: true if the CSI driver should be updated, false otherwise +// Returns: +// error: nil if successful, error object otherwise // Example: -// err := createOrPatchK8sCSIDriver(controllingCRDetails, labels, shouldUpdate) -// if err != nil { -// log.Errorf("failed to create or patch K8s CSI driver; %v", err) -// } - +// err := i.createOrPatchK8sCSIDriver(controllingCRDetails, labels, shouldUpdate) +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func (i *Installer) createOrPatchK8sCSIDriver(controllingCRDetails, labels map[string]string, shouldUpdate bool) error { CSIDriverName := getCSIDriverName() @@ -790,21 +812,18 @@ func (i *Installer) createOrPatchK8sCSIDriver(controllingCRDetails, labels map[s return nil } -// createRBACObjects creates the RBAC objects for Trident. +// createRBACObjects creates the RBAC objects for Trident // Parameters: -// controllingCRDetails - a map of labels and annotations to be applied to the RBAC objects -// labels - a map of labels to be applied to the RBAC objects -// shouldUpdate - whether or not to update the RBAC objects if they already exist +// controllingCRDetails - the details of the controlling CR +// labels - the labels to apply to the RBAC objects +// shouldUpdate - whether to update existing objects // Returns: -// newServiceAccount - whether or not a new service account was created +// newServiceAccount - whether a new service account was created // returnError - any error encountered // Example: -// newServiceAccount, returnError := createRBACObjects(controllingCRDetails, labels, false) -// if returnError != nil { -// log.Errorf("Failed to create RBAC objects for Trident; %v", returnError) -// return returnError -// } - +// newServiceAccount, returnError := i.createRBACObjects(controllingCRDetails, labels, true) +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func (i *Installer) createRBACObjects( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) (newServiceAccount bool, returnError error) { @@ -843,14 +862,17 @@ func (i *Installer) createRBACObjects( return } -// createTridentInstallationNamespace creates the Trident installation namespace -// It returns an error if the namespace could not be created. +// createTridentInstallationNamespace creates the namespace for Trident's installation +// It returns an error if the namespace already exists and is not empty +// Returns: +// error: if the namespace could not be created // Example: -// err := installer.createTridentInstallationNamespace() -// if err != nil { -// return fmt.Errorf("failed to create Trident installation namespace; %v", err) -// } - +// err := i.createTridentInstallationNamespace() +// if err != nil { +// // handle error +// } +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func (i *Installer) createTridentInstallationNamespace() error { createNamespace := true @@ -881,17 +903,24 @@ func (i *Installer) createTridentInstallationNamespace() error { } // createOrPatchTridentServiceAccount creates or patches the Trident service account +// It returns a boolean indicating whether the service account was created, and an error // Parameters: -// controllingCRDetails - a map of labels and values that will be applied to the Trident service account -// labels - a map of labels and values that will be applied to the Trident service account -// shouldUpdate - true if the Trident service account should be updated +// controllingCRDetails - a map containing the controlling CR's name and namespace +// labels - a map containing the labels to be applied to the service account +// shouldUpdate - a boolean indicating whether the service account should be updated // Return values: -// bool - true if the Trident service account was created -// error - nil if the Trident service account was created or patched successfully, or an error if it failed -// It returns an error if the Trident service account could not be created or patched. +// bool - a boolean indicating whether the service account was created +// error - an error indicating whether the function succeeded or failed +// Returns: +// bool - a boolean indicating whether the service account was created +// error - an error indicating whether the function succeeded or failed // Example: -// created, err := createOrPatchTridentServiceAccount(controllingCRDetails, labels, shouldUpdate) - +// newServiceAccount, err := createOrPatchTridentServiceAccount(controllingCRDetails, labels, shouldUpdate) +// if err != nil { +// return err +// } +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func (i *Installer) createOrPatchTridentServiceAccount( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) (bool, error) { @@ -919,20 +948,20 @@ func (i *Installer) createOrPatchTridentServiceAccount( return newServiceAccount, nil } -// createOrPatchTridentClusterRole creates or patches the Trident cluster role +// createOrPatchTridentClusterRole creates or patches the Trident cluster role. +// It returns an error if the operation fails. // Parameters: -// controllingCRDetails - details of the controlling CR -// labels - labels to apply to the Trident cluster role -// shouldUpdate - whether the Trident cluster role should be updated -// Return: -// error - error if any -// It returns error if it fails to create or patch the Trident cluster role. +// controllingCRDetails - details about the controlling CR +// labels - labels to apply to the cluster role +// shouldUpdate - whether the cluster role should be updated +// Returns: +// error - error if the operation fails // Example: -// err := i.createOrPatchTridentClusterRole(controllingCRDetails, labels, shouldUpdate) -// if err != nil { -// return err -// } - +// controllingCRDetails := map[string]string{"app": "trident"} +// labels := map[string]string{"app": "trident"} +// err := createOrPatchTridentClusterRole(controllingCRDetails, labels, true) +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func (i *Installer) createOrPatchTridentClusterRole( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -961,21 +990,19 @@ func (i *Installer) createOrPatchTridentClusterRole( return nil } -// createOrPatchTridentClusterRoleBinding creates or patches the Trident cluster role binding. -// Parameters: -// controllingCRDetails: map of controlling CR details -// labels: map of labels -// shouldUpdate: true if the cluster role binding should be updated +// createOrPatchTridentClusterRoleBinding creates or patches the Trident cluster role binding +// with the specified labels. // It returns an error if the operation fails. +// Parameters: +// controllingCRDetails - the details of the controlling CR +// labels - the labels to apply to the Trident cluster role binding +// shouldUpdate - true if the Trident cluster role binding should be updated, false otherwise +// Returns: +// error - error if the operation fails // Example: -// controllingCRDetails := map[string]string{ -// "name": "trident-csi-driver", -// "kind": "CSIDriver", -// } -// labels := map[string]string{"app": "trident"} -// shouldUpdate = true -// err = i.createOrPatchTridentClusterRoleBinding(controllingCRDetails, labels, shouldUpdate) - +// err := installer.createOrPatchTridentClusterRoleBinding(controllingCRDetails, labels, true) +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func (i *Installer) createOrPatchTridentClusterRoleBinding( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -1005,20 +1032,25 @@ func (i *Installer) createOrPatchTridentClusterRoleBinding( return nil } -// createOrPatchTridentOpenShiftSCC creates or patches the Trident OpenShift SCC +// createOrPatchTridentOpenShiftSCC creates or patches the Trident OpenShift SCC. +// It returns an error if the SCC could not be created or patched. // Parameters: -// controllingCRDetails - a map of the controlling CR's details -// labels - a map of labels to apply to the OpenShift SCC -// shouldUpdate - true if the SCC should be updated, false if it should be created +// controllingCRDetails: a map of the controlling CR's name and namespace +// labels: a map of labels to apply to the SCC +// shouldUpdate: whether or not the SCC should be updated // Returns: -// error - error if any -// It returns an error if it fails to create or patch the OpenShift SCC +// error: nil if the SCC was created or patched successfully, or an error if the SCC could not be created or patched // Example: -// err := i.createOrPatchTridentOpenShiftSCC(controllingCRDetails, labels, shouldUpdate) +// labels := map[string]string{ +// "app": "trident", +// } +// err := createOrPatchTridentOpenShiftSCC(map[string]string{}, labels, false) // if err != nil { -// return fmt.Errorf("failed to create or patch Trident OpenShift SCC; %v", err) +// log.Errorf("Unable to create Trident OpenShift SCC, err: %v", err) +// return err // } - +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func (i *Installer) createOrPatchTridentOpenShiftSCC( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -1060,12 +1092,16 @@ func (i *Installer) createOrPatchTridentOpenShiftSCC( return nil } -// createAndEnsureCRDs creates the Trident CRDs. +// createAndEnsureCRDs creates the Trident CRDs and ensures they are ready. +// Returns: +// error: nil if successful, else a descriptive error // Example: -// if err := i.createAndEnsureCRDs(); err != nil { -// return err -// } - +// err := i.createAndEnsureCRDs() +// if err != nil { +// // handle error +// } +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func (i *Installer) createAndEnsureCRDs() (returnError error) { returnError = i.createCRDs() @@ -1076,19 +1112,17 @@ func (i *Installer) createAndEnsureCRDs() (returnError error) { } // createOrPatchTridentPodSecurityPolicy creates or patches the Trident pod security policy +// It returns an error if the operation fails. // Parameters: // controllingCRDetails - a map of the controlling CR's details // labels - a map of labels to apply to the Trident pod security policy -// shouldUpdate - indicates whether the Trident pod security policy should be updated -// Return: -// error - error if any -// It returns an error if it fails to create or patch the Trident pod security policy +// shouldUpdate - true if the Trident pod security policy should be updated +// Returns: +// error - an error if the operation fails // Example: -// err := i.createOrPatchTridentPodSecurityPolicy(controllingCRDetails, labels, true) -// if err != nil { -// return err -// } - +// err := createOrPatchTridentPodSecurityPolicy(controllingCRDetails, labels, shouldUpdate) +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func (i *Installer) createOrPatchTridentPodSecurityPolicy( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -1114,20 +1148,21 @@ func (i *Installer) createOrPatchTridentPodSecurityPolicy( return nil } -// createOrPatchTridentService creates or patches the Trident service. +// createOrPatchTridentService creates or patches the Trident service +// It returns an error if the service could not be created or patched // Parameters: // controllingCRDetails - map of controlling CR details -// labels - map of labels -// shouldUpdate - true if the service should be updated, false otherwise +// labels - map of labels to apply to the Trident service +// shouldUpdate - whether or not the Trident service should be updated // Returns: -// error - error, if any -// It returns an error if it fails to create or patch the Trident service. +// error - error if the Trident service could not be created or patched // Example: -// err := installer.createOrPatchTridentService(controllingCRDetails, labels, shouldUpdate) +// err := i.createOrPatchTridentService(controllingCRDetails, labels, shouldUpdate) // if err != nil { // return err // } - +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func (i *Installer) createOrPatchTridentService( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -1153,17 +1188,24 @@ func (i *Installer) createOrPatchTridentService( return nil } -// createOrPatchTridentProtocolSecret creates or patches the Trident protocol secret +// createOrPatchTridentProtocolSecret creates or patches the Trident protocol secret. +// It returns an error if the secret could not be created or patched. // Parameters: -// controllingCRDetails - the controlling CR's details -// labels - the labels to apply to the secret -// shouldUpdate - whether the secret should be updated if it already exists -// Return: -// error - error if any -// It returns an error if the secret cannot be created or patched. +// controllingCRDetails - a map of labels and annotations to add to the secret +// labels - a map of labels to add to the secret +// shouldUpdate - true if the secret should be updated if it already exists +// Returns: +// error - nil if the secret was created or patched successfully // Example: -// err := i.createOrPatchTridentProtocolSecret(controllingCRDetails, labels, shouldUpdate) - +// controllingCRDetails := map[string]string{ +// "netapp.io/trident-version": "v1.0", +// } +// labels := map[string]string{ +// "netapp.io/trident-version": "v1.0", +// } +// err := i.createOrPatchTridentProtocolSecret(controllingCRDetails, labels, true) +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func (i *Installer) createOrPatchTridentProtocolSecret( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -1258,22 +1300,20 @@ func (i *Installer) createOrConsumeTridentEncryptionSecret( return nil } -// createOrPatchTridentDeployment creates or patches the Trident deployment +func (i *Installer) createOrPatchTridentDeployment( +// createOrPatchTridentDeployment creates or patches the Trident deployment. +// It returns an error if the deployment could not be created or patched. // Parameters: -// controllingCRDetails - the labels and annotations to add to the Trident deployment -// labels - the labels to add to the Trident deployment -// shouldUpdate - whether or not to update the Trident deployment -// newServiceAccount - whether or not a new service account should be created +// controllingCRDetails: a map of the controlling CR's name and namespace +// labels: a map of labels to apply to the deployment +// shouldUpdate: true if the deployment should be updated +// newServiceAccount: true if a new service account should be created // Returns: -// error - error if there was a problem creating or patching the Trident deployment -// It returns an error if there was a problem creating or patching the Trident deployment. +// error: nil if the deployment was created or patched successfully // Example: -// i := installer.NewInstaller(client) -// err := i.createOrPatchTridentDeployment(controllingCRDetails, labels, false, false) -// if err != nil { -// return err -// } - +// err := i.createOrPatchTridentDeployment(controllingCRDetails, labels, true, true) +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func (i *Installer) createOrPatchTridentDeployment( controllingCRDetails, labels map[string]string, shouldUpdate, newServiceAccount bool, ) error { @@ -1356,18 +1396,21 @@ func (i *Installer) TridentDeploymentInformation( return i.client.GetDeploymentInformation(getDeploymentName(true), deploymentLabel, i.namespace) } +func (i *Installer) createOrPatchTridentDaemonSet( // createOrPatchTridentDaemonSet creates or patches the Trident daemonset +// It returns an error if the daemonset cannot be created or patched // Parameters: -// controllingCRDetails - map of details about the controlling CR -// labels - map of labels to add to the daemonset +// controllingCRDetails - a map containing the name and namespace of the controlling CR +// labels - a map containing the labels to be applied to the daemonset // shouldUpdate - true if the daemonset should be updated // newServiceAccount - true if a new service account should be created -// Return: -// error - error if any -// It returns an error if it fails to create or patch the daemonset +// Returns: +// error - an error if the daemonset cannot be created or patched // Example: -// err := i.createOrPatchTridentDaemonSet(controllingCRDetails, labels, shouldUpdate, newServiceAccount) - +// error := i.createOrPatchTridentDaemonSet(controllingCRDetails, labels, shouldUpdate, newServiceAccount) +// +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func (i *Installer) createOrPatchTridentDaemonSet( controllingCRDetails, labels map[string]string, shouldUpdate, newServiceAccount bool, ) error { @@ -1440,15 +1483,20 @@ func (i *Installer) TridentDaemonSetInformation() (*appsv1.DaemonSet, return i.client.GetDaemonSetInformation(daemonSetName, nodeLabel, i.namespace) } -// waitForTridentPod waits for the Trident pod to start. -// It returns the pod object if successful. +func (i *Installer) waitForTridentPod() (*v1.Pod, error) { +// waitForTridentPod waits for the Trident pod to be running. +// It returns the pod if it is running, or an error if it is not. +// Returns: +// * Pod if running +// * Error if not running // Example: -// pod, err := waitForTridentPod() -// if err != nil { -// log.Error(err) -// return err -// } - +// pod, err := i.waitForTridentPod() +// if err != nil { +// fmt.Printf("error: %v", err) +// } +// fmt.Printf("pod: %v", pod) +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func (i *Installer) waitForTridentPod() (*v1.Pod, error) { var pod *v1.Pod @@ -1561,18 +1609,18 @@ func (i *Installer) waitForTridentPod() (*v1.Pod, error) { } // waitForRESTInterface waits for the Trident REST interface to become available. +// It returns an error if the REST interface is not available within the timeout. // Parameters: // tridentPodName - the name of the Trident pod // Returns: -// error - nil if the REST interface is available, error otherwise -// It returns an error if the REST interface is not available after 30 seconds. +// error - an error if the REST interface is not available within the timeout // Example: -// err := waitForRESTInterface("trident-csi-trident-0") +// err := i.waitForRESTInterface("trident-backend-pod-name") // if err != nil { -// return err +// return err // } -// fmt.Println("Trident REST interface is up.") - +// +// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- func (i *Installer) waitForRESTInterface(tridentPodName string) error { var version, versionWithMetadata string @@ -1671,6 +1719,7 @@ func (i *Installer) getTridentClientVersionInfo(imageName string, controllingCRD // resembles the `kubectl run --rm -it --restart=Never transient-trident-version-pod --image= -- // /bin/tridentctl version --client -o yaml` command func (i *Installer) getTridentVersionYAML(imageName string, controllingCRDetails map[string]string) ([]byte, error) { +func (i *Installer) getTridentClientVersionInfo(imageName string, controllingCRDetails map[string]string) (*api. podName := "transient-trident-version-pod" podLabels := make(map[string]string) @@ -1727,6 +1776,7 @@ func (i *Installer) getTridentVersionYAML(imageName string, controllingCRDetails // createTridentVersionPod takes the pod name and trident image name to create a pod func (i *Installer) createTridentVersionPod( +func (i *Installer) getTridentVersionYAML(imageName string, controllingCRDetails map[string]string) ([]byte, error) { podName, imageName string, controllingCRDetails, podLabels map[string]string, ) error { versionPodLabel := TridentVersionPodLabel diff --git a/operator/controllers/orchestrator/installer/installer_test.go b/operator/controllers/orchestrator/installer/installer_test.go index c0518c691..8bf97a91c 100644 --- a/operator/controllers/orchestrator/installer/installer_test.go +++ b/operator/controllers/orchestrator/installer/installer_test.go @@ -19,29 +19,31 @@ var ( k8sClientError = fmt.Errorf("k8s error") ) -// newMockKubeClient creates a new mock kubernetes client +// newMockKubeClient returns a mock k8s client // Parameters: -// t *testing.T - test object +// t *testing.T - test object // Returns: -// *mockExtendedK8sClient.MockExtendedK8sClient - mock kubernetes client -// It returns a mock kubernetes client +// *mockExtendedK8sClient.MockExtendedK8sClient - mock k8s client // Example: -// mockK8sClient := newMockKubeClient(t) - +// mockK8sClient := newMockKubeClient(t) +// +// -- Doc autogenerated on 2022-05-12 18:52:24.083540 -- func newMockKubeClient(t *testing.T) *mockExtendedK8sClient.MockExtendedK8sClient { mockCtrl := gomock.NewController(t) mockK8sClient := mockExtendedK8sClient.NewMockExtendedK8sClient(mockCtrl) return mockK8sClient } -// newTestInstaller creates a new Installer for testing purposes. +// newTestInstaller creates a new Installer for testing +// It returns a pointer to the Installer and a pointer to the mock client // Parameters: -// client - a mock client for the installer to use -// It returns the new Installer. +// client - a pointer to a mock client +// Returns: +// a pointer to the Installer // Example: -// client := mockExtendedK8sClient.NewMockClient() -// installer := newTestInstaller(client) - +// installer, client := newTestInstaller(client) +// +// -- Doc autogenerated on 2022-05-12 18:52:24.083540 -- func newTestInstaller(client *mockExtendedK8sClient.MockExtendedK8sClient) *Installer { return &Installer{ @@ -53,13 +55,12 @@ func newTestInstaller(client *mockExtendedK8sClient.MockExtendedK8sClient) *Inst // createTestControllingCRDetails creates a map of the controlling CR details // It returns a map of the controlling CR details +// Returns: +// map[string]string: map of the controlling CR details // Example: -// controllingCRDetails := createTestControllingCRDetails() -// fmt.Println(controllingCRDetails) +// crDetails := createTestControllingCRDetails() // -// Output: -// map[trident.netapp.io/apiVersion:v01.01.01 trident.netapp.io/controller:trident-orchestrator trident.netapp.io/kind:deployment trident.netapp.io/name:trident-csi trident.netapp.io/uid:1] - +// -- Doc autogenerated on 2022-05-12 18:52:24.083540 -- func createTestControllingCRDetails() map[string]string { controllingCRDetails := make(map[string]string) @@ -72,11 +73,14 @@ func createTestControllingCRDetails() map[string]string { return controllingCRDetails } -// createTestLabels creates a set of labels for testing +// createTestLabels creates a map of labels for testing // It returns a map of labels +// Returns: +// map[string]string: map of labels // Example: -// labels := createTestLabels() - +// labels := createTestLabels() +// +// -- Doc autogenerated on 2022-05-12 18:52:24.083540 -- func createTestLabels() map[string]string { labels := make(map[string]string) @@ -87,19 +91,14 @@ func createTestLabels() map[string]string { return labels } -// TestInstaller_createOrConsumeTridentEncryptionSecret tests the creation of the Trident encryption secret +// TestInstaller_createOrConsumeTridentEncryptionSecret tests the createOrConsumeTridentEncryptionSecret function // It checks for the following conditions: // 1. K8s error at CheckSecretExists // 2. Secret already exists and no K8s error // 3. Create secret with no failure at PutSecret // 4. Create secret with a failure at PutSecret -// Parameters: -// t *testing.T -// Returns: -// none -// Example: -// TestInstaller_createOrConsumeTridentEncryptionSecret(t) - +// +// -- Doc autogenerated on 2022-05-12 18:52:24.083540 -- func TestInstaller_createOrConsumeTridentEncryptionSecret(t *testing.T) { mockK8sClient := newMockKubeClient(t) diff --git a/operator/controllers/orchestrator/installer/k8s_client_test.go b/operator/controllers/orchestrator/installer/k8s_client_test.go index 48a2a20ce..14cd00e96 100644 --- a/operator/controllers/orchestrator/installer/k8s_client_test.go +++ b/operator/controllers/orchestrator/installer/k8s_client_test.go @@ -29,14 +29,10 @@ import ( "github.com/netapp/trident/utils" ) -// TestMain is the entry point for all tests. -// It checks for the presence of the KUBECONFIG environment variable. -// If it is not set, the tests are skipped. -// Parameters: -// m: the test suite -// Example: -// $ KUBECONFIG= go test ./... - +// TestMain is the main entry point for tests +// It checks for any standard log output and disables it +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestMain(m *testing.M) { // Disable any standard log output log.SetOutput(ioutil.Discard) @@ -68,24 +64,23 @@ func (m *JSONMatcher) Matches(x interface{}) bool { return reflect.DeepEqual(actual, expected) } -// String returns a string representation of the matcher. +func (m *JSONMatcher) String() string { +// String returns a string representation of the matcher +// Returns: +// string: a string representation of the matcher // Example: -// json.String() - +// matcher := installer.JSONMatcher{} +// fmt.Println(matcher.String()) +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func (m *JSONMatcher) String() string { return "" } // TestCreateCustomResourceDefinition tests the CreateCustomResourceDefinition function -// It checks that the function returns the expected error -// Parameters: -// crdName: the name of the CRD to create -// crdYAML: the YAML of the CRD to create -// Example: -// TestCreateCustomResourceDefinition("crd-name", "crd-yaml") -// Expected Results: -// The function should return an error if the K8s client returns an error - +// It checks that the correct error is returned when the k8s client returns an error +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestCreateCustomResourceDefinition(t *testing.T) { crdName := "crd-name" @@ -147,12 +142,8 @@ func TestCreateCustomResourceDefinition(t *testing.T) { // TestDeleteCustomResourceDefinition tests the DeleteCustomResourceDefinition function // It checks that the function returns the expected error -// Parameters: -// crdName: the name of the CRD to delete -// crdYAML: the YAML of the CRD to delete -// Example: -// TestDeleteCustomResourceDefinition("test-crd", "test-crd-yaml") - +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestDeleteCustomResourceDefinition(t *testing.T) { crdName := "crd-name" @@ -214,18 +205,12 @@ func TestDeleteCustomResourceDefinition(t *testing.T) { // TestWaitForCRDEstablished tests the WaitForCRDEstablished function // It checks for the following conditions: -// - CRD is not found -// - CRD is found but not in the expected state -// - CRD is found and in the expected state -// Parameters: -// - crdName: the name of the CRD to wait for -// - timeout: the time to wait for the CRD to be established -// Returns: -// - error: nil if the CRD is found and in the expected state, otherwise an error -// It returns an error if the CRD is not found or is not in the expected state -// Example: -// err := WaitForCRDEstablished("trident-crd", 5 * time.Second) - +// - the function returns an error when the k8s client returns an error +// - the function returns an error when the CRD is not in the expected state +// - the function returns nil when the CRD is in the expected state +// It returns an error if the test fails. +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestWaitForCRDEstablished(t *testing.T) { var validCRD, invalidCRD *v1.CustomResourceDefinition @@ -328,18 +313,13 @@ func TestWaitForCRDEstablished(t *testing.T) { } // TestDeleteTransientVersionPod tests the DeleteTransientVersionPod function -// It checks for the following cases: -// 1. k8s client error during GetPodsByLabel -// 2. no k8s client error and no transient pods found -// 3. no k8s client error and transient pods found but not removed -// 4. no k8s client error and transient pods found and removed -// Parameters: -// t *testing.T : go testing framework -// Example: -// TestDeleteTransientVersionPod(t) -// Output: -// asserts that the expected output is equal to the actual output - +// It checks for the following conditions: +// 1. K8s client errors +// 2. No transient pods found +// 3. Transient pods found but not removed +// 4. Transient pods found and removed +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestDeleteTransientVersionPod(t *testing.T) { // declare and initialize variables used throughout the test cases var versionPodLabel, name, invalidName, namespace string @@ -451,14 +431,11 @@ func TestDeleteTransientVersionPod(t *testing.T) { // TestGetBetaCSIDriverInformation tests the GetBetaCSIDriverInformation function // It checks the following cases: -// - k8s error -// - no beta CSI driver found and no k8s error -// - valid current beta CSI driver found and no k8s error -// Parameters: -// - t: test object -// Example: -// - installer.TestGetBetaCSIDriverInformation(t) - +// - k8s error +// - no beta CSI driver found and no k8s error +// - valid current beta CSI driver found and no k8s error +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestGetBetaCSIDriverInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -596,16 +573,13 @@ func TestGetBetaCSIDriverInformation(t *testing.T) { } // TestPutBetaCSIDriver tests the PutBetaCSIDriver function -// It checks that the function returns the correct error -// It also checks that the function calls the correct k8s client functions -// Parameters: -// currentBetaCSIDriver: the current beta CSI driver -// createBetaCSIDriver: whether or not to create the beta CSI driver -// newBetaCSIDriverYAML: the YAML for the new beta CSI driver -// appLabel: the app label to use for the beta CSI driver -// Example: -// TestPutBetaCSIDriver(&storagev1beta1.CSIDriver{}, false, "", "") - +// It checks the following cases: +// - create a beta CSI Driver and no k8s error occurs +// - create a beta CSI Driver and a k8s error occurs +// - update a beta CSI Driver and no k8s error occurs +// - update a beta CSI Driver and a k8s error occurs +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestPutBetaCSIDriver(t *testing.T) { driverName := getCSIDriverName() @@ -750,18 +724,12 @@ func TestPutBetaCSIDriver(t *testing.T) { } } -// TestDeleteTridentBetaCSIDriverCR tests the DeleteTridentBetaCSIDriverCR method -// It checks that the correct error is returned when the method fails -// Parameters: -// secretName: the name of the secret to delete -// appLabel: the label to use to find the secret -// It returns the error returned by the method -// Example: -// err := TestDeleteTridentBetaCSIDriverCR(secretName, appLabel) -// if err != nil { -// // handle error -// } - +// TestDeleteTridentBetaCSIDriverCR tests the DeleteTridentBetaCSIDriverCR function +// It checks that the function returns the expected error when the k8s client returns an error +// It checks that the function returns nil when the k8s client returns no error +// It returns nil when the k8s client returns no error +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestDeleteTridentBetaCSIDriverCR(t *testing.T) { // arrange variables for the tests var emptyBetaCSIDriverList, unwantedBetaCSIDrivers []storagev1beta1.CSIDriver @@ -861,15 +829,11 @@ func TestDeleteTridentBetaCSIDriverCR(t *testing.T) { } // TestRemoveMultipleBetaCSIDriverCRs tests the RemoveMultipleBetaCSIDriverCRs function -// It checks the following cases: -// 1. No beta csi driver crs -// 2. K8s call error -// 3. Valid beta csi driver crs -// Parameters: -// t *testing.T - go test handler -// Example: -// TestRemoveMultipleBetaCSIDriverCRs(t) - +// It checks that the function returns the expected error when the k8s client returns an error +// It also checks that the function returns nil when there are no beta csi driver crs to delete +// It also checks that the function returns nil when there are valid beta csi driver crs to delete +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestRemoveMultipleBetaCSIDriverCRs(t *testing.T) { // arrange variables for the tests var emptyCSIDriversCRs, undeletedCSIDriverCRs, unwantedCSIDriverCRs []storagev1beta1.CSIDriver @@ -952,14 +916,11 @@ func TestRemoveMultipleBetaCSIDriverCRs(t *testing.T) { // TestGetCSIDriverInformation tests the GetCSIDriverInformation function // It checks for the following conditions: -// 1. If the function returns an error when it is unable to get a list of CSI driver custom resources by label -// 2. If the function returns no error when there are no CSI driver custom resources found by label -// 3. If the function returns no error when there are valid CSI driver custom resources found by label -// Parameters: -// t *testing.T - go testing object -// Example: -// TestGetCSIDriverInformation(t) - +// - k8s error +// - no beta CSI driver found +// - valid current beta CSI driver found +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestGetCSIDriverInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -1096,28 +1057,11 @@ func TestGetCSIDriverInformation(t *testing.T) { } } -// TestPutCSIDriver tests the PutCSIDriver method -// It checks to make sure the correct k8s client calls are made -// It also checks to make sure the correct errors are returned -// Parameters: -// currentCSIDriver: the current CSI driver -// createCSIDriver: whether or not to create the CSI driver -// newCSIDriverYAML: the new CSI driver YAML -// appLabel: the app label -// Returns: -// error: the error returned by PutCSIDriver -// Example: -// TestPutCSIDriver(t, -// &storagev1.CSIDriver{ -// ObjectMeta: metav1.ObjectMeta{ -// Name: driverName, -// }, -// }, -// false, -// newCSIDriverYAML, -// appLabel, -// ) - +// TestPutCSIDriver tests the PutCSIDriver function +// It checks that the correct k8s client calls are made +// and that the correct error is returned +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestPutCSIDriver(t *testing.T) { var validCSIDriver *storagev1.CSIDriver @@ -1264,18 +1208,13 @@ func TestPutCSIDriver(t *testing.T) { } // TestDeleteTridentCSIDriverCR tests the DeleteTridentCSIDriverCR function -// It checks the following cases: -// - GetCSIDriversByLabel fails -// - GetCSIDriversByLabel returns no services -// - GetCSIDriversByLabel succeeds but RemoveMultipleCSIDriverCRs fails -// - GetCSIDriversByLabel succeeds and RemoveMultipleCSIDriverCRs succeeds -// Parameters: -// csiDriverName - the name of the CSI driver to delete -// appLabel - the label to use to find the CSI driver CRs to delete -// It returns an error if any of the above cases fail -// Example: -// err := DeleteTridentCSIDriverCR("trident-csi-driver", "app=trident") - +// It checks that the function returns the correct error when the k8s client +// returns an error, and that it returns nil when the k8s client does not return +// an error. +// It returns the correct error when the k8s client returns an error, and that +// it returns nil when the k8s client does not return an error. +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestDeleteTridentCSIDriverCR(t *testing.T) { // arrange variables for the tests var emptyCSIDriverList, unwantedCSIDrivers []storagev1.CSIDriver @@ -1376,14 +1315,11 @@ func TestDeleteTridentCSIDriverCR(t *testing.T) { // TestRemoveMultipleCSIDriverCRs tests the RemoveMultipleCSIDriverCRs function // It checks the following cases: -// - no CSI driver CRs -// - k8s call error -// - valid CSI driver CRs -// Parameters: -// t *testing.T - go test helper -// Example: -// TestRemoveMultipleCSIDriverCRs(t) - +// 1. No CSI driver CRs are passed in +// 2. A k8s call error occurs +// 3. Valid CSI driver CRs are passed in +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestRemoveMultipleCSIDriverCRs(t *testing.T) { // arrange variables for the tests var emptyCSIDriversCRs, undeletedCSIDriverCRs, unwantedCSIDriverCRs []storagev1.CSIDriver @@ -1465,13 +1401,14 @@ func TestRemoveMultipleCSIDriverCRs(t *testing.T) { } // TestGetClusterRoleInformation tests the GetClusterRoleInformation function -// It checks that the function returns the correct currentClusterRole, unwantedClusterRoles, -// createClusterRole, and error based on the input and mock k8s client -// Parameters: -// t *testing.T: go testing framework object used to manage test flow -// Example: -// TestGetClusterRoleInformation(t) - +// in the installer package. +// It checks for the following conditions: +// 1. If the function returns the correct current cluster role +// 2. If the function returns the correct unwanted cluster roles +// 3. If the function returns the correct create cluster role boolean +// 4. If the function returns the correct error +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestGetClusterRoleInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -1614,11 +1551,8 @@ func TestGetClusterRoleInformation(t *testing.T) { // - creating a ClusterRole and a k8s error occurs // - updating a ClusterRole and no k8s error occurs // - updating a ClusterRole and a k8s error occurs -// Parameters: -// t *testing.T -// Example: -// TestPutClusterRole(t) - +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestPutClusterRole(t *testing.T) { var validClusterRole *rbacv1.ClusterRole @@ -1762,16 +1696,10 @@ func TestPutClusterRole(t *testing.T) { } // TestDeleteTridentClusterRole tests the DeleteTridentClusterRole function -// It checks the following cases: -// 1. GetClusterRolesByLabel fails -// 2. GetClusterRolesByLabel returns no cluster roles -// 3. GetClusterRolesByLabel succeeds but RemoveMultipleClusterRoles fails -// 4. GetClusterRolesByLabel succeeds and RemoveMultipleClusterRoles succeeds -// Parameters: -// t *testing.T - go test handler -// Example: -// TestDeleteTridentClusterRole(t) - +// It checks that the function returns the expected error when the k8s client returns an error +// It checks that the function returns nil when the k8s client does not return an error +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestDeleteTridentClusterRole(t *testing.T) { // arrange variables for the tests var emptyClusterRoleList, unwantedClusterRoles []rbacv1.ClusterRole @@ -1870,15 +1798,12 @@ func TestDeleteTridentClusterRole(t *testing.T) { } // TestRemoveMultipleClusterRoles tests the RemoveMultipleClusterRoles function -// It checks to see if the correct error is returned when the k8s client returns an error -// It also checks to see if the correct error is returned when the k8s client does not return an error -// Parameters: -// t *testing.T : go test helper -// Example: -// TestRemoveMultipleClusterRoles(t) -// Returns: -// nothing - +// It checks the following cases: +// 1. No cluster roles to delete +// 2. Error returned from k8s client +// 3. Valid cluster roles to delete +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestRemoveMultipleClusterRoles(t *testing.T) { // arrange variables for the tests var emptyClusterRoles, unwantedClusterRoles, undeletedClusterRoles []rbacv1.ClusterRole @@ -1960,15 +1885,12 @@ func TestRemoveMultipleClusterRoles(t *testing.T) { } // TestGetClusterRoleBindingInformation tests the GetClusterRoleBindingInformation function -// It checks for the following conditions: -// 1. k8s error -// 2. no cluster role binding found and no k8s error -// 3. valid current cluster role binding found and no k8s error -// Parameters: -// t *testing.T - go test handler -// Example: -// TestGetClusterRoleBindingInformation(t) - +// It checks the following cases: +// 1. Expect to fail with k8s error +// 2. Expect to pass with no cluster role binding found and no k8s error +// 3. Expect to pass with valid current cluster role binding found and no k8s error +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestGetClusterRoleBindingInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -2110,15 +2032,9 @@ func TestGetClusterRoleBindingInformation(t *testing.T) { } // TestPutClusterRoleBinding tests the PutClusterRoleBinding function -// It checks for error conditions and also for the correct patching of the ClusterRoleBinding -// Parameters: -// currentClusterRoleBinding: the current ClusterRoleBinding -// createClusterRoleBinding: whether to create or update the ClusterRoleBinding -// newClusterRoleBindingYAML: the new ClusterRoleBinding YAML -// appLabel: the app label to use for patching -// Example: -// TestPutClusterRoleBinding(t, nil, true, "", "trident") - +// It checks that the function returns the expected error +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestPutClusterRoleBinding(t *testing.T) { var validClusterRoleBinding *rbacv1.ClusterRoleBinding @@ -2264,13 +2180,12 @@ func TestPutClusterRoleBinding(t *testing.T) { } // TestDeleteTridentClusterRoleBinding tests the DeleteTridentClusterRoleBinding function -// It checks that the function returns the expected error -// Parameters: -// clusterRoleBindingName: the name of the cluster role binding to delete -// appLabel: the label of the cluster role bindings to delete -// Example: -// TestDeleteTridentClusterRoleBinding("clusterRoleBindingName", "appLabel") - +// It checks that the function returns an error when it is unable to get the list of cluster role bindings +// It checks that the function returns nil when it is able to get the list of cluster role bindings +// It checks that the function returns an error when it is unable to delete the cluster role bindings +// It checks that the function returns nil when it is able to delete the cluster role bindings +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestDeleteTridentClusterRoleBinding(t *testing.T) { // arrange variables for the tests var emptyClusterRoleBindingList, unwantedClusterRoleBindings []rbacv1.ClusterRoleBinding @@ -2370,14 +2285,11 @@ func TestDeleteTridentClusterRoleBinding(t *testing.T) { // TestRemoveMultipleClusterRoleBindings tests the RemoveMultipleClusterRoleBindings function // It checks the following cases: -// - no cluster role bindings -// - k8s call error -// - valid cluster role bindings -// Parameters: -// t *testing.T : go test helper -// Example: -// TestRemoveMultipleClusterRoleBindings(t *testing.T) - +// 1. No cluster role bindings +// 2. K8s call error +// 3. Valid cluster role bindings +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestRemoveMultipleClusterRoleBindings(t *testing.T) { // arrange variables for the tests var emptyClusterRoleBindings, unwantedClusterRoleBindings, undeletedClusterRoleBindings []rbacv1.ClusterRoleBinding @@ -2461,15 +2373,12 @@ func TestRemoveMultipleClusterRoleBindings(t *testing.T) { } // TestGetDaemonSetInformation tests the GetDaemonSetInformation function -// It checks the following cases: -// 1. Expect to fail with k8s error -// 2. Expect to pass with no daemonset found and no k8s error -// 3. Expect to pass with current daemonset found and no k8s error -// Parameters: -// t *testing.T : go test helper type -// Example: -// TestGetDaemonSetInformation(t *testing.T) - +// It checks for the following cases: +// 1. k8s error +// 2. no daemonset found +// 3. current daemonset found +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestGetDaemonSetInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -2603,17 +2512,10 @@ func TestGetDaemonSetInformation(t *testing.T) { } // TestPutDaemonSet tests the PutDaemonSet function -// It checks that the correct k8s client calls are made and that the correct errors are returned -// Parameters: -// currentDaemonSet: the current Trident DaemonSet -// createDaemonSet: whether or not to create a DaemonSet -// newDaemonSetYAML: the YAML for the new Trident DaemonSet -// nodeLabel: the label to use for the DaemonSet -// Expected Results: -// The correct k8s client calls are made and the correct errors are returned -// Example: -// TestPutDaemonSet(nil, true, "newDaemonSetYAML", "nodeLabel") - +// It checks that the function returns the expected error +// It also checks that the k8s client is called with the expected arguments +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestPutDaemonSet(t *testing.T) { daemonSetName := TridentCSILabel @@ -2762,13 +2664,11 @@ func TestPutDaemonSet(t *testing.T) { } // TestDeleteTridentDaemonSet tests the DeleteTridentDaemonSet function -// It checks that the function returns the expected error when the k8s client returns an error -// It also checks that the function returns nil when the k8s client returns no error -// Parameters: -// t *testing.T: go test helper -// Example: -// TestDeleteTridentDaemonSet(t) - +// It checks that the function returns the correct error when the k8s client +// returns an error. It also checks that the function returns nil when the +// k8s client returns a list of daemonsets and when it returns an empty list. +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestDeleteTridentDaemonSet(t *testing.T) { // arrange variables for the tests var emptyDaemonSetList, unwantedDaemonSets []appsv1.DaemonSet @@ -2852,13 +2752,12 @@ func TestDeleteTridentDaemonSet(t *testing.T) { } // TestRemoveMultipleDaemonSets tests the RemoveMultipleDaemonSets function -// It checks that the correct error is returned when the k8s client returns an error -// It also checks that the correct error is returned when the k8s client does not return an error -// Parameters: -// t *testing.T : go test helper -// Example: -// TestRemoveMultipleDaemonSets(t *testing.T) - +// It checks the following cases: +// - no daemonsets +// - k8s call error +// - valid daemonsets +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestRemoveMultipleDaemonSets(t *testing.T) { // arrange variables for the tests var emptyDaemonSets, unwantedDaemonSets []appsv1.DaemonSet @@ -2938,15 +2837,12 @@ func TestRemoveMultipleDaemonSets(t *testing.T) { } // TestGetDeploymentInformation tests the GetDeploymentInformation function -// It checks the following cases: -// - k8s error -// - no daemonset found -// - current daemonset found -// Parameters: -// t *testing.T - go testing object -// Example: -// TestGetDeploymentInformation(t) - +// It checks for the following conditions: +// 1. k8s error +// 2. no daemonset found +// 3. current daemonset found +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestGetDeploymentInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -3080,16 +2976,9 @@ func TestGetDeploymentInformation(t *testing.T) { } // TestPutDeployment tests the PutDeployment function -// It checks for the following: -// - creating a Deployment when one does not exist -// - updating a Deployment when one does exist -// - error handling -// Parameters: -// t *testing.T -// Example: -// t := &testing.T{} -// TestPutDeployment(t) - +// It checks that the correct k8s client calls are made and that the correct error is returned +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestPutDeployment(t *testing.T) { deploymentName := getDeploymentName(true) @@ -3240,12 +3129,13 @@ func TestPutDeployment(t *testing.T) { } // TestDeleteTridentDeployment tests the DeleteTridentDeployment function -// It checks that the function returns the expected error codes -// Parameters: -// t: the test object -// Example: -// TestDeleteTridentDeployment(t) - +// It checks the following cases: +// - when GetDeploymentsByLabel fails +// - when GetDeploymentsByLabel returns no deployments +// - when GetDeploymentsByLabel succeeds but RemoveMultipleDeployments fails +// - when GetDeploymentsByLabel succeeds and RemoveMultipleDeployments succeeds +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestDeleteTridentDeployment(t *testing.T) { // arrange variables for the tests var emptyDeploymentList, unwantedDeployments []appsv1.Deployment @@ -3329,15 +3219,12 @@ func TestDeleteTridentDeployment(t *testing.T) { } // TestRemoveMultipleDeployments tests the RemoveMultipleDeployments function -// It checks for the following cases: +// It checks for the following conditions: // 1. No deployments to remove -// 2. Error from k8s client call +// 2. Error returned from k8s client // 3. Valid deployments to remove -// Parameters: -// t *testing.T : go test handler -// Example: -// TestRemoveMultipleDeployments(t *testing.T) - +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestRemoveMultipleDeployments(t *testing.T) { // arrange variables for the tests var emptyDeploymentList, unwantedDeployments []appsv1.Deployment @@ -3418,16 +3305,11 @@ func TestRemoveMultipleDeployments(t *testing.T) { // TestGetPodSecurityPolicyInformation tests the GetPodSecurityPolicyInformation function // It checks the following cases: -// - k8s error -// - no pod security policies found -// - valid pod security policies found -// Parameters: -// t *testing.T -// Example: -// TestGetPodSecurityPolicyInformation(t) -// Returns: -// nil - +// 1. Expect to fail with k8s error +// 2. Expect to pass with no pod security policies found and no k8s error +// 3. Expect to pass with valid current pod security policies found and no k8s error +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestGetPodSecurityPolicyInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -3567,30 +3449,13 @@ func TestGetPodSecurityPolicyInformation(t *testing.T) { } // TestPutPodSecurityPolicy tests the PutPodSecurityPolicy function -// It checks that the correct k8s client calls are made and that the correct error is returned -// Parameters: -// currentPSP: the current PSP -// createPSP: whether to create a new PSP or update an existing one -// newPSPYAML: the YAML for the new PSP -// appLabel: the label to use for the PSP -// Expected results: -// err: the expected error -// Example: -// TestPutPodSecurityPolicy( -// &policyv1beta1.PodSecurityPolicy{ -// ObjectMeta: metav1.ObjectMeta{ -// Name: "trident", -// }, -// }, -// false, -// k8sclient.GetPrivilegedPodSecurityPolicyYAML( -// "trident", -// make(map[string]string), -// make(map[string]string), -// ), -// "trident", -// ) - +// It checks the following cases: +// 1. Create a PodSecurityPolicy and no k8s error occurs +// 2. Create a PodSecurityPolicy and a k8s error occurs +// 3. Update a PodSecurityPolicy and no k8s error occurs +// 4. Update a PodSecurityPolicy and a k8s error occurs +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestPutPodSecurityPolicy(t *testing.T) { pspName := getPSPName() @@ -3731,13 +3596,10 @@ func TestPutPodSecurityPolicy(t *testing.T) { // TestDeleteTridentPodSecurityPolicy tests the DeleteTridentPodSecurityPolicy function // It checks that the function returns the expected error when the k8s client returns an error // It checks that the function returns nil when the k8s client returns no policies -// It checks that the function returns the expected error when the k8s client returns policies but fails to delete them -// It checks that the function returns nil when the k8s client returns policies and deletes them successfully -// Parameters: -// t *testing.T - go test handler -// Example: -// TestDeleteTridentPodSecurityPolicy(t) - +// It checks that the function returns an error when the k8s client returns policies but fails to delete them +// It checks that the function returns nil when the k8s client returns policies and succeeds in deleting them +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestDeleteTridentPodSecurityPolicy(t *testing.T) { // arrange variables for the tests var emptyPSPList, unwantedPSPs []policyv1beta1.PodSecurityPolicy @@ -3836,13 +3698,12 @@ func TestDeleteTridentPodSecurityPolicy(t *testing.T) { } // TestRemoveMultiplePodSecurityPolicies tests the RemoveMultiplePodSecurityPolicies function -// It checks that the function returns the expected error when given a list of pod security policies -// It also checks that the function returns nil when given an empty list of pod security policies -// Parameters: -// t *testing.T - go test handler -// Example: -// TestRemoveMultiplePodSecurityPolicies(t) - +// It checks for the following conditions: +// - no pod security policies +// - k8s call error +// - valid pod security policies +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestRemoveMultiplePodSecurityPolicies(t *testing.T) { // arrange variables for the tests var emptyPodSecurityPolicyList, undeletedPodSecurityPolicies, unwantedPodSecurityPolicies []policyv1beta1.PodSecurityPolicy @@ -3925,13 +3786,12 @@ func TestRemoveMultiplePodSecurityPolicies(t *testing.T) { } // TestGetSecretInformation tests the GetSecretInformation function -// It checks to make sure that the function returns the correct values -// for the current secret, unwanted secrets, create secret, and error -// Parameters: -// t *testing.T: go testing object that manages the test lifecycle -// Example: -// TestGetSecretInformation(t) - +// It checks the following cases: +// - k8s error +// - no secrets found +// - valid secrets found +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestGetSecretInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -4075,18 +3935,13 @@ func TestGetSecretInformation(t *testing.T) { } } -// TestPutSecret tests the PutSecret method +// TestPutSecret tests the PutSecret function // It checks for the following conditions: // - createSecret is true and no k8s error occurs // - createSecret is false // - createSecret is true and a k8s error occurs -// Parameters: -// createSecret: true if the Secret should be created, false if it should be updated -// newSecretYAML: the YAML for the Secret to be created or updated -// secretName: the name of the Secret to be created or updated -// Example: -// TestPutSecret(true, secretYAML, "test-secret") - +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestPutSecret(t *testing.T) { secretName := getProtocolSecretName() @@ -4182,15 +4037,11 @@ func TestPutSecret(t *testing.T) { } // TestDeleteTridentSecret tests the DeleteTridentSecret function -// It checks that the function returns an error when the k8s client returns an error -// It checks that the function returns nil when the k8s client returns no secrets -// It checks that the function returns an error when the k8s client returns secrets but fails to delete them -// It checks that the function returns nil when the k8s client returns secrets and deletes them successfully -// Parameters: -// t *testing.T: go test helper -// Example: -// TestDeleteTridentSecret(t) - +// It checks that the function returns the correct error when +// GetSecretsByLabel fails, when GetSecretsByLabel returns no secrets, +// when DeleteSecret fails, and when DeleteSecret succeeds +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestDeleteTridentSecret(t *testing.T) { // arrange variables for the tests var emptySecretList, unwantedSecrets []corev1.Secret @@ -4298,13 +4149,12 @@ func TestDeleteTridentSecret(t *testing.T) { } // TestRemoveMultipleSecrets tests the RemoveMultipleSecrets function -// It checks that the function returns the correct error when the k8s client returns an error -// It also checks that the function returns nil when the k8s client does not return an error -// Parameters: -// t *testing.T : go test helper -// Example: -// TestRemoveMultipleSecrets(t) - +// It checks the following cases: +// 1. no secrets +// 2. k8s call error +// 3. valid secrets +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestRemoveMultipleSecrets(t *testing.T) { // arrange variables for the tests var emptySecretList, undeletedSecrets, unwantedSecrets []corev1.Secret @@ -4394,15 +4244,11 @@ func TestRemoveMultipleSecrets(t *testing.T) { // TestGetServiceInformation tests the GetServiceInformation function // It checks the following cases: -// - k8s error -// - no services found -// - valid current services found -// Parameters: -// - t: test object -// Example: -// - t := new(testing.T) -// - TestGetServiceInformation(t) - +// - Expect to fail with k8s error +// - Expect to pass with no services found and no k8s error +// - Expect to pass with valid current services found and no k8s error +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestGetServiceInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -4547,14 +4393,8 @@ func TestGetServiceInformation(t *testing.T) { // TestPutService tests the PutService function // It checks that the correct k8s client calls are made and that the correct errors are returned -// Parameters: -// currentService: the current service object -// createService: whether to create a new service or update an existing one -// newServiceYAML: the new service YAML -// appLabel: the app label -// Example: -// TestPutService(t, service, true, newServiceYAML, TridentCSILabel) - +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestPutService(t *testing.T) { serviceName := getServiceName() @@ -4695,14 +4535,12 @@ func TestPutService(t *testing.T) { } // TestDeleteTridentService tests the DeleteTridentService function -// It checks that the function returns the correct error when the -// k8s client returns an error, and that the function returns no error -// when the k8s client returns no error -// Parameters: -// t *testing.T : go test helper object -// Example: -// TestDeleteTridentService(t *testing.T) - +// It checks that the function returns the expected error when the k8s client returns an error +// It checks that the function returns nil when the k8s client returns no services +// It checks that the function returns an error when the k8s client returns services but fails to delete them +// It checks that the function returns nil when the k8s client returns services and successfully deletes them +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestDeleteTridentService(t *testing.T) { // arrange variables for the tests var emptyServiceList, unwantedServices []corev1.Service @@ -4811,14 +4649,10 @@ func TestDeleteTridentService(t *testing.T) { } // TestRemoveMultipleServices tests the RemoveMultipleServices function -// It checks that the function returns the correct error when the k8s client -// returns an error and that it returns nil when the k8s client does not return -// an error -// Parameters: -// t *testing.T : go test helper -// Example: -// TestRemoveMultipleServices(t) - +// It checks that the function returns the correct error code based on the +// input and the k8s client calls +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestRemoveMultipleServices(t *testing.T) { // arrange variables for the tests var emptyServiceList, unwantedServices []corev1.Service @@ -4902,11 +4736,8 @@ func TestRemoveMultipleServices(t *testing.T) { // 1. k8s error // 2. no service accounts found // 3. valid service accounts found -// Parameters: -// t *testing.T - go test framework object used for running the test -// Example: -// TestGetServiceAccountInformation(t *testing.T) - +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestGetServiceAccountInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -5074,16 +4905,9 @@ func TestGetServiceAccountInformation(t *testing.T) { } // TestPutServiceAccount tests the PutServiceAccount function -// It checks the following cases: -// - when creating a service account, it should return a new service account and no error -// - when creating a service account, it should return an error if a k8s error occurs -// - when updating a service account, it should return no new service account and no error -// - when updating a service account, it should return an error if a k8s error occurs -// Parameters: -// t *testing.T -// Example: -// TestPutServiceAccount(t) - +// It checks for errors and ensures that the correct k8s client calls are made +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestPutServiceAccount(t *testing.T) { serviceAccountName := getServiceAccountName(true) @@ -5248,14 +5072,12 @@ func TestPutServiceAccount(t *testing.T) { } // TestDeleteTridentServiceAccount tests the DeleteTridentServiceAccount function -// It checks that the function returns the expected error when the k8s client -// returns an error and that it returns nil when the k8s client does not return -// an error -// Parameters: -// t *testing.T: go testing framework object used to control test flow -// Example: -// TestDeleteTridentServiceAccount(t) - +// It checks the following cases: +// - when GetServiceAccountsByLabel fails +// - when GetServiceAccountsByLabel succeeds but RemoveMultipleServiceAccounts fails +// - when GetServiceAccountsByLabel succeeds and RemoveMultipleServiceAccounts succeeds +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestDeleteTridentServiceAccount(t *testing.T) { // arrange variables for the tests var emptyServiceAccountList, unwantedServiceAccounts []corev1.ServiceAccount @@ -5364,13 +5186,10 @@ func TestDeleteTridentServiceAccount(t *testing.T) { } // TestRemoveMultipleServiceAccounts tests the RemoveMultipleServiceAccounts function -// It checks that the function returns the correct error codes and that the correct -// k8s calls are made -// Parameters: -// t *testing.T : go test handler -// Example: -// TestRemoveMultipleServiceAccounts(t *testing.T) - +// It checks that the function returns the correct error when the k8s client returns an error +// It also checks that the function returns nil when the k8s client does not return an error +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestRemoveMultipleServiceAccounts(t *testing.T) { // arrange variables for the tests var emptyServiceAccountList, undeletedServiceAccounts, unwantedServiceAccounts []corev1.ServiceAccount @@ -5458,17 +5277,14 @@ func TestRemoveMultipleServiceAccounts(t *testing.T) { } } -// TestGetTridentOpenShiftSCCInformation tests the GetTridentOpenShiftSCCInformation function -// It checks the following cases: +// TestGetTridentOpenShiftSCCInformation tests the GetTridentOpenShiftSCCInformation method +// It checks that the method returns the correct values for the following scenarios: // - k8s error // - no openshift scc found, no k8s error, and an scc user does not exist // - no openshift scc found, no k8s error, and a it should update // - valid current services found and no k8s error -// Parameters: -// t *testing.T: the test object -// Example: -// TestGetTridentOpenShiftSCCInformation(t *testing.T) - +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestGetTridentOpenShiftSCCInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var name, username string @@ -5615,15 +5431,9 @@ func TestGetTridentOpenShiftSCCInformation(t *testing.T) { } // TestExecPodForVersionInformation tests the ExecPodForVersionInformation function -// It checks the following cases: -// - no supplied cmd to exec -// - k8s error when exec the supplied cmd -// - no error when exec the supplied cmd -// Parameters: -// t *testing.T - go test handler -// Example: -// TestExecPodForVersionInformation(t *testing.T) - +// It checks that the function returns the expected error and output +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestExecPodForVersionInformation(t *testing.T) { podName := "trident-transient-pod" @@ -5719,22 +5529,10 @@ func TestExecPodForVersionInformation(t *testing.T) { } // TestGetCSISnapshotterVersion tests the GetCSISnapshotterVersion function -// It checks the following cases: -// 1. When the deployment is empty, it should return the snapshot CRD version -// 2. When the deployment has a snapshotter container with a version tag, it should return the snapshot CRD version -// 3. When the deployment has a snapshotter container without a version tag, it should return an empty string -// Parameters: -// deployment: The deployment to check -// Returns: -// string: The snapshot CRD version -// Example: -// snapshotCRDName := GetCSISnapshotterVersion(deployment) -// if snapshotCRDName == "" { -// fmt.Println("Snapshot CRD name is empty") -// } else { -// fmt.Println("Snapshot CRD name is: " + snapshotCRDName) -// } - +// It checks that the correct snapshot crd version is returned based on the deployment +// and the snapshot crd version +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestGetCSISnapshotterVersion(t *testing.T) { var emptyDeployment, validDeployment, invalidDeployment *appsv1.Deployment @@ -5817,17 +5615,13 @@ func TestGetCSISnapshotterVersion(t *testing.T) { } // TestDeleteTridentStatefulSet tests the DeleteTridentStatefulSet function -// It checks that the correct error is returned when the k8s client returns an error -// It also checks that the correct error is returned when the k8s client returns no statefulsets -// It also checks that the correct error is returned when the k8s client returns statefulsets but -// the delete fails -// It also checks that no error is returned when the k8s client returns statefulsets and -// the delete succeeds -// Parameters: -// t *testing.T -// Example: -// TestDeleteTridentStatefulSet(t) - +// It checks for the following conditions: +// 1. GetStatefulSetsByLabel fails +// 2. GetStatefulSetsByLabel returns no statefulsets +// 3. GetStatefulSetsByLabel succeeds but RemoveMultipleStatefulSets fails +// 4. GetStatefulSetsByLabel succeeds and RemoveMultipleStatefulSets succeeds +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestDeleteTridentStatefulSet(t *testing.T) { // arrange variables for the tests var emptyStatefulSets, unwantedStatefulSets []appsv1.StatefulSet @@ -5912,35 +5706,14 @@ func TestDeleteTridentStatefulSet(t *testing.T) { // TestPutOpenShiftSCC tests the PutOpenShiftSCC function // It checks the following cases: -// - create OpenShift SCCs and no k8s error occurs when removing Trident users from OpenShiftSCC -// - create OpenShift SCCs and a k8s error occurs when removing Trident users from OpenShiftSCC -// - create OpenShift SCCs and no k8s error occurs -// - create OpenShift SCCs and a k8s error occurs -// - update OpenShift SCCs and no k8s error occurs -// - update OpenShift SCCs and a k8s error occurs -// Parameters: -// currentOpenShiftSCCJSON: the current OpenShift SCC in JSON format -// createOpenShiftSCC: whether to create or update the OpenShift SCC -// newOpenShiftSCCYAML: the new OpenShift SCC in YAML format -// Example: -// currentOpenShiftSCCJSON, err := yaml.YAMLToJSON([]byte(k8sclient.GetOpenShiftSCCYAML( -// openShiftSCCUserName+"old", -// openShiftSCCName+"old", -// "trident", -// make(map[string]string), -// make(map[string]string)), -// )) -// if err != nil { -// t.Fatal("GetOpenShiftSCCYAML() returned invalid YAML") -// } -// newOpenShiftSCCYAML := k8sclient.GetOpenShiftSCCYAML( -// openShiftSCCUserName, -// openShiftSCCName, -// "trident", -// make(map[string]string), -// make(map[string]string)) -// err = extendedK8sClient.PutOpenShiftSCC(currentOpenShiftSCCJSON, createOpenShiftSCC, newOpenShiftSCCYAML) - +// 1. create OpenShift SCCs and no k8s error occurs when removing Trident users from OpenShiftSCC +// 2. create OpenShift SCCs and a k8s error occurs when removing Trident users from OpenShiftSCC +// 3. create OpenShift SCCs and no k8s error occurs +// 4. create OpenShift SCCs and a k8s error occurs +// 5. update OpenShift SCCs and no k8s error occurs +// 6. update OpenShift SCCs and a k8s error occurs +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestPutOpenShiftSCC(t *testing.T) { // arrange variables for the tests openShiftSCCUserName := getOpenShiftSCCUserName() @@ -6135,15 +5908,12 @@ func TestPutOpenShiftSCC(t *testing.T) { } // TestDeleteOpenShiftSCC tests the DeleteOpenShiftSCC function -// It checks the following cases: -// 1. GetOpenShiftSCCByName fails -// 2. GetOpenShiftSCCByName succeeds but DeleteObjectByYAML fails -// 3. GetOpenShiftSCCByName succeeds and RemoveTridentUserFromOpenShiftSCC is called -// Parameters: -// t *testing.T - the test object -// Example: -// TestDeleteOpenShiftSCC(t *testing.T) - +// It checks the following: +// - when GetOpenShiftSCCByName fails +// - when GetOpenShiftSCCByName succeeds but DeleteObjectByYAML fails +// - when GetOpenShiftSCCByName succeeds and RemoveTridentUserFromOpenShiftSCC is called +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestDeleteOpenShiftSCC(t *testing.T) { // arrange variables for the tests openShiftSCCName := "trident" @@ -6239,14 +6009,11 @@ func TestDeleteOpenShiftSCC(t *testing.T) { // TestRemoveMultiplePods tests the RemoveMultiplePods function // It checks the following cases: -// - no pods to delete -// - k8s call error -// - valid pods -// Parameters: -// t *testing.T : go test framework object -// Example: -// TestRemoveMultiplePods(t) - +// 1. no pods +// 2. k8s call error +// 3. valid pods +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestRemoveMultiplePods(t *testing.T) { // arrange variables for the tests var emptyPodList, undeletedPods, unwantedPods []corev1.Pod @@ -6335,15 +6102,12 @@ func TestRemoveMultiplePods(t *testing.T) { } // TestRemoveMultipleStatefulSets tests the RemoveMultipleStatefulSets function -// It checks the following cases: -// 1. No stateful sets to remove -// 2. Error from k8s call -// 3. Successful removal of stateful sets -// Parameters: -// t *testing.T : go test helper -// Example: -// TestRemoveMultipleStatefulSets(t) - +// It checks for the following cases: +// 1. No stateful sets are passed in +// 2. A k8s call error occurs +// 3. Valid stateful sets are passed in +// +// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- func TestRemoveMultipleStatefulSets(t *testing.T) { // arrange variables for the tests var emptyStatefulSetList, unwantedStatefulSets []appsv1.StatefulSet diff --git a/operator/controllers/orchestrator/installer/uninstaller.go b/operator/controllers/orchestrator/installer/uninstaller.go index 4fd8be595..3ca3b1b57 100644 --- a/operator/controllers/orchestrator/installer/uninstaller.go +++ b/operator/controllers/orchestrator/installer/uninstaller.go @@ -12,13 +12,16 @@ import ( ) // UninstallTrident uninstalls Trident from the Kubernetes cluster. -// It returns an error if the uninstallation fails. +// It returns an error if Trident is not installed. +// Returns: +// - error if Trident is not installed or if an error occurs during uninstall // Example: -// err := installer.UninstallTrident() -// if err != nil { -// log.Errorf("Could not uninstall Trident: %v", err) -// } - +// err := installer.UninstallTrident() +// if err != nil { +// fmt.Println(err) +// } +// +// -- Doc autogenerated on 2022-05-12 19:02:27.838010 -- func (i *Installer) UninstallTrident() error { // 1. preview CSI Trident --> uninstall preview CSI Trident @@ -116,13 +119,13 @@ func (i *Installer) UninstallTrident() error { } // UninstallCSIPreviewTrident uninstalls Trident CSI Preview -// It returns an error if the uninstall fails. +// It returns an error if the uninstall fails +// Returns: +// error: nil if uninstall was successful, otherwise an error object // Example: -// err := installer.UninstallCSIPreviewTrident() -// if err != nil { -// panic(err) -// } - +// err := installer.UninstallCSIPreviewTrident() +// +// -- Doc autogenerated on 2022-05-12 19:02:27.838010 -- func (i *Installer) UninstallCSIPreviewTrident() error { appLabel = TridentCSILabel appLabelKey = TridentCSILabelKey @@ -133,9 +136,12 @@ func (i *Installer) UninstallCSIPreviewTrident() error { // UninstallLegacyTrident uninstalls legacy Trident // It returns an error if the uninstall fails. +// Returns: +// error - error if uninstall fails // Example: // err := installer.UninstallLegacyTrident() - +// +// -- Doc autogenerated on 2022-05-12 19:02:27.838010 -- func (i *Installer) UninstallLegacyTrident() error { appLabel = TridentLegacyLabel appLabelKey = TridentLegacyLabelKey @@ -180,14 +186,15 @@ func (i *Installer) removeRBACObjects(csi bool) error { return nil } +func (i *Installer) ObliviateCRDs() error { // ObliviateCRDs removes all Trident CRDs from the cluster. // It returns an error if the CRDs cannot be removed. +// Returns: +// error - if the CRDs cannot be removed // Example: // err := installer.ObliviateCRDs() -// if err != nil { -// log.Fatalf("Could not remove Trident CRDs: %v", err) -// } - +// +// -- Doc autogenerated on 2022-05-12 19:02:27.838010 -- func (i *Installer) ObliviateCRDs() error { return cmd.ObliviateCRDs(i.client, i.tridentCRDClient, k8sTimeout) } diff --git a/operator/controllers/orchestrator/installer/utils.go b/operator/controllers/orchestrator/installer/utils.go index 1ba9e3a96..e2efac2ce 100644 --- a/operator/controllers/orchestrator/installer/utils.go +++ b/operator/controllers/orchestrator/installer/utils.go @@ -2,12 +2,14 @@ package installer // getServiceAccountName returns the name of the service account to use for Trident // Parameters: -// csi - if true, use the Trident CSI service account name; otherwise, use the legacy Trident service account name +// csi - if true, use the CSI service account name +// Returns: +// the service account name // Example: // getServiceAccountName(true) -// Returns: -// string - the service account name to use for Trident - +// Returns: "trident-csi" +// +// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- func getServiceAccountName(csi bool) string { if csi { return TridentCSI @@ -16,14 +18,15 @@ func getServiceAccountName(csi bool) string { } } -// getClusterRoleName returns the name of the cluster role to use for the given CSI flag +// getClusterRoleName returns the name of the cluster role to use for Trident // Parameters: -// csi - true if Trident should use the CSI driver -// Returns: -// string - the name of the cluster role to use +// csi - whether to use the CSI driver +// Return: +// string - the name of the cluster role // Example: -// name := getClusterRoleName(true) - +// getClusterRoleName(true) +// +// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- func getClusterRoleName(csi bool) string { if csi { return TridentCSI @@ -34,11 +37,13 @@ func getClusterRoleName(csi bool) string { // getClusterRoleBindingName returns the name of the cluster role binding to use // Parameters: -// csi - true if Trident should use the CSI driver +// csi - true if Trident should be installed as a CSI driver +// Returns: +// string - the name of the cluster role binding to use // Example: -// getClusterRoleBindingName(true) -// returns "trident-csi" - +// name := getClusterRoleBindingName(csi) +// +// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- func getClusterRoleBindingName(csi bool) string { if csi { return TridentCSI @@ -47,50 +52,62 @@ func getClusterRoleBindingName(csi bool) string { } } -// getPSPName returns the name of the PSP to use for Trident +// getPSPName returns the name of the PSP to be used for Trident +// Returns: +// string: the name of the PSP to be used for Trident // Example: -// trident-psp - +// pspName := getPSPName() +// +// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- func getPSPName() string { return TridentPSP } // getServiceName returns the name of the service +// Returns: +// string: service name // Example: -// kubectl get service -// NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -// trident-csi NodePort 10.100.200.1 8080/TCP 1d - +// name := getServiceName() +// +// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- func getServiceName() string { return TridentCSI } // getProtocolSecretName returns the name of the secret that contains the protocol -// information for the Trident CSI driver. +// for the CSI driver. +// Returns: +// string: the name of the secret // Example: -// trident-csi-secret - +// getProtocolSecretName() +// => "trident-csi-secret" +// +// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- func getProtocolSecretName() string { return TridentCSI } -// getEncryptionSecretName returns the name of the encryption secret +// getEncryptionSecretName returns the name of the secret that contains the encryption keys +// Returns: +// string: name of the secret // Example: -// getEncryptionSecretName() -// -> "trident-encryption-keys" - +// name := getEncryptionSecretName() +// +// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- func getEncryptionSecretName() string { return TridentEncryptionKeys } // getDeploymentName returns the name of the Trident deployment // Parameters: -// csi - true if the deployment is for the CSI driver +// csi - true if Trident is being deployed as a CSI driver // Returns: // string - the name of the Trident deployment // Example: -// deploymentName := getDeploymentName(true) - +// getDeploymentName(true) -> "trident-csi" +// getDeploymentName(false) -> "trident" +// +// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- func getDeploymentName(csi bool) string { if csi { return TridentCSI @@ -100,27 +117,35 @@ func getDeploymentName(csi bool) string { } // getDaemonSetName returns the name of the Trident CSI DaemonSet. +// Returns: +// string: The name of the Trident CSI DaemonSet. // Example: -// - trident-csi - +// getDaemonSetName() +// +// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- func getDaemonSetName() string { return TridentCSI } // getCSIDriverName returns the name of the CSI driver +// Returns: +// string: CSI driver name // Example: -// getCSIDriverName() returns "trident" - +// name := getCSIDriverName() +// +// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- func getCSIDriverName() string { return CSIDriver } -// getOpenShiftSCCUserName returns the name of the SCC user that Trident should be -// added to. +// getOpenShiftSCCUserName returns the name of the OpenShift SCC user +// Returns: +// TridentCSI - if Trident is deployed as a CSI driver +// TridentLegacy - if Trident is deployed as a FlexVolume driver // Example: -// TridentCSI -// TridentLegacy - +// getOpenShiftSCCUserName() -> "trident-csi" +// +// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- func getOpenShiftSCCUserName() string { if csi { return TridentCSI @@ -130,9 +155,12 @@ func getOpenShiftSCCUserName() string { } // getOpenShiftSCCName returns the name of the OpenShift SCC +// Returns: +// string - name of the OpenShift SCC // Example: -// getOpenShiftSCCName() -> "privileged" - +// name := getOpenShiftSCCName() +// +// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- func getOpenShiftSCCName() string { return OpenShiftSCCName } diff --git a/operator/controllers/provisioner/apis/netapp/v1/register.go b/operator/controllers/provisioner/apis/netapp/v1/register.go index ce9b955f1..e4da6b8c3 100644 --- a/operator/controllers/provisioner/apis/netapp/v1/register.go +++ b/operator/controllers/provisioner/apis/netapp/v1/register.go @@ -21,6 +21,7 @@ func Kind(kind string) schema.GroupKind { // Resource takes an unqualified resource and returns back a Group qualified GroupResource func Resource(resource string) schema.GroupResource { +func Kind(kind string) schema.GroupKind { return SchemeGroupVersion.WithResource(resource).GroupResource() } @@ -30,17 +31,22 @@ var ( ) // Adds the list of known types to the given scheme. +func addKnownTypes(scheme *runtime.Scheme) error { // addKnownTypes adds the set of types defined in this +// It returns the SchemeBuilder // Parameters: -// scheme *runtime.Scheme -// +// scheme *runtime.Scheme +// builder *runtime.SchemeBuilder +// config *rest.Config +// codecs serializer.CodecFactory +// options *generic.StoreOptions +// openAPIConfig *openapi.Config // Returns: -// error -// -// It returns an error if there was an issue with adding the types. +// *runtime.SchemeBuilder // Example: -// addKnownTypes(s) - +// addKnownTypes(scheme) +// +// -- Doc autogenerated on 2022-05-12 19:06:33.514412 -- func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &TridentProvisioner{}, diff --git a/operator/controllers/provisioner/client/clientset/versioned/fake/clientset_generated.go b/operator/controllers/provisioner/client/clientset/versioned/fake/clientset_generated.go index 164d56e68..5179fa978 100644 --- a/operator/controllers/provisioner/client/clientset/versioned/fake/clientset_generated.go +++ b/operator/controllers/provisioner/client/clientset/versioned/fake/clientset_generated.go @@ -52,27 +52,31 @@ type Clientset struct { tracker testing.ObjectTracker } +func (c *Clientset) Discovery() discovery.DiscoveryInterface { // Discovery retrieves the DiscoveryClient -// It returns a fake DiscoveryClient +// It returns a fake implementation of the discovery client +// Returns: +// *discovery.DiscoveryClient // Example: // clientset := fake.NewSimpleClientset() -// clientset.Discovery().RESTClient() - +// discoveryClient := clientset.Discovery() +// +// -- Doc autogenerated on 2022-05-12 19:06:58.435680 -- func (c *Clientset) Discovery() discovery.DiscoveryInterface { return c.discovery } -// Tracker is a fake implementation of the Tracker interface -type Tracker struct { - objects map[string]interface{} -} - -// NewTracker returns a new Tracker -// It returns a pointer to the Tracker +// Tracker is a fake implementation of the Tracker interface. +// It returns fake objects. +// Returns: +// * fake.Clientset +// * fake.Tracker +// * fake.Tracker // Example: -// tracker := NewTracker() -// tracker.Add("foo", "bar") - +// cs := fake.NewSimpleClientset() +// cs.Tracker() +// +// -- Doc autogenerated on 2022-05-12 19:06:58.435680 -- func (c *Clientset) Tracker() testing.ObjectTracker { return c.tracker } diff --git a/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go b/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go index 18dc72689..31ca3e820 100644 --- a/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go +++ b/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go @@ -14,17 +14,16 @@ type FakeTridentV1 struct { *testing.Fake } -// TridentProvisioners implements TridentProvisionerInterface -type FakeTridentProvisioners struct { - *FakeTridentV1 - namespace string -} +// TridentProvisioners returns a TridentProvisionerInterface. // Parameters: -// namespace - name of the Namespace -// It returns a TridentProvisionerInterface +// namespace - namespace of the TridentProvisionerInterface. +// Returns: +// TridentProvisionerInterface // Example: -// tridentProvisioners, err := client.TridentV1().TridentProvisioners("default") - +// kubeClient := fake.NewSimpleClientset() +// tridentProvisioners := kubeClient.TridentV1().TridentProvisioners("default") +// +// -- Doc autogenerated on 2022-05-12 19:08:18.384280 -- func (c *FakeTridentV1) TridentProvisioners(namespace string) v1.TridentProvisionerInterface { return &FakeTridentProvisioners{c, namespace} } diff --git a/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/netapp_client.go b/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/netapp_client.go index 464fdd9aa..f26d95afb 100644 --- a/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/netapp_client.go +++ b/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/netapp_client.go @@ -21,11 +21,15 @@ type TridentV1Client struct { } // TridentProvisioners returns a TridentProvisionerInterface. +// A group's client should implement this interface. // Parameters: -// namespace - the namespace where Trident is installed +// namespace: the namespace to use +// Returns: +// TridentProvisionerInterface: the TridentProvisionerInterface // Example: -// tridentProvisioners := tridentV1Client.TridentProvisioners("trident") - +// tridentProvisioners := c.TridentV1().TridentProvisioners("default") +// +// -- Doc autogenerated on 2022-05-12 19:07:44.790566 -- func (c *TridentV1Client) TridentProvisioners(namespace string) TridentProvisionerInterface { return newTridentProvisioners(c, namespace) } @@ -46,6 +50,7 @@ func NewForConfig(c *rest.Config) (*TridentV1Client, error) { // NewForConfigOrDie creates a new TridentV1Client for the given config and // panics if there is an error in the config. func NewForConfigOrDie(c *rest.Config) *TridentV1Client { +func NewForConfig(c *rest.Config) (*TridentV1Client, error) { client, err := NewForConfig(c) if err != nil { panic(err) @@ -55,20 +60,25 @@ func NewForConfigOrDie(c *rest.Config) *TridentV1Client { // New creates a new TridentV1Client for the given RESTClient. func New(c rest.Interface) *TridentV1Client { +func NewForConfigOrDie(c *rest.Config) *TridentV1Client { return &TridentV1Client{c} } +func setConfigDefaults(config *rest.Config) error { // setConfigDefaults sets the default values for the provided config +// It returns an error if the config is invalid // Parameters: -// config - config to set defaults on -// It returns an error if the config is nil +// config: the config to set defaults on +// Returns: +// error: an error if the config is invalid // Example: -// config := k8sclient.NewConfig() -// err := setConfigDefaults(config) -// if err != nil { -// // handle error -// } - +// config := &rest.Config{} +// err := setConfigDefaults(config) +// if err != nil { +// log.Fatal(err) +// } +// +// -- Doc autogenerated on 2022-05-12 19:07:44.790566 -- func setConfigDefaults(config *rest.Config) error { gv := v1.SchemeGroupVersion config.GroupVersion = &gv diff --git a/operator/controllers/provisioner/client/informers/externalversions/factory.go b/operator/controllers/provisioner/client/informers/externalversions/factory.go index f88a9e68f..10c13974d 100644 --- a/operator/controllers/provisioner/client/informers/externalversions/factory.go +++ b/operator/controllers/provisioner/client/informers/externalversions/factory.go @@ -47,6 +47,7 @@ func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInfo // WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { return func(factory *sharedInformerFactory) *sharedInformerFactory { factory.tweakListOptions = tweakListOptions return factory @@ -55,6 +56,7 @@ func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFu // WithNamespace limits the SharedInformerFactory to the specified namespace. func WithNamespace(namespace string) SharedInformerOption { +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { return func(factory *sharedInformerFactory) *sharedInformerFactory { factory.namespace = namespace return factory @@ -63,6 +65,7 @@ func WithNamespace(namespace string) SharedInformerOption { // NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { +func WithNamespace(namespace string) SharedInformerOption { return NewSharedInformerFactoryWithOptions(client, defaultResync) } @@ -71,11 +74,13 @@ func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Dur // as specified here. // Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { +func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) } // NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { +func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { factory := &sharedInformerFactory{ client: client, namespace: v1.NamespaceAll, @@ -95,6 +100,7 @@ func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResy // Start initializes all requested informers. func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { f.lock.Lock() defer f.lock.Unlock() @@ -108,6 +114,7 @@ func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { // WaitForCacheSync waits for all started informers' cache were synced. func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { +func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { informers := func() map[reflect.Type]cache.SharedIndexInformer { f.lock.Lock() defer f.lock.Unlock() @@ -130,29 +137,19 @@ func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[ref // InternalInformerFor returns the SharedIndexInformer for obj using an internal // client. -// InformerFor is the same as InformerFor without the lock. +func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { +// InformerFor is the same as InformerFor without the object +// It returns a SharedIndexInformer instead of an Interface. +// A SharedIndexInformer uses the Indexer internally. +// Therefore, lister is not needed (can be nil). // Parameters: -// obj - the object type to register the informer for -// newFunc - a function that returns a new informer for the given type -// resyncPeriod - resync period for the informer -// It returns the registered SharedIndexInformer for the given type. +// obj - the object +// Returns: +// a SharedIndexInformer // Example: -// lister := factory.InformerFor(&v1.Pod{}, func(client kubernetes.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { -// return cache.NewSharedIndexInformer( -// &cache.ListWatch{ -// ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { -// return client.CoreV1().Pods(metav1.NamespaceAll).List(options) -// }, -// WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { -// return client.CoreV1().Pods(metav1.NamespaceAll).Watch(options) -// }, -// }, -// &v1.Pod{}, -// resyncPeriod, -// cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, -// ) -// }, 0) - +// informer := factory.InformerFor(&v1.Pod{}, newPodInformer) +// +// -- Doc autogenerated on 2022-05-12 19:08:37.248494 -- func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { f.lock.Lock() defer f.lock.Unlock() @@ -185,10 +182,17 @@ type SharedInformerFactory interface { } // Trident returns a new Interface. +// Returns: +// - a new Interface +// - error if there is an error initializing the client // Example: -// f := externalversions.NewSharedInformerFactory(cSharedClient, resyncPeriod) -// i := f.Trident().V1alpha1().Tridents() - +// c, err := externalversions.NewForConfig(&config) +// if err != nil { +// return nil, err +// } +// return c.Trident() +// +// -- Doc autogenerated on 2022-05-12 19:08:37.248494 -- func (f *sharedInformerFactory) Trident() netapp.Interface { return netapp.New(f, f.namespace, f.tweakListOptions) } diff --git a/operator/controllers/provisioner/client/informers/externalversions/netapp/v1/tridentprovisioner.go b/operator/controllers/provisioner/client/informers/externalversions/netapp/v1/tridentprovisioner.go index 1587fbca3..676bec428 100644 --- a/operator/controllers/provisioner/client/informers/externalversions/netapp/v1/tridentprovisioner.go +++ b/operator/controllers/provisioner/client/informers/externalversions/netapp/v1/tridentprovisioner.go @@ -42,6 +42,7 @@ func NewTridentProvisionerInformer(client versioned.Interface, namespace string, // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. func NewFilteredTridentProvisionerInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { +func NewTridentProvisionerInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { return cache.NewSharedIndexInformer( &cache.ListWatch{ ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { @@ -63,74 +64,46 @@ func NewFilteredTridentProvisionerInformer(client versioned.Interface, namespace ) } -// defaultInformer is used to informer for TridentProvisioner types. -type tridentProvisionerInformer struct { - factory internalinterfaces.SharedInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc - namespace string -} - -// NewTridentProvisionerInformer constructs a new informer for TridentProvisioner type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. +func (f *tridentProvisionerInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { +// defaultInformer is +// It returns a SharedIndexInformer // Parameters: -// namespace: The namespace of the TridentProvisioner. -// resyncPeriod: The resync period to use for this informer. -// tweakListOptions: The tweak list options for this informer. -// It returns a new informer for TridentProvisioner type. +// client - the kubernetes client +// resyncPeriod - the resync period +// indexers - the indexers +// Returns: +// a SharedIndexInformer // Example: -// // create the informer for TridentProvisioner -// informer := v1.NewTridentProvisionerInformer( -// kubeClient, -// resyncPeriod, -// cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, -// ) - +// defaultInformer(kubernetes.NewForConfig(config), time.Duration(0 * time.Second), cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) +// +// -- Doc autogenerated on 2022-05-12 19:09:28.836842 -- func (f *tridentProvisionerInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { return NewFilteredTridentProvisionerInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) } -// Informer is used to fetch and store TridentProvisioner objects from the API server. -type TridentProvisionerInformer interface { - Informer() cache.SharedIndexInformer - Lister() *TridentProvisionerLister -} - -type tridentProvisionerInformer struct { - factory internalinterfaces.SharedInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc - namespace string -} - -// NewTridentProvisionerInformer constructs a new informer for TridentProvisioner type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -// It returns a TridentProvisionerInformer. +// Informer is used to inform about resources. +// It returns a cache.SharedIndexInformer. +// Returns: +// A cache.SharedIndexInformer // Example: -// // obtain a shared informer for the deployment object -// deploymentInformer := NewTridentProvisionerInformer(client, namespace) -// // obtain a shared informer for the pod object -// podInformer := NewTridentProvisionerInformer(client, namespace) - +// informer := f.TridentInformer().TridentProvisioner().Informer() +// indexer := informer.GetIndexer() +// indexer.Add(&netappv1.TridentProvisioner{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}) +// obj, exists, err := indexer.GetByKey("foo") +// +// -- Doc autogenerated on 2022-05-12 19:09:28.836842 -- func (f *tridentProvisionerInformer) Informer() cache.SharedIndexInformer { return f.factory.InformerFor(&netappv1.TridentProvisioner{}, f.defaultInformer) } // Lister implements the TridentProvisionerLister interface. -type tridentProvisionerInformer struct { - factory InternalInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc -} - -// NewTridentProvisionerInformer constructs a new informer for TridentProvisioner type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -// It returns a TridentProvisionerInformer. +// It returns TridentProvisionerLister. +// Returns: +// * TridentProvisionerLister // Example: -// lis, err := factory.NetAppV1().TridentProvisioners().Lister() -// ... -// lis.List(namespace).Items - +// lister := listers.NewTridentProvisionerLister(indexer) +// +// -- Doc autogenerated on 2022-05-12 19:09:28.836842 -- func (f *tridentProvisionerInformer) Lister() v1.TridentProvisionerLister { return v1.NewTridentProvisionerLister(f.Informer().GetIndexer()) } From 1f41c3710d1ef3888dc9d64a2629a335a5c53b8f Mon Sep 17 00:00:00 2001 From: "Roussin, Jerome" Date: Thu, 12 May 2022 21:30:29 -0400 Subject: [PATCH 5/5] One more bug --- core/core_test.go | 7 +- core/orchestrator_core.go | 1052 ++++++++--------- core/orchestrator_core_test.go | 678 ++++++----- core/transaction_monitor_test.go | 57 +- .../orchestrator/apis/netapp/v1/register.go | 13 +- .../orchestrator/apis/netapp/v1/types.go | 20 +- .../versioned/fake/clientset_generated.go | 24 +- .../netapp/v1/fake/fake_netapp_client.go | 6 +- .../typed/netapp/v1/netapp_client.go | 27 +- .../informers/externalversions/factory.go | 51 +- .../netapp/v1/tridentorchestrator.go | 32 +- .../controllers/orchestrator/controller.go | 187 ++- .../orchestrator/installer/installer.go | 303 +++-- .../orchestrator/installer/installer_test.go | 35 +- .../orchestrator/installer/k8s_client_test.go | 485 ++++---- .../orchestrator/installer/uninstaller.go | 40 +- .../orchestrator/installer/utils.go | 95 +- .../provisioner/apis/netapp/v1/register.go | 18 +- .../versioned/fake/clientset_generated.go | 27 +- .../netapp/v1/fake/fake_netapp_client.go | 14 +- .../typed/netapp/v1/netapp_client.go | 22 +- .../informers/externalversions/factory.go | 38 +- .../netapp/v1/tridentprovisioner.go | 41 +- 23 files changed, 1590 insertions(+), 1682 deletions(-) diff --git a/core/core_test.go b/core/core_test.go index bde9af169..ae48639ed 100644 --- a/core/core_test.go +++ b/core/core_test.go @@ -10,11 +10,10 @@ import ( log "github.com/sirupsen/logrus" ) -// TestMain is the entry point for all unit tests -// It checks for the environment variable TRACE and if set, -// enables debug logging. +// TestMain is the main entry point for tests +// It checks for a test config file and sets up the test environment // -// -- Doc autogenerated on 2022-05-12 17:31:05.128674 -- +// -- Doc autogenerated on 2022-05-12 20:34:20.021163 -- func TestMain(m *testing.M) { // Disable any standard log output log.SetOutput(ioutil.Discard) diff --git a/core/orchestrator_core.go b/core/orchestrator_core.go index 99b04aa27..e57b95878 100644 --- a/core/orchestrator_core.go +++ b/core/orchestrator_core.go @@ -54,18 +54,17 @@ func recordTiming(operation string, err *error) func() { } } -func recordTransactionTiming(txn *storage.VolumeTransaction, err *error) { -// recordTransactionTiming records the time it took to complete a transaction -// to the operationDurationInMsSummary metric. +// recordTransactionTiming records the time taken for a transaction to complete +// to a prometheus summary. // Parameters: -// txn: the transaction +// txn: the transaction to record // err: the error returned by the transaction // Returns: // None // Example: // recordTransactionTiming(txn, &err) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func recordTransactionTiming(txn *storage.VolumeTransaction, err *error) { if txn == nil || txn.VolumeCreatingConfig == nil { // for unit tests, there will be no txn to record @@ -120,20 +119,20 @@ func NewTridentOrchestrator(client persistentstore.Client) *TridentOrchestrator } } -func (o *TridentOrchestrator) transformPersistentState(ctx context.Context) error { -// transformPersistentState transforms the persistent state to the current version. +// transformPersistentState transforms the persistent state from the previous version to the current version. // It returns an error if the transformation fails. // Parameters: -// ctx - context for the operation +// ctx - context.Context object // Returns: -// error - error if the transformation fails +// error - error object // Example: +// ctx := context.Background() // err := o.transformPersistentState(ctx) // if err != nil { // return err // } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) transformPersistentState(ctx context.Context) error { version, err := o.storeClient.GetVersion(ctx) @@ -168,18 +167,17 @@ func (o *TridentOrchestrator) transformPersistentState(ctx context.Context) erro return nil } -// Bootstrap initializes the orchestrator. -// It returns an error if the orchestrator is already bootstrapped. +// Bootstrap initializes the orchestrator +// It returns an error if the orchestrator cannot be bootstrapped // Returns: -// - BootstrapError if the orchestrator is already bootstrapped -// - InternalError if the orchestrator fails to bootstrap +// error: error if the orchestrator cannot be bootstrapped // Example: -// - err := orchestrator.Bootstrap() -// - if err != nil { -// log.Errorf("Failed to bootstrap orchestrator: %v", err) +// err := orc.Bootstrap() +// if err != nil { +// log.Error("Failed to bootstrap orchestrator: %v", err) // } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) Bootstrap() error { ctx := GenerateRequestContext(context.Background(), "", ContextSourceInternal) var err error @@ -209,19 +207,16 @@ func (o *TridentOrchestrator) Bootstrap() error { return nil } -// bootstrapBackends is called during startup to load backends from the persistent store. -// It returns an error if any backends fail to initialize. +// bootstrapBackends is called during startup to load all backends from the persistent store. +// It returns an error if any of the backends fail to initialize. // Parameters: // ctx - context for logging // Returns: -// error - error if any backends fail to initialize +// error - if any backends fail to initialize // Example: // err := o.bootstrapBackends(ctx) -// if err != nil { -// return err -// } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) bootstrapBackends(ctx context.Context) error { persistentBackends, err := o.storeClient.GetBackends(ctx) @@ -314,16 +309,16 @@ func (o *TridentOrchestrator) bootstrapBackends(ctx context.Context) error { return nil } -// bootstrapStorageClasses is called during startup to load persistent storage classes from the backend. -// It returns an error if the persistent storage classes cannot be loaded. +// bootstrapStorageClasses loads the storage classes from the backend store. +// It returns an error if the storage classes cannot be loaded. // Parameters: -// ctx - context +// ctx - context for logging // Returns: -// error - error if the persistent storage classes cannot be loaded +// error - error if the storage classes cannot be loaded // Example: -// err := o.bootstrapStorageClasses(ctx) +// err := o.bootstrapStorageClasses(ctx) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) bootstrapStorageClasses(ctx context.Context) error { persistentStorageClasses, err := o.storeClient.GetStorageClasses(ctx) @@ -347,19 +342,16 @@ func (o *TridentOrchestrator) bootstrapStorageClasses(ctx context.Context) error // Updates the o.volumes cache with the latest backend data. This function should only edit o.volumes in place to avoid // briefly losing track of volumes that do exist. -// bootstrapVolumes adds existing volumes to the orchestrator. -// It returns an error if the volumes cannot be retrieved from the store. +// bootstrapVolumes reads the volumes from the store and adds them to the orchestrator. +// It returns an error if the store is not available. // Parameters: // ctx - context for logging // Returns: -// error - error if the volumes cannot be retrieved from the store +// error - if the store is not available // Example: // err := o.bootstrapVolumes(ctx) -// if err != nil { -// return err -// } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) bootstrapVolumes(ctx context.Context) error { volumes, err := o.storeClient.GetVolumes(ctx) @@ -413,16 +405,16 @@ func (o *TridentOrchestrator) bootstrapVolumes(ctx context.Context) error { return nil } -// bootstrapSnapshots adds existing snapshots to the orchestrator's snapshot map. -// It returns an error if the snapshot cannot be added. +// bootstrapSnapshots loads existing snapshots from the backend store. +// It returns an error if the store is unavailable. // Parameters: // ctx - context // Returns: -// error - error if the snapshot cannot be added +// error - error if the store is unavailable // Example: -// err := o.bootstrapSnapshots(ctx) +// error := o.bootstrapSnapshots(ctx) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) bootstrapSnapshots(ctx context.Context) error { snapshots, err := o.storeClient.GetSnapshots(ctx) @@ -458,16 +450,19 @@ func (o *TridentOrchestrator) bootstrapSnapshots(ctx context.Context) error { return nil } -// bootstrapVolTxns bootstraps volume transaction logs from persistent store -// It returns an error if it fails to bootstrap any volume transaction log +// bootstrapVolTxns handles any volume transactions that were in progress when the orchestrator was last stopped. +// It returns an error if any of the transactions could not be handled. // Parameters: // ctx - context // Returns: -// error - error if any +// error - any error encountered // Example: // err := o.bootstrapVolTxns(ctx) +// if err != nil { +// return err +// } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) bootstrapVolTxns(ctx context.Context) error { volTxns, err := o.storeClient.GetVolumeTransactions(ctx) @@ -485,16 +480,17 @@ func (o *TridentOrchestrator) bootstrapVolTxns(ctx context.Context) error { return nil } -// bootstrapNodes bootstraps the orchestrator with existing nodes -// It returns an error if it fails to bootstrap +// bootstrapNodes is called during startup to load any existing nodes from the backend +// into the orchestrator. +// It returns an error if the operation fails. // Parameters: -// ctx - context +// ctx - context for the operation // Returns: -// error - error if it fails to bootstrap +// error - any error encountered // Example: // err := o.bootstrapNodes(ctx) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) bootstrapNodes(ctx context.Context) error { // Don't bootstrap nodes if we're not CSI @@ -521,17 +517,16 @@ func (o *TridentOrchestrator) bootstrapNodes(ctx context.Context) error { return nil } -// bootstrapVolumePublications loads all existing volume publications from the backend -// and adds them to the orchestrator's cache. -// It returns an error if the backend could not be contacted. +// bootstrapVolumePublications bootstraps the orchestrator with existing volume publications +// It returns an error if it fails to read the volume publications from the store // Parameters: // ctx - context for logging // Returns: -// error - error if the backend could not be contacted +// error - if the volume publications cannot be read from the store // Example: -// err := o.bootstrapVolumePublications(ctx) +// err := bootstrapVolumePublications(ctx) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) bootstrapVolumePublications(ctx context.Context) error { // Don't bootstrap volume publications if we're not CSI @@ -554,15 +549,15 @@ func (o *TridentOrchestrator) bootstrapVolumePublications(ctx context.Context) e return nil } -// addVolumePublicationToCache adds a volume publication to the cache +// addVolumePublicationToCache adds the volume publication to the cache // Parameters: -// vp - volume publication to add +// vp - volume publication to add to the cache // Returns: // none // Example: -// orchestrator.addVolumePublicationToCache(vp) +// o.addVolumePublicationToCache(vp) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) addVolumePublicationToCache(vp *utils.VolumePublication) { // If the volume has no entry we need to initialize the inner map if o.volumePublications[vp.VolumeName] == nil { @@ -571,20 +566,20 @@ func (o *TridentOrchestrator) addVolumePublicationToCache(vp *utils.VolumePublic o.volumePublications[vp.VolumeName][vp.NodeName] = vp } -// bootstrap loads all persistent data from the store and initializes the -// orchestrator's internal state. +// bootstrap loads the state of the orchestrator from persistent storage. +// It is called once at startup. // It returns an error if the bootstrap fails. // Parameters: -// ctx - context for the operation +// ctx - context for the operation // Returns: -// error - any error encountered during bootstrap +// error - if the bootstrap fails // Example: -// err := o.bootstrap(ctx) -// if err != nil { -// // handle error -// } +// err := o.bootstrap(ctx) +// if err != nil { +// log.Fatalf("Bootstrap failed: %v", err) +// } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) bootstrap(ctx context.Context) error { // Fetching backend information @@ -647,7 +642,6 @@ func (o *TridentOrchestrator) Stop() { // updateMetrics updates the metrics that track the core objects. // The caller should hold the orchestrator lock. func (o *TridentOrchestrator) updateMetrics() { -func (o *TridentOrchestrator) Stop() { tridentBuildInfo.WithLabelValues(config.BuildHash, config.OrchestratorVersion.ShortString(), @@ -699,25 +693,32 @@ func (o *TridentOrchestrator) Stop() { } } -func (o *TridentOrchestrator) handleFailedTransaction(ctx context.Context, v *storage.VolumeTransaction) error { -// handleFailedTransaction attempts to clean up after a failed transaction. -// It is called when a transaction is found in the persistent store that -// doesn't have a corresponding transaction object in memory. +// handleFailedTransaction attempts to roll back a failed transaction. +// +// The transaction log is a record of operations that have been performed on +// the backend, but have not yet been persisted to the store. If the +// orchestrator crashes before the transaction is persisted, the transaction +// log will be used to roll back the operation. // -// This function is called with the orchestrator lock held. -// It returns an error if it is unable to clean up the transaction. +// The transaction log is a record of operations that have been performed on +// the backend, but have not yet been persisted to the store. If the +// orchestrator crashes before the transaction is persisted, the transaction +// log will be used to roll back the operation. +// +// The transaction log is a record of operations that have been performed on +// the backend, but have not yet been persisted to the store. If the +// orchestrator crashes before the transaction is persisted, the transaction +// log will be used to roll back the operation. +// It returns an error if the rollback fails. // Parameters: // ctx - context for logging -// v - the volume transaction to clean up +// v - the transaction to roll back // Returns: -// error - an error if the transaction could not be cleaned up +// error - an error if the rollback fails // Example: // err := handleFailedTransaction(ctx, v) -// if err != nil { -// log.Errorf("Unable to clean up transaction %v: %v", v.ID(), err) -// } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) handleFailedTransaction(ctx context.Context, v *storage.VolumeTransaction) error { switch v.Op { @@ -956,18 +957,19 @@ func (o *TridentOrchestrator) handleFailedTransaction(ctx context.Context, v *st return nil } -// resetImportedVolumeName resets the name of a volume that was imported. -// It returns an error if the volume was not found. +// resetImportedVolumeName attempts to rename the volume back to its original name. +// It returns an error if the volume is not found. // Parameters: -// ctx - context -// volume - volume to reset +// volume: the volume to rename // Returns: -// error - error if the volume was not found +// error: nil if the volume was found and renamed, or an error if the volume was not found // Example: -// Reset the volume name for a volume that was imported -// err := o.resetImportedVolumeName(ctx, volume) +// err := o.resetImportedVolumeName(ctx, volume) +// if err != nil { +// return fmt.Errorf("failed to reset name for imported volume %s: %v", volume.Config.Name, err) +// } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) resetImportedVolumeName(ctx context.Context, volume *storage.VolumeConfig) error { // The volume could be renamed (notManaged = false) without being persisted. @@ -991,9 +993,9 @@ func (o *TridentOrchestrator) resetImportedVolumeName(ctx context.Context, volum // Returns: // none // Example: -// orchestrator.AddFrontend(f) +// orchestrator.AddFrontend(frontend.NewKubernetes()) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) AddFrontend(f frontend.Plugin) { name := f.GetName() if _, ok := o.frontends[name]; ok { @@ -1004,20 +1006,20 @@ func (o *TridentOrchestrator) AddFrontend(f frontend.Plugin) { o.frontends[name] = f } -// GetFrontend returns the frontend plugin for the specified name +// GetFrontend returns a frontend plugin by name // Parameters: -// ctx - context for logging +// ctx - context // name - name of the frontend plugin // Returns: // frontend.Plugin - the frontend plugin -// error - error if one occurred +// error - error if any // Example: -// frontend, err := o.GetFrontend(ctx, "nfs") +// frontend, err := tridentOrchestrator.GetFrontend(context.Background(), "ontap-nas") // if err != nil { // // handle error // } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) GetFrontend(ctx context.Context, name string) (frontend.Plugin, error) { if fe, ok := o.frontends[name]; !ok { @@ -1029,20 +1031,17 @@ func (o *TridentOrchestrator) GetFrontend(ctx context.Context, name string) (fro } } -// validateBackendUpdate validates that a backend update is allowed. -// It returns an error if the update is not allowed. +// validateBackendUpdate validates that the backend update is valid. +// It returns an error if the backend update is invalid. // Parameters: -// oldBackend - the backend before the update -// newBackend - the backend after the update +// oldBackend - the current backend +// newBackend - the backend to be updated // Returns: -// error - an error if the update is not allowed +// error - an error if the backend update is invalid // Example: -// err := validateBackendUpdate(oldBackend, newBackend) -// if err != nil { -// return err -// } +// err := o.validateBackendUpdate(oldBackend, newBackend) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) validateBackendUpdate(oldBackend, newBackend storage.Backend) error { // Validate that backend type isn't being changed as backend type has // implications for the internal volume names. @@ -1055,7 +1054,7 @@ func (o *TridentOrchestrator) validateBackendUpdate(oldBackend, newBackend stora return nil } -// GetVersion returns the version of the orchestrator. +// GetVersion returns the version of the orchestrator // Parameters: // context - context for the request // Returns: @@ -1064,12 +1063,10 @@ func (o *TridentOrchestrator) validateBackendUpdate(oldBackend, newBackend stora // Example: // version, err := orchestrator.GetVersion(context) // if err != nil { -// log.Error(err) -// } else { -// log.Infof("Orchestrator version is %s", version) +// log.Errorf("%v", err) // } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) GetVersion(context.Context) (string, error) { return config.OrchestratorVersion.String(), o.bootstrapError } @@ -1108,7 +1105,6 @@ func (o *TridentOrchestrator) AddBackend( // addBackend creates a new storage backend. It assumes the mutex lock is // already held or not required (e.g., during bootstrapping). func (o *TridentOrchestrator) addBackend( -func (o *TridentOrchestrator) AddBackend( ctx context.Context, configJSON, backendUUID, configRef string, ) (backendExternal *storage.BackendExternal, err error) { @@ -1212,7 +1208,6 @@ func (o *TridentOrchestrator) AddBackend( // validateAndCreateBackendFromConfig validates config and creates backend based on Config func (o *TridentOrchestrator) validateAndCreateBackendFromConfig( -func (o *TridentOrchestrator) addBackend( ctx context.Context, configJSON string, configRef string, backendUUID string, ) (backendExternal storage.Backend, err error) { @@ -1251,7 +1246,6 @@ func (o *TridentOrchestrator) addBackend( // UpdateBackend updates an existing backend. func (o *TridentOrchestrator) UpdateBackend( -func (o *TridentOrchestrator) validateAndCreateBackendFromConfig( ctx context.Context, backendName, configJSON, configRef string, ) (backendExternal *storage.BackendExternal, err error) { if o.bootstrapError != nil { @@ -1285,7 +1279,6 @@ func (o *TridentOrchestrator) validateAndCreateBackendFromConfig( // updateBackend updates an existing backend. It assumes the mutex lock is already held. func (o *TridentOrchestrator) updateBackend( -func (o *TridentOrchestrator) UpdateBackend( ctx context.Context, backendName, configJSON, configRef string, ) (backendExternal *storage.BackendExternal, err error) { backendToUpdate, err := o.getBackendByBackendName(backendName) @@ -1299,7 +1292,6 @@ func (o *TridentOrchestrator) UpdateBackend( // UpdateBackendByBackendUUID updates an existing backend. func (o *TridentOrchestrator) UpdateBackendByBackendUUID( -func (o *TridentOrchestrator) updateBackend( ctx context.Context, backendName, configJSON, backendUUID, configRef string, ) (backend *storage.BackendExternal, err error) { if o.bootstrapError != nil { @@ -1334,7 +1326,6 @@ func (o *TridentOrchestrator) updateBackend( // TODO combine this one and the one above // updateBackendByBackendUUID updates an existing backend. It assumes the mutex lock is already held. func (o *TridentOrchestrator) updateBackendByBackendUUID( -func (o *TridentOrchestrator) UpdateBackendByBackendUUID( ctx context.Context, backendName, configJSON, backendUUID, callingConfigRef string, ) (backendExternal *storage.BackendExternal, err error) { @@ -1560,7 +1551,6 @@ func (o *TridentOrchestrator) UpdateBackendByBackendUUID( // UpdateBackendState updates an existing backend's state. func (o *TridentOrchestrator) UpdateBackendState( -func (o *TridentOrchestrator) updateBackendByBackendUUID( ctx context.Context, backendName, backendState string, ) (backendExternal *storage.BackendExternal, err error) { if o.bootstrapError != nil { @@ -1578,7 +1568,6 @@ func (o *TridentOrchestrator) updateBackendByBackendUUID( // updateBackendState updates an existing backend's state. It assumes the mutex lock is already held. func (o *TridentOrchestrator) updateBackendState( -func (o *TridentOrchestrator) UpdateBackendState( ctx context.Context, backendName, backendState string, ) (backendExternal *storage.BackendExternal, err error) { @@ -1616,17 +1605,16 @@ func (o *TridentOrchestrator) UpdateBackendState( return backend.ConstructExternal(ctx), o.storeClient.UpdateBackend(ctx, backend) } -func (o *TridentOrchestrator) getBackendUUIDByBackendName(backendName string) (string, error) { -// getBackendUUIDByBackendName returns the UUID of a backend given its name +// getBackendUUIDByBackendName returns the backend UUID for a given backend name // Parameters: // backendName - name of the backend // Returns: // backendUUID - UUID of the backend // error - error if any // Example: -// backendUUID, err := o.getBackendUUIDByBackendName(backendName) +// backendUUID, err := getBackendUUIDByBackendName("backend1") // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) getBackendUUIDByBackendName(backendName string) (string, error) { backendUUID := "" for _, b := range o.backends { @@ -1643,11 +1631,14 @@ func (o *TridentOrchestrator) getBackendUUIDByBackendName(backendName string) (s // backendName - the name of the backend to return // Returns: // storage.Backend - the backend object -// error - any error encountered +// error - an error if one occurred // Example: // backend, err := o.getBackendByBackendName(backendName) +// if err != nil { +// // handle error +// } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) getBackendByBackendName(backendName string) (storage.Backend, error) { for _, b := range o.backends { if b.Name() == backendName { @@ -1657,16 +1648,16 @@ func (o *TridentOrchestrator) getBackendByBackendName(backendName string) (stora return nil, utils.NotFoundError(fmt.Sprintf("backend %v was not found", backendName)) } -// getBackendByConfigRef returns a backend based on its configRef +// getBackendByConfigRef returns the backend based on the configRef // Parameters: -// configRef - the configRef of the backend to return +// configRef string // Returns: -// storage.Backend - the backend with the specified configRef -// error - nil if the backend was found, or an error if the backend was not found +// storage.Backend +// error // Example: -// backend, err := getBackendByConfigRef("backend1") +// backend, err := o.getBackendByConfigRef(configRef) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) getBackendByConfigRef(configRef string) (storage.Backend, error) { for _, b := range o.backends { if b.ConfigRef() == configRef { @@ -1678,14 +1669,14 @@ func (o *TridentOrchestrator) getBackendByConfigRef(configRef string) (storage.B // getBackendByBackendUUID returns a backend by its UUID // Parameters: -// backendUUID - the UUID of the backend to retrieve +// backendUUID - the UUID of the backend to return // Returns: // storage.Backend - the backend with the specified UUID -// error - nil if no error occurred +// error - any error encountered // Example: -// backend, err := orchestrator.getBackendByBackendUUID("be-12345678-1234-1234-1234-123456789012") +// backend, err := o.getBackendByBackendUUID(backendUUID) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) getBackendByBackendUUID(backendUUID string) (storage.Backend, error) { backend := o.backends[backendUUID] if backend != nil { @@ -1694,20 +1685,17 @@ func (o *TridentOrchestrator) getBackendByBackendUUID(backendUUID string) (stora return nil, utils.NotFoundError(fmt.Sprintf("backend uuid %v was not found", backendUUID)) } -// GetBackend returns the backend object for the given backend name. +// GetBackend returns the backend object for the specified backend name // Parameters: -// ctx - context for logging -// backendName - name of the backend +// ctx - context for logging +// backendName - name of the backend // Returns: -// *storage.BackendExternal - backend object -// error - error object +// backendExternal - backend object +// err - error object // Example: -// backendExternal, err := orchestrator.GetBackend(ctx, "backend1") -// if err != nil { -// // handle error -// } +// backendExternal, err := o.GetBackend(ctx, backendName) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) GetBackend( ctx context.Context, backendName string, ) (backendExternal *storage.BackendExternal, err error) { @@ -1743,14 +1731,14 @@ func (o *TridentOrchestrator) GetBackend( // GetBackendByBackendUUID returns the backend object for the given backend UUID // Parameters: // ctx - context for logging -// backendUUID - UUID of the backend +// backendUUID - UUID of the backend to retrieve // Returns: -// *storage.BackendExternal - backend object -// error - error object +// *storage.BackendExternal - the backend object +// error - any error encountered // Example: -// backendExternal, err := o.GetBackendByBackendUUID(ctx, backendUUID) +// backendExternal, err := orchestrator.GetBackendByBackendUUID(ctx, "backend-uuid") // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) GetBackendByBackendUUID( ctx context.Context, backendUUID string, ) (backendExternal *storage.BackendExternal, err error) { @@ -1780,16 +1768,16 @@ func (o *TridentOrchestrator) GetBackendByBackendUUID( return backendExternal, nil } -// ListBackends returns a list of all backends known to the orchestrator. +// ListBackends returns the list of backends known to the orchestrator. // Parameters: -// ctx - the context for the operation +// ctx - context for the request // Returns: -// a list of backends -// an error object if the operation failed +// backends - list of backends known to the orchestrator +// err - error object, if any // Example: -// backends, err := tridentOrchestrator.ListBackends(ctx) +// backends, err := o.ListBackends(ctx) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) ListBackends( ctx context.Context, ) (backendExternals []*storage.BackendExternal, err error) { @@ -1817,17 +1805,13 @@ func (o *TridentOrchestrator) ListBackends( // DeleteBackend deletes a backend from the orchestrator // It returns an error if the backend does not exist // Parameters: -// backendName - the name of the backend to delete -// ctx - the context for the operation +// backendName - the name of the backend to delete // Returns: -// error - nil if successful, non-nil if an error occurred +// error - nil if successful, otherwise an error // Example: -// err := o.DeleteBackend("backend1", ctx) -// if err != nil { -// log.Errorf("DeleteBackend failed: %v", err) -// } +// err := orchestrator.DeleteBackend("myBackend") // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) DeleteBackend(ctx context.Context, backendName string) (err error) { if o.bootstrapError != nil { @@ -1850,17 +1834,17 @@ func (o *TridentOrchestrator) DeleteBackend(ctx context.Context, backendName str return o.deleteBackendByBackendUUID(ctx, backendName, backendUUID) } -// DeleteBackendByBackendUUID deletes a backend by its UUID. +// DeleteBackendByBackendUUID deletes a backend by backendUUID // It returns an error if the backend does not exist. // Parameters: -// backendName - the name of the backend to delete -// backendUUID - the UUID of the backend to delete +// backendName: Name of the backend to delete +// backendUUID: UUID of the backend to delete // Returns: -// error - nil if successful +// error: nil if successful, otherwise reason for failure // Example: -// err := orchestrator.DeleteBackendByBackendUUID(ctx, "backend1", "6e0c6e1e-b5d0-11e7-9598-080027d29755") +// err := orchestrator.DeleteBackendByBackendUUID(ctx, "myBackend", "12345678-1234-1234-1234-1234567890ab") // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) DeleteBackendByBackendUUID( ctx context.Context, backendName, backendUUID string, ) (err error) { @@ -1882,17 +1866,17 @@ func (o *TridentOrchestrator) DeleteBackendByBackendUUID( } // deleteBackendByBackendUUID deletes a backend by backendUUID -// It returns an error if the backend is not found +// It returns an error if the backend is not found. // Parameters: // ctx - context -// backendName - name of the backend to delete -// backendUUID - UUID of the backend to delete +// backendName - name of the backend +// backendUUID - UUID of the backend // Returns: -// error - if the backend is not found +// error - error if the backend is not found // Example: -// err := o.deleteBackendByBackendUUID(ctx, "ontap-nas", "12345678-1234-1234-1234-123456789012") +// err := o.deleteBackendByBackendUUID(ctx, "my-backend", "12345678-1234-1234-1234-123456789012") // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) deleteBackendByBackendUUID(ctx context.Context, backendName, backendUUID string) error { Logc(ctx).WithFields(log.Fields{ @@ -1972,29 +1956,18 @@ func (o *TridentOrchestrator) RemoveBackendConfigRef(ctx context.Context, backen return o.storeClient.UpdateBackend(ctx, b) } -func (o *TridentOrchestrator) AddVolume( -// AddVolume adds a new volume to the system. -// It returns the volume's external representation. +// AddVolume creates a new volume +// It returns the external volume object and an error if any // Parameters: -// volumeConfig: the volume configuration -// backendUUID: the UUID of the backend to use for this volume -// backend: the backend to use for this volume -// backendState: the state of the backend to use for this volume -// backendName: the name of the backend to use for this volume -// backendFilesystem: the filesystem of the backend to use for this volume -// backendPool: the pool of the backend to use for this volume -// backendInternal: whether or not the backend is internal -// backendAccessInfo: the access info of the backend to use for this volume -// backendBlockSizeBytes: the block size of the backend to use for this volume -// backendStoragePrefix: the storage prefix of the backend to use for this volume -// backendStorageClasses: the storage classes of the backend to use for this volume +// volumeConfig - configuration for the new volume +// backendUUID - UUID of the backend to create the volume on // Returns: -// externalVol: the volume's external representation -// err: any errors encountered +// externalVol - external volume object +// err - error if any // Example: -// externalVol, err := o.AddVolume(volumeConfig) +// externalVol, err := orchestrator.AddVolume(ctx, volumeConfig, backendUUID) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) AddVolume( ctx context.Context, volumeConfig *storage.VolumeConfig, ) (externalVol *storage.VolumeExternal, err error) { @@ -2159,7 +2132,6 @@ func (o *TridentOrchestrator) addVolumeInitial( // This method should only be called from AddVolume, as it does not take locks or otherwise do much validation // of the volume config. func (o *TridentOrchestrator) addVolumeRetry( -func (o *TridentOrchestrator) addVolumeInitial( ctx context.Context, txn *storage.VolumeTransaction, ) (externalVol *storage.VolumeExternal, err error) { @@ -2225,7 +2197,6 @@ func (o *TridentOrchestrator) addVolumeInitial( // addVolumeFinish is called after successful completion of a volume create/clone operation // to save the volume in the persistent store as well as Trident's in-memory cache. func (o *TridentOrchestrator) addVolumeFinish( -func (o *TridentOrchestrator) addVolumeRetry( ctx context.Context, txn *storage.VolumeTransaction, vol *storage.Volume, backend storage.Backend, pool storage.Pool, ) (externalVol *storage.VolumeExternal, err error) { @@ -2254,19 +2225,18 @@ func (o *TridentOrchestrator) addVolumeRetry( return externalVol, nil } -func (o *TridentOrchestrator) CloneVolume( // CloneVolume clones a volume -// It returns the volume spec and a transaction ID +// It returns the volume object and an error // Parameters: -// ctx - context -// volumeConfig - the volume config +// ctx - context for logging +// volumeConfig - volume config // Returns: -// *storage.VolumeExternal - the volume spec -// error - any error encountered +// *storage.VolumeExternal - volume object +// error - error, if any // Example: -// volumeSpec, err := orchestrator.CloneVolume(ctx, volumeConfig) +// volume, err := o.CloneVolume(ctx, volumeConfig) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) CloneVolume( ctx context.Context, volumeConfig *storage.VolumeConfig, ) (externalVol *storage.VolumeExternal, err error) { @@ -2299,19 +2269,18 @@ func (o *TridentOrchestrator) CloneVolume( return o.cloneVolumeInitial(ctx, volumeConfig) } -// cloneVolumeInitial creates a new volume by cloning an existing volume. -// It returns the new volume and a transaction ID that can be used to roll back -// the operation. +// cloneVolumeInitial clones a volume +// It returns the volume and an error if one occurred // Parameters: -// ctx - the context for the operation -// volumeConfig - the configuration for the new volume +// ctx - context +// volumeConfig - volume config // Returns: -// externalVol - the new volume -// err - any error encountered +// volume - volume +// error - error // Example: -// externalVol, txnID, err := orch.cloneVolumeInitial(ctx, volumeConfig) +// volume, err := orchestrator.cloneVolumeInitial(ctx, volumeConfig) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) cloneVolumeInitial( ctx context.Context, volumeConfig *storage.VolumeConfig, ) (externalVol *storage.VolumeExternal, err error) { @@ -2454,18 +2423,19 @@ func (o *TridentOrchestrator) cloneVolumeInitial( return o.addVolumeFinish(ctx, txn, vol, backend, pool) } -// cloneVolumeRetry is called to retry a volume clone operation. -// It returns the volume and any error encountered. +// cloneVolumeRetry attempts to create a clone of the specified volume on the specified backend. +// If successful, it returns the volume and backend. If not, it returns an error. +// It returns the volume and backend even if an error is returned. // Parameters: -// ctx - context -// txn - transaction +// ctx - context +// txn - the volume transaction // Returns: -// externalVol - volume -// err - error +// externalVol - the volume +// err - any error encountered // Example: -// externalVol, err := cloneVolumeRetry(ctx, txn) +// externalVol, err := o.cloneVolumeRetry(ctx, txn) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) cloneVolumeRetry( ctx context.Context, txn *storage.VolumeTransaction, ) (externalVol *storage.VolumeExternal, err error) { @@ -2582,7 +2552,6 @@ func (o *TridentOrchestrator) GetVolumeExternal( // GetVolumeByInternalName returns a volume by the given internal name func (o *TridentOrchestrator) GetVolumeByInternalName( -func (o *TridentOrchestrator) GetVolumeExternal( volumeInternal string, _ context.Context, ) (volume string, err error) { @@ -2600,20 +2569,16 @@ func (o *TridentOrchestrator) GetVolumeExternal( return "", utils.NotFoundError(fmt.Sprintf("volume %s not found", volumeInternal)) } -func (o *TridentOrchestrator) validateImportVolume(ctx context.Context, volumeConfig *storage.VolumeConfig) error { // validateImportVolume validates the volume // It returns an error if the volume is not valid // Parameters: -// volumeConfig - volume configuration +// volumeConfig: volume configuration // Returns: -// error - error if any +// error: error if the volume is not valid // Example: // err := o.validateImportVolume(ctx, volumeConfig) -// if err != nil { -// return nil, err -// } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) validateImportVolume(ctx context.Context, volumeConfig *storage.VolumeConfig) error { backend, err := o.getBackendByBackendUUID(volumeConfig.ImportBackendUUID) @@ -2676,20 +2641,20 @@ func (o *TridentOrchestrator) validateImportVolume(ctx context.Context, volumeCo return nil } -// LegacyImportVolume imports a volume that was created outside of Trident. -// It returns an error if the volume already exists. +// LegacyImportVolume imports a volume from a backend. +// It returns a VolumeExternal object. // Parameters: -// volumeConfig: the configuration for the volume to be imported -// backendName: the name of the backend on which the volume will be imported -// notManaged: if true, the volume will not be managed by Trident -// createPVandPVC: a callback function that creates a PV and PVC for the imported volume +// volumeConfig: VolumeConfig object +// backendName: Name of the backend +// notManaged: If true, the volume is not managed by Trident +// createPVandPVC: Callback function to create PV and PVC for the volume // Returns: -// externalVol: the volume that was imported -// err: any error encountered +// VolumeExternal object +// error // Example: -// externalVol, err := o.LegacyImportVolume(ctx, volumeConfig, backendName, notManaged, createPVandPVC) +// importVol, err := orchestrator.LegacyImportVolume(volumeConfig, backendName, notManaged, createPVandPVC) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) LegacyImportVolume( ctx context.Context, volumeConfig *storage.VolumeConfig, backendName string, notManaged bool, createPVandPVC VolumeCallback, @@ -2781,18 +2746,25 @@ func (o *TridentOrchestrator) LegacyImportVolume( return volExternal, nil } -// ImportVolume imports a volume from a backend. +// ImportVolume imports a volume into Trident. // It returns the volume's external representation. // Parameters: -// ctx - context for logging -// volumeConfig - volume configuration +// volumeConfig - the volume's configuration +// backendUUID - the UUID of the backend where the volume is located +// originalName - the original name of the volume // Returns: -// *storage.VolumeExternal - volume's external representation -// error - error, if any +// *storage.VolumeExternal - the volume's external representation +// error - any error encountered // Example: -// volExternal, err := orchestrator.ImportVolume(ctx, volumeConfig) +// volumeConfig := &storage.VolumeConfig{ +// Name: "testvol", +// Size: "1GiB", +// } +// externalVol, err := orchestrator.ImportVolume(ctx, volumeConfig, "backend1", "testvol") +// if err != nil { +// log.Fatal("Failed to // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) ImportVolume( ctx context.Context, volumeConfig *storage.VolumeConfig, ) (externalVol *storage.VolumeExternal, err error) { @@ -2925,18 +2897,18 @@ func (o *TridentOrchestrator) AddVolumeTransaction(ctx context.Context, volTxn * return o.storeClient.AddVolumeTransaction(ctx, volTxn) } -func (o *TridentOrchestrator) GetVolumeCreatingTransaction( -// GetVolumeCreatingTransaction returns the volume transaction for a volume that is being created. +// GetVolumeCreatingTransaction returns a VolumeTransaction with the specified +// VolumeConfig if one exists. // Parameters: -// ctx - context for the operation -// config - volume config +// ctx - context +// config - volume config // Returns: -// *storage.VolumeTransaction - volume transaction -// error - error, if any +// *storage.VolumeTransaction - volume transaction +// error - error // Example: -// volTxn, err := o.GetVolumeCreatingTransaction(ctx, config) +// txn, err := GetVolumeCreatingTransaction(ctx, config) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) GetVolumeCreatingTransaction( ctx context.Context, config *storage.VolumeConfig, ) (*storage.VolumeTransaction, error) { @@ -2957,22 +2929,20 @@ func (o *TridentOrchestrator) GetVolumeCreatingTransaction( } } -// GetVolumeTransaction retrieves a volume transaction from the backend -// It returns an error if the transaction does not exist +// GetVolumeTransaction retrieves a volume transaction from the persistent store +// It returns a volume transaction and an error if one occurred // Parameters: // ctx - context for the request -// volTxn - volume transaction to retrieve +// volTxn - the volume transaction to retrieve // Returns: -// *storage.VolumeTransaction - retrieved volume transaction -// error - error if any +// *storage.VolumeTransaction - the retrieved volume transaction +// error - an error if one occurred // Example: -// volTxn, err := orchestrator.GetVolumeTransaction(ctx, &storage.VolumeTransaction{ -// Config: &storage.VolumeConfig{ -// Name: "vol1", -// }, +// volTxn, err := o.GetVolumeTransaction(ctx, &storage.VolumeTransaction{ +// TransactionID: "abc123", // }) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) GetVolumeTransaction( ctx context.Context, volTxn *storage.VolumeTransaction, ) (*storage.VolumeTransaction, error) { @@ -2988,7 +2958,6 @@ func (o *TridentOrchestrator) DeleteVolumeTransaction(ctx context.Context, volTx // addVolumeCleanup is used as a deferred method from the volume create/clone methods // to clean up in case anything goes wrong during the operation. func (o *TridentOrchestrator) addVolumeCleanup( -func (o *TridentOrchestrator) DeleteVolumeTransaction(ctx context.Context, volTxn *storage.VolumeTransaction) error { ctx context.Context, err error, backend storage.Backend, vol *storage.Volume, volTxn *storage.VolumeTransaction, volumeConfig *storage.VolumeConfig, ) error { @@ -3051,7 +3020,6 @@ func (o *TridentOrchestrator) DeleteVolumeTransaction(ctx context.Context, volTx // to handles the case where a volume creation took too long, is still ongoing, and must be // preserved in a transaction. func (o *TridentOrchestrator) addVolumeRetryCleanup( -func (o *TridentOrchestrator) addVolumeCleanup( ctx context.Context, err error, backend storage.Backend, pool storage.Pool, volTxn *storage.VolumeTransaction, volumeConfig *storage.VolumeConfig, ) error { @@ -3103,19 +3071,22 @@ func (o *TridentOrchestrator) addVolumeCleanup( return err } -func (o *TridentOrchestrator) importVolumeCleanup( -// importVolumeCleanup is called when an error is encountered during the -// It returns an error if it is unable to clean up the volume. +// importVolumeCleanup is called when an +// It returns an error if it was unable to clean up the volume. // Parameters: -// err: error encountered during import -// volumeConfig: volume config of the volume being imported -// volTxn: volume transaction of the volume being imported +// err: the error that caused the cleanup to be called +// volumeConfig: the volume config for the volume being imported +// volTxn: the volume transaction for the volume being imported // Returns: -// error: error encountered during cleanup +// error: any error encountered during cleanup // Example: -// err := importVolumeCleanup(ctx, err, volConfig, volTxn) +// err := o.importVolumeCleanup(ctx, err, volumeConfig, volTxn) +// if err != nil { +// Logc(ctx).Warnf("Unable to clean up artifacts of volume import: %v. Repeat importing the volume %v.", +// err, volumeConfig.ImportOriginalName) +// } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) importVolumeCleanup( ctx context.Context, err error, volumeConfig *storage.VolumeConfig, volTxn *storage.VolumeTransaction, ) error { @@ -3173,16 +3144,16 @@ func (o *TridentOrchestrator) importVolumeCleanup( return err } -// GetVolume returns a volume by name +// GetVolume returns a volume // Parameters: -// volume - name of the volume to return +// volume - the name of the volume // Returns: -// *storage.VolumeExternal - volume object -// error - error, if any +// *storage.VolumeExternal - the volume object +// error - any error encountered // Example: -// vol, err := tridentOrchestrator.GetVolume(context.Background(), "myvol") +// volume, err := orchestrator.GetVolume("volume-123") // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) GetVolume( ctx context.Context, volume string, ) (volExternal *storage.VolumeExternal, err error) { @@ -3200,14 +3171,17 @@ func (o *TridentOrchestrator) GetVolume( // getVolume returns a volume by name // Parameters: -// volume - name of the volume +// volume - name of the volume to retrieve // Returns: -// *storage.VolumeExternal - volume object -// error - error object +// *storage.VolumeExternal - volume object +// error - error, if any // Example: -// volume, err := tridentOrchestrator.getVolume("volume1") +// vol, err := trident.getVolume(ctx, "vol1") +// if err != nil { +// // handle error +// } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) getVolume( _ context.Context, volume string, ) (volExternal *storage.VolumeExternal, err error) { @@ -3220,14 +3194,14 @@ func (o *TridentOrchestrator) getVolume( // GetDriverTypeForVolume returns the driver // Parameters: -// vol *storage.VolumeExternal - volume to query +// vol - the volume to query // Returns: -// string - driver type -// error - any error +// driver type +// error // Example: -// type, err := o.GetDriverTypeForVolume(vol) +// driverType, err := o.GetDriverTypeForVolume(vol) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) GetDriverTypeForVolume(_ context.Context, vol *storage.VolumeExternal) (string, error) { if o.bootstrapError != nil { return config.UnknownDriver, o.bootstrapError @@ -3250,18 +3224,16 @@ func (o *TridentOrchestrator) getDriverTypeForVolume(backendUUID string) (string return config.UnknownDriver, nil } -func (o *TridentOrchestrator) GetVolumeType( // GetVolumeType returns the volume // Parameters: -// vol *storage.VolumeExternal -// volume to get the -// Returns: -// config.VolumeType -// error +// vol *storage.VolumeExternal +// Returns: +// volumeType config.VolumeType +// err error // Example: -// volumeType, err := orchestrator.GetVolumeType(vol) +// volumeType, err := o.GetVolumeType(vol) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) GetVolumeType( _ context.Context, vol *storage.VolumeExternal, ) (volumeType config.VolumeType, err error) { @@ -3295,16 +3267,17 @@ func (o *TridentOrchestrator) GetVolumeType( return } -// ListVolumes returns a list of volumes +// ListVolumes returns a list of volumes. // Parameters: -// context - context for logging +// context - context for the call +// options - options for the call // Returns: -// volumes - list of volumes -// error - error if any +// volumes - list of volumes +// err - error object // Example: -// volumes, err := orchestrator.ListVolumes(context.Background()) +// volumes, err := orchestrator.ListVolumes(context, options) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) ListVolumes(context.Context) (volumes []*storage.VolumeExternal, err error) { if o.bootstrapError != nil { return nil, o.bootstrapError @@ -3346,7 +3319,6 @@ func (o *TridentOrchestrator) volumeSnapshots(volumeName string) ([]*storage.Sna // caller will take care of both of these. It also assumes that the volume // exists in memory. func (o *TridentOrchestrator) deleteVolume(ctx context.Context, volumeName string) error { -func (o *TridentOrchestrator) volumeSnapshots(volumeName string) ([]*storage.Snapshot, error) { volume := o.volumes[volumeName] volumeBackend := o.backends[volume.BackendUUID] @@ -3424,23 +3396,18 @@ func (o *TridentOrchestrator) volumeSnapshots(volumeName string) ([]*storage.Sna return nil } -func (o *TridentOrchestrator) deleteVolumeFromPersistentStoreIgnoreError( // deleteVolumeFromPersistentStoreIgnoreError deletes a volume from the persistent store, ignoring // errors if the volume is not found. // It returns an error if the volume is found but cannot be deleted. // Parameters: -// ctx - context -// volume - volume to delete +// ctx - context for logging +// volume - volume to delete // Returns: -// error - error if the volume is found but cannot be deleted +// error - error if the volume is found but cannot be deleted // Example: -// volume := &storage.Volume{...} -// err := o.deleteVolumeFromPersistentStoreIgnoreError(ctx, volume) -// if err != nil { -// return err -// } +// err := o.deleteVolumeFromPersistentStoreIgnoreError(ctx, volume) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) deleteVolumeFromPersistentStoreIgnoreError( ctx context.Context, volume *storage.Volume, ) error { @@ -3516,17 +3483,17 @@ func (o *TridentOrchestrator) DeleteVolume(ctx context.Context, volumeName strin return o.deleteVolume(ctx, volumeName) } -func (o *TridentOrchestrator) ListVolumesByPlugin( -// ListVolumesByPlugin returns a list of volumes for the specified plugin. +// ListVolumesByPlugin returns all volumes managed by the specified plugin. // Parameters: -// pluginName - the name of the plugin -// Returns: -// []*storage.VolumeExternal - a list of volumes -// error - any error encountered +// pluginName - name of the plugin +// Return: +// volumes - list of volumes managed by the plugin +// err - error if any // Example: -// volumes, err := c.ListVolumesByPlugin("ontap-nas") +// List of volumes managed by the ontap-nas plugin +// volumes, err := orchestrator.ListVolumesByPlugin(context.Background(), "ontap-nas") // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) ListVolumesByPlugin( _ context.Context, pluginName string, ) (volumes []*storage.VolumeExternal, err error) { @@ -3551,18 +3518,17 @@ func (o *TridentOrchestrator) ListVolumesByPlugin( return volumes, nil } -// PublishVolume publishes a volume to a set of nodes +// PublishVolume publishes a volume to a node // It returns an error if the volume is not found or is being deleted // Parameters: -// ctx - context for logging -// volumeName - name of the volume to publish -// publishInfo - information about the nodes to publish to -// Returns: -// error - error if the operation fails +// volumeName - the name of the volume to publish +// publishInfo - the information about the node to publish to +// Return: +// error - nil if successful // Example: -// err := orchestrator.PublishVolume(ctx, volumeName, publishInfo) +// err := orchestrator.PublishVolume("volume1", &utils.VolumePublishInfo{NodeID: "node1"}) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) PublishVolume( ctx context.Context, volumeName string, publishInfo *utils.VolumePublishInfo, ) (err error) { @@ -3614,18 +3580,17 @@ func (o *TridentOrchestrator) PublishVolume( return nil } -// UnpublishVolume unpublishes a volume from a node -// It returns an error if the volume is not published to the node +// UnpublishVolume unpublishes a volume from a node. +// It returns an error if the volume is not found or if the node is not found. // Parameters: -// ctx - context -// volumeName - name of the volume -// nodeName - name of the node +// volumeName - the name of the volume to be unpublished +// nodeName - the name of the node from which to unpublish the volume // Returns: // error - any error encountered // Example: -// err := orchestrator.UnpublishVolume(context.Background(), "vol1", "node1") +// err := c.UnpublishVolume("vol0", "node0") // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) UnpublishVolume(ctx context.Context, volumeName, nodeName string) (err error) { if o.bootstrapError != nil { @@ -3788,7 +3753,6 @@ func (o *TridentOrchestrator) AttachVolume( // which the volume will be attached. It ensures the volume is already mounted, and it attempts to // delete the mount point. func (o *TridentOrchestrator) DetachVolume(ctx context.Context, volumeName, mountpoint string) (err error) { -func (o *TridentOrchestrator) AttachVolume( if o.bootstrapError != nil { return o.bootstrapError @@ -3828,7 +3792,6 @@ func (o *TridentOrchestrator) AttachVolume( // SetVolumeState sets the state of a volume to a given value func (o *TridentOrchestrator) SetVolumeState( -func (o *TridentOrchestrator) DetachVolume(ctx context.Context, volumeName, mountpoint string) (err error) { ctx context.Context, volumeName string, state storage.VolumeState, ) (err error) { @@ -3862,7 +3825,6 @@ func (o *TridentOrchestrator) DetachVolume(ctx context.Context, volumeName, moun // CreateSnapshot creates a snapshot of the given volume func (o *TridentOrchestrator) CreateSnapshot( -func (o *TridentOrchestrator) SetVolumeState( ctx context.Context, snapshotConfig *storage.SnapshotConfig, ) (externalSnapshot *storage.SnapshotExternal, err error) { @@ -3951,7 +3913,6 @@ func (o *TridentOrchestrator) SetVolumeState( // addSnapshotCleanup is used as a deferred method from the snapshot create method // to clean up in case anything goes wrong during the operation. func (o *TridentOrchestrator) addSnapshotCleanup( -func (o *TridentOrchestrator) CreateSnapshot( ctx context.Context, err error, backend storage.Backend, snapshot *storage.Snapshot, volTxn *storage.VolumeTransaction, snapConfig *storage.SnapshotConfig, ) error { @@ -4002,20 +3963,18 @@ func (o *TridentOrchestrator) CreateSnapshot( return err } -func (o *TridentOrchestrator) GetSnapshot( -// GetSnapshot retrieves the snapshot object for a given volume and snapshot name. -// It returns a SnapshotExternal object. +// GetSnapshot returns a snapshot object // Parameters: // ctx - context for logging // volumeName - name of the volume // snapshotName - name of the snapshot // Returns: -// SnapshotExternal object -// error - non-nil if an error occurred +// snapshotExternal - snapshot object +// err - error object // Example: -// snapshot, err := tridentOrchestrator.GetSnapshot(ctx, "foo", "snapshot1") +// snapshotExternal, err := orchestrator.GetSnapshot(ctx, "volume1", "snapshot1") // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) GetSnapshot( ctx context.Context, volumeName, snapshotName string, ) (snapshotExternal *storage.SnapshotExternal, err error) { @@ -4032,23 +3991,20 @@ func (o *TridentOrchestrator) GetSnapshot( return o.getSnapshot(ctx, volumeName, snapshotName) } -// getSnapshot retrieves a snapshot from the orchestrator's cache. -// It returns a NotFoundError if the snapshot is not found. -// If the snapshot is in the process of being created or uploaded, -// it will attempt to update the snapshot's state from Trident. +// getSnapshot returns the snapshot with the given name // Parameters: -// volumeName - the name of the volume the snapshot belongs to -// snapshotName - the name of the snapshot +// volumeName - name of the volume the snapshot is associated with +// snapshotName - name of the snapshot to retrieve // Returns: -// *storage.SnapshotExternal - the snapshot object +// *storage.SnapshotExternal - the snapshot with the given name // error - any error encountered // Example: -// snapshot, err := o.getSnapshot(ctx, "my-volume", "my-snapshot") +// snapshot, err := o.getSnapshot(ctx, "vol1", "snap1") // if err != nil { -// // handle error +// return nil, err // } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) getSnapshot( ctx context.Context, volumeName, snapshotName string, ) (*storage.SnapshotExternal, error) { @@ -4068,8 +4024,8 @@ func (o *TridentOrchestrator) getSnapshot( } } -// updateSnapshot updates the snapshot's state in the orchestrator and persistent store -// It returns the updated snapshot and any error encountered +// updateSnapshot updates the snapshot state from the backend +// It returns the updated snapshot and an error // Parameters: // ctx - context // snapshot - the snapshot to update @@ -4079,7 +4035,7 @@ func (o *TridentOrchestrator) getSnapshot( // Example: // updatedSnapshot, err := o.updateSnapshot(ctx, snapshot) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) updateSnapshot( ctx context.Context, snapshot *storage.Snapshot, ) (*storage.Snapshot, error) { @@ -4179,21 +4135,18 @@ func (o *TridentOrchestrator) deleteSnapshot(ctx context.Context, snapshotConfig return nil } -func (o *TridentOrchestrator) deleteSnapshotFromPersistentStoreIgnoreError( -// deleteSnapshotFromPersistentStoreIgnoreError deletes a snapshot from the persistent store, ignoring -// errors if the snapshot is not found. +// deleteSnapshotFromPersistentStoreIgnoreError deletes a snapshot from the persistent store, +// ignoring errors if the snapshot is not found. // It returns an error if the snapshot is found but cannot be deleted. // Parameters: -// snapshot - the snapshot to delete +// ctx - context +// snapshot - snapshot to be deleted // Returns: -// error - any error encountered +// error - error if the snapshot is found but cannot be deleted // Example: // err := o.deleteSnapshotFromPersistentStoreIgnoreError(ctx, snapshot) -// if err != nil { -// return fmt.Errorf("error deleting snapshot %v: %v", snapshot.Config.Name, err) -// } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) deleteSnapshotFromPersistentStoreIgnoreError( ctx context.Context, snapshot *storage.Snapshot, ) error { @@ -4312,17 +4265,23 @@ func (o *TridentOrchestrator) DeleteSnapshot(ctx context.Context, volumeName, sn return o.deleteSnapshot(ctx, snapshot.Config) } -func (o *TridentOrchestrator) ListSnapshots(context.Context) (snapshots []*storage.SnapshotExternal, err error) { // ListSnapshots returns a list of snapshots // Parameters: -// context - context for the call +// context - context for logging +// filter - a filter to apply to the list of snapshots // Returns: -// []*storage.SnapshotExternal - list of snapshots -// error - error if any +// a list of snapshots +// an error if the operation fails // Example: -// snapshotList, err := orchestrator.ListSnapshots(context.Background()) +// snapshots, err := c.ListSnapshots(context.Background(), nil) +// if err != nil { +// return err +// } +// for _, snapshot := range snapshots { +// fmt.Printf("%s\n", snapshot.Config.Name) +// } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) ListSnapshots(context.Context) (snapshots []*storage.SnapshotExternal, err error) { if o.bootstrapError != nil { return nil, o.bootstrapError @@ -4341,17 +4300,20 @@ func (o *TridentOrchestrator) ListSnapshots(context.Context) (snapshots []*stora return snapshots, nil } -// ListSnapshotsByName lists all snapshots with the given name -// It returns a list of SnapshotExternal objects +// ListSnapshotsByName returns a list of snapshots that match the given name. // Parameters: -// snapshotName - the name of the snapshot to list +// snapshotName - the name of the snapshot to match +// volumeID - the ID of the volume to match +// volumeName - the name of the volume to match +// volume - the volume to match +// all - if true, return all snapshots, otherwise only return snapshots that are not deleted // Returns: -// []*storage.SnapshotExternal - a list of SnapshotExternal objects -// error - any error encountered +// a list of snapshots that match the given name +// an error, if any // Example: -// snapshots, err := orchestrator.ListSnapshotsByName("mySnapshot") +// snapshots, err := orchestrator.ListSnapshotsByName(context.Background(), "mysnapshot") // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) ListSnapshotsByName( _ context.Context, snapshotName string, ) (snapshots []*storage.SnapshotExternal, err error) { @@ -4374,17 +4336,15 @@ func (o *TridentOrchestrator) ListSnapshotsByName( return snapshots, nil } -// ListSnapshotsForVolume returns a list of snapshots for a given volume +// ListSnapshotsForVolume returns a list of snapshots for a given volume. // Parameters: -// ctx - context for logging -// volumeName - name of the volume +// volumeName (string) - the name of the volume // Returns: -// list of snapshots for the given volume -// error - non-nil if an error occurred +// ([]*storage.SnapshotExternal, error) - a list of snapshots and an error if one occurred // Example: -// snapshots, err := orchestrator.ListSnapshotsForVolume(ctx, "volume1") +// snapshots, err := orchestrator.ListSnapshotsForVolume("vol1") // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) ListSnapshotsForVolume( _ context.Context, volumeName string, ) (snapshots []*storage.SnapshotExternal, err error) { @@ -4411,17 +4371,17 @@ func (o *TridentOrchestrator) ListSnapshotsForVolume( return snapshots, nil } -// ReadSnapshotsForVolume returns a list of snapshots for the specified volume +// ReadSnapshotsForVolume reads all snapshots for a given volume +// It returns a list of SnapshotExternal objects // Parameters: -// ctx - context for logging -// volumeName - name of the volume +// volumeName: the name of the volume // Returns: -// []*storage.SnapshotExternal - list of snapshots -// error - any error encountered +// a list of SnapshotExternal objects +// an error, if any // Example: -// snapshots, err := orchestrator.ReadSnapshotsForVolume(ctx, volumeName) +// snapshots, err := orchestrator.ReadSnapshotsForVolume("vol1") // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) ReadSnapshotsForVolume( ctx context.Context, volumeName string, ) (externalSnapshots []*storage.SnapshotExternal, err error) { @@ -4449,20 +4409,16 @@ func (o *TridentOrchestrator) ReadSnapshotsForVolume( return externalSnapshots, nil } -// ReloadVolumes re-reads the list of volumes from the backend and updates the -// orchestrator's internal state. -// It returns an error if the volume list could not be retrieved. +// ReloadVolumes reloads all volumes from the backend +// It returns an error if the reload fails // Parameters: -// ctx - context for logging +// ctx - context // Returns: -// error - nil if successful, otherwise an error +// error - error if the reload fails // Example: -// err := o.ReloadVolumes(ctx) -// if err != nil { -// // handle error -// } +// err := o.ReloadVolumes(ctx) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) ReloadVolumes(ctx context.Context) (err error) { if o.bootstrapError != nil { @@ -4564,7 +4520,6 @@ func (o *TridentOrchestrator) ResizeVolume(ctx context.Context, volumeName, newS // caller will take care of both of these. It also assumes that the volume // exists in memory. func (o *TridentOrchestrator) resizeVolume(ctx context.Context, volume *storage.Volume, newSize string) error { -func (o *TridentOrchestrator) ResizeVolume(ctx context.Context, volumeName, newSize string) (err error) { volumeBackend, found := o.backends[volume.BackendUUID] if !found { @@ -4605,7 +4560,6 @@ func (o *TridentOrchestrator) ResizeVolume(ctx context.Context, volumeName, newS // resizeVolumeCleanup is used to clean up artifacts of volume resize in case // anything goes wrong during the operation. func (o *TridentOrchestrator) resizeVolumeCleanup( -func (o *TridentOrchestrator) resizeVolume(ctx context.Context, volume *storage.Volume, newSize string) error { ctx context.Context, err error, vol *storage.Volume, volTxn *storage.VolumeTransaction, ) error { @@ -4648,7 +4602,6 @@ func (o *TridentOrchestrator) resizeVolume(ctx context.Context, volume *storage. // 2. 'BlockOnFile' protocol set via the PVC annotation with multi-node access mode // 3. We do not support raw block volumes with block on file or NFS protocol. func (o *TridentOrchestrator) getProtocol( -func (o *TridentOrchestrator) resizeVolumeCleanup( ctx context.Context, volumeMode config.VolumeMode, accessMode config.AccessMode, protocol config.Protocol, ) (config.Protocol, error) { @@ -4730,19 +4683,18 @@ func (o *TridentOrchestrator) resizeVolumeCleanup( return res.protocol, res.err } -func (o *TridentOrchestrator) AddStorageClass( // AddStorageClass adds a storage class to the orchestrator -// It returns the storage class and an error if one occurred +// It returns the storage class that was added // Parameters: // ctx - context for logging // scConfig - storage class configuration // Returns: -// *storageclass.External - storage class -// error - error if one occurred +// *storageclass.External - storage class that was added +// error - error if any // Example: -// scExternal, err := o.AddStorageClass(ctx, scConfig) +// sc, err := o.AddStorageClass(ctx, scConfig) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) AddStorageClass( ctx context.Context, scConfig *storageclass.Config, ) (scExternal *storageclass.External, err error) { @@ -4784,15 +4736,14 @@ func (o *TridentOrchestrator) AddStorageClass( // GetStorageClass returns the storage class with the given name // Parameters: -// ctx - context for logging // scName - name of the storage class to retrieve // Returns: -// *storageclass.External - the storage class -// error - any error encountered +// *storageclass.External - the storage class with the given name +// error - nil if no error occurred // Example: -// sc, err := tridentOrchestrator.GetStorageClass(ctx, "sc1") +// storageclass, err := o.GetStorageClass("my-storage-class") // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) GetStorageClass( ctx context.Context, scName string, ) (scExternal *storageclass.External, err error) { @@ -4819,11 +4770,14 @@ func (o *TridentOrchestrator) GetStorageClass( // ctx - context for logging // Returns: // []*storageclass.External - a list of storage classes -// error - error, if any +// error - any error encountered // Example: -// scExternals, err := o.ListStorageClasses(ctx) +// storageClasses, err := o.ListStorageClasses(context.Background()) +// if err != nil { +// return err +// } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) ListStorageClasses(ctx context.Context) ( scExternals []*storageclass.External, err error, ) { @@ -4844,18 +4798,19 @@ func (o *TridentOrchestrator) ListStorageClasses(ctx context.Context) ( } // DeleteStorageClass deletes a storage class -// It returns an error if the storage class does not exist +// It returns an error if the storage class is not found // Parameters: // scName - name of the storage class to delete +// ctx - context for the request // Returns: -// error - any error encountered +// error - if the storage class is not found // Example: -// err := orchestrator.DeleteStorageClass(ctx, "my-storage-class") +// err := orchestrator.DeleteStorageClass(ctx, "mystorageclass") // if err != nil { -// log.Error("Error deleting storage class: ", err) +// // handle error // } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) DeleteStorageClass(ctx context.Context, scName string) (err error) { if o.bootstrapError != nil { return o.bootstrapError @@ -4887,16 +4842,20 @@ func (o *TridentOrchestrator) DeleteStorageClass(ctx context.Context, scName str return nil } -// reconcileNodeAccessOnAllBackends reconciles node access on all backends -// It returns an error if any backend fails to reconcile +// reconcileNodeAccessOnAllBackends reconciles node access on all backends. +// It returns an error if any of the backends fail to reconcile. // Parameters: -// ctx - context +// ctx - context // Returns: -// error - error if any backend fails to reconcile +// error - if any of the backends fail to reconcile // Example: -// err := o.reconcileNodeAccessOnAllBackends(ctx) +// ctx := context.Background() +// err := o.reconcileNodeAccessOnAllBackends(ctx) +// if err != nil { +// ... +// } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) reconcileNodeAccessOnAllBackends(ctx context.Context) error { if config.CurrentDriverContext != config.ContextCSI { @@ -4918,20 +4877,20 @@ func (o *TridentOrchestrator) reconcileNodeAccessOnAllBackends(ctx context.Conte return nil } -// reconcileNodeAccessOnBackend reconciles node access on the backend. -// It returns an error if the operation fails. +// reconcileNodeAccessOnBackend reconciles the node access on the backend +// It returns an error if the operation fails // Parameters: // ctx - context -// b - backend +// b - backend // Returns: -// error - any error encountered +// error - error if the operation fails // Example: // err := o.reconcileNodeAccessOnBackend(ctx, b) // if err != nil { // return err // } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) reconcileNodeAccessOnBackend(ctx context.Context, b storage.Backend) error { if config.CurrentDriverContext != config.ContextCSI { @@ -4958,7 +4917,6 @@ func (o *TridentOrchestrator) safeReconcileNodeAccessOnBackend(ctx context.Conte // PeriodicallyReconcileNodeAccessOnBackends is intended to be run as a goroutine and will periodically run // safeReconcileNodeAccessOnBackend for each backend in the orchestrator func (o *TridentOrchestrator) PeriodicallyReconcileNodeAccessOnBackends() { -func (o *TridentOrchestrator) safeReconcileNodeAccessOnBackend(ctx context.Context, b storage.Backend) error { o.stopNodeAccessLoop = make(chan bool) ctx := GenerateRequestContext(context.Background(), "", ContextSourcePeriodic) @@ -4992,22 +4950,18 @@ func (o *TridentOrchestrator) safeReconcileNodeAccessOnBackend(ctx context.Conte } } -func (o *TridentOrchestrator) AddNode( // AddNode adds a node to the orchestrator -// It returns an error if the node could not be added +// It returns an error if the node already exists // Parameters: // ctx - context // node - the node to add -// nodeEventCallback - callback function to be invoked when a node event occurs -// Return: -// error - error if the node could not be added +// nodeEventCallback - callback function to invoke when a node event occurs +// Returns: +// error - any error encountered // Example: -// err := o.AddNode(ctx, node, nodeEventCallback) -// if err != nil { -// return err -// } +// err := o.AddNode(ctx, node) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) AddNode( ctx context.Context, node *utils.Node, nodeEventCallback NodeEventCallback, ) (err error) { @@ -5050,32 +5004,31 @@ func (o *TridentOrchestrator) AddNode( return nil } -// invalidateAllBackendNodeAccess invalidates the node access cache for all backends. +// invalidateAllBackendNodeAccess invalidates the node access for all backends // Returns: -// - nil if successful -// - error if unsuccessful +// none // Example: -// - err := o.invalidateAllBackendNodeAccess() +// orchestrator.invalidateAllBackendNodeAccess() // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) invalidateAllBackendNodeAccess() { for _, backend := range o.backends { backend.InvalidateNodeAccess() } } -// handleUpdatedNodePrep handles node prep updates from the backend +// handleUpdatedNodePrep handles the node prep status for a node that has been updated. // Parameters: -// ctx - context -// protocol - protocol for which node prep is being reported -// node - node for which node prep is being reported -// nodeEventCallback - callback to invoke to report node events +// ctx - context for logging +// protocol - the protocol for which node prep is being reported +// node - the node object +// nodeEventCallback - a callback function to be called to report an event // Returns: // none // Example: -// handleUpdatedNodePrep(ctx, "NFS", node, nodeEventCallback) +// o.handleUpdatedNodePrep(ctx, "NFS", node, nodeEventCallback) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) handleUpdatedNodePrep( ctx context.Context, protocol string, node *utils.Node, nodeEventCallback NodeEventCallback, ) { @@ -5118,17 +5071,20 @@ func (o *TridentOrchestrator) handleUpdatedNodePrep( } } -// GetNode returns the node object for the specified node name +// GetNode returns the node object for the specified node name. // Parameters: // ctx - context for logging // nName - name of the node // Returns: -// *utils.Node - the node object -// error - error if any +// *utils.Node - node object +// error - error object // Example: -// node, err := GetNode(context.TODO(), "localhost") +// node, err := o.GetNode(ctx, "node01") +// if err != nil { +// // handle error +// } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) GetNode(ctx context.Context, nName string) (node *utils.Node, err error) { if o.bootstrapError != nil { return nil, o.bootstrapError @@ -5149,17 +5105,16 @@ func (o *TridentOrchestrator) GetNode(ctx context.Context, nName string) (node * return node, nil } -// ListNodes returns a list of all nodes in the cluster +// ListNodes returns a list of all nodes known to the orchestrator. // Parameters: -// context - context for the request -// filter - filter to apply to the list +// ctx - context for the request // Returns: -// []*utils.Node - list of nodes -// error - error if any +// []*utils.Node - list of nodes +// error - non-nil if an error occurred // Example: -// nodes, err := core.ListNodes(context, nil) +// nodes, err := api.ListNodes(ctx) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) ListNodes(context.Context) (nodes []*utils.Node, err error) { if o.bootstrapError != nil { return nil, o.bootstrapError @@ -5177,17 +5132,16 @@ func (o *TridentOrchestrator) ListNodes(context.Context) (nodes []*utils.Node, e return nodes, nil } -// DeleteNode removes the node from the orchestrator. -// It returns an error if the node does not exist. +// DeleteNode removes a node from the orchestrator. +// It returns an error if the node is not found. // Parameters: -// nodeName - name of the node to delete -// force - if true, delete the node even if volumes are published to it +// nodeName - the name of the node to delete // Returns: -// error - error if the node could not be deleted +// error - any error encountered // Example: -// error := orchestrator.DeleteNode(ctx, "node1") +// err := orchestrator.DeleteNode("mynode") // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) DeleteNode(ctx context.Context, nodeName string) (err error) { if o.bootstrapError != nil { return o.bootstrapError @@ -5233,16 +5187,16 @@ func (o *TridentOrchestrator) DeleteNode(ctx context.Context, nodeName string) ( } // deleteNode deletes a node from the orchestrator -// It returns an error if the node is not found +// It returns an error if the node is not found, or if the node is in use // Parameters: -// ctx - context +// ctx - context for the request // nodeName - name of the node to delete -// Returns: -// error - error if the node is not found +// Return: +// error - if the node is not found, or if the node is in use // Example: // err := o.deleteNode(ctx, "node1") // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) deleteNode(ctx context.Context, nodeName string) (err error) { node, found := o.nodes[nodeName] @@ -5283,7 +5237,6 @@ func (o *TridentOrchestrator) AddVolumePublication( // GetVolumePublication returns the volume publication for a given volume/node pair func (o *TridentOrchestrator) GetVolumePublication( -func (o *TridentOrchestrator) AddVolumePublication( _ context.Context, volumeName, nodeName string, ) (publication *utils.VolumePublication, err error) { if o.bootstrapError != nil { @@ -5305,7 +5258,6 @@ func (o *TridentOrchestrator) AddVolumePublication( // ListVolumePublications returns a list of all volume publications func (o *TridentOrchestrator) ListVolumePublications( -func (o *TridentOrchestrator) GetVolumePublication( context.Context, ) (publications []*utils.VolumePublication, err error) { if o.bootstrapError != nil { @@ -5328,7 +5280,6 @@ func (o *TridentOrchestrator) GetVolumePublication( // ListVolumePublicationsForVolume returns a list of all volume publications for a given volume func (o *TridentOrchestrator) ListVolumePublicationsForVolume( -func (o *TridentOrchestrator) ListVolumePublications( ctx context.Context, volumeName string, ) (publications []*utils.VolumePublication, err error) { if o.bootstrapError != nil { @@ -5344,16 +5295,15 @@ func (o *TridentOrchestrator) ListVolumePublications( return } -func (o *TridentOrchestrator) listVolumePublicationsForVolume( -// listVolumePublicationsForVolume returns a list of publications for the given volume +// listVolumePublicationsForVolume returns the list of volume publications for a given volume // Parameters: -// volumeName - name of the volume +// volumeName - name of the volume // Returns: -// list of publications for the given volume +// list of volume publications for the given volume // Example: -// publications := o.listVolumePublicationsForVolume(volumeName) +// publications := o.listVolumePublicationsForVolume(ctx, "foo") // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) listVolumePublicationsForVolume( _ context.Context, volumeName string, ) (publications []*utils.VolumePublication) { @@ -5382,16 +5332,15 @@ func (o *TridentOrchestrator) ListVolumePublicationsForNode( return } -func (o *TridentOrchestrator) listVolumePublicationsForNode( -// listVolumePublicationsForNode returns the list of published volumes for a given node +// listVolumePublicationsForNode returns the list of volume publications for the given node // Parameters: // nodeName - the name of the node // Returns: -// []*utils.VolumePublication - the list of published volumes for the node +// []*utils.VolumePublication - the list of volume publications for the node // Example: -// volumes, err := o.listVolumePublicationsForNode(ctx, "kube-node-1") +// publications := o.listVolumePublicationsForNode(nodeName) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) listVolumePublicationsForNode( _ context.Context, nodeName string, ) (publications []*utils.VolumePublication) { @@ -5431,7 +5380,6 @@ func (o *TridentOrchestrator) DeleteVolumePublication(ctx context.Context, volum return nil } -func (o *TridentOrchestrator) removeVolumePublicationFromCache(volumeID string, nodeID string) { // removeVolumePublicationFromCache removes the volume publication from the cache // Parameters: // volumeID: the volume ID @@ -5439,9 +5387,9 @@ func (o *TridentOrchestrator) removeVolumePublicationFromCache(volumeID string, // Returns: // None // Example: -// o.removeVolumePublicationFromCache(volumeID, nodeID) +// removeVolumePublicationFromCache(volumeID, nodeID) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) removeVolumePublicationFromCache(volumeID string, nodeID string) { delete(o.volumePublications[volumeID], nodeID) // If there are no more nodes for this volume, remove the volume's entry @@ -5451,20 +5399,20 @@ func (o *TridentOrchestrator) removeVolumePublicationFromCache(volumeID string, } // updateBackendOnPersistentStore updates the backend information on the persistent store -// It returns an error if the update fails +// It returns an error if the update fails. // Parameters: -// ctx - context for logging -// backend - the backend to update -// newBackend - true if this is a new backend, false if it is an existing backend -// Return: +// ctx - context +// backend - backend to update +// newBackend - true if this is a new backend +// Returns: // error - error if the update fails // Example: -// err := updateBackendOnPersistentStore(ctx, backend, true) +// err := o.updateBackendOnPersistentStore(ctx, backend, true) // if err != nil { -// return err +// return err // } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) updateBackendOnPersistentStore( ctx context.Context, backend storage.Backend, newBackend bool, ) error { @@ -5490,16 +5438,20 @@ func (o *TridentOrchestrator) updateBackendOnPersistentStore( } // updateVolumeOnPersistentStore updates the volume information in persistent store -// It returns an error if the update fails +// It returns an error if the volume cannot be updated. // Parameters: // ctx - context for logging -// vol - volume to update +// vol - volume to be updated // Returns: -// error - error if the update fails +// error - error if the volume cannot be updated // Example: -// err := o.updateVolumeOnPersistentStore(ctx, vol) +// err := orchestrator.updateVolumeOnPersistentStore(ctx, vol) +// if err != nil { +// log.Errorf("Could not update volume %s on persistent store: %v", +// vol.Config.Name, err) +// } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) updateVolumeOnPersistentStore(ctx context.Context, vol *storage.Volume) error { // Update the volume information in persistent store @@ -5512,17 +5464,20 @@ func (o *TridentOrchestrator) updateVolumeOnPersistentStore(ctx context.Context, return o.storeClient.UpdateVolume(ctx, vol) } -// replaceBackendAndUpdateVolumesOnPersistentStore updates the backend and volume information in persistent store -// It returns an error if the backend or volume information could not be updated +// replaceBackendAndUpdateVolumesOnPersistentStore updates both backend and volume information in persistent store +// It returns an error if the backend or volume information cannot be updated. // Parameters: // origBackend - the original backend // newBackend - the new backend // Returns: -// error - an error if the backend or volume information could not be updated +// error - if the backend or volume information cannot be updated // Example: -// error := o.replaceBackendAndUpdateVolumesOnPersistentStore(ctx, oldBackend, newBackend) +// err := o.replaceBackendAndUpdateVolumesOnPersistentStore(ctx, origBackend, newBackend) +// if err != nil { +// Logc(ctx).Errorf("Error updating backend %s and volumes: %v", newBackend.Name(), err) +// } // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) replaceBackendAndUpdateVolumesOnPersistentStore( ctx context.Context, origBackend, newBackend storage.Backend, ) error { @@ -5537,14 +5492,14 @@ func (o *TridentOrchestrator) replaceBackendAndUpdateVolumesOnPersistentStore( // isCRDContext returns true if the context is from a CRD request // Parameters: -// ctx - the context +// ctx - the context // Returns: -// true if the context is from a CRD request, false otherwise +// true if the context is from a CRD request // Example: -// ctx := context.WithValue(context.Background(), ContextKeyRequestSource, ContextSourceCRD) -// isCRD := isCRDContext(ctx) +// ctx := context.WithValue(context.Background(), ContextKeyRequestSource, ContextSourceCRD) +// core.isCRDContext(ctx) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) isCRDContext(ctx context.Context) bool { ctxSource := ctx.Value(ContextKeyRequestSource) return ctxSource != nil && ctxSource == ContextSourceCRD @@ -5576,7 +5531,6 @@ func (o *TridentOrchestrator) EstablishMirror( // ReestablishMirror recreates a previously existing replication mirror relationship between 2 volumes on a backend func (o *TridentOrchestrator) ReestablishMirror( -func (o *TridentOrchestrator) EstablishMirror( ctx context.Context, backendUUID, localVolumeHandle, remoteVolumeHandle string, ) (err error) { @@ -5601,7 +5555,6 @@ func (o *TridentOrchestrator) EstablishMirror( // PromoteMirror makes the local volume the primary func (o *TridentOrchestrator) PromoteMirror( -func (o *TridentOrchestrator) ReestablishMirror( ctx context.Context, backendUUID, localVolumeHandle, remoteVolumeHandle, snapshotHandle string, ) (waitingForSnapshot bool, err error) { @@ -5626,7 +5579,6 @@ func (o *TridentOrchestrator) ReestablishMirror( // GetMirrorStatus returns the current status of the mirror relationship func (o *TridentOrchestrator) GetMirrorStatus( -func (o *TridentOrchestrator) PromoteMirror( ctx context.Context, backendUUID, localVolumeHandle, remoteVolumeHandle string, ) (status string, err error) { @@ -5649,18 +5601,16 @@ func (o *TridentOrchestrator) PromoteMirror( return mirrorBackend.GetMirrorStatus(ctx, localVolumeHandle, remoteVolumeHandle) } -func (o *TridentOrchestrator) CanBackendMirror(_ context.Context, backendUUID string) (capable bool, err error) { -// CanBackendMirror checks if the backend can mirror -// It returns true if the backend can mirror and false otherwise +// CanBackendMirror returns true if the backend is capable of mirroring // Parameters: -// backendUUID - the backend UUID +// backendUUID - the backend UUID // Returns: -// capable - true if the backend can mirror, false otherwise -// err - any error encountered +// capable - true if the backend is capable of mirroring +// err - any error encountered // Example: -// capable, err := o.CanBackendMirror(ctx, backendUUID) +// capable, err := tridentcore.CanBackendMirror(backendUUID) // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) CanBackendMirror(_ context.Context, backendUUID string) (capable bool, err error) { if o.bootstrapError != nil { @@ -5702,19 +5652,17 @@ func (o *TridentOrchestrator) ReleaseMirror( return mirrorBackend.ReleaseMirror(ctx, localVolumeHandle) } -func (o *TridentOrchestrator) GetCHAP( -// GetCHAP returns the CHAP information for a volume +// GetCHAP returns CHAP information for a volume // Parameters: -// ctx - context -// volumeName - name of the volume -// nodeName - name of the node +// volumeName - Name of the volume +// nodeName - Name of the node // Returns: // chapInfo - CHAP information for the volume -// err - error, if any +// err - error object // Example: -// chapInfo, err := orchestrator.GetCHAP(ctx, "volume1", "node1") +// chapInfo, err := orchestrator.GetCHAP(ctx, "vol1", "node1") // -// -- Doc autogenerated on 2022-05-12 17:31:11.257272 -- +// -- Doc autogenerated on 2022-05-12 19:51:03.426932 -- func (o *TridentOrchestrator) GetCHAP( ctx context.Context, volumeName, nodeName string, ) (chapInfo *utils.IscsiChapInfo, err error) { diff --git a/core/orchestrator_core_test.go b/core/orchestrator_core_test.go index 836d170aa..73b183977 100644 --- a/core/orchestrator_core_test.go +++ b/core/orchestrator_core_test.go @@ -64,13 +64,13 @@ type recoveryTest struct { // cleanup cleans up the persistent store and the in-memory client. // Parameters: // t: the test object -// o: the orchestrator to clean up +// o: the orchestrator // Returns: // None // Example: // cleanup(t, o) // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func cleanup(t *testing.T, o *TridentOrchestrator) { err := o.storeClient.DeleteBackends(ctx()) if err != nil && !persistentstore.MatchKeyNotFoundErr(err) { @@ -104,23 +104,28 @@ func cleanup(t *testing.T, o *TridentOrchestrator) { } } -// diffConfig compares two structs and returns a list of differences -// between them. -// It returns an empty list if there are no differences. -// -// The fieldToSkip parameter is optional and can be used to skip a field -// in the comparison. +// diffConfig compares two structs of the same +// It returns a list of differences // Parameters: // expected: the expected struct // got: the actual struct -// fieldToSkip: the name of a field to skip in the comparison +// fieldToSkip: a field to skip when comparing // Returns: // a list of differences // Example: +// expected := &Config{ +// Debug: true, +// LogFile: "/tmp/log", +// } +// got := &Config{ +// Debug: false, +// LogFile: "/tmp/log", +// } // diffs := diffConfig(expected, got, "") -// diffs := diffConfig(expected, got, "FieldToSkip") +// fmt.Println(diffs) +// // Output: [Debug: expected true, got false] // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func diffConfig(expected, got interface{}, fieldToSkip string) []string { diffs := make([]string, 0) @@ -148,17 +153,20 @@ func diffConfig(expected, got interface{}, fieldToSkip string) []string { } // To be called after reflect.DeepEqual has failed. -// diffExternalBackends compares two external backends and logs any differences +// diffExternalBackends compares two external backends and returns a list of differences // Parameters: -// t: testing.T object +// t: test object // expected: expected backend -// got: got backend +// got: actual backend // Returns: -// None +// diffs: list of differences // Example: -// diffExternalBackends(t, expected, got) +// diffs := diffExternalBackends(t, expected, got) +// if len(diffs) > 0 { +// t.Errorf("External backends differ:\n\t%s", strings.Join(diffs, "\n\t")) +// } // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func diffExternalBackends(t *testing.T, expected, got *storage.BackendExternal) { diffs := make([]string, 0) @@ -250,17 +258,19 @@ func diffExternalBackends(t *testing.T, expected, got *storage.BackendExternal) } } -// runDeleteTest runs a single test from the deleteTest suite. +// runDeleteTest runs a single test for the DeleteVolume method. // Parameters: -// t: the test object -// d: the deleteTest to run -// orchestrator: the orchestrator to use +// t: The test object +// d: The test definition +// orchestrator: The orchestrator object // Returns: -// nothing +// Nothing // Example: -// runDeleteTest(t, tests[0], orchestrator) +// runDeleteTest(t, &deleteTest{ +// "myvol1", true, +// }, orchestrator) // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func runDeleteTest( t *testing.T, d *deleteTest, orchestrator *TridentOrchestrator, ) { @@ -318,18 +328,16 @@ type storageClassTest struct { expected []*tu.PoolMatch } -// getOrchestrator is a helper function for tests that need to create an orchestrator. -// It will create a new orchestrator, bootstrap it, and return it. -// It returns the orchestrator and a cleanup function that should be called when the test is done. +// getOrchestrator returns a new TridentOrchestrator instance with a new +// in-memory persistent store. // Parameters: -// t: the test object +// t *testing.T - the test object // Returns: -// o: the orchestrator +// *TridentOrchestrator - the new orchestrator // Example: // o := getOrchestrator(t) -// defer o.Terminate() // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func getOrchestrator(t *testing.T) *TridentOrchestrator { var ( storeClient persistentstore.Client @@ -347,20 +355,21 @@ func getOrchestrator(t *testing.T) *TridentOrchestrator { return o } -// validateStorageClass validates that the storage class has the expected pools. +// validateStorageClass validates that the storage class matches the expected pools. // Parameters: -// t: The test object. -// o: The orchestrator. -// name: The name of the storage class. -// expected: The expected pools. +// t: Test object +// o: Orchestrator +// name: Name of the storage class +// expected: List of expected pool matches // Returns: -// None. +// None // Example: // validateStorageClass(t, o, "sc1", []*tu.PoolMatch{ -// tu.NewPoolMatch("be1", "pool1"), +// &tu.PoolMatch{Backend: "mock1", Pool: "gold"}, +// &tu.PoolMatch{Backend: "mock2", Pool: "platinum"}, // }) // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func validateStorageClass( t *testing.T, o *TridentOrchestrator, @@ -898,11 +907,11 @@ func TestAddStorageClassVolumes(t *testing.T) { // This test is modeled after TestAddStorageClassVolumes, but we don't need all the // tests around storage class deletion, etc. -// TestCloneVolumes tests the CloneVolume functionality. -// It checks that the clone is placed in the same backend as the source volume, -// and that the clone is registered in the store. +// TestCloneVolumes tests the clone volume functionality. +// It checks that the clone is placed in the same backend as the source volume. +// It also checks that the clone is stored in the persistent store. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestCloneVolumes(t *testing.T) { mockPools := tu.GetFakePools() orchestrator := getOrchestrator(t) @@ -1174,18 +1183,18 @@ func TestCloneVolumes(t *testing.T) { cleanup(t, orchestrator) } -// addBackend adds a backend with the specified name and protocol. +// addBackend adds a backend to the orchestrator. // Parameters: -// t *testing.T: the test object -// orchestrator *TridentOrchestrator: the orchestrator object -// backendName string: the name of the backend to add -// backendProtocol config.Protocol: the protocol of the backend to add +// t: test object +// orchestrator: orchestrator object +// backendName: name of the backend to add +// backendProtocol: protocol of the backend to add // Returns: // None // Example: -// addBackend(t, orchestrator, "mockBackend", config.File) +// addBackend(t, orchestrator, "fakeBackend", config.File) // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func addBackend( t *testing.T, orchestrator *TridentOrchestrator, backendName string, backendProtocol config.Protocol, ) { @@ -1244,20 +1253,19 @@ func addBackendStorageClass( } } -func captureOutput(f func()) string { -// captureOutput captures the output of the provided function and returns it as a string -// It returns an empty string if the function doesn't log anything +// captureOutput captures the output of the given function and returns it as a string +// It returns an empty string if the function does not produce any output // Parameters: -// f - function to capture output of +// f: the function to capture the output of // Returns: -// string - captured output +// the output of the function as a string // Example: -// output := captureOutput(func() { -// log.Printf("foo") -// }) -// log.Printf("Output: %s", output) +// output := captureOutput(func() { +// log.Println("Hello, World!") +// }) +// // output = "Hello, World!" // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func captureOutput(f func()) string { var buf bytes.Buffer log.SetOutput(&buf) @@ -1266,12 +1274,15 @@ func captureOutput(f func()) string { return buf.String() } -// TestBackendUpdateAndDelete tests the ability to update and delete backends. -// It checks that the orchestrator correctly updates storage classes and -// volumes when a backend is updated. It also checks that the orchestrator -// correctly offlines a backend when it is deleted. +// TestBackendUpdateAndDelete tests the update and delete functionality of the +// orchestrator. +// It checks that the orchestrator can update a backend, that the storage class +// is updated to point to the new backend, and that the volume points to the +// right storage pool. +// It also checks that the orchestrator can offline a backend, and that the +// storage class is updated to remove the backend. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestBackendUpdateAndDelete(t *testing.T) { const ( backendName = "updateBackend" @@ -1583,17 +1594,17 @@ func TestBackendUpdateAndDelete(t *testing.T) { cleanup(t, orchestrator) } -// backendPasswordsInLogsHelper is a helper function for backendPasswordsInLogs -// and backendPasswordsInLogsWithDebugTraceFlags. +// backendPasswordsInLogsHelper is a helper function that checks if the backend config +// is suppressed in the logs. // Parameters: -// t: the test object -// debugTraceFlags: a map of debug trace flags to enable +// t: test object +// debugTraceFlags: debug trace flags // Returns: -// nothing +// None // Example: -// backendPasswordsInLogsHelper(t, map[string]bool{"backend": true}) +// backendPasswordsInLogsHelper(t, debugTraceFlags) // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func backendPasswordsInLogsHelper(t *testing.T, debugTraceFlags map[string]bool) { backendName := "passwordBackend" @@ -1641,21 +1652,21 @@ func backendPasswordsInLogsHelper(t *testing.T, debugTraceFlags map[string]bool) cleanup(t, orchestrator) } -// TestBackendPasswordsInLogs tests that backend passwords are not logged -// when the method is not specified. -// It checks that backend passwords are logged when the method is specified. +// TestBackendPasswordsInLogs tests that backend passwords are not logged. +// It checks that the backend password is not logged when the backend is created, +// and that it is not logged when the backend is used. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestBackendPasswordsInLogs(t *testing.T) { backendPasswordsInLogsHelper(t, nil) backendPasswordsInLogsHelper(t, map[string]bool{"method": true}) } // TestEmptyBackendDeletion tests that an empty backend can be deleted. -// It checks that the backend is removed from the orchestrator's memory, +// It checks that the backend is removed from the orchestrator's memory // and that the backend is removed from the store client. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestEmptyBackendDeletion(t *testing.T) { const ( backendName = "emptyBackend" @@ -1691,11 +1702,11 @@ func TestEmptyBackendDeletion(t *testing.T) { cleanup(t, orchestrator) } -// TestBootstrapSnapshotMissingVolume tests that a snapshot in the missing_volume state is bootstrapped -// correctly and can be deleted. -// It checks that the snapshot is in the missing_volume state and that it can be deleted. +// TestBootstrapSnapshotMissingVolume tests that a snapshot in the missing_volume state is +// bootstrapped correctly. +// It checks that the snapshot is bootstrapped with the correct state, and that it can be deleted. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestBootstrapSnapshotMissingVolume(t *testing.T) { const ( offlineBackendName = "snapNoVolBackend" @@ -1754,11 +1765,10 @@ func TestBootstrapSnapshotMissingVolume(t *testing.T) { } } -// TestBootstrapSnapshotMissingBackend tests that a snapshot in the missing_backend state is -// bootstrapped correctly. -// It checks that the snapshot is bootstrapped with the correct state and that it can be deleted. +// TestBootstrapSnapshotMissingBackend tests bootstrapping a snapshot that has a missing backend. +// It checks that the snapshot is in the missing_backend state. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestBootstrapSnapshotMissingBackend(t *testing.T) { const ( offlineBackendName = "snapNoBackBackend" @@ -1817,11 +1827,11 @@ func TestBootstrapSnapshotMissingBackend(t *testing.T) { } } -// TestBootstrapVolumeMissingBackend tests that a volume in the missing_backend state can be -// bootstrapped and deleted. -// It checks that the volume is in the missing_backend state and that it can be deleted. +// TestBootstrapVolumeMissingBackend tests that a volume in missing_backend state is bootstrapped +// correctly. +// It checks that the volume is bootstrapped with the correct state and that it can be deleted. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestBootstrapVolumeMissingBackend(t *testing.T) { const ( offlineBackendName = "bootstrapVolBackend" @@ -1874,10 +1884,12 @@ func TestBootstrapVolumeMissingBackend(t *testing.T) { } } -// TestBackendCleanup tests that offline backends are cleaned up during bootstrap. -// It checks that online backends are not cleaned up during bootstrap. +// TestBackendCleanup tests that when a backend is deleted, it is also removed +// from the backend store. +// It checks that when the orchestrator is restarted, the backend is not +// bootstrapped. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestBackendCleanup(t *testing.T) { const ( offlineBackendName = "cleanupBackend" @@ -1929,10 +1941,9 @@ func TestBackendCleanup(t *testing.T) { } // TestLoadBackend tests that a backend can be loaded from a config file. -// It checks that the backend is loaded correctly and that it can be loaded -// after a restart. +// It checks that the backend is the same after being loaded from the config file. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestLoadBackend(t *testing.T) { const ( backendName = "load-backend-test" @@ -1985,19 +1996,19 @@ func TestLoadBackend(t *testing.T) { cleanup(t, orchestrator) } -// prepRecoveryTest prepares a backend and storage class for testing -// recovery test functionality. +// prepRecoveryTest sets up a backend and storage class for testing recovery +// tests. // Parameters: -// t: Test object -// orchestrator: Trident orchestrator -// backendName: Name of the backend to create -// scName: Name of the storage class to create +// t: the test object +// orchestrator: the orchestrator object +// backendName: the name of the backend to create +// scName: the name of the storage class to create // Returns: // None // Example: -// prepRecoveryTest(t, orchestrator, "backend", "sc") +// prepRecoveryTest(t, orchestrator, "recoveryTest", "recoveryTestSC") // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func prepRecoveryTest( t *testing.T, orchestrator *TridentOrchestrator, backendName, scName string, ) { @@ -2035,37 +2046,20 @@ func prepRecoveryTest( } } -// runRecoveryTests runs a set of recovery tests. -// -// Each test is a volume transaction that's been partially completed. -// The test is run by creating a new orchestrator, which should -// recover from the transaction and then clean up after itself. +// runRecoveryTests runs a set of tests that ensure that the orchestrator +// can recover from a partially completed volume addition. // Parameters: -// t: the test object -// orchestrator: the orchestrator to use for the test -// backendName: the name of the backend to use for the test -// op: the operation to perform -// testCases: a list of recoveryTest objects, each of which contains -// a VolumeConfig and a name for the test. +// t: The test object +// orchestrator: The orchestrator to be tested +// backendName: The name of the backend to be used +// op: The operation to be tested (add or delete) +// testCases: The set of tests to be run // Returns: -// nothing +// None // Example: -// runRecoveryTests(t, orchestrator, "be-1", storage.AddVolume, []recoveryTest{ -// { -// name: "Test 1", -// volumeConfig: &storage.VolumeConfig{ -// Name: "vol-1", -// Size: "1GiB", -// Attributes: map[string]sa.Request{ -// "fakeattrib": sa.NewStringRequest("fakeval"), -// }, -// Internal: true, -// AccessMode: tridentconfig.ReadWriteOnce, -// }, -// }, -// }) +// runRecoveryTests(t, orchestrator, "test-backend", storage.AddVolume, addRecoveryTests) // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func runRecoveryTests( t *testing.T, orchestrator *TridentOrchestrator, @@ -2122,11 +2116,12 @@ func runRecoveryTests( } } -// TestAddVolumeRecovery tests that adding a volume is properly recovered -// from a transaction failure. -// It checks that the volume is properly created and destroyed. +// TestAddVolumeRecovery tests that adding a volume is properly rolled back +// when the transaction is rolled back. +// It checks both the case where the volume is added to the orchestrator and +// the case where it is only added to the transaction. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestAddVolumeRecovery(t *testing.T) { const ( backendName = "addRecoveryBackend" @@ -2155,11 +2150,12 @@ func TestAddVolumeRecovery(t *testing.T) { cleanup(t, orchestrator) } -// TestAddVolumeWithTMRNonONTAPNAS tests that a volume with a TMR relationship -// to a non-ONTAP NAS backend fails to be added -// It checks that the error message is as expected +// TestAddVolumeWithTMRNonONTAPNAS tests that we fail to add a volume with +// a relationship annotation if the backend is not ONTAP NAS +// It checks that we fail to add a volume with a relationship annotation +// if the backend is not ONTAP NAS // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestAddVolumeWithTMRNonONTAPNAS(t *testing.T) { // Add a single backend of fake // create volume with relationship annotation added @@ -2186,10 +2182,12 @@ func TestAddVolumeWithTMRNonONTAPNAS(t *testing.T) { cleanup(t, orchestrator) } -// TestDeleteVolumeRecovery tests the recovery of a volume delete. -// It checks that the volume is removed from the orchestrator, but not destroyed. +// TestDeleteVolumeRecovery tests that the orchestrator can recover from a +// partially completed volume deletion. +// It checks that the orchestrator can recover from deleting a volume that +// has been partially deleted. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestDeleteVolumeRecovery(t *testing.T) { const ( backendName = "deleteRecoveryBackend" @@ -2225,17 +2223,17 @@ func TestDeleteVolumeRecovery(t *testing.T) { cleanup(t, orchestrator) } -// generateSnapshotConfig returns a SnapshotConfig object with the specified name and volume +// generateSnapshotConfig returns a SnapshotConfig object // Parameters: -// name - the name of the snapshot -// volumeName - the name of the volume to snapshot -// volumeInternalName - the internal name of the volume to snapshot +// name: name of the snapshot +// volumeName: name of the volume +// volumeInternalName: internal name of the volume // Returns: // SnapshotConfig object // Example: -// snapshotConfig := generateSnapshotConfig("snapshot-name", "volume-name", "volume-internal-name") +// config := generateSnapshotConfig("snapshot-name", "volume-name", "volume-internal-name") // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func generateSnapshotConfig( name, volumeName, volumeInternalName string, ) *storage.SnapshotConfig { @@ -2247,28 +2245,31 @@ func generateSnapshotConfig( } } -// runSnapshotRecoveryTests runs a set of tests to verify that the orchestrator -// is able to recover from a partially completed snapshot addition. +// runSnapshotRecoveryTests runs a set of tests that verify that the orchestrator +// can recover from a partially completed snapshot operation. // Parameters: -// t: The test object -// orchestrator: The orchestrator object to use for the tests -// backendName: The name of the backend to use for the tests -// op: The operation to test (AddSnapshot or DeleteSnapshot) -// testCases: A slice of recoveryTest objects describing the tests to run +// t: the test object +// orchestrator: the orchestrator to test +// backendName: the name of the backend to use +// op: the operation to test +// testCases: a slice of recoveryTest objects that describe the test cases to run // Returns: // None // Example: -// runSnapshotRecoveryTests(t, orchestrator, "fake", storage.DeleteSnapshot, -// []recoveryTest{ -// { -// name: "SnapshotDeleted", -// volumeConfig: &storage.VolumeConfig{}, -// snapshotConfig: &storage.SnapshotConfig{}, -// expectDestroy: true, -// }, -// }) +// runSnapshotRecoveryTests(t, orchestrator, "fake-backend", storage.AddSnapshot, []recoveryTest{ +// { +// name: "AddSnapshot - volume not found", +// volumeConfig: &storage.VolumeConfig{ +// Name: "snap-vol-not-found", +// }, +// snapshotConfig: &storage.SnapshotConfig{ +// Name: "snap-not-found", +// }, +// expectDestroy: false, +// }, +// }) // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func runSnapshotRecoveryTests( t *testing.T, orchestrator *TridentOrchestrator, @@ -2329,11 +2330,13 @@ func runSnapshotRecoveryTests( } } -// TestAddSnapshotRecovery tests the recovery of AddSnapshot transactions. -// It checks that the snapshot is deleted if the transaction was fully committed, -// and that the snapshot is not deleted if the transaction was only partially committed. +// TestAddSnapshotRecovery tests that the AddSnapshot transaction is properly +// recovered. +// It checks that the snapshot is created and destroyed when the transaction +// is fully recovered, and that the snapshot is not destroyed when only the +// transaction is recovered. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestAddSnapshotRecovery(t *testing.T) { const ( backendName = "addSnapshotRecoveryBackend" @@ -2373,12 +2376,13 @@ func TestAddSnapshotRecovery(t *testing.T) { cleanup(t, orchestrator) } -// TestDeleteSnapshotRecovery tests that snapshot delete transactions are properly -// recovered. -// It checks that the snapshot is not deleted if the snapshot exists, and that the -// snapshot is deleted if the snapshot does not exist. +// TestDeleteSnapshotRecovery tests that delete snapshot transactions are properly +// recovered after a restart. +// It checks that the snapshot is not deleted if the snapshot was fully deleted +// before the restart, and that the snapshot is deleted if the snapshot was only +// partially deleted before the restart. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestDeleteSnapshotRecovery(t *testing.T) { const ( backendName = "deleteSnapshotRecoveryBackend" @@ -2426,11 +2430,11 @@ func TestDeleteSnapshotRecovery(t *testing.T) { // The next series of tests test that bootstrap doesn't exit early if it // encounters a key error for one of the main types of entries. // TestStorageClassOnlyBootstrap tests that a storage class can be bootstrapped -// without any other objects. +// without any volumes. // It checks that the storage class is bootstrapped and that it matches the -// original storage class. +// original. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestStorageClassOnlyBootstrap(t *testing.T) { const scName = "storageclass-only" @@ -2458,10 +2462,13 @@ func TestStorageClassOnlyBootstrap(t *testing.T) { cleanup(t, orchestrator) } -// TestFirstVolumeRecovery tests that the first volume in a backend is recovered correctly -// It checks that the volume is destroyed and recreated +// TestFirstVolumeRecovery tests the first volume recovery scenario. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// The first volume recovery scenario is when the first volume is added to a +// backend. +// It checks that the volume is destroyed. +// +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestFirstVolumeRecovery(t *testing.T) { const ( backendName = "firstRecoveryBackend" @@ -2483,11 +2490,11 @@ func TestFirstVolumeRecovery(t *testing.T) { cleanup(t, orchestrator) } -// TestOrchestratorNotReady tests the behavior of the orchestrator when it is not ready. -// It checks that all the orchestrator methods return an error. +// TestOrchestratorNotReady tests the orchestrator when it is not ready. +// It checks that all orchestrator methods return an error. // It returns an error if any of the methods do not return an error. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestOrchestratorNotReady(t *testing.T) { var ( @@ -2627,22 +2634,22 @@ func TestOrchestratorNotReady(t *testing.T) { } } -// importVolumeSetup is a helper function for tests that need to -// It returns an orchestrator and a volume config +// importVolumeSetup is a helper function to setup the orchestrator and volume config for +// It returns a pointer to the orchestrator and the volume config // Parameters: -// t - the test object -// backendName - the name of the backend to create -// scName - the name of the storage class to create -// volumeName - the name of the volume to create -// importOriginalName - the original name of the volume to import -// backendProtocol - the protocol of the backend to create +// t *testing.T - the test object +// backendName - the name of the backend +// scName - the name of the storage class +// volumeName - the name of the volume +// importOriginalName - the original name of the volume being imported +// backendProtocol - the protocol of the backend // Returns: -// *TridentOrchestrator - the orchestrator object -// *storage.VolumeConfig - the volume config object +// *TridentOrchestrator - a pointer to the orchestrator +// *storage.VolumeConfig - the volume config // Example: -// orchestrator, volumeConfig := importVolumeSetup(t, "backend1", "sc1", "vol1", "originalVolName", config.File) +// orchestrator, volumeConfig := importVolumeSetup(t, "backend1", "sc1", "volume1", "volume2", config.File) // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func importVolumeSetup( t *testing.T, backendName string, scName string, volumeName string, importOriginalName string, backendProtocol config.Protocol, @@ -2676,14 +2683,14 @@ func importVolumeSetup( return orchestrator, volumeConfig } -// TestImportVolumeFailures tests that importVolumeCleanup is called when -// importVolumeSetup fails -// It checks that the volume is renamed to the original name and that the -// persisted state is cleaned up -// It returns an error if the volume is not renamed or if the persisted state -// is not cleaned up +// TestImportVolumeFailures tests the behavior of the orchestrator when +// importing a volume fails. +// It checks that the volume is renamed to its original name, and that +// the persisted state is cleaned up. +// It returns an error if the volume is not renamed, or if the persisted +// state is not cleaned up. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestImportVolumeFailures(t *testing.T) { const ( backendName = "backend82" @@ -2724,11 +2731,11 @@ func TestImportVolumeFailures(t *testing.T) { } // TestLegacyImportVolume tests the legacy -// It checks that the volume is imported with the expected name and that it is persisted -// if it is managed. -// It returns the volumeExternal and the volumeConfig. +// It checks that the volume is imported correctly and that the volume is +// persisted if it is managed. +// It returns the volume name and the volume config. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestLegacyImportVolume(t *testing.T) { const ( backendName = "backend02" @@ -2806,10 +2813,11 @@ func TestLegacyImportVolume(t *testing.T) { cleanup(t, orchestrator) } -// TestImportVolume tests the ImportVolume method -// It checks that the volume is persisted and that the internal name is correct +// TestImportVolume tests the +// It checks that the volume is imported with the correct internal name +// and that it is persisted in the orchestrator's volume map. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestImportVolume(t *testing.T) { const ( backendName = "backend02" @@ -2867,16 +2875,16 @@ func TestImportVolume(t *testing.T) { cleanup(t, orchestrator) } -// TestValidateImportVolumeNasBackend tests the validateImportVolume function for NAS backends. +// TestValidateImportVolumeNasBackend tests the validateImportVolume function for NAS backends // It checks for the following error conditions: -// - The volume already exists +// - The volume exists on the backend with the original name // - The storage class is unknown // - The volume does not exist on the backend -// - The volume is not compatible with the access mode -// - The volume is not compatible with the volume mode -// - The volume is not compatible with the protocol +// - The volume has an incompatible access mode +// - The volume has an incompatible volume mode +// - The volume has an incompatible protocol // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestValidateImportVolumeNasBackend(t *testing.T) { const ( backendName = "backend01" @@ -2956,11 +2964,35 @@ func TestValidateImportVolumeNasBackend(t *testing.T) { } // TestValidateImportVolumeSanBackend tests the validateImportVolume function for SAN backends. -// It checks for the following error conditions: -// - Protocol is not compatible with the backend -// - FileSystem is not compatible with the backend +// It checks the following conditions: +// - The volume exists on the backend with the original name. +// - The volume is not already imported. +// - The volume is not already attached to a node. +// - The volume is not already in use by a pod. +// - The volume is not already in use by a PVC. +// - The volume is not already in use by a PV. +// - The volume is not already in use by a snapshot. +// - The volume is not already in use by a clone. +// - The volume is not already in use by a volume group. +// - The volume is not already in use by a consistency group. +// - The volume is not already in use by a consistency group snapshot. +// - The volume is not already in use by a consistency group clone. +// - The volume is not already in use by a consistency group view. +// - The volume is not already in use by a snapshot schedule. +// - The volume is not already in use by a snapshot session. +// - The volume is not already in use by a snapshot session clone. +// - The volume is not already in use by a snapshot session view. +// - The volume is not already in use by a snapshot session schedule. +// - The volume is not already in use by an export policy. +// - The volume is not already in use by an export policy rule. +// - The volume is not already in use by an export policy snapshot rule. +// - The volume is not already in use by an export policy clone rule. +// - The volume is not already in use by an export policy view rule. +// - The volume is not already in use by an export policy schedule rule. +// - The volume has the same protocol as the backend. +// - The volume does not have an ext4 filesystem if it's a raw-block volume. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestValidateImportVolumeSanBackend(t *testing.T) { const ( backendName = "backend01" @@ -3022,11 +3054,11 @@ func TestValidateImportVolumeSanBackend(t *testing.T) { cleanup(t, orchestrator) } -// TestAddVolumePublication tests adding a volume publication to the orchestrator -// It checks that the orchestrator calls the store client with the correct object, -// and that the orchestrator's cache is updated correctly +// TestAddVolumePublication tests that the orchestrator correctly adds a volume publication +// to its cache, and calls the store client to persist the volume publication +// It checks that the orchestrator's cache is updated correctly // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestAddVolumePublication(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3059,12 +3091,13 @@ func TestAddVolumePublication(t *testing.T) { "volume publication was not correctly added") } -// TestAddVolumePublicationError tests that the orchestrator returns an error when the store client returns an error -// when adding a volume publication -// It checks that the orchestrator's cache is not updated -// It returns an error +// TestAddVolumePublicationError tests that the orchestrator correctly handles +// errors from the persistent store client +// It checks that the orchestrator does not add the volume publication to its cache +// if the store client returns an error +// It returns an error if the store client returns an error // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestAddVolumePublicationError(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3093,10 +3126,10 @@ func TestAddVolumePublicationError(t *testing.T) { "volume publication was added orchestrator's cache") } -// TestGetVolumePublication tests the GetVolumePublication method -// It checks that the correct volume publication is returned +// TestGetVolumePublication tests that a volume publication can be retrieved from the orchestrator +// It checks that the orchestrator correctly retrieves the volume publication from the cache // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestGetVolumePublication(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3123,10 +3156,10 @@ func TestGetVolumePublication(t *testing.T) { } // TestGetVolumePublicationNotFound tests that a volume publication is not found -// when the volume is not found -// It checks that the correct error is returned +// when the volume does not exist +// It checks that the correct error is returned and that the publication is empty // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestGetVolumePublicationNotFound(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3144,10 +3177,10 @@ func TestGetVolumePublicationNotFound(t *testing.T) { assert.Empty(t, actualPub, "non-empty publication returned") } -// TestGetVolumePublicationError tests the GetVolumePublication function when an error is returned -// It checks that the correct error is returned +// TestGetVolumePublicationError tests the error path for GetVolumePublication +// It checks that the correct error is returned when the orchestrator is in a bootstrap error state // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestGetVolumePublicationError(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3177,10 +3210,10 @@ func TestGetVolumePublicationError(t *testing.T) { assert.Empty(t, actualPub, "non-empty publication returned") } -// TestListVolumePublications tests the ListVolumePublications method -// It checks that the correct list of publications is returned +// TestListVolumePublications tests the ListVolumePublications function +// It checks that the list of volume publications returned is correct // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestListVolumePublications(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3224,11 +3257,10 @@ func TestListVolumePublications(t *testing.T) { assert.ElementsMatch(t, expectedPubs, actualPubs, "incorrect publication list returned") } -// TestListVolumePublicationsNotFound tests the case where there are no volume publications -// in the persistent store -// It checks that the returned list is empty and that there is no error +// TestListVolumePublicationsNotFound tests the case where no volume publications are found +// It checks that the orchestrator returns an empty list and no error // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestListVolumePublicationsNotFound(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3245,12 +3277,11 @@ func TestListVolumePublicationsNotFound(t *testing.T) { assert.Empty(t, actualPubs, "non-empty publication list returned") } -// TestListVolumePublicationsError tests that ListVolumePublications returns an error if the -// orchestrator is in an error state -// It checks that the orchestrator returns an error if it is in an error state -// It checks that the orchestrator returns an empty list of publications +// TestListVolumePublicationsError tests the ListVolumePublications method +// when the orchestrator is in an error state +// It checks that the method returns an error and an empty list // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestListVolumePublicationsError(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3281,9 +3312,9 @@ func TestListVolumePublicationsError(t *testing.T) { } // TestListVolumePublicationsForVolume tests the ListVolumePublicationsForVolume function -// It checks that the correct list of publications is returned +// It checks that the correct publications are returned for a given volume // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestListVolumePublicationsForVolume(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3327,11 +3358,11 @@ func TestListVolumePublicationsForVolume(t *testing.T) { assert.ElementsMatch(t, expectedPubs, actualPubs, "incorrect publication list returned") } -// TestListVolumePublicationsForVolumeNotFound tests the ListVolumePublicationsForVolume method -// when the volume is not found -// It checks that an empty list is returned +// TestListVolumePublicationsForVolumeNotFound tests the case where a volume is not found +// when listing volume publications +// It checks that an empty list is returned with no error // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestListVolumePublicationsForVolumeNotFound(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3359,9 +3390,9 @@ func TestListVolumePublicationsForVolumeNotFound(t *testing.T) { } // TestListVolumePublicationsForVolumeError tests the error path of ListVolumePublicationsForVolume -// It checks that the orchestrator returns an error when it is in a bootstrap error state +// It checks that the correct error is returned when the orchestrator is in an error state // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestListVolumePublicationsForVolumeError(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3391,10 +3422,11 @@ func TestListVolumePublicationsForVolumeError(t *testing.T) { assert.Empty(t, actualPubs, "non-empty publication list returned") } -// TestListVolumePublicationsForNode tests the ListVolumePublicationsForNode method +// TestListVolumePublicationsForNode tests the ListVolumePublicationsForNode +// method of the orchestrator // It checks that the correct publications are returned for a given node // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestListVolumePublicationsForNode(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3438,11 +3470,11 @@ func TestListVolumePublicationsForNode(t *testing.T) { assert.ElementsMatch(t, expectedPubs, actualPubs, "incorrect publication list returned") } -// TestListVolumePublicationsForNodeNotFound tests that ListVolumePublicationsForNode returns an empty list when -// the node is not found. -// It checks that the orchestrator does not return an error when the node is not found. +// TestListVolumePublicationsForNodeNotFound tests that ListVolumePublicationsForNode returns an empty list +// when the node is not found +// It checks that the orchestrator returns an empty list when the node is not found // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestListVolumePublicationsForNodeNotFound(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3469,11 +3501,11 @@ func TestListVolumePublicationsForNodeNotFound(t *testing.T) { assert.Empty(t, actualPubs, "non-empty publication list returned") } -// TestListVolumePublicationsForNodeError tests the case where there is an error -// during bootstrap. -// It checks that the error is returned to the caller. +// TestListVolumePublicationsForNodeError tests the case where the orchestrator +// is in an error state and we attempt to list volume publications for a node +// It checks that the error is returned and no publications are returned // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestListVolumePublicationsForNodeError(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3504,10 +3536,9 @@ func TestListVolumePublicationsForNodeError(t *testing.T) { } // TestDeleteVolumePublication tests the DeleteVolumePublication method -// It checks that the volume publication is removed from the cache -// and that the volume entry is removed from the cache if this is the last nodeID for a given volume +// It checks that the volume publication is removed from the cache and the store // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestDeleteVolumePublication(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3564,10 +3595,11 @@ func TestDeleteVolumePublication(t *testing.T) { "publication not properly removed from cache") } -// TestDeleteVolumePublicationNotFound tests that an error is returned when a volume publication is not found -// It checks that the correct error +// TestDeleteVolumePublicationNotFound tests that a volume publication is not found +// when attempting to delete a volume publication that does not exist +// It checks that the correct error is returned // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestDeleteVolumePublicationNotFound(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3595,12 +3627,12 @@ func TestDeleteVolumePublicationNotFound(t *testing.T) { } // TestDeleteVolumePublicationNotFoundPersistence tests that the orchestrator -// handles the case where a volume publication is not found in the persistence -// layer. +// handles the case where a volume publication is not found in the persistent +// store. // It checks that the orchestrator does not return an error and that the // publication is removed from the cache. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestDeleteVolumePublicationNotFoundPersistence(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3630,10 +3662,11 @@ func TestDeleteVolumePublicationNotFoundPersistence(t *testing.T) { "publication not properly removed from cache") } -// TestDeleteVolumePublicationError tests the error path for deleting a volume publication -// It checks that the error is returned and that the cache is not updated +// TestDeleteVolumePublicationError tests the DeleteVolumePublication function +// when an error is returned from the persistent store +// It checks that the volume publication is not removed from the cache // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestDeleteVolumePublicationError(t *testing.T) { mockCtrl := gomock.NewController(t) // Create a mocked persistent store client @@ -3664,10 +3697,10 @@ func TestDeleteVolumePublicationError(t *testing.T) { "publication improperly removed/updated in cache") } -// TestAddNode tests adding a node to the orchestrator +// TestAddNode tests adding a node // It checks that the node is added to the orchestrator // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestAddNode(t *testing.T) { node := &utils.Node{ Name: "testNode", @@ -3684,9 +3717,8 @@ func TestAddNode(t *testing.T) { // TestGetNode tests the GetNode method // It checks that the expected node is returned -// It checks that an error is returned if the node does not exist // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestGetNode(t *testing.T) { orchestrator := getOrchestrator(t) expectedNode := &utils.Node{ @@ -3718,10 +3750,10 @@ func TestGetNode(t *testing.T) { } } -// TestListNodes tests that the orchestrator can list nodes -// It checks that the orchestrator returns the correct nodes +// TestListNodes tests the ListNodes method +// It checks that the returned list of nodes matches the expected list // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestListNodes(t *testing.T) { orchestrator := getOrchestrator(t) expectedNode1 := &utils.Node{ @@ -3753,18 +3785,19 @@ func TestListNodes(t *testing.T) { } // unorderedNodeSlicesEqual compares two slices of nodes for equality. -// The order of the nodes in the slices is not considered. -// It returns true if the slices contain the same nodes. +// The order of the slices is not considered. +// It returns true if the slices are equal, false otherwise. // Parameters: -// x, y - the slices to compare +// x: first slice of nodes +// y: second slice of nodes // Returns: -// bool - true if the slices contain the same nodes +// bool: true if the slices are equal, false otherwise // Example: -// x := []*utils.Node{n1, n2, n3} -// y := []*utils.Node{n3, n2, n1} -// unorderedNodeSlicesEqual(x, y) // returns true +// x := []*utils.Node{n1, n2} +// y := []*utils.Node{n2, n1} +// unorderedNodeSlicesEqual(x, y) // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func unorderedNodeSlicesEqual(x, y []*utils.Node) bool { if len(x) != len(y) { return false @@ -3788,10 +3821,10 @@ func unorderedNodeSlicesEqual(x, y []*utils.Node) bool { return len(diff) == 0 } -// TestDeleteNode tests the DeleteNode method +// TestDeleteNode tests the DeleteNode function // It checks that the node is properly deleted // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestDeleteNode(t *testing.T) { orchestrator := getOrchestrator(t) initialNode := &utils.Node{ @@ -3813,10 +3846,11 @@ func TestDeleteNode(t *testing.T) { } } -// TestSnapshotVolumes tests snapshotting volumes. -// It checks that the snapshot is created and deleted correctly. +// TestSnapshotVolumes tests the ability to create and delete snapshots. +// It checks that the snapshot is created in the correct pool, and that +// the snapshot is correctly stored in the persistent store. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestSnapshotVolumes(t *testing.T) { mockPools := tu.GetFakePools() orchestrator := getOrchestrator(t) @@ -4023,9 +4057,10 @@ func TestSnapshotVolumes(t *testing.T) { } // TestGetProtocol tests the getProtocol function -// It checks for all the valid and invalid combinations of volumeMode, accessMode and protocol +// It checks for all the possible combinations of volumeMode, accessMode and protocol +// and checks if the function returns the expected protocol // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestGetProtocol(t *testing.T) { orchestrator := getOrchestrator(t) @@ -4095,11 +4130,11 @@ func TestGetProtocol(t *testing.T) { } } -// TestGetBackend tests the GetBackend function +// TestGetBackend tests the GetBackend method // It checks that the correct object is returned // It returns an error if the backend does not exist // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestGetBackend(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -4134,11 +4169,11 @@ func TestGetBackend(t *testing.T) { assert.Equal(t, expectedBackendExternal, actualBackendExternal, "Did not get the expected backend object") } -// TestGetBackendByBackendUUID tests the GetBackendByBackendUUID function +// TestGetBackendByBackendUUID tests the GetBackendByBackendUUID method // It checks that the correct backend is returned // It returns an error if the backend does not exist // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestGetBackendByBackendUUID(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -4169,11 +4204,11 @@ func TestGetBackendByBackendUUID(t *testing.T) { assert.Equal(t, expectedBackendExternal, actualBackendExternal, "Did not get the expected backend object") } -// TestListBackends tests the ListBackends function +// TestListBackends tests the ListBackends method // It checks that the expected list of backends is returned // It returns an error if the list of backends is not as expected // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestListBackends(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -4211,11 +4246,10 @@ func TestListBackends(t *testing.T) { } // TestDeleteBackend tests the DeleteBackend method -// It checks that the backend is set to deleting, set offline, and terminated -// It also checks that the backend is removed from the orchestrator's backend map +// It checks that the backend is properly deleted from the orchestrator // It returns an error if the backend is not found // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestDeleteBackend(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -4261,9 +4295,9 @@ func TestDeleteBackend(t *testing.T) { } // TestPublishVolume tests the PublishVolume function -// It checks that the correct backend is called and that the volume is updated in the persistent store +// It checks that the correct calls are made to the backend // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestPublishVolume(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -4296,12 +4330,10 @@ func TestPublishVolume(t *testing.T) { } // TestPublishVolumeFailedToUpdatePersistentStore tests the case where the -// orchestrator fails to update the persistent store after a successful publish -// operation. -// It checks that the orchestrator returns the error from the persistent store -// client. +// persistent store fails to update the volume. +// It checks that the error is returned to the caller. // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestPublishVolumeFailedToUpdatePersistentStore(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -4338,10 +4370,10 @@ func TestPublishVolumeFailedToUpdatePersistentStore(t *testing.T) { } // TestGetCHAP tests the GetCHAP method of the orchestrator -// It checks that the correct backend is called and that the -// returned chap info is correct +// It checks that the orchestrator correctly calls the backend +// and returns the expected chap info // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestGetCHAP(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) @@ -4374,10 +4406,10 @@ func TestGetCHAP(t *testing.T) { assert.Equal(t, expectedChapInfo, actualChapInfo, "Unexpected chap info returned.") } -// TestGetCHAPFailure tests the failure path of the GetCHAP function -// It checks that the correct error is returned +// TestGetCHAPFailure tests the GetCHAP method +// It checks that the correct error is returned when the backend returns an error // -// -- Doc autogenerated on 2022-05-12 18:24:02.136775 -- +// -- Doc autogenerated on 2022-05-12 20:34:25.796588 -- func TestGetCHAPFailure(t *testing.T) { // Boilerplate mocking code mockCtrl := gomock.NewController(t) diff --git a/core/transaction_monitor_test.go b/core/transaction_monitor_test.go index 1e03b29c6..e776e332a 100644 --- a/core/transaction_monitor_test.go +++ b/core/transaction_monitor_test.go @@ -31,13 +31,13 @@ func init() { // waitForTransactionMontitorToStart waits for the transaction monitor to start // Parameters: -// o: the orchestrator +// o - the orchestrator // Returns: // none // Example: // waitForTransactionMontitorToStart(o) // -// -- Doc autogenerated on 2022-05-12 18:37:26.431118 -- +// -- Doc autogenerated on 2022-05-12 20:47:43.548344 -- func waitForTransactionMontitorToStart(o *TridentOrchestrator) { if o.txnMonitorChannel == nil { time.Sleep(1 * time.Second) @@ -45,9 +45,12 @@ func waitForTransactionMontitorToStart(o *TridentOrchestrator) { } // TestStartStop tests the start and stop of the transaction monitor -// It checks that the transaction monitor is started and stopped correctly +// It checks that the transaction monitor channel is not nil and that +// the transaction monitor is not stopped when it is started. +// It then checks that the transaction monitor is stopped when StopTransactionMonitor() +// is called. // -// -- Doc autogenerated on 2022-05-12 18:37:26.431118 -- +// -- Doc autogenerated on 2022-05-12 20:47:43.548344 -- func TestStartStop(t *testing.T) { storeClient := persistentstore.NewInMemoryClient() @@ -105,7 +108,6 @@ func TestLongRunningTransaction(t *testing.T) { // TestCancelledLongRunningTransaction tests that a transaction older than the max age is cancelled. func TestCancelledLongRunningTransaction(t *testing.T) { -func TestLongRunningTransaction(t *testing.T) { o, storeClient := setupOrchestratorAndBackend(t) restartTransactionMonitor(o) @@ -135,13 +137,11 @@ func TestLongRunningTransaction(t *testing.T) { } // TestUpdateTransactionVolumeCreatingTransaction tests that a VolumeCreatingTransaction can be updated. -func TestUpdateVolumeCreatingTransaction(t *testing.T) { // TestUpdateVolumeCreatingTransaction tests that we can update a volume creating transaction // and that the updated transaction is persisted. -// It checks that the transaction is created, then updates the transaction and checks that the -// update is persisted. +// It checks that the transaction is updated in the store. // -// -- Doc autogenerated on 2022-05-12 18:37:26.431118 -- +// -- Doc autogenerated on 2022-05-12 20:47:43.548344 -- func TestUpdateVolumeCreatingTransaction(t *testing.T) { o, storeClient := setupOrchestratorAndBackend(t) restartTransactionMonitor(o) @@ -215,13 +215,11 @@ func TestErrorVolumeCreatingTransaction(t *testing.T) { } // TestVolumeCreatingTwoTransaction tests that two volumeCreatingTransactions work as expected -func TestVolumeCreatingTwoTransactions(t *testing.T) { -// TestVolumeCreatingTwoTransactions tests that the orchestrator can handle two volume creating transactions. -// This is a regression test for BUG-724 -// It checks that the orchestrator can handle two volume creating transactions. -// It also checks that the orchestrator can handle a volume creating transaction and a clone transaction. +// TestVolumeCreatingTwoTransactions tests that two volume creating transactions can be created and +// that the second transaction is not deleted when the first transaction is deleted. +// It checks that the second transaction is deleted when the second transaction is deleted. // -// -- Doc autogenerated on 2022-05-12 18:37:26.431118 -- +// -- Doc autogenerated on 2022-05-12 20:47:43.548344 -- func TestVolumeCreatingTwoTransactions(t *testing.T) { o, storeClient := setupOrchestratorAndBackend(t) restartTransactionMonitor(o) @@ -287,23 +285,17 @@ func TestVolumeCreatingTwoTransactions(t *testing.T) { } // setupOrchestratorAndBackend creates a new orchestrator and backend -// and returns them. -// It returns the orchestrator and the backend. -// It also returns the backend name and the storage class name. +// for use in tests. +// It returns the orchestrator and the store client. // Parameters: -// t: the test object -// backendName: the name of the backend to create -// storageClassName: the name of the storage class to create -// provisioningType: the provisioning +// t - the test object // Returns: -// o: the orchestrator -// storeClient: the persistent store client -// backendName: the name of the backend -// storageClassName: the name of the storage class +// *TridentOrchestrator - the orchestrator +// *persistentstore.InMemoryClient - the store client // Example: -// o, _, _, _ := setupOrchestratorAndBackend(t, "fakeOne", "slow", "thin") +// o, storeClient := setupOrchestratorAndBackend(t) // -// -- Doc autogenerated on 2022-05-12 18:37:26.431118 -- +// -- Doc autogenerated on 2022-05-12 20:47:43.548344 -- func setupOrchestratorAndBackend(t *testing.T) (*TridentOrchestrator, *persistentstore.InMemoryClient) { storeClient := persistentstore.NewInMemoryClient() o := NewTridentOrchestrator(storeClient) @@ -344,17 +336,16 @@ func setupOrchestratorAndBackend(t *testing.T) (*TridentOrchestrator, *persisten return o, storeClient } -// restartTransactionMonitor is a helper function to restart the transaction monitor -// with testable limits. +// restartTransactionMonitor stops and restarts the transaction monitor with testable limits. // Parameters: -// o - TridentOrchestrator instance +// o: The orchestrator. // Returns: -// None +// None. // Example: // o := NewTridentOrchestrator(...) // restartTransactionMonitor(o) // -// -- Doc autogenerated on 2022-05-12 18:37:26.431118 -- +// -- Doc autogenerated on 2022-05-12 20:47:43.548344 -- func restartTransactionMonitor(o *TridentOrchestrator) { // Bootstrap starts the transaction monitor. diff --git a/operator/controllers/orchestrator/apis/netapp/v1/register.go b/operator/controllers/orchestrator/apis/netapp/v1/register.go index d3e708ca1..c086be90d 100644 --- a/operator/controllers/orchestrator/apis/netapp/v1/register.go +++ b/operator/controllers/orchestrator/apis/netapp/v1/register.go @@ -21,7 +21,6 @@ func Kind(kind string) schema.GroupKind { // Resource takes an unqualified resource and returns back a Group qualified GroupResource func Resource(resource string) schema.GroupResource { -func Kind(kind string) schema.GroupKind { return SchemeGroupVersion.WithResource(resource).GroupResource() } @@ -31,19 +30,19 @@ var ( ) // Adds the list of known types to the given scheme. -func addKnownTypes(scheme *runtime.Scheme) error { // addKnownTypes adds the set of types defined in this // It returns the SchemeBuilder // Parameters: -// scheme: the SchemeBuilder instance -// addToScheme: the function to add the types to the scheme +// scheme *runtime.Scheme +// builder *runtime.SchemeBuilder +// config *rest.Config +// options runtime.SchemeBuilderOptions // Returns: -// the SchemeBuilder instance +// error // Example: -// s := runtime.NewScheme() // addKnownTypes(s) // -// -- Doc autogenerated on 2022-05-12 18:41:46.879131 -- +// -- Doc autogenerated on 2022-05-12 20:51:57.584496 -- func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &TridentOrchestrator{}, diff --git a/operator/controllers/orchestrator/apis/netapp/v1/types.go b/operator/controllers/orchestrator/apis/netapp/v1/types.go index 0999e78ce..754d28909 100644 --- a/operator/controllers/orchestrator/apis/netapp/v1/types.go +++ b/operator/controllers/orchestrator/apis/netapp/v1/types.go @@ -67,15 +67,27 @@ type Toleration struct { TolerationSeconds int `json:"tolerationSeconds,omitempty"` } -// GetMap returns a map of toleration +// GetMap returns a map representation of the Toleration // Returns: // map[string]string // Example: -// toleration := v1.Toleration{"key": "app", "operator": "Equal", "value": "abc"} +// toleration := Toleration{ +// Key: "key", +// Effect: "NoSchedule", +// Value: "value", +// Operator: "Exists", +// TolerationSeconds: 10, +// } // toleration.GetMap() -// => map[string]string{"key": "app", "operator": "Equal", "value": "abc"} +// >>> map[string]string{ +// "key": "key", +// "effect": "NoSchedule", +// "value": "value", +// "operator": "Exists", +// "tolerationSeconds": "10", +// } // -// -- Doc autogenerated on 2022-05-12 18:42:04.843308 -- +// -- Doc autogenerated on 2022-05-12 20:52:19.775422 -- func (t *Toleration) GetMap() map[string]string { toleration := map[string]string{} diff --git a/operator/controllers/orchestrator/client/clientset/versioned/fake/clientset_generated.go b/operator/controllers/orchestrator/client/clientset/versioned/fake/clientset_generated.go index 1d7ec805b..e386d258d 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/fake/clientset_generated.go +++ b/operator/controllers/orchestrator/client/clientset/versioned/fake/clientset_generated.go @@ -52,30 +52,30 @@ type Clientset struct { tracker testing.ObjectTracker } -func (c *Clientset) Discovery() discovery.DiscoveryInterface { // Discovery retrieves the DiscoveryClient // It returns a fake implementation of the DiscoveryClient // Returns: -// *discovery.DiscoveryClient +// * fake.DiscoveryClient // Example: -// discoveryClient := fake.Clientset{}.Discovery() +// discovery := fake.Discovery() // -// -- Doc autogenerated on 2022-05-12 18:42:24.343390 -- +// -- Doc autogenerated on 2022-05-12 20:52:36.883752 -- func (c *Clientset) Discovery() discovery.DiscoveryInterface { return c.discovery } -// Tracker is a fake implementation of a Tracker. -// It returns fake objects. +// Tracker is a fake implementation of the ObjectTracker interface. +// It returns the same object for all calls to GetObject. // Returns: -// * fake.Clientset -// * fake.Tracker +// - the object passed to NewTracker +// - an error if the object passed to NewTracker is nil // Example: -// clientset, tracker := testing.NewClientsetTracker() -// k8sclient := clientset.Kubernetes() -// tracker.AddObj(k8sclient.Core().Services("ns1").Get("svc1", metav1.GetOptions{})) +// tracker := fake.NewTracker(obj) +// tracker.GetObject() == obj +// tracker.GetObject() == obj +// tracker.GetObject() == obj // -// -- Doc autogenerated on 2022-05-12 18:42:24.343390 -- +// -- Doc autogenerated on 2022-05-12 20:52:36.883752 -- func (c *Clientset) Tracker() testing.ObjectTracker { return c.tracker } diff --git a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go b/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go index 8e7c07378..e51596bf0 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go +++ b/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go @@ -16,11 +16,11 @@ type FakeTridentV1 struct { // TridentOrchestrators returns a TridentOrchestratorInterface. // Returns: -// * FakeTridentOrchestrators +// * TridentOrchestratorInterface // Example: -// * tridentOrchestrators := fake.TridentOrchestrators() +// tridentOrchestrator := fake.TridentOrchestrators() // -// -- Doc autogenerated on 2022-05-12 18:43:38.177255 -- +// -- Doc autogenerated on 2022-05-12 20:53:49.042127 -- func (c *FakeTridentV1) TridentOrchestrators() v1.TridentOrchestratorInterface { return &FakeTridentOrchestrators{c} } diff --git a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/netapp_client.go b/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/netapp_client.go index a52de5ac1..3cd80882e 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/netapp_client.go +++ b/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/netapp_client.go @@ -24,9 +24,10 @@ type TridentV1Client struct { // Returns: // * TridentOrchestratorInterface // Example: -// trident, err := client.TridentV1().TridentOrchestrators() +// * tridentClient := v1.NewTridentV1Client(...) +// * tridentOrchestratorInterface := tridentClient.TridentOrchestrators() // -// -- Doc autogenerated on 2022-05-12 18:43:04.890052 -- +// -- Doc autogenerated on 2022-05-12 20:53:17.470904 -- func (c *TridentV1Client) TridentOrchestrators() TridentOrchestratorInterface { return newTridentOrchestrators(c) } @@ -47,7 +48,6 @@ func NewForConfig(c *rest.Config) (*TridentV1Client, error) { // NewForConfigOrDie creates a new TridentV1Client for the given config and // panics if there is an error in the config. func NewForConfigOrDie(c *rest.Config) *TridentV1Client { -func NewForConfig(c *rest.Config) (*TridentV1Client, error) { client, err := NewForConfig(c) if err != nil { panic(err) @@ -57,25 +57,22 @@ func NewForConfig(c *rest.Config) (*TridentV1Client, error) { // New creates a new TridentV1Client for the given RESTClient. func New(c rest.Interface) *TridentV1Client { -func NewForConfigOrDie(c *rest.Config) *TridentV1Client { return &TridentV1Client{c} } -func setConfigDefaults(config *rest.Config) error { -// setConfigDefaults sets default values for rest.Config -// It returns an error if the supplied config is invalid. +// setConfigDefaults sets the default values for the provided config +// It returns an error if the config is invalid // Parameters: -// config - the rest.Config object to set defaults for +// config: the config to set defaults on // Returns: -// error - an error if the supplied config is invalid +// error: if the config is invalid // Example: -// config := &rest.Config{} -// err := setConfigDefaults(config) -// if err != nil { -// return err -// } +// config := &rest.Config{} +// if err := setConfigDefaults(config); err != nil { +// return nil, err +// } // -// -- Doc autogenerated on 2022-05-12 18:43:04.890052 -- +// -- Doc autogenerated on 2022-05-12 20:53:17.470904 -- func setConfigDefaults(config *rest.Config) error { gv := v1.SchemeGroupVersion config.GroupVersion = &gv diff --git a/operator/controllers/orchestrator/client/informers/externalversions/factory.go b/operator/controllers/orchestrator/client/informers/externalversions/factory.go index c6f5ac746..6a86af07c 100644 --- a/operator/controllers/orchestrator/client/informers/externalversions/factory.go +++ b/operator/controllers/orchestrator/client/informers/externalversions/factory.go @@ -47,7 +47,6 @@ func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInfo // WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { -func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { return func(factory *sharedInformerFactory) *sharedInformerFactory { factory.tweakListOptions = tweakListOptions return factory @@ -56,7 +55,6 @@ func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInfo // WithNamespace limits the SharedInformerFactory to the specified namespace. func WithNamespace(namespace string) SharedInformerOption { -func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { return func(factory *sharedInformerFactory) *sharedInformerFactory { factory.namespace = namespace return factory @@ -65,7 +63,6 @@ func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFu // NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { -func WithNamespace(namespace string) SharedInformerOption { return NewSharedInformerFactoryWithOptions(client, defaultResync) } @@ -74,13 +71,11 @@ func WithNamespace(namespace string) SharedInformerOption { // as specified here. // Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { -func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) } // NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { -func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { factory := &sharedInformerFactory{ client: client, namespace: v1.NamespaceAll, @@ -100,7 +95,6 @@ func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync // Start initializes all requested informers. func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { -func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { f.lock.Lock() defer f.lock.Unlock() @@ -114,7 +108,6 @@ func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResy // WaitForCacheSync waits for all started informers' cache were synced. func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { -func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { informers := func() map[reflect.Type]cache.SharedIndexInformer { f.lock.Lock() defer f.lock.Unlock() @@ -137,30 +130,23 @@ func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { // InternalInformerFor returns the SharedIndexInformer for obj using an internal // client. -func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { -// InformerFor returns the SharedIndexInformer for obj using an external client. +// InformerFor is the same as SharedInformerFactory.InformerFor, except it uses the default resync period. +// It returns an informer for the given object type. // Parameters: -// obj - the object +// obj - the object type +// newFunc - a function that returns a new informer for the given object. +// It is usually an anonymous function: +// func(client internalclientset.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { +// return NewFilteredFooInformer(client, resyncPeriod, namespace, tweakListOptions) +// } // Returns: -// SharedIndexInformer +// An informer for the given object type. // Example: -// lister := f.InformerFor(&v1.Pod{}, func(client clientset.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { -// return cache.NewSharedIndexInformer( -// &cache.ListWatch{ -// ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { -// return client.CoreV1().Pods(api.NamespaceAll).List(options) -// }, -// WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { -// return client.CoreV1().Pods(api.NamespaceAll).Watch(options) -// }, -// }, -// &v1.Pod{}, -// resyncPeriod, -// cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, -// ) -// } +// informer := externalversions.InformerFor(&appsv1.Deployment{}, func(client internalclientset.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { +// return NewFilteredDeploymentInformer(client, resyncPeriod, namespace, tweakListOptions) +// }) // -// -- Doc autogenerated on 2022-05-12 18:43:51.155916 -- +// -- Doc autogenerated on 2022-05-12 20:54:01.837641 -- func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { f.lock.Lock() defer f.lock.Unlock() @@ -192,14 +178,15 @@ type SharedInformerFactory interface { Trident() netapp.Interface } -// Trident returns a new Interface. +// Trident is the external version of the API. +// It returns the Trident API client. // Returns: -// - a new Interface -// - error if there is an error initializing the client +// netapp.Interface: Trident API client // Example: -// - tridentClient, err := Trident(config) +// Trident(), err := externalversions.Trident() +// TridentClient := Trident.NetAppV1() // -// -- Doc autogenerated on 2022-05-12 18:43:51.155916 -- +// -- Doc autogenerated on 2022-05-12 20:54:01.837641 -- func (f *sharedInformerFactory) Trident() netapp.Interface { return netapp.New(f, f.namespace, f.tweakListOptions) } diff --git a/operator/controllers/orchestrator/client/informers/externalversions/netapp/v1/tridentorchestrator.go b/operator/controllers/orchestrator/client/informers/externalversions/netapp/v1/tridentorchestrator.go index 804ede7ef..69a28d9ee 100644 --- a/operator/controllers/orchestrator/client/informers/externalversions/netapp/v1/tridentorchestrator.go +++ b/operator/controllers/orchestrator/client/informers/externalversions/netapp/v1/tridentorchestrator.go @@ -41,7 +41,6 @@ func NewTridentOrchestratorInformer(client versioned.Interface, resyncPeriod tim // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. func NewFilteredTridentOrchestratorInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { -func NewTridentOrchestratorInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { return cache.NewSharedIndexInformer( &cache.ListWatch{ ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { @@ -63,34 +62,31 @@ func NewTridentOrchestratorInformer(client versioned.Interface, resyncPeriod tim ) } -func (f *tridentOrchestratorInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { -// defaultInformer is used to informer for TridentOrchestrator resources. -// It returns a SharedIndexInformer which can be used to list and get TridentOrchestrator resources. +// defaultInformer is used to initialize the TridentOrchestrator informer +// It returns a SharedIndexInformer that is used to listen to the TridentOrchestrator custom resource +// and call the TridentOrchestratorInformer(internal) Reconcile function when the resource changes // Parameters: -// client - the kubernetes client +// client - the k8s client // resyncPeriod - the resync period -// indexers - the indexers for the TridentOrchestrator resources +// indexers - used to add/remove indexers for the controller // Returns: -// A SharedIndexInformer +// a SharedIndexInformer // Example: -// lw := cache.NewListWatchFromClient(client, "tridentOrchestrator", v1.NamespaceAll, fields.Everything()) -// i := tridentOrchestrator.NewTridentOrchestratorInformer(lw, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) +// defaultInformer := defaultInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) // -// -- Doc autogenerated on 2022-05-12 18:44:26.289244 -- +// -- Doc autogenerated on 2022-05-12 20:54:47.199556 -- func (f *tridentOrchestratorInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { return NewFilteredTridentOrchestratorInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) } -// Informer for TridentOrchestrator objects. -// It returns a cache.SharedIndexInformer for the TridentOrchestrator type. +// Informer for TridentOrchestrator objects +// It returns a cache.SharedIndexInformer for TridentOrchestrator objects // Returns: // * cache.SharedIndexInformer // Example: -// tridentOrchestratorInformer := informers.NewTridentOrchestratorInformer(...) -// ... -// tridentOrchestrator := tridentOrchestratorInformer.Lister().ByIndex(...) +// tridentOrchestratorInformer := informers.NewTridentOrchestratorInformer(client, 0) // -// -- Doc autogenerated on 2022-05-12 18:44:26.289244 -- +// -- Doc autogenerated on 2022-05-12 20:54:47.199556 -- func (f *tridentOrchestratorInformer) Informer() cache.SharedIndexInformer { return f.factory.InformerFor(&netappv1.TridentOrchestrator{}, f.defaultInformer) } @@ -100,9 +96,9 @@ func (f *tridentOrchestratorInformer) Informer() cache.SharedIndexInformer { // Returns: // * TridentOrchestratorLister // Example: -// lister := listers.NewTridentOrchestratorLister() +// lister := informers.NewTridentOrchestratorInformer().Lister() // -// -- Doc autogenerated on 2022-05-12 18:44:26.289244 -- +// -- Doc autogenerated on 2022-05-12 20:54:47.199556 -- func (f *tridentOrchestratorInformer) Lister() v1.TridentOrchestratorLister { return v1.NewTridentOrchestratorLister(f.Informer().GetIndexer()) } diff --git a/operator/controllers/orchestrator/controller.go b/operator/controllers/orchestrator/controller.go index fc7e74a94..973aa38f2 100644 --- a/operator/controllers/orchestrator/controller.go +++ b/operator/controllers/orchestrator/controller.go @@ -107,20 +107,18 @@ type Controller struct { workqueue workqueue.RateLimitingInterface } -// NewController creates a new TridentOrchestrator controller -// It returns a pointer to the controller and an error if one occurred +// NewController creates a new controller +// It returns the controller and an error if any // Parameters: -// clients - a pointer to the clients struct +// clients - the clients for the controller +// config - the configuration for the controller // Returns: -// *Controller - a pointer to the controller -// error - an error if one occurred +// controller - the controller +// error - any error encountered // Example: -// c, err := NewController(clients) -// if err != nil { -// log.Fatal(err) -// } +// controller, err := NewController(clients, config) // -// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- +// -- Doc autogenerated on 2022-05-12 20:48:56.267584 -- func NewController(clients *clients.Clients) (*Controller, error) { log.WithField("Controller", ControllerName).Info("Initializing controller.") @@ -230,15 +228,16 @@ func NewController(clients *clients.Clients) (*Controller, error) { } // Activate starts the controller -// It returns an error if the controller fails to start. +// It returns an error if the controller cannot be started // Returns: -// error: error starting the controller +// error: error if the controller cannot be started // Example: -// if err := c.Activate(); err != nil { -// log.Fatalf("Failed to start controller: %v", err) +// err := c.Activate() +// if err != nil { +// log.WithError(err) // } // -// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- +// -- Doc autogenerated on 2022-05-12 20:48:56.267584 -- func (c *Controller) Activate() error { log.WithField("Controller", ControllerName).Infof("Activating controller.") @@ -260,17 +259,17 @@ func (c *Controller) Activate() error { return nil } -// Deactivate stops the controller -// It returns an error if the controller could not be stopped +// Deactivate deactivates the controller +// It returns an error if it fails to deactivate the controller // Returns: -// error: an error if the controller could not be stopped +// error: an error if it fails to deactivate the controller // Example: -// err := c.Deactivate() +// err := controller.Deactivate() // if err != nil { -// return err +// log.Errorf("Failed to deactivate controller: %v", err) // } // -// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- +// -- Doc autogenerated on 2022-05-12 20:48:56.267584 -- func (c *Controller) Deactivate() error { log.WithField("Controller", ControllerName).Infof("Deactivating controller.") @@ -283,11 +282,12 @@ func (c *Controller) Deactivate() error { // GetName returns the name of the controller // Returns: -// string: name of the controller +// string: the name of the controller // Example: -// name := c.GetName() +// controller := NewController() +// controller.GetName() // => "controller" // -// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- +// -- Doc autogenerated on 2022-05-12 20:48:56.267584 -- func (c *Controller) GetName() string { return ControllerName } @@ -296,9 +296,13 @@ func (c *Controller) GetName() string { // Returns: // string: the current version of the orchestrator // Example: -// version := orchestrator.Version() +// v, err := c.Version() +// if err != nil { +// log.Errorf("Error getting orchestrator version: %v", err) +// } +// log.Infof("Orchestrator version: %v", v) // -// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- +// -- Doc autogenerated on 2022-05-12 20:48:56.267584 -- func (c *Controller) Version() string { return ControllerVersion } @@ -314,7 +318,6 @@ func (c *Controller) runWorker() { // processNextWorkItem will read a single work item off the workqueue and // attempt to process it, by calling the syncHandler. func (c *Controller) processNextWorkItem() bool { -func (c *Controller) runWorker() { obj, shutdown := c.workqueue.Get() if shutdown { @@ -392,7 +395,6 @@ func (c *Controller) runWorker() { // addOrchestrator is the add handler for the TridentOrchestrator watcher. func (c *Controller) addOrchestrator(obj interface{}) { -func (c *Controller) processNextWorkItem() bool { var key string var err error @@ -423,7 +425,6 @@ func (c *Controller) processNextWorkItem() bool { // updateOrchestrator is the update handler for the TridentOrchestrator watcher. func (c *Controller) updateOrchestrator(oldObj, newObj interface{}) { -func (c *Controller) addOrchestrator(obj interface{}) { _, ok := oldObj.(*netappv1.TridentOrchestrator) if !ok { @@ -468,7 +469,6 @@ func (c *Controller) addOrchestrator(obj interface{}) { // deleteOrchestrator is the delete handler for the TridentOrchestrator watcher. func (c *Controller) deleteOrchestrator(obj interface{}) { -func (c *Controller) updateOrchestrator(oldObj, newObj interface{}) { var key string var err error @@ -499,7 +499,6 @@ func (c *Controller) updateOrchestrator(oldObj, newObj interface{}) { // deploymentAddedOrDeleted is a handler for the trident-csi deployment watcher. func (c *Controller) deploymentAddedOrDeleted(obj interface{}) { -func (c *Controller) deleteOrchestrator(obj interface{}) { var key string var err error @@ -530,7 +529,6 @@ func (c *Controller) deleteOrchestrator(obj interface{}) { // deploymentUpdated is the handler for the trident-csi deployment watcher. func (c *Controller) deploymentUpdated(oldObj interface{}, newObj interface{}) { -func (c *Controller) deploymentAddedOrDeleted(obj interface{}) { var key string var err error @@ -586,7 +584,6 @@ func (c *Controller) deploymentAddedOrDeleted(obj interface{}) { // daemonsetAddedOrDeleted is the handler for the trident-csi daemonset watcher. func (c *Controller) daemonsetAddedOrDeleted(obj interface{}) { -func (c *Controller) deploymentUpdated(oldObj interface{}, newObj interface{}) { var key string var err error @@ -617,7 +614,6 @@ func (c *Controller) deploymentUpdated(oldObj interface{}, newObj interface{}) { // daemonsetUpdated is the handler for the trident-csi daemonset watcher. func (c *Controller) daemonsetUpdated(_ interface{}, newObj interface{}) { -func (c *Controller) daemonsetAddedOrDeleted(obj interface{}) { var key string var err error @@ -655,7 +651,6 @@ func (c *Controller) daemonsetAddedOrDeleted(obj interface{}) { // 2. However, if legacy, CSI Preview or tridentctl based Trident are installed after installing the // operator, these will be removed eventually. func (c *Controller) unsupportedInstallationsPrechecks(controllingCRBasedOnStatusExists, -func (c *Controller) daemonsetUpdated(_ interface{}, newObj interface{}) { operatorCSIDeploymentFound bool) error { // CSI Preview Trident should not be present @@ -713,7 +708,6 @@ func (c *Controller) daemonsetUpdated(_ interface{}, newObj interface{}) { // alphaSnapshotCRDsExist identifies if the alpha snapshot CRDs not present func (c *Controller) alphaSnapshotCRDsExist() (bool, []string, error) { -func (c *Controller) unsupportedInstallationsPrechecks(controllingCRBasedOnStatusExists, var alphaSnapshotCRDsExist bool var alphaSnapshotCRDsList []string @@ -750,7 +744,6 @@ func (c *Controller) unsupportedInstallationsPrechecks(controllingCRBasedOnStatu // alphaSnapshotCRDsPreinstallationCheck identifies if the alpha snapshot CRDs are present before any Trident // installation by the operator func (c *Controller) alphaSnapshotCRDsPreinstallationCheck() error { -func (c *Controller) alphaSnapshotCRDsExist() (bool, []string, error) { alphaSnapshotCRDsExist, alphaSnapshotCRDsList, err := c.alphaSnapshotCRDsExist() if err != nil { @@ -776,7 +769,6 @@ func (c *Controller) alphaSnapshotCRDsExist() (bool, []string, error) { // installation by the operator, this should only be called once controllingCR has been identified and before // installing, patching, updating the Trident func (c *Controller) alphaSnapshotCRDsPostinstallationCheck(tridentCR *netappv1.TridentOrchestrator, -func (c *Controller) alphaSnapshotCRDsPreinstallationCheck() error { currentInstalledTridentVersion string) error { alphaSnapshotCRDsExist, alphaSnapshotCRDsList, err := c.alphaSnapshotCRDsExist() @@ -809,7 +801,6 @@ func (c *Controller) alphaSnapshotCRDsPreinstallationCheck() error { // k8sVersionPreinstallationCheck identifies if K8s version is valid or not func (c *Controller) k8sVersionPreinstallationCheck() error { -func (c *Controller) alphaSnapshotCRDsPostinstallationCheck(tridentCR *netappv1.TridentOrchestrator, isCurrentK8sVersionValid, warningMessage := c.validateCurrentK8sVersion() @@ -828,7 +819,6 @@ func (c *Controller) alphaSnapshotCRDsPostinstallationCheck(tridentCR *netappv1. // handleMigrationScenario identifies if there is a valid Tprov CR with `Installed` status and // if true then operator copies its config to a new Torc CR. func (c *Controller) handleMigrationScenario() error { -func (c *Controller) k8sVersionPreinstallationCheck() error { log.Debug("Verify migration from TridentProvisioner to TridentOrchestrator required.") @@ -919,7 +909,6 @@ func (c *Controller) k8sVersionPreinstallationCheck() error { // reconcile runs the reconcile logic and ensures we move to the desired state and the desired state is // maintained func (c *Controller) reconcile(key KeyItem) error { -func (c *Controller) handleMigrationScenario() error { // Check if there already exists a controllingCR - if deployment is deleted it is possible that we may run // into a situation where there is no deployment but there is a controlling CR @@ -987,20 +976,15 @@ func (c *Controller) handleMigrationScenario() error { } } -func (c *Controller) reconcileTridentNotPresent() error { -// reconcileTridentNotPresent reconciles the state of the cluster when Trident is not installed. -// -// This method will identify a valid TridentOrchestrator CR and install Trident using that CR. -// It returns an error if it fails to install Trident. +// reconcileTridentNotPresent reconciles the case where Trident is not present in the cluster. +// It returns an error if the reconciliation fails. // Returns: -// error: any error encountered +// - nil if the reconciliation succeeds +// - error if the reconciliation fails // Example: -// err := c.reconcileTridentNotPresent() -// if err != nil { -// return err -// } +// - reconcileTridentNotPresent() // -// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- +// -- Doc autogenerated on 2022-05-12 20:48:56.267584 -- func (c *Controller) reconcileTridentNotPresent() error { log.Info("Reconciler found no operator-based Trident installation.") @@ -1085,24 +1069,21 @@ func (c *Controller) reconcileTridentNotPresent() error { return err } -// reconcileTridentPresent reconciles the Trident installation when Trident is present -// -// This function is called when Trident is present, i.e. Trident deployment(s) exist. -// This function identifies the controlling CR for the Trident installation and then -// performs reconcile based on the controlling CR. -// It returns an error if the reconcile fails. +// reconcileTridentPresent reconciles the state of the Trident installation when the Trident deployment exists +// and is controlled by a CR. +// It returns an error if the reconcile failed. // Parameters: -// key: the key of the calling CR -// operatorCSIDeployments: the list of Trident CSI deployments -// deploymentNamespace: the namespace of the calling CR -// isCSI: whether the calling CR is CSI based -// controllingCRBasedOnStatus: the controlling CR based on status +// key - the key of the CR that triggered the reconcile +// operatorCSIDeployments - the list of Trident CSI deployments in the namespace +// deploymentNamespace - the namespace where Trident is installed +// isCSI - true if Trident is installed as a CSI driver, false if it is installed as a Flexvolume driver +// controllingCRBasedOnStatus - the CR that is currently controlling the Trident installation based on its status // Returns: -// error: error if reconcile fails +// error - an error if the reconcile failed // Example: // err := c.reconcileTridentPresent(key, operatorCSIDeployments, deploymentNamespace, isCSI, controllingCRBasedOnStatus) // -// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- +// -- Doc autogenerated on 2022-05-12 20:48:56.267584 -- func (c *Controller) reconcileTridentPresent(key KeyItem, operatorCSIDeployments []appsv1.Deployment, deploymentNamespace string, isCSI bool, controllingCRBasedOnStatus *netappv1.TridentOrchestrator) error { @@ -1379,7 +1360,6 @@ func (c *Controller) controllingCRBasedReconcile(controllingCR *netappv1.Trident // installTridentAndUpdateStatus installs Trident and updates status of the ControllingCR accordingly // based on success or failure func (c *Controller) installTridentAndUpdateStatus(tridentCR netappv1.TridentOrchestrator, -func (c *Controller) controllingCRBasedReconcile(controllingCR *netappv1.TridentOrchestrator, currentInstalledTridentVersion, warningMessage string, shouldUpdate bool) error { var identifiedTridentVersion string @@ -1431,7 +1411,6 @@ func (c *Controller) controllingCRBasedReconcile(controllingCR *netappv1.Trident // uninstallTridentAndUpdateStatus uninstalls Trident and updates status of the ControllingCR accordingly // based on success or failure func (c *Controller) uninstallTridentAndUpdateStatus(tridentCR netappv1.TridentOrchestrator, -func (c *Controller) installTridentAndUpdateStatus(tridentCR netappv1.TridentOrchestrator, currentInstalledTridentVersion string) (*netappv1. TridentOrchestrator, error) { @@ -1482,7 +1461,6 @@ func (c *Controller) installTridentAndUpdateStatus(tridentCR netappv1.TridentOrc // uninstallTridentAll uninstalls Trident CSI, Trident CSI Preview, Trident Legacy func (c *Controller) uninstallTridentAll(namespace string) error { -func (c *Controller) uninstallTridentAndUpdateStatus(tridentCR netappv1.TridentOrchestrator, i, err := installer.NewInstaller(c.KubeConfig, namespace, 0) if err != nil { return err @@ -1499,7 +1477,6 @@ func (c *Controller) uninstallTridentAndUpdateStatus(tridentCR netappv1.TridentO // wipeout removes Trident object specifies in the wipeout list func (c *Controller) wipeout(tridentCR netappv1.TridentOrchestrator) (bool, error) { -func (c *Controller) uninstallTridentAll(namespace string) error { var deletedCRDs bool if len(tridentCR.Spec.Wipeout) > 0 { @@ -1530,7 +1507,6 @@ func (c *Controller) uninstallTridentAll(namespace string) error { // obliviateCRDs calls obliviate functionality, equivalent to: // $ tridentctl obliviate crds func (c *Controller) obliviateCRDs(tridentCR netappv1.TridentOrchestrator) error { -func (c *Controller) wipeout(tridentCR netappv1.TridentOrchestrator) (bool, error) { // Obliviate CRDs Trident i, err := installer.NewInstaller(c.KubeConfig, tridentCR.Status.Namespace, tridentCR.Spec.K8sTimeout) if err != nil { @@ -1550,7 +1526,6 @@ func (c *Controller) wipeout(tridentCR netappv1.TridentOrchestrator) (bool, erro ************************************************/ // ensureTridentOrchestratorCRDExist ensures TridentOrchestrator CRD exist func (c *Controller) ensureTridentOrchestratorCRDExist() error { -func (c *Controller) obliviateCRDs(tridentCR netappv1.TridentOrchestrator) error { i, err := installer.NewInstaller(c.KubeConfig, metav1.NamespaceDefault, 0) if err != nil { @@ -1562,7 +1537,6 @@ func (c *Controller) obliviateCRDs(tridentCR netappv1.TridentOrchestrator) error // createTridentOrchestratorCR creates a new TridentOrchestrator CR func (c *Controller) createTridentOrchestratorCR(tridentCR *netappv1.TridentOrchestrator) error { -func (c *Controller) ensureTridentOrchestratorCRDExist() error { _, err := c.CRDClient.TridentV1().TridentOrchestrators().Create(ctx(), tridentCR, createOpts) if err != nil { return err @@ -1572,7 +1546,6 @@ func (c *Controller) ensureTridentOrchestratorCRDExist() error { // getTridentOrchestratorCRsAll gets all the TridentOrchestrator CRs across all namespaces func (c *Controller) getTridentOrchestratorCRsAll() ([]netappv1.TridentOrchestrator, error) { -func (c *Controller) createTridentOrchestratorCR(tridentCR *netappv1.TridentOrchestrator) error { list, err := c.CRDClient.TridentV1().TridentOrchestrators().List(ctx(), listOpts) if err != nil { return nil, err @@ -1583,7 +1556,6 @@ func (c *Controller) createTridentOrchestratorCR(tridentCR *netappv1.TridentOrch // identifyControllingCRBasedOnStatus identified the controllingCR purely on status and independent of any deployment // logic involved func (c *Controller) identifyControllingCRBasedOnStatus() (bool, *netappv1.TridentOrchestrator, error) { -func (c *Controller) getTridentOrchestratorCRsAll() ([]netappv1.TridentOrchestrator, error) { // Get all TridentOrchestrator CRs tridentCRs, err := c.getTridentOrchestratorCRsAll() @@ -1609,7 +1581,6 @@ func (c *Controller) getTridentOrchestratorCRsAll() ([]netappv1.TridentOrchestra // identifyControllingCRForTridentDeployments identifies controllingCR for deployment and reports nil if length of the // operatorCSIDeployments is more than 1 func (c *Controller) identifyControllingCRForTridentDeployments(operatorCSIDeployments []appsv1.Deployment) (*netappv1. -func (c *Controller) identifyControllingCRBasedOnStatus() (bool, *netappv1.TridentOrchestrator, error) { TridentOrchestrator, error) { @@ -1654,7 +1625,6 @@ func (c *Controller) identifyControllingCRBasedOnStatus() (bool, *netappv1.Tride // updateAllCRs get called only when no ControllingCR exist to report a configuration error func (c *Controller) updateAllCRs(message string) error { -func (c *Controller) identifyControllingCRForTridentDeployments(operatorCSIDeployments []appsv1.Deployment) (*netappv1. allCRs, err := c.getTridentOrchestratorCRsAll() if err != nil { @@ -1675,7 +1645,6 @@ func (c *Controller) identifyControllingCRForTridentDeployments(operatorCSIDeplo // updateOtherCRs get called only when a ControllingCR exist to set error state on the non-ControllingCRs func (c *Controller) updateOtherCRs(controllingCRName string) error { -func (c *Controller) updateAllCRs(message string) error { allCRs, err := c.getTridentOrchestratorCRsAll() if err != nil { @@ -1700,23 +1669,23 @@ func (c *Controller) updateAllCRs(message string) error { } // updateLogAndStatus updates the event logs and status of a TridentOrchestrator CR (if required) -func (c *Controller) updateTorcEventAndStatus( // updateTorcEventAndStatus updates the status of the TridentOrchestrator CR and logs an event // Parameters: // tridentCR - the TridentOrchestrator CR -// debugMessage - the message to be logged as debug -// message - the message to be logged as info -// status - the status to be updated in the CR -// version - the version of the CR -// namespace - the namespace of the CR +// debugMessage - the debug message to be logged +// message - the message to be logged +// status - the status to be updated +// version - the version to be updated +// namespace - the namespace to be updated // eventType - the // Returns: // torcCR - the updated TridentOrchestrator CR // err - error if any // Example: -// torcCR, err := c.updateTorcEventAndStatus(tridentCR, "", "", "", "", "", corev1.EventTypeNormal) +// torcCR, err := updateTorcEventAndStatus(tridentCR, "debug message", "message", "status", "version", "namespace", +// corev1.EventTypeNormal) // -// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- +// -- Doc autogenerated on 2022-05-12 20:48:56.267584 -- func (c *Controller) updateTorcEventAndStatus( tridentCR *netappv1.TridentOrchestrator, debugMessage, message, status, version, namespace, eventType string, specValues *netappv1.TridentOrchestratorSpecValues) (torcCR *netappv1.TridentOrchestrator, err error) { @@ -1786,7 +1755,6 @@ func (c *Controller) updateTridentOrchestratorCRStatus( ***********************************************/ // getTridentTprovCRsAll gets all the TridentProvisioner CRs across all namespaces func (c *Controller) getTridentTprovCRsAll() ([]tprovv1.TridentProvisioner, error) { -func (c *Controller) updateTridentOrchestratorCRStatus( list, err := c.CRDTprovClient.TridentV1().TridentProvisioners(corev1.NamespaceAll).List(ctx(), listOpts) if err != nil { return nil, err @@ -1796,7 +1764,6 @@ func (c *Controller) updateTridentOrchestratorCRStatus( // identifyTprovCRWithInstalledStatus identified the controllingCR with installed status func (c *Controller) identifyTprovCRWithInstalledStatus() (*tprovv1.TridentProvisioner, error) { -func (c *Controller) getTridentTprovCRsAll() ([]tprovv1.TridentProvisioner, error) { // Get all TridentOrchestrator CRs tridentTprovCRs, err := c.getTridentTprovCRsAll() @@ -1818,7 +1785,6 @@ func (c *Controller) getTridentTprovCRsAll() ([]tprovv1.TridentProvisioner, erro // deleteTridentTprovCRD deletes TridentProvisioner CRD func (c *Controller) deleteTridentTprovCRD() error { -func (c *Controller) identifyTprovCRWithInstalledStatus() (*tprovv1.TridentProvisioner, error) { log.Debug("Starting TridentProvisioner CRD cleanup.") logFields := log.Fields{"CRD": TridentProvisionersCRDName} @@ -1867,13 +1833,11 @@ func (c *Controller) identifyTprovCRWithInstalledStatus() (*tprovv1.TridentProvi // deleteTridentTprovCR deletes TridentProvisioner CR func (c *Controller) deleteTridentTprovCR(name, namespace string) error { -func (c *Controller) deleteTridentTprovCRD() error { return c.CRDTprovClient.TridentV1().TridentProvisioners(namespace).Delete(ctx(), name, deleteOpts) } // deleteTridentTprovCRAll deletes all the TridentProvisioner CRs func (c *Controller) deleteTridentTprovCRAll() error { -func (c *Controller) deleteTridentTprovCR(name, namespace string) error { log.Debug("Starting TridentProvisioner CR cleanup.") // See if CRD exists @@ -1904,18 +1868,17 @@ func (c *Controller) deleteTridentTprovCR(name, namespace string) error { return nil } -func (c *Controller) cleanupTridentProvisioner() error { -// cleanupTridentProvisioner deletes the Trident provisioner CRD and all CRs. +// cleanupTridentProvisioner cleans up the Trident provisioner // It returns an error if any of the operations fail. // Returns: -// - error: nil if all operations succeed, otherwise an error +// - error: if any of the operations fail // Example: -// - err := c.cleanupTridentProvisioner() -// - if err != nil { -// - log.Errorf("Failed to clean up Trident provisioner: %v", err) -// - } +// err := c.cleanupTridentProvisioner() +// if err != nil { +// return err +// } // -// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- +// -- Doc autogenerated on 2022-05-12 20:48:56.267584 -- func (c *Controller) cleanupTridentProvisioner() error { if err := c.deleteTridentTprovCRAll(); err != nil { return err @@ -1938,7 +1901,6 @@ func (c *Controller) getTridentOrchestratorCSIDeployments() ([]appsv1.Deployment // getCRDBasedCSIDeployments returns CSI Trident deployments (if any) created by CR based of crdName func (c *Controller) getCRDBasedCSIDeployments(crdName string) ([]appsv1.Deployment, string, error) { -func (c *Controller) getTridentOrchestratorCSIDeployments() ([]appsv1.Deployment, string, error) { var tridentCSIDeployments []appsv1.Deployment var tridentCSIExist bool var tridentCSINamespace string @@ -1980,7 +1942,6 @@ func (c *Controller) getTridentOrchestratorCSIDeployments() ([]appsv1.Deployment // matchDeploymentControllingCR identified the controllingCR for an operator based deployment from the list of CRs func (c *Controller) matchDeploymentControllingCR(tridentCRs []netappv1.TridentOrchestrator, -func (c *Controller) getCRDBasedCSIDeployments(crdName string) ([]appsv1.Deployment, string, error) { operatorCSIDeployment appsv1.Deployment) (*netappv1.TridentOrchestrator, error) { // Identify Trident CR that controls the deployment @@ -2004,25 +1965,21 @@ func (c *Controller) getCRDBasedCSIDeployments(crdName string) ([]appsv1.Deploym **************************/ // isLegacyTridentInstalled identifies if legacy Trident is installed func (c *Controller) isLegacyTridentInstalled() (installed bool, namespace string, err error) { -func (c *Controller) matchDeploymentControllingCR(tridentCRs []netappv1.TridentOrchestrator, return c.K8SClient.CheckDeploymentExistsByLabel(installer.TridentLegacyLabel, true) } // isPreviewCSITridentInstalled identifies if CSI Preview Trident is installed func (c *Controller) isPreviewCSITridentInstalled() (installed bool, namespace string, err error) { -func (c *Controller) isLegacyTridentInstalled() (installed bool, namespace string, err error) { return c.K8SClient.CheckStatefulSetExistsByLabel(installer.TridentCSILabel, true) } // isCSITridentInstalled identifies if CSI Trident is installed func (c *Controller) isCSITridentInstalled() (installed bool, namespace string, err error) { -func (c *Controller) isPreviewCSITridentInstalled() (installed bool, namespace string, err error) { return c.K8SClient.CheckDeploymentExistsByLabel(installer.TridentCSILabel, true) } // uninstallCSIPreviewTrident uninstalls Trident CSI Preview func (c *Controller) uninstallCSIPreviewTrident(namespace string) error { -func (c *Controller) isCSITridentInstalled() (installed bool, namespace string, err error) { i, err := installer.NewInstaller(c.KubeConfig, namespace, 0) if err != nil { return err @@ -2040,7 +1997,6 @@ func (c *Controller) isCSITridentInstalled() (installed bool, namespace string, // uninstallLegacyTrident uninstalls Trident CSI Legacy func (c *Controller) uninstallLegacyTrident(namespace string) error { -func (c *Controller) uninstallCSIPreviewTrident(namespace string) error { i, err := installer.NewInstaller(c.KubeConfig, namespace, 0) if err != nil { return err @@ -2058,7 +2014,6 @@ func (c *Controller) uninstallCSIPreviewTrident(namespace string) error { // removeNonTorcBasedCSIInstallation identifies if the Tprov-based or tridentctl-based CSI Trident is installed, // if it is installed it will be uninstalled. func (c *Controller) removeNonTorcBasedCSIInstallation(tridentCR *netappv1.TridentOrchestrator) error { -func (c *Controller) uninstallLegacyTrident(namespace string) error { var uninstallRequired bool // Check for the CSI based Trident installation @@ -2109,7 +2064,6 @@ func (c *Controller) uninstallLegacyTrident(namespace string) error { // getCurrentTridentAndK8sVersion reports current Trident version installed and K8s version according // to which Trident was installed func (c *Controller) getCurrentTridentAndK8sVersion(tridentCR *netappv1.TridentOrchestrator) (string, string, error) { -func (c *Controller) removeNonTorcBasedCSIInstallation(tridentCR *netappv1.TridentOrchestrator) error { var currentTridentVersionString string var currentK8sVersionString string @@ -2145,7 +2099,6 @@ func (c *Controller) removeNonTorcBasedCSIInstallation(tridentCR *netappv1.Tride // validateCurrentK8sVersion identifies any changes in the K8s version, if it is valid, and if not valid should // user be warned about it func (c *Controller) validateCurrentK8sVersion() (bool, string) { -func (c *Controller) getCurrentTridentAndK8sVersion(tridentCR *netappv1.TridentOrchestrator) (string, string, error) { var isValid bool var warning string @@ -2179,7 +2132,6 @@ func (c *Controller) getCurrentTridentAndK8sVersion(tridentCR *netappv1.TridentO // tridentUpgradeNeeded compares the K8's version as per which Trident is installed with the current K8s version, // if it has changed we need to update Trident as well func (c *Controller) tridentUpgradeNeeded(tridentK8sConfigVersion string) bool { -func (c *Controller) validateCurrentK8sVersion() (bool, string) { var shouldUpdate bool @@ -2208,7 +2160,6 @@ func (c *Controller) validateCurrentK8sVersion() (bool, string) { ************************/ // doesCRDExist checks if the given CRD exist func (c *Controller) doesCRDExist(crdName string) (bool, error) { -func (c *Controller) tridentUpgradeNeeded(tridentK8sConfigVersion string) bool { // Discover CRD data crdExist, returnError := c.K8SClient.CheckCRDExists(crdName) @@ -2219,19 +2170,17 @@ func (c *Controller) tridentUpgradeNeeded(tridentK8sConfigVersion string) bool { return crdExist, returnError } -func isNotFoundError(err error) bool { -// isNotFoundError returns true if the error is an API not found error +// isNotFoundError returns true if the error is an API not found error. // Parameters: -// err: the error to check +// err: the error to check // Returns: -// true if the error is an API not found error +// true if the error is an API not found error // Example: -// err := ... -// if isNotFoundError(err) { -// // do something -// } +// if isNotFoundError(err) { +// ... +// } // -// -- Doc autogenerated on 2022-05-12 18:38:47.645975 -- +// -- Doc autogenerated on 2022-05-12 20:48:56.267584 -- func isNotFoundError(err error) bool { if statusErr, ok := err.(*apierrors.StatusError); ok && statusErr.Status().Reason == metav1.StatusReasonNotFound { return true diff --git a/operator/controllers/orchestrator/installer/installer.go b/operator/controllers/orchestrator/installer/installer.go index 327acf7d6..95e7bb839 100644 --- a/operator/controllers/orchestrator/installer/installer.go +++ b/operator/controllers/orchestrator/installer/installer.go @@ -109,23 +109,22 @@ type Installer struct { namespace string } -// NewInstaller creates a new installer -// It returns a TridentInstaller interface +// NewInstaller creates a new Trident installer // It returns an error if the installer cannot be created // Parameters: -// kubeConfig - Kubernetes config -// namespace - Kubernetes namespace -// timeout - timeout for Kubernetes operations +// kubeConfig: the Kubernetes client configuration +// namespace: the Kubernetes namespace where Trident will be installed +// timeout: the timeout for Kubernetes operations // Returns: -// TridentInstaller - Trident installer -// error - error if the installer cannot be created +// TridentInstaller: the Trident installer +// error: an error if the installer cannot be created // Example: -// installer, err := installer.NewInstaller(kubeConfig, namespace, timeout) -// if err != nil { -// return err -// } +// installer, err := installer.NewInstaller(kubeConfig, namespace, timeout) +// if err != nil { +// // Handle error +// } // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func NewInstaller(kubeConfig *rest.Config, namespace string, timeout int) (TridentInstaller, error) { if timeout <= 0 { @@ -155,18 +154,17 @@ func NewInstaller(kubeConfig *rest.Config, namespace string, timeout int) (Tride }, nil } -// logFormatPrechecks checks that the log format is valid +// logFormatPrechecks checks the log format // It returns an error if the log format is not valid // Returns: -// error: if the log format is not valid +// returnError: error if the log format is not valid // Example: -// returnError := i.logFormatPrechecks() +// returnError := logFormatPrechecks() // if returnError != nil { -// log.Error(returnError) -// return returnError +// return returnError // } // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func (i *Installer) logFormatPrechecks() (returnError error) { switch logFormat { case "text", "json": @@ -285,7 +283,6 @@ func (i *Installer) imagePrechecks(labels, controllingCRDetails map[string]strin // setInstallationParams identifies the correct parameters for the Trident installation func (i *Installer) setInstallationParams( -func (i *Installer) imagePrechecks(labels, controllingCRDetails map[string]string) (string, error) { cr netappv1.TridentOrchestrator, currentInstallationVersion string, ) (map[string]string, map[string]string, bool, error) { @@ -443,16 +440,15 @@ func (i *Installer) imagePrechecks(labels, controllingCRDetails map[string]strin return controllingCRDetails, labels, tridentUpdateNeeded, nil } -func (i *Installer) InstallOrPatchTrident( // InstallOrPatchTrident installs or patches Trident -// It returns the TridentOrchestratorSpecValues, the version of Trident installed, and an error +// It returns the TridentOrchestratorSpecValues, the Trident version, and any error encountered // Parameters: // cr - the TridentOrchestrator CR -// currentInstallationVersion - the version of Trident currently installed -// k8sUpdateNeeded - true if the K8s version has changed since the last installation +// currentInstallationVersion - the current Trident version +// k8sUpdateNeeded - true if the K8s version has changed // Returns: -// TridentOrchestratorSpecValues - the values from the CR that were used to install Trident -// string - the version of Trident installed +// TridentOrchestratorSpecValues - the TridentOrchestratorSpecValues +// string - the Trident version // error - any error encountered // Example: // specValues, version, err := i.InstallOrPatchTrident(cr, currentInstallationVersion, k8sUpdateNeeded) @@ -460,7 +456,7 @@ func (i *Installer) InstallOrPatchTrident( // // Handle error // } // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func (i *Installer) InstallOrPatchTrident( cr netappv1.TridentOrchestrator, currentInstallationVersion string, k8sUpdateNeeded bool, ) (*netappv1.TridentOrchestratorSpecValues, string, error) { @@ -651,7 +647,6 @@ func (i *Installer) createCRDs() error { // CreateCRD creates and establishes the CRD func (i *Installer) CreateCRD(crdName, crdYAML string) error { -func (i *Installer) createCRDs() error { // Discover CRD data crdExist, returnError := i.client.CheckCRDExists(crdName) @@ -692,7 +687,6 @@ func (i *Installer) createCRDs() error { // ensureCRDEstablished waits until a CRD is Established. func (i *Installer) ensureCRDEstablished(crdName string) error { -func (i *Installer) CreateCRD(crdName, crdYAML string) error { checkCRDEstablished := func() error { crd, err := i.client.GetCRD(crdName) @@ -733,20 +727,19 @@ func (i *Installer) CreateCRD(crdName, crdYAML string) error { return nil } -func (i *Installer) createOrPatchK8sBetaCSIDriver( // createOrPatchK8sBetaCSIDriver creates or patches the K8s (beta) CSI driver -// TODO (cknight): remove when 1.18 is our minimum version -// It returns an error if the operation fails. +// for the specified version of K8s. +// It returns an error if it fails to create or patch the K8s (beta) CSI driver. // Parameters: -// controllingCRDetails - map of the controlling CR's details -// labels - map of labels to apply to the K8s (beta) CSI driver -// shouldUpdate - whether or not to update the K8s (beta) CSI driver +// controllingCRDetails - the details of the controlling CR +// labels - the labels to apply to the K8s (beta) CSI driver +// shouldUpdate - whether to update the K8s (beta) CSI driver // Returns: -// error - if the operation fails +// error - an error if it fails to create or patch the K8s (beta) CSI driver // Example: -// err := installer.createOrPatchK8sBetaCSIDriver(controllingCRDetails, labels, shouldUpdate) +// err := i.createOrPatchK8sBetaCSIDriver(controllingCRDetails, labels, shouldUpdate) // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func (i *Installer) createOrPatchK8sBetaCSIDriver( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -776,17 +769,20 @@ func (i *Installer) createOrPatchK8sBetaCSIDriver( } // createOrPatchK8sCSIDriver creates or patches the K8s CSI driver -// It returns an error if the operation fails +// It returns error if the operation fails // Parameters: -// controllingCRDetails: map of the controlling CR details -// labels: map of labels to be applied to the CSI driver -// shouldUpdate: true if the CSI driver should be updated, false otherwise +// controllingCRDetails - map of the controlling CR details +// labels - map of labels +// shouldUpdate - boolean to indicate if the CSI driver should be updated // Returns: -// error: nil if successful, error object otherwise +// error - error if the operation fails // Example: -// err := i.createOrPatchK8sCSIDriver(controllingCRDetails, labels, shouldUpdate) +// err := createOrPatchK8sCSIDriver(controllingCRDetails, labels, shouldUpdate) +// if err != nil { +// fmt.Println(err) +// } // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func (i *Installer) createOrPatchK8sCSIDriver(controllingCRDetails, labels map[string]string, shouldUpdate bool) error { CSIDriverName := getCSIDriverName() @@ -814,16 +810,19 @@ func (i *Installer) createOrPatchK8sCSIDriver(controllingCRDetails, labels map[s // createRBACObjects creates the RBAC objects for Trident // Parameters: -// controllingCRDetails - the details of the controlling CR -// labels - the labels to apply to the RBAC objects -// shouldUpdate - whether to update existing objects +// controllingCRDetails - a map of details about the controlling CR +// labels - a map of labels to apply to the RBAC objects +// shouldUpdate - whether or not to update the RBAC objects if they already exist +// Return values: +// newServiceAccount - whether or not a new service account was created +// returnError - any error encountered // Returns: -// newServiceAccount - whether a new service account was created +// newServiceAccount - whether or not a new service account was created // returnError - any error encountered // Example: -// newServiceAccount, returnError := i.createRBACObjects(controllingCRDetails, labels, true) +// newServiceAccount, returnError := createRBACObjects(controllingCRDetails, labels, shouldUpdate) // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func (i *Installer) createRBACObjects( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) (newServiceAccount bool, returnError error) { @@ -862,17 +861,17 @@ func (i *Installer) createRBACObjects( return } -// createTridentInstallationNamespace creates the namespace for Trident's installation -// It returns an error if the namespace already exists and is not empty +// createTridentInstallationNamespace creates the namespace in which Trident will be installed. +// It returns an error if the namespace already exists and is not empty. // Returns: -// error: if the namespace could not be created +// error - if the namespace could not be created // Example: // err := i.createTridentInstallationNamespace() // if err != nil { -// // handle error +// return err // } // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func (i *Installer) createTridentInstallationNamespace() error { createNamespace := true @@ -903,24 +902,21 @@ func (i *Installer) createTridentInstallationNamespace() error { } // createOrPatchTridentServiceAccount creates or patches the Trident service account -// It returns a boolean indicating whether the service account was created, and an error +// It returns a boolean indicating if the service account was created or patched and an error // Parameters: -// controllingCRDetails - a map containing the controlling CR's name and namespace +// controllingCRDetails - a map containing the controlling CR's details // labels - a map containing the labels to be applied to the service account -// shouldUpdate - a boolean indicating whether the service account should be updated -// Return values: -// bool - a boolean indicating whether the service account was created -// error - an error indicating whether the function succeeded or failed +// shouldUpdate - a boolean indicating if the service account should be updated // Returns: -// bool - a boolean indicating whether the service account was created -// error - an error indicating whether the function succeeded or failed +// bool - true if the service account was created or patched, false otherwise +// error - an error if one occurred // Example: // newServiceAccount, err := createOrPatchTridentServiceAccount(controllingCRDetails, labels, shouldUpdate) // if err != nil { -// return err +// return err // } // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func (i *Installer) createOrPatchTridentServiceAccount( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) (bool, error) { @@ -949,19 +945,17 @@ func (i *Installer) createOrPatchTridentServiceAccount( } // createOrPatchTridentClusterRole creates or patches the Trident cluster role. -// It returns an error if the operation fails. +// It returns an error if it encounters one. // Parameters: -// controllingCRDetails - details about the controlling CR -// labels - labels to apply to the cluster role -// shouldUpdate - whether the cluster role should be updated +// controllingCRDetails - the details of the controlling CR +// labels - the labels to apply to the CR +// shouldUpdate - whether the CR should be updated if it already exists // Returns: -// error - error if the operation fails +// error - an error if one occurred // Example: -// controllingCRDetails := map[string]string{"app": "trident"} -// labels := map[string]string{"app": "trident"} -// err := createOrPatchTridentClusterRole(controllingCRDetails, labels, true) +// err := i.createOrPatchTridentClusterRole(controllingCRDetails, labels, shouldUpdate) // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func (i *Installer) createOrPatchTridentClusterRole( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -990,19 +984,18 @@ func (i *Installer) createOrPatchTridentClusterRole( return nil } -// createOrPatchTridentClusterRoleBinding creates or patches the Trident cluster role binding -// with the specified labels. +// createOrPatchTridentClusterRoleBinding creates or patches the Trident cluster role binding. // It returns an error if the operation fails. // Parameters: -// controllingCRDetails - the details of the controlling CR -// labels - the labels to apply to the Trident cluster role binding -// shouldUpdate - true if the Trident cluster role binding should be updated, false otherwise +// controllingCRDetails - a map of labels and annotations to be applied to the cluster role binding +// labels - a map of labels to be applied to the cluster role binding +// shouldUpdate - true if the cluster role binding should be updated if it already exists // Returns: // error - error if the operation fails // Example: -// err := installer.createOrPatchTridentClusterRoleBinding(controllingCRDetails, labels, true) +// err := createOrPatchTridentClusterRoleBinding(controllingCRDetails, labels, true) // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func (i *Installer) createOrPatchTridentClusterRoleBinding( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -1032,25 +1025,21 @@ func (i *Installer) createOrPatchTridentClusterRoleBinding( return nil } -// createOrPatchTridentOpenShiftSCC creates or patches the Trident OpenShift SCC. -// It returns an error if the SCC could not be created or patched. +// createOrPatchTridentOpenShiftSCC creates or patches the Trident OpenShift SCC +// It returns an error if the SCC cannot be created or patched // Parameters: -// controllingCRDetails: a map of the controlling CR's name and namespace -// labels: a map of labels to apply to the SCC -// shouldUpdate: whether or not the SCC should be updated +// controllingCRDetails - a map of the controlling CR's details +// labels - a map of labels to apply to the SCC +// shouldUpdate - true if the SCC should be updated, false otherwise // Returns: -// error: nil if the SCC was created or patched successfully, or an error if the SCC could not be created or patched +// error - an error if the SCC cannot be created or patched // Example: -// labels := map[string]string{ -// "app": "trident", -// } -// err := createOrPatchTridentOpenShiftSCC(map[string]string{}, labels, false) +// err := installer.createOrPatchTridentOpenShiftSCC(controllingCRDetails, labels, shouldUpdate) // if err != nil { -// log.Errorf("Unable to create Trident OpenShift SCC, err: %v", err) -// return err +// log.Errorf("Unable to create or patch Trident OpenShift SCC; %v", err) // } // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func (i *Installer) createOrPatchTridentOpenShiftSCC( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -1092,16 +1081,16 @@ func (i *Installer) createOrPatchTridentOpenShiftSCC( return nil } -// createAndEnsureCRDs creates the Trident CRDs and ensures they are ready. +// createAndEnsureCRDs creates the Trident CRDs, and ensures that they are installed. // Returns: -// error: nil if successful, else a descriptive error +// error: nil if the CRDs are created and installed, or an error if not. // Example: -// err := i.createAndEnsureCRDs() -// if err != nil { -// // handle error +// returnError := i.createAndEnsureCRDs() +// if returnError != nil { +// return returnError // } // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func (i *Installer) createAndEnsureCRDs() (returnError error) { returnError = i.createCRDs() @@ -1114,15 +1103,18 @@ func (i *Installer) createAndEnsureCRDs() (returnError error) { // createOrPatchTridentPodSecurityPolicy creates or patches the Trident pod security policy // It returns an error if the operation fails. // Parameters: -// controllingCRDetails - a map of the controlling CR's details -// labels - a map of labels to apply to the Trident pod security policy -// shouldUpdate - true if the Trident pod security policy should be updated +// controllingCRDetails - a map of labels and values that will be applied to the Trident pod security policy +// labels - a map of labels and values that will be applied to the Trident pod security policy +// shouldUpdate - true if the Trident pod security policy should be updated if it already exists // Returns: -// error - an error if the operation fails +// error - nil if the operation succeeds, otherwise an error object is returned // Example: -// err := createOrPatchTridentPodSecurityPolicy(controllingCRDetails, labels, shouldUpdate) +// err := createOrPatchTridentPodSecurityPolicy(controllingCRDetails, labels, false) +// if err != nil { +// log.Errorf("createOrPatchTridentPodSecurityPolicy() failed: %v", err) +// } // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func (i *Installer) createOrPatchTridentPodSecurityPolicy( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -1151,18 +1143,18 @@ func (i *Installer) createOrPatchTridentPodSecurityPolicy( // createOrPatchTridentService creates or patches the Trident service // It returns an error if the service could not be created or patched // Parameters: -// controllingCRDetails - map of controlling CR details -// labels - map of labels to apply to the Trident service -// shouldUpdate - whether or not the Trident service should be updated +// controllingCRDetails - a map of the controlling CR's details +// labels - a map of labels to apply to the Trident service +// shouldUpdate - true if the Trident service should be updated // Returns: -// error - error if the Trident service could not be created or patched +// error - nil if successful, otherwise an error object // Example: // err := i.createOrPatchTridentService(controllingCRDetails, labels, shouldUpdate) // if err != nil { -// return err +// log.Error("Could not create or patch Trident service: %v", err) // } // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func (i *Installer) createOrPatchTridentService( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -1188,24 +1180,21 @@ func (i *Installer) createOrPatchTridentService( return nil } -// createOrPatchTridentProtocolSecret creates or patches the Trident protocol secret. -// It returns an error if the secret could not be created or patched. +// createOrPatchTridentProtocolSecret creates or patches the Trident protocol secret +// It returns an error if the operation fails. // Parameters: -// controllingCRDetails - a map of labels and annotations to add to the secret -// labels - a map of labels to add to the secret -// shouldUpdate - true if the secret should be updated if it already exists +// controllingCRDetails - the controlling CR's details +// labels - the labels to apply to the secret +// shouldUpdate - whether the secret should be updated if it already exists // Returns: -// error - nil if the secret was created or patched successfully +// error - error if the operation fails // Example: -// controllingCRDetails := map[string]string{ -// "netapp.io/trident-version": "v1.0", -// } -// labels := map[string]string{ -// "netapp.io/trident-version": "v1.0", +// secret, err := i.createOrPatchTridentProtocolSecret(controllingCRDetails, labels, shouldUpdate) +// if err != nil { +// return fmt.Errorf("failed to create or patch Trident protocol secret; %v", err) // } -// err := i.createOrPatchTridentProtocolSecret(controllingCRDetails, labels, true) // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func (i *Installer) createOrPatchTridentProtocolSecret( controllingCRDetails, labels map[string]string, shouldUpdate bool, ) error { @@ -1300,20 +1289,23 @@ func (i *Installer) createOrConsumeTridentEncryptionSecret( return nil } -func (i *Installer) createOrPatchTridentDeployment( // createOrPatchTridentDeployment creates or patches the Trident deployment. // It returns an error if the deployment could not be created or patched. // Parameters: -// controllingCRDetails: a map of the controlling CR's name and namespace -// labels: a map of labels to apply to the deployment -// shouldUpdate: true if the deployment should be updated -// newServiceAccount: true if a new service account should be created +// controllingCRDetails - a map of the controlling CR's name and namespace +// labels - a map of labels to apply to the deployment +// shouldUpdate - true if the deployment should be updated +// newServiceAccount - true if a new service account should be created // Returns: -// error: nil if the deployment was created or patched successfully +// error - nil if the deployment was created or patched successfully // Example: -// err := i.createOrPatchTridentDeployment(controllingCRDetails, labels, true, true) +// err := i.createOrPatchTridentDeployment(controllingCRDetails, labels, +// shouldUpdate, newServiceAccount) +// if err != nil { +// return fmt.Errorf("failed to create or patch Trident deployment; %v", err) +// } // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func (i *Installer) createOrPatchTridentDeployment( controllingCRDetails, labels map[string]string, shouldUpdate, newServiceAccount bool, ) error { @@ -1396,21 +1388,22 @@ func (i *Installer) TridentDeploymentInformation( return i.client.GetDeploymentInformation(getDeploymentName(true), deploymentLabel, i.namespace) } -func (i *Installer) createOrPatchTridentDaemonSet( // createOrPatchTridentDaemonSet creates or patches the Trident daemonset // It returns an error if the daemonset cannot be created or patched // Parameters: -// controllingCRDetails - a map containing the name and namespace of the controlling CR -// labels - a map containing the labels to be applied to the daemonset +// controllingCRDetails - a map of the controlling CR's details +// labels - a map of labels to be applied to the daemonset // shouldUpdate - true if the daemonset should be updated // newServiceAccount - true if a new service account should be created // Returns: // error - an error if the daemonset cannot be created or patched // Example: -// error := i.createOrPatchTridentDaemonSet(controllingCRDetails, labels, shouldUpdate, newServiceAccount) -// +// err := i.createOrPatchTridentDaemonSet(controllingCRDetails, labels, true, true) +// if err != nil { +// log.Errorf("Failed to create or patch Trident daemonset; %v", err) +// } // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func (i *Installer) createOrPatchTridentDaemonSet( controllingCRDetails, labels map[string]string, shouldUpdate, newServiceAccount bool, ) error { @@ -1483,20 +1476,15 @@ func (i *Installer) TridentDaemonSetInformation() (*appsv1.DaemonSet, return i.client.GetDaemonSetInformation(daemonSetName, nodeLabel, i.namespace) } -func (i *Installer) waitForTridentPod() (*v1.Pod, error) { -// waitForTridentPod waits for the Trident pod to be running. -// It returns the pod if it is running, or an error if it is not. +// waitForTridentPod waits for the Trident pod to be created and running. +// It returns the pod object if successful. // Returns: -// * Pod if running -// * Error if not running +// * pod object if successful +// * error if unsuccessful // Example: -// pod, err := i.waitForTridentPod() -// if err != nil { -// fmt.Printf("error: %v", err) -// } -// fmt.Printf("pod: %v", pod) +// pod, err := waitForTridentPod() // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func (i *Installer) waitForTridentPod() (*v1.Pod, error) { var pod *v1.Pod @@ -1608,19 +1596,16 @@ func (i *Installer) waitForTridentPod() (*v1.Pod, error) { return pod, nil } -// waitForRESTInterface waits for the Trident REST interface to become available. -// It returns an error if the REST interface is not available within the timeout. +// waitForRESTInterface waits for the Trident REST interface to be available. +// It returns an error if the REST interface is not available after the timeout. // Parameters: // tridentPodName - the name of the Trident pod // Returns: -// error - an error if the REST interface is not available within the timeout +// error - any error encountered // Example: -// err := i.waitForRESTInterface("trident-backend-pod-name") -// if err != nil { -// return err -// } +// err := i.waitForRESTInterface("trident-installer-12345678-abcd") // -// -- Doc autogenerated on 2022-05-12 18:45:31.327808 -- +// -- Doc autogenerated on 2022-05-12 20:55:50.637319 -- func (i *Installer) waitForRESTInterface(tridentPodName string) error { var version, versionWithMetadata string @@ -1719,7 +1704,6 @@ func (i *Installer) getTridentClientVersionInfo(imageName string, controllingCRD // resembles the `kubectl run --rm -it --restart=Never transient-trident-version-pod --image= -- // /bin/tridentctl version --client -o yaml` command func (i *Installer) getTridentVersionYAML(imageName string, controllingCRDetails map[string]string) ([]byte, error) { -func (i *Installer) getTridentClientVersionInfo(imageName string, controllingCRDetails map[string]string) (*api. podName := "transient-trident-version-pod" podLabels := make(map[string]string) @@ -1776,7 +1760,6 @@ func (i *Installer) getTridentClientVersionInfo(imageName string, controllingCRD // createTridentVersionPod takes the pod name and trident image name to create a pod func (i *Installer) createTridentVersionPod( -func (i *Installer) getTridentVersionYAML(imageName string, controllingCRDetails map[string]string) ([]byte, error) { podName, imageName string, controllingCRDetails, podLabels map[string]string, ) error { versionPodLabel := TridentVersionPodLabel diff --git a/operator/controllers/orchestrator/installer/installer_test.go b/operator/controllers/orchestrator/installer/installer_test.go index 8bf97a91c..21a3bb3a0 100644 --- a/operator/controllers/orchestrator/installer/installer_test.go +++ b/operator/controllers/orchestrator/installer/installer_test.go @@ -21,29 +21,30 @@ var ( // newMockKubeClient returns a mock k8s client // Parameters: -// t *testing.T - test object +// t *testing.T - test object // Returns: -// *mockExtendedK8sClient.MockExtendedK8sClient - mock k8s client +// *mockExtendedK8sClient.MockExtendedK8sClient - mock k8s client // Example: -// mockK8sClient := newMockKubeClient(t) +// mockK8sClient := newMockKubeClient(t) // -// -- Doc autogenerated on 2022-05-12 18:52:24.083540 -- +// -- Doc autogenerated on 2022-05-12 21:02:44.073079 -- func newMockKubeClient(t *testing.T) *mockExtendedK8sClient.MockExtendedK8sClient { mockCtrl := gomock.NewController(t) mockK8sClient := mockExtendedK8sClient.NewMockExtendedK8sClient(mockCtrl) return mockK8sClient } -// newTestInstaller creates a new Installer for testing -// It returns a pointer to the Installer and a pointer to the mock client +// newTestInstaller creates a new Installer for testing purposes +// It returns a pointer to the Installer and a pointer to the mock Trident client // Parameters: -// client - a pointer to a mock client +// client - a pointer to the mock Trident client // Returns: -// a pointer to the Installer +// *Installer - a pointer to the Installer +// *mockExtendedK8sClient.MockExtendedK8sClient - a pointer to the mock Trident client // Example: -// installer, client := newTestInstaller(client) +// installer, client := newTestInstaller() // -// -- Doc autogenerated on 2022-05-12 18:52:24.083540 -- +// -- Doc autogenerated on 2022-05-12 21:02:44.073079 -- func newTestInstaller(client *mockExtendedK8sClient.MockExtendedK8sClient) *Installer { return &Installer{ @@ -58,9 +59,9 @@ func newTestInstaller(client *mockExtendedK8sClient.MockExtendedK8sClient) *Inst // Returns: // map[string]string: map of the controlling CR details // Example: -// crDetails := createTestControllingCRDetails() +// controllingCRDetails := createTestControllingCRDetails() // -// -- Doc autogenerated on 2022-05-12 18:52:24.083540 -- +// -- Doc autogenerated on 2022-05-12 21:02:44.073079 -- func createTestControllingCRDetails() map[string]string { controllingCRDetails := make(map[string]string) @@ -73,14 +74,14 @@ func createTestControllingCRDetails() map[string]string { return controllingCRDetails } -// createTestLabels creates a map of labels for testing +// createTestLabels creates a set of labels for testing // It returns a map of labels // Returns: -// map[string]string: map of labels +// map[string]string: labels // Example: // labels := createTestLabels() // -// -- Doc autogenerated on 2022-05-12 18:52:24.083540 -- +// -- Doc autogenerated on 2022-05-12 21:02:44.073079 -- func createTestLabels() map[string]string { labels := make(map[string]string) @@ -92,13 +93,13 @@ func createTestLabels() map[string]string { } // TestInstaller_createOrConsumeTridentEncryptionSecret tests the createOrConsumeTridentEncryptionSecret function -// It checks for the following conditions: +// It checks the following cases: // 1. K8s error at CheckSecretExists // 2. Secret already exists and no K8s error // 3. Create secret with no failure at PutSecret // 4. Create secret with a failure at PutSecret // -// -- Doc autogenerated on 2022-05-12 18:52:24.083540 -- +// -- Doc autogenerated on 2022-05-12 21:02:44.073079 -- func TestInstaller_createOrConsumeTridentEncryptionSecret(t *testing.T) { mockK8sClient := newMockKubeClient(t) diff --git a/operator/controllers/orchestrator/installer/k8s_client_test.go b/operator/controllers/orchestrator/installer/k8s_client_test.go index 14cd00e96..b88b32876 100644 --- a/operator/controllers/orchestrator/installer/k8s_client_test.go +++ b/operator/controllers/orchestrator/installer/k8s_client_test.go @@ -29,10 +29,11 @@ import ( "github.com/netapp/trident/utils" ) -// TestMain is the main entry point for tests -// It checks for any standard log output and disables it +// TestMain is the main entry point for the installer tests +// It checks for the presence of the KUBECONFIG environment variable +// and if it is not set, it will skip all tests. // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestMain(m *testing.M) { // Disable any standard log output log.SetOutput(ioutil.Discard) @@ -64,23 +65,22 @@ func (m *JSONMatcher) Matches(x interface{}) bool { return reflect.DeepEqual(actual, expected) } -func (m *JSONMatcher) String() string { -// String returns a string representation of the matcher +// String returns a string representation of the JSONMatcher. // Returns: -// string: a string representation of the matcher +// string: A string representation of the JSONMatcher. // Example: -// matcher := installer.JSONMatcher{} +// matcher := &JSONMatcher{} // fmt.Println(matcher.String()) // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func (m *JSONMatcher) String() string { return "" } // TestCreateCustomResourceDefinition tests the CreateCustomResourceDefinition function -// It checks that the correct error is returned when the k8s client returns an error +// It checks the error returned by the function // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestCreateCustomResourceDefinition(t *testing.T) { crdName := "crd-name" @@ -141,9 +141,9 @@ func TestCreateCustomResourceDefinition(t *testing.T) { } // TestDeleteCustomResourceDefinition tests the DeleteCustomResourceDefinition function -// It checks that the function returns the expected error +// It checks that the function returns the correct error when the k8s client fails to delete the CRD // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestDeleteCustomResourceDefinition(t *testing.T) { crdName := "crd-name" @@ -204,13 +204,36 @@ func TestDeleteCustomResourceDefinition(t *testing.T) { } // TestWaitForCRDEstablished tests the WaitForCRDEstablished function -// It checks for the following conditions: -// - the function returns an error when the k8s client returns an error -// - the function returns an error when the CRD is not in the expected state -// - the function returns nil when the CRD is in the expected state -// It returns an error if the test fails. +// It checks that the function returns nil when the CRD is established +// and returns an error when the CRD is not established +// It returns an error when the CRD is not found +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established +// It returns an error when the CRD is not established // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestWaitForCRDEstablished(t *testing.T) { var validCRD, invalidCRD *v1.CustomResourceDefinition @@ -313,13 +336,13 @@ func TestWaitForCRDEstablished(t *testing.T) { } // TestDeleteTransientVersionPod tests the DeleteTransientVersionPod function -// It checks for the following conditions: -// 1. K8s client errors -// 2. No transient pods found -// 3. Transient pods found but not removed -// 4. Transient pods found and removed +// It checks the following cases: +// 1. k8s client error during GetPodsByLabel +// 2. no k8s client error and no transient pods found +// 3. no k8s client error and transient pods found but not removed +// 4. no k8s client error and transient pods found and removed // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestDeleteTransientVersionPod(t *testing.T) { // declare and initialize variables used throughout the test cases var versionPodLabel, name, invalidName, namespace string @@ -430,12 +453,12 @@ func TestDeleteTransientVersionPod(t *testing.T) { } // TestGetBetaCSIDriverInformation tests the GetBetaCSIDriverInformation function -// It checks the following cases: -// - k8s error -// - no beta CSI driver found and no k8s error -// - valid current beta CSI driver found and no k8s error +// It checks for the following conditions: +// - no beta CSI driver found +// - valid current beta CSI driver found +// - k8s error // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestGetBetaCSIDriverInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -579,7 +602,7 @@ func TestGetBetaCSIDriverInformation(t *testing.T) { // - update a beta CSI Driver and no k8s error occurs // - update a beta CSI Driver and a k8s error occurs // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestPutBetaCSIDriver(t *testing.T) { driverName := getCSIDriverName() @@ -725,11 +748,11 @@ func TestPutBetaCSIDriver(t *testing.T) { } // TestDeleteTridentBetaCSIDriverCR tests the DeleteTridentBetaCSIDriverCR function -// It checks that the function returns the expected error when the k8s client returns an error -// It checks that the function returns nil when the k8s client returns no error -// It returns nil when the k8s client returns no error +// It checks that the function returns the expected error when the k8s client +// returns the expected error. +// It returns nil when the k8s client returns nil. // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestDeleteTridentBetaCSIDriverCR(t *testing.T) { // arrange variables for the tests var emptyBetaCSIDriverList, unwantedBetaCSIDrivers []storagev1beta1.CSIDriver @@ -829,11 +852,12 @@ func TestDeleteTridentBetaCSIDriverCR(t *testing.T) { } // TestRemoveMultipleBetaCSIDriverCRs tests the RemoveMultipleBetaCSIDriverCRs function -// It checks that the function returns the expected error when the k8s client returns an error -// It also checks that the function returns nil when there are no beta csi driver crs to delete -// It also checks that the function returns nil when there are valid beta csi driver crs to delete +// It checks the following cases: +// 1. No beta csi driver crs +// 2. K8s call error +// 3. Valid beta csi driver crs // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestRemoveMultipleBetaCSIDriverCRs(t *testing.T) { // arrange variables for the tests var emptyCSIDriversCRs, undeletedCSIDriverCRs, unwantedCSIDriverCRs []storagev1beta1.CSIDriver @@ -915,12 +939,12 @@ func TestRemoveMultipleBetaCSIDriverCRs(t *testing.T) { } // TestGetCSIDriverInformation tests the GetCSIDriverInformation function -// It checks for the following conditions: -// - k8s error -// - no beta CSI driver found -// - valid current beta CSI driver found +// It checks the following cases: +// - fail with k8s error +// - pass with no beta CSI driver found and no k8s error +// - pass with valid current beta CSI driver found and no k8s error // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestGetCSIDriverInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -1057,11 +1081,14 @@ func TestGetCSIDriverInformation(t *testing.T) { } } -// TestPutCSIDriver tests the PutCSIDriver function -// It checks that the correct k8s client calls are made -// and that the correct error is returned +// TestPutCSIDriver tests the PutCSIDriver method +// It checks for the following cases: +// 1. Creating a CSI Driver and no k8s error occurs +// 2. Creating a CSI Driver and a k8s error occurs +// 3. Updating a CSI Driver and no k8s error occurs +// 4. Updating a CSI Driver and a k8s error occurs // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestPutCSIDriver(t *testing.T) { var validCSIDriver *storagev1.CSIDriver @@ -1207,14 +1234,14 @@ func TestPutCSIDriver(t *testing.T) { } } -// TestDeleteTridentCSIDriverCR tests the DeleteTridentCSIDriverCR function -// It checks that the function returns the correct error when the k8s client -// returns an error, and that it returns nil when the k8s client does not return -// an error. -// It returns the correct error when the k8s client returns an error, and that -// it returns nil when the k8s client does not return an error. +// TestDeleteTridentCSIDriverCR tests the DeleteTridentCSIDriverCR function. +// It checks the following cases: +// 1. GetCSIDriversByLabel fails +// 2. GetCSIDriversByLabel succeeds but RemoveMultipleCSIDriverCRs fails +// 3. GetCSIDriversByLabel succeeds and RemoveMultipleCSIDriverCRs succeeds +// It returns an error if any of the tests fail. // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestDeleteTridentCSIDriverCR(t *testing.T) { // arrange variables for the tests var emptyCSIDriverList, unwantedCSIDrivers []storagev1.CSIDriver @@ -1315,11 +1342,11 @@ func TestDeleteTridentCSIDriverCR(t *testing.T) { // TestRemoveMultipleCSIDriverCRs tests the RemoveMultipleCSIDriverCRs function // It checks the following cases: -// 1. No CSI driver CRs are passed in -// 2. A k8s call error occurs -// 3. Valid CSI driver CRs are passed in +// 1. No CSI driver CRs +// 2. K8s call error +// 3. Valid CSI driver CRs // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestRemoveMultipleCSIDriverCRs(t *testing.T) { // arrange variables for the tests var emptyCSIDriversCRs, undeletedCSIDriverCRs, unwantedCSIDriverCRs []storagev1.CSIDriver @@ -1401,14 +1428,12 @@ func TestRemoveMultipleCSIDriverCRs(t *testing.T) { } // TestGetClusterRoleInformation tests the GetClusterRoleInformation function -// in the installer package. -// It checks for the following conditions: -// 1. If the function returns the correct current cluster role -// 2. If the function returns the correct unwanted cluster roles -// 3. If the function returns the correct create cluster role boolean -// 4. If the function returns the correct error +// It checks the following cases: +// - k8s error +// - no cluster role found +// - valid current cluster role found // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestGetClusterRoleInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -1546,13 +1571,10 @@ func TestGetClusterRoleInformation(t *testing.T) { } // TestPutClusterRole tests the PutClusterRole function -// It checks the following cases: -// - creating a ClusterRole and no k8s error occurs -// - creating a ClusterRole and a k8s error occurs -// - updating a ClusterRole and no k8s error occurs -// - updating a ClusterRole and a k8s error occurs +// It checks that the function returns the expected error when a k8s error occurs +// It also checks that the function returns nil when no k8s error occurs // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestPutClusterRole(t *testing.T) { var validClusterRole *rbacv1.ClusterRole @@ -1696,10 +1718,13 @@ func TestPutClusterRole(t *testing.T) { } // TestDeleteTridentClusterRole tests the DeleteTridentClusterRole function -// It checks that the function returns the expected error when the k8s client returns an error -// It checks that the function returns nil when the k8s client does not return an error +// It checks for the following conditions: +// - GetClusterRolesByLabel fails +// - GetClusterRolesByLabel returns no cluster role bindings +// - GetClusterRolesByLabel succeeds but RemoveMultipleClusterRoles fails +// - GetClusterRolesByLabel succeeds and RemoveMultipleClusterRoles succeeds // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestDeleteTridentClusterRole(t *testing.T) { // arrange variables for the tests var emptyClusterRoleList, unwantedClusterRoles []rbacv1.ClusterRole @@ -1798,12 +1823,12 @@ func TestDeleteTridentClusterRole(t *testing.T) { } // TestRemoveMultipleClusterRoles tests the RemoveMultipleClusterRoles function -// It checks the following cases: -// 1. No cluster roles to delete -// 2. Error returned from k8s client -// 3. Valid cluster roles to delete +// It checks the following: +// - no cluster roles passed in +// - k8s call error +// - valid cluster roles passed in // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestRemoveMultipleClusterRoles(t *testing.T) { // arrange variables for the tests var emptyClusterRoles, unwantedClusterRoles, undeletedClusterRoles []rbacv1.ClusterRole @@ -1886,11 +1911,11 @@ func TestRemoveMultipleClusterRoles(t *testing.T) { // TestGetClusterRoleBindingInformation tests the GetClusterRoleBindingInformation function // It checks the following cases: -// 1. Expect to fail with k8s error -// 2. Expect to pass with no cluster role binding found and no k8s error -// 3. Expect to pass with valid current cluster role binding found and no k8s error +// - k8s error +// - no cluster role binding found and no k8s error +// - valid current cluster role binding found and no k8s error // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestGetClusterRoleBindingInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -2032,9 +2057,10 @@ func TestGetClusterRoleBindingInformation(t *testing.T) { } // TestPutClusterRoleBinding tests the PutClusterRoleBinding function -// It checks that the function returns the expected error +// It checks that the correct k8s client calls are made and that the +// correct error is returned. // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestPutClusterRoleBinding(t *testing.T) { var validClusterRoleBinding *rbacv1.ClusterRoleBinding @@ -2180,12 +2206,12 @@ func TestPutClusterRoleBinding(t *testing.T) { } // TestDeleteTridentClusterRoleBinding tests the DeleteTridentClusterRoleBinding function -// It checks that the function returns an error when it is unable to get the list of cluster role bindings -// It checks that the function returns nil when it is able to get the list of cluster role bindings -// It checks that the function returns an error when it is unable to delete the cluster role bindings -// It checks that the function returns nil when it is able to delete the cluster role bindings +// It checks the following cases: +// - GetClusterRoleBindingsByLabel fails +// - GetClusterRoleBindingsByLabel succeeds but RemoveMultipleClusterRoleBindings fails +// - GetClusterRoleBindingsByLabel succeeds and RemoveMultipleClusterRoleBindings succeeds // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestDeleteTridentClusterRoleBinding(t *testing.T) { // arrange variables for the tests var emptyClusterRoleBindingList, unwantedClusterRoleBindings []rbacv1.ClusterRoleBinding @@ -2289,7 +2315,7 @@ func TestDeleteTridentClusterRoleBinding(t *testing.T) { // 2. K8s call error // 3. Valid cluster role bindings // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestRemoveMultipleClusterRoleBindings(t *testing.T) { // arrange variables for the tests var emptyClusterRoleBindings, unwantedClusterRoleBindings, undeletedClusterRoleBindings []rbacv1.ClusterRoleBinding @@ -2373,12 +2399,12 @@ func TestRemoveMultipleClusterRoleBindings(t *testing.T) { } // TestGetDaemonSetInformation tests the GetDaemonSetInformation function -// It checks for the following cases: -// 1. k8s error -// 2. no daemonset found -// 3. current daemonset found +// It checks the following cases: +// 1. Expect to fail with k8s error +// 2. Expect to pass with no daemonset found and no k8s error +// 3. Expect to pass with current daemonset found and no k8s error // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestGetDaemonSetInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -2512,10 +2538,13 @@ func TestGetDaemonSetInformation(t *testing.T) { } // TestPutDaemonSet tests the PutDaemonSet function -// It checks that the function returns the expected error -// It also checks that the k8s client is called with the expected arguments +// It checks the following cases: +// - creating a DaemonSet and no k8s error occurs +// - creating a DaemonSet and a k8s error occurs +// - updating a DaemonSet and no k8s error occurs +// - updating a DaemonSet and a k8s error occurs // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestPutDaemonSet(t *testing.T) { daemonSetName := TridentCSILabel @@ -2664,11 +2693,13 @@ func TestPutDaemonSet(t *testing.T) { } // TestDeleteTridentDaemonSet tests the DeleteTridentDaemonSet function -// It checks that the function returns the correct error when the k8s client -// returns an error. It also checks that the function returns nil when the -// k8s client returns a list of daemonsets and when it returns an empty list. +// It checks the following cases: +// 1. GetDaemonSetsByLabel fails +// 2. GetDaemonSetsByLabel returns no deployments +// 3. GetDaemonSetsByLabel succeeds but RemoveMultipleDeployments fails +// 4. GetDaemonSetsByLabel succeeds and RemoveMultipleDeployments succeeds // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestDeleteTridentDaemonSet(t *testing.T) { // arrange variables for the tests var emptyDaemonSetList, unwantedDaemonSets []appsv1.DaemonSet @@ -2752,12 +2783,9 @@ func TestDeleteTridentDaemonSet(t *testing.T) { } // TestRemoveMultipleDaemonSets tests the RemoveMultipleDaemonSets function -// It checks the following cases: -// - no daemonsets -// - k8s call error -// - valid daemonsets +// It checks that the correct k8s calls are made and that the correct errors are returned // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestRemoveMultipleDaemonSets(t *testing.T) { // arrange variables for the tests var emptyDaemonSets, unwantedDaemonSets []appsv1.DaemonSet @@ -2837,12 +2865,12 @@ func TestRemoveMultipleDaemonSets(t *testing.T) { } // TestGetDeploymentInformation tests the GetDeploymentInformation function -// It checks for the following conditions: -// 1. k8s error -// 2. no daemonset found -// 3. current daemonset found +// It checks the following cases: +// - k8s error +// - no daemonset found +// - current daemonset found // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestGetDeploymentInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -2976,9 +3004,13 @@ func TestGetDeploymentInformation(t *testing.T) { } // TestPutDeployment tests the PutDeployment function -// It checks that the correct k8s client calls are made and that the correct error is returned +// It checks the following cases: +// - creating a Deployment and no k8s error occurs +// - creating a Deployment and a k8s error occurs +// - updating a Deployment and no k8s error occurs +// - updating a Deployment and a k8s error occurs // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestPutDeployment(t *testing.T) { deploymentName := getDeploymentName(true) @@ -3129,13 +3161,10 @@ func TestPutDeployment(t *testing.T) { } // TestDeleteTridentDeployment tests the DeleteTridentDeployment function -// It checks the following cases: -// - when GetDeploymentsByLabel fails -// - when GetDeploymentsByLabel returns no deployments -// - when GetDeploymentsByLabel succeeds but RemoveMultipleDeployments fails -// - when GetDeploymentsByLabel succeeds and RemoveMultipleDeployments succeeds +// It checks that the function returns the expected error when the k8s client +// returns the expected error // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestDeleteTridentDeployment(t *testing.T) { // arrange variables for the tests var emptyDeploymentList, unwantedDeployments []appsv1.Deployment @@ -3219,12 +3248,12 @@ func TestDeleteTridentDeployment(t *testing.T) { } // TestRemoveMultipleDeployments tests the RemoveMultipleDeployments function -// It checks for the following conditions: -// 1. No deployments to remove -// 2. Error returned from k8s client -// 3. Valid deployments to remove +// It checks the following cases: +// 1. No deployments to delete +// 2. K8s call error +// 3. Valid deployments // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestRemoveMultipleDeployments(t *testing.T) { // arrange variables for the tests var emptyDeploymentList, unwantedDeployments []appsv1.Deployment @@ -3304,12 +3333,13 @@ func TestRemoveMultipleDeployments(t *testing.T) { } // TestGetPodSecurityPolicyInformation tests the GetPodSecurityPolicyInformation function -// It checks the following cases: -// 1. Expect to fail with k8s error -// 2. Expect to pass with no pod security policies found and no k8s error -// 3. Expect to pass with valid current pod security policies found and no k8s error +// It checks for the following: +// - returns the correct current pod security policy +// - returns the correct unwanted pod security policies +// - returns the correct create pod security policy boolean +// - returns the correct error // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestGetPodSecurityPolicyInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -3450,12 +3480,12 @@ func TestGetPodSecurityPolicyInformation(t *testing.T) { // TestPutPodSecurityPolicy tests the PutPodSecurityPolicy function // It checks the following cases: -// 1. Create a PodSecurityPolicy and no k8s error occurs -// 2. Create a PodSecurityPolicy and a k8s error occurs -// 3. Update a PodSecurityPolicy and no k8s error occurs -// 4. Update a PodSecurityPolicy and a k8s error occurs +// - create a new PodSecurityPolicy +// - update an existing PodSecurityPolicy +// - fail to create a new PodSecurityPolicy +// - fail to update an existing PodSecurityPolicy // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestPutPodSecurityPolicy(t *testing.T) { pspName := getPSPName() @@ -3596,10 +3626,11 @@ func TestPutPodSecurityPolicy(t *testing.T) { // TestDeleteTridentPodSecurityPolicy tests the DeleteTridentPodSecurityPolicy function // It checks that the function returns the expected error when the k8s client returns an error // It checks that the function returns nil when the k8s client returns no policies -// It checks that the function returns an error when the k8s client returns policies but fails to delete them -// It checks that the function returns nil when the k8s client returns policies and succeeds in deleting them +// It checks that the function returns the expected error when the k8s client returns policies but +// the delete fails +// It checks that the function returns nil when the k8s client returns policies and the delete succeeds // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestDeleteTridentPodSecurityPolicy(t *testing.T) { // arrange variables for the tests var emptyPSPList, unwantedPSPs []policyv1beta1.PodSecurityPolicy @@ -3698,12 +3729,10 @@ func TestDeleteTridentPodSecurityPolicy(t *testing.T) { } // TestRemoveMultiplePodSecurityPolicies tests the RemoveMultiplePodSecurityPolicies function -// It checks for the following conditions: -// - no pod security policies -// - k8s call error -// - valid pod security policies +// It checks that the function returns the correct error when the k8s client fails to delete +// a pod security policy // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestRemoveMultiplePodSecurityPolicies(t *testing.T) { // arrange variables for the tests var emptyPodSecurityPolicyList, undeletedPodSecurityPolicies, unwantedPodSecurityPolicies []policyv1beta1.PodSecurityPolicy @@ -3786,12 +3815,12 @@ func TestRemoveMultiplePodSecurityPolicies(t *testing.T) { } // TestGetSecretInformation tests the GetSecretInformation function -// It checks the following cases: -// - k8s error -// - no secrets found -// - valid secrets found +// It checks for the following conditions: +// 1. k8s error +// 2. no secrets found +// 3. valid current secrets found // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestGetSecretInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -3936,12 +3965,12 @@ func TestGetSecretInformation(t *testing.T) { } // TestPutSecret tests the PutSecret function -// It checks for the following conditions: +// It checks the following cases: // - createSecret is true and no k8s error occurs // - createSecret is false // - createSecret is true and a k8s error occurs // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestPutSecret(t *testing.T) { secretName := getProtocolSecretName() @@ -4037,11 +4066,11 @@ func TestPutSecret(t *testing.T) { } // TestDeleteTridentSecret tests the DeleteTridentSecret function -// It checks that the function returns the correct error when -// GetSecretsByLabel fails, when GetSecretsByLabel returns no secrets, -// when DeleteSecret fails, and when DeleteSecret succeeds +// It checks that the function returns the expected error when the +// k8s client returns an error, and that it returns nil when the +// k8s client returns no error. // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestDeleteTridentSecret(t *testing.T) { // arrange variables for the tests var emptySecretList, unwantedSecrets []corev1.Secret @@ -4149,12 +4178,11 @@ func TestDeleteTridentSecret(t *testing.T) { } // TestRemoveMultipleSecrets tests the RemoveMultipleSecrets function -// It checks the following cases: -// 1. no secrets -// 2. k8s call error -// 3. valid secrets +// It checks that the function returns the correct error when the k8s client +// returns an error, and that it returns nil when the k8s client does not return +// an error // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestRemoveMultipleSecrets(t *testing.T) { // arrange variables for the tests var emptySecretList, undeletedSecrets, unwantedSecrets []corev1.Secret @@ -4243,12 +4271,10 @@ func TestRemoveMultipleSecrets(t *testing.T) { } // TestGetServiceInformation tests the GetServiceInformation function -// It checks the following cases: -// - Expect to fail with k8s error -// - Expect to pass with no services found and no k8s error -// - Expect to pass with valid current services found and no k8s error +// It checks to see if the correct service is returned and that the correct +// unwanted services are returned // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestGetServiceInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -4392,9 +4418,9 @@ func TestGetServiceInformation(t *testing.T) { } // TestPutService tests the PutService function -// It checks that the correct k8s client calls are made and that the correct errors are returned +// It checks that the correct k8s client functions are called and that the correct error is returned // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestPutService(t *testing.T) { serviceName := getServiceName() @@ -4535,12 +4561,13 @@ func TestPutService(t *testing.T) { } // TestDeleteTridentService tests the DeleteTridentService function -// It checks that the function returns the expected error when the k8s client returns an error -// It checks that the function returns nil when the k8s client returns no services -// It checks that the function returns an error when the k8s client returns services but fails to delete them -// It checks that the function returns nil when the k8s client returns services and successfully deletes them +// It checks that the function returns an error when the GetServicesByLabel function fails +// It checks that the function returns nil when the GetServicesByLabel function succeeds but +// the RemoveMultipleServices function fails +// It checks that the function returns nil when the GetServicesByLabel function succeeds and +// the RemoveMultipleServices function succeeds // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestDeleteTridentService(t *testing.T) { // arrange variables for the tests var emptyServiceList, unwantedServices []corev1.Service @@ -4649,10 +4676,12 @@ func TestDeleteTridentService(t *testing.T) { } // TestRemoveMultipleServices tests the RemoveMultipleServices function -// It checks that the function returns the correct error code based on the -// input and the k8s client calls +// It checks the following cases: +// - no services +// - k8s call error +// - valid services // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestRemoveMultipleServices(t *testing.T) { // arrange variables for the tests var emptyServiceList, unwantedServices []corev1.Service @@ -4732,12 +4761,12 @@ func TestRemoveMultipleServices(t *testing.T) { } // TestGetServiceAccountInformation tests the GetServiceAccountInformation function -// It checks for the following: -// 1. k8s error -// 2. no service accounts found -// 3. valid service accounts found +// It checks for the following cases: +// - k8s error +// - no service accounts found +// - valid service accounts found // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestGetServiceAccountInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var label, name, invalidName, namespace string @@ -4905,9 +4934,13 @@ func TestGetServiceAccountInformation(t *testing.T) { } // TestPutServiceAccount tests the PutServiceAccount function -// It checks for errors and ensures that the correct k8s client calls are made +// It checks for the following cases: +// - creating a service account and no k8s error occurs +// - creating a service account and a k8s error occurs +// - updating a service account and no k8s error occurs +// - updating a service account and a k8s error occurs // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestPutServiceAccount(t *testing.T) { serviceAccountName := getServiceAccountName(true) @@ -5072,12 +5105,10 @@ func TestPutServiceAccount(t *testing.T) { } // TestDeleteTridentServiceAccount tests the DeleteTridentServiceAccount function -// It checks the following cases: -// - when GetServiceAccountsByLabel fails -// - when GetServiceAccountsByLabel succeeds but RemoveMultipleServiceAccounts fails -// - when GetServiceAccountsByLabel succeeds and RemoveMultipleServiceAccounts succeeds +// It checks that the function returns the expected error when the k8s client returns an error +// It also checks that the function returns nil when the k8s client returns no error // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestDeleteTridentServiceAccount(t *testing.T) { // arrange variables for the tests var emptyServiceAccountList, unwantedServiceAccounts []corev1.ServiceAccount @@ -5186,10 +5217,12 @@ func TestDeleteTridentServiceAccount(t *testing.T) { } // TestRemoveMultipleServiceAccounts tests the RemoveMultipleServiceAccounts function -// It checks that the function returns the correct error when the k8s client returns an error -// It also checks that the function returns nil when the k8s client does not return an error +// It checks for the following cases: +// 1. No service accounts +// 2. K8s call error +// 3. Valid service accounts // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestRemoveMultipleServiceAccounts(t *testing.T) { // arrange variables for the tests var emptyServiceAccountList, undeletedServiceAccounts, unwantedServiceAccounts []corev1.ServiceAccount @@ -5277,14 +5310,14 @@ func TestRemoveMultipleServiceAccounts(t *testing.T) { } } -// TestGetTridentOpenShiftSCCInformation tests the GetTridentOpenShiftSCCInformation method -// It checks that the method returns the correct values for the following scenarios: -// - k8s error -// - no openshift scc found, no k8s error, and an scc user does not exist -// - no openshift scc found, no k8s error, and a it should update -// - valid current services found and no k8s error +// TestGetTridentOpenShiftSCCInformation tests the GetTridentOpenShiftSCCInformation function +// It checks the following cases: +// - when the k8s client returns an error +// - when the k8s client returns no error and no openshift scc is found +// - when the k8s client returns no error and an openshift scc is found +// - when the k8s client returns no error and an openshift scc is found, but it should be updated // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestGetTridentOpenShiftSCCInformation(t *testing.T) { // declare and initialize variables used throughout the test cases var name, username string @@ -5431,9 +5464,12 @@ func TestGetTridentOpenShiftSCCInformation(t *testing.T) { } // TestExecPodForVersionInformation tests the ExecPodForVersionInformation function -// It checks that the function returns the expected error and output +// It checks the following cases: +// 1. No command supplied +// 2. K8s error when exec the supplied cmd +// 3. No error when exec the supplied cmd // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestExecPodForVersionInformation(t *testing.T) { podName := "trident-transient-pod" @@ -5529,10 +5565,12 @@ func TestExecPodForVersionInformation(t *testing.T) { } // TestGetCSISnapshotterVersion tests the GetCSISnapshotterVersion function -// It checks that the correct snapshot crd version is returned based on the deployment -// and the snapshot crd version +// It checks the following cases: +// 1. When the deployment is empty, it should return v1 +// 2. When the deployment contains a snapshotter:v4 image, it should return v1 +// 3. When the deployment contains a snapshotter image without a version, it should return an empty string // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestGetCSISnapshotterVersion(t *testing.T) { var emptyDeployment, validDeployment, invalidDeployment *appsv1.Deployment @@ -5615,13 +5653,10 @@ func TestGetCSISnapshotterVersion(t *testing.T) { } // TestDeleteTridentStatefulSet tests the DeleteTridentStatefulSet function -// It checks for the following conditions: -// 1. GetStatefulSetsByLabel fails -// 2. GetStatefulSetsByLabel returns no statefulsets -// 3. GetStatefulSetsByLabel succeeds but RemoveMultipleStatefulSets fails -// 4. GetStatefulSetsByLabel succeeds and RemoveMultipleStatefulSets succeeds +// It checks that the function returns the expected error when the k8s client +// returns the expected error // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestDeleteTridentStatefulSet(t *testing.T) { // arrange variables for the tests var emptyStatefulSets, unwantedStatefulSets []appsv1.StatefulSet @@ -5706,14 +5741,14 @@ func TestDeleteTridentStatefulSet(t *testing.T) { // TestPutOpenShiftSCC tests the PutOpenShiftSCC function // It checks the following cases: -// 1. create OpenShift SCCs and no k8s error occurs when removing Trident users from OpenShiftSCC -// 2. create OpenShift SCCs and a k8s error occurs when removing Trident users from OpenShiftSCC -// 3. create OpenShift SCCs and no k8s error occurs -// 4. create OpenShift SCCs and a k8s error occurs -// 5. update OpenShift SCCs and no k8s error occurs -// 6. update OpenShift SCCs and a k8s error occurs +// - when creating OpenShift SCCs and no k8s error occurs when removing Trident users from OpenShiftSCC +// - when creating OpenShift SCCs and a k8s error occurs when removing Trident users from OpenShiftSCC +// - when creating OpenShift SCCs and no k8s error occurs +// - when creating OpenShift SCCs and a k8s error occurs +// - when updating OpenShift SCCs and no k8s error occurs +// - when updating OpenShift SCCs and a k8s error occurs // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestPutOpenShiftSCC(t *testing.T) { // arrange variables for the tests openShiftSCCUserName := getOpenShiftSCCUserName() @@ -5913,7 +5948,7 @@ func TestPutOpenShiftSCC(t *testing.T) { // - when GetOpenShiftSCCByName succeeds but DeleteObjectByYAML fails // - when GetOpenShiftSCCByName succeeds and RemoveTridentUserFromOpenShiftSCC is called // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestDeleteOpenShiftSCC(t *testing.T) { // arrange variables for the tests openShiftSCCName := "trident" @@ -6009,11 +6044,11 @@ func TestDeleteOpenShiftSCC(t *testing.T) { // TestRemoveMultiplePods tests the RemoveMultiplePods function // It checks the following cases: -// 1. no pods -// 2. k8s call error -// 3. valid pods +// 1. No pods to delete +// 2. Error from k8s client +// 3. Valid pods to delete // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestRemoveMultiplePods(t *testing.T) { // arrange variables for the tests var emptyPodList, undeletedPods, unwantedPods []corev1.Pod @@ -6102,12 +6137,12 @@ func TestRemoveMultiplePods(t *testing.T) { } // TestRemoveMultipleStatefulSets tests the RemoveMultipleStatefulSets function -// It checks for the following cases: -// 1. No stateful sets are passed in -// 2. A k8s call error occurs -// 3. Valid stateful sets are passed in +// It checks the following cases: +// 1. No stateful sets to delete +// 2. Error returned from k8s client +// 3. Successful deletion of stateful sets // -// -- Doc autogenerated on 2022-05-12 18:53:38.819789 -- +// -- Doc autogenerated on 2022-05-12 21:04:12.772596 -- func TestRemoveMultipleStatefulSets(t *testing.T) { // arrange variables for the tests var emptyStatefulSetList, unwantedStatefulSets []appsv1.StatefulSet diff --git a/operator/controllers/orchestrator/installer/uninstaller.go b/operator/controllers/orchestrator/installer/uninstaller.go index 3ca3b1b57..080454e35 100644 --- a/operator/controllers/orchestrator/installer/uninstaller.go +++ b/operator/controllers/orchestrator/installer/uninstaller.go @@ -12,16 +12,16 @@ import ( ) // UninstallTrident uninstalls Trident from the Kubernetes cluster. -// It returns an error if Trident is not installed. +// It returns an error if the uninstall fails. // Returns: -// - error if Trident is not installed or if an error occurs during uninstall +// error: if the uninstall fails // Example: -// err := installer.UninstallTrident() -// if err != nil { -// fmt.Println(err) -// } +// err := i.UninstallTrident() +// if err != nil { +// log.Errorf("Uninstall failed: %v", err) +// } // -// -- Doc autogenerated on 2022-05-12 19:02:27.838010 -- +// -- Doc autogenerated on 2022-05-12 21:12:31.321270 -- func (i *Installer) UninstallTrident() error { // 1. preview CSI Trident --> uninstall preview CSI Trident @@ -121,11 +121,11 @@ func (i *Installer) UninstallTrident() error { // UninstallCSIPreviewTrident uninstalls Trident CSI Preview // It returns an error if the uninstall fails // Returns: -// error: nil if uninstall was successful, otherwise an error object +// error: error object if the uninstall fails // Example: -// err := installer.UninstallCSIPreviewTrident() +// err := i.UninstallCSIPreviewTrident() // -// -- Doc autogenerated on 2022-05-12 19:02:27.838010 -- +// -- Doc autogenerated on 2022-05-12 21:12:31.321270 -- func (i *Installer) UninstallCSIPreviewTrident() error { appLabel = TridentCSILabel appLabelKey = TridentCSILabelKey @@ -134,14 +134,17 @@ func (i *Installer) UninstallCSIPreviewTrident() error { return i.client.DeleteTridentStatefulSet(appLabel) } -// UninstallLegacyTrident uninstalls legacy Trident -// It returns an error if the uninstall fails. +// UninstallLegacyTrident removes the legacy Trident deployment and RBAC objects +// It returns an error if the uninstall fails // Returns: -// error - error if uninstall fails +// error: any errors encountered during uninstall // Example: -// err := installer.UninstallLegacyTrident() +// err := i.UninstallLegacyTrident() +// if err != nil { +// return err +// } // -// -- Doc autogenerated on 2022-05-12 19:02:27.838010 -- +// -- Doc autogenerated on 2022-05-12 21:12:31.321270 -- func (i *Installer) UninstallLegacyTrident() error { appLabel = TridentLegacyLabel appLabelKey = TridentLegacyLabelKey @@ -186,15 +189,14 @@ func (i *Installer) removeRBACObjects(csi bool) error { return nil } -func (i *Installer) ObliviateCRDs() error { // ObliviateCRDs removes all Trident CRDs from the cluster. -// It returns an error if the CRDs cannot be removed. +// It returns an error if any CRD cannot be deleted. // Returns: -// error - if the CRDs cannot be removed +// error - any error encountered // Example: // err := installer.ObliviateCRDs() // -// -- Doc autogenerated on 2022-05-12 19:02:27.838010 -- +// -- Doc autogenerated on 2022-05-12 21:12:31.321270 -- func (i *Installer) ObliviateCRDs() error { return cmd.ObliviateCRDs(i.client, i.tridentCRDClient, k8sTimeout) } diff --git a/operator/controllers/orchestrator/installer/utils.go b/operator/controllers/orchestrator/installer/utils.go index e2efac2ce..8fb95bd0e 100644 --- a/operator/controllers/orchestrator/installer/utils.go +++ b/operator/controllers/orchestrator/installer/utils.go @@ -2,14 +2,13 @@ package installer // getServiceAccountName returns the name of the service account to use for Trident // Parameters: -// csi - if true, use the CSI service account name +// csi (bool) - true if Trident is being installed as a CSI driver; false if Trident is being installed as a legacy driver // Returns: -// the service account name +// (string) - the name of the service account to use for Trident // Example: -// getServiceAccountName(true) -// Returns: "trident-csi" +// name := getServiceAccountName(true) // -// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- +// -- Doc autogenerated on 2022-05-12 21:13:42.659080 -- func getServiceAccountName(csi bool) string { if csi { return TridentCSI @@ -18,15 +17,16 @@ func getServiceAccountName(csi bool) string { } } -// getClusterRoleName returns the name of the cluster role to use for Trident +// getClusterRoleName returns the name of the cluster role to use for the given CSI flag // Parameters: -// csi - whether to use the CSI driver -// Return: -// string - the name of the cluster role +// csi - true if Trident should be installed as a CSI driver +// Returns: +// string - name of the cluster role to use // Example: -// getClusterRoleName(true) +// getClusterRoleName(false) +// > "trident" // -// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- +// -- Doc autogenerated on 2022-05-12 21:13:42.659080 -- func getClusterRoleName(csi bool) string { if csi { return TridentCSI @@ -41,9 +41,10 @@ func getClusterRoleName(csi bool) string { // Returns: // string - the name of the cluster role binding to use // Example: -// name := getClusterRoleBindingName(csi) +// getClusterRoleBindingName(true) +// > "trident-csi" // -// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- +// -- Doc autogenerated on 2022-05-12 21:13:42.659080 -- func getClusterRoleBindingName(csi bool) string { if csi { return TridentCSI @@ -52,62 +53,59 @@ func getClusterRoleBindingName(csi bool) string { } } -// getPSPName returns the name of the PSP to be used for Trident +// getPSPName returns the name of the PSP to use // Returns: -// string: the name of the PSP to be used for Trident +// string: the name of the PSP // Example: -// pspName := getPSPName() +// psp := getPSPName() // -// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- +// -- Doc autogenerated on 2022-05-12 21:13:42.659080 -- func getPSPName() string { return TridentPSP } // getServiceName returns the name of the service // Returns: -// string: service name +// string: the name of the service // Example: -// name := getServiceName() +// installer.getServiceName() // -// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- +// -- Doc autogenerated on 2022-05-12 21:13:42.659080 -- func getServiceName() string { return TridentCSI } -// getProtocolSecretName returns the name of the secret that contains the protocol -// for the CSI driver. +// getProtocolSecretName returns the name of the protocol secret // Returns: -// string: the name of the secret +// string - the name of the protocol secret // Example: // getProtocolSecretName() -// => "trident-csi-secret" // -// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- +// -- Doc autogenerated on 2022-05-12 21:13:42.659080 -- func getProtocolSecretName() string { return TridentCSI } // getEncryptionSecretName returns the name of the secret that contains the encryption keys // Returns: -// string: name of the secret +// string: the name of the secret // Example: -// name := getEncryptionSecretName() +// getEncryptionSecretName() // -// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- +// -- Doc autogenerated on 2022-05-12 21:13:42.659080 -- func getEncryptionSecretName() string { return TridentEncryptionKeys } // getDeploymentName returns the name of the Trident deployment // Parameters: -// csi - true if Trident is being deployed as a CSI driver +// csi - true if the CSI deployment should be used // Returns: -// string - the name of the Trident deployment +// The name of the Trident deployment // Example: -// getDeploymentName(true) -> "trident-csi" -// getDeploymentName(false) -> "trident" +// getDeploymentName(true) returns "trident-csi" // -// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- +// -- Doc autogenerated on 2022-05-12 21:13:42.659080 -- func getDeploymentName(csi bool) string { if csi { return TridentCSI @@ -116,36 +114,37 @@ func getDeploymentName(csi bool) string { } } -// getDaemonSetName returns the name of the Trident CSI DaemonSet. +// getDaemonSetName returns the name of the Trident CSI DaemonSet // Returns: -// string: The name of the Trident CSI DaemonSet. +// string: the name of the Trident CSI DaemonSet // Example: -// getDaemonSetName() +// name := getDaemonSetName() // -// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- +// -- Doc autogenerated on 2022-05-12 21:13:42.659080 -- func getDaemonSetName() string { return TridentCSI } // getCSIDriverName returns the name of the CSI driver // Returns: -// string: CSI driver name +// string: the name of the CSI driver // Example: -// name := getCSIDriverName() +// csiDriverName := getCSIDriverName() // -// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- +// -- Doc autogenerated on 2022-05-12 21:13:42.659080 -- func getCSIDriverName() string { return CSIDriver } // getOpenShiftSCCUserName returns the name of the OpenShift SCC user +// depending on whether CSI is enabled or not. // Returns: -// TridentCSI - if Trident is deployed as a CSI driver -// TridentLegacy - if Trident is deployed as a FlexVolume driver +// TridentCSI: if CSI is enabled +// TridentLegacy: if CSI is disabled // Example: -// getOpenShiftSCCUserName() -> "trident-csi" +// sccuser := getOpenShiftSCCUserName() // -// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- +// -- Doc autogenerated on 2022-05-12 21:13:42.659080 -- func getOpenShiftSCCUserName() string { if csi { return TridentCSI @@ -154,13 +153,13 @@ func getOpenShiftSCCUserName() string { } } -// getOpenShiftSCCName returns the name of the OpenShift SCC +// getOpenShiftSCCName returns the name of the SCC to use for OpenShift // Returns: -// string - name of the OpenShift SCC +// string: the name of the SCC to use for OpenShift // Example: -// name := getOpenShiftSCCName() +// sccName := installer.getOpenShiftSCCName() // -// -- Doc autogenerated on 2022-05-12 19:03:40.444825 -- +// -- Doc autogenerated on 2022-05-12 21:13:42.659080 -- func getOpenShiftSCCName() string { return OpenShiftSCCName } diff --git a/operator/controllers/provisioner/apis/netapp/v1/register.go b/operator/controllers/provisioner/apis/netapp/v1/register.go index e4da6b8c3..1072dec3d 100644 --- a/operator/controllers/provisioner/apis/netapp/v1/register.go +++ b/operator/controllers/provisioner/apis/netapp/v1/register.go @@ -21,7 +21,6 @@ func Kind(kind string) schema.GroupKind { // Resource takes an unqualified resource and returns back a Group qualified GroupResource func Resource(resource string) schema.GroupResource { -func Kind(kind string) schema.GroupKind { return SchemeGroupVersion.WithResource(resource).GroupResource() } @@ -31,22 +30,17 @@ var ( ) // Adds the list of known types to the given scheme. -func addKnownTypes(scheme *runtime.Scheme) error { // addKnownTypes adds the set of types defined in this -// It returns the SchemeBuilder +// It returns the SchemeBuilder. // Parameters: -// scheme *runtime.Scheme -// builder *runtime.SchemeBuilder -// config *rest.Config -// codecs serializer.CodecFactory -// options *generic.StoreOptions -// openAPIConfig *openapi.Config +// scheme: the SchemeBuilder instance used to register the types +// addToScheme: a function that adds the types to a scheme // Returns: -// *runtime.SchemeBuilder +// the SchemeBuilder instance used to register the types // Example: -// addKnownTypes(scheme) +// addKnownTypes(s, api.SchemeBuilder.AddToScheme) // -// -- Doc autogenerated on 2022-05-12 19:06:33.514412 -- +// -- Doc autogenerated on 2022-05-12 21:16:56.865707 -- func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &TridentProvisioner{}, diff --git a/operator/controllers/provisioner/client/clientset/versioned/fake/clientset_generated.go b/operator/controllers/provisioner/client/clientset/versioned/fake/clientset_generated.go index 5179fa978..2605591f7 100644 --- a/operator/controllers/provisioner/client/clientset/versioned/fake/clientset_generated.go +++ b/operator/controllers/provisioner/client/clientset/versioned/fake/clientset_generated.go @@ -52,31 +52,30 @@ type Clientset struct { tracker testing.ObjectTracker } -func (c *Clientset) Discovery() discovery.DiscoveryInterface { -// Discovery retrieves the DiscoveryClient -// It returns a fake implementation of the discovery client +// Discovery is the discovery interface +// It returns a fake discovery client // Returns: -// *discovery.DiscoveryClient +// *fake.Discovery // Example: -// clientset := fake.NewSimpleClientset() -// discoveryClient := clientset.Discovery() +// discovery := fake.Discovery() // -// -- Doc autogenerated on 2022-05-12 19:06:58.435680 -- +// -- Doc autogenerated on 2022-05-12 21:17:18.298051 -- func (c *Clientset) Discovery() discovery.DiscoveryInterface { return c.discovery } // Tracker is a fake implementation of the Tracker interface. -// It returns fake objects. +// It returns fake objects from the fake client. // Returns: -// * fake.Clientset -// * fake.Tracker -// * fake.Tracker +// *fake.Client - fake client +// *fake.Tracker - fake tracker // Example: -// cs := fake.NewSimpleClientset() -// cs.Tracker() +// c := fake.NewSimpleClientset() +// t := c.Tracker() +// fakeClient := t.Client() +// fakeTracker := t.Tracker() // -// -- Doc autogenerated on 2022-05-12 19:06:58.435680 -- +// -- Doc autogenerated on 2022-05-12 21:17:18.298051 -- func (c *Clientset) Tracker() testing.ObjectTracker { return c.tracker } diff --git a/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go b/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go index 31ca3e820..213971bdb 100644 --- a/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go +++ b/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go @@ -14,16 +14,18 @@ type FakeTridentV1 struct { *testing.Fake } -// TridentProvisioners returns a TridentProvisionerInterface. +// TridentProvisioners implements TridentProvisionerInterface +// It returns a fake TridentProvisionerInterface // Parameters: -// namespace - namespace of the TridentProvisionerInterface. +// c - a TridentClient +// namespace - the namespace // Returns: -// TridentProvisionerInterface +// a fake TridentProvisionerInterface // Example: -// kubeClient := fake.NewSimpleClientset() -// tridentProvisioners := kubeClient.TridentV1().TridentProvisioners("default") +// c := fake.NewSimpleClientset() +// fake.TridentProvisioners(c, "default") // -// -- Doc autogenerated on 2022-05-12 19:08:18.384280 -- +// -- Doc autogenerated on 2022-05-12 21:18:39.129394 -- func (c *FakeTridentV1) TridentProvisioners(namespace string) v1.TridentProvisionerInterface { return &FakeTridentProvisioners{c, namespace} } diff --git a/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/netapp_client.go b/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/netapp_client.go index f26d95afb..baa490bbc 100644 --- a/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/netapp_client.go +++ b/operator/controllers/provisioner/client/clientset/versioned/typed/netapp/v1/netapp_client.go @@ -21,15 +21,15 @@ type TridentV1Client struct { } // TridentProvisioners returns a TridentProvisionerInterface. -// A group's client should implement this interface. // Parameters: -// namespace: the namespace to use +// namespace - the namespace where Trident is installed // Returns: -// TridentProvisionerInterface: the TridentProvisionerInterface +// a TridentProvisionerInterface // Example: -// tridentProvisioners := c.TridentV1().TridentProvisioners("default") +// c := v1.NewTridentV1Client("", "", nil) +// c.TridentProvisioners("trident").Get("trident") // -// -- Doc autogenerated on 2022-05-12 19:07:44.790566 -- +// -- Doc autogenerated on 2022-05-12 21:18:04.957298 -- func (c *TridentV1Client) TridentProvisioners(namespace string) TridentProvisionerInterface { return newTridentProvisioners(c, namespace) } @@ -50,7 +50,6 @@ func NewForConfig(c *rest.Config) (*TridentV1Client, error) { // NewForConfigOrDie creates a new TridentV1Client for the given config and // panics if there is an error in the config. func NewForConfigOrDie(c *rest.Config) *TridentV1Client { -func NewForConfig(c *rest.Config) (*TridentV1Client, error) { client, err := NewForConfig(c) if err != nil { panic(err) @@ -60,25 +59,20 @@ func NewForConfig(c *rest.Config) (*TridentV1Client, error) { // New creates a new TridentV1Client for the given RESTClient. func New(c rest.Interface) *TridentV1Client { -func NewForConfigOrDie(c *rest.Config) *TridentV1Client { return &TridentV1Client{c} } -func setConfigDefaults(config *rest.Config) error { // setConfigDefaults sets the default values for the provided config // It returns an error if the config is invalid // Parameters: -// config: the config to set defaults on +// config: the configuration to set the defaults for // Returns: // error: an error if the config is invalid // Example: // config := &rest.Config{} -// err := setConfigDefaults(config) -// if err != nil { -// log.Fatal(err) -// } +// setConfigDefaults(config) // -// -- Doc autogenerated on 2022-05-12 19:07:44.790566 -- +// -- Doc autogenerated on 2022-05-12 21:18:04.957298 -- func setConfigDefaults(config *rest.Config) error { gv := v1.SchemeGroupVersion config.GroupVersion = &gv diff --git a/operator/controllers/provisioner/client/informers/externalversions/factory.go b/operator/controllers/provisioner/client/informers/externalversions/factory.go index 10c13974d..5f0d09672 100644 --- a/operator/controllers/provisioner/client/informers/externalversions/factory.go +++ b/operator/controllers/provisioner/client/informers/externalversions/factory.go @@ -47,7 +47,6 @@ func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInfo // WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { -func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { return func(factory *sharedInformerFactory) *sharedInformerFactory { factory.tweakListOptions = tweakListOptions return factory @@ -56,7 +55,6 @@ func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInfo // WithNamespace limits the SharedInformerFactory to the specified namespace. func WithNamespace(namespace string) SharedInformerOption { -func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { return func(factory *sharedInformerFactory) *sharedInformerFactory { factory.namespace = namespace return factory @@ -65,7 +63,6 @@ func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFu // NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { -func WithNamespace(namespace string) SharedInformerOption { return NewSharedInformerFactoryWithOptions(client, defaultResync) } @@ -74,13 +71,11 @@ func WithNamespace(namespace string) SharedInformerOption { // as specified here. // Deprecated: Please use NewSharedInformerFactoryWithOptions instead func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { -func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) } // NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { -func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { factory := &sharedInformerFactory{ client: client, namespace: v1.NamespaceAll, @@ -100,7 +95,6 @@ func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync // Start initializes all requested informers. func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { -func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { f.lock.Lock() defer f.lock.Unlock() @@ -114,7 +108,6 @@ func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResy // WaitForCacheSync waits for all started informers' cache were synced. func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { -func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { informers := func() map[reflect.Type]cache.SharedIndexInformer { f.lock.Lock() defer f.lock.Unlock() @@ -137,19 +130,19 @@ func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { // InternalInformerFor returns the SharedIndexInformer for obj using an internal // client. -func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { -// InformerFor is the same as InformerFor without the object -// It returns a SharedIndexInformer instead of an Interface. -// A SharedIndexInformer uses the Indexer internally. -// Therefore, lister is not needed (can be nil). +// InformerFor returns the SharedIndexInformer for objects of a given type. +// It is a convenience method for calling NewFilteredSharedInformerFactory. // Parameters: -// obj - the object +// obj - the object type +// newFunc - a function that creates a new object of the given type. +// This is used to instantiate a new informer. +// If newFunc is nil, the default informer for the given // Returns: -// a SharedIndexInformer +// The SharedIndexInformer for the given object type // Example: -// informer := factory.InformerFor(&v1.Pod{}, newPodInformer) +// informer := f.InformerFor(&v1.Pod{}, newPodInformer) // -// -- Doc autogenerated on 2022-05-12 19:08:37.248494 -- +// -- Doc autogenerated on 2022-05-12 21:19:03.478754 -- func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { f.lock.Lock() defer f.lock.Unlock() @@ -181,18 +174,13 @@ type SharedInformerFactory interface { Trident() netapp.Interface } -// Trident returns a new Interface. +// Trident returns a new interface to the Trident API. // Returns: -// - a new Interface -// - error if there is an error initializing the client +// * netapp.Interface: Trident API client // Example: -// c, err := externalversions.NewForConfig(&config) -// if err != nil { -// return nil, err -// } -// return c.Trident() +// trident := externalversions.Trident() // -// -- Doc autogenerated on 2022-05-12 19:08:37.248494 -- +// -- Doc autogenerated on 2022-05-12 21:19:03.478754 -- func (f *sharedInformerFactory) Trident() netapp.Interface { return netapp.New(f, f.namespace, f.tweakListOptions) } diff --git a/operator/controllers/provisioner/client/informers/externalversions/netapp/v1/tridentprovisioner.go b/operator/controllers/provisioner/client/informers/externalversions/netapp/v1/tridentprovisioner.go index 676bec428..f0b7de285 100644 --- a/operator/controllers/provisioner/client/informers/externalversions/netapp/v1/tridentprovisioner.go +++ b/operator/controllers/provisioner/client/informers/externalversions/netapp/v1/tridentprovisioner.go @@ -42,7 +42,6 @@ func NewTridentProvisionerInformer(client versioned.Interface, namespace string, // Always prefer using an informer factory to get a shared informer instead of getting an independent // one. This reduces memory footprint and number of connections to the server. func NewFilteredTridentProvisionerInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { -func NewTridentProvisionerInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { return cache.NewSharedIndexInformer( &cache.ListWatch{ ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { @@ -64,46 +63,48 @@ func NewTridentProvisionerInformer(client versioned.Interface, namespace string, ) } -func (f *tridentProvisionerInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { -// defaultInformer is -// It returns a SharedIndexInformer +// defaultInformer is used to initialize the TridentProvisioner informer +// It returns a SharedIndexInformer for TridentProvisioner objects // Parameters: -// client - the kubernetes client +// client - the TridentProvisioner client // resyncPeriod - the resync period // indexers - the indexers // Returns: -// a SharedIndexInformer +// a SharedIndexInformer for TridentProvisioner objects // Example: -// defaultInformer(kubernetes.NewForConfig(config), time.Duration(0 * time.Second), cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) +// defaultInformer := v1.defaultInformer(clientset, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}) // -// -- Doc autogenerated on 2022-05-12 19:09:28.836842 -- +// -- Doc autogenerated on 2022-05-12 21:19:39.312814 -- func (f *tridentProvisionerInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { return NewFilteredTridentProvisionerInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) } -// Informer is used to inform about resources. -// It returns a cache.SharedIndexInformer. +// Informer provides access to a shared informer and lister for +// TridentProvisioners. +// It returns a cache.SharedIndexInformer // Returns: -// A cache.SharedIndexInformer +// * cache.SharedIndexInformer // Example: -// informer := f.TridentInformer().TridentProvisioner().Informer() -// indexer := informer.GetIndexer() -// indexer.Add(&netappv1.TridentProvisioner{ObjectMeta: metav1.ObjectMeta{Name: "foo"}}) -// obj, exists, err := indexer.GetByKey("foo") +// tpInformer := informers.NewTridentProvisionerInformer(client, 0) +// tpInformer.Informer() +// tpInformer.Lister() // -// -- Doc autogenerated on 2022-05-12 19:09:28.836842 -- +// -- Doc autogenerated on 2022-05-12 21:19:39.312814 -- func (f *tridentProvisionerInformer) Informer() cache.SharedIndexInformer { return f.factory.InformerFor(&netappv1.TridentProvisioner{}, f.defaultInformer) } -// Lister implements the TridentProvisionerLister interface. -// It returns TridentProvisionerLister. +// Lister implements a generic lister for TridentProvisioner resources. +// It returns TridentProvisioner objects retrieved from a shared informer's store. // Returns: // * TridentProvisionerLister +// * TridentProvisionerNamespaceLister // Example: -// lister := listers.NewTridentProvisionerLister(indexer) +// lister := listers.NewTridentProvisionerLister() +// svc, err := lister.Get("foo") +// Use "NewTridentProvisionerLister" to construct a new TridentProvisionerLister. // -// -- Doc autogenerated on 2022-05-12 19:09:28.836842 -- +// -- Doc autogenerated on 2022-05-12 21:19:39.312814 -- func (f *tridentProvisionerInformer) Lister() v1.TridentProvisionerLister { return v1.NewTridentProvisionerLister(f.Informer().GetIndexer()) }