blob: 24a8666eb16409d095310269d7eec493559cd900 [file] [log] [blame]
/*
* Copyright 2022 Red Hat, Inc. and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package client
import (
"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"
"k8s.io/klog/v2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/kiegroup/kogito-serverless-operator/container-builder/util/log"
)
// FastMapperAllowedAPIGroups 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 FastMapperAllowedAPIGroups = map[string]bool{
"": true, // core APIs
"apiextensions.k8s.io": true,
"apps": true,
"batch": true,
"rbac.authorization.k8s.io": true,
"console.openshift.io": true, // OpenShift console resources
"operators.coreos.com": true, // Operator SDK OLM
"monitoring.coreos.com": true, // Prometheus resources
}
// newFastDiscoveryRESTMapper comes from https://github.com/kubernetes-sigs/controller-runtime/pull/592.
// We may leverage the controller-runtime bits in the future, if that gets merged upstream.
func newFastDiscoveryRESTMapper(config *rest.Config) meta.RESTMapper {
return meta.NewLazyRESTMapperLoader(func() (meta.RESTMapper, error) {
return newFastDiscoveryRESTMapperWithFilter(config, func(g *metav1.APIGroup) bool {
return FastMapperAllowedAPIGroups[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
grs := make([]*restmapper.APIGroupResources, 0)
for _, group := range groups.Groups {
pinnedGroup := group
pick := filter(&pinnedGroup)
klog.V(log.D).InfoS("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()
klog.V(log.D).InfoS("Picked", "pickedCount", pickedCount, "totalCount", 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 {
klog.V(log.E).ErrorS(err, version.GroupVersion)
}
gr.VersionedResources[version.Version] = resources.APIResources
}
}