func Update(c UpdateConfig) (*unstructured.Unstructured, error) {
	client, err := c.ClientSet.ResourceClient(c.Inputs.GroupVersionKind(), c.Inputs.GetNamespace())
	if err != nil {
		return nil, err
	}
	liveOldObj, err := client.Get(context.TODO(), c.Previous.GetName(), metav1.GetOptions{})
	if err != nil {
		return nil, err
	}
	patch, patchType, _, err := openapi.PatchForResourceUpdate(c.Resources, c.Previous, c.Inputs, liveOldObj)
	if err != nil {
		return nil, err
	}
	var options metav1.PatchOptions
	if c.DryRun {
		options.DryRun = []string{metav1.DryRunAll}
	}
	currentOutputs, err := client.Patch(context.TODO(), c.Inputs.GetName(), patchType, patch, options)
	if err != nil {
		return nil, err
	}
	if c.DryRun {
		return currentOutputs, nil
	}
	id := fmt.Sprintf("%s/%s", c.Inputs.GetAPIVersion(), c.Inputs.GetKind())
	if awaiter, exists := awaiters[id]; exists {
		if metadata.SkipAwaitLogic(c.Inputs) {
			logger.V(1).Infof("Skipping await logic for %v", c.Inputs.GetName())
		} else {
			if awaiter.awaitUpdate != nil {
				conf := updateAwaitConfig{
					createAwaitConfig: createAwaitConfig{
						host:              c.Host,
						ctx:               c.Context,
						urn:               c.URN,
						initialAPIVersion: c.InitialAPIVersion,
						clientSet:         c.ClientSet,
						currentInputs:     c.Inputs,
						currentOutputs:    currentOutputs,
						logger:            c.DedupLogger,
						timeout:           c.Timeout,
					},
					lastInputs:  c.Previous,
					lastOutputs: liveOldObj,
				}
				waitErr := awaiter.awaitUpdate(conf)
				if waitErr != nil {
					return nil, waitErr
				}
			}
		}
	} else {
		logger.V(1).Infof("No initialization logic found for object of type %q; assuming initialization successful", id)
	}
	gvk := c.Inputs.GroupVersionKind()
	logger.V(3).Infof("Resource %s/%s/%s  '%s.%s' patched and updated", gvk.Group, gvk.Version,
		gvk.Kind, c.Inputs.GetNamespace(), c.Inputs.GetName())
	live, err := client.Get(context.TODO(), c.Inputs.GetName(), metav1.GetOptions{})
	if err != nil {
		return currentOutputs, nil
	}
	return live, nil
}
Update takes `lastSubmitted` (the last version of a Kubernetes API object submitted to the API
server) and `currentSubmitted` (the version of the Kubernetes API object being submitted for an
update currently) and blocks until one of the following is true: (1) the Kubernetes resource is
reported to be updated; (2) the update timeout has occurred; or (3) an error has occurred while
the resource was being updated.

Update updates an existing resource with new values. Currently this client supports the
Kubernetes-standard three-way JSON patch. See references here[1] and here[2].

