Skip to content

Commit

Permalink
Fix #792: making CLI super-fast
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolaferraro authored and astefanutti committed Sep 18, 2019
1 parent edf6305 commit 53ab079
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 3 deletions.
2 changes: 1 addition & 1 deletion cmd/builder/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func main() {
rand.Seed(time.Now().UTC().UnixNano())
printVersion()

c, err := client.NewClient()
c, err := client.NewClient(false)
exitOnError(err)

ctx := cancellable.NewContext()
Expand Down
12 changes: 10 additions & 2 deletions pkg/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"os/user"
"path/filepath"

"k8s.io/apimachinery/pkg/api/meta"
"github.com/apache/camel-k/pkg/apis"
"github.com/operator-framework/operator-sdk/pkg/k8sutil"
"github.com/pkg/errors"
Expand Down Expand Up @@ -68,11 +69,12 @@ func (c *defaultClient) GetScheme() *runtime.Scheme {
// NewOutOfClusterClient creates a new k8s client that can be used from outside the cluster
func NewOutOfClusterClient(kubeconfig string) (Client, error) {
initialize(kubeconfig)
return NewClient()
// using fast discovery from outside the cluster
return NewClient(true)
}

// NewClient creates a new k8s client that can be used from outside or in the cluster
func NewClient() (Client, error) {
func NewClient(fastDiscovery bool) (Client, error) {
// Get a config to talk to the apiserver
cfg, err := config.GetConfig()
if err != nil {
Expand All @@ -91,9 +93,15 @@ func NewClient() (Client, error) {
return nil, err
}

var mapper meta.RESTMapper
if fastDiscovery {
mapper = newFastDiscoveryRESTMapper(cfg)
}

// Create a new client to avoid using cache (enabled by default on operator-sdk client)
clientOptions := controller.Options{
Scheme: scheme,
Mapper: mapper,
}
dynClient, err := controller.New(cfg, clientOptions)
if err != nil {
Expand Down
70 changes: 70 additions & 0 deletions pkg/client/fastmapper.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package client

import (
"github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/discovery"
"k8s.io/client-go/rest"
"k8s.io/client-go/restmapper"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// allowedAPIGroups contains a set of API groups that are allowed when using the fastmapper.
// Those must correspond to all groups used by the "kamel" binary tool when running out-of-cluster.
var allowedAPIGroups = map[string]bool{
"": true, // core APIs
"apiextensions.k8s.io": true,
"apps": true,
"camel.apache.org": true,
"rbac.authorization.k8s.io": true,
}

func newFastDiscoveryRESTMapper(config *rest.Config) meta.RESTMapper {
return meta.NewLazyRESTMapperLoader(func() (meta.RESTMapper, error) {
return newFastDiscoveryRESTMapperWithFilter(config, func(g *metav1.APIGroup) bool {
return allowedAPIGroups[g.Name]
})
})
}

func newFastDiscoveryRESTMapperWithFilter(config *rest.Config, filter func(*metav1.APIGroup) bool) (meta.RESTMapper, error) {
dc := discovery.NewDiscoveryClientForConfigOrDie(config)
groups, err := dc.ServerGroups()
if err != nil {
return nil, err
}
wg := wait.Group{}
totalCount := 0
pickedCount := 0
var grs []*restmapper.APIGroupResources
for _, group := range groups.Groups {
pick := filter(&group)
logrus.Debugf("Group: %s %v", group.Name, pick)
totalCount++
if !pick {
continue
}
pickedCount++
gr := &restmapper.APIGroupResources{
Group: group,
VersionedResources: make(map[string][]metav1.APIResource),
}
grs = append(grs, gr)
wg.Start(func() { discoverGroupResources(dc, gr) })
}
wg.Wait()
logrus.Debugf("Picked %d/%d", pickedCount, totalCount)
return restmapper.NewDiscoveryRESTMapper(grs), nil
}

func discoverGroupResources(dc discovery.DiscoveryInterface, gr *restmapper.APIGroupResources) {
for _, version := range gr.Group.Versions {
resources, err := dc.ServerResourcesForGroupVersion(version.GroupVersion)
if err != nil {
logrus.Fatal(err, version.GroupVersion)
}
gr.VersionedResources[version.Version] = resources.APIResources
}
}

0 comments on commit 53ab079

Please sign in to comment.