You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by as...@apache.org on 2019/09/18 18:47:57 UTC
[camel-k] 01/04: Fix #792: making CLI super-fast
This is an automated email from the ASF dual-hosted git repository.
astefanutti pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git
commit 53ab079c38eeb2c58706fe4715ee74c381a3ebd8
Author: nferraro <ni...@gmail.com>
AuthorDate: Wed Sep 18 13:20:36 2019 +0200
Fix #792: making CLI super-fast
---
cmd/builder/main.go | 2 +-
pkg/client/client.go | 12 +++++++--
pkg/client/fastmapper.go | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 81 insertions(+), 3 deletions(-)
diff --git a/cmd/builder/main.go b/cmd/builder/main.go
index 2a20e0e..e526aed 100644
--- a/cmd/builder/main.go
+++ b/cmd/builder/main.go
@@ -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()
diff --git a/pkg/client/client.go b/pkg/client/client.go
index f800fb6..ddb8332 100644
--- a/pkg/client/client.go
+++ b/pkg/client/client.go
@@ -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"
@@ -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 {
@@ -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 {
diff --git a/pkg/client/fastmapper.go b/pkg/client/fastmapper.go
new file mode 100644
index 0000000..2752953
--- /dev/null
+++ b/pkg/client/fastmapper.go
@@ -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
+ }
+}