nolint
[1]:
https://kubernetes.io/docs/tasks/run-application/update-api-object-kubectl-patch/#use-a-json-merge-patch-to-update-a-deployment
[2]:
https://kubernetes.io/docs/concepts/overview/object-management-kubectl/declarative-config/#how-apply-calculates-differences-and-merges-changes
package await
import (
	"context"
	"fmt"
	"github.com/pulumi/pulumi-kubernetes/provider/v3/pkg/clients"
	"github.com/pulumi/pulumi-kubernetes/provider/v3/pkg/cluster"
	"github.com/pulumi/pulumi-kubernetes/provider/v3/pkg/kinds"
	"github.com/pulumi/pulumi-kubernetes/provider/v3/pkg/logging"
	"github.com/pulumi/pulumi-kubernetes/provider/v3/pkg/metadata"
	"github.com/pulumi/pulumi-kubernetes/provider/v3/pkg/openapi"
	"github.com/pulumi/pulumi-kubernetes/provider/v3/pkg/retry"
	pulumiprovider "github.com/pulumi/pulumi/pkg/v3/resource/provider"
	"github.com/pulumi/pulumi/sdk/v3/go/common/diag"
	"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
	logger "github.com/pulumi/pulumi/sdk/v3/go/common/util/logging"
	"k8s.io/apimachinery/pkg/api/errors"
	"k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/fields"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/apimachinery/pkg/watch"
	"k8s.io/client-go/dynamic"
	k8sopenapi "k8s.io/kubectl/pkg/util/openapi"
)
type ProviderConfig struct {
	Context           context.Context
	Host              *pulumiprovider.HostClient
	URN               resource.URN
	InitialAPIVersion string
	ClusterVersion    *cluster.ServerVersion
	ClientSet   *clients.DynamicClientSet
	DedupLogger *logging.DedupLogger
	Resources   k8sopenapi.Resources
}
type CreateConfig struct {
	ProviderConfig
	Inputs  *unstructured.Unstructured
	Timeout float64
	DryRun  bool
}
type ReadConfig struct {
	ProviderConfig
	Inputs *unstructured.Unstructured
	Name   string
}
type UpdateConfig struct {
	ProviderConfig
	Previous *unstructured.Unstructured
	Inputs   *unstructured.Unstructured
	Timeout  float64
	DryRun   bool
}
type DeleteConfig struct {
	ProviderConfig
	Inputs  *unstructured.Unstructured
	Name    string
	Timeout float64
}
type ResourceID struct {
	Name       string
	Namespace  string  
	GVK        schema.GroupVersionKind
	Generation int64
}
func (r ResourceID) String() string {
	if len(r.Namespace) > 0 {
		return r.Namespace + "/" + r.Name
	}
	return r.Name
}
func (r ResourceID) GVKString() string {
	return fmt.Sprintf(`'[%s] %s'`, r.GVK, r.String())
}
func ResourceIDFromUnstructured(uns *unstructured.Unstructured) ResourceID {
	return ResourceID{
		Namespace:  clients.NamespaceOrDefault(uns.GetNamespace()),
		Name:       uns.GetName(),
		GVK:        uns.GroupVersionKind(),
		Generation: uns.GetGeneration(),
	}
}
func skipRetry(gvk schema.GroupVersionKind, k8sVersion *cluster.ServerVersion, err error,
) (bool, *cluster.ServerVersion) {
	if meta.IsNoMatchError(err) {
		if removed, version := kinds.RemovedAPIVersion(gvk, *k8sVersion); removed {
			return true, version
		}
	}
	return false, nil
}
func Creation(c CreateConfig) (*unstructured.Unstructured, error) {
	var options metav1.CreateOptions
	if c.DryRun {
		options.DryRun = []string{metav1.DryRunAll}
	}
	var outputs *unstructured.Unstructured
	var client dynamic.ResourceInterface
	err := retry.SleepingRetry(
		func(i uint) error {
			var err error
			if client == nil {
				client, err = c.ClientSet.ResourceClient(c.Inputs.GroupVersionKind(), c.Inputs.GetNamespace())
				if err != nil {
					if skip, version := skipRetry(c.Inputs.GroupVersionKind(), c.ClusterVersion, err); skip {
						return &kinds.RemovedAPIError{
							GVK:     c.Inputs.GroupVersionKind(),
							Version: version,
						}
					}
					_ = c.Host.LogStatus(c.Context, diag.Info, c.URN, fmt.Sprintf(
						"Retry #%d; creation failed: %v", i, err))
					return err
				}
			}
			outputs, err = client.Create(context.TODO(), c.Inputs, options)
			if err != nil {
				if c.DryRun && IsNamespaceNotFoundErr(err) {
					return &namespaceError{c.Inputs}
				}
				_ = c.Host.LogStatus(c.Context, diag.Info, c.URN, fmt.Sprintf(
					"Retry #%d; creation failed: %v", i, err))
				return err
			}
			return nil
		}).
		WithMaxRetries(5).
		WithBackoffFactor(2).
		Do(errors.IsNotFound, meta.IsNoMatchError)
	if err != nil {
		return nil, err
	}
	_ = clearStatus(c.Context, c.Host, c.URN)
	if c.DryRun {
		return outputs, nil
	}
	id := fmt.Sprintf("%s/%s", c.Inputs.GetAPIVersion(), c.Inputs.GetKind())
	if awaiter, exists := awaiters[id]; exists {
		if metadata.SkipAwaitLogic(c.Inputs) {
			logger.V(1).Infof("Skipping await logic for %v", c.Inputs.GetName())
		} else {
			if awaiter.awaitCreation != nil {
				conf := createAwaitConfig{
					host:              c.Host,
					ctx:               c.Context,
					urn:               c.URN,
					initialAPIVersion: c.InitialAPIVersion,
					clientSet:         c.ClientSet,
					currentInputs:     c.Inputs,
					currentOutputs:    outputs,
					logger:            c.DedupLogger,
					timeout:           c.Timeout,
				}
				waitErr := awaiter.awaitCreation(conf)
				if waitErr != nil {
					return nil, waitErr
				}
			}
		}
	} else {
		logger.V(1).Infof(
			"No initialization logic found for object of type %q; assuming initialization successful", id)
	}
	live, err := client.Get(context.TODO(), c.Inputs.GetName(), metav1.GetOptions{})
	if err != nil {
		return outputs, nil
	}
	return live, nil
}
func Read(c ReadConfig) (*unstructured.Unstructured, error) {
	client, err := c.ClientSet.ResourceClient(c.Inputs.GroupVersionKind(), c.Inputs.GetNamespace())
	if err != nil {
		return nil, err
	}
	outputs, err := client.Get(context.TODO(), c.Name, metav1.GetOptions{})
	if err != nil {
		return nil, err
	} else if c.Inputs == nil || len(c.Inputs.Object) == 0 {
		return outputs, nil
	}
	id := fmt.Sprintf("%s/%s", outputs.GetAPIVersion(), outputs.GetKind())
	if awaiter, exists := awaiters[id]; exists {
		if metadata.SkipAwaitLogic(c.Inputs) {
			logger.V(1).Infof("Skipping await logic for %v", c.Inputs.GetName())
		} else {
			if awaiter.awaitRead != nil {
				conf := createAwaitConfig{
					host:              c.Host,
					ctx:               c.Context,
					urn:               c.URN,
					initialAPIVersion: c.InitialAPIVersion,
					clientSet:         c.ClientSet,
					currentInputs:     c.Inputs,
					currentOutputs:    outputs,
					logger:            c.DedupLogger,
				}
				waitErr := awaiter.awaitRead(conf)
				if waitErr != nil {
					return nil, waitErr
				}
			}
		}
	}
	logger.V(1).Infof(
		"No read logic found for object of type %q; falling back to retrieving object", id)
	live, err := client.Get(context.TODO(), c.Name, metav1.GetOptions{})
	if err != nil {
		return outputs, nil
	}
	return live, nil
}