1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-06 07:57:07 +00:00
kyverno/pkg/openapi/crdSync.go

154 lines
4 KiB
Go
Raw Normal View History

2020-03-04 18:56:59 +05:30
package openapi
import (
"context"
2020-03-27 19:06:06 +05:30
"fmt"
2020-09-02 16:33:55 +05:30
"strings"
"time"
2020-03-04 18:56:59 +05:30
"github.com/kyverno/kyverno/pkg/clients/dclient"
"github.com/kyverno/kyverno/pkg/logging"
"github.com/kyverno/kyverno/pkg/metrics"
util "github.com/kyverno/kyverno/pkg/utils"
"github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtimeSchema "k8s.io/apimachinery/pkg/runtime/schema"
2020-03-04 18:56:59 +05:30
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/discovery"
2020-03-04 18:56:59 +05:30
)
type crdSync struct {
client dclient.Interface
manager *Manager
2020-03-04 18:56:59 +05:30
}
const (
skipErrorMsg = "Got empty response for"
)
// crdDefinitionPrior represents CRDs version prior to 1.16
2020-05-15 16:57:26 -07:00
var crdDefinitionPrior struct {
Spec struct {
Names struct {
Kind string `json:"kind"`
} `json:"names"`
Validation struct {
OpenAPIV3Schema interface{} `json:"openAPIV3Schema"`
} `json:"validation"`
} `json:"spec"`
}
// crdDefinitionNew represents CRDs version 1.16+
2020-05-15 16:57:26 -07:00
var crdDefinitionNew struct {
Spec struct {
Names struct {
Kind string `json:"kind"`
} `json:"names"`
Versions []struct {
Schema struct {
OpenAPIV3Schema interface{} `json:"openAPIV3Schema"`
} `json:"schema"`
Storage bool `json:"storage"`
} `json:"versions"`
} `json:"spec"`
}
2020-11-17 13:07:30 -08:00
// NewCRDSync ...
func NewCRDSync(client dclient.Interface, mgr *Manager) *crdSync {
if mgr == nil {
panic(fmt.Errorf("nil manager sent into crd sync"))
2020-03-27 19:06:06 +05:30
}
2020-03-04 18:56:59 +05:30
return &crdSync{
manager: mgr,
client: client,
2020-03-04 18:56:59 +05:30
}
}
func (c *crdSync) Run(ctx context.Context, workers int) {
if err := c.updateInClusterKindToAPIVersions(); err != nil {
logging.Error(err, "failed to update in-cluster api versions")
}
newDoc, err := c.client.Discovery().OpenAPISchema()
2020-03-05 22:50:32 +05:30
if err != nil {
logging.Error(err, "cannot get OpenAPI schema")
2020-03-05 22:50:32 +05:30
}
err = c.manager.useOpenAPIDocument(newDoc)
2020-03-05 22:50:32 +05:30
if err != nil {
logging.Error(err, "Could not set custom OpenAPI document")
2020-03-05 22:50:32 +05:30
}
// Sync CRD before kyverno starts
c.sync()
2020-03-04 18:56:59 +05:30
for i := 0; i < workers; i++ {
go wait.UntilWithContext(ctx, c.CheckSync, 15*time.Second)
2020-03-04 18:56:59 +05:30
}
}
2020-03-05 22:50:32 +05:30
func (c *crdSync) sync() {
c.client.Discovery().DiscoveryCache().Invalidate()
2020-04-02 12:19:32 +05:30
crds, err := c.client.GetDynamicInterface().Resource(runtimeSchema.GroupVersionResource{
Group: "apiextensions.k8s.io",
Version: "v1",
2020-04-02 12:19:32 +05:30
Resource: "customresourcedefinitions",
}).List(context.TODO(), metav1.ListOptions{})
c.client.RecordClientQuery(metrics.ClientList, metrics.KubeDynamicClient, "CustomResourceDefinition", "")
2020-03-04 18:56:59 +05:30
if err != nil {
logging.Error(err, "could not fetch crd's from server")
2020-03-05 22:50:32 +05:30
return
2020-03-04 18:56:59 +05:30
}
c.manager.deleteCRDFromPreviousSync()
2020-03-06 01:09:38 +05:30
2020-03-05 22:50:32 +05:30
for _, crd := range crds.Items {
c.manager.ParseCRD(crd)
2020-03-06 01:09:38 +05:30
}
if err := c.updateInClusterKindToAPIVersions(); err != nil {
logging.Error(err, "sync failed, unable to update in-cluster api versions")
}
2021-11-22 19:22:45 +05:30
newDoc, err := c.client.Discovery().OpenAPISchema()
2021-11-22 19:22:45 +05:30
if err != nil {
logging.Error(err, "cannot get OpenAPI schema")
2021-11-22 19:22:45 +05:30
}
err = c.manager.useOpenAPIDocument(newDoc)
2021-11-22 19:22:45 +05:30
if err != nil {
logging.Error(err, "Could not set custom OpenAPI document")
2021-11-22 19:22:45 +05:30
}
}
func (c *crdSync) updateInClusterKindToAPIVersions() error {
util.OverrideRuntimeErrorHandler()
_, apiResourceLists, err := discovery.ServerGroupsAndResources(c.client.Discovery().DiscoveryInterface())
if err != nil && !strings.Contains(err.Error(), skipErrorMsg) {
return errors.Wrapf(err, "fetching API server groups and resources")
}
preferredAPIResourcesLists, err := discovery.ServerPreferredResources(c.client.Discovery().DiscoveryInterface())
if err != nil && !strings.Contains(err.Error(), skipErrorMsg) {
return errors.Wrapf(err, "fetching API server preferreds resources")
}
c.manager.updateKindToAPIVersions(apiResourceLists, preferredAPIResourcesLists)
return nil
2020-03-06 01:09:38 +05:30
}
func (c *crdSync) CheckSync(ctx context.Context) {
crds, err := c.client.GetDynamicInterface().Resource(runtimeSchema.GroupVersionResource{
Group: "apiextensions.k8s.io",
Version: "v1",
Resource: "customresourcedefinitions",
}).List(ctx, metav1.ListOptions{})
if err != nil {
logging.Error(err, "could not fetch crd's from server")
return
}
if len(c.manager.crdList) != len(crds.Items) {
c.sync()
}
}