From fedcb2928c8a42b4b7a557326a1860566fb2e09b Mon Sep 17 00:00:00 2001 From: VinayKumarHavanur <54576364+VinayKumarHavanur@users.noreply.github.com> Date: Mon, 8 Apr 2024 15:48:44 +0530 Subject: [PATCH] Enhancements to run Trident as an AKS extension. * Enhancement to run Trident as an AKS extension as part of offering Trident as an 1P service in Azure. --------- Co-authored-by: Shubham Phadnis <42840905+sphadnis007@users.noreply.github.com> --- Makefile | 10 +- cli/api/types.go | 22 + cli/cmd/check.go | 20 + cli/cmd/check_operator.go | 158 ++ cli/cmd/install.go | 2 + cli/k8s_client/client_factory.go | 2 +- cli/k8s_client/yaml_factory.go | 69 +- cli/k8s_client/yaml_factory_test.go | 163 ++ deploy/bundle_post_1_25.yaml | 7 + deploy/bundle_pre_1_25.yaml | 7 + deploy/operator.yaml | 7 + hack/boilerplate.go.txt | 2 +- .../crds/tridentconfigurators.yaml | 54 + .../templates/clusterrole.yaml | 8 + .../templates/deployment.yaml | 25 + .../templates/postinstallupgradehook.yaml | 58 + .../templates/serviceaccount.yaml | 7 + .../templates/tridentconfigurator.yaml | 31 + helm/trident-operator/values.yaml | 16 + mocks/mock_operator/mock_clients/mock_api.go | 276 +++ .../mock_clients/mock_api.go | 1873 +++++++++++++++++ .../mock_installer/mock_installer.go | 2 +- .../mock_azure/mock_api.go | 28 + operator/clients/factory.go | 32 +- operator/clients/operator_crd.go | 68 + operator/clients/snapshot_crd.go | 42 + operator/clients/trident_crd.go | 43 + operator/clients/types.go | 50 + operator/config/config.go | 4 + .../configurator/clients/configurator.go | 217 ++ .../configurator/clients/extended_k8s.go | 71 + .../controllers/configurator/clients/types.go | 59 + .../controllers/configurator/controller.go | 622 ++++++ .../configurator/controller_test.go | 17 + .../configurator/storage_drivers/anf.go | 339 +++ .../configurator/storage_drivers/anf_test.go | 432 ++++ .../configurator/storage_drivers/config.go | 20 + .../configurator/storage_drivers/types.go | 11 + .../storage_drivers/yaml_factory.go | 139 ++ operator/controllers/controller.go | 9 +- .../controllers/orchestrator/controller.go | 51 +- .../orchestrator/installer/installer.go | 7 +- .../orchestrator/installer/types.go | 2 +- .../apis/netapp/v1/doc.go | 0 .../apis/netapp/v1/register.go | 2 + .../crd/apis/netapp/v1/tridentconfigurator.go | 58 + .../crd/apis/netapp/v1/tridentorchestrator.go | 33 + .../netapp/v1/tridentorchestrator_test.go | 78 + .../apis/netapp/v1/types.go | 50 + .../apis/netapp/v1/zz_generated.deepcopy.go | 105 +- .../client/clientset/versioned/clientset.go | 4 +- .../client/clientset/versioned/doc.go | 2 +- .../versioned/fake/clientset_generated.go | 8 +- .../client/clientset/versioned/fake/doc.go | 2 +- .../clientset/versioned/fake/register.go | 4 +- .../client/clientset/versioned/scheme/doc.go | 2 +- .../clientset/versioned/scheme/register.go | 4 +- .../versioned/typed/netapp/v1/doc.go | 2 +- .../versioned/typed/netapp/v1/fake/doc.go | 2 +- .../netapp/v1/fake/fake_netapp_client.go | 8 +- .../v1/fake/fake_tridentconfigurator.go | 119 ++ .../v1/fake/fake_tridentorchestrator.go | 4 +- .../typed/netapp/v1/generated_expansion.go | 4 +- .../typed/netapp/v1/netapp_client.go | 11 +- .../typed/netapp/v1/tridentconfigurator.go | 170 ++ .../typed/netapp/v1/tridentorchestrator.go | 6 +- .../informers/externalversions/factory.go | 8 +- .../informers/externalversions/generic.go | 6 +- .../internalinterfaces/factory_interfaces.go | 4 +- .../externalversions/netapp/interface.go | 6 +- .../externalversions/netapp/v1/interface.go | 11 +- .../netapp/v1/tridentconfigurator.go | 75 + .../netapp/v1/tridentorchestrator.go | 10 +- .../listers/netapp/v1/expansion_generated.go | 6 +- .../listers/netapp/v1/tridentconfigurator.go | 51 + .../listers/netapp/v1/tridentorchestrator.go | 4 +- operator/frontend/frontend.go | 10 + operator/frontend/rest/apiserver_http.go | 69 + operator/frontend/rest/handler.go | 113 + operator/frontend/rest/handler_test.go | 146 ++ operator/frontend/rest/routes.go | 52 + operator/main.go | 34 +- storage_drivers/azure/api/azure_discovery.go | 106 + .../azure/api/azure_discovery_test.go | 128 +- storage_drivers/azure/api/types.go | 2 + 85 files changed, 6492 insertions(+), 109 deletions(-) create mode 100644 cli/cmd/check.go create mode 100644 cli/cmd/check_operator.go create mode 100644 helm/trident-operator/crds/tridentconfigurators.yaml create mode 100644 helm/trident-operator/templates/postinstallupgradehook.yaml create mode 100644 helm/trident-operator/templates/tridentconfigurator.yaml create mode 100644 mocks/mock_operator/mock_clients/mock_api.go create mode 100644 mocks/mock_operator/mock_controllers/mock_configurator/mock_clients/mock_api.go create mode 100644 operator/clients/operator_crd.go create mode 100644 operator/clients/snapshot_crd.go create mode 100644 operator/clients/trident_crd.go create mode 100644 operator/clients/types.go create mode 100644 operator/controllers/configurator/clients/configurator.go create mode 100644 operator/controllers/configurator/clients/extended_k8s.go create mode 100644 operator/controllers/configurator/clients/types.go create mode 100644 operator/controllers/configurator/controller.go create mode 100644 operator/controllers/configurator/controller_test.go create mode 100644 operator/controllers/configurator/storage_drivers/anf.go create mode 100644 operator/controllers/configurator/storage_drivers/anf_test.go create mode 100644 operator/controllers/configurator/storage_drivers/config.go create mode 100644 operator/controllers/configurator/storage_drivers/types.go create mode 100644 operator/controllers/configurator/storage_drivers/yaml_factory.go rename operator/{controllers/orchestrator => crd}/apis/netapp/v1/doc.go (100%) rename operator/{controllers/orchestrator => crd}/apis/netapp/v1/register.go (95%) create mode 100644 operator/crd/apis/netapp/v1/tridentconfigurator.go create mode 100644 operator/crd/apis/netapp/v1/tridentorchestrator.go create mode 100644 operator/crd/apis/netapp/v1/tridentorchestrator_test.go rename operator/{controllers/orchestrator => crd}/apis/netapp/v1/types.go (81%) rename operator/{controllers/orchestrator => crd}/apis/netapp/v1/zz_generated.deepcopy.go (64%) rename operator/{controllers/orchestrator => crd}/client/clientset/versioned/clientset.go (93%) rename operator/{controllers/orchestrator => crd}/client/clientset/versioned/doc.go (70%) rename operator/{controllers/orchestrator => crd}/client/clientset/versioned/fake/clientset_generated.go (82%) rename operator/{controllers/orchestrator => crd}/client/clientset/versioned/fake/doc.go (70%) rename operator/{controllers/orchestrator => crd}/client/clientset/versioned/fake/register.go (90%) rename operator/{controllers/orchestrator => crd}/client/clientset/versioned/scheme/doc.go (73%) rename operator/{controllers/orchestrator => crd}/client/clientset/versioned/scheme/register.go (90%) rename operator/{controllers/orchestrator => crd}/client/clientset/versioned/typed/netapp/v1/doc.go (70%) rename operator/{controllers/orchestrator => crd}/client/clientset/versioned/typed/netapp/v1/fake/doc.go (69%) rename operator/{controllers/orchestrator => crd}/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go (66%) create mode 100644 operator/crd/client/clientset/versioned/typed/netapp/v1/fake/fake_tridentconfigurator.go rename operator/{controllers/orchestrator => crd}/client/clientset/versioned/typed/netapp/v1/fake/fake_tridentorchestrator.go (97%) rename operator/{controllers/orchestrator => crd}/client/clientset/versioned/typed/netapp/v1/generated_expansion.go (51%) rename operator/{controllers/orchestrator => crd}/client/clientset/versioned/typed/netapp/v1/netapp_client.go (83%) create mode 100644 operator/crd/client/clientset/versioned/typed/netapp/v1/tridentconfigurator.go rename operator/{controllers/orchestrator => crd}/client/clientset/versioned/typed/netapp/v1/tridentorchestrator.go (96%) rename operator/{controllers/orchestrator => crd}/client/informers/externalversions/factory.go (93%) rename operator/{controllers/orchestrator => crd}/client/informers/externalversions/generic.go (81%) rename operator/{controllers/orchestrator => crd}/client/informers/externalversions/internalinterfaces/factory_interfaces.go (83%) rename operator/{controllers/orchestrator => crd}/client/informers/externalversions/netapp/interface.go (73%) rename operator/{controllers/orchestrator => crd}/client/informers/externalversions/netapp/v1/interface.go (64%) create mode 100644 operator/crd/client/informers/externalversions/netapp/v1/tridentconfigurator.go rename operator/{controllers/orchestrator => crd}/client/informers/externalversions/netapp/v1/tridentorchestrator.go (86%) rename operator/{controllers/orchestrator => crd}/client/listers/netapp/v1/expansion_generated.go (50%) create mode 100644 operator/crd/client/listers/netapp/v1/tridentconfigurator.go rename operator/{controllers/orchestrator => crd}/client/listers/netapp/v1/tridentorchestrator.go (92%) create mode 100644 operator/frontend/frontend.go create mode 100644 operator/frontend/rest/apiserver_http.go create mode 100644 operator/frontend/rest/handler.go create mode 100644 operator/frontend/rest/handler_test.go create mode 100644 operator/frontend/rest/routes.go diff --git a/Makefile b/Makefile index 10346098d..9d2942dbd 100644 --- a/Makefile +++ b/Makefile @@ -96,7 +96,7 @@ OPERATOR_CONFIG_PKG = github.com/netapp/trident/operator/config TRIDENT_KUBERNETES_PKG = github.com/netapp/trident/persistent_store/crd OPERATOR_CONFIG_PKG = github.com/netapp/trident/operator/config OPERATOR_INSTALLER_CONFIG_PKG = github.com/netapp/trident/operator/controllers/orchestrator/installer -OPERATOR_KUBERNETES_PKG = github.com/netapp/trident/operator/controllers/orchestrator +OPERATOR_KUBERNETES_PKG = github.com/netapp/trident/operator/crd VERSION_FILE = github.com/netapp/trident/hack/VERSION BUILD_ROOT = /go/src/github.com/netapp/trident TRIDENT_VOLUME = trident-build @@ -429,10 +429,10 @@ k8s_codegen_operator: @$(K8S_CODE_GENERATOR)/generate-groups.sh all $(OPERATOR_KUBERNETES_PKG)/client \ $(OPERATOR_KUBERNETES_PKG)/apis "netapp:v1" -h ./hack/boilerplate.go.txt @rm -rf $(K8S_CODE_GENERATOR) - @rm -rf ./operator/controllers/orchestrator/client/* - @mv $(OPERATOR_KUBERNETES_PKG)/client/* ./operator/controllers/orchestrator/client/ - @rm -rf ./operator/controllers/orchestrator/apis/netapp/v1/zz_generated.deepcopy.go - @mv $(OPERATOR_KUBERNETES_PKG)/apis/netapp/v1/zz_generated.deepcopy.go ./operator/controllers/orchestrator/apis/netapp/v1/ + @rm -rf ./operator/crd/client/* + @mv $(OPERATOR_KUBERNETES_PKG)/client/* ./operator/crd/client/ + @rm -rf ./operator/crd/apis/netapp/v1/zz_generated.deepcopy.go + @mv $(OPERATOR_KUBERNETES_PKG)/apis/netapp/v1/zz_generated.deepcopy.go ./operator/crd/apis/netapp/v1/ mocks: @go install github.com/golang/mock/mockgen@v1.6.0 diff --git a/cli/api/types.go b/cli/api/types.go index fff37ab49..17b4113ae 100644 --- a/cli/api/types.go +++ b/cli/api/types.go @@ -86,3 +86,25 @@ type KubernetesNamespace struct { Kind string `json:"kind"` Metadata Metadata `json:"metadata"` } + +type CRStatus struct { + Status string `json:"status"` + Message string `json:"message"` +} + +type OperatorPhaseStatus string + +const ( + OperatorPhaseDone OperatorPhaseStatus = "Done" + OperatorPhaseProcessing OperatorPhaseStatus = "Processing" + OperatorPhaseUnknown OperatorPhaseStatus = "Unknown" + OperatorPhaseFailed OperatorPhaseStatus = "Failed" + OperatorPhaseError OperatorPhaseStatus = "Error" +) + +type OperatorStatus struct { + ErrorMessage string `json:"errorMessage"` + Status string `json:"operatorStatus"` + TorcStatus map[string]CRStatus `json:"torcStatus"` + TconfStatus map[string]CRStatus `json:"tconfStatus"` +} diff --git a/cli/cmd/check.go b/cli/cmd/check.go new file mode 100644 index 000000000..613221061 --- /dev/null +++ b/cli/cmd/check.go @@ -0,0 +1,20 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package cmd + +import "github.com/spf13/cobra" + +func init() { + RootCmd.AddCommand(checkCmd) +} + +var checkCmd = &cobra.Command{ + Use: "check", + Short: "check status of a Trident pod", + Hidden: true, + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { + initCmdLogging() + err := discoverOperatingMode(cmd) + return err + }, +} diff --git a/cli/cmd/check_operator.go b/cli/cmd/check_operator.go new file mode 100644 index 000000000..b224c40fb --- /dev/null +++ b/cli/cmd/check_operator.go @@ -0,0 +1,158 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package cmd + +import ( + "encoding/json" + "fmt" + "net/http" + "os" + "time" + + "github.com/cenkalti/backoff/v4" + "github.com/olekukonko/tablewriter" + "github.com/spf13/cobra" + + cliapi "github.com/netapp/trident/cli/api" + "github.com/netapp/trident/utils/errors" +) + +var checkTimeout int32 + +const ( + RequestTimeout = 5 * time.Second + backoffMaxInterval = 5 * time.Second + operatorService = "trident-operator" + operatorServicePort = "8000" + operatorServicePath = "/operator/status" +) + +func init() { + checkCmd.AddCommand(checkOperatorCmd) + checkOperatorCmd.Flags().Int32VarP(&checkTimeout, "timeout", "t", 1, "timeout in seconds for the operator check") + if err := checkOperatorCmd.Flags().MarkHidden("timeout"); err != nil { + fmt.Fprintln(os.Stderr, err) + } +} + +var checkOperatorCmd = &cobra.Command{ + Use: "operator", + Short: "check operator pod status", + Aliases: []string{"o"}, + Hidden: true, + RunE: func(cmd *cobra.Command, args []string) error { + if OperatingMode == ModeTunnel { + command := []string{ + "check", + "operator", + "--timeout", + fmt.Sprintf("%d", checkTimeout), + } + out, err := TunnelCommand(append(command, args...)) + printOutput(cmd, out, err) + return err + } else { + return checkOperatorStatus(checkTimeout) + } + }, +} + +func checkOperatorStatus(checkTimeout int32) error { + var err error + status := cliapi.OperatorStatus{} + var response *http.Response + var url string + + getOperatorStatus := func() error { + if namespace := os.Getenv("POD_NAMESPACE"); namespace == "" { + return errors.New("error in getting trident operator pod") + } else { + url = "http://" + operatorService + "." + namespace + "." + "svc.cluster.local" + ":" + operatorServicePort + operatorServicePath + } + request, err := http.NewRequest("GET", url, nil) + request.Header.Set("Content-Type", "application/json") + + client := &http.Client{Timeout: RequestTimeout} + if response, err = client.Do(request); err != nil { + return err + } + + defer response.Body.Close() + + err = json.NewDecoder(response.Body).Decode(&status) + if status.Status != string(cliapi.OperatorPhaseDone) { + return errors.New("operator pod status is not set to done") + } + + return nil + } + + checkOperatorNotify := func(err error, duration time.Duration) {} + + checkOperatorBackoff := backoff.NewExponentialBackOff() + checkOperatorBackoff.MaxInterval = backoffMaxInterval + checkOperatorBackoff.MaxElapsedTime = time.Duration(checkTimeout) * time.Second + + if err = backoff.RetryNotify(getOperatorStatus, checkOperatorBackoff, checkOperatorNotify); err != nil { + if status.Status != "" { + writeStatus(status) + } + return err + } + + writeStatus(status) + return nil +} + +func writeStatus(status cliapi.OperatorStatus) { + switch OutputFormat { + case FormatJSON: + WriteJSON(status) + case FormatYAML: + WriteYAML(status) + case FormatWide: + writeStatusTableWide(status) + default: + writeStatusTable(status) + } +} + +func writeStatusTable(status cliapi.OperatorStatus) { + table := tablewriter.NewWriter(os.Stdout) + table.SetHeader([]string{"Name", "Type", "Status"}) + if status.ErrorMessage != "" { + table.SetFooter([]string{"Overall Status", status.Status, status.ErrorMessage}) + } else { + table.SetFooter([]string{"Overall Status", status.Status, ""}) + } + + for torcName, torcStatus := range status.TorcStatus { + table.Append([]string{torcName, "TridentOrchestratorCR", torcStatus.Status}) + } + + for tconfName, tconfStatus := range status.TconfStatus { + table.Append([]string{tconfName, "TridentConfiguratorCR", tconfStatus.Status}) + } + + table.Render() +} + +func writeStatusTableWide(status cliapi.OperatorStatus) { + table := tablewriter.NewWriter(os.Stdout) + table.SetHeader([]string{"Name", "Type", "Status", "Message"}) + if status.ErrorMessage != "" { + table.SetFooter([]string{"Overall Status", status.Status, status.ErrorMessage, ""}) + } else { + table.SetFooter([]string{"Overall Status", status.Status, "", ""}) + } + + for torcName, torcStatus := range status.TorcStatus { + table.Append([]string{torcName, "TridentOrchestratorCR", torcStatus.Status, torcStatus.Message}) + } + + for tconfName, tconfStatus := range status.TconfStatus { + table.Append([]string{tconfName, "TridentConfiguratorCR", tconfStatus.Status, tconfStatus.Message}) + } + + table.Render() +} diff --git a/cli/cmd/install.go b/cli/cmd/install.go index 2c4b74f18..5e7efa3ec 100644 --- a/cli/cmd/install.go +++ b/cli/cmd/install.go @@ -49,6 +49,7 @@ const ( VolumeCRDName = "tridentvolumes.trident.netapp.io" VolumePublicationCRDName = "tridentvolumepublications.trident.netapp.io" VolumeReferenceCRDName = "tridentvolumereferences.trident.netapp.io" + ConfiguratorCRDName = "tridentconfigurators.trident.netapp.io" ControllerRoleFilename = "trident-controller-role.yaml" ControllerClusterRoleFilename = "trident-controller-clusterrole.yaml" @@ -181,6 +182,7 @@ var ( VolumeCRDName, VolumePublicationCRDName, ActionSnapshotRestoreCRDName, + ConfiguratorCRDName, } ) diff --git a/cli/k8s_client/client_factory.go b/cli/k8s_client/client_factory.go index 03cb8649b..b72ad9fee 100644 --- a/cli/k8s_client/client_factory.go +++ b/cli/k8s_client/client_factory.go @@ -19,7 +19,7 @@ import ( "github.com/netapp/trident/config" . "github.com/netapp/trident/logging" - torc "github.com/netapp/trident/operator/controllers/orchestrator/client/clientset/versioned" + torc "github.com/netapp/trident/operator/crd/client/clientset/versioned" tridentv1clientset "github.com/netapp/trident/persistent_store/crd/client/clientset/versioned" "github.com/netapp/trident/utils/errors" ) diff --git a/cli/k8s_client/yaml_factory.go b/cli/k8s_client/yaml_factory.go index 98271adfd..111e5e305 100644 --- a/cli/k8s_client/yaml_factory.go +++ b/cli/k8s_client/yaml_factory.go @@ -602,6 +602,10 @@ spec: fieldRef: apiVersion: v1 fieldPath: spec.nodeName + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace - name: CSI_ENDPOINT value: unix://plugin/csi.sock - name: TRIDENT_SERVER @@ -1597,6 +1601,12 @@ func GetBackendConfigCRDYAML() string { return tridentBackendConfigCRDYAMLv1 } +func GetConfiguratorCRDYAML() string { + Log().Trace(">>>> GetConfiguratorCRDYAML") + defer func() { Log().Trace("<<<< GetConfiguratorCRDYAML") }() + return tridentConfiguratorCRDYAMLv1 +} + func GetMirrorRelationshipCRDYAML() string { Log().Trace(">>>> GetMirrorRelationshipCRDYAML") defer func() { Log().Trace("<<<< GetMirrorRelationshipCRDYAML") }() @@ -2066,6 +2076,62 @@ spec: - trident-internal - trident-external` +const tridentConfiguratorCRDYAMLv1 = ` +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: tridentconfigurators.trident.netapp.io +spec: + group: trident.netapp.io + versions: + - name: v1 + served: true + storage: true + schema: + openAPIV3Schema: + type: object + x-kubernetes-preserve-unknown-fields: true + subresources: + status: {} + additionalPrinterColumns: + - name: Phase + type: string + description: The backend config phase + priority: 0 + jsonPath: .status.phase + - name: Status + type: string + description: The result of the last operation + priority: 0 + jsonPath: .status.lastOperationStatus + - name: Cloud Provider + type: string + description: The name of cloud provider + priority: 0 + jsonPath: .status.cloudProvider + - name: Storage Driver + type: string + description: The storage driver type + priority: 1 + jsonPath: .spec.storageDriverName + - name: Deletion Policy + type: string + description: The deletion policy + priority: 1 + jsonPath: .status.deletionPolicy + scope: Cluster + names: + plural: tridentconfigurators + singular: tridentconfigurator + kind: TridentConfigurator + shortNames: + - tconf + - tconfigurator + categories: + - trident + - trident-internal + - trident-external` + const tridentStorageClassCRDYAMLv1 = ` apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition @@ -2433,7 +2499,8 @@ const customResourceDefinitionYAMLv1 = tridentVersionCRDYAMLv1 + "\n---" + tridentTransactionCRDYAMLv1 + "\n---" + tridentSnapshotCRDYAMLv1 + "\n---" + tridentVolumeReferenceCRDYAMLv1 + - "\n---" + tridentActionSnapshotRestoreCRDYAMLv1 + "\n" + "\n---" + tridentActionSnapshotRestoreCRDYAMLv1 + + "\n---" + tridentConfiguratorCRDYAMLv1 + "\n" func GetCSIDriverYAML(name string, labels, controllingCRDetails map[string]string) string { Log().WithFields(LogFields{ diff --git a/cli/k8s_client/yaml_factory_test.go b/cli/k8s_client/yaml_factory_test.go index a0d0ee55d..3e794cace 100644 --- a/cli/k8s_client/yaml_factory_test.go +++ b/cli/k8s_client/yaml_factory_test.go @@ -2134,6 +2134,75 @@ func TestGetCRDsYAML(t *testing.T) { }, }, } + expected15 := apiextensionsv1.CustomResourceDefinition{ + TypeMeta: metav1.TypeMeta{ + Kind: "CustomResourceDefinition", + APIVersion: "apiextensions.k8s.io/v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "tridentconfigurators.trident.netapp.io", + }, + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "trident.netapp.io", + Names: apiextensionsv1.CustomResourceDefinitionNames{ + Plural: "tridentconfigurators", + Singular: "tridentconfigurator", + Kind: "TridentConfigurator", + ShortNames: []string{"tconf", "tconfigurator"}, + Categories: []string{"trident", "trident-internal", "trident-external"}, + }, + Scope: "Cluster", + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ + { + Name: "v1", + Served: true, + Storage: true, + Schema: &schema1, + Subresources: &apiextensionsv1.CustomResourceSubresources{ + Status: &apiextensionsv1.CustomResourceSubresourceStatus{}, + Scale: nil, + }, + AdditionalPrinterColumns: []apiextensionsv1.CustomResourceColumnDefinition{ + { + Name: "Phase", + Type: "string", + Description: "The backend config phase", + Priority: int32(0), + JSONPath: ".status.phase", + }, + { + Name: "Status", + Type: "string", + Description: "The result of the last operation", + Priority: int32(0), + JSONPath: ".status.lastOperationStatus", + }, + { + Name: "Cloud Provider", + Type: "string", + Description: "The name of cloud provider", + Priority: int32(0), + JSONPath: ".status.cloudProvider", + }, + { + Name: "Storage Driver", + Type: "string", + Description: "The storage driver type", + Priority: int32(1), + JSONPath: ".spec.storageDriverName", + }, + { + Name: "Deletion Policy", + Type: "string", + Description: "The deletion policy", + Priority: int32(1), + JSONPath: ".status.deletionPolicy", + }, + }, + }, + }, + }, + } // trident version var actual1 apiextensionsv1.CustomResourceDefinition @@ -2232,6 +2301,13 @@ func TestGetCRDsYAML(t *testing.T) { assert.True(t, reflect.DeepEqual(expected14.TypeMeta, actual14.TypeMeta)) assert.True(t, reflect.DeepEqual(expected14.ObjectMeta, actual14.ObjectMeta)) assert.True(t, reflect.DeepEqual(expected14.Spec, actual14.Spec)) + + // trident configurator + var actual15 apiextensionsv1.CustomResourceDefinition + assert.Nil(t, yaml.Unmarshal([]byte(result[14]), &actual15), "invalid YAML") + assert.True(t, reflect.DeepEqual(expected15.TypeMeta, actual15.TypeMeta)) + assert.True(t, reflect.DeepEqual(expected15.ObjectMeta, actual15.ObjectMeta)) + assert.True(t, reflect.DeepEqual(expected15.Spec, actual15.Spec)) } func TestGetVersionCRDYAML(t *testing.T) { @@ -2502,6 +2578,93 @@ func TestGetBackendConfigCRDYAML(t *testing.T) { assert.True(t, reflect.DeepEqual(expected.Spec, actual.Spec)) } +func TestGetConfiguratorCRDYAML(t *testing.T) { + preserveValue := true + schema := apiextensionsv1.CustomResourceValidation{ + OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{ + Type: "object", + XPreserveUnknownFields: &preserveValue, + }, + } + expected := apiextensionsv1.CustomResourceDefinition{ + TypeMeta: metav1.TypeMeta{ + Kind: "CustomResourceDefinition", + APIVersion: "apiextensions.k8s.io/v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "tridentconfigurators.trident.netapp.io", + }, + Spec: apiextensionsv1.CustomResourceDefinitionSpec{ + Group: "trident.netapp.io", + Names: apiextensionsv1.CustomResourceDefinitionNames{ + Plural: "tridentconfigurators", + Singular: "tridentconfigurator", + Kind: "TridentConfigurator", + ShortNames: []string{"tconf", "tconfigurator"}, + Categories: []string{"trident", "trident-internal", "trident-external"}, + }, + Scope: "Cluster", + Versions: []apiextensionsv1.CustomResourceDefinitionVersion{ + { + Name: "v1", + Served: true, + Storage: true, + Schema: &schema, + Subresources: &apiextensionsv1.CustomResourceSubresources{ + Status: &apiextensionsv1.CustomResourceSubresourceStatus{}, + Scale: nil, + }, + AdditionalPrinterColumns: []apiextensionsv1.CustomResourceColumnDefinition{ + { + Name: "Phase", + Type: "string", + Description: "The backend config phase", + Priority: int32(0), + JSONPath: ".status.phase", + }, + { + Name: "Status", + Type: "string", + Description: "The result of the last operation", + Priority: int32(0), + JSONPath: ".status.lastOperationStatus", + }, + { + Name: "Cloud Provider", + Type: "string", + Description: "The name of cloud provider", + Priority: int32(0), + JSONPath: ".status.cloudProvider", + }, + { + Name: "Storage Driver", + Type: "string", + Description: "The storage driver type", + Priority: int32(1), + JSONPath: ".spec.storageDriverName", + }, + { + Name: "Deletion Policy", + Type: "string", + Description: "The deletion policy", + Priority: int32(1), + JSONPath: ".status.deletionPolicy", + }, + }, + }, + }, + }, + } + + actualYAML := GetConfiguratorCRDYAML() + + var actual apiextensionsv1.CustomResourceDefinition + assert.Nil(t, yaml.Unmarshal([]byte(actualYAML), &actual), "invalid YAML") + assert.True(t, reflect.DeepEqual(expected.TypeMeta, actual.TypeMeta)) + assert.True(t, reflect.DeepEqual(expected.ObjectMeta, actual.ObjectMeta)) + assert.True(t, reflect.DeepEqual(expected.Spec, actual.Spec)) +} + func TestGetMirrorRelationshipCRDYAML(t *testing.T) { minItems := int64(1) maxItems := int64(1) diff --git a/deploy/bundle_post_1_25.yaml b/deploy/bundle_post_1_25.yaml index 5b08fbcca..8d2677b5e 100644 --- a/deploy/bundle_post_1_25.yaml +++ b/deploy/bundle_post_1_25.yaml @@ -457,6 +457,13 @@ spec: image: docker.io/netapp/trident-operator:24.05.0 imagePullPolicy: IfNotPresent name: trident-operator + resources: + requests: + cpu: "10m" + memory: "40Mi" + limits: + cpu: "20m" + memory: "80Mi" securityContext: capabilities: drop: diff --git a/deploy/bundle_pre_1_25.yaml b/deploy/bundle_pre_1_25.yaml index 2e0938c16..e11812a5a 100644 --- a/deploy/bundle_pre_1_25.yaml +++ b/deploy/bundle_pre_1_25.yaml @@ -460,6 +460,13 @@ spec: image: docker.io/netapp/trident-operator:24.05.0 imagePullPolicy: IfNotPresent name: trident-operator + resources: + requests: + cpu: "10m" + memory: "40Mi" + limits: + cpu: "20m" + memory: "80Mi" securityContext: capabilities: drop: diff --git a/deploy/operator.yaml b/deploy/operator.yaml index 3575ccd28..0980fc6c8 100644 --- a/deploy/operator.yaml +++ b/deploy/operator.yaml @@ -34,6 +34,13 @@ spec: fieldPath: metadata.name - name: OPERATOR_NAME value: "trident-operator" + resources: + requests: + cpu: "10m" + memory: "40Mi" + limits: + cpu: "20m" + memory: "80Mi" affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: diff --git a/hack/boilerplate.go.txt b/hack/boilerplate.go.txt index 36d510c76..b22e3fd33 100644 --- a/hack/boilerplate.go.txt +++ b/hack/boilerplate.go.txt @@ -1 +1 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. diff --git a/helm/trident-operator/crds/tridentconfigurators.yaml b/helm/trident-operator/crds/tridentconfigurators.yaml new file mode 100644 index 000000000..f3aa8971f --- /dev/null +++ b/helm/trident-operator/crds/tridentconfigurators.yaml @@ -0,0 +1,54 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: tridentconfigurators.trident.netapp.io +spec: + group: trident.netapp.io + versions: + - name: v1 + served: true + storage: true + schema: + openAPIV3Schema: + type: object + x-kubernetes-preserve-unknown-fields: true + subresources: + status: {} + additionalPrinterColumns: + - name: Phase + type: string + description: The backend config phase + priority: 0 + jsonPath: .status.phase + - name: Status + type: string + description: The result of the last operation + priority: 0 + jsonPath: .status.lastOperationStatus + - name: Cloud Provider + type: string + description: The name of cloud provider + priority: 0 + jsonPath: .status.cloudProvider + - name: Storage Driver + type: string + description: The storage driver type + priority: 1 + jsonPath: .spec.storageDriverName + - name: Deletion Policy + type: string + description: The deletion policy + priority: 1 + jsonPath: .status.deletionPolicy + scope: Cluster + names: + plural: tridentconfigurators + singular: tridentconfigurator + kind: TridentConfigurator + shortNames: + - tconf + - tconfigurator + categories: + - trident + - trident-internal + - trident-external \ No newline at end of file diff --git a/helm/trident-operator/templates/clusterrole.yaml b/helm/trident-operator/templates/clusterrole.yaml index e6c8a91aa..6d8bbaea8 100644 --- a/helm/trident-operator/templates/clusterrole.yaml +++ b/helm/trident-operator/templates/clusterrole.yaml @@ -138,6 +138,12 @@ rules: - watch - update - patch + - apiGroups: + - snapshot.storage.k8s.io + resources: + - volumesnapshotclasses + verbs: + - create - apiGroups: - snapshot.storage.k8s.io resources: @@ -222,6 +228,8 @@ rules: - tridentprovisioners/status # Required to update Tprov's status section - tridentorchestrators # Required for torc - tridentorchestrators/status # Required to update torc's status section + - tridentconfigurators # Required for tconf + - tridentconfigurators/status # Required to update tconf's status section verbs: - get - list diff --git a/helm/trident-operator/templates/deployment.yaml b/helm/trident-operator/templates/deployment.yaml index ae7bea634..1fca4a8b1 100644 --- a/helm/trident-operator/templates/deployment.yaml +++ b/helm/trident-operator/templates/deployment.yaml @@ -26,6 +26,9 @@ spec: labels: app: operator.trident.netapp.io name: trident-operator + {{- if and (eq .Values.cloudProvider "Azure") (ne .Values.cloudIdentity "") }} + azure.workload.identity/use: 'true' + {{- end }} spec: affinity: nodeAffinity: @@ -61,6 +64,7 @@ spec: containers: - command: - /trident-operator + - -configurator-reconcile-interval={{ .Values.configuratorReconcileInterval }} {{- if .Values.operatorDebug }} - -debug {{- end }} @@ -71,6 +75,27 @@ spec: fieldPath: metadata.name - name: OPERATOR_NAME value: trident-operator + {{- if and (eq .Values.cloudProvider "Azure") (eq .Values.cloudIdentity "") }} + - name: AZURE_CREDENTIAL_FILE + value: /etc/kubernetes/azure.json + volumeMounts: + - name: azure-cred + mountPath: /etc/kubernetes + {{- end }} image: {{ include "trident-operator.image" $ }} imagePullPolicy: {{ .Values.imagePullPolicy }} name: trident-operator + resources: + requests: + cpu: "10m" + memory: "40Mi" + limits: + cpu: "20m" + memory: "80Mi" + {{- if and (eq .Values.cloudProvider "Azure") (eq .Values.cloudIdentity "") }} + volumes: + - name: azure-cred + hostPath: + path: /etc/kubernetes + type: DirectoryOrCreate + {{- end }} diff --git a/helm/trident-operator/templates/postinstallupgradehook.yaml b/helm/trident-operator/templates/postinstallupgradehook.yaml new file mode 100644 index 000000000..6eb617fdf --- /dev/null +++ b/helm/trident-operator/templates/postinstallupgradehook.yaml @@ -0,0 +1,58 @@ +{{- if .Values.anfConfigurator.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: trident-operator + namespace: {{ .Release.Namespace }} +spec: + selector: + app: operator.trident.netapp.io + ports: + - name: http + protocol: TCP + port: 8000 + targetPort: 8002 +--- +apiVersion: v1 +kind: Pod +metadata: + name: trident-post-install-upgrade-hook + namespace: {{ .Release.Namespace }} + annotations: + "helm.sh/hook": post-install, post-upgrade + "helm.sh/hook-delete-policy": hook-succeeded, hook-failed +spec: + restartPolicy: Never + initContainers: + - name: init-container-1 + image: {{ include "trident.image" $ }} + command: + - tridentctl + - --debug + - -s + - 127.0.0.1:8000 + - check + - operator + - --timeout + - "7200" # Keeping it 12mins as AKS extension script has an upper limit of 15mins. + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + containers: + - name: trident-post-hook + image: {{ include "trident.image" $ }} + command: + - tridentctl + - --debug + - -s + - 127.0.0.1:8000 + - check + - operator + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace +{{- end }} diff --git a/helm/trident-operator/templates/serviceaccount.yaml b/helm/trident-operator/templates/serviceaccount.yaml index e2e5bdf33..7a73016df 100644 --- a/helm/trident-operator/templates/serviceaccount.yaml +++ b/helm/trident-operator/templates/serviceaccount.yaml @@ -3,6 +3,13 @@ kind: ServiceAccount metadata: name: trident-operator namespace: {{ .Release.Namespace }} + {{- if and (ne .Values.cloudIdentity "") (ne .Values.cloudProvider "") }} + {{- $cloudIdentity := trimPrefix "'" .Values.cloudIdentity }} + {{- $cloudIdentity = trimSuffix "'" $cloudIdentity }} + {{- $cloudIdentityPair := regexSplit ": " $cloudIdentity 2 }} + annotations: + {{ first $cloudIdentityPair }}: {{ last $cloudIdentityPair }} + {{- end }} labels: app: operator.trident.netapp.io {{- if .Values.imagePullSecrets }} diff --git a/helm/trident-operator/templates/tridentconfigurator.yaml b/helm/trident-operator/templates/tridentconfigurator.yaml new file mode 100644 index 000000000..b8805cf5e --- /dev/null +++ b/helm/trident-operator/templates/tridentconfigurator.yaml @@ -0,0 +1,31 @@ +{{- if .Values.anfConfigurator.enabled }} +apiVersion: trident.netapp.io/v1 +kind: TridentConfigurator +metadata: + name: netapp-anf-backend-configurator +spec: + storageDriverName: azure-netapp-files + {{- if eq .Values.cloudProvider "" }} + tenantID: {{ .Values.anfConfigurator.tenantID }} + clientCredentials: {{ .Values.anfConfigurator.clientCredentials }} + {{- end }} + {{- if or (eq .Values.cloudProvider "") (and (eq .Values.cloudProvider "Azure") (ne .Values.cloudIdentity "")) }} + subscriptionID: {{ .Values.anfConfigurator.subscriptionID }} + location: {{ .Values.anfConfigurator.location }} + {{- end }} + virtualNetwork: {{ .Values.anfConfigurator.virtualNetwork }} + subnet: {{ .Values.anfConfigurator.subnet }} + capacityPools: + {{- range .Values.anfConfigurator.capacityPools }} + - {{ . }} + {{- end }} + netappAccounts: + {{- range .Values.anfConfigurator.netappAccounts }} + - {{ . }} + {{- end }} + resourceGroups: + {{- range .Values.anfConfigurator.resourceGroups }} + - {{ . }} + {{- end }} +{{- end }} + diff --git a/helm/trident-operator/values.yaml b/helm/trident-operator/values.yaml index 1c938c7e3..23376c83c 100644 --- a/helm/trident-operator/values.yaml +++ b/helm/trident-operator/values.yaml @@ -144,3 +144,19 @@ iscsiSelfHealingInterval: "5m0s" # iscsiSelfHealingWaitTime is the wait time after which iSCSI self-healing attempts to fix stale sessions iscsiSelfHealingWaitTime: "7m0s" + +# configuratorReconcileInterval is the resource refresh rate for the auto generated backends. +configuratorReconcileInterval: 30m0s + +# Auto generated ANF backend related fields consumed by the configurator controller. +anfConfigurator: + enabled: false + virtualNetwork: "" + subnet: "" + subscriptionID: "" + tenantID: "" + location: "" + clientCredentials: "" + capacityPools: [] + netappAccounts: [] + resourceGroups: [] diff --git a/mocks/mock_operator/mock_clients/mock_api.go b/mocks/mock_operator/mock_clients/mock_api.go new file mode 100644 index 000000000..9c55e7730 --- /dev/null +++ b/mocks/mock_operator/mock_clients/mock_api.go @@ -0,0 +1,276 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/netapp/trident/operator/clients (interfaces: OperatorCRDClientInterface,TridentCRDClientInterface,SnapshotCRDClientInterface) + +// Package mock_clients is a generated GoMock package. +package mock_clients + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" + v1 "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1" + v10 "github.com/netapp/trident/operator/crd/apis/netapp/v1" + v11 "github.com/netapp/trident/persistent_store/crd/apis/netapp/v1" + types "k8s.io/apimachinery/pkg/types" +) + +// MockOperatorCRDClientInterface is a mock of OperatorCRDClientInterface interface. +type MockOperatorCRDClientInterface struct { + ctrl *gomock.Controller + recorder *MockOperatorCRDClientInterfaceMockRecorder +} + +// MockOperatorCRDClientInterfaceMockRecorder is the mock recorder for MockOperatorCRDClientInterface. +type MockOperatorCRDClientInterfaceMockRecorder struct { + mock *MockOperatorCRDClientInterface +} + +// NewMockOperatorCRDClientInterface creates a new mock instance. +func NewMockOperatorCRDClientInterface(ctrl *gomock.Controller) *MockOperatorCRDClientInterface { + mock := &MockOperatorCRDClientInterface{ctrl: ctrl} + mock.recorder = &MockOperatorCRDClientInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockOperatorCRDClientInterface) EXPECT() *MockOperatorCRDClientInterfaceMockRecorder { + return m.recorder +} + +// GetControllingTorcCR mocks base method. +func (m *MockOperatorCRDClientInterface) GetControllingTorcCR() (*v10.TridentOrchestrator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetControllingTorcCR") + ret0, _ := ret[0].(*v10.TridentOrchestrator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetControllingTorcCR indicates an expected call of GetControllingTorcCR. +func (mr *MockOperatorCRDClientInterfaceMockRecorder) GetControllingTorcCR() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetControllingTorcCR", reflect.TypeOf((*MockOperatorCRDClientInterface)(nil).GetControllingTorcCR)) +} + +// GetTconfCR mocks base method. +func (m *MockOperatorCRDClientInterface) GetTconfCR(arg0 string) (*v10.TridentConfigurator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTconfCR", arg0) + ret0, _ := ret[0].(*v10.TridentConfigurator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetTconfCR indicates an expected call of GetTconfCR. +func (mr *MockOperatorCRDClientInterfaceMockRecorder) GetTconfCR(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTconfCR", reflect.TypeOf((*MockOperatorCRDClientInterface)(nil).GetTconfCR), arg0) +} + +// GetTconfCRList mocks base method. +func (m *MockOperatorCRDClientInterface) GetTconfCRList() (*v10.TridentConfiguratorList, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTconfCRList") + ret0, _ := ret[0].(*v10.TridentConfiguratorList) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetTconfCRList indicates an expected call of GetTconfCRList. +func (mr *MockOperatorCRDClientInterfaceMockRecorder) GetTconfCRList() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTconfCRList", reflect.TypeOf((*MockOperatorCRDClientInterface)(nil).GetTconfCRList)) +} + +// GetTorcCRList mocks base method. +func (m *MockOperatorCRDClientInterface) GetTorcCRList() (*v10.TridentOrchestratorList, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTorcCRList") + ret0, _ := ret[0].(*v10.TridentOrchestratorList) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetTorcCRList indicates an expected call of GetTorcCRList. +func (mr *MockOperatorCRDClientInterfaceMockRecorder) GetTorcCRList() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTorcCRList", reflect.TypeOf((*MockOperatorCRDClientInterface)(nil).GetTorcCRList)) +} + +// UpdateTridentConfiguratorStatus mocks base method. +func (m *MockOperatorCRDClientInterface) UpdateTridentConfiguratorStatus(arg0 *v10.TridentConfigurator, arg1 v10.TridentConfiguratorStatus) (*v10.TridentConfigurator, bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateTridentConfiguratorStatus", arg0, arg1) + ret0, _ := ret[0].(*v10.TridentConfigurator) + ret1, _ := ret[1].(bool) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// UpdateTridentConfiguratorStatus indicates an expected call of UpdateTridentConfiguratorStatus. +func (mr *MockOperatorCRDClientInterfaceMockRecorder) UpdateTridentConfiguratorStatus(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTridentConfiguratorStatus", reflect.TypeOf((*MockOperatorCRDClientInterface)(nil).UpdateTridentConfiguratorStatus), arg0, arg1) +} + +// MockTridentCRDClientInterface is a mock of TridentCRDClientInterface interface. +type MockTridentCRDClientInterface struct { + ctrl *gomock.Controller + recorder *MockTridentCRDClientInterfaceMockRecorder +} + +// MockTridentCRDClientInterfaceMockRecorder is the mock recorder for MockTridentCRDClientInterface. +type MockTridentCRDClientInterfaceMockRecorder struct { + mock *MockTridentCRDClientInterface +} + +// NewMockTridentCRDClientInterface creates a new mock instance. +func NewMockTridentCRDClientInterface(ctrl *gomock.Controller) *MockTridentCRDClientInterface { + mock := &MockTridentCRDClientInterface{ctrl: ctrl} + mock.recorder = &MockTridentCRDClientInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockTridentCRDClientInterface) EXPECT() *MockTridentCRDClientInterfaceMockRecorder { + return m.recorder +} + +// CheckTridentBackendConfigExists mocks base method. +func (m *MockTridentCRDClientInterface) CheckTridentBackendConfigExists(arg0, arg1 string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckTridentBackendConfigExists", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CheckTridentBackendConfigExists indicates an expected call of CheckTridentBackendConfigExists. +func (mr *MockTridentCRDClientInterfaceMockRecorder) CheckTridentBackendConfigExists(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckTridentBackendConfigExists", reflect.TypeOf((*MockTridentCRDClientInterface)(nil).CheckTridentBackendConfigExists), arg0, arg1) +} + +// DeleteTridentBackendConfig mocks base method. +func (m *MockTridentCRDClientInterface) DeleteTridentBackendConfig(arg0, arg1 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteTridentBackendConfig", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteTridentBackendConfig indicates an expected call of DeleteTridentBackendConfig. +func (mr *MockTridentCRDClientInterfaceMockRecorder) DeleteTridentBackendConfig(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteTridentBackendConfig", reflect.TypeOf((*MockTridentCRDClientInterface)(nil).DeleteTridentBackendConfig), arg0, arg1) +} + +// GetTridentBackendConfig mocks base method. +func (m *MockTridentCRDClientInterface) GetTridentBackendConfig(arg0, arg1 string) (*v11.TridentBackendConfig, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTridentBackendConfig", arg0, arg1) + ret0, _ := ret[0].(*v11.TridentBackendConfig) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetTridentBackendConfig indicates an expected call of GetTridentBackendConfig. +func (mr *MockTridentCRDClientInterfaceMockRecorder) GetTridentBackendConfig(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTridentBackendConfig", reflect.TypeOf((*MockTridentCRDClientInterface)(nil).GetTridentBackendConfig), arg0, arg1) +} + +// PatchTridentBackendConfig mocks base method. +func (m *MockTridentCRDClientInterface) PatchTridentBackendConfig(arg0, arg1 string, arg2 []byte, arg3 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchTridentBackendConfig", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchTridentBackendConfig indicates an expected call of PatchTridentBackendConfig. +func (mr *MockTridentCRDClientInterfaceMockRecorder) PatchTridentBackendConfig(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchTridentBackendConfig", reflect.TypeOf((*MockTridentCRDClientInterface)(nil).PatchTridentBackendConfig), arg0, arg1, arg2, arg3) +} + +// MockSnapshotCRDClientInterface is a mock of SnapshotCRDClientInterface interface. +type MockSnapshotCRDClientInterface struct { + ctrl *gomock.Controller + recorder *MockSnapshotCRDClientInterfaceMockRecorder +} + +// MockSnapshotCRDClientInterfaceMockRecorder is the mock recorder for MockSnapshotCRDClientInterface. +type MockSnapshotCRDClientInterfaceMockRecorder struct { + mock *MockSnapshotCRDClientInterface +} + +// NewMockSnapshotCRDClientInterface creates a new mock instance. +func NewMockSnapshotCRDClientInterface(ctrl *gomock.Controller) *MockSnapshotCRDClientInterface { + mock := &MockSnapshotCRDClientInterface{ctrl: ctrl} + mock.recorder = &MockSnapshotCRDClientInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockSnapshotCRDClientInterface) EXPECT() *MockSnapshotCRDClientInterfaceMockRecorder { + return m.recorder +} + +// CheckVolumeSnapshotClassExists mocks base method. +func (m *MockSnapshotCRDClientInterface) CheckVolumeSnapshotClassExists(arg0 string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckVolumeSnapshotClassExists", arg0) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CheckVolumeSnapshotClassExists indicates an expected call of CheckVolumeSnapshotClassExists. +func (mr *MockSnapshotCRDClientInterfaceMockRecorder) CheckVolumeSnapshotClassExists(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckVolumeSnapshotClassExists", reflect.TypeOf((*MockSnapshotCRDClientInterface)(nil).CheckVolumeSnapshotClassExists), arg0) +} + +// DeleteVolumeSnapshotClass mocks base method. +func (m *MockSnapshotCRDClientInterface) DeleteVolumeSnapshotClass(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteVolumeSnapshotClass", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteVolumeSnapshotClass indicates an expected call of DeleteVolumeSnapshotClass. +func (mr *MockSnapshotCRDClientInterfaceMockRecorder) DeleteVolumeSnapshotClass(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteVolumeSnapshotClass", reflect.TypeOf((*MockSnapshotCRDClientInterface)(nil).DeleteVolumeSnapshotClass), arg0) +} + +// GetVolumeSnapshotClass mocks base method. +func (m *MockSnapshotCRDClientInterface) GetVolumeSnapshotClass(arg0 string) (*v1.VolumeSnapshotClass, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetVolumeSnapshotClass", arg0) + ret0, _ := ret[0].(*v1.VolumeSnapshotClass) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetVolumeSnapshotClass indicates an expected call of GetVolumeSnapshotClass. +func (mr *MockSnapshotCRDClientInterfaceMockRecorder) GetVolumeSnapshotClass(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetVolumeSnapshotClass", reflect.TypeOf((*MockSnapshotCRDClientInterface)(nil).GetVolumeSnapshotClass), arg0) +} + +// PatchVolumeSnapshotClass mocks base method. +func (m *MockSnapshotCRDClientInterface) PatchVolumeSnapshotClass(arg0 string, arg1 []byte, arg2 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchVolumeSnapshotClass", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchVolumeSnapshotClass indicates an expected call of PatchVolumeSnapshotClass. +func (mr *MockSnapshotCRDClientInterfaceMockRecorder) PatchVolumeSnapshotClass(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchVolumeSnapshotClass", reflect.TypeOf((*MockSnapshotCRDClientInterface)(nil).PatchVolumeSnapshotClass), arg0, arg1, arg2) +} diff --git a/mocks/mock_operator/mock_controllers/mock_configurator/mock_clients/mock_api.go b/mocks/mock_operator/mock_controllers/mock_configurator/mock_clients/mock_api.go new file mode 100644 index 000000000..0aa89c493 --- /dev/null +++ b/mocks/mock_operator/mock_controllers/mock_configurator/mock_clients/mock_api.go @@ -0,0 +1,1873 @@ +// Code generated by MockGen. DO NOT EDIT. +// Source: github.com/netapp/trident/operator/controllers/configurator/clients (interfaces: ConfiguratorClientInterface,ExtendedK8sClientInterface) + +// Package mock_clients is a generated GoMock package. +package mock_clients + +import ( + reflect "reflect" + time "time" + + gomock "github.com/golang/mock/gomock" + k8sclient "github.com/netapp/trident/cli/k8s_client" + clients "github.com/netapp/trident/operator/controllers/configurator/clients" + v1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" + version "github.com/netapp/trident/utils/version" + v10 "k8s.io/api/apps/v1" + v11 "k8s.io/api/core/v1" + v1beta1 "k8s.io/api/policy/v1beta1" + v12 "k8s.io/api/rbac/v1" + v13 "k8s.io/api/storage/v1" + v14 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + types "k8s.io/apimachinery/pkg/types" + version0 "k8s.io/apimachinery/pkg/version" +) + +// MockConfiguratorClientInterface is a mock of ConfiguratorClientInterface interface. +type MockConfiguratorClientInterface struct { + ctrl *gomock.Controller + recorder *MockConfiguratorClientInterfaceMockRecorder +} + +// MockConfiguratorClientInterfaceMockRecorder is the mock recorder for MockConfiguratorClientInterface. +type MockConfiguratorClientInterfaceMockRecorder struct { + mock *MockConfiguratorClientInterface +} + +// NewMockConfiguratorClientInterface creates a new mock instance. +func NewMockConfiguratorClientInterface(ctrl *gomock.Controller) *MockConfiguratorClientInterface { + mock := &MockConfiguratorClientInterface{ctrl: ctrl} + mock.recorder = &MockConfiguratorClientInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockConfiguratorClientInterface) EXPECT() *MockConfiguratorClientInterfaceMockRecorder { + return m.recorder +} + +// CreateOrPatchObject mocks base method. +func (m *MockConfiguratorClientInterface) CreateOrPatchObject(arg0 clients.ObjectType, arg1, arg2, arg3 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateOrPatchObject", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateOrPatchObject indicates an expected call of CreateOrPatchObject. +func (mr *MockConfiguratorClientInterfaceMockRecorder) CreateOrPatchObject(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrPatchObject", reflect.TypeOf((*MockConfiguratorClientInterface)(nil).CreateOrPatchObject), arg0, arg1, arg2, arg3) +} + +// GetANFSecrets mocks base method. +func (m *MockConfiguratorClientInterface) GetANFSecrets(arg0 string) (string, string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetANFSecrets", arg0) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(string) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// GetANFSecrets indicates an expected call of GetANFSecrets. +func (mr *MockConfiguratorClientInterfaceMockRecorder) GetANFSecrets(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetANFSecrets", reflect.TypeOf((*MockConfiguratorClientInterface)(nil).GetANFSecrets), arg0) +} + +// GetControllingTorcCR mocks base method. +func (m *MockConfiguratorClientInterface) GetControllingTorcCR() (*v1.TridentOrchestrator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetControllingTorcCR") + ret0, _ := ret[0].(*v1.TridentOrchestrator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetControllingTorcCR indicates an expected call of GetControllingTorcCR. +func (mr *MockConfiguratorClientInterfaceMockRecorder) GetControllingTorcCR() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetControllingTorcCR", reflect.TypeOf((*MockConfiguratorClientInterface)(nil).GetControllingTorcCR)) +} + +// GetTconfCR mocks base method. +func (m *MockConfiguratorClientInterface) GetTconfCR(arg0 string) (*v1.TridentConfigurator, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetTconfCR", arg0) + ret0, _ := ret[0].(*v1.TridentConfigurator) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetTconfCR indicates an expected call of GetTconfCR. +func (mr *MockConfiguratorClientInterfaceMockRecorder) GetTconfCR(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetTconfCR", reflect.TypeOf((*MockConfiguratorClientInterface)(nil).GetTconfCR), arg0) +} + +// UpdateTridentConfiguratorStatus mocks base method. +func (m *MockConfiguratorClientInterface) UpdateTridentConfiguratorStatus(arg0 *v1.TridentConfigurator, arg1 v1.TridentConfiguratorStatus) (*v1.TridentConfigurator, bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateTridentConfiguratorStatus", arg0, arg1) + ret0, _ := ret[0].(*v1.TridentConfigurator) + ret1, _ := ret[1].(bool) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// UpdateTridentConfiguratorStatus indicates an expected call of UpdateTridentConfiguratorStatus. +func (mr *MockConfiguratorClientInterfaceMockRecorder) UpdateTridentConfiguratorStatus(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTridentConfiguratorStatus", reflect.TypeOf((*MockConfiguratorClientInterface)(nil).UpdateTridentConfiguratorStatus), arg0, arg1) +} + +// MockExtendedK8sClientInterface is a mock of ExtendedK8sClientInterface interface. +type MockExtendedK8sClientInterface struct { + ctrl *gomock.Controller + recorder *MockExtendedK8sClientInterfaceMockRecorder +} + +// MockExtendedK8sClientInterfaceMockRecorder is the mock recorder for MockExtendedK8sClientInterface. +type MockExtendedK8sClientInterfaceMockRecorder struct { + mock *MockExtendedK8sClientInterface +} + +// NewMockExtendedK8sClientInterface creates a new mock instance. +func NewMockExtendedK8sClientInterface(ctrl *gomock.Controller) *MockExtendedK8sClientInterface { + mock := &MockExtendedK8sClientInterface{ctrl: ctrl} + mock.recorder = &MockExtendedK8sClientInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockExtendedK8sClientInterface) EXPECT() *MockExtendedK8sClientInterfaceMockRecorder { + return m.recorder +} + +// AddFinalizerToCRD mocks base method. +func (m *MockExtendedK8sClientInterface) AddFinalizerToCRD(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddFinalizerToCRD", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// AddFinalizerToCRD indicates an expected call of AddFinalizerToCRD. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) AddFinalizerToCRD(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddFinalizerToCRD", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).AddFinalizerToCRD), arg0) +} + +// AddFinalizerToCRDs mocks base method. +func (m *MockExtendedK8sClientInterface) AddFinalizerToCRDs(arg0 []string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "AddFinalizerToCRDs", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// AddFinalizerToCRDs indicates an expected call of AddFinalizerToCRDs. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) AddFinalizerToCRDs(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddFinalizerToCRDs", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).AddFinalizerToCRDs), arg0) +} + +// CLI mocks base method. +func (m *MockExtendedK8sClientInterface) CLI() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CLI") + ret0, _ := ret[0].(string) + return ret0 +} + +// CLI indicates an expected call of CLI. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CLI() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CLI", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CLI)) +} + +// CheckCRDExists mocks base method. +func (m *MockExtendedK8sClientInterface) CheckCRDExists(arg0 string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckCRDExists", arg0) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CheckCRDExists indicates an expected call of CheckCRDExists. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CheckCRDExists(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckCRDExists", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CheckCRDExists), arg0) +} + +// CheckCSIDriverExistsByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) CheckCSIDriverExistsByLabel(arg0 string) (bool, string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckCSIDriverExistsByLabel", arg0) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(string) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// CheckCSIDriverExistsByLabel indicates an expected call of CheckCSIDriverExistsByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CheckCSIDriverExistsByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckCSIDriverExistsByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CheckCSIDriverExistsByLabel), arg0) +} + +// CheckClusterRoleBindingExistsByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) CheckClusterRoleBindingExistsByLabel(arg0 string) (bool, string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckClusterRoleBindingExistsByLabel", arg0) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(string) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// CheckClusterRoleBindingExistsByLabel indicates an expected call of CheckClusterRoleBindingExistsByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CheckClusterRoleBindingExistsByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckClusterRoleBindingExistsByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CheckClusterRoleBindingExistsByLabel), arg0) +} + +// CheckClusterRoleExistsByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) CheckClusterRoleExistsByLabel(arg0 string) (bool, string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckClusterRoleExistsByLabel", arg0) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(string) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// CheckClusterRoleExistsByLabel indicates an expected call of CheckClusterRoleExistsByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CheckClusterRoleExistsByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckClusterRoleExistsByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CheckClusterRoleExistsByLabel), arg0) +} + +// CheckDaemonSetExists mocks base method. +func (m *MockExtendedK8sClientInterface) CheckDaemonSetExists(arg0, arg1 string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckDaemonSetExists", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CheckDaemonSetExists indicates an expected call of CheckDaemonSetExists. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CheckDaemonSetExists(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckDaemonSetExists", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CheckDaemonSetExists), arg0, arg1) +} + +// CheckDaemonSetExistsByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) CheckDaemonSetExistsByLabel(arg0 string, arg1 bool) (bool, string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckDaemonSetExistsByLabel", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(string) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// CheckDaemonSetExistsByLabel indicates an expected call of CheckDaemonSetExistsByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CheckDaemonSetExistsByLabel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckDaemonSetExistsByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CheckDaemonSetExistsByLabel), arg0, arg1) +} + +// CheckDeploymentExists mocks base method. +func (m *MockExtendedK8sClientInterface) CheckDeploymentExists(arg0, arg1 string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckDeploymentExists", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CheckDeploymentExists indicates an expected call of CheckDeploymentExists. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CheckDeploymentExists(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckDeploymentExists", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CheckDeploymentExists), arg0, arg1) +} + +// CheckDeploymentExistsByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) CheckDeploymentExistsByLabel(arg0 string, arg1 bool) (bool, string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckDeploymentExistsByLabel", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(string) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// CheckDeploymentExistsByLabel indicates an expected call of CheckDeploymentExistsByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CheckDeploymentExistsByLabel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckDeploymentExistsByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CheckDeploymentExistsByLabel), arg0, arg1) +} + +// CheckNamespaceExists mocks base method. +func (m *MockExtendedK8sClientInterface) CheckNamespaceExists(arg0 string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckNamespaceExists", arg0) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CheckNamespaceExists indicates an expected call of CheckNamespaceExists. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CheckNamespaceExists(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckNamespaceExists", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CheckNamespaceExists), arg0) +} + +// CheckPodExistsByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) CheckPodExistsByLabel(arg0 string, arg1 bool) (bool, string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckPodExistsByLabel", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(string) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// CheckPodExistsByLabel indicates an expected call of CheckPodExistsByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CheckPodExistsByLabel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckPodExistsByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CheckPodExistsByLabel), arg0, arg1) +} + +// CheckPodSecurityPolicyExistsByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) CheckPodSecurityPolicyExistsByLabel(arg0 string) (bool, string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckPodSecurityPolicyExistsByLabel", arg0) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(string) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// CheckPodSecurityPolicyExistsByLabel indicates an expected call of CheckPodSecurityPolicyExistsByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CheckPodSecurityPolicyExistsByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckPodSecurityPolicyExistsByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CheckPodSecurityPolicyExistsByLabel), arg0) +} + +// CheckSecretExists mocks base method. +func (m *MockExtendedK8sClientInterface) CheckSecretExists(arg0 string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckSecretExists", arg0) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CheckSecretExists indicates an expected call of CheckSecretExists. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CheckSecretExists(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckSecretExists", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CheckSecretExists), arg0) +} + +// CheckServiceAccountExistsByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) CheckServiceAccountExistsByLabel(arg0 string, arg1 bool) (bool, string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckServiceAccountExistsByLabel", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(string) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// CheckServiceAccountExistsByLabel indicates an expected call of CheckServiceAccountExistsByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CheckServiceAccountExistsByLabel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckServiceAccountExistsByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CheckServiceAccountExistsByLabel), arg0, arg1) +} + +// CheckServiceExistsByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) CheckServiceExistsByLabel(arg0 string, arg1 bool) (bool, string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckServiceExistsByLabel", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(string) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// CheckServiceExistsByLabel indicates an expected call of CheckServiceExistsByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CheckServiceExistsByLabel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckServiceExistsByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CheckServiceExistsByLabel), arg0, arg1) +} + +// CheckStorageClassExists mocks base method. +func (m *MockExtendedK8sClientInterface) CheckStorageClassExists(arg0 string) (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CheckStorageClassExists", arg0) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CheckStorageClassExists indicates an expected call of CheckStorageClassExists. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CheckStorageClassExists(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CheckStorageClassExists", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CheckStorageClassExists), arg0) +} + +// CreateObjectByFile mocks base method. +func (m *MockExtendedK8sClientInterface) CreateObjectByFile(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateObjectByFile", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateObjectByFile indicates an expected call of CreateObjectByFile. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CreateObjectByFile(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateObjectByFile", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CreateObjectByFile), arg0) +} + +// CreateObjectByYAML mocks base method. +func (m *MockExtendedK8sClientInterface) CreateObjectByYAML(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateObjectByYAML", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateObjectByYAML indicates an expected call of CreateObjectByYAML. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CreateObjectByYAML(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateObjectByYAML", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CreateObjectByYAML), arg0) +} + +// CreateSecret mocks base method. +func (m *MockExtendedK8sClientInterface) CreateSecret(arg0 *v11.Secret) (*v11.Secret, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateSecret", arg0) + ret0, _ := ret[0].(*v11.Secret) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// CreateSecret indicates an expected call of CreateSecret. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) CreateSecret(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateSecret", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).CreateSecret), arg0) +} + +// DeleteCRD mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteCRD(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteCRD", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteCRD indicates an expected call of DeleteCRD. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteCRD(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteCRD", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteCRD), arg0) +} + +// DeleteCSIDriver mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteCSIDriver(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteCSIDriver", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteCSIDriver indicates an expected call of DeleteCSIDriver. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteCSIDriver(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteCSIDriver", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteCSIDriver), arg0) +} + +// DeleteCSIDriverByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteCSIDriverByLabel(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteCSIDriverByLabel", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteCSIDriverByLabel indicates an expected call of DeleteCSIDriverByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteCSIDriverByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteCSIDriverByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteCSIDriverByLabel), arg0) +} + +// DeleteClusterRole mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteClusterRole(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteClusterRole", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteClusterRole indicates an expected call of DeleteClusterRole. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteClusterRole(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteClusterRole", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteClusterRole), arg0) +} + +// DeleteClusterRoleBinding mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteClusterRoleBinding(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteClusterRoleBinding", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteClusterRoleBinding indicates an expected call of DeleteClusterRoleBinding. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteClusterRoleBinding(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteClusterRoleBinding", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteClusterRoleBinding), arg0) +} + +// DeleteClusterRoleBindingByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteClusterRoleBindingByLabel(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteClusterRoleBindingByLabel", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteClusterRoleBindingByLabel indicates an expected call of DeleteClusterRoleBindingByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteClusterRoleBindingByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteClusterRoleBindingByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteClusterRoleBindingByLabel), arg0) +} + +// DeleteClusterRoleByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteClusterRoleByLabel(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteClusterRoleByLabel", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteClusterRoleByLabel indicates an expected call of DeleteClusterRoleByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteClusterRoleByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteClusterRoleByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteClusterRoleByLabel), arg0) +} + +// DeleteDaemonSet mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteDaemonSet(arg0, arg1 string, arg2 bool) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteDaemonSet", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteDaemonSet indicates an expected call of DeleteDaemonSet. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteDaemonSet(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteDaemonSet", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteDaemonSet), arg0, arg1, arg2) +} + +// DeleteDaemonSetByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteDaemonSetByLabel(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteDaemonSetByLabel", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteDaemonSetByLabel indicates an expected call of DeleteDaemonSetByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteDaemonSetByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteDaemonSetByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteDaemonSetByLabel), arg0) +} + +// DeleteDaemonSetByLabelAndName mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteDaemonSetByLabelAndName(arg0, arg1 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteDaemonSetByLabelAndName", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteDaemonSetByLabelAndName indicates an expected call of DeleteDaemonSetByLabelAndName. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteDaemonSetByLabelAndName(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteDaemonSetByLabelAndName", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteDaemonSetByLabelAndName), arg0, arg1) +} + +// DeleteDeployment mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteDeployment(arg0, arg1 string, arg2 bool) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteDeployment", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteDeployment indicates an expected call of DeleteDeployment. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteDeployment(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteDeployment", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteDeployment), arg0, arg1, arg2) +} + +// DeleteDeploymentByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteDeploymentByLabel(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteDeploymentByLabel", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteDeploymentByLabel indicates an expected call of DeleteDeploymentByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteDeploymentByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteDeploymentByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteDeploymentByLabel), arg0) +} + +// DeleteObjectByFile mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteObjectByFile(arg0 string, arg1 bool) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteObjectByFile", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteObjectByFile indicates an expected call of DeleteObjectByFile. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteObjectByFile(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteObjectByFile", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteObjectByFile), arg0, arg1) +} + +// DeleteObjectByYAML mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteObjectByYAML(arg0 string, arg1 bool) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteObjectByYAML", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteObjectByYAML indicates an expected call of DeleteObjectByYAML. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteObjectByYAML(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteObjectByYAML", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteObjectByYAML), arg0, arg1) +} + +// DeletePod mocks base method. +func (m *MockExtendedK8sClientInterface) DeletePod(arg0, arg1 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeletePod", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeletePod indicates an expected call of DeletePod. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeletePod(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeletePod", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeletePod), arg0, arg1) +} + +// DeletePodByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) DeletePodByLabel(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeletePodByLabel", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeletePodByLabel indicates an expected call of DeletePodByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeletePodByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeletePodByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeletePodByLabel), arg0) +} + +// DeletePodSecurityPolicy mocks base method. +func (m *MockExtendedK8sClientInterface) DeletePodSecurityPolicy(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeletePodSecurityPolicy", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeletePodSecurityPolicy indicates an expected call of DeletePodSecurityPolicy. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeletePodSecurityPolicy(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeletePodSecurityPolicy", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeletePodSecurityPolicy), arg0) +} + +// DeletePodSecurityPolicyByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) DeletePodSecurityPolicyByLabel(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeletePodSecurityPolicyByLabel", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeletePodSecurityPolicyByLabel indicates an expected call of DeletePodSecurityPolicyByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeletePodSecurityPolicyByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeletePodSecurityPolicyByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeletePodSecurityPolicyByLabel), arg0) +} + +// DeleteResourceQuota mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteResourceQuota(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteResourceQuota", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteResourceQuota indicates an expected call of DeleteResourceQuota. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteResourceQuota(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteResourceQuota", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteResourceQuota), arg0) +} + +// DeleteResourceQuotaByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteResourceQuotaByLabel(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteResourceQuotaByLabel", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteResourceQuotaByLabel indicates an expected call of DeleteResourceQuotaByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteResourceQuotaByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteResourceQuotaByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteResourceQuotaByLabel), arg0) +} + +// DeleteRole mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteRole(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteRole", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteRole indicates an expected call of DeleteRole. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteRole(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteRole", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteRole), arg0) +} + +// DeleteRoleBinding mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteRoleBinding(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteRoleBinding", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteRoleBinding indicates an expected call of DeleteRoleBinding. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteRoleBinding(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteRoleBinding", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteRoleBinding), arg0) +} + +// DeleteSecret mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteSecret(arg0, arg1 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteSecret", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteSecret indicates an expected call of DeleteSecret. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteSecret(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSecret", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteSecret), arg0, arg1) +} + +// DeleteSecretByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteSecretByLabel(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteSecretByLabel", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteSecretByLabel indicates an expected call of DeleteSecretByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteSecretByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSecretByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteSecretByLabel), arg0) +} + +// DeleteSecretDefault mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteSecretDefault(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteSecretDefault", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteSecretDefault indicates an expected call of DeleteSecretDefault. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteSecretDefault(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteSecretDefault", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteSecretDefault), arg0) +} + +// DeleteService mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteService(arg0, arg1 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteService", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteService indicates an expected call of DeleteService. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteService(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteService", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteService), arg0, arg1) +} + +// DeleteServiceAccount mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteServiceAccount(arg0, arg1 string, arg2 bool) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteServiceAccount", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteServiceAccount indicates an expected call of DeleteServiceAccount. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteServiceAccount(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteServiceAccount", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteServiceAccount), arg0, arg1, arg2) +} + +// DeleteServiceAccountByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteServiceAccountByLabel(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteServiceAccountByLabel", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteServiceAccountByLabel indicates an expected call of DeleteServiceAccountByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteServiceAccountByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteServiceAccountByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteServiceAccountByLabel), arg0) +} + +// DeleteServiceByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteServiceByLabel(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteServiceByLabel", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteServiceByLabel indicates an expected call of DeleteServiceByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteServiceByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteServiceByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteServiceByLabel), arg0) +} + +// DeleteStorageClass mocks base method. +func (m *MockExtendedK8sClientInterface) DeleteStorageClass(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteStorageClass", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteStorageClass indicates an expected call of DeleteStorageClass. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) DeleteStorageClass(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteStorageClass", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).DeleteStorageClass), arg0) +} + +// Exec mocks base method. +func (m *MockExtendedK8sClientInterface) Exec(arg0, arg1 string, arg2 []string) ([]byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Exec", arg0, arg1, arg2) + ret0, _ := ret[0].([]byte) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// Exec indicates an expected call of Exec. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) Exec(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Exec", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).Exec), arg0, arg1, arg2) +} + +// Flavor mocks base method. +func (m *MockExtendedK8sClientInterface) Flavor() k8sclient.OrchestratorFlavor { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Flavor") + ret0, _ := ret[0].(k8sclient.OrchestratorFlavor) + return ret0 +} + +// Flavor indicates an expected call of Flavor. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) Flavor() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Flavor", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).Flavor)) +} + +// GetCRD mocks base method. +func (m *MockExtendedK8sClientInterface) GetCRD(arg0 string) (*v14.CustomResourceDefinition, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCRD", arg0) + ret0, _ := ret[0].(*v14.CustomResourceDefinition) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCRD indicates an expected call of GetCRD. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetCRD(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCRD", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetCRD), arg0) +} + +// GetCSIDriverByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetCSIDriverByLabel(arg0 string) (*v13.CSIDriver, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCSIDriverByLabel", arg0) + ret0, _ := ret[0].(*v13.CSIDriver) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCSIDriverByLabel indicates an expected call of GetCSIDriverByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetCSIDriverByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCSIDriverByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetCSIDriverByLabel), arg0) +} + +// GetCSIDriversByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetCSIDriversByLabel(arg0 string) ([]v13.CSIDriver, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetCSIDriversByLabel", arg0) + ret0, _ := ret[0].([]v13.CSIDriver) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetCSIDriversByLabel indicates an expected call of GetCSIDriversByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetCSIDriversByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCSIDriversByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetCSIDriversByLabel), arg0) +} + +// GetClusterRoleBindingByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetClusterRoleBindingByLabel(arg0 string) (*v12.ClusterRoleBinding, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetClusterRoleBindingByLabel", arg0) + ret0, _ := ret[0].(*v12.ClusterRoleBinding) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetClusterRoleBindingByLabel indicates an expected call of GetClusterRoleBindingByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetClusterRoleBindingByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetClusterRoleBindingByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetClusterRoleBindingByLabel), arg0) +} + +// GetClusterRoleBindingByLabelAndName mocks base method. +func (m *MockExtendedK8sClientInterface) GetClusterRoleBindingByLabelAndName(arg0, arg1 string) (*v12.ClusterRoleBinding, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetClusterRoleBindingByLabelAndName", arg0, arg1) + ret0, _ := ret[0].(*v12.ClusterRoleBinding) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetClusterRoleBindingByLabelAndName indicates an expected call of GetClusterRoleBindingByLabelAndName. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetClusterRoleBindingByLabelAndName(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetClusterRoleBindingByLabelAndName", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetClusterRoleBindingByLabelAndName), arg0, arg1) +} + +// GetClusterRoleBindingsByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetClusterRoleBindingsByLabel(arg0 string) ([]v12.ClusterRoleBinding, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetClusterRoleBindingsByLabel", arg0) + ret0, _ := ret[0].([]v12.ClusterRoleBinding) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetClusterRoleBindingsByLabel indicates an expected call of GetClusterRoleBindingsByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetClusterRoleBindingsByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetClusterRoleBindingsByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetClusterRoleBindingsByLabel), arg0) +} + +// GetClusterRoleByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetClusterRoleByLabel(arg0 string) (*v12.ClusterRole, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetClusterRoleByLabel", arg0) + ret0, _ := ret[0].(*v12.ClusterRole) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetClusterRoleByLabel indicates an expected call of GetClusterRoleByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetClusterRoleByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetClusterRoleByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetClusterRoleByLabel), arg0) +} + +// GetClusterRoleByLabelAndName mocks base method. +func (m *MockExtendedK8sClientInterface) GetClusterRoleByLabelAndName(arg0, arg1 string) (*v12.ClusterRole, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetClusterRoleByLabelAndName", arg0, arg1) + ret0, _ := ret[0].(*v12.ClusterRole) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetClusterRoleByLabelAndName indicates an expected call of GetClusterRoleByLabelAndName. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetClusterRoleByLabelAndName(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetClusterRoleByLabelAndName", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetClusterRoleByLabelAndName), arg0, arg1) +} + +// GetClusterRolesByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetClusterRolesByLabel(arg0 string) ([]v12.ClusterRole, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetClusterRolesByLabel", arg0) + ret0, _ := ret[0].([]v12.ClusterRole) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetClusterRolesByLabel indicates an expected call of GetClusterRolesByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetClusterRolesByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetClusterRolesByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetClusterRolesByLabel), arg0) +} + +// GetDaemonSetByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetDaemonSetByLabel(arg0 string, arg1 bool) (*v10.DaemonSet, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetDaemonSetByLabel", arg0, arg1) + ret0, _ := ret[0].(*v10.DaemonSet) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetDaemonSetByLabel indicates an expected call of GetDaemonSetByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetDaemonSetByLabel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDaemonSetByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetDaemonSetByLabel), arg0, arg1) +} + +// GetDaemonSetByLabelAndName mocks base method. +func (m *MockExtendedK8sClientInterface) GetDaemonSetByLabelAndName(arg0, arg1 string, arg2 bool) (*v10.DaemonSet, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetDaemonSetByLabelAndName", arg0, arg1, arg2) + ret0, _ := ret[0].(*v10.DaemonSet) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetDaemonSetByLabelAndName indicates an expected call of GetDaemonSetByLabelAndName. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetDaemonSetByLabelAndName(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDaemonSetByLabelAndName", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetDaemonSetByLabelAndName), arg0, arg1, arg2) +} + +// GetDaemonSetsByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetDaemonSetsByLabel(arg0 string, arg1 bool) ([]v10.DaemonSet, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetDaemonSetsByLabel", arg0, arg1) + ret0, _ := ret[0].([]v10.DaemonSet) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetDaemonSetsByLabel indicates an expected call of GetDaemonSetsByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetDaemonSetsByLabel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDaemonSetsByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetDaemonSetsByLabel), arg0, arg1) +} + +// GetDeploymentByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetDeploymentByLabel(arg0 string, arg1 bool) (*v10.Deployment, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetDeploymentByLabel", arg0, arg1) + ret0, _ := ret[0].(*v10.Deployment) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetDeploymentByLabel indicates an expected call of GetDeploymentByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetDeploymentByLabel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDeploymentByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetDeploymentByLabel), arg0, arg1) +} + +// GetDeploymentsByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetDeploymentsByLabel(arg0 string, arg1 bool) ([]v10.Deployment, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetDeploymentsByLabel", arg0, arg1) + ret0, _ := ret[0].([]v10.Deployment) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetDeploymentsByLabel indicates an expected call of GetDeploymentsByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetDeploymentsByLabel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDeploymentsByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetDeploymentsByLabel), arg0, arg1) +} + +// GetNamespace mocks base method. +func (m *MockExtendedK8sClientInterface) GetNamespace(arg0 string) (*v11.Namespace, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetNamespace", arg0) + ret0, _ := ret[0].(*v11.Namespace) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetNamespace indicates an expected call of GetNamespace. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetNamespace(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetNamespace", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetNamespace), arg0) +} + +// GetOpenShiftSCCByName mocks base method. +func (m *MockExtendedK8sClientInterface) GetOpenShiftSCCByName(arg0, arg1 string) (bool, bool, []byte, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetOpenShiftSCCByName", arg0, arg1) + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(bool) + ret2, _ := ret[2].([]byte) + ret3, _ := ret[3].(error) + return ret0, ret1, ret2, ret3 +} + +// GetOpenShiftSCCByName indicates an expected call of GetOpenShiftSCCByName. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetOpenShiftSCCByName(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOpenShiftSCCByName", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetOpenShiftSCCByName), arg0, arg1) +} + +// GetPodByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetPodByLabel(arg0 string, arg1 bool) (*v11.Pod, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPodByLabel", arg0, arg1) + ret0, _ := ret[0].(*v11.Pod) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPodByLabel indicates an expected call of GetPodByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetPodByLabel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPodByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetPodByLabel), arg0, arg1) +} + +// GetPodSecurityPoliciesByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetPodSecurityPoliciesByLabel(arg0 string) ([]v1beta1.PodSecurityPolicy, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPodSecurityPoliciesByLabel", arg0) + ret0, _ := ret[0].([]v1beta1.PodSecurityPolicy) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPodSecurityPoliciesByLabel indicates an expected call of GetPodSecurityPoliciesByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetPodSecurityPoliciesByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPodSecurityPoliciesByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetPodSecurityPoliciesByLabel), arg0) +} + +// GetPodSecurityPolicyByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetPodSecurityPolicyByLabel(arg0 string) (*v1beta1.PodSecurityPolicy, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPodSecurityPolicyByLabel", arg0) + ret0, _ := ret[0].(*v1beta1.PodSecurityPolicy) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPodSecurityPolicyByLabel indicates an expected call of GetPodSecurityPolicyByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetPodSecurityPolicyByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPodSecurityPolicyByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetPodSecurityPolicyByLabel), arg0) +} + +// GetPodsByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetPodsByLabel(arg0 string, arg1 bool) ([]v11.Pod, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetPodsByLabel", arg0, arg1) + ret0, _ := ret[0].([]v11.Pod) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetPodsByLabel indicates an expected call of GetPodsByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetPodsByLabel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPodsByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetPodsByLabel), arg0, arg1) +} + +// GetResourceQuota mocks base method. +func (m *MockExtendedK8sClientInterface) GetResourceQuota(arg0 string) (*v11.ResourceQuota, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetResourceQuota", arg0) + ret0, _ := ret[0].(*v11.ResourceQuota) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetResourceQuota indicates an expected call of GetResourceQuota. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetResourceQuota(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetResourceQuota", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetResourceQuota), arg0) +} + +// GetResourceQuotaByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetResourceQuotaByLabel(arg0 string) (*v11.ResourceQuota, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetResourceQuotaByLabel", arg0) + ret0, _ := ret[0].(*v11.ResourceQuota) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetResourceQuotaByLabel indicates an expected call of GetResourceQuotaByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetResourceQuotaByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetResourceQuotaByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetResourceQuotaByLabel), arg0) +} + +// GetResourceQuotasByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetResourceQuotasByLabel(arg0 string) ([]v11.ResourceQuota, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetResourceQuotasByLabel", arg0) + ret0, _ := ret[0].([]v11.ResourceQuota) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetResourceQuotasByLabel indicates an expected call of GetResourceQuotasByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetResourceQuotasByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetResourceQuotasByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetResourceQuotasByLabel), arg0) +} + +// GetRoleBindingByLabelAndName mocks base method. +func (m *MockExtendedK8sClientInterface) GetRoleBindingByLabelAndName(arg0, arg1 string) (*v12.RoleBinding, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetRoleBindingByLabelAndName", arg0, arg1) + ret0, _ := ret[0].(*v12.RoleBinding) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetRoleBindingByLabelAndName indicates an expected call of GetRoleBindingByLabelAndName. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetRoleBindingByLabelAndName(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRoleBindingByLabelAndName", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetRoleBindingByLabelAndName), arg0, arg1) +} + +// GetRoleBindingsByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetRoleBindingsByLabel(arg0 string) ([]v12.RoleBinding, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetRoleBindingsByLabel", arg0) + ret0, _ := ret[0].([]v12.RoleBinding) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetRoleBindingsByLabel indicates an expected call of GetRoleBindingsByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetRoleBindingsByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRoleBindingsByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetRoleBindingsByLabel), arg0) +} + +// GetRolesByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetRolesByLabel(arg0 string) ([]v12.Role, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetRolesByLabel", arg0) + ret0, _ := ret[0].([]v12.Role) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetRolesByLabel indicates an expected call of GetRolesByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetRolesByLabel(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRolesByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetRolesByLabel), arg0) +} + +// GetSecret mocks base method. +func (m *MockExtendedK8sClientInterface) GetSecret(arg0 string) (*v11.Secret, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSecret", arg0) + ret0, _ := ret[0].(*v11.Secret) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSecret indicates an expected call of GetSecret. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetSecret(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSecret", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetSecret), arg0) +} + +// GetSecretByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetSecretByLabel(arg0 string, arg1 bool) (*v11.Secret, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSecretByLabel", arg0, arg1) + ret0, _ := ret[0].(*v11.Secret) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSecretByLabel indicates an expected call of GetSecretByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetSecretByLabel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSecretByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetSecretByLabel), arg0, arg1) +} + +// GetSecretsByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetSecretsByLabel(arg0 string, arg1 bool) ([]v11.Secret, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetSecretsByLabel", arg0, arg1) + ret0, _ := ret[0].([]v11.Secret) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetSecretsByLabel indicates an expected call of GetSecretsByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetSecretsByLabel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSecretsByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetSecretsByLabel), arg0, arg1) +} + +// GetServiceAccountByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetServiceAccountByLabel(arg0 string, arg1 bool) (*v11.ServiceAccount, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetServiceAccountByLabel", arg0, arg1) + ret0, _ := ret[0].(*v11.ServiceAccount) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetServiceAccountByLabel indicates an expected call of GetServiceAccountByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetServiceAccountByLabel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceAccountByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetServiceAccountByLabel), arg0, arg1) +} + +// GetServiceAccountByLabelAndName mocks base method. +func (m *MockExtendedK8sClientInterface) GetServiceAccountByLabelAndName(arg0, arg1 string, arg2 bool) (*v11.ServiceAccount, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetServiceAccountByLabelAndName", arg0, arg1, arg2) + ret0, _ := ret[0].(*v11.ServiceAccount) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetServiceAccountByLabelAndName indicates an expected call of GetServiceAccountByLabelAndName. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetServiceAccountByLabelAndName(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceAccountByLabelAndName", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetServiceAccountByLabelAndName), arg0, arg1, arg2) +} + +// GetServiceAccountsByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetServiceAccountsByLabel(arg0 string, arg1 bool) ([]v11.ServiceAccount, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetServiceAccountsByLabel", arg0, arg1) + ret0, _ := ret[0].([]v11.ServiceAccount) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetServiceAccountsByLabel indicates an expected call of GetServiceAccountsByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetServiceAccountsByLabel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceAccountsByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetServiceAccountsByLabel), arg0, arg1) +} + +// GetServiceByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetServiceByLabel(arg0 string, arg1 bool) (*v11.Service, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetServiceByLabel", arg0, arg1) + ret0, _ := ret[0].(*v11.Service) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetServiceByLabel indicates an expected call of GetServiceByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetServiceByLabel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServiceByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetServiceByLabel), arg0, arg1) +} + +// GetServicesByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) GetServicesByLabel(arg0 string, arg1 bool) ([]v11.Service, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetServicesByLabel", arg0, arg1) + ret0, _ := ret[0].([]v11.Service) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetServicesByLabel indicates an expected call of GetServicesByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetServicesByLabel(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetServicesByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetServicesByLabel), arg0, arg1) +} + +// GetStorageClass mocks base method. +func (m *MockExtendedK8sClientInterface) GetStorageClass(arg0 string) (*v13.StorageClass, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetStorageClass", arg0) + ret0, _ := ret[0].(*v13.StorageClass) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetStorageClass indicates an expected call of GetStorageClass. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) GetStorageClass(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStorageClass", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).GetStorageClass), arg0) +} + +// IsTopologyInUse mocks base method. +func (m *MockExtendedK8sClientInterface) IsTopologyInUse() (bool, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsTopologyInUse") + ret0, _ := ret[0].(bool) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// IsTopologyInUse indicates an expected call of IsTopologyInUse. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) IsTopologyInUse() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsTopologyInUse", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).IsTopologyInUse)) +} + +// Namespace mocks base method. +func (m *MockExtendedK8sClientInterface) Namespace() string { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Namespace") + ret0, _ := ret[0].(string) + return ret0 +} + +// Namespace indicates an expected call of Namespace. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) Namespace() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Namespace", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).Namespace)) +} + +// PatchCRD mocks base method. +func (m *MockExtendedK8sClientInterface) PatchCRD(arg0 string, arg1 []byte, arg2 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchCRD", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchCRD indicates an expected call of PatchCRD. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchCRD(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchCRD", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchCRD), arg0, arg1, arg2) +} + +// PatchCSIDriverByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) PatchCSIDriverByLabel(arg0 string, arg1 []byte, arg2 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchCSIDriverByLabel", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchCSIDriverByLabel indicates an expected call of PatchCSIDriverByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchCSIDriverByLabel(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchCSIDriverByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchCSIDriverByLabel), arg0, arg1, arg2) +} + +// PatchClusterRoleBindingByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) PatchClusterRoleBindingByLabel(arg0 string, arg1 []byte, arg2 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchClusterRoleBindingByLabel", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchClusterRoleBindingByLabel indicates an expected call of PatchClusterRoleBindingByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchClusterRoleBindingByLabel(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchClusterRoleBindingByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchClusterRoleBindingByLabel), arg0, arg1, arg2) +} + +// PatchClusterRoleBindingByLabelAndName mocks base method. +func (m *MockExtendedK8sClientInterface) PatchClusterRoleBindingByLabelAndName(arg0, arg1 string, arg2 []byte, arg3 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchClusterRoleBindingByLabelAndName", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchClusterRoleBindingByLabelAndName indicates an expected call of PatchClusterRoleBindingByLabelAndName. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchClusterRoleBindingByLabelAndName(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchClusterRoleBindingByLabelAndName", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchClusterRoleBindingByLabelAndName), arg0, arg1, arg2, arg3) +} + +// PatchClusterRoleByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) PatchClusterRoleByLabel(arg0 string, arg1 []byte, arg2 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchClusterRoleByLabel", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchClusterRoleByLabel indicates an expected call of PatchClusterRoleByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchClusterRoleByLabel(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchClusterRoleByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchClusterRoleByLabel), arg0, arg1, arg2) +} + +// PatchClusterRoleByLabelAndName mocks base method. +func (m *MockExtendedK8sClientInterface) PatchClusterRoleByLabelAndName(arg0, arg1 string, arg2 []byte, arg3 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchClusterRoleByLabelAndName", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchClusterRoleByLabelAndName indicates an expected call of PatchClusterRoleByLabelAndName. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchClusterRoleByLabelAndName(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchClusterRoleByLabelAndName", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchClusterRoleByLabelAndName), arg0, arg1, arg2, arg3) +} + +// PatchDaemonSetByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) PatchDaemonSetByLabel(arg0 string, arg1 []byte, arg2 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchDaemonSetByLabel", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchDaemonSetByLabel indicates an expected call of PatchDaemonSetByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchDaemonSetByLabel(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchDaemonSetByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchDaemonSetByLabel), arg0, arg1, arg2) +} + +// PatchDaemonSetByLabelAndName mocks base method. +func (m *MockExtendedK8sClientInterface) PatchDaemonSetByLabelAndName(arg0, arg1 string, arg2 []byte, arg3 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchDaemonSetByLabelAndName", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchDaemonSetByLabelAndName indicates an expected call of PatchDaemonSetByLabelAndName. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchDaemonSetByLabelAndName(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchDaemonSetByLabelAndName", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchDaemonSetByLabelAndName), arg0, arg1, arg2, arg3) +} + +// PatchDeploymentByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) PatchDeploymentByLabel(arg0 string, arg1 []byte, arg2 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchDeploymentByLabel", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchDeploymentByLabel indicates an expected call of PatchDeploymentByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchDeploymentByLabel(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchDeploymentByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchDeploymentByLabel), arg0, arg1, arg2) +} + +// PatchNamespace mocks base method. +func (m *MockExtendedK8sClientInterface) PatchNamespace(arg0 string, arg1 []byte, arg2 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchNamespace", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchNamespace indicates an expected call of PatchNamespace. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchNamespace(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchNamespace", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchNamespace), arg0, arg1, arg2) +} + +// PatchNamespaceLabels mocks base method. +func (m *MockExtendedK8sClientInterface) PatchNamespaceLabels(arg0 string, arg1 map[string]string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchNamespaceLabels", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchNamespaceLabels indicates an expected call of PatchNamespaceLabels. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchNamespaceLabels(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchNamespaceLabels", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchNamespaceLabels), arg0, arg1) +} + +// PatchOpenShiftSCC mocks base method. +func (m *MockExtendedK8sClientInterface) PatchOpenShiftSCC(arg0 []byte) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchOpenShiftSCC", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchOpenShiftSCC indicates an expected call of PatchOpenShiftSCC. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchOpenShiftSCC(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchOpenShiftSCC", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchOpenShiftSCC), arg0) +} + +// PatchPodSecurityPolicyByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) PatchPodSecurityPolicyByLabel(arg0 string, arg1 []byte, arg2 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchPodSecurityPolicyByLabel", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchPodSecurityPolicyByLabel indicates an expected call of PatchPodSecurityPolicyByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchPodSecurityPolicyByLabel(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchPodSecurityPolicyByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchPodSecurityPolicyByLabel), arg0, arg1, arg2) +} + +// PatchPodSecurityPolicyByLabelAndName mocks base method. +func (m *MockExtendedK8sClientInterface) PatchPodSecurityPolicyByLabelAndName(arg0, arg1 string, arg2 []byte, arg3 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchPodSecurityPolicyByLabelAndName", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchPodSecurityPolicyByLabelAndName indicates an expected call of PatchPodSecurityPolicyByLabelAndName. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchPodSecurityPolicyByLabelAndName(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchPodSecurityPolicyByLabelAndName", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchPodSecurityPolicyByLabelAndName), arg0, arg1, arg2, arg3) +} + +// PatchResourceQuotaByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) PatchResourceQuotaByLabel(arg0 string, arg1 []byte, arg2 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchResourceQuotaByLabel", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchResourceQuotaByLabel indicates an expected call of PatchResourceQuotaByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchResourceQuotaByLabel(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchResourceQuotaByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchResourceQuotaByLabel), arg0, arg1, arg2) +} + +// PatchRoleBindingByLabelAndName mocks base method. +func (m *MockExtendedK8sClientInterface) PatchRoleBindingByLabelAndName(arg0, arg1 string, arg2 []byte, arg3 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchRoleBindingByLabelAndName", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchRoleBindingByLabelAndName indicates an expected call of PatchRoleBindingByLabelAndName. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchRoleBindingByLabelAndName(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchRoleBindingByLabelAndName", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchRoleBindingByLabelAndName), arg0, arg1, arg2, arg3) +} + +// PatchRoleByLabelAndName mocks base method. +func (m *MockExtendedK8sClientInterface) PatchRoleByLabelAndName(arg0, arg1 string, arg2 []byte, arg3 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchRoleByLabelAndName", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchRoleByLabelAndName indicates an expected call of PatchRoleByLabelAndName. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchRoleByLabelAndName(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchRoleByLabelAndName", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchRoleByLabelAndName), arg0, arg1, arg2, arg3) +} + +// PatchSecretByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) PatchSecretByLabel(arg0 string, arg1 []byte, arg2 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchSecretByLabel", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchSecretByLabel indicates an expected call of PatchSecretByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchSecretByLabel(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchSecretByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchSecretByLabel), arg0, arg1, arg2) +} + +// PatchServiceAccountByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) PatchServiceAccountByLabel(arg0 string, arg1 []byte, arg2 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchServiceAccountByLabel", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchServiceAccountByLabel indicates an expected call of PatchServiceAccountByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchServiceAccountByLabel(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchServiceAccountByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchServiceAccountByLabel), arg0, arg1, arg2) +} + +// PatchServiceAccountByLabelAndName mocks base method. +func (m *MockExtendedK8sClientInterface) PatchServiceAccountByLabelAndName(arg0, arg1 string, arg2 []byte, arg3 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchServiceAccountByLabelAndName", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchServiceAccountByLabelAndName indicates an expected call of PatchServiceAccountByLabelAndName. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchServiceAccountByLabelAndName(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchServiceAccountByLabelAndName", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchServiceAccountByLabelAndName), arg0, arg1, arg2, arg3) +} + +// PatchServiceByLabel mocks base method. +func (m *MockExtendedK8sClientInterface) PatchServiceByLabel(arg0 string, arg1 []byte, arg2 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchServiceByLabel", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchServiceByLabel indicates an expected call of PatchServiceByLabel. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchServiceByLabel(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchServiceByLabel", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchServiceByLabel), arg0, arg1, arg2) +} + +// PatchStorageClass mocks base method. +func (m *MockExtendedK8sClientInterface) PatchStorageClass(arg0 string, arg1 []byte, arg2 types.PatchType) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "PatchStorageClass", arg0, arg1, arg2) + ret0, _ := ret[0].(error) + return ret0 +} + +// PatchStorageClass indicates an expected call of PatchStorageClass. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) PatchStorageClass(arg0, arg1, arg2 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchStorageClass", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).PatchStorageClass), arg0, arg1, arg2) +} + +// RemoveFinalizerFromCRD mocks base method. +func (m *MockExtendedK8sClientInterface) RemoveFinalizerFromCRD(arg0 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RemoveFinalizerFromCRD", arg0) + ret0, _ := ret[0].(error) + return ret0 +} + +// RemoveFinalizerFromCRD indicates an expected call of RemoveFinalizerFromCRD. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) RemoveFinalizerFromCRD(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveFinalizerFromCRD", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).RemoveFinalizerFromCRD), arg0) +} + +// RemoveTridentUserFromOpenShiftSCC mocks base method. +func (m *MockExtendedK8sClientInterface) RemoveTridentUserFromOpenShiftSCC(arg0, arg1 string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "RemoveTridentUserFromOpenShiftSCC", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// RemoveTridentUserFromOpenShiftSCC indicates an expected call of RemoveTridentUserFromOpenShiftSCC. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) RemoveTridentUserFromOpenShiftSCC(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveTridentUserFromOpenShiftSCC", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).RemoveTridentUserFromOpenShiftSCC), arg0, arg1) +} + +// ServerVersion mocks base method. +func (m *MockExtendedK8sClientInterface) ServerVersion() *version.Version { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ServerVersion") + ret0, _ := ret[0].(*version.Version) + return ret0 +} + +// ServerVersion indicates an expected call of ServerVersion. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) ServerVersion() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ServerVersion", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).ServerVersion)) +} + +// SetNamespace mocks base method. +func (m *MockExtendedK8sClientInterface) SetNamespace(arg0 string) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetNamespace", arg0) +} + +// SetNamespace indicates an expected call of SetNamespace. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) SetNamespace(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetNamespace", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).SetNamespace), arg0) +} + +// SetTimeout mocks base method. +func (m *MockExtendedK8sClientInterface) SetTimeout(arg0 time.Duration) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "SetTimeout", arg0) +} + +// SetTimeout indicates an expected call of SetTimeout. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) SetTimeout(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetTimeout", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).SetTimeout), arg0) +} + +// UpdateSecret mocks base method. +func (m *MockExtendedK8sClientInterface) UpdateSecret(arg0 *v11.Secret) (*v11.Secret, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateSecret", arg0) + ret0, _ := ret[0].(*v11.Secret) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateSecret indicates an expected call of UpdateSecret. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) UpdateSecret(arg0 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateSecret", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).UpdateSecret), arg0) +} + +// Version mocks base method. +func (m *MockExtendedK8sClientInterface) Version() *version0.Info { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "Version") + ret0, _ := ret[0].(*version0.Info) + return ret0 +} + +// Version indicates an expected call of Version. +func (mr *MockExtendedK8sClientInterfaceMockRecorder) Version() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Version", reflect.TypeOf((*MockExtendedK8sClientInterface)(nil).Version)) +} diff --git a/mocks/mock_operator/mock_controllers/mock_orchestrator/mock_installer/mock_installer.go b/mocks/mock_operator/mock_controllers/mock_orchestrator/mock_installer/mock_installer.go index 66276be33..5555c70df 100644 --- a/mocks/mock_operator/mock_controllers/mock_orchestrator/mock_installer/mock_installer.go +++ b/mocks/mock_operator/mock_controllers/mock_orchestrator/mock_installer/mock_installer.go @@ -11,7 +11,7 @@ import ( gomock "github.com/golang/mock/gomock" v1 "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1" k8sclient "github.com/netapp/trident/cli/k8s_client" - v10 "github.com/netapp/trident/operator/controllers/orchestrator/apis/netapp/v1" + v10 "github.com/netapp/trident/operator/crd/apis/netapp/v1" version "github.com/netapp/trident/utils/version" v11 "k8s.io/api/apps/v1" v12 "k8s.io/api/core/v1" diff --git a/mocks/mock_storage_drivers/mock_azure/mock_api.go b/mocks/mock_storage_drivers/mock_azure/mock_api.go index 540ce65f2..c300c5364 100644 --- a/mocks/mock_storage_drivers/mock_azure/mock_api.go +++ b/mocks/mock_storage_drivers/mock_azure/mock_api.go @@ -229,6 +229,34 @@ func (mr *MockAzureMockRecorder) Features() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Features", reflect.TypeOf((*MockAzure)(nil).Features)) } +// FilteredCapacityPoolMap mocks base method. +func (m *MockAzure) FilteredCapacityPoolMap(arg0 context.Context, arg1, arg2, arg3 []string) map[string]*api.CapacityPool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FilteredCapacityPoolMap", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(map[string]*api.CapacityPool) + return ret0 +} + +// FilteredCapacityPoolMap indicates an expected call of FilteredCapacityPoolMap. +func (mr *MockAzureMockRecorder) FilteredCapacityPoolMap(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FilteredCapacityPoolMap", reflect.TypeOf((*MockAzure)(nil).FilteredCapacityPoolMap), arg0, arg1, arg2, arg3) +} + +// FilteredSubnetMap mocks base method. +func (m *MockAzure) FilteredSubnetMap(arg0 context.Context, arg1 []string, arg2, arg3 string) map[string]*api.Subnet { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "FilteredSubnetMap", arg0, arg1, arg2, arg3) + ret0, _ := ret[0].(map[string]*api.Subnet) + return ret0 +} + +// FilteredSubnetMap indicates an expected call of FilteredSubnetMap. +func (mr *MockAzureMockRecorder) FilteredSubnetMap(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FilteredSubnetMap", reflect.TypeOf((*MockAzure)(nil).FilteredSubnetMap), arg0, arg1, arg2, arg3) +} + // HasFeature mocks base method. func (m *MockAzure) HasFeature(arg0 string) bool { m.ctrl.T.Helper() diff --git a/operator/clients/factory.go b/operator/clients/factory.go index 4ed7c4975..55b2ff89d 100644 --- a/operator/clients/factory.go +++ b/operator/clients/factory.go @@ -7,6 +7,7 @@ import ( "os" "time" + snapshotClient "github.com/kubernetes-csi/external-snapshotter/client/v6/clientset/versioned" k8sversion "k8s.io/apimachinery/pkg/version" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" @@ -16,16 +17,19 @@ import ( k8sclient "github.com/netapp/trident/cli/k8s_client" commonconfig "github.com/netapp/trident/config" . "github.com/netapp/trident/logging" - "github.com/netapp/trident/operator/controllers/orchestrator/client/clientset/versioned" + "github.com/netapp/trident/operator/crd/client/clientset/versioned" + tridentClient "github.com/netapp/trident/persistent_store/crd/client/clientset/versioned" ) type Clients struct { - KubeConfig *rest.Config - KubeClient *kubernetes.Clientset - K8SClient k8sclient.KubernetesClient - CRDClient *versioned.Clientset - K8SVersion *k8sversion.Info - Namespace string + KubeConfig *rest.Config + KubeClient *kubernetes.Clientset + K8SClient k8sclient.KubernetesClient + CRDClient *versioned.Clientset + TridentCRDClient *tridentClient.Clientset + SnapshotClient *snapshotClient.Clientset + K8SVersion *k8sversion.Info + Namespace string } const k8sTimeout = 30 * time.Second @@ -52,12 +56,24 @@ func CreateK8SClients(apiServerIP, kubeConfigPath string) (*Clients, error) { return nil, err } - // Create the CRD client + // Create the Operator CRD client clients.CRDClient, err = versioned.NewForConfig(clients.KubeConfig) if err != nil { return nil, fmt.Errorf("could not initialize CRD client; %v", err) } + // Create the Trident CRD client + clients.TridentCRDClient, err = tridentClient.NewForConfig(clients.KubeConfig) + if err != nil { + return nil, fmt.Errorf("could not initialize Trident CRD client; %v", err) + } + + // Create the Snapshot CRD client + clients.SnapshotClient, err = snapshotClient.NewForConfig(clients.KubeConfig) + if err != nil { + return nil, fmt.Errorf("could not initialize Snapshot CRD client; %v", err) + } + // Get the Kubernetes server version clients.K8SVersion, err = clients.KubeClient.Discovery().ServerVersion() if err != nil { diff --git a/operator/clients/operator_crd.go b/operator/clients/operator_crd.go new file mode 100644 index 000000000..b3feb8170 --- /dev/null +++ b/operator/clients/operator_crd.go @@ -0,0 +1,68 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package clients + +import ( + "fmt" + "reflect" + + operatorV1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" + operatorClient "github.com/netapp/trident/operator/crd/client/clientset/versioned" +) + +type OperatorCRDClient struct { + client *operatorClient.Clientset +} + +func NewOperatorCRDClient(client *operatorClient.Clientset) OperatorCRDClientInterface { + return &OperatorCRDClient{client: client} +} + +func (oc *OperatorCRDClient) GetTconfCR(name string) (*operatorV1.TridentConfigurator, error) { + return oc.client.TridentV1().TridentConfigurators().Get(ctx, name, getOpts) +} + +func (oc *OperatorCRDClient) GetTconfCRList() (*operatorV1.TridentConfiguratorList, error) { + return oc.client.TridentV1().TridentConfigurators().List(ctx, listOpts) +} + +func (oc *OperatorCRDClient) GetTorcCRList() (*operatorV1.TridentOrchestratorList, error) { + return oc.client.TridentV1().TridentOrchestrators().List(ctx, listOpts) +} + +func (oc *OperatorCRDClient) GetControllingTorcCR() (*operatorV1.TridentOrchestrator, error) { + torcList, err := oc.client.TridentV1().TridentOrchestrators().List(ctx, listOpts) + if err != nil { + return nil, err + } + + for _, torc := range torcList.Items { + if torc.Status.Status == string(operatorV1.AppStatusInstalled) { + return &torc, nil + } + } + + return nil, fmt.Errorf("trident is not installed yet") +} + +func (oc *OperatorCRDClient) UpdateTridentConfiguratorStatus( + tconfCR *operatorV1.TridentConfigurator, newStatus operatorV1.TridentConfiguratorStatus, +) (*operatorV1.TridentConfigurator, bool, error) { + if reflect.DeepEqual(tconfCR.Status, newStatus) { + // Nothing to update + return tconfCR, false, nil + } + + tconfCRCopy := tconfCR.DeepCopy() + tconfCRCopy.Status = newStatus + + newTconfCR, err := oc.client.TridentV1().TridentConfigurators().UpdateStatus(ctx, tconfCRCopy, updateOpts) + if err != nil { + return tconfCR, true, err + } else { + newTconfCR.APIVersion = tconfCR.APIVersion + newTconfCR.Kind = tconfCR.Kind + } + + return newTconfCR, true, nil +} diff --git a/operator/clients/snapshot_crd.go b/operator/clients/snapshot_crd.go new file mode 100644 index 000000000..5612128e3 --- /dev/null +++ b/operator/clients/snapshot_crd.go @@ -0,0 +1,42 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package clients + +import ( + snapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1" + snapshotClient "github.com/kubernetes-csi/external-snapshotter/client/v6/clientset/versioned" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +type SnapshotCRDClient struct { + client *snapshotClient.Clientset +} + +func NewSnapshotCRDClient(client *snapshotClient.Clientset) SnapshotCRDClientInterface { + return &SnapshotCRDClient{client: client} +} + +func (sc *SnapshotCRDClient) CheckVolumeSnapshotClassExists(name string) (bool, error) { + if _, err := sc.GetVolumeSnapshotClass(name); err != nil { + if statusErr, ok := err.(*apierrors.StatusError); ok && statusErr.Status().Reason == metav1.StatusReasonNotFound { + return false, nil + } + return false, err + } + return true, nil +} + +func (sc *SnapshotCRDClient) GetVolumeSnapshotClass(name string) (*snapshotv1.VolumeSnapshotClass, error) { + return sc.client.SnapshotV1().VolumeSnapshotClasses().Get(ctx, name, getOpts) +} + +func (sc *SnapshotCRDClient) PatchVolumeSnapshotClass(name string, patchBytes []byte, patchType types.PatchType) error { + _, err := sc.client.SnapshotV1().VolumeSnapshotClasses().Patch(ctx, name, patchType, patchBytes, patchOpts) + return err +} + +func (sc *SnapshotCRDClient) DeleteVolumeSnapshotClass(name string) error { + return sc.client.SnapshotV1().VolumeSnapshotClasses().Delete(ctx, name, deleteOpts) +} diff --git a/operator/clients/trident_crd.go b/operator/clients/trident_crd.go new file mode 100644 index 000000000..fc22f87fe --- /dev/null +++ b/operator/clients/trident_crd.go @@ -0,0 +1,43 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package clients + +import ( + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + tridentV1 "github.com/netapp/trident/persistent_store/crd/apis/netapp/v1" + tridentClient "github.com/netapp/trident/persistent_store/crd/client/clientset/versioned" +) + +type TridentCRDClient struct { + client *tridentClient.Clientset +} + +func NewTridentCRDClient(client *tridentClient.Clientset) TridentCRDClientInterface { + return &TridentCRDClient{client: client} +} + +func (tc *TridentCRDClient) CheckTridentBackendConfigExists(name, namespace string) (bool, error) { + if _, err := tc.GetTridentBackendConfig(name, namespace); err != nil { + if statusErr, ok := err.(*apierrors.StatusError); ok && statusErr.Status().Reason == metav1.StatusReasonNotFound { + return false, nil + } + return false, err + } + return true, nil +} + +func (tc *TridentCRDClient) GetTridentBackendConfig(name, namespace string) (*tridentV1.TridentBackendConfig, error) { + return tc.client.TridentV1().TridentBackendConfigs(namespace).Get(ctx, name, getOpts) +} + +func (tc *TridentCRDClient) PatchTridentBackendConfig(name, namespace string, patchBytes []byte, patchType types.PatchType) error { + _, err := tc.client.TridentV1().TridentBackendConfigs(namespace).Patch(ctx, name, patchType, patchBytes, patchOpts) + return err +} + +func (tc *TridentCRDClient) DeleteTridentBackendConfig(name, namespace string) error { + return tc.client.TridentV1().TridentBackendConfigs(namespace).Delete(ctx, name, deleteOpts) +} diff --git a/operator/clients/types.go b/operator/clients/types.go new file mode 100644 index 000000000..2caf18089 --- /dev/null +++ b/operator/clients/types.go @@ -0,0 +1,50 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package clients + +import ( + "context" + + snapshotv1 "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + operatorV1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" + tridentV1 "github.com/netapp/trident/persistent_store/crd/apis/netapp/v1" +) + +//go:generate mockgen -destination=../../mocks/mock_operator/mock_clients/mock_api.go github.com/netapp/trident/operator/clients OperatorCRDClientInterface,TridentCRDClientInterface,SnapshotCRDClientInterface + +var ( + ctx = context.TODO() + + deleteOpts = metav1.DeleteOptions{} + getOpts = metav1.GetOptions{} + listOpts = metav1.ListOptions{} + patchOpts = metav1.PatchOptions{} + updateOpts = metav1.UpdateOptions{} +) + +type OperatorCRDClientInterface interface { + GetTconfCR(name string) (*operatorV1.TridentConfigurator, error) + GetTconfCRList() (*operatorV1.TridentConfiguratorList, error) + GetTorcCRList() (*operatorV1.TridentOrchestratorList, error) + GetControllingTorcCR() (*operatorV1.TridentOrchestrator, error) + UpdateTridentConfiguratorStatus( + tconfCR *operatorV1.TridentConfigurator, newStatus operatorV1.TridentConfiguratorStatus, + ) (*operatorV1.TridentConfigurator, bool, error) +} + +type TridentCRDClientInterface interface { + CheckTridentBackendConfigExists(name, namespace string) (bool, error) + GetTridentBackendConfig(name, namespace string) (*tridentV1.TridentBackendConfig, error) + PatchTridentBackendConfig(name, namespace string, patchBytes []byte, patchType types.PatchType) error + DeleteTridentBackendConfig(name, namespace string) error +} + +type SnapshotCRDClientInterface interface { + CheckVolumeSnapshotClassExists(name string) (bool, error) + GetVolumeSnapshotClass(name string) (*snapshotv1.VolumeSnapshotClass, error) + PatchVolumeSnapshotClass(name string, patchBytes []byte, patchType types.PatchType) error + DeleteVolumeSnapshotClass(name string) error +} diff --git a/operator/config/config.go b/operator/config/config.go index 82510503f..5156c0654 100644 --- a/operator/config/config.go +++ b/operator/config/config.go @@ -4,6 +4,7 @@ package config import ( "fmt" + "time" "github.com/netapp/trident/config" versionutils "github.com/netapp/trident/utils/version" @@ -21,6 +22,9 @@ const ( /* Misc. orchestrator constants */ OperatorName = "trident-operator" operatorVersion = config.DefaultOrchestratorVersion + + // ConfiguratorReconcileInterval is the resource refresh rate for the auto generated backends. + ConfiguratorReconcileInterval time.Duration = 30 * time.Minute ) var ( diff --git a/operator/controllers/configurator/clients/configurator.go b/operator/controllers/configurator/clients/configurator.go new file mode 100644 index 000000000..695ddb61e --- /dev/null +++ b/operator/controllers/configurator/clients/configurator.go @@ -0,0 +1,217 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package clients + +import ( + "encoding/json" + "fmt" + "strings" + + jsonPatch "github.com/evanphx/json-patch/v5" + "github.com/ghodss/yaml" + "k8s.io/apimachinery/pkg/types" + + k8sClient "github.com/netapp/trident/cli/k8s_client" + . "github.com/netapp/trident/logging" + "github.com/netapp/trident/operator/clients" + operatorV1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" + tridentV1 "github.com/netapp/trident/persistent_store/crd/apis/netapp/v1" +) + +const ( + ANFClientID = "ClientID" + ANFClientSecret = "ClientSecret" +) + +type ConfiguratorClient struct { + kClient ExtendedK8sClientInterface + tClient clients.TridentCRDClientInterface + sClient clients.SnapshotCRDClientInterface + oClient clients.OperatorCRDClientInterface +} + +func NewConfiguratorClient( + kClient ExtendedK8sClientInterface, tClient clients.TridentCRDClientInterface, + sClient clients.SnapshotCRDClientInterface, oClient clients.OperatorCRDClientInterface, +) ConfiguratorClientInterface { + return &ConfiguratorClient{kClient: kClient, tClient: tClient, sClient: sClient, oClient: oClient} +} + +func (c *ConfiguratorClient) CreateOrPatchObject(objType ObjectType, objName, objNamespace, objYAML string) error { + objExists, err := c.checkObjectExists(objType, objName, objNamespace) + if err != nil { + return err + } + + if !objExists { + Log().Debugf("Creating %s %s.", objName, objType) + return c.kClient.CreateObjectByYAML(objYAML) + } + + obj, err := c.getObject(objType, objName, objNamespace) + if err != nil { + return err + } + + patchBytes, err := c.getPatch(objType, obj, objYAML) + if err != nil { + return err + } + + if err := c.patchObject(objType, objName, objNamespace, patchBytes); err == nil { + Log().Debugf("Patched %s %s", objName, objType) + return nil + } else { + Log().Errorf("Patch failed for %s %s: %v", objName, objType, err) + } + + if err := c.deleteObject(objType, objName, objNamespace); err != nil { + return err + } + + Log().Debugf("Creating %s %s after deleting it.", objName, objType) + return c.kClient.CreateObjectByYAML(objYAML) +} + +func (c *ConfiguratorClient) UpdateTridentConfiguratorStatus( + tconfCR *operatorV1.TridentConfigurator, newStatus operatorV1.TridentConfiguratorStatus, +) (*operatorV1.TridentConfigurator, bool, error) { + return c.oClient.UpdateTridentConfiguratorStatus(tconfCR, newStatus) +} + +func (c *ConfiguratorClient) checkObjectExists(objType ObjectType, objName, objNamespace string) (bool, error) { + switch objType { + case OCRD: + return c.kClient.CheckCRDExists(objName) + case OBackend: + return c.tClient.CheckTridentBackendConfigExists(objName, objNamespace) + case OStorageClass: + return c.kClient.CheckStorageClassExists(objName) + case OSnapshotClass: + return c.sClient.CheckVolumeSnapshotClassExists(objName) + } + + return false, fmt.Errorf("unsupported object %s of type %s", objName, objType) +} + +func (c *ConfiguratorClient) getObject(objType ObjectType, objName, objNamespace string) (interface{}, error) { + switch objType { + case OCRD: + return c.kClient.GetCRD(objName) + case OBackend: + return c.tClient.GetTridentBackendConfig(objName, objNamespace) + case OStorageClass: + return c.kClient.GetStorageClass(objName) + case OSnapshotClass: + return c.sClient.GetVolumeSnapshotClass(objName) + } + + return nil, fmt.Errorf("unsupported object %s of type %s", objName, objType) +} + +func (c *ConfiguratorClient) getPatch(objType ObjectType, obj interface{}, newObjYAML string) ([]byte, error) { + // For TBC spec, few fields may get added/removed with 'helm upgrade'. This needs special handling at TBC.Spec level. + if objType == OBackend { + emptyPatch := []byte("{}") + oldObj, ok := obj.(*tridentV1.TridentBackendConfig) + if ok { + oldSpecBytes, err := json.Marshal(oldObj.Spec) + if err != nil { + return emptyPatch, err + } + + newObj := tridentV1.TridentBackendConfig{} + if err := yaml.Unmarshal([]byte(newObjYAML), &newObj); err != nil { + return emptyPatch, err + } + newSpecBytes, err := json.Marshal(newObj.Spec) + if err != nil { + return emptyPatch, err + } + + // Getting the Spec difference between old TBC and new TBC. + patch, err := jsonPatch.CreateMergePatch(oldSpecBytes, newSpecBytes) + if err != nil { + return emptyPatch, err + } + + if len(patch) > 2 { + newPatch := "{\"spec\": " + string(patch) + "}" + return []byte(newPatch), nil + } else { + return emptyPatch, nil + } + } else { + return emptyPatch, fmt.Errorf("wrong object type in getPatch") + } + } + + // We can use k8sClient.GenericPatch for other objects as it combines the old and new objects into one. And + // currently, these objects have almost static fields. + return k8sClient.GenericPatch(obj, []byte(newObjYAML)) +} + +func (c *ConfiguratorClient) patchObject(objType ObjectType, objName, objNamespace string, patchBytes []byte) error { + switch objType { + case OCRD: + return c.kClient.PatchCRD(objName, patchBytes, types.MergePatchType) + case OBackend: + return c.tClient.PatchTridentBackendConfig(objName, objNamespace, patchBytes, types.MergePatchType) + case OStorageClass: + return c.kClient.PatchStorageClass(objName, patchBytes, types.StrategicMergePatchType) + case OSnapshotClass: + return c.sClient.PatchVolumeSnapshotClass(objName, patchBytes, types.MergePatchType) + } + + return fmt.Errorf("unsupported object %s of type %s", objName, objType) +} + +func (c *ConfiguratorClient) deleteObject(objType ObjectType, objName, objNamespace string) error { + switch objType { + case OCRD: + return c.kClient.DeleteCRD(objName) + case OBackend: + return c.tClient.DeleteTridentBackendConfig(objName, objNamespace) + case OStorageClass: + return c.kClient.DeleteStorageClass(objName) + case OSnapshotClass: + return c.sClient.DeleteVolumeSnapshotClass(objName) + } + + return fmt.Errorf("unsupported object %s of type %s", objName, objType) +} + +func (c *ConfiguratorClient) GetControllingTorcCR() (*operatorV1.TridentOrchestrator, error) { + return c.oClient.GetControllingTorcCR() +} + +func (c *ConfiguratorClient) GetTconfCR(name string) (*operatorV1.TridentConfigurator, error) { + return c.oClient.GetTconfCR(name) +} + +func (c *ConfiguratorClient) GetANFSecrets(secretName string) (string, string, error) { + secret, err := c.kClient.GetSecret(secretName) + if err != nil { + return "", "", err + } + + secretMap := make(map[string]string) + for key, value := range secret.Data { + secretMap[strings.ToLower(key)] = string(value) + } + for key, value := range secret.StringData { + secretMap[strings.ToLower(key)] = value + } + + clientID, ok := secretMap[strings.ToLower(ANFClientID)] + if !ok { + return "", "", fmt.Errorf("client id not present in secret") + } + + clientSecret, ok := secretMap[strings.ToLower(ANFClientSecret)] + if !ok { + return "", "", fmt.Errorf("client secret not present in secret") + } + + return clientID, clientSecret, nil +} diff --git a/operator/controllers/configurator/clients/extended_k8s.go b/operator/controllers/configurator/clients/extended_k8s.go new file mode 100644 index 000000000..9de2b4c62 --- /dev/null +++ b/operator/controllers/configurator/clients/extended_k8s.go @@ -0,0 +1,71 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package clients + +import ( + "fmt" + "time" + + v1 "k8s.io/api/storage/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + + k8sclient "github.com/netapp/trident/cli/k8s_client" +) + +// TODO(sphadnis): Combine this Extended client with orchestrator extended client + +type K8sClient struct { + k8sclient.KubernetesClient + KubeClient *kubernetes.Clientset +} + +func NewExtendedK8sClient( + config *rest.Config, namespace string, timeout int, client *kubernetes.Clientset, +) (ExtendedK8sClientInterface, error) { + if client == nil { + return nil, fmt.Errorf("invalid k8s clientset") + } + + if timeout <= 0 { + k8sTimeout = DefaultK8sClientTimeout + } + k8sTimeout = time.Duration(timeout) * time.Second + + // Create the Kubernetes client + kubeClient, err := k8sclient.NewKubeClient(config, namespace, k8sTimeout) + if err != nil { + return nil, fmt.Errorf("failed to initialize Kubernetes client; %v", err) + } + + return &K8sClient{ + KubernetesClient: kubeClient, + KubeClient: client, + }, nil +} + +func (kc *K8sClient) CheckStorageClassExists(name string) (bool, error) { + if _, err := kc.GetStorageClass(name); err != nil { + if statusErr, ok := err.(*apierrors.StatusError); ok && statusErr.Status().Reason == metav1.StatusReasonNotFound { + return false, nil + } + return false, err + } + return true, nil +} + +func (kc *K8sClient) GetStorageClass(name string) (*v1.StorageClass, error) { + return kc.KubeClient.StorageV1().StorageClasses().Get(ctx, name, getOpts) +} + +func (kc *K8sClient) PatchStorageClass(name string, patchBytes []byte, patchType types.PatchType) error { + _, err := kc.KubeClient.StorageV1().StorageClasses().Patch(ctx, name, patchType, patchBytes, patchOpts) + return err +} + +func (kc *K8sClient) DeleteStorageClass(name string) error { + return kc.KubeClient.StorageV1().StorageClasses().Delete(ctx, name, deleteOpts) +} diff --git a/operator/controllers/configurator/clients/types.go b/operator/controllers/configurator/clients/types.go new file mode 100644 index 000000000..3339e0a01 --- /dev/null +++ b/operator/controllers/configurator/clients/types.go @@ -0,0 +1,59 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package clients + +import ( + "context" + "time" + + v1 "k8s.io/api/storage/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + + k8sclient "github.com/netapp/trident/cli/k8s_client" + operatorV1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" +) + +//go:generate mockgen -destination=../../../../mocks/mock_operator/mock_controllers/mock_configurator/mock_clients/mock_api.go github.com/netapp/trident/operator/controllers/configurator/clients ConfiguratorClientInterface,ExtendedK8sClientInterface + +const DefaultK8sClientTimeout = 30 + +var ( + k8sTimeout time.Duration + + ctx = context.TODO() + + deleteOpts = metav1.DeleteOptions{} + getOpts = metav1.GetOptions{} + listOpts = metav1.ListOptions{} + patchOpts = metav1.PatchOptions{} + updateOpts = metav1.UpdateOptions{} +) + +type ObjectType string + +const ( + OCRD ObjectType = "CRD" + OBackend ObjectType = "Backend" + OStorageClass ObjectType = "StorageClass" + OSnapshotClass ObjectType = "SnapshotClass" +) + +type ConfiguratorClientInterface interface { + CreateOrPatchObject(objType ObjectType, objName, objNamespace, objYAML string) error + UpdateTridentConfiguratorStatus( + tconfCR *operatorV1.TridentConfigurator, newStatus operatorV1.TridentConfiguratorStatus, + ) (*operatorV1.TridentConfigurator, bool, error) + GetControllingTorcCR() (*operatorV1.TridentOrchestrator, error) + GetTconfCR(name string) (*operatorV1.TridentConfigurator, error) + GetANFSecrets(secretName string) (string, string, error) +} + +type ExtendedK8sClientInterface interface { + k8sclient.KubernetesClient + + CheckStorageClassExists(name string) (bool, error) + GetStorageClass(name string) (*v1.StorageClass, error) + PatchStorageClass(name string, patchBytes []byte, patchType types.PatchType) error + DeleteStorageClass(name string) error +} diff --git a/operator/controllers/configurator/controller.go b/operator/controllers/configurator/controller.go new file mode 100644 index 000000000..57008f3b2 --- /dev/null +++ b/operator/controllers/configurator/controller.go @@ -0,0 +1,622 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package configurator + +import ( + "context" + "fmt" + "reflect" + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/apimachinery/pkg/watch" + clientv1 "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/tools/record" + "k8s.io/client-go/util/workqueue" + + k8sclient "github.com/netapp/trident/cli/k8s_client" + "github.com/netapp/trident/config" + . "github.com/netapp/trident/logging" + "github.com/netapp/trident/operator/clients" + confClients "github.com/netapp/trident/operator/controllers/configurator/clients" + "github.com/netapp/trident/operator/controllers/configurator/storage_drivers" + netappv1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" + operatorV1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" + "github.com/netapp/trident/operator/crd/client/clientset/versioned/scheme" + "github.com/netapp/trident/utils/errors" +) + +const ( + ControllerName = "Trident Configurator" + ControllerVersion = "0.1" + CRDName = "TridentConfigurator" + Operator = "trident-operator.netapp.io" + + TridentConfiguratorCRDName = "tridentconfigurators.trident.netapp.io" +) + +var ctx = context.TODO + +type Controller struct { + Clients confClients.ConfiguratorClientInterface + + eventRecorder record.EventRecorder + + configuratorIndexer cache.Indexer + configuratorInformer cache.SharedIndexInformer + configuratorWatcher cache.ListerWatcher + + stopChan chan struct{} + + // workqueue is a rate limited work queue. This is used to queue work to be + // processed instead of performing it as soon as a change happens. This + // means we can ensure we only process a fixed amount of resources at a + // time, and makes it easy to ensure we are never processing the same item + // simultaneously in two different workers. + workqueue workqueue.RateLimitingInterface +} + +func NewController(clientFactory *clients.Clients, cacheRefreshPeriod time.Duration) (*Controller, error) { + kClient, err := confClients.NewExtendedK8sClient(clientFactory.KubeConfig, "trident", + 0, clientFactory.KubeClient) + if err != nil { + return nil, err + } + + c := &Controller{ + Clients: confClients.NewConfiguratorClient(kClient, + clients.NewTridentCRDClient(clientFactory.TridentCRDClient), + clients.NewSnapshotCRDClient(clientFactory.SnapshotClient), + clients.NewOperatorCRDClient(clientFactory.CRDClient)), + stopChan: make(chan struct{}), + workqueue: workqueue.NewRateLimitingQueueWithConfig(workqueue.DefaultControllerRateLimiter(), + workqueue.RateLimitingQueueConfig{Name: CRDName}), + } + + // Add our types to the default Kubernetes Scheme so Events can be logged. + utilruntime.Must(scheme.AddToScheme(scheme.Scheme)) + + // Set up event broadcaster + broadcaster := record.NewBroadcaster() + broadcaster.StartRecordingToSink(&clientv1.EventSinkImpl{Interface: clientFactory.KubeClient.CoreV1().Events("")}) + c.eventRecorder = broadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: Operator}) + + // Set up a watch for TridentConfigurator CRs + c.configuratorWatcher = &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + return clientFactory.CRDClient.TridentV1().TridentConfigurators().List(ctx(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + return clientFactory.CRDClient.TridentV1().TridentConfigurators().Watch(ctx(), options) + }, + } + + // Set up the CR indexing controller + c.configuratorInformer = cache.NewSharedIndexInformer( + c.configuratorWatcher, + &netappv1.TridentConfigurator{}, + cacheRefreshPeriod, + cache.Indexers{}, + ) + c.configuratorIndexer = c.configuratorInformer.GetIndexer() + + // Add handlers for TridentConfigurator CRs + _, _ = c.configuratorInformer.AddEventHandler( + cache.ResourceEventHandlerFuncs{ + AddFunc: c.addConfigurator, + UpdateFunc: c.updateConfigurator, + DeleteFunc: c.deleteConfigurator, + }, + ) + + return c, nil +} + +// Activate controller. +func (c *Controller) Activate() error { + Log().WithField("Controller", ControllerName).Infof("Activating controller.") + + // The reason we have this here is to ensure that by the time Trident Orchestrator's List and Watcher + // start they do not throw any error for unable to list/watch this CRD. + if err := c.ensureTridentConfiguratorCRDExists(); err != nil { + Log().WithField("err", err).Warnf("Unable to ensure TridentOrchestrator exist.") + } + + go c.configuratorInformer.Run(c.stopChan) + + Log().Info("Starting workers") + go wait.Until(c.runWorker, time.Second, c.stopChan) + + Log().Info("Started workers") + + return nil +} + +// Deactivate controller. +func (c *Controller) Deactivate() error { + Log().WithField("Controller", ControllerName).Infof("Deactivating controller.") + + close(c.stopChan) + + c.workqueue.ShutDown() + utilruntime.HandleCrash() + return nil +} + +// GetName returns controller name. +func (c *Controller) GetName() string { + return ControllerName +} + +// Version returns the controller version. +func (c *Controller) Version() string { + return ControllerVersion +} + +// runWorker is a long-running function that will continually call the +// processNextWorkItem function in order to read and process a message on the +// workqueue. +func (c *Controller) runWorker() { + for c.processNextWorkItem() { + } +} + +// processNextWorkItem will read a single work item off the workqueue and +// attempt to process it, by calling the syncHandler. +func (c *Controller) processNextWorkItem() bool { + obj, shutdown := c.workqueue.Get() + + if shutdown { + return false + } + + // We wrap this block in a func so we can defer c.workqueue.Done. + err := func(obj interface{}) error { + // We call Done here so the workqueue knows we have finished + // processing this item. We also must remember to call Forget if we + // do not want this work item being re-queued. For example, we do + // not call Forget if a transient error occurs, instead the item is + // put back on the workqueue and attempted again after a back-off + // period. + defer c.workqueue.Done(obj) + var keyItem string + var ok bool + // We expect KeyItem to come off the workqueue. We do this as the + // delayed nature of the workqueue means the items in the informer + // cache may actually be more up to date that when the item was + // initially put onto the workqueue. + if keyItem, ok = obj.(string); !ok { + // As the item in the workqueue is actually invalid, we call + // Forget here else we'd go into a loop of attempting to + // process a work item that is invalid. + c.workqueue.Forget(obj) + Log().Errorf("expected string in workqueue but got %#v", obj) + return nil + } + // Run the reconcile, passing it the keyItems struct to be synced. + if err := c.reconcile(keyItem); err != nil { + // Put the item back on the workqueue to handle any transient errors. + if errors.IsUnsupportedConfigError(err) { + errMessage := fmt.Sprintf("found unsupported configuration, "+ + "needs manual intervention to fix the issue;"+ + "error syncing tconf '%s': %s, not requeuing", keyItem, err.Error()) + + c.workqueue.Forget(keyItem) + + Log().Errorf(errMessage) + Log().Info("-------------------------------------------------") + Log().Info("-------------------------------------------------") + + return fmt.Errorf(errMessage) + } else if errors.IsNotFoundError(err) { + errMessage := fmt.Sprintf("resource not found, needs manual intervention to fix it;"+ + "error syncing tconf '%s': %s, not requeuing", keyItem, err.Error()) + + c.workqueue.Forget(keyItem) + + Log().Errorf(errMessage) + Log().Info("-------------------------------------------------") + Log().Info("-------------------------------------------------") + + return fmt.Errorf(errMessage) + } else if errors.IsReconcileIncompleteError(err) { + c.workqueue.Add(keyItem) + } else { + c.workqueue.AddRateLimited(keyItem) + } + + errMessage := fmt.Sprintf("error syncing tconf '%s': %s, requeuing", keyItem, err.Error()) + Log().Errorf(errMessage) + Log().Info("-------------------------------------------------") + Log().Info("-------------------------------------------------") + + return fmt.Errorf(errMessage) + } + // Finally, if no error occurs we Forget this item so it does not + // get queued again until another change happens. + c.workqueue.Forget(obj) + Log().Infof("Synced TridentConfigurator '%s'", keyItem) + Log().Info("-------------------------------------------------") + Log().Info("-------------------------------------------------") + + return nil + }(obj) + if err != nil { + Log().Error(err) + return true + } + + return true +} + +// addConfigurator is the add handler for the TridentConfigurator watcher. +func (c *Controller) addConfigurator(obj interface{}) { + var key string + var err error + + if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil { + Log().Error(err) + return + } + + // Convert the namespace/name string into a distinct namespace and name + _, name, err := cache.SplitMetaNamespaceKey(key) + if err != nil { + Log().Errorf("invalid resource key: %s", key) + return + } + + Log().WithFields(LogFields{ + "CR": name, + "CRD": CRDName, + }).Infof("CR added.") + + c.workqueue.Add(key) +} + +// updateConfigurator is the update handler for the TridentConfigurator watcher. +func (c *Controller) updateConfigurator(oldObj, newObj interface{}) { + oldCR, ok := oldObj.(*netappv1.TridentConfigurator) + if !ok { + Log().Errorf("'%s' controller expected '%s' CR; got '%v'", ControllerName, CRDName, oldObj) + return + } + + newCR, ok := newObj.(*netappv1.TridentConfigurator) + if !ok { + Log().Errorf("'%s' controller expected '%s' CR; got '%v'", ControllerName, CRDName, newObj) + return + } + + if !newCR.ObjectMeta.DeletionTimestamp.IsZero() { + Log().WithFields(LogFields{ + "name": newCR.Name, + "deletionTimestamp": newCR.ObjectMeta.DeletionTimestamp, + }).Infof("'%s' CR is being deleted, not updated.", CRDName) + return + } + + if !reflect.DeepEqual(oldCR.Status, newCR.Status) { + // Update request comes when we UpdateStatus of tconfCR + Log().Debug("Update request came for tconfCR after we updated its status; this doesn't need processing; skipping") + return + } + + var key string + var err error + + if key, err = cache.MetaNamespaceKeyFunc(newObj); err != nil { + Log().Error(err) + return + } + + Log().WithFields(LogFields{ + "CR": newCR.Name, + "CRD": CRDName, + }).Infof("CR updated.") + + c.workqueue.Add(key) +} + +// deleteConfigurator is the delete handler for the TridentConfigurator watcher. +func (c *Controller) deleteConfigurator(obj interface{}) { + var key string + var err error + + if key, err = cache.MetaNamespaceKeyFunc(obj); err != nil { + Log().Error(err) + return + } + + // Convert the namespace/name string into a distinct namespace and name + _, name, err := cache.SplitMetaNamespaceKey(key) + if err != nil { + Log().Errorf("invalid resource key: '%s'", key) + return + } + + Log().WithFields(LogFields{ + "CR": name, + "CRD": CRDName, + }).Infof("CR deleted.") + + c.workqueue.Add(key) +} + +// reconcile runs the reconcile logic and ensures we move to the desired state and the desired state is +// maintained +func (c *Controller) reconcile(keyItem string) error { + Log().Infof("Reconcile request came for TridentConfigurator CR %s", keyItem) + // Get Controlling Trident Orchestrator CR and wait till trident is installed. + torcCR, err := c.Clients.GetControllingTorcCR() + if err != nil { + Log().Error("Failed to get controlling torcCR", err) + return err + } + + _, tconfCRName, err := cache.SplitMetaNamespaceKey(keyItem) + if err != nil { + Log().Errorf("Invalid resource key: '%s'", keyItem) + return err + } + + tconfCR, err := c.Clients.GetTconfCR(tconfCRName) + if err != nil { + Log().Error("Failed to get tconfCR: ", err) + return errors.NotFoundError(err.Error()) + } + + if err = tconfCR.Validate(); err != nil { + Log().Error("Invalid tconfCR: ", err) + return err + } + + driverName, err := tconfCR.GetStorageDriverName() + if err != nil { + Log().Error("Failed to get storage driver name: ", err) + return err + } + + switch driverName { + case config.AzureNASStorageDriverName: + anf, err := storage_drivers.NewANFInstance(torcCR, tconfCR, c.Clients) + if err != nil { + Log().Info("Failed to create ANF backend instance: ", err) + return err + } + if err := c.ProcessBackend(anf, tconfCR); err != nil { + Log().Error("Failed to process ANF backend: ", err) + return err + } + default: + return fmt.Errorf("backend not supported") + } + + return nil +} + +// ensureTridentConfiguratorCRDExists creates TridentConfigurator CRD if it doesn't exist. +func (c *Controller) ensureTridentConfiguratorCRDExists() error { + if err := c.Clients.CreateOrPatchObject(confClients.OCRD, TridentConfiguratorCRDName, + "", k8sclient.GetConfiguratorCRDYAML()); err != nil { + Log().Error("Failed to create/patch TConf CRD", err) + return err + } + + return nil +} + +// ProcessBackend does validate backend, create backend, create storage class and create snapshot class operations +// on the trident configurator CR in phases. +func (c *Controller) ProcessBackend(backend storage_drivers.Backend, tconfCR *operatorV1.TridentConfigurator) error { + if tconfCR == nil { + return fmt.Errorf("invalid trident configurator CR") + } + + currentPhase := operatorV1.TConfPhase("") + currentStatus := operatorV1.Processing + var processErr, updateErr error + cProvider := backend.GetCloudProvider() + + for currentStatus == operatorV1.Processing { + currentPhase = c.getNextProcessingPhase(currentPhase) + + switch currentPhase { + case operatorV1.ValidatingConfig: + tconfCR, processErr, updateErr = c.backendGenericOperation(tconfCR, currentPhase, backend.Validate, cProvider) + if processErr != nil { + Log().Error("Backend config validation failed", processErr) + return errors.UnsupportedConfigError(processErr.Error()) + } + if updateErr != nil { + Log().Error("Updating backend config validation status failed", updateErr) + return updateErr + } + case operatorV1.CreatingBackend: + tconfCR, processErr, updateErr = c.backendCreateOperation(tconfCR, currentPhase, backend.Create, cProvider) + if processErr != nil { + Log().Error("Backend creation failed", processErr) + return processErr + } + if updateErr != nil { + Log().Error("Updating backend creation status failed", updateErr) + return updateErr + } + case operatorV1.CreatingSC: + tconfCR, processErr, updateErr = c.backendGenericOperation(tconfCR, currentPhase, backend.CreateStorageClass, + cProvider) + if processErr != nil { + Log().Error("Backend storage class creation failed", processErr) + return processErr + } + if updateErr != nil { + Log().Error("Updating TConf status for backend storage class failed", updateErr) + return updateErr + } + case operatorV1.CreatingSnapClass: + tconfCR, processErr, updateErr = c.backendGenericOperation(tconfCR, currentPhase, backend.CreateSnapshotClass, + cProvider) + if processErr != nil { + Log().Error("Backend snapshot class creation failed", processErr) + return processErr + } + if updateErr != nil { + Log().Error("Updating TConf status for backend snapshot class failed", updateErr) + return updateErr + } + currentStatus = operatorV1.Success + default: + Log().Error("Encountered incorrect processing phase.") + return fmt.Errorf("encountered incorrect processing phase; exiting ProcessBackend") + } + } + + return nil +} + +// backendGenericOperation does operationFunc and updates tconfCR status accordingly. +// This function is common for Backends.Validate(), Backends.CreateStorageClass(), Backends.CreateSnapshotClass(). +func (c *Controller) backendGenericOperation( + tconfCR *operatorV1.TridentConfigurator, currPhase operatorV1.TConfPhase, + operationFunc func() error, cloudProvider string, +) (newTconfCR *operatorV1.TridentConfigurator, operationErr, updateErr error) { + newTconfCR, updateErr = c.updateEventAndStatus(tconfCR, currPhase, nil, cloudProvider, tconfCR.Status.BackendNames) + if updateErr != nil { + return + } + + operationErr = operationFunc() + + newPhase := c.getProcessedPhase(currPhase) + newTconfCR, updateErr = c.updateEventAndStatus(newTconfCR, newPhase, operationErr, cloudProvider, newTconfCR.Status.BackendNames) + return +} + +// backendCreateOperation does operationFunc and updates tconfCR status accordingly. +// This function is implemented for Backends.Create(). +func (c *Controller) backendCreateOperation( + tconfCR *operatorV1.TridentConfigurator, currPhase operatorV1.TConfPhase, + operationFunc func() ([]string, error), cloudProvider string, +) (newTconfCR *operatorV1.TridentConfigurator, operationErr, updateErr error) { + newTconfCR, updateErr = c.updateEventAndStatus(tconfCR, currPhase, nil, cloudProvider, tconfCR.Status.BackendNames) + if updateErr != nil { + return + } + + backendNames, operationErr := operationFunc() + + newPhase := c.getProcessedPhase(currPhase) + newTconfCR, updateErr = c.updateEventAndStatus(newTconfCR, newPhase, operationErr, cloudProvider, backendNames) + return +} + +// updateEventAndStatus updates events and status of trident configurator CR. +func (c *Controller) updateEventAndStatus( + tconfCR *operatorV1.TridentConfigurator, currentPhase operatorV1.TConfPhase, + operationError error, cloudProvider string, backendNames []string, +) (*operatorV1.TridentConfigurator, error) { + newStatus := c.getNewConfiguratorStatus(currentPhase, tconfCR.Status.Phase, operationError, cloudProvider, backendNames) + + newTconfCR, updateEvent, err := c.Clients.UpdateTridentConfiguratorStatus(tconfCR, newStatus) + if err != nil { + return newTconfCR, err + } + + c.updateTridentConfiguratorEvent(newTconfCR, operationError, updateEvent) + + return newTconfCR, nil +} + +// updateTridentConfiguratorEvent updates the events for TConf object in event recorder. +func (c *Controller) updateTridentConfiguratorEvent( + tconfCR *operatorV1.TridentConfigurator, updateError error, updateEvent bool, +) { + if updateError != nil { + c.eventRecorder.Event(tconfCR, corev1.EventTypeWarning, tconfCR.Status.LastOperationStatus, tconfCR.Status.Message) + return + } + if updateEvent { + c.eventRecorder.Event(tconfCR, corev1.EventTypeNormal, tconfCR.Status.LastOperationStatus, tconfCR.Status.Message) + return + } +} + +// getNewConfiguratorStatus returns the new configurator status that we update on the CR. +// We set LastOperationStatus as success when we reach operatorV1.Done phase without errors. +// If any error occurs, we return the LastOperationStatus as failed. +func (c *Controller) getNewConfiguratorStatus( + currentPhase operatorV1.TConfPhase, lastPhase string, err error, cloudProvider string, backendNames []string, +) operatorV1.TridentConfiguratorStatus { + newStatus := operatorV1.TridentConfiguratorStatus{ + BackendNames: backendNames, + Phase: string(currentPhase), + LastOperationStatus: string(operatorV1.Processing), + CloudProvider: cloudProvider, + } + + if err != nil { + newStatus.Message = fmt.Sprintf("Failed: %v", err) + newStatus.Phase = lastPhase + newStatus.LastOperationStatus = string(operatorV1.Failed) + return newStatus + } + + switch currentPhase { + case operatorV1.ValidatingConfig: + newStatus.Message = "Validating backend configuration" + case operatorV1.ValidatedConfig: + newStatus.Message = "Provided backend configuration is correct" + case operatorV1.CreatingBackend: + newStatus.Message = "Creating backend with the provided configuration" + case operatorV1.CreatedBackend: + newStatus.Message = "Backend creation successful" + case operatorV1.CreatingSC: + newStatus.Message = "Creating storage classes for the backend" + case operatorV1.CreatedSC: + newStatus.Message = "Storage class creation successful" + case operatorV1.CreatingSnapClass: + newStatus.Message = "Validating backend configuration" + case operatorV1.Done: + newStatus.Message = "Completed Trident backend configuration" + newStatus.LastOperationStatus = string(operatorV1.Success) + } + + return newStatus +} + +// getNextProcessingPhase returns the next phase that needs to be processed. +func (c *Controller) getNextProcessingPhase(currPhase operatorV1.TConfPhase) operatorV1.TConfPhase { + switch currPhase { + case operatorV1.ValidatingConfig: + return operatorV1.CreatingBackend + case operatorV1.CreatingBackend: + return operatorV1.CreatingSC + case operatorV1.CreatingSC: + return operatorV1.CreatingSnapClass + default: + // When we start processing tconfCR, we send it's currPhase as empty. + return operatorV1.ValidatingConfig + } +} + +// getProcessedPhase returns the corresponding done phase for the given processing phase. +// This function should always be called with an "ing" Phase to get the correct processed phase. +func (c *Controller) getProcessedPhase(currPhase operatorV1.TConfPhase) operatorV1.TConfPhase { + switch currPhase { + case operatorV1.ValidatingConfig: + return operatorV1.ValidatedConfig + case operatorV1.CreatingBackend: + return operatorV1.CreatedBackend + case operatorV1.CreatingSC: + return operatorV1.CreatedSC + case operatorV1.CreatingSnapClass: + return operatorV1.Done + default: + return "" + } +} diff --git a/operator/controllers/configurator/controller_test.go b/operator/controllers/configurator/controller_test.go new file mode 100644 index 000000000..d32406830 --- /dev/null +++ b/operator/controllers/configurator/controller_test.go @@ -0,0 +1,17 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package configurator + +import ( + "io" + "os" + "testing" + + . "github.com/netapp/trident/logging" +) + +func TestMain(m *testing.M) { + // Disable any standard log output + InitLogOutput(io.Discard) + os.Exit(m.Run()) +} diff --git a/operator/controllers/configurator/storage_drivers/anf.go b/operator/controllers/configurator/storage_drivers/anf.go new file mode 100644 index 000000000..69a5f05c1 --- /dev/null +++ b/operator/controllers/configurator/storage_drivers/anf.go @@ -0,0 +1,339 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package storage_drivers + +import ( + "context" + "encoding/json" + "fmt" + "os" + "strings" + + "sigs.k8s.io/cloud-provider-azure/pkg/azclient" + + k8sclient "github.com/netapp/trident/cli/k8s_client" + "github.com/netapp/trident/config" + . "github.com/netapp/trident/logging" + confClients "github.com/netapp/trident/operator/controllers/configurator/clients" + operatorV1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" + sa "github.com/netapp/trident/storage_attribute" + "github.com/netapp/trident/storage_drivers/azure/api" +) + +type ANF struct { + ANFConfig + + AZClient api.Azure + ConfClient confClients.ConfiguratorClientInterface + + FilteredCapacityPoolMap map[string]*api.CapacityPool + FilteredSubnetMap map[string]*api.Subnet + + AMIEnabled bool + WorkloadIdentityEnabled bool + TBCNamePrefix string + TridentNamespace string +} + +type ANFConfig struct { + // Access related + SubscriptionID string `json:"subscriptionID"` + TenantID string `json:"tenantID"` + Location string `json:"location"` + ClientID string `json:"clientID"` + ClientSecret string `json:"clientSecret"` + ClientCredentials string `json:"clientCredentials"` // Client credential secret name. + + // Filters + CapacityPools []string `json:"capacityPools"` + NetappAccounts []string `json:"netappAccounts"` + ResourceGroups []string `json:"resourceGroups"` + VirtualNetwork string `json:"virtualNetwork"` + Subnet string `json:"subnet"` +} + +func NewANFInstance( + torcCR *operatorV1.TridentOrchestrator, configuratorCR *operatorV1.TridentConfigurator, + client confClients.ConfiguratorClientInterface, +) (*ANF, error) { + if torcCR == nil { + return nil, fmt.Errorf("empty torc CR") + } + + if configuratorCR == nil { + return nil, fmt.Errorf("empty ANF configurator CR") + } + + if client == nil { + return nil, fmt.Errorf("invalid client") + } + + anfConfig := ANFConfig{} + if err := json.Unmarshal(configuratorCR.Spec.Raw, &anfConfig); err != nil { + return nil, err + } + + Log().Debug("ANF Config: ", anfConfig) + + return &ANF{ + ANFConfig: anfConfig, + ConfClient: client, + AMIEnabled: torcCR.Spec.CloudProvider == k8sclient.CloudProviderAzure, + TBCNamePrefix: configuratorCR.Name, + TridentNamespace: torcCR.Spec.Namespace, + }, nil +} + +func (a *ANF) Validate() error { + var err error + + clientConfig := api.ClientConfig{ + AzureAuthConfig: azclient.AzureAuthConfig{ + AADClientID: a.ClientID, + AADClientSecret: a.ClientSecret, + }, + TenantID: a.TenantID, + SubscriptionID: a.SubscriptionID, + Location: a.Location, + StorageDriverName: config.AzureNASStorageDriverName, + DebugTraceFlags: map[string]bool{"method": true, "api": true}, + SDKTimeout: api.DefaultSDKTimeout, + MaxCacheAge: api.DefaultMaxCacheAge, + } + + if os.Getenv("AZURE_CLIENT_ID") != "" && os.Getenv("AZURE_TENANT_ID") != "" && os.Getenv("AZURE_FEDERATED_TOKEN_FILE") != "" && os.Getenv("AZURE_AUTHORITY_HOST") != "" { + Log().Debug("Using Azure workload identity.") + a.WorkloadIdentityEnabled = true + } else if a.AMIEnabled { + Log().Debug("Using Azure managed identity.") + + if a.ANFConfig.ClientSecret == "" && a.ANFConfig.ClientID == "" && os.Getenv("AZURE_CREDENTIAL_FILE") != "" { + credFilePath := os.Getenv("AZURE_CREDENTIAL_FILE") + Log().WithField("credFilePath", credFilePath).Debug("Using Azure credential config file.") + + credFile, err := os.ReadFile(credFilePath) + if err != nil { + return fmt.Errorf("error reading from azure config file: " + err.Error()) + } + if err = json.Unmarshal(credFile, &clientConfig); err != nil { + return fmt.Errorf("error parsing azureAuthConfig: " + err.Error()) + } + + // Set SubscriptionID + a.ANFConfig.SubscriptionID = clientConfig.SubscriptionID + } + } else { + a.ClientID, a.ClientSecret, err = a.ConfClient.GetANFSecrets(a.ClientCredentials) + if err != nil { + Log().Errorf("ANF secrets not provided, %v", err) + return err + } + // Set ClientID and ClientSecret + clientConfig.AADClientID = a.ClientID + clientConfig.AADClientSecret = a.ClientSecret + } + + client, err := api.NewDriver(clientConfig) + if err != nil { + return err + } + + // Unit tests mock the API layer, so we only use the real API interface if it doesn't already exist. + if a.AZClient == nil { + a.AZClient = client + } + + if err = a.AZClient.DiscoverAzureResources(context.TODO()); err != nil { + return err + } + + if err = a.populateAndValidateAZResources(); err != nil { + return err + } + + return nil +} + +func (a *ANF) Create() ([]string, error) { + nfsBackendYAML, smbBackendYAML := a.buildTridentANFBackendTBC() + nfsBackendName := getANFBackendName(a.TBCNamePrefix, sa.NFS) + smbBackendName := getANFBackendName(a.TBCNamePrefix, sa.SMB) + + if err := a.ConfClient.CreateOrPatchObject(confClients.OBackend, nfsBackendName, + a.TridentNamespace, nfsBackendYAML); err != nil { + return []string{}, err + } + + if err := a.ConfClient.CreateOrPatchObject(confClients.OBackend, smbBackendName, + a.TridentNamespace, smbBackendYAML); err != nil { + return []string{}, err + } + + return []string{nfsBackendName, smbBackendName}, nil +} + +func (a *ANF) CreateStorageClass() error { + anfStorageClassMap := NewANFStorageClassMap() + + for _, cPool := range a.FilteredCapacityPoolMap { + switch cPool.ServiceLevel { + case api.ServiceLevelStandard: + anfStorageClassMap.Add(ANFStorageClassHardwareStandard, api.ServiceLevelStandard, sa.NFS) + anfStorageClassMap.Add(ANFStorageClassHardwareStandardSMB, api.ServiceLevelStandard, sa.SMB) + case api.ServiceLevelPremium: + anfStorageClassMap.Add(ANFStorageClassHardwarePremium, api.ServiceLevelPremium, sa.NFS) + anfStorageClassMap.Add(ANFStorageClassHardwarePremiumSMB, api.ServiceLevelPremium, sa.SMB) + case api.ServiceLevelUltra: + anfStorageClassMap.Add(ANFStorageClassHardwareUltra, api.ServiceLevelUltra, sa.NFS) + anfStorageClassMap.Add(ANFStorageClassHardwareUltraSMB, api.ServiceLevelUltra, sa.SMB) + } + } + + for _, sc := range anfStorageClassMap.SCMap { + scYAML := getANFStorageClassYAML(sc, config.AzureNASStorageDriverName, a.TridentNamespace) + err := a.ConfClient.CreateOrPatchObject(confClients.OStorageClass, sc.Name, "", scYAML) + if err != nil { + return err + } + } + + return nil +} + +func (a *ANF) CreateSnapshotClass() error { + anfSnapClassYAML := GetVolumeSnapshotClassYAML(NetAppSnapshotClassName) + return a.ConfClient.CreateOrPatchObject(confClients.OSnapshotClass, NetAppSnapshotClassName, + "", anfSnapClassYAML) +} + +func (a *ANF) GetCloudProvider() string { + if a.AMIEnabled { + return k8sclient.CloudProviderAzure + } + return "None" +} + +func (a *ANF) populateAndValidateAZResources() error { + a.FilteredCapacityPoolMap = a.AZClient.FilteredCapacityPoolMap(context.TODO(), a.ResourceGroups, + a.NetappAccounts, a.CapacityPools) + if len(a.FilteredCapacityPoolMap) == 0 { + return fmt.Errorf("no capacity pools discovered after filtering") + } + + a.FilteredSubnetMap = a.AZClient.FilteredSubnetMap(context.TODO(), a.ResourceGroups, a.VirtualNetwork, a.Subnet) + if len(a.FilteredSubnetMap) == 0 { + return fmt.Errorf("no ANF subnets discovered after filtering") + } + + return nil +} + +func (a *ANF) buildTridentANFBackendTBC() (string, string) { + var addPools bool + if len(a.CapacityPools) > 0 { + addPools = true + } + + anfVPoolMap := NewANFVPoolMap(addPools) + + for cPoolFullName, cPool := range a.FilteredCapacityPoolMap { + switch cPool.ServiceLevel { + case api.ServiceLevelStandard: + anfVPool := anfVPoolMap.Add(api.ServiceLevelStandard) + anfVPool.AddCPool(cPoolFullName) + case api.ServiceLevelPremium: + anfVPool := anfVPoolMap.Add(api.ServiceLevelPremium) + anfVPool.AddCPool(cPoolFullName) + case api.ServiceLevelUltra: + anfVPool := anfVPoolMap.Add(api.ServiceLevelUltra) + anfVPool.AddCPool(cPoolFullName) + } + } + + return getANFTBCYaml(a, anfVPoolMap.GetYAMLs(sa.NFS), sa.NFS), + getANFTBCYaml(a, anfVPoolMap.GetYAMLs(sa.SMB), sa.SMB) +} + +func getANFBackendName(backendPrefix, nasType string) string { + backendPrefix = strings.TrimSuffix(backendPrefix, "-configurator") + return backendPrefix + "-" + nasType +} + +// Backend VPool functions + +type ANFVPool struct { + ServiceLevel string + CPools []string + AddPool bool +} + +func NewANFVPool(serviceLevel string, addPool bool) *ANFVPool { + return &ANFVPool{ServiceLevel: serviceLevel, AddPool: addPool} +} + +func (avp *ANFVPool) AddCPool(cPoolName string) { + if avp.AddPool { + avp.CPools = append(avp.CPools, cPoolName) + } +} + +func (avp *ANFVPool) GetYAML(nasType string) string { + return getANFVPoolYAML(avp.ServiceLevel, nasType, strings.Join(avp.CPools, ",")) +} + +type ANFVPoolMap struct { + VPoolMap map[string]*ANFVPool + AddPools bool +} + +func NewANFVPoolMap(addPools bool) *ANFVPoolMap { + return &ANFVPoolMap{ + VPoolMap: make(map[string]*ANFVPool, MaxNumberOfANFServiceLevels), + AddPools: addPools, + } +} + +func (avm *ANFVPoolMap) Add(serviceLevel string) *ANFVPool { + avp, ok := avm.VPoolMap[serviceLevel] + if ok { + return avp + } + + avp = NewANFVPool(serviceLevel, avm.AddPools) + avm.VPoolMap[serviceLevel] = avp + return avp +} + +func (avm *ANFVPoolMap) GetYAMLs(nasType string) string { + vPoolsYAML := "" + for _, vPool := range avm.VPoolMap { + vPoolsYAML += vPool.GetYAML(nasType) + } + + return vPoolsYAML +} + +// ANF Storage Class functions + +type ANFStorageClass struct { + Name string + ServiceLevel string + NASType string +} + +type ANFStorageClassMap struct { + SCMap map[string]ANFStorageClass +} + +func NewANFStorageClassMap() *ANFStorageClassMap { + return &ANFStorageClassMap{SCMap: make(map[string]ANFStorageClass, MaxNumberOfANFStorageClasses)} +} + +func (asm *ANFStorageClassMap) Add(name, serviceLevel, nasType string) { + _, ok := asm.SCMap[name] + if ok { + return + } + + asm.SCMap[name] = ANFStorageClass{name, serviceLevel, nasType} +} diff --git a/operator/controllers/configurator/storage_drivers/anf_test.go b/operator/controllers/configurator/storage_drivers/anf_test.go new file mode 100644 index 000000000..3d427d41f --- /dev/null +++ b/operator/controllers/configurator/storage_drivers/anf_test.go @@ -0,0 +1,432 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package storage_drivers + +import ( + "context" + "encoding/json" + "fmt" + "os" + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + "k8s.io/apimachinery/pkg/runtime" + + k8sclient "github.com/netapp/trident/cli/k8s_client" + mockConfClients "github.com/netapp/trident/mocks/mock_operator/mock_controllers/mock_configurator/mock_clients" + mockAzureClient "github.com/netapp/trident/mocks/mock_storage_drivers/mock_azure" + operatorV1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" + "github.com/netapp/trident/storage_drivers/azure/api" +) + +var ctx = context.TODO() + +func getTestANFInstanceAndClients(t *testing.T) (*ANF, *mockConfClients.MockConfiguratorClientInterface, *mockAzureClient.MockAzure) { + mockCtrl := gomock.NewController(t) + mockClient := mockConfClients.NewMockConfiguratorClientInterface(mockCtrl) + mockAzure := mockAzureClient.NewMockAzure(mockCtrl) + + anfConfig := ANFConfig{ + SubscriptionID: "fake-uuid", + TenantID: "fake-uuid", + Location: "fake-location", + ClientID: "fake-uuid", + ClientSecret: "fake-secret", + ClientCredentials: "fake-cred", + } + + return &ANF{ + ANFConfig: anfConfig, + AZClient: mockAzure, + ConfClient: mockClient, + TBCNamePrefix: "anf-tbc", + TridentNamespace: "ns", + }, mockClient, mockAzure +} + +func getFilteredANFResources() (map[string]*api.CapacityPool, map[string]*api.Subnet) { + cp1 := &api.CapacityPool{ + ID: "cp1-uuid", + ResourceGroup: "fake-rg", + NetAppAccount: "fake-na", + Name: "cp1", + FullName: "fake-rg/fake-na/cp1", + Location: "fake-location", + ServiceLevel: api.ServiceLevelStandard, + } + + cp2 := &api.CapacityPool{ + ID: "cp2-uuid", + ResourceGroup: "fake-rg", + NetAppAccount: "fake-na", + Name: "cp2", + FullName: "fake-rg/fake-na/cp2", + Location: "fake-location", + ServiceLevel: api.ServiceLevelPremium, + } + + cp3 := &api.CapacityPool{ + ID: "cp3-uuid", + ResourceGroup: "fake-rg", + NetAppAccount: "fake-na", + Name: "cp3", + FullName: "fake-rg/fake-na/cp3", + Location: "fake-location", + ServiceLevel: api.ServiceLevelUltra, + } + + // Adding 2nd CP of same service level to increase the code coverage in ANFVPoolMap/ANFStorageClassMap functions. + cp4 := &api.CapacityPool{ + ID: "cp4-uuid", + ResourceGroup: "fake-rg", + NetAppAccount: "fake-na", + Name: "cp4", + FullName: "fake-rg/fake-na/cp4", + Location: "fake-location", + ServiceLevel: api.ServiceLevelUltra, + } + + cpMap := make(map[string]*api.CapacityPool, 4) + cpMap[cp1.FullName] = cp1 + cpMap[cp2.FullName] = cp2 + cpMap[cp3.FullName] = cp3 + cpMap[cp4.FullName] = cp4 + + s1 := &api.Subnet{ + ID: "s1-uuid", + ResourceGroup: "fake-rg", + VirtualNetwork: "fake-vnet", + Name: "s1", + FullName: "fake-rg/fake-vnet/s1", + Location: "fake-location", + } + + sMap := make(map[string]*api.Subnet, 1) + sMap[s1.FullName] = s1 + + return cpMap, sMap +} + +func MustEncode(b []byte, err error) []byte { + if err != nil { + panic(err) + } + + return b +} + +func TestNewANFInstance(t *testing.T) { + _, mClient, _ := getTestANFInstanceAndClients(t) + torcCR := &operatorV1.TridentOrchestrator{} + tconfCR := &operatorV1.TridentConfigurator{} + + // Test1: Nil TorcCR. + _, err := NewANFInstance(nil, nil, nil) + + assert.ErrorContains(t, err, "empty torc CR", "Torc CR is not nil.") + + // Test2: Nil ConfiguratorCR. + _, err = NewANFInstance(torcCR, nil, nil) + + assert.ErrorContains(t, err, "empty ANF configurator CR", "Configurator CR is not nil.") + + // Test3: Nil Configurator Clients. + _, err = NewANFInstance(torcCR, tconfCR, nil) + + assert.ErrorContains(t, err, "invalid client", "Valid Configurator Client.") + + // Test4: Json Unmarshal error. + _, err = NewANFInstance(torcCR, tconfCR, mClient) + + assert.Error(t, err, "Configurator Unmarshal success.") + + // Test5: Get new ANF instance successfully. + tconfCRSpecContents := ANFConfig{SubscriptionID: "fake-uuid"} + tconfCR.Spec.RawExtension = runtime.RawExtension{Raw: MustEncode(json.Marshal(tconfCRSpecContents))} + + _, err = NewANFInstance(torcCR, tconfCR, mClient) + + assert.NoError(t, err, "Failed to get ANF instance.") +} + +func TestANF_Validate_WorkloadIdentityDiscoveryError(t *testing.T) { + anf, _, mAzure := getTestANFInstanceAndClients(t) + + // Workload Identity + envVariables := map[string]string{ + "AZURE_CLIENT_ID": "deadbeef-784c-4b35-8329-460f52a3ad50", + "AZURE_TENANT_ID": "deadbeef-4746-4444-a919-3b34af5f0a3c", + "AZURE_FEDERATED_TOKEN_FILE": "/test/file/path", + "AZURE_AUTHORITY_HOST": "https://msft.com/", + } + + // Set required environment variables for testing + for key, value := range envVariables { + _ = os.Setenv(key, value) + } + + mAzure.EXPECT().DiscoverAzureResources(ctx).Return(fmt.Errorf("failed to discover resources")) + + err := anf.Validate() + + assert.True(t, anf.WorkloadIdentityEnabled, "Workload Identity not enabled.") + assert.Error(t, err, "Discovered all the resources.") + + // Unset all the environment variables + for key := range envVariables { + _ = os.Unsetenv(key) + } +} + +func TestANF_Validate_AMINoFileError(t *testing.T) { + anf, _, _ := getTestANFInstanceAndClients(t) + + anf.ClientID = "" + anf.ClientSecret = "" + anf.AMIEnabled = true + + envVariable := map[string]string{ + "AZURE_CREDENTIAL_FILE": "/no/such/path/azure.json", + } + + // Set required environment variables for testing + for key, value := range envVariable { + _ = os.Setenv(key, value) + } + + err := anf.Validate() + + assert.ErrorContains(t, err, "error reading from azure config file", "Read azure.json file.") + + // Unset environment variable + for key := range envVariable { + _ = os.Unsetenv(key) + } +} + +func TestANF_Validate_AMIUnmarshalFileError(t *testing.T) { + anf, _, _ := getTestANFInstanceAndClients(t) + + anf.ClientID = "" + anf.ClientSecret = "" + anf.AMIEnabled = true + + configFile, _ := os.Getwd() + envVariable := map[string]string{ + "AZURE_CREDENTIAL_FILE": configFile + "azure.json", + } + + // Set required environment variables for testing + for key, value := range envVariable { + _ = os.Setenv(key, value) + } + + // Giving string as int to fail Unmarshal + configFileContent := ` + { + "aadClientId": 111, + }` + + _ = os.WriteFile(envVariable["AZURE_CREDENTIAL_FILE"], []byte(configFileContent), os.ModePerm) + + err := anf.Validate() + + assert.ErrorContains(t, err, "error parsing azureAuthConfig", "Read azure.json file.") + + // Remove the file + _ = os.Remove(envVariable["AZURE_CREDENTIAL_FILE"]) + + // Unset environment variable + for key := range envVariable { + _ = os.Unsetenv(key) + } +} + +func TestANF_Validate_AMIDiscoveryError(t *testing.T) { + anf, _, mAzure := getTestANFInstanceAndClients(t) + + anf.ClientID = "" + anf.ClientSecret = "" + anf.AMIEnabled = true + + configFile, _ := os.Getwd() + envVariable := map[string]string{ + "AZURE_CREDENTIAL_FILE": configFile + "azure.json", + } + + // Set required environment variables for testing + for key, value := range envVariable { + _ = os.Setenv(key, value) + } + + configFileContent := ` + { + "cloud": "AzurePublicCloud", + "tenantId": "deadbeef-784c-4b35-8329-460f52a3ad50", + "subscriptionId": "deadbeef-173f-4bf4-b5b8-f17f8d2fe43b", + "aadClientId": "test-msi", + "aadClientSecret": "test-msi", + "resourceGroup": "RG1", + "location": "fake-location", + "useManagedIdentityExtension": true, + "userAssignedIdentityID": "deadbeef-173f-4bf4-b5b8-7cba6f53a227" + }` + + _ = os.WriteFile(envVariable["AZURE_CREDENTIAL_FILE"], []byte(configFileContent), os.ModePerm) + + mAzure.EXPECT().DiscoverAzureResources(ctx).Return(fmt.Errorf("failed to discover resources")) + + err := anf.Validate() + + assert.Equal(t, "deadbeef-173f-4bf4-b5b8-f17f8d2fe43b", anf.SubscriptionID, "Failed to set subscription ID.") + assert.Error(t, err, "Discovered all the resources.") + + // Remove the file + _ = os.Remove(envVariable["AZURE_CREDENTIAL_FILE"]) + + // Unset environment variable + for key := range envVariable { + _ = os.Unsetenv(key) + } +} + +func TestANF_Validate_NoClientSecretError(t *testing.T) { + anf, mClient, _ := getTestANFInstanceAndClients(t) + + mClient.EXPECT().GetANFSecrets(gomock.Any()).Return("", "", fmt.Errorf("failed to get secret")) + + err := anf.Validate() + + assert.ErrorContains(t, err, "failed to get secret", "Got the Client secret.") +} + +func TestANF_Validate_PopulateAZResourcesError(t *testing.T) { + anf, mClient, mAzure := getTestANFInstanceAndClients(t) + cMap, _ := getFilteredANFResources() + + // Test1: No capacity pool error. + mClient.EXPECT().GetANFSecrets(gomock.Any()).Return("fake-uuid", "fake-secret", nil) + mAzure.EXPECT().DiscoverAzureResources(ctx).Return(nil) + mAzure.EXPECT().FilteredCapacityPoolMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(make(map[string]*api.CapacityPool)) + + err := anf.Validate() + + assert.ErrorContains(t, err, "no capacity pools discovered after filtering") + + // Test2: No subnets error. + mClient.EXPECT().GetANFSecrets(gomock.Any()).Return("fake-uuid", "fake-secret", nil) + mAzure.EXPECT().DiscoverAzureResources(ctx).Return(nil) + mAzure.EXPECT().FilteredCapacityPoolMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(cMap) + mAzure.EXPECT().FilteredSubnetMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(make(map[string]*api.Subnet)) + + err = anf.Validate() + + assert.ErrorContains(t, err, "no ANF subnets discovered after filtering") +} + +func TestANF_Validate_Success(t *testing.T) { + anf, mClient, mAzure := getTestANFInstanceAndClients(t) + cMap, sMap := getFilteredANFResources() + + mClient.EXPECT().GetANFSecrets(gomock.Any()).Return("fake-uuid", "fake-secret", nil) + mAzure.EXPECT().DiscoverAzureResources(ctx).Return(nil) + mAzure.EXPECT().FilteredCapacityPoolMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(cMap) + mAzure.EXPECT().FilteredSubnetMap(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(sMap) + + err := anf.Validate() + + assert.NoError(t, err, "Validation failed.") +} + +func TestANF_Create(t *testing.T) { + anf, mClient, _ := getTestANFInstanceAndClients(t) + cpMap, sMap := getFilteredANFResources() + anf.FilteredCapacityPoolMap = cpMap + anf.FilteredSubnetMap = sMap + anf.CapacityPools = []string{"cp1"} + + // Test1: ANF NFS backend create error. + mClient.EXPECT().CreateOrPatchObject(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Return(fmt.Errorf("failed to create ANF NFS backend")) + + _, err := anf.Create() + + assert.ErrorContains(t, err, "failed to create ANF NFS backend", "NFS backend created.") + + // Test2: ANF SMB backend create error. + mClient.EXPECT().CreateOrPatchObject(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + mClient.EXPECT().CreateOrPatchObject(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Return(fmt.Errorf("failed to create ANF SMB backend")) + + _, err = anf.Create() + + assert.ErrorContains(t, err, "failed to create ANF SMB backend", "SMB backend created.") + + // Test3: Successfully created both the backends. + mClient.EXPECT().CreateOrPatchObject(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + mClient.EXPECT().CreateOrPatchObject(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + + backends, err := anf.Create() + + assert.NoError(t, err, "Backend creation failed.") + assert.Equal(t, "anf-tbc-nfs", backends[0], "Wrong TBC name.") + assert.Equal(t, "anf-tbc-smb", backends[1], "Wrong TBC name.") +} + +func TestANF_CreateStorageClass(t *testing.T) { + anf, mClient, _ := getTestANFInstanceAndClients(t) + cpMap, sMap := getFilteredANFResources() + anf.FilteredCapacityPoolMap = cpMap + anf.FilteredSubnetMap = sMap + + // Test1: Storage class create failure. + mClient.EXPECT().CreateOrPatchObject(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Return(fmt.Errorf("failed to create storage class")) + + err := anf.CreateStorageClass() + + assert.ErrorContains(t, err, "failed to create storage class", "Created Storage class.") + + // Test2: Successfully created all the storage classes. + mClient.EXPECT().CreateOrPatchObject(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).Times(6) + + err = anf.CreateStorageClass() + + assert.NoError(t, err, "Failed to create storage classes.") +} + +func TestANF_CreateSnapshotClass(t *testing.T) { + anf, mClient, _ := getTestANFInstanceAndClients(t) + + // Test1: Snapshot class create failure. + mClient.EXPECT().CreateOrPatchObject(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()). + Return(fmt.Errorf("failed to create snapshot class")) + + err := anf.CreateSnapshotClass() + + assert.ErrorContains(t, err, "failed to create snapshot class", "Created Snapshot class.") + + // Test2: Successfully created Snapshot class. + mClient.EXPECT().CreateOrPatchObject(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + + err = anf.CreateSnapshotClass() + + assert.NoError(t, err, "Failed to create Snapshot class.") +} + +func TestANF_GetCloudProvider(t *testing.T) { + anf, _, _ := getTestANFInstanceAndClients(t) + + // Test1: Non-AMI. + cp := anf.GetCloudProvider() + + assert.Equal(t, "None", cp, "Cloud Provider is Azure.") + + // Test2: AMI or Workload Identity. + anf.AMIEnabled = true + + cp = anf.GetCloudProvider() + + assert.Equal(t, k8sclient.CloudProviderAzure, cp, "Cloud Provider is None.") +} diff --git a/operator/controllers/configurator/storage_drivers/config.go b/operator/controllers/configurator/storage_drivers/config.go new file mode 100644 index 000000000..b29097a16 --- /dev/null +++ b/operator/controllers/configurator/storage_drivers/config.go @@ -0,0 +1,20 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package storage_drivers + +// ANF Configurations + +const ( + ANFStorageClassHardwareStandard = "netapp-anf-perf-standard" + ANFStorageClassHardwarePremium = "netapp-anf-perf-premium" + ANFStorageClassHardwareUltra = "netapp-anf-perf-ultra" + + ANFStorageClassHardwareStandardSMB = "netapp-anf-perf-standard-smb" + ANFStorageClassHardwarePremiumSMB = "netapp-anf-perf-premium-smb" + ANFStorageClassHardwareUltraSMB = "netapp-anf-perf-ultra-smb" + + NetAppSnapshotClassName = "netapp-snapshot-class" + + MaxNumberOfANFServiceLevels = 3 + MaxNumberOfANFStorageClasses = 6 +) diff --git a/operator/controllers/configurator/storage_drivers/types.go b/operator/controllers/configurator/storage_drivers/types.go new file mode 100644 index 000000000..2553634c7 --- /dev/null +++ b/operator/controllers/configurator/storage_drivers/types.go @@ -0,0 +1,11 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package storage_drivers + +type Backend interface { + Validate() error + Create() ([]string, error) + CreateStorageClass() error + CreateSnapshotClass() error + GetCloudProvider() string +} diff --git a/operator/controllers/configurator/storage_drivers/yaml_factory.go b/operator/controllers/configurator/storage_drivers/yaml_factory.go new file mode 100644 index 000000000..c1b2fd0e4 --- /dev/null +++ b/operator/controllers/configurator/storage_drivers/yaml_factory.go @@ -0,0 +1,139 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package storage_drivers + +import ( + "fmt" + "strings" + + sa "github.com/netapp/trident/storage_attribute" +) + +func getANFTBCYaml(anf *ANF, vPools, nasType string) string { + tbcYaml := ANFTBCYaml + + tbcYaml = strings.ReplaceAll(tbcYaml, "{TBC_NAME}", getANFBackendName(anf.TBCNamePrefix, nasType)) + tbcYaml = strings.ReplaceAll(tbcYaml, "{NAMESPACE}", anf.TridentNamespace) + tbcYaml = strings.ReplaceAll(tbcYaml, "{SUBSCRIPTION_ID}", anf.SubscriptionID) + tbcYaml = strings.ReplaceAll(tbcYaml, "{TENANT_ID}", anf.TenantID) + tbcYaml = strings.ReplaceAll(tbcYaml, "{LOCATION}", anf.Location) + tbcYaml = strings.ReplaceAll(tbcYaml, "{RESOURCE_GROUPS}", strings.Join(anf.ResourceGroups, ",")) + tbcYaml = strings.ReplaceAll(tbcYaml, "{NETAPP_ACCOUNTS}", strings.Join(anf.NetappAccounts, ",")) + tbcYaml = strings.ReplaceAll(tbcYaml, "{VIRTUAL_NETWORK}", anf.VirtualNetwork) + tbcYaml = strings.ReplaceAll(tbcYaml, "{SUBNET}", anf.Subnet) + tbcYaml = strings.ReplaceAll(tbcYaml, "{NAS_TYPE}", nasType) + tbcYaml = strings.ReplaceAll(tbcYaml, "{V_POOLS}", vPools) + + if !anf.AMIEnabled && !anf.WorkloadIdentityEnabled { + tbcYaml = strings.ReplaceAll(tbcYaml, "{CLIENT_CREDENTIALS}", constructClientCredentials(anf.ClientCredentials)) + } else { + tbcYaml = strings.ReplaceAll(tbcYaml, "{CLIENT_CREDENTIALS}", "") + } + + return tbcYaml +} + +const ANFTBCYaml = `--- +apiVersion: trident.netapp.io/v1 +kind: TridentBackendConfig +metadata: + name: {TBC_NAME} + namespace: {NAMESPACE} +spec: + version: 1 + storageDriverName: azure-netapp-files + nasType: {NAS_TYPE} + resourceGroups: [{RESOURCE_GROUPS}] + netappAccounts: [{NETAPP_ACCOUNTS}] + virtualNetwork: {VIRTUAL_NETWORK} + subnet: {SUBNET} + subscriptionID: {SUBSCRIPTION_ID} + tenantID: {TENANT_ID} + location: {LOCATION} + {CLIENT_CREDENTIALS} + debugTraceFlags: + discovery: true + method: true + api: true + storage: + {V_POOLS} +` + +func getANFVPoolYAML(serviceLevel, nasType, cPools string) string { + anfVPool := ANFVPoolYAML + + anfVPool = strings.ReplaceAll(anfVPool, "{SERVICE_LEVEL}", serviceLevel) + anfVPool = strings.ReplaceAll(anfVPool, "{NAS_TYPE}", nasType) + anfVPool = strings.ReplaceAll(anfVPool, "{CAPACITY_POOLS}", cPools) + + return anfVPool +} + +const ANFVPoolYAML = ` + - serviceLevel: {SERVICE_LEVEL} + capacityPools: [{CAPACITY_POOLS}] + labels: + serviceLevel: {SERVICE_LEVEL} + nasType: {NAS_TYPE} +` + +func constructClientCredentials(clientCred string) string { + cred := "credentials:\n" + cred += fmt.Sprintf(" name: %s", clientCred) + return cred +} + +func getANFStorageClassYAML(sc ANFStorageClass, backendType, namespace string) string { + scYAML := anfStorageClassTemplate + + scYAML = strings.ReplaceAll(scYAML, "{NAME}", sc.Name) + scYAML = strings.ReplaceAll(scYAML, "{BACKEND_TYPE}", backendType) + scYAML = strings.ReplaceAll(scYAML, "{SERVICE_LEVEL}", sc.ServiceLevel) + scYAML = strings.ReplaceAll(scYAML, "{NAS_TYPE}", sc.NASType) + + if sc.NASType == sa.SMB { + scYAML = strings.ReplaceAll(scYAML, "{AAD_SECRET}", constructAADSecret(namespace)) + } else { + scYAML = strings.ReplaceAll(scYAML, "{AAD_SECRET}", "") + } + + return scYAML +} + +const anfStorageClassTemplate = `--- +apiVersion: storage.k8s.io/v1 +kind: StorageClass +metadata: + name: {NAME} +provisioner: csi.trident.netapp.io +parameters: + backendType: {BACKEND_TYPE} + selector: serviceLevel={SERVICE_LEVEL};nasType={NAS_TYPE} + {AAD_SECRET} +volumeBindingMode: Immediate +allowVolumeExpansion: true +` + +func constructAADSecret(namespace string) string { + //nolint:gosec + aadSecret := "csi.storage.k8s.io/node-stage-secret-name: 'smbcreds'\n" + aadSecret += fmt.Sprintf(" csi.storage.k8s.io/node-stage-secret-namespace: '%s'", namespace) + return aadSecret +} + +func GetVolumeSnapshotClassYAML(name string) string { + vscYAML := volumeSnapshotClassTemplate + + vscYAML = strings.ReplaceAll(vscYAML, "{NAME}", name) + + return vscYAML +} + +const volumeSnapshotClassTemplate = `--- +apiVersion: snapshot.storage.k8s.io/v1 +kind: VolumeSnapshotClass +metadata: + name: {NAME} +driver: csi.trident.netapp.io +deletionPolicy: Delete +` diff --git a/operator/controllers/controller.go b/operator/controllers/controller.go index db8353b98..0fa19b022 100644 --- a/operator/controllers/controller.go +++ b/operator/controllers/controller.go @@ -2,9 +2,10 @@ package controllers +import ( + . "github.com/netapp/trident/operator/frontend" +) + type Controller interface { - Activate() error - Deactivate() error - GetName() string - Version() string + Frontend } diff --git a/operator/controllers/orchestrator/controller.go b/operator/controllers/orchestrator/controller.go index 12b760da4..5671b8c98 100644 --- a/operator/controllers/orchestrator/controller.go +++ b/operator/controllers/orchestrator/controller.go @@ -26,15 +26,15 @@ import ( commonconfig "github.com/netapp/trident/config" . "github.com/netapp/trident/logging" "github.com/netapp/trident/operator/clients" - netappv1 "github.com/netapp/trident/operator/controllers/orchestrator/apis/netapp/v1" - "github.com/netapp/trident/operator/controllers/orchestrator/client/clientset/versioned/scheme" "github.com/netapp/trident/operator/controllers/orchestrator/installer" + netappv1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" + operatorV1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" + "github.com/netapp/trident/operator/crd/client/clientset/versioned/scheme" "github.com/netapp/trident/utils/errors" versionutils "github.com/netapp/trident/utils/version" ) type ( - AppStatus string ResourceType string // If Operator starts to List and Watch other CR types, this can be used to differentiate. ) @@ -45,15 +45,6 @@ const ( Operator = "trident-operator.netapp.io" CacheSyncPeriod = 300 * time.Second - AppStatusNotInstalled AppStatus = "" // default - AppStatusInstalling AppStatus = "Installing" // Set only on controlling CR - AppStatusInstalled AppStatus = "Installed" // Set only on controlling CR - AppStatusUninstalling AppStatus = "Uninstalling" // Set only on controlling CR - AppStatusUninstalled AppStatus = "Uninstalled" // Set only on controlling CR - AppStatusFailed AppStatus = "Failed" // Set only on controlling CR - AppStatusUpdating AppStatus = "Updating" // Set only on controlling CR - AppStatusError AppStatus = "Error" // Should not be set on controlling CR - ResourceTridentOrchestratorCR ResourceType = "resourceTridentOrchestratorCR" ResourceDeployment ResourceType = "resourceDeployment" ResourceDaemonSet ResourceType = "resourceDaemonset" @@ -668,7 +659,7 @@ func (c *Controller) reconcileTridentNotPresent() error { // Iterate through all the CRs, identify if any of the CRs has status "Uninstalled" then return, // until this CR is removed cannot perform new Trident installation. for _, cr := range tridentCRs { - if cr.Status.Status == string(AppStatusUninstalled) { + if cr.Status.Status == string(operatorV1.AppStatusUninstalled) { Log().WithField("controllingCR", cr.Name).Warnf("Remove TridentOrchestrator CR with uninstalled status to allow new Trident installation.") @@ -703,7 +694,7 @@ func (c *Controller) reconcileTridentNotPresent() error { statusMessage := "Installing Trident" newTridentCR, err := c.updateTorcEventAndStatus(tridentCR, debugMessage, statusMessage, - string(AppStatusInstalling), "", "", tridentCR.Spec.Namespace, corev1.EventTypeNormal, nil) + string(operatorV1.AppStatusInstalling), "", "", tridentCR.Spec.Namespace, corev1.EventTypeNormal, nil) if err != nil { return errors.ReconcileFailedError( "unable to update status of the CR '%v' to installing", tridentCR.Name) @@ -865,7 +856,7 @@ func (c *Controller) controllingCRBasedReconcile( controllingCR *netappv1.TridentOrchestrator, deploymentExist bool, ) error { // Check to see if controllingCR status is uninstalled, if this is the case installation/patch should not be run - if controllingCR.Status.Status == string(AppStatusUninstalled) { + if controllingCR.Status.Status == string(operatorV1.AppStatusUninstalled) { // If for some reason deployment exists remove Trident installation to make sure Trident remains in // uninstalled state @@ -892,7 +883,7 @@ func (c *Controller) controllingCRBasedReconcile( statusMessage := "Uninstalled Trident" + crdNote + UninstallationNote if _, crErr := c.updateTorcEventAndStatus(controllingCR, debugMessage, statusMessage, - string(AppStatusUninstalled), "", "", controllingCR.Status.Namespace, corev1.EventTypeNormal, + string(operatorV1.AppStatusUninstalled), "", "", controllingCR.Status.Namespace, corev1.EventTypeNormal, nil); crErr != nil { Log().Error(crErr) } @@ -924,7 +915,7 @@ func (c *Controller) controllingCRBasedReconcile( debugMessage := "Updating Trident Orchestrator CR after failing to detect Trident Deployment and/or DaemonSet." statusMessage := fmt.Sprintf("Failed to detect installed Trident resources; err: %s", err.Error()) - if _, crErr := c.updateTorcEventAndStatus(controllingCR, debugMessage, statusMessage, string(AppStatusFailed), + if _, crErr := c.updateTorcEventAndStatus(controllingCR, debugMessage, statusMessage, string(operatorV1.AppStatusFailed), controllingCR.Status.Version, currentInstalledACPVersion, controllingCR.Status.Namespace, corev1.EventTypeWarning, &controllingCR.Status.CurrentInstallationParams); crErr != nil { @@ -959,7 +950,7 @@ func (c *Controller) controllingCRBasedReconcile( " `%v` to `%v`; namespace change is not allowed.", currentInstallationNamespace, controllingCR.Spec.Namespace) - if _, crErr := c.updateTorcEventAndStatus(controllingCR, debugMessage, errorMessage, string(AppStatusFailed), + if _, crErr := c.updateTorcEventAndStatus(controllingCR, debugMessage, errorMessage, string(operatorV1.AppStatusFailed), currentInstalledTridentVersion, currentInstalledACPVersion, currentInstallationNamespace, corev1.EventTypeWarning, &controllingCR.Status.CurrentInstallationParams); crErr != nil { @@ -993,7 +984,7 @@ func (c *Controller) controllingCRBasedReconcile( controllingCRName := controllingCR.Name controllingCR, err = c.updateTorcEventAndStatus(controllingCR, debugMessage, statusMessage, - string(AppStatusUpdating), currentInstalledTridentVersion, currentInstalledACPVersion, + string(operatorV1.AppStatusUpdating), currentInstalledTridentVersion, currentInstalledACPVersion, currentInstallationNamespace, eventType, &controllingCR.Status.CurrentInstallationParams) if err != nil { @@ -1042,7 +1033,7 @@ func (c *Controller) installTridentAndUpdateStatus(tridentCR netappv1.TridentOrc } if _, crErr := c.updateTorcEventAndStatus(&tridentCR, debugMessage, statusMessage, - string(AppStatusFailed), "", "", tridentCR.Spec.Namespace, corev1.EventTypeWarning, + string(operatorV1.AppStatusFailed), "", "", tridentCR.Spec.Namespace, corev1.EventTypeWarning, identifiedSpecValues); crErr != nil { Log().Error(crErr) } @@ -1064,7 +1055,7 @@ func (c *Controller) installTridentAndUpdateStatus(tridentCR netappv1.TridentOrc } // TODO: may need to check if ACP version needs to be bumped - _, err = c.updateTorcEventAndStatus(&tridentCR, debugMessage, statusMessage, string(AppStatusInstalled), + _, err = c.updateTorcEventAndStatus(&tridentCR, debugMessage, statusMessage, string(operatorV1.AppStatusInstalled), identifiedTridentVersion, identifiedACPVersion, tridentCR.Spec.Namespace, eventType, identifiedSpecValues) @@ -1080,7 +1071,7 @@ func (c *Controller) uninstallTridentAndUpdateStatus( debugMessage := "Updating TridentOrchestrator CR before uninstallation" statusMessage := "Uninstalling Trident" - newTridentCR, err := c.updateTorcEventAndStatus(&tridentCR, debugMessage, statusMessage, string(AppStatusUninstalling), + newTridentCR, err := c.updateTorcEventAndStatus(&tridentCR, debugMessage, statusMessage, string(operatorV1.AppStatusUninstalling), currentInstalledTridentVersion, tridentCR.Status.ACPVersion, tridentCR.Status.Namespace, corev1.EventTypeNormal, &tridentCR.Status.CurrentInstallationParams) if err != nil { @@ -1094,7 +1085,7 @@ func (c *Controller) uninstallTridentAndUpdateStatus( debugMessage := "Updating TridentOrchestrator CR after failed uninstallation." statusMessage := fmt.Sprintf("Failed to uninstall Trident; err: %s", err.Error()) - if _, crErr := c.updateTorcEventAndStatus(newTridentCR, debugMessage, statusMessage, string(AppStatusFailed), + if _, crErr := c.updateTorcEventAndStatus(newTridentCR, debugMessage, statusMessage, string(operatorV1.AppStatusFailed), currentInstalledTridentVersion, tridentCR.Status.ACPVersion, tridentCR.Status.Namespace, corev1.EventTypeWarning, &tridentCR.Status.CurrentInstallationParams); crErr != nil { @@ -1119,7 +1110,7 @@ func (c *Controller) uninstallTridentAndUpdateStatus( statusMessage = "Uninstalled Trident" + crdNote + UninstallationNote return c.updateTorcEventAndStatus(newTridentCR, debugMessage, statusMessage, - string(AppStatusUninstalled), "", "", newTridentCR.Status.Namespace, corev1.EventTypeNormal, nil) + string(operatorV1.AppStatusUninstalled), "", "", newTridentCR.Status.Namespace, corev1.EventTypeNormal, nil) } // uninstallTridentAll uninstalls Trident CSI, Trident CSI Preview, Trident Legacy @@ -1233,7 +1224,7 @@ func (c *Controller) identifyControllingCRBasedOnStatus() (bool, *netappv1.Tride // Identify and return the CR that has status neither "NotInstalled" not "Error" for _, cr := range tridentCRs { - if cr.Status.Status == string(AppStatusNotInstalled) || cr.Status.Status == string(AppStatusError) { + if cr.Status.Status == string(operatorV1.AppStatusNotInstalled) || cr.Status.Status == string(operatorV1.AppStatusError) { continue } @@ -1299,7 +1290,7 @@ func (c *Controller) updateAllCRs(message string) error { var debugMessage string for _, cr := range allCRs { debugMessage = "Updating " + cr.Name + " TridentOrchestrator CR." - _, err = c.updateTorcEventAndStatus(cr, debugMessage, message, string(AppStatusError), "", "", + _, err = c.updateTorcEventAndStatus(cr, debugMessage, message, string(operatorV1.AppStatusError), "", "", cr.Spec.Namespace, corev1.EventTypeWarning, nil) } @@ -1323,7 +1314,7 @@ func (c *Controller) updateOtherCRs(controllingCRName string) error { statusMessage := fmt.Sprintf("Trident is bound to another CR '%v'", controllingCRName) - _, err = c.updateTorcEventAndStatus(cr, debugMessage, statusMessage, string(AppStatusError), "", "", + _, err = c.updateTorcEventAndStatus(cr, debugMessage, statusMessage, string(operatorV1.AppStatusError), "", "", cr.Spec.Namespace, corev1.EventTypeWarning, nil) } } @@ -1490,7 +1481,7 @@ func (c *Controller) removeNonTorcBasedCSIInstallation(tridentCR *netappv1.Tride " namespace '%v'.", csiTridentNamespace) Log().Info(eventMessage) - c.eventRecorder.Event(tridentCR, corev1.EventTypeNormal, string(AppStatusInstalling), eventMessage) + c.eventRecorder.Event(tridentCR, corev1.EventTypeNormal, string(operatorV1.AppStatusInstalling), eventMessage) uninstallRequired = true } @@ -1505,7 +1496,7 @@ func (c *Controller) removeNonTorcBasedCSIInstallation(tridentCR *netappv1.Tride Log().Error(failureMessage) if _, crErr := c.updateTorcEventAndStatus(tridentCR, debugMessage, failureMessage, - string(AppStatusFailed), "", "", tridentCR.Spec.Namespace, corev1.EventTypeWarning, nil); crErr != nil { + string(operatorV1.AppStatusFailed), "", "", tridentCR.Spec.Namespace, corev1.EventTypeWarning, nil); crErr != nil { Log().Error(crErr) } @@ -1517,7 +1508,7 @@ func (c *Controller) removeNonTorcBasedCSIInstallation(tridentCR *netappv1.Tride eventMessage := "Non-Trident Orchestrator based CSI Trident installation removed." Log().Info(eventMessage) - c.eventRecorder.Event(tridentCR, corev1.EventTypeNormal, string(AppStatusInstalling), eventMessage) + c.eventRecorder.Event(tridentCR, corev1.EventTypeNormal, string(operatorV1.AppStatusInstalling), eventMessage) } return nil diff --git a/operator/controllers/orchestrator/installer/installer.go b/operator/controllers/orchestrator/installer/installer.go index 7c091f7e4..a0701b8fc 100644 --- a/operator/controllers/orchestrator/installer/installer.go +++ b/operator/controllers/orchestrator/installer/installer.go @@ -20,7 +20,7 @@ import ( k8sclient "github.com/netapp/trident/cli/k8s_client" commonconfig "github.com/netapp/trident/config" . "github.com/netapp/trident/logging" - netappv1 "github.com/netapp/trident/operator/controllers/orchestrator/apis/netapp/v1" + netappv1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" crdclient "github.com/netapp/trident/persistent_store/crd/client/clientset/versioned" "github.com/netapp/trident/utils" "github.com/netapp/trident/utils/crypto" @@ -44,6 +44,7 @@ const ( VolumePublicationCRDName = "tridentvolumepublications.trident.netapp.io" SnapshotCRDName = "tridentsnapshots.trident.netapp.io" VolumeReferenceCRDName = "tridentvolumereferences.trident.netapp.io" + ConfiguratorCRDName = "tridentconfigurators.trident.netapp.io" DefaultTimeout = 30 ) @@ -112,6 +113,7 @@ var ( VolumeCRDName, VolumeReferenceCRDName, VolumePublicationCRDName, + ConfiguratorCRDName, } ) @@ -766,6 +768,9 @@ func (i *Installer) createCRDs(performOperationOnce bool) error { false); err != nil { return err } + if err = i.CreateOrPatchCRD(ConfiguratorCRDName, k8sclient.GetConfiguratorCRDYAML(), false); err != nil { + return err + } return err } diff --git a/operator/controllers/orchestrator/installer/types.go b/operator/controllers/orchestrator/installer/types.go index db6858b5e..df2a2b5d8 100644 --- a/operator/controllers/orchestrator/installer/types.go +++ b/operator/controllers/orchestrator/installer/types.go @@ -15,7 +15,7 @@ import ( apiextensionv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" k8sclient "github.com/netapp/trident/cli/k8s_client" - v15 "github.com/netapp/trident/operator/controllers/orchestrator/apis/netapp/v1" + v15 "github.com/netapp/trident/operator/crd/apis/netapp/v1" ) // TridentInstaller is responsible for installing, patching, or uninstalling orchestrator controlled instances of Trident. diff --git a/operator/controllers/orchestrator/apis/netapp/v1/doc.go b/operator/crd/apis/netapp/v1/doc.go similarity index 100% rename from operator/controllers/orchestrator/apis/netapp/v1/doc.go rename to operator/crd/apis/netapp/v1/doc.go diff --git a/operator/controllers/orchestrator/apis/netapp/v1/register.go b/operator/crd/apis/netapp/v1/register.go similarity index 95% rename from operator/controllers/orchestrator/apis/netapp/v1/register.go rename to operator/crd/apis/netapp/v1/register.go index d2cb6bbd1..4174284c3 100644 --- a/operator/controllers/orchestrator/apis/netapp/v1/register.go +++ b/operator/crd/apis/netapp/v1/register.go @@ -36,6 +36,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, &TridentOrchestrator{}, &TridentOrchestratorList{}, + &TridentConfigurator{}, + &TridentConfiguratorList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil diff --git a/operator/crd/apis/netapp/v1/tridentconfigurator.go b/operator/crd/apis/netapp/v1/tridentconfigurator.go new file mode 100644 index 000000000..5002c4fe2 --- /dev/null +++ b/operator/crd/apis/netapp/v1/tridentconfigurator.go @@ -0,0 +1,58 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package v1 + +import ( + "encoding/json" + "fmt" +) + +type ( + TConfStatus string + TConfPhase string +) + +const ( + // TridentConfigurator Status Values + + Processing TConfStatus = "Processing" + Success TConfStatus = "Success" + Failed TConfStatus = "Failed" + + // TridentConfigurator Phase Values + + ValidatingConfig TConfPhase = "Validating Config" + ValidatedConfig TConfPhase = "Validated Config" + CreatingBackend TConfPhase = "Creating Backend" + CreatedBackend TConfPhase = "Created Backend" + CreatingSC TConfPhase = "Creating Storage Class" + CreatedSC TConfPhase = "Created Storage Class" + CreatingSnapClass TConfPhase = "Creating Snapshot Class" + Done TConfPhase = "Done" + + StorageDriverName = "storageDriverName" +) + +func (tc *TridentConfigurator) GetStorageDriverName() (string, error) { + var tConfSpec map[string]interface{} + if err := json.Unmarshal(tc.Spec.Raw, &tConfSpec); err != nil { + return "", err + } + + if name, ok := tConfSpec[StorageDriverName]; ok { + return name.(string), nil + } + + return "", fmt.Errorf("storageDriverName not set") +} + +func (tc *TridentConfigurator) IsSpecValid() bool { + return len(tc.Spec.Raw) != 0 +} + +func (tc *TridentConfigurator) Validate() error { + if !tc.IsSpecValid() { + return fmt.Errorf("empty tconf spec is not allowed") + } + return nil +} diff --git a/operator/crd/apis/netapp/v1/tridentorchestrator.go b/operator/crd/apis/netapp/v1/tridentorchestrator.go new file mode 100644 index 000000000..4e319a918 --- /dev/null +++ b/operator/crd/apis/netapp/v1/tridentorchestrator.go @@ -0,0 +1,33 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package v1 + +type AppStatus string + +const ( + AppStatusNotInstalled AppStatus = "" // default + AppStatusInstalling AppStatus = "Installing" // Set only on controlling CR + AppStatusInstalled AppStatus = "Installed" // Set only on controlling CR + AppStatusUninstalling AppStatus = "Uninstalling" // Set only on controlling CR + AppStatusUninstalled AppStatus = "Uninstalled" // Set only on controlling CR + AppStatusFailed AppStatus = "Failed" // Set only on controlling CR + AppStatusUpdating AppStatus = "Updating" // Set only on controlling CR + AppStatusError AppStatus = "Error" // Should not be set on controlling CR +) + +const MaxNumberOfTridentOrchestrators int = 1 + +func (o *TridentOrchestrator) HasTridentInstallationFailed() bool { + if o.Status.Status == string(AppStatusFailed) || o.Status.Status == string(AppStatusError) { + return true + } + return false +} + +func (o *TridentOrchestrator) IsTridentOperationInProgress() bool { + if o.Status.Status != string(AppStatusInstalled) && o.Status.Status != string(AppStatusUninstalled) && + !o.HasTridentInstallationFailed() { + return true + } + return false +} diff --git a/operator/crd/apis/netapp/v1/tridentorchestrator_test.go b/operator/crd/apis/netapp/v1/tridentorchestrator_test.go new file mode 100644 index 000000000..5353b0b16 --- /dev/null +++ b/operator/crd/apis/netapp/v1/tridentorchestrator_test.go @@ -0,0 +1,78 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package v1 + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestTridentOrchestrator_HasTridentInstallationFailed(t *testing.T) { + torc := TridentOrchestrator{Status: TridentOrchestratorStatus{}} + + tests := []struct { + name string + status []AppStatus + expected bool + }{ + { + name: "InstallFailed", + status: []AppStatus{AppStatusFailed, AppStatusError}, + expected: true, + }, + { + name: "InstallNotFailed", + status: []AppStatus{ + AppStatusNotInstalled, AppStatusInstalling, AppStatusInstalled, AppStatusUninstalling, + AppStatusUninstalled, AppStatusUpdating, + }, + expected: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + for _, s := range test.status { + torc.Status.Status = string(s) + + actual := torc.HasTridentInstallationFailed() + + assert.Equal(t, test.expected, actual, "Unexpected Torc status.") + } + }) + } +} + +func TestTridentOrchestrator_IsTridentOperationInProgress(t *testing.T) { + torc := TridentOrchestrator{Status: TridentOrchestratorStatus{}} + + tests := []struct { + name string + status []AppStatus + expected bool + }{ + { + name: "OperationInProgress", + status: []AppStatus{AppStatusNotInstalled, AppStatusInstalling, AppStatusUninstalling, AppStatusUpdating}, + expected: true, + }, + { + name: "OperationNotInProgress", + status: []AppStatus{AppStatusInstalled, AppStatusUninstalled, AppStatusFailed, AppStatusError}, + expected: false, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + for _, s := range test.status { + torc.Status.Status = string(s) + + actual := torc.IsTridentOperationInProgress() + + assert.Equal(t, test.expected, actual, "Unexpected Torc status.") + } + }) + } +} diff --git a/operator/controllers/orchestrator/apis/netapp/v1/types.go b/operator/crd/apis/netapp/v1/types.go similarity index 81% rename from operator/controllers/orchestrator/apis/netapp/v1/types.go rename to operator/crd/apis/netapp/v1/types.go index ab7bd155d..a5ba45ad4 100644 --- a/operator/controllers/orchestrator/apis/netapp/v1/types.go +++ b/operator/crd/apis/netapp/v1/types.go @@ -6,8 +6,13 @@ import ( "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" ) +/************************ +* Trident Orchestrator +************************/ + // +genclient // +genclient:nonNamespaced // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object @@ -146,3 +151,48 @@ type TridentOrchestratorSpecValues struct { ISCSISelfHealingInterval string `json:"iscsiSelfHealingInterval"` ISCSISelfHealingWaitTime string `json:"iscsiSelfHealingWaitTime"` } + +/************************ +* Trident Configurator +************************/ + +// TridentConfigurator defines a Trident backend. +// +genclient +// +genclient:nonNamespaced +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type TridentConfigurator struct { + metav1.TypeMeta `json:",inline"` + // +k8s:openapi-gen=false + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Input spec for the Trident Backend + Spec TridentConfiguratorSpec `json:"spec"` + Status TridentConfiguratorStatus `json:"status"` +} + +// TridentConfiguratorList is a list of TridentBackend objects. +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +type TridentConfiguratorList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + + // List of TridentConfigurator objects + Items []*TridentConfigurator `json:"items"` +} + +// TridentConfiguratorSpec defines the desired state of TridentConfigurator +type TridentConfiguratorSpec struct { + runtime.RawExtension +} + +// TridentConfiguratorStatus defines the observed state of TridentConfigurator +type TridentConfiguratorStatus struct { + BackendNames []string `json:"backendNames"` + Message string `json:"message"` + DeletionPolicy string `json:"deletionPolicy"` + Phase string `json:"phase"` + LastOperationStatus string `json:"lastOperationStatus"` + CloudProvider string `json:"cloudProvider"` +} diff --git a/operator/controllers/orchestrator/apis/netapp/v1/zz_generated.deepcopy.go b/operator/crd/apis/netapp/v1/zz_generated.deepcopy.go similarity index 64% rename from operator/controllers/orchestrator/apis/netapp/v1/zz_generated.deepcopy.go rename to operator/crd/apis/netapp/v1/zz_generated.deepcopy.go index f6b915940..8ee49138b 100644 --- a/operator/controllers/orchestrator/apis/netapp/v1/zz_generated.deepcopy.go +++ b/operator/crd/apis/netapp/v1/zz_generated.deepcopy.go @@ -1,7 +1,7 @@ //go:build !ignore_autogenerated // +build !ignore_autogenerated -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by deepcopy-gen. DO NOT EDIT. @@ -27,6 +27,109 @@ func (in *Toleration) DeepCopy() *Toleration { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TridentConfigurator) DeepCopyInto(out *TridentConfigurator) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TridentConfigurator. +func (in *TridentConfigurator) DeepCopy() *TridentConfigurator { + if in == nil { + return nil + } + out := new(TridentConfigurator) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TridentConfigurator) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TridentConfiguratorList) DeepCopyInto(out *TridentConfiguratorList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]*TridentConfigurator, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(TridentConfigurator) + (*in).DeepCopyInto(*out) + } + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TridentConfiguratorList. +func (in *TridentConfiguratorList) DeepCopy() *TridentConfiguratorList { + if in == nil { + return nil + } + out := new(TridentConfiguratorList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *TridentConfiguratorList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TridentConfiguratorSpec) DeepCopyInto(out *TridentConfiguratorSpec) { + *out = *in + in.RawExtension.DeepCopyInto(&out.RawExtension) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TridentConfiguratorSpec. +func (in *TridentConfiguratorSpec) DeepCopy() *TridentConfiguratorSpec { + if in == nil { + return nil + } + out := new(TridentConfiguratorSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TridentConfiguratorStatus) DeepCopyInto(out *TridentConfiguratorStatus) { + *out = *in + if in.BackendNames != nil { + in, out := &in.BackendNames, &out.BackendNames + *out = make([]string, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TridentConfiguratorStatus. +func (in *TridentConfiguratorStatus) DeepCopy() *TridentConfiguratorStatus { + if in == nil { + return nil + } + out := new(TridentConfiguratorStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TridentOrchestrator) DeepCopyInto(out *TridentOrchestrator) { *out = *in diff --git a/operator/controllers/orchestrator/client/clientset/versioned/clientset.go b/operator/crd/client/clientset/versioned/clientset.go similarity index 93% rename from operator/controllers/orchestrator/client/clientset/versioned/clientset.go rename to operator/crd/client/clientset/versioned/clientset.go index f37c036d0..d99db7e94 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/clientset.go +++ b/operator/crd/client/clientset/versioned/clientset.go @@ -1,4 +1,4 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by client-gen. DO NOT EDIT. @@ -7,7 +7,7 @@ package versioned import ( "fmt" - tridentv1 "github.com/netapp/trident/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1" + tridentv1 "github.com/netapp/trident/operator/crd/client/clientset/versioned/typed/netapp/v1" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" flowcontrol "k8s.io/client-go/util/flowcontrol" diff --git a/operator/controllers/orchestrator/client/clientset/versioned/doc.go b/operator/crd/client/clientset/versioned/doc.go similarity index 70% rename from operator/controllers/orchestrator/client/clientset/versioned/doc.go rename to operator/crd/client/clientset/versioned/doc.go index 5f58c9011..7f111c07b 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/doc.go +++ b/operator/crd/client/clientset/versioned/doc.go @@ -1,4 +1,4 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by client-gen. DO NOT EDIT. diff --git a/operator/controllers/orchestrator/client/clientset/versioned/fake/clientset_generated.go b/operator/crd/client/clientset/versioned/fake/clientset_generated.go similarity index 82% rename from operator/controllers/orchestrator/client/clientset/versioned/fake/clientset_generated.go rename to operator/crd/client/clientset/versioned/fake/clientset_generated.go index 0b9871b31..ac0facad2 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/fake/clientset_generated.go +++ b/operator/crd/client/clientset/versioned/fake/clientset_generated.go @@ -1,13 +1,13 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by client-gen. DO NOT EDIT. package fake import ( - clientset "github.com/netapp/trident/operator/controllers/orchestrator/client/clientset/versioned" - tridentv1 "github.com/netapp/trident/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1" - faketridentv1 "github.com/netapp/trident/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake" + clientset "github.com/netapp/trident/operator/crd/client/clientset/versioned" + tridentv1 "github.com/netapp/trident/operator/crd/client/clientset/versioned/typed/netapp/v1" + faketridentv1 "github.com/netapp/trident/operator/crd/client/clientset/versioned/typed/netapp/v1/fake" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/discovery" diff --git a/operator/controllers/orchestrator/client/clientset/versioned/fake/doc.go b/operator/crd/client/clientset/versioned/fake/doc.go similarity index 70% rename from operator/controllers/orchestrator/client/clientset/versioned/fake/doc.go rename to operator/crd/client/clientset/versioned/fake/doc.go index e1f96a121..da719ead7 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/fake/doc.go +++ b/operator/crd/client/clientset/versioned/fake/doc.go @@ -1,4 +1,4 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by client-gen. DO NOT EDIT. diff --git a/operator/controllers/orchestrator/client/clientset/versioned/fake/register.go b/operator/crd/client/clientset/versioned/fake/register.go similarity index 90% rename from operator/controllers/orchestrator/client/clientset/versioned/fake/register.go rename to operator/crd/client/clientset/versioned/fake/register.go index 90960655e..7ef008373 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/fake/register.go +++ b/operator/crd/client/clientset/versioned/fake/register.go @@ -1,11 +1,11 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by client-gen. DO NOT EDIT. package fake import ( - tridentv1 "github.com/netapp/trident/operator/controllers/orchestrator/apis/netapp/v1" + tridentv1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/operator/controllers/orchestrator/client/clientset/versioned/scheme/doc.go b/operator/crd/client/clientset/versioned/scheme/doc.go similarity index 73% rename from operator/controllers/orchestrator/client/clientset/versioned/scheme/doc.go rename to operator/crd/client/clientset/versioned/scheme/doc.go index 02121db3d..f8c8851a9 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/scheme/doc.go +++ b/operator/crd/client/clientset/versioned/scheme/doc.go @@ -1,4 +1,4 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by client-gen. DO NOT EDIT. diff --git a/operator/controllers/orchestrator/client/clientset/versioned/scheme/register.go b/operator/crd/client/clientset/versioned/scheme/register.go similarity index 90% rename from operator/controllers/orchestrator/client/clientset/versioned/scheme/register.go rename to operator/crd/client/clientset/versioned/scheme/register.go index 205d4174d..a69736106 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/scheme/register.go +++ b/operator/crd/client/clientset/versioned/scheme/register.go @@ -1,11 +1,11 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by client-gen. DO NOT EDIT. package scheme import ( - tridentv1 "github.com/netapp/trident/operator/controllers/orchestrator/apis/netapp/v1" + tridentv1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/doc.go b/operator/crd/client/clientset/versioned/typed/netapp/v1/doc.go similarity index 70% rename from operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/doc.go rename to operator/crd/client/clientset/versioned/typed/netapp/v1/doc.go index 2c4fa60ac..365bdf382 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/doc.go +++ b/operator/crd/client/clientset/versioned/typed/netapp/v1/doc.go @@ -1,4 +1,4 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by client-gen. DO NOT EDIT. diff --git a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/doc.go b/operator/crd/client/clientset/versioned/typed/netapp/v1/fake/doc.go similarity index 69% rename from operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/doc.go rename to operator/crd/client/clientset/versioned/typed/netapp/v1/fake/doc.go index 0ed352683..b87e6aba9 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/doc.go +++ b/operator/crd/client/clientset/versioned/typed/netapp/v1/fake/doc.go @@ -1,4 +1,4 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by client-gen. DO NOT EDIT. diff --git a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go b/operator/crd/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go similarity index 66% rename from operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go rename to operator/crd/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go index 70153a002..4be0e7062 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go +++ b/operator/crd/client/clientset/versioned/typed/netapp/v1/fake/fake_netapp_client.go @@ -1,11 +1,11 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by client-gen. DO NOT EDIT. package fake import ( - v1 "github.com/netapp/trident/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1" + v1 "github.com/netapp/trident/operator/crd/client/clientset/versioned/typed/netapp/v1" rest "k8s.io/client-go/rest" testing "k8s.io/client-go/testing" ) @@ -14,6 +14,10 @@ type FakeTridentV1 struct { *testing.Fake } +func (c *FakeTridentV1) TridentConfigurators() v1.TridentConfiguratorInterface { + return &FakeTridentConfigurators{c} +} + func (c *FakeTridentV1) TridentOrchestrators() v1.TridentOrchestratorInterface { return &FakeTridentOrchestrators{c} } diff --git a/operator/crd/client/clientset/versioned/typed/netapp/v1/fake/fake_tridentconfigurator.go b/operator/crd/client/clientset/versioned/typed/netapp/v1/fake/fake_tridentconfigurator.go new file mode 100644 index 000000000..c5b7c1ce5 --- /dev/null +++ b/operator/crd/client/clientset/versioned/typed/netapp/v1/fake/fake_tridentconfigurator.go @@ -0,0 +1,119 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + netappv1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeTridentConfigurators implements TridentConfiguratorInterface +type FakeTridentConfigurators struct { + Fake *FakeTridentV1 +} + +var tridentconfiguratorsResource = schema.GroupVersionResource{Group: "trident.netapp.io", Version: "v1", Resource: "tridentconfigurators"} + +var tridentconfiguratorsKind = schema.GroupVersionKind{Group: "trident.netapp.io", Version: "v1", Kind: "TridentConfigurator"} + +// Get takes name of the tridentConfigurator, and returns the corresponding tridentConfigurator object, and an error if there is any. +func (c *FakeTridentConfigurators) Get(ctx context.Context, name string, options v1.GetOptions) (result *netappv1.TridentConfigurator, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(tridentconfiguratorsResource, name), &netappv1.TridentConfigurator{}) + if obj == nil { + return nil, err + } + return obj.(*netappv1.TridentConfigurator), err +} + +// List takes label and field selectors, and returns the list of TridentConfigurators that match those selectors. +func (c *FakeTridentConfigurators) List(ctx context.Context, opts v1.ListOptions) (result *netappv1.TridentConfiguratorList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(tridentconfiguratorsResource, tridentconfiguratorsKind, opts), &netappv1.TridentConfiguratorList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &netappv1.TridentConfiguratorList{ListMeta: obj.(*netappv1.TridentConfiguratorList).ListMeta} + for _, item := range obj.(*netappv1.TridentConfiguratorList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested tridentConfigurators. +func (c *FakeTridentConfigurators) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(tridentconfiguratorsResource, opts)) +} + +// Create takes the representation of a tridentConfigurator and creates it. Returns the server's representation of the tridentConfigurator, and an error, if there is any. +func (c *FakeTridentConfigurators) Create(ctx context.Context, tridentConfigurator *netappv1.TridentConfigurator, opts v1.CreateOptions) (result *netappv1.TridentConfigurator, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(tridentconfiguratorsResource, tridentConfigurator), &netappv1.TridentConfigurator{}) + if obj == nil { + return nil, err + } + return obj.(*netappv1.TridentConfigurator), err +} + +// Update takes the representation of a tridentConfigurator and updates it. Returns the server's representation of the tridentConfigurator, and an error, if there is any. +func (c *FakeTridentConfigurators) Update(ctx context.Context, tridentConfigurator *netappv1.TridentConfigurator, opts v1.UpdateOptions) (result *netappv1.TridentConfigurator, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(tridentconfiguratorsResource, tridentConfigurator), &netappv1.TridentConfigurator{}) + if obj == nil { + return nil, err + } + return obj.(*netappv1.TridentConfigurator), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeTridentConfigurators) UpdateStatus(ctx context.Context, tridentConfigurator *netappv1.TridentConfigurator, opts v1.UpdateOptions) (*netappv1.TridentConfigurator, error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(tridentconfiguratorsResource, "status", tridentConfigurator), &netappv1.TridentConfigurator{}) + if obj == nil { + return nil, err + } + return obj.(*netappv1.TridentConfigurator), err +} + +// Delete takes name of the tridentConfigurator and deletes it. Returns an error if one occurs. +func (c *FakeTridentConfigurators) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteAction(tridentconfiguratorsResource, name), &netappv1.TridentConfigurator{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeTridentConfigurators) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(tridentconfiguratorsResource, listOpts) + + _, err := c.Fake.Invokes(action, &netappv1.TridentConfiguratorList{}) + return err +} + +// Patch applies the patch and returns the patched tridentConfigurator. +func (c *FakeTridentConfigurators) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *netappv1.TridentConfigurator, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(tridentconfiguratorsResource, name, pt, data, subresources...), &netappv1.TridentConfigurator{}) + if obj == nil { + return nil, err + } + return obj.(*netappv1.TridentConfigurator), err +} diff --git a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/fake_tridentorchestrator.go b/operator/crd/client/clientset/versioned/typed/netapp/v1/fake/fake_tridentorchestrator.go similarity index 97% rename from operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/fake_tridentorchestrator.go rename to operator/crd/client/clientset/versioned/typed/netapp/v1/fake/fake_tridentorchestrator.go index 9f1f7c53f..d49ae8b98 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/fake/fake_tridentorchestrator.go +++ b/operator/crd/client/clientset/versioned/typed/netapp/v1/fake/fake_tridentorchestrator.go @@ -1,4 +1,4 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by client-gen. DO NOT EDIT. @@ -7,7 +7,7 @@ package fake import ( "context" - netappv1 "github.com/netapp/trident/operator/controllers/orchestrator/apis/netapp/v1" + netappv1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" labels "k8s.io/apimachinery/pkg/labels" schema "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/generated_expansion.go b/operator/crd/client/clientset/versioned/typed/netapp/v1/generated_expansion.go similarity index 51% rename from operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/generated_expansion.go rename to operator/crd/client/clientset/versioned/typed/netapp/v1/generated_expansion.go index 7135c9dac..62c308536 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/generated_expansion.go +++ b/operator/crd/client/clientset/versioned/typed/netapp/v1/generated_expansion.go @@ -1,7 +1,9 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by client-gen. DO NOT EDIT. package v1 +type TridentConfiguratorExpansion interface{} + type TridentOrchestratorExpansion interface{} diff --git a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/netapp_client.go b/operator/crd/client/clientset/versioned/typed/netapp/v1/netapp_client.go similarity index 83% rename from operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/netapp_client.go rename to operator/crd/client/clientset/versioned/typed/netapp/v1/netapp_client.go index cb9075601..efd6579d2 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/netapp_client.go +++ b/operator/crd/client/clientset/versioned/typed/netapp/v1/netapp_client.go @@ -1,17 +1,18 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by client-gen. DO NOT EDIT. package v1 import ( - v1 "github.com/netapp/trident/operator/controllers/orchestrator/apis/netapp/v1" - "github.com/netapp/trident/operator/controllers/orchestrator/client/clientset/versioned/scheme" + v1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" + "github.com/netapp/trident/operator/crd/client/clientset/versioned/scheme" rest "k8s.io/client-go/rest" ) type TridentV1Interface interface { RESTClient() rest.Interface + TridentConfiguratorsGetter TridentOrchestratorsGetter } @@ -20,6 +21,10 @@ type TridentV1Client struct { restClient rest.Interface } +func (c *TridentV1Client) TridentConfigurators() TridentConfiguratorInterface { + return newTridentConfigurators(c) +} + func (c *TridentV1Client) TridentOrchestrators() TridentOrchestratorInterface { return newTridentOrchestrators(c) } diff --git a/operator/crd/client/clientset/versioned/typed/netapp/v1/tridentconfigurator.go b/operator/crd/client/clientset/versioned/typed/netapp/v1/tridentconfigurator.go new file mode 100644 index 000000000..ed3898f09 --- /dev/null +++ b/operator/crd/client/clientset/versioned/typed/netapp/v1/tridentconfigurator.go @@ -0,0 +1,170 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +// Code generated by client-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + "time" + + v1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" + scheme "github.com/netapp/trident/operator/crd/client/clientset/versioned/scheme" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// TridentConfiguratorsGetter has a method to return a TridentConfiguratorInterface. +// A group's client should implement this interface. +type TridentConfiguratorsGetter interface { + TridentConfigurators() TridentConfiguratorInterface +} + +// TridentConfiguratorInterface has methods to work with TridentConfigurator resources. +type TridentConfiguratorInterface interface { + Create(ctx context.Context, tridentConfigurator *v1.TridentConfigurator, opts metav1.CreateOptions) (*v1.TridentConfigurator, error) + Update(ctx context.Context, tridentConfigurator *v1.TridentConfigurator, opts metav1.UpdateOptions) (*v1.TridentConfigurator, error) + UpdateStatus(ctx context.Context, tridentConfigurator *v1.TridentConfigurator, opts metav1.UpdateOptions) (*v1.TridentConfigurator, error) + Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error + Get(ctx context.Context, name string, opts metav1.GetOptions) (*v1.TridentConfigurator, error) + List(ctx context.Context, opts metav1.ListOptions) (*v1.TridentConfiguratorList, error) + Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.TridentConfigurator, err error) + TridentConfiguratorExpansion +} + +// tridentConfigurators implements TridentConfiguratorInterface +type tridentConfigurators struct { + client rest.Interface +} + +// newTridentConfigurators returns a TridentConfigurators +func newTridentConfigurators(c *TridentV1Client) *tridentConfigurators { + return &tridentConfigurators{ + client: c.RESTClient(), + } +} + +// Get takes name of the tridentConfigurator, and returns the corresponding tridentConfigurator object, and an error if there is any. +func (c *tridentConfigurators) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.TridentConfigurator, err error) { + result = &v1.TridentConfigurator{} + err = c.client.Get(). + Resource("tridentconfigurators"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of TridentConfigurators that match those selectors. +func (c *tridentConfigurators) List(ctx context.Context, opts metav1.ListOptions) (result *v1.TridentConfiguratorList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1.TridentConfiguratorList{} + err = c.client.Get(). + Resource("tridentconfigurators"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested tridentConfigurators. +func (c *tridentConfigurators) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Resource("tridentconfigurators"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a tridentConfigurator and creates it. Returns the server's representation of the tridentConfigurator, and an error, if there is any. +func (c *tridentConfigurators) Create(ctx context.Context, tridentConfigurator *v1.TridentConfigurator, opts metav1.CreateOptions) (result *v1.TridentConfigurator, err error) { + result = &v1.TridentConfigurator{} + err = c.client.Post(). + Resource("tridentconfigurators"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(tridentConfigurator). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a tridentConfigurator and updates it. Returns the server's representation of the tridentConfigurator, and an error, if there is any. +func (c *tridentConfigurators) Update(ctx context.Context, tridentConfigurator *v1.TridentConfigurator, opts metav1.UpdateOptions) (result *v1.TridentConfigurator, err error) { + result = &v1.TridentConfigurator{} + err = c.client.Put(). + Resource("tridentconfigurators"). + Name(tridentConfigurator.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(tridentConfigurator). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *tridentConfigurators) UpdateStatus(ctx context.Context, tridentConfigurator *v1.TridentConfigurator, opts metav1.UpdateOptions) (result *v1.TridentConfigurator, err error) { + result = &v1.TridentConfigurator{} + err = c.client.Put(). + Resource("tridentconfigurators"). + Name(tridentConfigurator.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(tridentConfigurator). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the tridentConfigurator and deletes it. Returns an error if one occurs. +func (c *tridentConfigurators) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + return c.client.Delete(). + Resource("tridentconfigurators"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *tridentConfigurators) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Resource("tridentconfigurators"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched tridentConfigurator. +func (c *tridentConfigurators) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.TridentConfigurator, err error) { + result = &v1.TridentConfigurator{} + err = c.client.Patch(pt). + Resource("tridentconfigurators"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/tridentorchestrator.go b/operator/crd/client/clientset/versioned/typed/netapp/v1/tridentorchestrator.go similarity index 96% rename from operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/tridentorchestrator.go rename to operator/crd/client/clientset/versioned/typed/netapp/v1/tridentorchestrator.go index 505bac55b..68f9e889a 100644 --- a/operator/controllers/orchestrator/client/clientset/versioned/typed/netapp/v1/tridentorchestrator.go +++ b/operator/crd/client/clientset/versioned/typed/netapp/v1/tridentorchestrator.go @@ -1,4 +1,4 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by client-gen. DO NOT EDIT. @@ -8,8 +8,8 @@ import ( "context" "time" - v1 "github.com/netapp/trident/operator/controllers/orchestrator/apis/netapp/v1" - scheme "github.com/netapp/trident/operator/controllers/orchestrator/client/clientset/versioned/scheme" + v1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" + scheme "github.com/netapp/trident/operator/crd/client/clientset/versioned/scheme" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" types "k8s.io/apimachinery/pkg/types" watch "k8s.io/apimachinery/pkg/watch" diff --git a/operator/controllers/orchestrator/client/informers/externalversions/factory.go b/operator/crd/client/informers/externalversions/factory.go similarity index 93% rename from operator/controllers/orchestrator/client/informers/externalversions/factory.go rename to operator/crd/client/informers/externalversions/factory.go index 7f56bc1ce..5af14f4ae 100644 --- a/operator/controllers/orchestrator/client/informers/externalversions/factory.go +++ b/operator/crd/client/informers/externalversions/factory.go @@ -1,4 +1,4 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by informer-gen. DO NOT EDIT. @@ -9,9 +9,9 @@ import ( sync "sync" time "time" - versioned "github.com/netapp/trident/operator/controllers/orchestrator/client/clientset/versioned" - internalinterfaces "github.com/netapp/trident/operator/controllers/orchestrator/client/informers/externalversions/internalinterfaces" - netapp "github.com/netapp/trident/operator/controllers/orchestrator/client/informers/externalversions/netapp" + versioned "github.com/netapp/trident/operator/crd/client/clientset/versioned" + internalinterfaces "github.com/netapp/trident/operator/crd/client/informers/externalversions/internalinterfaces" + netapp "github.com/netapp/trident/operator/crd/client/informers/externalversions/netapp" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" schema "k8s.io/apimachinery/pkg/runtime/schema" diff --git a/operator/controllers/orchestrator/client/informers/externalversions/generic.go b/operator/crd/client/informers/externalversions/generic.go similarity index 81% rename from operator/controllers/orchestrator/client/informers/externalversions/generic.go rename to operator/crd/client/informers/externalversions/generic.go index 966d1f1f0..a2a058adf 100644 --- a/operator/controllers/orchestrator/client/informers/externalversions/generic.go +++ b/operator/crd/client/informers/externalversions/generic.go @@ -1,4 +1,4 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by informer-gen. DO NOT EDIT. @@ -7,7 +7,7 @@ package externalversions import ( "fmt" - v1 "github.com/netapp/trident/operator/controllers/orchestrator/apis/netapp/v1" + v1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" schema "k8s.io/apimachinery/pkg/runtime/schema" cache "k8s.io/client-go/tools/cache" ) @@ -39,6 +39,8 @@ func (f *genericInformer) Lister() cache.GenericLister { func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { switch resource { // Group=trident.netapp.io, Version=v1 + case v1.SchemeGroupVersion.WithResource("tridentconfigurators"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Trident().V1().TridentConfigurators().Informer()}, nil case v1.SchemeGroupVersion.WithResource("tridentorchestrators"): return &genericInformer{resource: resource.GroupResource(), informer: f.Trident().V1().TridentOrchestrators().Informer()}, nil diff --git a/operator/controllers/orchestrator/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/operator/crd/client/informers/externalversions/internalinterfaces/factory_interfaces.go similarity index 83% rename from operator/controllers/orchestrator/client/informers/externalversions/internalinterfaces/factory_interfaces.go rename to operator/crd/client/informers/externalversions/internalinterfaces/factory_interfaces.go index 20457a9f6..5faddfc27 100644 --- a/operator/controllers/orchestrator/client/informers/externalversions/internalinterfaces/factory_interfaces.go +++ b/operator/crd/client/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -1,4 +1,4 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by informer-gen. DO NOT EDIT. @@ -7,7 +7,7 @@ package internalinterfaces import ( time "time" - versioned "github.com/netapp/trident/operator/controllers/orchestrator/client/clientset/versioned" + versioned "github.com/netapp/trident/operator/crd/client/clientset/versioned" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" cache "k8s.io/client-go/tools/cache" diff --git a/operator/controllers/orchestrator/client/informers/externalversions/netapp/interface.go b/operator/crd/client/informers/externalversions/netapp/interface.go similarity index 73% rename from operator/controllers/orchestrator/client/informers/externalversions/netapp/interface.go rename to operator/crd/client/informers/externalversions/netapp/interface.go index bc21b7157..34d183d3b 100644 --- a/operator/controllers/orchestrator/client/informers/externalversions/netapp/interface.go +++ b/operator/crd/client/informers/externalversions/netapp/interface.go @@ -1,12 +1,12 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by informer-gen. DO NOT EDIT. package netapp import ( - internalinterfaces "github.com/netapp/trident/operator/controllers/orchestrator/client/informers/externalversions/internalinterfaces" - v1 "github.com/netapp/trident/operator/controllers/orchestrator/client/informers/externalversions/netapp/v1" + internalinterfaces "github.com/netapp/trident/operator/crd/client/informers/externalversions/internalinterfaces" + v1 "github.com/netapp/trident/operator/crd/client/informers/externalversions/netapp/v1" ) // Interface provides access to each of this group's versions. diff --git a/operator/controllers/orchestrator/client/informers/externalversions/netapp/v1/interface.go b/operator/crd/client/informers/externalversions/netapp/v1/interface.go similarity index 64% rename from operator/controllers/orchestrator/client/informers/externalversions/netapp/v1/interface.go rename to operator/crd/client/informers/externalversions/netapp/v1/interface.go index c2988b25d..654a99cbc 100644 --- a/operator/controllers/orchestrator/client/informers/externalversions/netapp/v1/interface.go +++ b/operator/crd/client/informers/externalversions/netapp/v1/interface.go @@ -1,15 +1,17 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by informer-gen. DO NOT EDIT. package v1 import ( - internalinterfaces "github.com/netapp/trident/operator/controllers/orchestrator/client/informers/externalversions/internalinterfaces" + internalinterfaces "github.com/netapp/trident/operator/crd/client/informers/externalversions/internalinterfaces" ) // Interface provides access to all the informers in this group version. type Interface interface { + // TridentConfigurators returns a TridentConfiguratorInformer. + TridentConfigurators() TridentConfiguratorInformer // TridentOrchestrators returns a TridentOrchestratorInformer. TridentOrchestrators() TridentOrchestratorInformer } @@ -25,6 +27,11 @@ func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakList return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} } +// TridentConfigurators returns a TridentConfiguratorInformer. +func (v *version) TridentConfigurators() TridentConfiguratorInformer { + return &tridentConfiguratorInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} +} + // TridentOrchestrators returns a TridentOrchestratorInformer. func (v *version) TridentOrchestrators() TridentOrchestratorInformer { return &tridentOrchestratorInformer{factory: v.factory, tweakListOptions: v.tweakListOptions} diff --git a/operator/crd/client/informers/externalversions/netapp/v1/tridentconfigurator.go b/operator/crd/client/informers/externalversions/netapp/v1/tridentconfigurator.go new file mode 100644 index 000000000..57cf40c40 --- /dev/null +++ b/operator/crd/client/informers/externalversions/netapp/v1/tridentconfigurator.go @@ -0,0 +1,75 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1 + +import ( + "context" + time "time" + + netappv1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" + versioned "github.com/netapp/trident/operator/crd/client/clientset/versioned" + internalinterfaces "github.com/netapp/trident/operator/crd/client/informers/externalversions/internalinterfaces" + v1 "github.com/netapp/trident/operator/crd/client/listers/netapp/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// TridentConfiguratorInformer provides access to a shared informer and lister for +// TridentConfigurators. +type TridentConfiguratorInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1.TridentConfiguratorLister +} + +type tridentConfiguratorInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// NewTridentConfiguratorInformer constructs a new informer for TridentConfigurator 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 NewTridentConfiguratorInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredTridentConfiguratorInformer(client, resyncPeriod, indexers, nil) +} + +// NewFilteredTridentConfiguratorInformer constructs a new informer for TridentConfigurator 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 NewFilteredTridentConfiguratorInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options metav1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TridentV1().TridentConfigurators().List(context.TODO(), options) + }, + WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.TridentV1().TridentConfigurators().Watch(context.TODO(), options) + }, + }, + &netappv1.TridentConfigurator{}, + resyncPeriod, + indexers, + ) +} + +func (f *tridentConfiguratorInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredTridentConfiguratorInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *tridentConfiguratorInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&netappv1.TridentConfigurator{}, f.defaultInformer) +} + +func (f *tridentConfiguratorInformer) Lister() v1.TridentConfiguratorLister { + return v1.NewTridentConfiguratorLister(f.Informer().GetIndexer()) +} diff --git a/operator/controllers/orchestrator/client/informers/externalversions/netapp/v1/tridentorchestrator.go b/operator/crd/client/informers/externalversions/netapp/v1/tridentorchestrator.go similarity index 86% rename from operator/controllers/orchestrator/client/informers/externalversions/netapp/v1/tridentorchestrator.go rename to operator/crd/client/informers/externalversions/netapp/v1/tridentorchestrator.go index f1b9b223c..359c9b105 100644 --- a/operator/controllers/orchestrator/client/informers/externalversions/netapp/v1/tridentorchestrator.go +++ b/operator/crd/client/informers/externalversions/netapp/v1/tridentorchestrator.go @@ -1,4 +1,4 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by informer-gen. DO NOT EDIT. @@ -8,10 +8,10 @@ import ( "context" time "time" - netappv1 "github.com/netapp/trident/operator/controllers/orchestrator/apis/netapp/v1" - versioned "github.com/netapp/trident/operator/controllers/orchestrator/client/clientset/versioned" - internalinterfaces "github.com/netapp/trident/operator/controllers/orchestrator/client/informers/externalversions/internalinterfaces" - v1 "github.com/netapp/trident/operator/controllers/orchestrator/client/listers/netapp/v1" + netappv1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" + versioned "github.com/netapp/trident/operator/crd/client/clientset/versioned" + internalinterfaces "github.com/netapp/trident/operator/crd/client/informers/externalversions/internalinterfaces" + v1 "github.com/netapp/trident/operator/crd/client/listers/netapp/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" watch "k8s.io/apimachinery/pkg/watch" diff --git a/operator/controllers/orchestrator/client/listers/netapp/v1/expansion_generated.go b/operator/crd/client/listers/netapp/v1/expansion_generated.go similarity index 50% rename from operator/controllers/orchestrator/client/listers/netapp/v1/expansion_generated.go rename to operator/crd/client/listers/netapp/v1/expansion_generated.go index 3f9e69781..3cabae878 100644 --- a/operator/controllers/orchestrator/client/listers/netapp/v1/expansion_generated.go +++ b/operator/crd/client/listers/netapp/v1/expansion_generated.go @@ -1,9 +1,13 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by lister-gen. DO NOT EDIT. package v1 +// TridentConfiguratorListerExpansion allows custom methods to be added to +// TridentConfiguratorLister. +type TridentConfiguratorListerExpansion interface{} + // TridentOrchestratorListerExpansion allows custom methods to be added to // TridentOrchestratorLister. type TridentOrchestratorListerExpansion interface{} diff --git a/operator/crd/client/listers/netapp/v1/tridentconfigurator.go b/operator/crd/client/listers/netapp/v1/tridentconfigurator.go new file mode 100644 index 000000000..4251e8a5d --- /dev/null +++ b/operator/crd/client/listers/netapp/v1/tridentconfigurator.go @@ -0,0 +1,51 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1 + +import ( + v1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// TridentConfiguratorLister helps list TridentConfigurators. +type TridentConfiguratorLister interface { + // List lists all TridentConfigurators in the indexer. + List(selector labels.Selector) (ret []*v1.TridentConfigurator, err error) + // Get retrieves the TridentConfigurator from the index for a given name. + Get(name string) (*v1.TridentConfigurator, error) + TridentConfiguratorListerExpansion +} + +// tridentConfiguratorLister implements the TridentConfiguratorLister interface. +type tridentConfiguratorLister struct { + indexer cache.Indexer +} + +// NewTridentConfiguratorLister returns a new TridentConfiguratorLister. +func NewTridentConfiguratorLister(indexer cache.Indexer) TridentConfiguratorLister { + return &tridentConfiguratorLister{indexer: indexer} +} + +// List lists all TridentConfigurators in the indexer. +func (s *tridentConfiguratorLister) List(selector labels.Selector) (ret []*v1.TridentConfigurator, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1.TridentConfigurator)) + }) + return ret, err +} + +// Get retrieves the TridentConfigurator from the index for a given name. +func (s *tridentConfiguratorLister) Get(name string) (*v1.TridentConfigurator, error) { + obj, exists, err := s.indexer.GetByKey(name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1.Resource("tridentconfigurator"), name) + } + return obj.(*v1.TridentConfigurator), nil +} diff --git a/operator/controllers/orchestrator/client/listers/netapp/v1/tridentorchestrator.go b/operator/crd/client/listers/netapp/v1/tridentorchestrator.go similarity index 92% rename from operator/controllers/orchestrator/client/listers/netapp/v1/tridentorchestrator.go rename to operator/crd/client/listers/netapp/v1/tridentorchestrator.go index 42e2ef315..5a17f89ad 100644 --- a/operator/controllers/orchestrator/client/listers/netapp/v1/tridentorchestrator.go +++ b/operator/crd/client/listers/netapp/v1/tridentorchestrator.go @@ -1,11 +1,11 @@ -// Copyright 2023 NetApp, Inc. All Rights Reserved. +// Copyright 2024 NetApp, Inc. All Rights Reserved. // Code generated by lister-gen. DO NOT EDIT. package v1 import ( - v1 "github.com/netapp/trident/operator/controllers/orchestrator/apis/netapp/v1" + v1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/tools/cache" diff --git a/operator/frontend/frontend.go b/operator/frontend/frontend.go new file mode 100644 index 000000000..6778c991d --- /dev/null +++ b/operator/frontend/frontend.go @@ -0,0 +1,10 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package frontend + +type Frontend interface { + Activate() error + Deactivate() error + GetName() string + Version() string +} diff --git a/operator/frontend/rest/apiserver_http.go b/operator/frontend/rest/apiserver_http.go new file mode 100644 index 000000000..237e34cb4 --- /dev/null +++ b/operator/frontend/rest/apiserver_http.go @@ -0,0 +1,69 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package rest + +import ( + "context" + "fmt" + "net/http" + "time" + + . "github.com/netapp/trident/logging" + "github.com/netapp/trident/operator/clients" +) + +type APIServerHTTP struct { + server *http.Server +} + +const ( + httpReadTimeout = 90 * time.Second + httpWriteTimeout = 5 * time.Second + httpTimeout = 90 * time.Second + apiVersion = "1" +) + +func NewHTTPServer(address, port string, clientFactory *clients.Clients) *APIServerHTTP { + apiServer := &APIServerHTTP{ + server: &http.Server{ + Addr: fmt.Sprintf("%s:%s", address, port), + Handler: NewRouter(clientFactory), + ReadTimeout: httpReadTimeout, + WriteTimeout: httpWriteTimeout, + }, + } + + Log().WithField("address", apiServer.server.Addr).Info("Initializing HTTP REST frontend.") + return apiServer +} + +func (s *APIServerHTTP) Activate() error { + go func() { + Log().WithField("address", s.server.Addr).Info("Activating HTTP REST frontend.") + + err := s.server.ListenAndServe() + if err == http.ErrServerClosed { + Log().WithField("address", s.server.Addr).Info("HTTP REST frontend server has closed.") + } else if err != nil { + Log().Fatal(err) + } + }() + + return nil +} + +func (s *APIServerHTTP) Deactivate() error { + Log().WithField("address", s.server.Addr).Info("Deactivating HTTP REST frontend.") + ctx, cancel := context.WithTimeout(context.Background(), httpTimeout) + defer cancel() + + return s.server.Shutdown(ctx) +} + +func (s *APIServerHTTP) GetName() string { + return "Operator HTTP REST Server" +} + +func (s *APIServerHTTP) Version() string { + return apiVersion +} diff --git a/operator/frontend/rest/handler.go b/operator/frontend/rest/handler.go new file mode 100644 index 000000000..b5e32a191 --- /dev/null +++ b/operator/frontend/rest/handler.go @@ -0,0 +1,113 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package rest + +import ( + "encoding/json" + "net/http" + + cliapi "github.com/netapp/trident/cli/api" + "github.com/netapp/trident/operator/clients" + operatorV1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" +) + +type OperatorHandler struct { + oClient clients.OperatorCRDClientInterface +} + +func NewOperatorHandler(clientFactory *clients.Clients) *OperatorHandler { + return &OperatorHandler{oClient: clients.NewOperatorCRDClient(clientFactory.CRDClient)} +} + +func (h *OperatorHandler) GetStatus(w http.ResponseWriter, _ *http.Request) { + httpStatusCode := http.StatusOK + + operatorStatus, err := h.getStatus() + if err != nil { + httpStatusCode = http.StatusInternalServerError + operatorStatus.Status = string(cliapi.OperatorPhaseError) + operatorStatus.ErrorMessage = err.Error() + } + + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(httpStatusCode) + _ = json.NewEncoder(w).Encode(operatorStatus) +} + +func (h *OperatorHandler) getStatus() (cliapi.OperatorStatus, error) { + var torcCR *operatorV1.TridentOrchestrator + + configuratorsInstalled := true + configuratorsProcessing := false + status := cliapi.OperatorStatus{ + TorcStatus: make(map[string]cliapi.CRStatus, operatorV1.MaxNumberOfTridentOrchestrators), + TconfStatus: make(map[string]cliapi.CRStatus), + } + + torcCRList, err := h.oClient.GetTorcCRList() + if err != nil { + return status, err + } + + // Ideally, there will be none (tridentctl installation) or a single TorcCR present. + if len(torcCRList.Items) > operatorV1.MaxNumberOfTridentOrchestrators { + status.Status = string(cliapi.OperatorPhaseUnknown) + status.ErrorMessage = "More than one Trident Orchestrator CR found" + return status, nil + } + + if len(torcCRList.Items) == 1 { + torcCR = &torcCRList.Items[0] + status.TorcStatus[torcCR.Name] = cliapi.CRStatus{Status: torcCR.Status.Status, Message: torcCR.Status.Message} + } + + tconfCRList, err := h.oClient.GetTconfCRList() + if err != nil { + return status, err + } + + for _, tconfCR := range tconfCRList.Items { + status.TconfStatus[tconfCR.Name] = cliapi.CRStatus{ + Status: tconfCR.Status.LastOperationStatus, + Message: tconfCR.Status.Message, + } + + if tconfCR.Status.LastOperationStatus == string(operatorV1.Processing) || + tconfCR.Status.LastOperationStatus == "" { + configuratorsProcessing = true + } + if tconfCR.Status.LastOperationStatus == string(operatorV1.Failed) { + configuratorsInstalled = false + } + } + + if torcCR != nil && torcCR.IsTridentOperationInProgress() { + status.Status = string(cliapi.OperatorPhaseProcessing) + return status, nil + } + + if torcCR != nil && torcCR.HasTridentInstallationFailed() { + status.Status = string(cliapi.OperatorPhaseFailed) + return status, nil + } + + // We consider that Trident is installed beyond this point. + + // If all the TconfCRs are processed successfully, we should report operator status as "Done". + if configuratorsInstalled { + status.Status = string(cliapi.OperatorPhaseDone) + } + + // If any one of the TconfCR is in processing state, we should report operator status as "Processing". + if configuratorsProcessing { + status.Status = string(cliapi.OperatorPhaseProcessing) + } + + // If no TconfCR is in processing state and at least one of the TconfCR failed, we should report operator + // status as "Failed". + if !configuratorsProcessing && !configuratorsInstalled { + status.Status = string(cliapi.OperatorPhaseFailed) + } + + return status, nil +} diff --git a/operator/frontend/rest/handler_test.go b/operator/frontend/rest/handler_test.go new file mode 100644 index 000000000..96369baff --- /dev/null +++ b/operator/frontend/rest/handler_test.go @@ -0,0 +1,146 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package rest + +import ( + "fmt" + "testing" + + "github.com/golang/mock/gomock" + "github.com/stretchr/testify/assert" + + cliapi "github.com/netapp/trident/cli/api" + mockClients "github.com/netapp/trident/mocks/mock_operator/mock_clients" + operatorV1 "github.com/netapp/trident/operator/crd/apis/netapp/v1" +) + +func getTorcAndTconfList() (*operatorV1.TridentOrchestratorList, *operatorV1.TridentConfiguratorList) { + torc := operatorV1.TridentOrchestrator{ + Status: operatorV1.TridentOrchestratorStatus{Status: string(operatorV1.AppStatusInstalled)}, + } + torcList := &operatorV1.TridentOrchestratorList{ + Items: []operatorV1.TridentOrchestrator{torc}, + } + + tconf1 := &operatorV1.TridentConfigurator{} + tconf2 := &operatorV1.TridentConfigurator{} + tconfList := &operatorV1.TridentConfiguratorList{ + Items: []*operatorV1.TridentConfigurator{tconf1, tconf2}, + } + + return torcList, tconfList +} + +func TestOperatorHandler_GetStatus(t *testing.T) { + tests := []struct { + name string + status string + err bool + mockFunc func(*mockClients.MockOperatorCRDClientInterface) + }{ + { + name: "TorcListError", + status: "", + err: true, + mockFunc: func(client *mockClients.MockOperatorCRDClientInterface) { + client.EXPECT().GetTorcCRList().Return(nil, fmt.Errorf("failed to get torc list")) + }, + }, + { + name: "MoreThanOneTorc", + status: string(cliapi.OperatorPhaseUnknown), + err: false, + mockFunc: func(client *mockClients.MockOperatorCRDClientInterface) { + torcList, _ := getTorcAndTconfList() + torc2 := operatorV1.TridentOrchestrator{} + torcList.Items = append(torcList.Items, torc2) + client.EXPECT().GetTorcCRList().Return(torcList, nil) + }, + }, + { + name: "TconfListError", + status: "", + err: true, + mockFunc: func(client *mockClients.MockOperatorCRDClientInterface) { + client.EXPECT().GetTorcCRList().Return(&operatorV1.TridentOrchestratorList{}, nil) + client.EXPECT().GetTconfCRList().Return(nil, fmt.Errorf("failed to get tconf list")) + }, + }, + { + name: "OperatorInstallingTrident", + status: string(cliapi.OperatorPhaseProcessing), + err: false, + mockFunc: func(client *mockClients.MockOperatorCRDClientInterface) { + torcList, tconfList := getTorcAndTconfList() + torcList.Items[0].Status = operatorV1.TridentOrchestratorStatus{Status: string(operatorV1.AppStatusInstalling)} + client.EXPECT().GetTorcCRList().Return(torcList, nil) + client.EXPECT().GetTconfCRList().Return(tconfList, nil) + }, + }, + { + name: "OperatorTridentInstallFailed", + status: string(cliapi.OperatorPhaseFailed), + err: false, + mockFunc: func(client *mockClients.MockOperatorCRDClientInterface) { + torcList, tconfList := getTorcAndTconfList() + torcList.Items[0].Status = operatorV1.TridentOrchestratorStatus{Status: string(operatorV1.AppStatusFailed)} + client.EXPECT().GetTorcCRList().Return(torcList, nil) + client.EXPECT().GetTconfCRList().Return(tconfList, nil) + }, + }, + { + name: "OperatorAllConfiguratorsSuccess", + status: string(cliapi.OperatorPhaseDone), + err: false, + mockFunc: func(client *mockClients.MockOperatorCRDClientInterface) { + torcList, tconfList := getTorcAndTconfList() + tconfList.Items[0].Status = operatorV1.TridentConfiguratorStatus{LastOperationStatus: string(operatorV1.Success)} + tconfList.Items[1].Status = operatorV1.TridentConfiguratorStatus{LastOperationStatus: string(operatorV1.Success)} + client.EXPECT().GetTorcCRList().Return(torcList, nil) + client.EXPECT().GetTconfCRList().Return(tconfList, nil) + }, + }, + { + name: "OperatorAtLeastOneConfiguratorProcessing", + status: string(cliapi.OperatorPhaseProcessing), + err: false, + mockFunc: func(client *mockClients.MockOperatorCRDClientInterface) { + torcList, tconfList := getTorcAndTconfList() + tconfList.Items[0].Status = operatorV1.TridentConfiguratorStatus{LastOperationStatus: string(operatorV1.Processing)} + tconfList.Items[1].Status = operatorV1.TridentConfiguratorStatus{LastOperationStatus: string(operatorV1.Failed)} + client.EXPECT().GetTorcCRList().Return(torcList, nil) + client.EXPECT().GetTconfCRList().Return(tconfList, nil) + }, + }, + { + name: "OperatorOneConfiguratorFailedAndOthersSucceeded", + status: string(cliapi.OperatorPhaseFailed), + err: false, + mockFunc: func(client *mockClients.MockOperatorCRDClientInterface) { + torcList, tconfList := getTorcAndTconfList() + tconfList.Items[0].Status = operatorV1.TridentConfiguratorStatus{LastOperationStatus: string(operatorV1.Failed)} + tconfList.Items[1].Status = operatorV1.TridentConfiguratorStatus{LastOperationStatus: string(operatorV1.Success)} + client.EXPECT().GetTorcCRList().Return(torcList, nil) + client.EXPECT().GetTconfCRList().Return(tconfList, nil) + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + mockCtrl := gomock.NewController(t) + mockOperatorClient := mockClients.NewMockOperatorCRDClientInterface(mockCtrl) + oh := OperatorHandler{oClient: mockOperatorClient} + + test.mockFunc(mockOperatorClient) + + status, err := oh.getStatus() + + if test.err { + assert.Error(t, err, "Failed to get status.") + } else { + assert.Equal(t, test.status, status.Status) + } + }) + } +} diff --git a/operator/frontend/rest/routes.go b/operator/frontend/rest/routes.go new file mode 100644 index 000000000..30c3c7b35 --- /dev/null +++ b/operator/frontend/rest/routes.go @@ -0,0 +1,52 @@ +// Copyright 2024 NetApp, Inc. All Rights Reserved. + +package rest + +import ( + "net/http" + + "github.com/gorilla/mux" + + logger "github.com/netapp/trident/frontend/rest" + "github.com/netapp/trident/operator/clients" +) + +type route struct { + Name string + Method string + Pattern string + HandlerFunc http.HandlerFunc +} + +// NewRouter is used to set up HTTP and HTTPS endpoints for the controller +func NewRouter(clientFactory *clients.Clients) *mux.Router { + return newRouter(clientFactory) +} + +func newRouter(clientFactory *clients.Clients) *mux.Router { + opHandler := NewOperatorHandler(clientFactory) + + router := mux.NewRouter() + routes := []route{ + { + "readiness", + "GET", + "/operator/status", + opHandler.GetStatus, + }, + } + + for _, r := range routes { + var handler http.Handler + handler = r.HandlerFunc + handler = logger.Logger(handler, r.Name) + + router. + Methods(r.Method). + Path(r.Pattern). + Name(r.Name). + Handler(r.HandlerFunc) + } + + return router +} diff --git a/operator/main.go b/operator/main.go index f557b8ea4..242fbd1b9 100644 --- a/operator/main.go +++ b/operator/main.go @@ -17,7 +17,9 @@ import ( operatorclient "github.com/netapp/trident/operator/clients" "github.com/netapp/trident/operator/config" "github.com/netapp/trident/operator/controllers" + "github.com/netapp/trident/operator/controllers/configurator" "github.com/netapp/trident/operator/controllers/orchestrator" + "github.com/netapp/trident/operator/frontend/rest" ) var ( @@ -30,6 +32,14 @@ var ( k8sAPIServer = flag.String("k8s-api-server", "", "Kubernetes API server address") k8sConfigPath = flag.String("k8s-config-path", "", "Path to KubeConfig file") skipK8sVersionCheck = flag.Bool("skip-k8s-version-check", false, "(Deprecated) Skip Kubernetes version check for Trident compatibility") + + configuratorReconcileInterval = flag.Duration("configurator-reconcile-interval", + config.ConfiguratorReconcileInterval, "Set resource refresh rate for the auto generated backends") +) + +const ( + operatorCheckAddress = "" + operatorCheckPort = "8002" ) func printFlag(f *flag.Flag) { @@ -41,7 +51,7 @@ func main() { runtime.GOMAXPROCS(runtime.NumCPU()) flag.Parse() - crdControllers := make([]controllers.Controller, 0) + frontends := make([]controllers.Controller, 0) // Seed RNG one time rand.Seed(time.Now().UnixNano()) @@ -88,14 +98,24 @@ func main() { } // Create Trident Orchestrator controller - tridentOrchestrator, err := orchestrator.NewController(k8sClients) + torcFrontend, err := orchestrator.NewController(k8sClients) if err != nil { Log().WithField("error", err).Fatalf("Could not create Trident Orchestrator controller.") } - crdControllers = append(crdControllers, tridentOrchestrator) - // Activate the controllers - for _, c := range crdControllers { + // Create Trident Configurator controller + tconfFrontend, err := configurator.NewController(k8sClients, *configuratorReconcileInterval) + if err != nil { + Log().WithField("error", err).Fatalf("Could not create Trident Configurator controller.") + } + + // Create the Operator frontend + operatorFrontend := rest.NewHTTPServer(operatorCheckAddress, operatorCheckPort, k8sClients) + + frontends = append(frontends, torcFrontend, tconfFrontend, operatorFrontend) + + // Activate the frontends + for _, c := range frontends { _ = c.Activate() } @@ -105,8 +125,8 @@ func main() { <-c Log().Info("Shutting down.") - // Deactivate the controllers - for _, c := range crdControllers { + // Deactivate the frontends + for _, c := range frontends { _ = c.Deactivate() } } diff --git a/storage_drivers/azure/api/azure_discovery.go b/storage_drivers/azure/api/azure_discovery.go index 9a358c4d3..2299c49ac 100644 --- a/storage_drivers/azure/api/azure_discovery.go +++ b/storage_drivers/azure/api/azure_discovery.go @@ -999,3 +999,109 @@ func (c Client) RandomSubnetForStoragePool(ctx context.Context, sPool storage.Po return filteredSubnets[crypto.GetRandomNumber(len(filteredSubnets))] } + +// AZ Client Functions for AKS Extension + +func (c Client) FilteredCapacityPoolMap( + ctx context.Context, rgFilter, naFilter, cpFilter []string, +) map[string]*CapacityPool { + // This map tracks which capacity pools have passed the filters + filteredCapacityPoolMap := make(map[string]bool) + + // Start with all capacity pools marked as passing the filters + for cPoolFullName := range c.sdkClient.CapacityPoolMap { + filteredCapacityPoolMap[cPoolFullName] = true + } + + if len(rgFilter) > 0 { + for cPoolFullName, cPool := range c.sdkClient.CapacityPoolMap { + if !utils.SliceContainsString(rgFilter, cPool.ResourceGroup) { + Logd(ctx, c.config.StorageDriverName, c.config.DebugTraceFlags["discovery"]). + Debugf("Ignoring capacity pool %s, not in resource groups [%s].", cPoolFullName, rgFilter) + filteredCapacityPoolMap[cPoolFullName] = false + } + } + } + + if len(naFilter) > 0 { + for cPoolFullName, cPool := range c.sdkClient.CapacityPoolMap { + naName := cPool.NetAppAccount + naFullName := CreateNetappAccountFullName(cPool.ResourceGroup, cPool.NetAppAccount) + if !utils.SliceContainsString(naFilter, naName) && !utils.SliceContainsString(naFilter, naFullName) { + Logd(ctx, c.config.StorageDriverName, c.config.DebugTraceFlags["discovery"]). + Debugf("Ignoring capacity pool %s, not in netapp accounts [%s].", cPoolFullName, naFilter) + filteredCapacityPoolMap[cPoolFullName] = false + } + } + } + + if len(cpFilter) > 0 { + for cPoolFullName, cPool := range c.sdkClient.CapacityPoolMap { + if !utils.SliceContainsString(cpFilter, cPool.Name) && !utils.SliceContainsString(cpFilter, cPoolFullName) { + Logd(ctx, c.config.StorageDriverName, c.config.DebugTraceFlags["discovery"]). + Debugf("Ignoring capacity pool %s, not in capacity pools [%s].", cPoolFullName, cpFilter) + filteredCapacityPoolMap[cPoolFullName] = false + } + } + } + + newCapacityPoolMap := make(map[string]*CapacityPool) + for cpFullName, present := range filteredCapacityPoolMap { + if present { + newCapacityPoolMap[cpFullName] = c.sdkClient.CapacityPoolMap[cpFullName] + } + } + + return newCapacityPoolMap +} + +func (c Client) FilteredSubnetMap( + ctx context.Context, rgFilter []string, vnFilter, snFilter string, +) map[string]*Subnet { + filteredSubnetMap := make(map[string]bool) + + for subnetFullName := range c.sdkClient.SubnetMap { + filteredSubnetMap[subnetFullName] = true + } + + if len(rgFilter) > 0 { + for subnetFullName, subnet := range c.sdkClient.SubnetMap { + if !utils.SliceContainsString(rgFilter, subnet.ResourceGroup) { + Logd(ctx, c.config.StorageDriverName, c.config.DebugTraceFlags["discovery"]). + Tracef("Ignoring subnet %s, not in resource groups [%s].", subnetFullName, rgFilter) + filteredSubnetMap[subnetFullName] = false + } + } + } + + if vnFilter != "" { + for subnetFullName, subnet := range c.sdkClient.SubnetMap { + vnName := subnet.VirtualNetwork + vnFullName := CreateVirtualNetworkFullName(subnet.ResourceGroup, subnet.VirtualNetwork) + if vnFilter != vnName && vnFilter != vnFullName { + Logd(ctx, c.config.StorageDriverName, c.config.DebugTraceFlags["discovery"]). + Debugf("Ignoring subnet %s, not in virtual network %s.", subnetFullName, vnFilter) + filteredSubnetMap[subnetFullName] = false + } + } + } + + if snFilter != "" { + for subnetFullName, subnet := range c.sdkClient.SubnetMap { + if snFilter != subnet.Name && snFilter != subnetFullName { + Logd(ctx, c.config.StorageDriverName, c.config.DebugTraceFlags["discovery"]). + Debugf("Ignoring subnet %s, not equal to subnet %s.", subnetFullName, snFilter) + filteredSubnetMap[subnetFullName] = false + } + } + } + + newSubnetMap := make(map[string]*Subnet) + for snFullName, present := range filteredSubnetMap { + if present { + newSubnetMap[snFullName] = c.sdkClient.SubnetMap[snFullName] + } + } + + return newSubnetMap +} diff --git a/storage_drivers/azure/api/azure_discovery_test.go b/storage_drivers/azure/api/azure_discovery_test.go index fafd235d9..a52bff652 100644 --- a/storage_drivers/azure/api/azure_discovery_test.go +++ b/storage_drivers/azure/api/azure_discovery_test.go @@ -5,6 +5,7 @@ package api import ( "context" "math/rand" + "strings" "testing" "time" @@ -845,7 +846,7 @@ func TestEnsureVolumeInValidCapacityPool(t *testing.T) { assert.Nil(t, sdk.EnsureVolumeInValidCapacityPool(context.TODO(), volume), "result not nil") } -func TestSubnetsForStoragePool(t *testing.T) { +func TestSubnetsForStoragePoolAndFilteredSubnetMap(t *testing.T) { sdk := getFakeSDK() RG1_VN1_SN1 := sdk.subnet("RG1/VN1/SN1") RG1_VN2_SN2 := sdk.subnet("RG1/VN2/SN2") @@ -971,4 +972,129 @@ func TestSubnetsForStoragePool(t *testing.T) { assert.Nil(t, subnet) } } + + for _, test := range tests { + var rgFilter []string + if test.resourceGroups != "" { + rgFilter = strings.Split(test.resourceGroups, ",") + } + + subnetMap := sdk.FilteredSubnetMap(context.TODO(), rgFilter, test.virtualNetwork, test.subnet) + var subnetList []*Subnet + for _, subnet := range subnetMap { + subnetList = append(subnetList, subnet) + } + + if len(test.expected) > 0 { + assert.ElementsMatch(t, test.expected, subnetList) + } else { + assert.Nil(t, subnetList) + } + } +} + +func TestFilteredCapacityPoolMap(t *testing.T) { + sdk := getFakeSDK() + RG1_NA1_CP1 := sdk.capacityPool("RG1/NA1/CP1") + RG1_NA1_CP2 := sdk.capacityPool("RG1/NA1/CP2") + RG1_NA2_CP1 := sdk.capacityPool("RG1/NA2/CP1") + RG1_NA2_CP2 := sdk.capacityPool("RG1/NA2/CP2") + RG2_NA1_CP1 := sdk.capacityPool("RG2/NA1/CP1") + RG2_NA1_CP2 := sdk.capacityPool("RG2/NA1/CP2") + RG2_NA2_CP3 := sdk.capacityPool("RG2/NA2/CP3") + + tests := []struct { + resourceGroups []string + netappAccounts []string + capacityPools []string + expected []*CapacityPool + }{ + { + resourceGroups: []string{"RG1"}, + netappAccounts: []string{}, + capacityPools: []string{}, + expected: []*CapacityPool{RG1_NA1_CP1, RG1_NA1_CP2, RG1_NA2_CP1, RG1_NA2_CP2}, + }, + { + resourceGroups: []string{"RG2"}, + netappAccounts: []string{}, + capacityPools: []string{}, + expected: []*CapacityPool{RG2_NA1_CP1, RG2_NA1_CP2, RG2_NA2_CP3}, + }, + { + resourceGroups: []string{}, + netappAccounts: []string{}, + capacityPools: []string{}, + expected: []*CapacityPool{RG1_NA1_CP1, RG1_NA1_CP2, RG1_NA2_CP1, RG1_NA2_CP2, RG2_NA1_CP1, RG2_NA1_CP2, RG2_NA2_CP3}, + }, + { + resourceGroups: []string{}, + netappAccounts: []string{"NA1"}, + capacityPools: []string{}, + expected: []*CapacityPool{RG1_NA1_CP1, RG1_NA1_CP2, RG2_NA1_CP1, RG2_NA1_CP2}, + }, + { + resourceGroups: []string{}, + netappAccounts: []string{"NA2"}, + capacityPools: []string{}, + expected: []*CapacityPool{RG1_NA2_CP1, RG1_NA2_CP2, RG2_NA2_CP3}, + }, + { + resourceGroups: []string{"RG2"}, + netappAccounts: []string{"NA2"}, + capacityPools: []string{"CP3"}, + expected: []*CapacityPool{RG2_NA2_CP3}, + }, + { + resourceGroups: []string{}, + netappAccounts: []string{}, + capacityPools: []string{"RG1/NA1/CP2"}, + expected: []*CapacityPool{RG1_NA1_CP2}, + }, + { + resourceGroups: []string{}, + netappAccounts: []string{}, + capacityPools: []string{"CP2"}, + expected: []*CapacityPool{RG1_NA1_CP2, RG1_NA2_CP2, RG2_NA1_CP2}, + }, + { + resourceGroups: []string{"RG3"}, + netappAccounts: []string{}, + capacityPools: []string{}, + expected: []*CapacityPool{}, + }, + { + resourceGroups: []string{}, + netappAccounts: []string{"NA3"}, + capacityPools: []string{}, + expected: []*CapacityPool{}, + }, + { + resourceGroups: []string{}, + netappAccounts: []string{}, + capacityPools: []string{"CP4"}, + expected: []*CapacityPool{}, + }, + { + resourceGroups: []string{}, + netappAccounts: []string{}, + capacityPools: []string{"RG3/NA3/CP4"}, + expected: []*CapacityPool{}, + }, + } + + for _, test := range tests { + cpMap := sdk.FilteredCapacityPoolMap(context.TODO(), test.resourceGroups, test.netappAccounts, test.capacityPools) + + var cpList []*CapacityPool + for _, cp := range cpMap { + cpList = append(cpList, cp) + } + + if len(test.expected) > 0 { + assert.ElementsMatch(t, test.expected, cpList) + } else { + assert.Nil(t, cpList) + } + } } diff --git a/storage_drivers/azure/api/types.go b/storage_drivers/azure/api/types.go index 42a2f8725..a39bbceba 100644 --- a/storage_drivers/azure/api/types.go +++ b/storage_drivers/azure/api/types.go @@ -25,6 +25,8 @@ type Azure interface { EnsureVolumeInValidCapacityPool(context.Context, *FileSystem) error SubnetsForStoragePool(context.Context, storage.Pool) []*Subnet RandomSubnetForStoragePool(context.Context, storage.Pool) *Subnet + FilteredCapacityPoolMap(ctx context.Context, rgFilter, naFilter, cpFilter []string) map[string]*CapacityPool + FilteredSubnetMap(ctx context.Context, rgFilter []string, vnFilter, snFilter string) map[string]*Subnet Volumes(context.Context) (*[]*FileSystem, error) Volume(context.Context, *storage.VolumeConfig) (*FileSystem, error)