Repository: istio/istio
File: pkg/kube/client.go (Go)

Code before:
		fc.PrependWatchReactor("*", watchReactor(fc.Tracker()))
		fc.PrependReactor("create", "*", createReactor)
	}

	c.fastSync = true
	c.isFake = true

	c.version = lazy.NewWithRetry(c.kube.Discovery().ServerVersion)

	if NewCrdWatcher != nil {
		c.crdWatcher = NewCrdWatcher(c)
	}

	return c
}

func NewFakeClientWithVersion(minor string, objects ...runtime.Object) CLIClient {
	c := NewFakeClient(objects...).(*client)
	c.Kube().Discovery().(*fakediscovery.FakeDiscovery).FakedServerVersion = &kubeVersion.Info{Major: "1", Minor: minor, GitVersion: fmt.Sprintf("v1.%v.0", minor)}
	return c
}

// NewFakeClientWithFailures creates a fake client that fails for get operations on the specified
// resource kinds for the first failureCount attempts, then succeeds.
// failingResources is a set of resource (e.g., "pods", "namespaces") that should fail.
func NewFakeClientWithFailures(failureCount int, failingResources sets.Set[schema.GroupVersionResource], objects ...runtime.Object) CLIClient {
	c := NewFakeClient(objects...).(*client)

	// Track retry attempts per resource
	attempts := &sync.Map{}

	// Create a reactor that fails initially then succeeds
	retryReactor := func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
		// Only handle Get actions for failingResources
		if action.GetVerb() != "get" {
			return false, nil, nil
		}
		resource := action.GetResource()
		if !failingResources.Contains(resource) {
			return false, nil, nil
		}

		getAction := action.(clienttesting.GetAction)
		key := fmt.Sprintf("%s/%s/%s", resource, action.GetNamespace(), getAction.GetName())

		val, _ := attempts.LoadOrStore(key, atomic.NewInt32(0))
		attemptCounter := val.(*atomic.Int32)

		currentAttempt := attemptCounter.Inc()

		if int(currentAttempt) <= failureCount {

Review comment (bug):
I know it's different but it feels similar to NewErroringFakeClient. Maybe rename this one to `NewFakeClientWithTemporaryFailures`?

Code after:
		fc.PrependWatchReactor("*", watchReactor(fc.Tracker()))
		fc.PrependReactor("create", "*", createReactor)
	}

	c.fastSync = true
	c.isFake = true

	c.version = lazy.NewWithRetry(c.kube.Discovery().ServerVersion)

	if NewCrdWatcher != nil {
		c.crdWatcher = NewCrdWatcher(c)
	}

	return c
}

func NewFakeClientWithVersion(minor string, objects ...runtime.Object) CLIClient {
	c := NewFakeClient(objects...).(*client)
	c.Kube().Discovery().(*fakediscovery.FakeDiscovery).FakedServerVersion = &kubeVersion.Info{Major: "1", Minor: minor, GitVersion: fmt.Sprintf("v1.%v.0", minor)}
	return c
}

// NewFakeClientWithNFailures creates a fake client that fails for get operations on the specified
// resource kinds for the first failureCount attempts, then succeeds.
// failingResources is a set of resource (e.g., "pods", "namespaces") that should fail.
func NewFakeClientWithNFailures(failureCount int, failingResources sets.Set[schema.GroupVersionResource], objects ...runtime.Object) CLIClient {
	c := NewFakeClient(objects...).(*client)

	// Track retry attempts per resource
	attempts := &sync.Map{}

	// Create a reactor that fails initially then succeeds
	retryReactor := func(action clienttesting.Action) (handled bool, ret runtime.Object, err error) {
		// Only handle Get actions for failingResources
		if action.GetVerb() != "get" {
			return false, nil, nil
		}
		resource := action.GetResource()
		if !failingResources.Contains(resource) {
			return false, nil, nil
		}

		getAction := action.(clienttesting.GetAction)
		key := fmt.Sprintf("%s/%s/%s", resource, action.GetNamespace(), getAction.GetName())

		val, _ := attempts.LoadOrStore(key, atomic.NewInt32(0))
		attemptCounter := val.(*atomic.Int32)

		currentAttempt := attemptCounter.Inc()

		if int(currentAttempt) <= failureCount {