You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: uninstall.go
    path of file: ./repos/istio/operator/cmd/mesh
    
    the code of the file until where you have to start completion: // Copyright Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package mesh

import (
	"errors"
	"fmt"
	"os"
	"strings"

	"github.com/spf13/cobra"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"

	"istio.io/api/operator/v1alpha1"
	"istio.io/istio/istioctl/pkg/cli"
	"istio.io/istio/istioctl/pkg/tag"
	iopv1alpha1 "istio.io/istio/operator/pkg/apis/istio/v1alpha1"
	"istio.io/istio/operator/pkg/cache"
	"istio.io/istio/operator/pkg/helmreconciler"
	"istio.io/istio/operator/pkg/manifest"
	"istio.io/istio/operator/pkg/object"
	"istio.io/istio/operator/pkg/translate"
	"istio.io/istio/operator/pkg/util/clog"
	"istio.io/istio/operator/pkg/util/progress"
	"istio.io/istio/pkg/kube"
	"istio.io/istio/pkg/log"
	proxyinfo "istio.io/istio/pkg/proxy"
)

type uninstallArgs struct {
	// skipConfirmation determines whether the user is prompted for confirmation.
	// If set to true, the user is not prompted and a Yes response is assumed in all cases.
	skipConfirmation bool
	// force proceeds even if there are validation errors
	force bool
	// purge results in deletion of all Istio resources.
	purge bool
	// revision is the Istio control plane revision the command targets.
	revision string
	// filename is the path of input IstioOperator CR.
	filename string
	// set is a string with element format "path=value" where path is an IstioOperator path and the value is a
	// value to set the node at that path to.
	set []string
	// manifestsPath is a path to a charts and profiles directory in the local filesystem with a release tgz.
	manifestsPath string
	// verbose generates verbose output.
	verbose bool
}

const (
	AllResourcesRemovedWarning = "All Istio resources will be pruned from the cluster\n"
	NoResourcesRemovedWarning  
    
func uninstall(cmd *cobra.Command, ctx cli.Context, rootArgs *RootArgs, uiArgs *uninstallArgs, logOpts *log.Options) error {
	l := clog.NewConsoleLogger(cmd.OutOrStdout(), cmd.ErrOrStderr(), installerScope)
	if err := configLogs(logOpts); err != nil {
		return fmt.Errorf("could not configure logs: %s", err)
	}
	cliClient, err := ctx.CLIClient()
	if err != nil {
		return err
	}
	kubeClient, client, err := KubernetesClients(cliClient, l)
	if err != nil {
		l.LogAndFatal(err)
	}
	var kubeClientWithRev kube.CLIClient
	if uiArgs.revision != "" && uiArgs.revision != "default" {
		kubeClientWithRev, err = ctx.CLIClientWithRevision(uiArgs.revision)
		if err != nil {
			return err
		}
	} else {
		kubeClientWithRev = kubeClient
	}

	if uiArgs.revision != "" {
		revisions, err := tag.ListRevisionDescriptions(kubeClient)
		if err != nil {
			return fmt.Errorf("could not list revisions: %s", err)
		}
		if _, exists := revisions[uiArgs.revision]; !exists {
			return errors.New("could not find target revision")
		}
	}

	cache.FlushObjectCaches()
	opts := &helmreconciler.Options{DryRun: rootArgs.DryRun, Log: l, ProgressLog: progress.NewLog()}
	var h *helmreconciler.HelmReconciler

	// If the user is performing a purge install but also specified a revision or filename, we should warn
	// that the purge will still remove all resources
	if uiArgs.purge && (uiArgs.revision != "" || uiArgs.filename != "") {
		l.LogAndPrint(PurgeWithRevisionOrOperatorSpecifiedWarning)
	}
	// If only revision flag is set, we would prune resources by the revision label.
	// Otherwise we would merge the revision flag and the filename flag and delete resources by following the
	// owning name label.
	var iop *iopv1alpha1.IstioOperator
	if uiArgs.filename == "" {
		emptyiops := &v1alpha1.IstioOperatorSpec{Profile: "empty", Revision: uiArgs.revision}
		iop, err = translate.IOPStoIOP(emptyiops, "", "")
		if err != nil {
			return err
		}
	} else {
		_, iop, err = manifest.GenManifests([]string{uiArgs.filename},
			applyFlagAliases(uiArgs.set, uiArgs.manifestsPath, uiArgs.revision), uiArgs.force, nil, kubeClient, l)
		if err != nil {
			return err
		}
		iop.Name = savedIOPName(iop)
	}

	h, err = helmreconciler.NewHelmReconciler(client, kubeClient, iop, opts)
	if err != nil {
		return fmt.Errorf("failed to create reconciler: %v", err)
	}
	objectsList, err := h.GetPrunedResources(uiArgs.revision, uiArgs.purge, "")
	if err != nil {
		return err
	}
	preCheckWarnings(cmd, kubeClientWithRev, uiArgs, ctx.IstioNamespace(), uiArgs.revision, objectsList, nil, l, rootArgs.DryRun)

	if err := h.DeleteObjectsList(objectsList, ""); err != nil {
		return fmt.Errorf("failed to delete control plane resources by revision: %v", err)
	}
	opts.ProgressLog.SetState(progress.StateUninstallComplete)
	return nil
}