diff --git a/.golangci.yml b/.golangci.yml index 25adf6f68e..f508b31c77 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -68,27 +68,27 @@ linters-settings: exclude: - '^ \+.*' - '^ ANCHOR.*' - # gocritic: - # enabled-tags: - # - diagnostic - # - experimental - # - performance - # disabled-checks: - # - appendAssign - # - dupImport # https://github.com/go-critic/go-critic/issues/845 - # - evalOrder - # - ifElseChain - # - octalLiteral - # - regexpSimplify - # - sloppyReassign - # - truncateCmp - # - typeDefFirst - # - unnamedResult - # - unnecessaryDefer - # - whyNoLint - # - wrapperFunc - # - rangeValCopy - # - hugeParam + gocritic: + enabled-tags: + - diagnostic + - experimental + - performance + disabled-checks: + - appendAssign + - dupImport # https://github.com/go-critic/go-critic/issues/845 + - evalOrder + - ifElseChain + - octalLiteral + - regexpSimplify + - sloppyReassign + - truncateCmp + - typeDefFirst + - unnamedResult + - unnecessaryDefer + - whyNoLint + - wrapperFunc + - rangeValCopy + - hugeParam importas: no-unaliased: true alias: diff --git a/apis/v1alpha3/cloudprovider_encoding_test.go b/apis/v1alpha3/cloudprovider_encoding_test.go index ca7d8ae9b1..82285cb81f 100644 --- a/apis/v1alpha3/cloudprovider_encoding_test.go +++ b/apis/v1alpha3/cloudprovider_encoding_test.go @@ -610,7 +610,6 @@ func TestUnmarshalINI(t *testing.T) { }, } - //nolint:gocritic testCases := append( testcases, deprecatedTestCases..., diff --git a/apis/v1alpha3/cloudprovider_types.go b/apis/v1alpha3/cloudprovider_types.go index 043ed3eb6d..b3bfb83669 100644 --- a/apis/v1alpha3/cloudprovider_types.go +++ b/apis/v1alpha3/cloudprovider_types.go @@ -23,7 +23,7 @@ limitations under the License. // // The "gopkg.in/go-ini/ini.v1" package was investigated, but it does not // support reflecting a struct with a field of type "map[string]TYPE" to INI. -//nolint:gocritic,godot + package v1alpha3 // CPIConfig is the vSphere cloud provider's configuration. diff --git a/apis/v1alpha3/haproxyloadbalancer_types.go b/apis/v1alpha3/haproxyloadbalancer_types.go index b5c2736c96..c821ef018f 100644 --- a/apis/v1alpha3/haproxyloadbalancer_types.go +++ b/apis/v1alpha3/haproxyloadbalancer_types.go @@ -14,7 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -//nolint:gocritic,godot package v1alpha3 import ( diff --git a/apis/v1alpha3/vspherecluster_types.go b/apis/v1alpha3/vspherecluster_types.go index 008e0cfb7c..2a1702de1d 100644 --- a/apis/v1alpha3/vspherecluster_types.go +++ b/apis/v1alpha3/vspherecluster_types.go @@ -14,7 +14,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -//nolint:gocritic,godot package v1alpha3 import ( diff --git a/apis/v1alpha4/vspheremachinetemplate_conversion.go b/apis/v1alpha4/vspheremachinetemplate_conversion.go index 43fe4977ef..e1c2a4ea8e 100644 --- a/apis/v1alpha4/vspheremachinetemplate_conversion.go +++ b/apis/v1alpha4/vspheremachinetemplate_conversion.go @@ -26,7 +26,7 @@ import ( infrav1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1" ) -// ConvertTo. +// ConvertTo converts this VSphereMachineTemplate to the Hub version (v1beta1). func (src *VSphereMachineTemplate) ConvertTo(dstRaw conversion.Hub) error { dst := dstRaw.(*infrav1.VSphereMachineTemplate) if err := Convert_v1alpha4_VSphereMachineTemplate_To_v1beta1_VSphereMachineTemplate(src, dst, nil); err != nil { @@ -51,6 +51,7 @@ func (src *VSphereMachineTemplate) ConvertTo(dstRaw conversion.Hub) error { return nil } +// ConvertFrom converts from the Hub version (v1beta1) to this VSphereMachineTemplate. func (dst *VSphereMachineTemplate) ConvertFrom(srcRaw conversion.Hub) error { src := srcRaw.(*infrav1.VSphereMachineTemplate) if err := Convert_v1beta1_VSphereMachineTemplate_To_v1alpha4_VSphereMachineTemplate(src, dst, nil); err != nil { diff --git a/controllers/controllers_suite_test.go b/controllers/controllers_suite_test.go index 5b54b3d2b9..8883837797 100644 --- a/controllers/controllers_suite_test.go +++ b/controllers/controllers_suite_test.go @@ -51,9 +51,7 @@ var ( func TestMain(m *testing.M) { setup() - defer func() { - teardown() - }() + defer teardown() code := m.Run() os.Exit(code) //nolint:gocritic } diff --git a/controllers/servicediscovery_controller.go b/controllers/servicediscovery_controller.go index 2b8872cc22..5899a64cd9 100644 --- a/controllers/servicediscovery_controller.go +++ b/controllers/servicediscovery_controller.go @@ -429,7 +429,7 @@ func getSupervisorAPIServerURLWithFIP(client client.Client) (string, error) { // tryParseClusterInfoFromConfigMap tries to parse a kubeconfig file from a ConfigMap key. func tryParseClusterInfoFromConfigMap(cm *corev1.ConfigMap) (*clientcmdapi.Config, error) { kubeConfigString, ok := cm.Data[bootstrapapi.KubeConfigKey] - if !ok || len(kubeConfigString) == 0 { + if !ok || kubeConfigString == "" { return nil, errors.Errorf("no %s key in ConfigMap %s/%s", bootstrapapi.KubeConfigKey, cm.Namespace, cm.Name) } parsedKubeConfig, err := clientcmd.Load([]byte(kubeConfigString)) diff --git a/controllers/vspherecluster_reconciler.go b/controllers/vspherecluster_reconciler.go index 65aac0a8b8..7ea6d4559b 100644 --- a/controllers/vspherecluster_reconciler.go +++ b/controllers/vspherecluster_reconciler.go @@ -153,18 +153,19 @@ func (r clusterReconciler) reconcileDelete(clusterCtx *capvcontext.ClusterContex // If the VSphereMachine is not owned by the CAPI Machine object because the machine object was deleted // before setting the owner references, then proceed with the deletion of the VSphereMachine object. // This is required until CAPI has a solution for https://github.com/kubernetes-sigs/cluster-api/issues/5483 - if clusterutilv1.IsOwnedByObject(vsphereMachine, clusterCtx.VSphereCluster) && len(vsphereMachine.OwnerReferences) == 1 { - machineDeletionCount++ - // Remove the finalizer since VM creation wouldn't proceed - r.Logger.Info("Removing finalizer from VSphereMachine", "namespace", vsphereMachine.Namespace, "name", vsphereMachine.Name) - ctrlutil.RemoveFinalizer(vsphereMachine, infrav1.MachineFinalizer) - if err := r.Client.Update(clusterCtx, vsphereMachine); err != nil { - return reconcile.Result{}, err - } - if err := r.Client.Delete(clusterCtx, vsphereMachine); err != nil && !apierrors.IsNotFound(err) { - clusterCtx.Logger.Error(err, "Failed to delete for VSphereMachine", "namespace", vsphereMachine.Namespace, "name", vsphereMachine.Name) - deletionErrors = append(deletionErrors, err) - } + if !clusterutilv1.IsOwnedByObject(vsphereMachine, clusterCtx.VSphereCluster) || len(vsphereMachine.OwnerReferences) != 1 { + continue + } + machineDeletionCount++ + // Remove the finalizer since VM creation wouldn't proceed + r.Logger.Info("Removing finalizer from VSphereMachine", "namespace", vsphereMachine.Namespace, "name", vsphereMachine.Name) + ctrlutil.RemoveFinalizer(vsphereMachine, infrav1.MachineFinalizer) + if err := r.Client.Update(clusterCtx, vsphereMachine); err != nil { + return reconcile.Result{}, err + } + if err := r.Client.Delete(clusterCtx, vsphereMachine); err != nil && !apierrors.IsNotFound(err) { + clusterCtx.Logger.Error(err, "Failed to delete for VSphereMachine", "namespace", vsphereMachine.Namespace, "name", vsphereMachine.Name) + deletionErrors = append(deletionErrors, err) } } if len(deletionErrors) > 0 { diff --git a/controllers/vspheredeploymentzone_controller.go b/controllers/vspheredeploymentzone_controller.go index 14be19e5e7..77a59a7a53 100644 --- a/controllers/vspheredeploymentzone_controller.go +++ b/controllers/vspheredeploymentzone_controller.go @@ -243,20 +243,21 @@ func (r vsphereDeploymentZoneReconciler) getVCenterSession(deploymentZoneCtx *ca } for _, vsphereCluster := range clusterList.Items { - if deploymentZoneCtx.VSphereDeploymentZone.Spec.Server == vsphereCluster.Spec.Server && vsphereCluster.Spec.IdentityRef != nil { - logger := deploymentZoneCtx.Logger.WithValues("cluster", vsphereCluster.Name) - params = params.WithThumbprint(vsphereCluster.Spec.Thumbprint) - clust := vsphereCluster - creds, err := identity.GetCredentials(deploymentZoneCtx, r.Client, &clust, r.Namespace) - if err != nil { - logger.Error(err, "error retrieving credentials from IdentityRef") - continue - } - logger.Info("using server credentials to create the authenticated session") - params = params.WithUserInfo(creds.Username, creds.Password) - return session.GetOrCreate(r.Context, - params) + if deploymentZoneCtx.VSphereDeploymentZone.Spec.Server != vsphereCluster.Spec.Server || vsphereCluster.Spec.IdentityRef == nil { + continue + } + logger := deploymentZoneCtx.Logger.WithValues("cluster", vsphereCluster.Name) + params = params.WithThumbprint(vsphereCluster.Spec.Thumbprint) + clust := vsphereCluster + creds, err := identity.GetCredentials(deploymentZoneCtx, r.Client, &clust, r.Namespace) + if err != nil { + logger.Error(err, "error retrieving credentials from IdentityRef") + continue } + logger.Info("using server credentials to create the authenticated session") + params = params.WithUserInfo(creds.Username, creds.Password) + return session.GetOrCreate(r.Context, + params) } // Fallback to using credentials provided to the manager diff --git a/controllers/vspheredeploymentzone_controller_domain_test.go b/controllers/vspheredeploymentzone_controller_domain_test.go index a46c095468..bce0507249 100644 --- a/controllers/vspheredeploymentzone_controller_domain_test.go +++ b/controllers/vspheredeploymentzone_controller_domain_test.go @@ -32,13 +32,7 @@ import ( "sigs.k8s.io/cluster-api-provider-vsphere/test/helpers/vcsim" ) -//nolint:paralleltest -func TestVsphereDeploymentZoneReconciler_Reconcile_VerifyFailureDomain(t *testing.T) { - t.Run("for Compute Cluster Zone Failure Domain", ForComputeClusterZone) - t.Run("for Host Group Zone Failure Domain", ForHostGroupZone) -} - -func ForComputeClusterZone(t *testing.T) { +func TestVsphereDeploymentZoneReconciler_Reconcile_VerifyFailureDomain_ComputeClusterZone(t *testing.T) { g := NewWithT(t) model := simulator.VPX() @@ -120,7 +114,7 @@ func ForComputeClusterZone(t *testing.T) { g.Expect(reconciler.verifyFailureDomain(deploymentZoneCtx, vsphereFailureDomain.Spec.Zone)).To(HaveOccurred()) } -func ForHostGroupZone(t *testing.T) { +func TestVsphereDeploymentZoneReconciler_Reconcile_VerifyFailureDomain_HostGroupZone(t *testing.T) { g := NewWithT(t) model := simulator.VPX() diff --git a/controllers/vspherevm_controller_test.go b/controllers/vspherevm_controller_test.go index 94c71eaa70..bae9d662d6 100644 --- a/controllers/vspherevm_controller_test.go +++ b/controllers/vspherevm_controller_test.go @@ -710,31 +710,32 @@ func createMachineOwnerHierarchy(machine *clusterv1.Machine) []client.Object { clusterName, _ = machine.Labels[clusterv1.ClusterNameLabel] ) - objs = append(objs, &clusterv1.MachineSet{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-ms", machine.Name), - Namespace: machine.Namespace, - Labels: map[string]string{ - clusterv1.ClusterNameLabel: clusterName, - }, - OwnerReferences: []metav1.OwnerReference{ - { - APIVersion: clusterv1.GroupVersion.String(), - Kind: "MachineDeployment", - Name: fmt.Sprintf("%s-md", machine.Name), + objs = append( + objs, + &clusterv1.MachineSet{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-ms", machine.Name), + Namespace: machine.Namespace, + Labels: map[string]string{ + clusterv1.ClusterNameLabel: clusterName, + }, + OwnerReferences: []metav1.OwnerReference{ + { + APIVersion: clusterv1.GroupVersion.String(), + Kind: "MachineDeployment", + Name: fmt.Sprintf("%s-md", machine.Name), + }, }, }, }, - }) - - objs = append(objs, &clusterv1.MachineDeployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-md", machine.Name), - Namespace: machine.Namespace, - Labels: map[string]string{ - clusterv1.ClusterNameLabel: clusterName, + &clusterv1.MachineDeployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-md", machine.Name), + Namespace: machine.Namespace, + Labels: map[string]string{ + clusterv1.ClusterNameLabel: clusterName, + }, }, - }, - }) + }) return objs } diff --git a/pkg/manager/manager_test.go b/pkg/manager/manager_test.go index 01d4c1e8ed..8d1c33ae80 100644 --- a/pkg/manager/manager_test.go +++ b/pkg/manager/manager_test.go @@ -63,7 +63,7 @@ password: '%s' // Update the file and wait for watch to detect the change content := fmt.Sprintf(contentFmt, updatedUsername, updatedPassword) - _, err = tmpFile.Write([]byte(content)) + _, err = tmpFile.WriteString(content) g.Expect(err).ToNot(HaveOccurred()) g.Eventually(func() bool { @@ -98,7 +98,7 @@ password: '%s' // Update the file and wait for watch to detect the change content := fmt.Sprintf(contentFmt, updatedUsername, updatedPassword) - if _, err := tmpFile.Write([]byte(content)); err != nil { + if _, err := tmpFile.WriteString(content); err != nil { fmt.Printf("failed to update credentials in the file err:%s", err.Error()) } diff --git a/pkg/manager/options_test.go b/pkg/manager/options_test.go index ab12284a48..4d1d9cc6f2 100644 --- a/pkg/manager/options_test.go +++ b/pkg/manager/options_test.go @@ -62,7 +62,7 @@ password: '%s' } t.Cleanup(func() { os.Remove(tmpFile.Name()) }) - if _, err := tmpFile.Write([]byte(content)); err != nil { + if _, err := tmpFile.WriteString(content); err != nil { t.Fatal(err) } if err := tmpFile.Close(); err != nil { diff --git a/pkg/services/govmomi/util.go b/pkg/services/govmomi/util.go index 78873682ad..2a9c2f9b83 100644 --- a/pkg/services/govmomi/util.go +++ b/pkg/services/govmomi/util.go @@ -366,7 +366,7 @@ func waitForMacAddresses(ctx *virtualMachineContext) error { func getMacAddresses(ctx *virtualMachineContext) ([]string, map[string]int, map[int]string, error) { var ( vm mo.VirtualMachine - macAddresses []string + macAddresses = make([]string, 0) macToDeviceSpecIndex = map[string]int{} deviceSpecIndexToMac = map[int]string{} ) @@ -375,13 +375,15 @@ func getMacAddresses(ctx *virtualMachineContext) ([]string, map[string]int, map[ } i := 0 for _, device := range vm.Config.Hardware.Device { - if nic, ok := device.(types.BaseVirtualEthernetCard); ok { - mac := nic.GetVirtualEthernetCard().MacAddress - macAddresses = append(macAddresses, mac) - macToDeviceSpecIndex[mac] = i - deviceSpecIndexToMac[i] = mac - i++ + nic, ok := device.(types.BaseVirtualEthernetCard) + if !ok { + continue } + mac := nic.GetVirtualEthernetCard().MacAddress + macAddresses = append(macAddresses, mac) + macToDeviceSpecIndex[mac] = i + deviceSpecIndexToMac[i] = mac + i++ } return macAddresses, macToDeviceSpecIndex, deviceSpecIndexToMac, nil } diff --git a/pkg/services/govmomi/vcenter/clone_test.go b/pkg/services/govmomi/vcenter/clone_test.go index e304c99486..67c9385358 100644 --- a/pkg/services/govmomi/vcenter/clone_test.go +++ b/pkg/services/govmomi/vcenter/clone_test.go @@ -122,12 +122,7 @@ func TestGetDiskSpec(t *testing.T) { } vmContext := &context.VMContext{VSphereVM: vsphereVM} devices, err := getDiskSpec(vmContext, tc.disks) - switch { - case tc.err != "" && err == nil: - fallthrough - case tc.err == "" && err != nil: - fallthrough - case err != nil && tc.err != err.Error(): + if (tc.err != "" && err == nil) || (tc.err == "" && err != nil) || (err != nil && tc.err != err.Error()) { t.Fatalf("Expected to get '%v' error from getDiskSpec, got: '%v'", tc.err, err) } if deviceFound := len(devices) != 0; tc.expectDevice != deviceFound { diff --git a/pkg/util/label_test.go b/pkg/util/label_test.go index 793d913aa4..dacbbd421c 100644 --- a/pkg/util/label_test.go +++ b/pkg/util/label_test.go @@ -22,12 +22,7 @@ import ( "github.com/onsi/gomega" ) -func TestSanitizeHostInfoLabel(t *testing.T) { - t.Run("for IP addresses", testIPAddressLogic) - t.Run("for DNS entries", testDNSLogic) -} - -func testIPAddressLogic(t *testing.T) { +func TestSanitizeIPHostInfoLabel(t *testing.T) { tests := []struct { name, input, expected string }{ @@ -61,7 +56,7 @@ func testIPAddressLogic(t *testing.T) { } } -func testDNSLogic(t *testing.T) { +func TestSanitizeDNSHostInfoLabel(t *testing.T) { tests := []struct { name, input, expected string }{ diff --git a/test/e2e/gpu_pci_passthrough_test.go b/test/e2e/gpu_pci_passthrough_test.go index 7cddf7aaf4..55a3f3f4fc 100644 --- a/test/e2e/gpu_pci_passthrough_test.go +++ b/test/e2e/gpu_pci_passthrough_test.go @@ -75,18 +75,19 @@ var _ = Describe("Cluster creation with GPU devices as PCI passthrough [speciali func verifyPCIDeviceOnWorkerNodes(clusterName, namespace string) { list := getVSphereVMsForCluster(clusterName, namespace) for _, vm := range list.Items { - if _, ok := vm.GetLabels()[clusterv1.MachineControlPlaneLabel]; !ok { - finder := find.NewFinder(vsphereClient.Client, false) - dc, err := finder.Datacenter(ctx, vm.Spec.Datacenter) - Expect(err).NotTo(HaveOccurred()) - finder.SetDatacenter(dc) - - vmObj, err := finder.VirtualMachine(ctx, fmt.Sprintf("/%s/vm/%s/%s", vm.Spec.Datacenter, vm.Spec.Folder, vm.Name)) - Expect(err).NotTo(HaveOccurred()) - devices, err := vmObj.Device(ctx) - Expect(err).NotTo(HaveOccurred()) - defaultPciDevices := devices.SelectByType((*types.VirtualPCIPassthrough)(nil)) - Expect(defaultPciDevices).To(HaveLen(1)) + if _, ok := vm.GetLabels()[clusterv1.MachineControlPlaneLabel]; ok { + continue } + finder := find.NewFinder(vsphereClient.Client, false) + dc, err := finder.Datacenter(ctx, vm.Spec.Datacenter) + Expect(err).NotTo(HaveOccurred()) + finder.SetDatacenter(dc) + + vmObj, err := finder.VirtualMachine(ctx, fmt.Sprintf("/%s/vm/%s/%s", vm.Spec.Datacenter, vm.Spec.Folder, vm.Name)) + Expect(err).NotTo(HaveOccurred()) + devices, err := vmObj.Device(ctx) + Expect(err).NotTo(HaveOccurred()) + defaultPciDevices := devices.SelectByType((*types.VirtualPCIPassthrough)(nil)) + Expect(defaultPciDevices).To(HaveLen(1)) } } diff --git a/test/e2e/log_collector.go b/test/e2e/log_collector.go index cc59221f75..a79ea91d77 100644 --- a/test/e2e/log_collector.go +++ b/test/e2e/log_collector.go @@ -148,7 +148,7 @@ func newSSHConfig() (*ssh.ClientConfig, error) { func readPrivateKey() ([]byte, error) { privateKeyFilePath := os.Getenv(VSpherePrivateKeyFilePath) - if len(privateKeyFilePath) == 0 { + if privateKeyFilePath == "" { return nil, errors.Errorf("private key information missing. Please set %s environment variable", VSpherePrivateKeyFilePath) } diff --git a/test/helpers/vmware/intg_test_context.go b/test/helpers/vmware/intg_test_context.go index 3314a6011b..b19351bcb8 100644 --- a/test/helpers/vmware/intg_test_context.go +++ b/test/helpers/vmware/intg_test_context.go @@ -19,7 +19,6 @@ package vmware import ( "context" "fmt" - "path/filepath" "github.com/go-logr/logr" "github.com/google/uuid" @@ -109,17 +108,11 @@ func NewIntegrationTestContextWithClusters(ctx context.Context, integrationTestC }) var config *rest.Config + By("Creating guest cluster control plane", func() { // Initialize a test environment to simulate the control plane of the guest cluster. var err error - envTest := &envtest.Environment{ - // Add some form of CRD so the CRD object is registered in the - // scheme... - CRDDirectoryPaths: []string{ - filepath.Join("../../", "config", "default", "crd"), - filepath.Join("../../", "config", "supervisor", "crd"), - }, - } + envTest := &envtest.Environment{} envTest.ControlPlane.GetAPIServer().Configure().Set("allow-privileged", "true") config, err = envTest.Start() Expect(err).ShouldNot(HaveOccurred()) diff --git a/test/helpers/webhook.go b/test/helpers/webhook.go index 7bc1399645..e2caa3e7f0 100644 --- a/test/helpers/webhook.go +++ b/test/helpers/webhook.go @@ -23,7 +23,6 @@ import ( "path/filepath" goruntime "runtime" "strconv" - "strings" "time" v1 "k8s.io/api/admissionregistration/v1" @@ -55,7 +54,7 @@ func appendWebhookConfiguration(configyamlFile []byte, tag string) ([]*v1.Mutati // update the name in metadata if o.GetName() == mutatingwebhook { var m v1.MutatingWebhookConfiguration - o.SetName(strings.Join([]string{mutatingwebhook, "-", tag}, "")) + o.SetName(mutatingwebhook + "-" + tag) if err := scheme.Convert(&o, &m, nil); err != nil { return nil, nil, err } @@ -66,7 +65,7 @@ func appendWebhookConfiguration(configyamlFile []byte, tag string) ([]*v1.Mutati // update the name in metadata if o.GetName() == validatingwebhook { var v v1.ValidatingWebhookConfiguration - o.SetName(strings.Join([]string{validatingwebhook, "-", tag}, "")) + o.SetName(validatingwebhook + "-" + tag) if err := scheme.Convert(&o, &v, nil); err != nil { return nil, nil, err } diff --git a/test/integration/integration_suite_test.go b/test/integration/integration_suite_test.go index 00abb4a72e..4419017bdd 100644 --- a/test/integration/integration_suite_test.go +++ b/test/integration/integration_suite_test.go @@ -631,7 +631,6 @@ func updateResourceStatus(resource schema.GroupVersionResource, obj runtimeObjec Expect(err).NotTo(HaveOccurred(), "Error updating status of %s %s/%s", resource, obj.GetNamespace(), obj.GetName()) } -//nolint:gocritic func assertEventuallyExists(resource schema.GroupVersionResource, name, ns string, ownerRef *metav1.OwnerReference) *unstructuredv1.Unstructured { var obj *unstructuredv1.Unstructured EventuallyWithOffset(1, func() (bool, error) {