func (c Context) KubeContextInfo() (*remote.ContextInfo, error) {
	return c.remote.CurrentContextInfo()
}
KubeContextInfo returns kube context information.
package cmd
import (
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"os"
	"sync"
	"github.com/chzyer/readline"
	"github.com/mattn/go-isatty"
	"github.com/spf13/cobra"
	"github.com/splunk/qbec/internal/eval"
	"github.com/splunk/qbec/internal/model"
	"github.com/splunk/qbec/internal/remote"
	"github.com/splunk/qbec/internal/remote/k8smeta"
	"github.com/splunk/qbec/internal/vmexternals"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/client-go/dynamic"
)
type KubeClient interface {
	DisplayName(o model.K8sMeta) string
	IsNamespaced(kind schema.GroupVersionKind) (bool, error)
	Get(obj model.K8sMeta) (*unstructured.Unstructured, error)
	Sync(obj model.K8sLocalObject, opts remote.SyncOptions) (*remote.SyncResult, error)
	ValidatorFor(gvk schema.GroupVersionKind) (k8smeta.Validator, error)
	ListObjects(scope remote.ListQueryConfig) (remote.Collection, error)
	Delete(model.K8sMeta, remote.DeleteOptions) (*remote.SyncResult, error)
	ObjectKey(obj model.K8sMeta) string
	ResourceInterface(obj schema.GroupVersionKind, namespace string) (dynamic.ResourceInterface, error)
}
type ClientProvider func(env string) (KubeClient, error)
type KubeAttrsProvider func(env string) (*remote.KubeAttributes, error)
type Options struct {
	Stdout            io.Writer
	Stderr            io.Writer
	SkipConfirm       bool
	ClientProvider    ClientProvider
	KubeAttrsProvider KubeAttrsProvider
}
type Context struct {
	root            string                        
	appTag          string                        
	envFile         string                        
	remote          *remote.Config                
	forceOptsFn     func() (ForceOptions, error)  
	ext             vmexternals.Externals         
	clp             ClientProvider                
	attrsp          KubeAttrsProvider             
	colors          bool                          
	yes             bool                          
	evalConcurrency int                           
	verbose         int                           
	stdin           io.Reader                     
	stdout          io.Writer                     
	stderr          io.Writer                     
	strictVars      bool                          
	profiler        *profiler                     
	app             *model.App                    
}
func envOrDefault(name, def string) string {
	v := os.Getenv(name)
	if v != "" {
		return v
	}
	return def
}
func defaultRoot() string {
	return envOrDefault("QBEC_ROOT", "")
}
func defaultEnvironmentFile() string {
	return envOrDefault("QBEC_ENV_FILE", "")
}
func skipPrompts() bool {
	return os.Getenv("QBEC_YES") == "true"
}
func memoizeForceFn(fn func() (ForceOptions, error)) func() (ForceOptions, error) {
	var fOpts ForceOptions
	var fErr error
	var once sync.Once
	return func() (ForceOptions, error) {
		once.Do(func() {
			fOpts, fErr = fn()
		})
		return fOpts, fErr
	}
}
func NewContext(root *cobra.Command, opts Options) func() (Context, error) {
	extConfigFn := vmexternals.FromCommandParams(root, "vm:", true)
	remoteConfig := remote.NewConfig(root, "k8s:")
	forceOptsFn := addForceOptions(root, remoteConfig, "force:")
	profilerFn := addProfilerOptions(root, "pprof:")
	cf := Context{
		remote:      remoteConfig,
		clp:         opts.ClientProvider,
		forceOptsFn: memoizeForceFn(forceOptsFn),
		attrsp:      opts.KubeAttrsProvider,
		stdout:      opts.Stdout,
		stderr:      opts.Stderr,
		yes:         opts.SkipConfirm || skipPrompts(),
	}
	cf.stdin = os.Stdin
	if cf.stdout == nil {
		cf.stdout = os.Stdout
	}
	if cf.stderr == nil {
		cf.stderr = os.Stderr
	}
	root.PersistentFlags().StringVar(&cf.root, "root", defaultRoot(), "root directory of repo (from QBEC_ROOT or auto-detect)")
	root.PersistentFlags().IntVarP(&cf.verbose, "verbose", "v", cf.verbose, "verbosity level")
	root.PersistentFlags().BoolVar(&cf.colors, "colors", cf.colors, "colorize output (set automatically if not specified)")
	root.PersistentFlags().BoolVar(&cf.yes, "yes", cf.yes, "do not prompt for confirmation. The default value can be overridden by setting QBEC_YES=true")
	root.PersistentFlags().BoolVar(&cf.strictVars, "strict-vars", cf.strictVars, "require declared variables to be specified, do not allow undeclared variables")
	root.PersistentFlags().IntVar(&cf.evalConcurrency, "eval-concurrency", cf.evalConcurrency, "concurrency with which to evaluate components")
	root.PersistentFlags().StringVar(&cf.appTag, "app-tag", "", "build tag to create suffixed objects, indicates GC scope")
	root.PersistentFlags().StringVarP(&cf.envFile, "env-file", "E", defaultEnvironmentFile(), "use additional environment file not declared in qbec.yaml")
	return func() (_ Context, err error) {
		if !root.Flags().Changed("colors") {
			cf.colors = isatty.IsTerminal(os.Stdout.Fd())
		}
		cf.ext, err = extConfigFn()
		if err != nil {
			return cf, err
		}
		cf.profiler, err = profilerFn()
		if err != nil {
			return cf, err
		}
		RegisterCleanupTask(cf.profiler)
		return cf, nil
	}
}
func (c Context) RootDir() string { return c.root }
func (c Context) AppTag() string { return c.appTag }
func (c Context) EnvFiles() []string {
	if c.envFile == "" {
		return nil
	}
	return []string{c.envFile}
}
func (c Context) Colorize() bool { return c.colors }
func (c Context) Verbosity() int { return c.verbose }
func (c Context) EvalConcurrency() int { return c.evalConcurrency }
func (c Context) Stdout() io.Writer { return c.stdout }
func (c Context) Stderr() io.Writer { return c.stderr }
func (c Context) ForceOptions() (ForceOptions, error) {
	return c.forceOptsFn()
}