func (c *Client) DisplayName(o model.K8sMeta) string {
	sm := c.resources
	gvk := o.GroupVersionKind()
	info := sm.APIResource(gvk)
	displayType := func() string {
		if info != nil {
			return info.Name
		}
		return strings.ToLower(gvk.Kind)
	}
	displayName := func() string {
		ns := c.objectNamespace(o)
		name := model.NameForDisplay(o)
		if ns == "" {
			return name
		}
		return name + " -n " + ns
	}
	name := fmt.Sprintf("%s %s", displayType(), displayName())
	if l, ok := o.(model.K8sLocalObject); ok {
		comp := l.Component()
		if comp != "" {
			name += fmt.Sprintf(" (source %s)", comp)
		}
	}
	return name
}
DisplayName returns the display name of the supplied K8s object.
package remote
import (
	"encoding/json"
	"fmt"
	"strings"
	"time"
	"github.com/ghodss/yaml"
	"github.com/jonboulle/clockwork"
	"github.com/pkg/errors"
	"github.com/splunk/qbec/internal/model"
	"github.com/splunk/qbec/internal/remote/k8smeta"
	"github.com/splunk/qbec/internal/sio"
	"github.com/splunk/qbec/internal/types"
	apiErrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime/schema"
	apiTypes "k8s.io/apimachinery/pkg/types"
	"k8s.io/client-go/discovery"
	"k8s.io/client-go/dynamic"
)
const (
	identicalObjects = "objects are identical"
	opUpdate         = "update object"
	opCreate         = "create object"
)
var (
	ErrForbidden        = errors.New("forbidden")              
	ErrNotFound         = errors.New("not found")              
	errMetadataNotFound = errors.New("server type not found")  
)
type TypeWaitOptions struct {
	Timeout time.Duration  
	Poll    time.Duration  
}
type ConditionFunc func(obj model.K8sMeta) bool
type SyncOptions struct {
	DryRun          bool             
	DisableCreate   bool             
	DisableUpdateFn ConditionFunc    
	WaitOptions     TypeWaitOptions  
	ShowSecrets     bool             
}
type DeleteOptions struct {
	DryRun          bool           
	DisableDeleteFn ConditionFunc  
}
type internalSyncOptions struct {
	secretDryRun       bool                
	pristiner          pristineReadWriter  
	pristineAnnotation string              
}
type resourceClient interface {
	clientForGroupVersionKind(kind schema.GroupVersionKind) (dynamic.Interface, error)
}
type Client struct {
	resources *k8smeta.Resources         
	schema    *k8smeta.ServerSchema      
	pool      resourceClient             
	disco     k8smeta.ResourceDiscovery  
	defaultNs string                     
	verbosity int                        
}
func newClient(pool resourceClient, disco discovery.DiscoveryInterface, ns string, verbosity int) (*Client, error) {
	start := time.Now()
	resources, err := k8smeta.NewResources(disco, k8smeta.ResourceOpts{WarnFn: sio.Warnln})
	if err != nil {
		return nil, errors.Wrap(err, "get server metadata")
	}
	if verbosity > 0 {
		resources.Dump(sio.Debugln)
	}
	duration := time.Since(start).Round(time.Millisecond)
	sio.Debugln("cluster metadata load took", duration)
	ss := k8smeta.NewServerSchema(disco)
	c := &Client{
		resources: resources,
		schema:    ss,
		pool:      pool,
		disco:     disco,
		defaultNs: ns,
		verbosity: verbosity,
	}
	return c, nil
}
func (c *Client) ValidatorFor(gvk schema.GroupVersionKind) (k8smeta.Validator, error) {
	return c.schema.ValidatorFor(gvk)
}
func (c *Client) objectNamespace(o model.K8sMeta) string {
	info := c.resources.APIResource(o.GroupVersionKind())
	ns := o.GetNamespace()
	if info != nil {
		if info.Namespaced {
			if ns == "" {
				ns = c.defaultNs
			}
		} else {
			ns = ""
		}
	}
	return ns
}