Add caching for discovery info

This commit is contained in:
Dr. Stefan Schimanski
2016-10-24 12:58:47 +02:00
parent 5a2c473c1c
commit 14ce6f6065
8 changed files with 711 additions and 43 deletions

View File

@@ -27,6 +27,7 @@ import (
"os/user"
"path"
"path/filepath"
"regexp"
"sort"
"strconv"
"strings"
@@ -61,6 +62,7 @@ import (
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/runtime/serializer/json"
utilflag "k8s.io/kubernetes/pkg/util/flag"
"k8s.io/kubernetes/pkg/util/homedir"
"k8s.io/kubernetes/pkg/watch"
)
@@ -77,6 +79,8 @@ type Factory interface {
// Returns internal flagset
FlagSet() *pflag.FlagSet
// Returns a discovery client
DiscoveryClient() (discovery.CachedDiscoveryInterface, error)
// Returns interfaces for dealing with arbitrary runtime.Objects.
Object() (meta.RESTMapper, runtime.ObjectTyper)
// Returns interfaces for dealing with arbitrary
@@ -313,27 +317,36 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) Factory {
}
clients := NewClientCache(clientConfig)
return &factory{
f := &factory{
flags: flags,
clientConfig: clientConfig,
clients: clients,
}
return f
}
func (f *factory) FlagSet() *pflag.FlagSet {
return f.flags
}
func (f *factory) Object() (meta.RESTMapper, runtime.ObjectTyper) {
func (f *factory) DiscoveryClient() (discovery.CachedDiscoveryInterface, error) {
cfg, err := f.clientConfig.ClientConfig()
checkErrWithPrefix("failed to get client config: ", err)
cmdApiVersion := unversioned.GroupVersion{}
if cfg.GroupVersion != nil {
cmdApiVersion = *cfg.GroupVersion
if err != nil {
return nil, err
}
mapper := registered.RESTMapper()
discoveryClient, err := discovery.NewDiscoveryClientForConfig(cfg)
if err != nil {
return nil, err
}
cacheDir := computeDiscoverCacheDir(filepath.Join(homedir.HomeDir(), ".kube", "cache", "discovery"), cfg.Host)
return NewCachedDiscoveryClient(discoveryClient, cacheDir, time.Duration(10*time.Minute)), nil
}
func (f *factory) Object() (meta.RESTMapper, runtime.ObjectTyper) {
mapper := registered.RESTMapper()
discoveryClient, err := f.DiscoveryClient()
if err == nil {
mapper = meta.FirstHitRESTMapper{
MultiRESTMapper: meta.MultiRESTMapper{
@@ -345,23 +358,28 @@ func (f *factory) Object() (meta.RESTMapper, runtime.ObjectTyper) {
// wrap with shortcuts
mapper = NewShortcutExpander(mapper, discoveryClient)
// wrap with output preferences
cfg, err := f.clients.ClientConfigForVersion(nil)
checkErrWithPrefix("failed to get client config: ", err)
cmdApiVersion := unversioned.GroupVersion{}
if cfg.GroupVersion != nil {
cmdApiVersion = *cfg.GroupVersion
}
mapper = kubectl.OutputVersionMapper{RESTMapper: mapper, OutputVersions: []unversioned.GroupVersion{cmdApiVersion}}
return mapper, api.Scheme
}
func (f *factory) UnstructuredObject() (meta.RESTMapper, runtime.ObjectTyper, error) {
cfg, err := f.clients.ClientConfigForVersion(nil)
discoveryClient, err := f.DiscoveryClient()
if err != nil {
return nil, nil, err
}
dc, err := discovery.NewDiscoveryClientForConfig(cfg)
if err != nil {
return nil, nil, err
groupResources, err := discovery.GetAPIGroupResources(discoveryClient)
if err != nil && !discoveryClient.Fresh() {
discoveryClient.Invalidate()
groupResources, err = discovery.GetAPIGroupResources(discoveryClient)
}
groupResources, err := discovery.GetAPIGroupResources(dc)
if err != nil {
return nil, nil, err
}
@@ -378,11 +396,9 @@ func (f *factory) UnstructuredObject() (meta.RESTMapper, runtime.ObjectTyper, er
}
}
mapper := discovery.NewRESTMapper(groupResources, meta.InterfacesForUnstructured)
mapper := discovery.NewDeferredDiscoveryRESTMapper(discoveryClient, meta.InterfacesForUnstructured)
typer := discovery.NewUnstructuredObjectTyper(groupResources)
return NewShortcutExpander(mapper, dc), typer, nil
return NewShortcutExpander(mapper, discoveryClient), typer, nil
}
func (f *factory) RESTClient() (*restclient.RESTClient, error) {
@@ -1316,3 +1332,16 @@ func (f *factory) SuggestedPodTemplateResources() []unversioned.GroupResource {
{Resource: "replicaset"},
}
}
// overlyCautiousIllegalFileCharacters matches characters that *might* not be supported. Windows is really restrictive, so this is really restrictive
var overlyCautiousIllegalFileCharacters = regexp.MustCompile(`[^(\w/\.)]`)
// computeDiscoverCacheDir takes the parentDir and the host and comes up with a "usually non-colliding" name.
func computeDiscoverCacheDir(parentDir, host string) string {
// strip the optional scheme from host if its there:
schemelessHost := strings.Replace(strings.Replace(host, "https://", "", 1), "http://", "", 1)
// now do a simple collapse of non-AZ09 characters. Collisions are possible but unlikely. Even if we do collide the problem is short lived
safeHost := overlyCautiousIllegalFileCharacters.ReplaceAllString(schemelessHost, "_")
return filepath.Join(parentDir, safeHost)
}