1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-14 11:57:48 +00:00

Feature/api version 852 (#1028)

* apiVersion support for generate

* added apiVersion to crds
This commit is contained in:
Mohan B E 2020-08-07 09:47:33 +05:30 committed by GitHub
parent 9c0d54f35a
commit a14828246d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 147 additions and 97 deletions

View file

@ -87,6 +87,8 @@ spec:
type: object
generate:
properties:
apiVersion:
type: string
clone:
properties:
name:

View file

@ -107,7 +107,7 @@ func removeWebhookIfExists(client *client.Client, kind string, name string) erro
logger := log.Log.WithName("removeExistingWebhook").WithValues("kind", kind, "name", name)
var err error
// Get resource
_, err = client.GetResource(kind, "", name)
_, err = client.GetResource("", kind, "", name)
if errors.IsNotFound(err) {
logger.V(4).Info("resource not found")
return nil
@ -117,7 +117,7 @@ func removeWebhookIfExists(client *client.Client, kind string, name string) erro
return err
}
// Delete resource
err = client.DeleteResource(kind, "", name, false)
err = client.DeleteResource("", kind, "", name, false)
if err != nil {
logger.Error(err, "failed to delete resource")
return err

View file

@ -247,6 +247,8 @@ spec:
- kind
- name
properties:
apiVersion:
type: string
kind:
type: string
name:

View file

@ -92,6 +92,8 @@ spec:
type: object
generate:
properties:
apiVersion:
type: string
clone:
properties:
name:

View file

@ -92,6 +92,8 @@ spec:
type: object
generate:
properties:
apiVersion:
type: string
clone:
properties:
name:

1
go.sum
View file

@ -1,5 +1,4 @@
9fans.net/go v0.0.0-20181112161441-237454027057/go.mod h1:diCsxrliIURU9xsYtjCp5AbpQKqdhKmf0ujWDUSkfoY=
<<<<<<< Updated upstream
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=

View file

@ -361,6 +361,9 @@ type PolicyViolationSpec struct {
// ResourceSpec information to identify the resource
type ResourceSpec struct {
// Specifies resource apiVersionm
// +optional
APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"`
// Specifies resource kind
// +optional
Kind string `json:"kind,omitempty" yaml:"kind,omitempty"`

View file

@ -67,7 +67,7 @@ func (o *CanIOptions) RunAccessCheck() (bool, error) {
logger := o.log.WithValues("kind", sar.Kind, "namespace", sar.Namespace, "name", sar.Name)
// Create the Resource
resp, err := o.client.CreateResource("SelfSubjectAccessReview", "", sar, false)
resp, err := o.client.CreateResource("", "SelfSubjectAccessReview", "", sar, false)
if err != nil {
logger.Error(err, "failed to create resource")
return false, err

View file

@ -56,7 +56,7 @@ func (vc StatusControl) setStatus(status string) error {
logger := vc.log.WithValues("name", deployName, "namespace", deployNamespace)
var ann map[string]string
var err error
deploy, err := vc.client.GetResource("Deployment", deployNamespace, deployName)
deploy, err := vc.client.GetResource("", "Deployment", deployNamespace, deployName)
if err != nil {
logger.Error(err, "failed to get deployment")
return err
@ -83,7 +83,7 @@ func (vc StatusControl) setStatus(status string) error {
deploy.SetAnnotations(ann)
// update counter
_, err = vc.client.UpdateResource("Deployment", deployNamespace, deploy, false)
_, err = vc.client.UpdateResource("", "Deployment", deployNamespace, deploy, false)
if err != nil {
logger.Error(err, "failed to update deployment annotation", "key", annWebhookStatus, "val", status)
return err
@ -109,7 +109,7 @@ func (vc StatusControl) IncrementAnnotation() error {
logger := vc.log
var ann map[string]string
var err error
deploy, err := vc.client.GetResource("Deployment", deployNamespace, deployName)
deploy, err := vc.client.GetResource("", "Deployment", deployNamespace, deployName)
if err != nil {
logger.Error(err, "failed to find Kyverno", "deployment", deployName, "namespace", deployNamespace)
return err
@ -138,7 +138,7 @@ func (vc StatusControl) IncrementAnnotation() error {
deploy.SetAnnotations(ann)
// update counter
_, err = vc.client.UpdateResource("Deployment", deployNamespace, deploy, false)
_, err = vc.client.UpdateResource("", "Deployment", deployNamespace, deploy, false)
if err != nil {
logger.Error(err, fmt.Sprintf("failed to update annotation %s for deployment %s in namespace %s", annCounter, deployName, deployNamespace))
return err

View file

@ -75,14 +75,14 @@ func (c *Client) submitAndApproveCertificateRequest(req *certificates.Certificat
if err != nil {
return nil, err
}
csrList, err := c.ListResource(CSRs, "", nil)
csrList, err := c.ListResource("", CSRs, "", nil)
if err != nil {
return nil, fmt.Errorf("Unable to list existing certificate requests: %v", err)
}
for _, csr := range csrList.Items {
if csr.GetName() == req.ObjectMeta.Name {
err := c.DeleteResource(CSRs, "", csr.GetName(), false)
err := c.DeleteResource("", CSRs, "", csr.GetName(), false)
if err != nil {
return nil, fmt.Errorf("Unable to delete existing certificate request: %v", err)
}
@ -91,7 +91,7 @@ func (c *Client) submitAndApproveCertificateRequest(req *certificates.Certificat
}
}
unstrRes, err := c.CreateResource(CSRs, "", req, false)
unstrRes, err := c.CreateResource("", CSRs, "", req, false)
if err != nil {
return nil, err
}
@ -120,7 +120,7 @@ func (c *Client) fetchCertificateFromRequest(req *certificates.CertificateSignin
// TODO: react of SIGINT and SIGTERM
timeStart := time.Now()
for time.Since(timeStart) < time.Duration(maxWaitSeconds)*time.Second {
unstrR, err := c.GetResource(CSRs, "", req.ObjectMeta.Name)
unstrR, err := c.GetResource("", CSRs, "", req.ObjectMeta.Name)
if err != nil {
return nil, err
}
@ -151,7 +151,7 @@ func (c *Client) ReadRootCASecret() (result []byte) {
return result
}
sname := generateRootCASecretName(certProps)
stlsca, err := c.GetResource(Secrets, certProps.Namespace, sname)
stlsca, err := c.GetResource("", Secrets, certProps.Namespace, sname)
if err != nil {
return result
}
@ -177,7 +177,7 @@ const rootCAKey string = "rootCA.crt"
func (c *Client) ReadTlsPair(props tls.TlsCertificateProps) *tls.TlsPemPair {
logger := c.log.WithName("ReadTlsPair")
sname := generateTLSPairSecretName(props)
unstrSecret, err := c.GetResource(Secrets, props.Namespace, sname)
unstrSecret, err := c.GetResource("", Secrets, props.Namespace, sname)
if err != nil {
logger.Error(err, "Failed to get secret", "name", sname, "namespace", props.Namespace)
return nil
@ -188,7 +188,7 @@ func (c *Client) ReadTlsPair(props tls.TlsCertificateProps) *tls.TlsPemPair {
annotations := unstrSecret.GetAnnotations()
if _, ok := annotations[selfSignedAnnotation]; ok {
sname := generateRootCASecretName(props)
_, err := c.GetResource(Secrets, props.Namespace, sname)
_, err := c.GetResource("", Secrets, props.Namespace, sname)
if err != nil {
logger.Error(err, "Root CA secret is required while using self-signed certificates TLS pair, defaulting to generating new TLS pair", "name", sname, "namespace", props.Namespace)
return nil
@ -218,7 +218,7 @@ func (c *Client) ReadTlsPair(props tls.TlsCertificateProps) *tls.TlsPemPair {
func (c *Client) WriteTlsPair(props tls.TlsCertificateProps, pemPair *tls.TlsPemPair) error {
logger := c.log.WithName("WriteTlsPair")
name := generateTLSPairSecretName(props)
_, err := c.GetResource(Secrets, props.Namespace, name)
_, err := c.GetResource("", Secrets, props.Namespace, name)
if err != nil {
secret := &v1.Secret{
TypeMeta: metav1.TypeMeta{
@ -236,7 +236,7 @@ func (c *Client) WriteTlsPair(props tls.TlsCertificateProps, pemPair *tls.TlsPem
Type: v1.SecretTypeTLS,
}
_, err := c.CreateResource(Secrets, props.Namespace, secret, false)
_, err := c.CreateResource("", Secrets, props.Namespace, secret, false)
if err == nil {
logger.Info("secret created", "name", name, "namespace", props.Namespace)
}
@ -250,7 +250,7 @@ func (c *Client) WriteTlsPair(props tls.TlsCertificateProps, pemPair *tls.TlsPem
secret.Data[v1.TLSCertKey] = pemPair.Certificate
secret.Data[v1.TLSPrivateKeyKey] = pemPair.PrivateKey
_, err = c.UpdateResource(Secrets, props.Namespace, secret, false)
_, err = c.UpdateResource("", Secrets, props.Namespace, secret, false)
if err != nil {
return err
}

View file

@ -74,7 +74,7 @@ func (c *Client) NewDynamicSharedInformerFactory(defaultResync time.Duration) dy
//GetKubePolicyDeployment returns kube policy depoyment value
func (c *Client) GetKubePolicyDeployment() (*apps.Deployment, error) {
kubePolicyDeployment, err := c.GetResource("Deployment", config.KubePolicyNamespace, config.KubePolicyDeploymentName)
kubePolicyDeployment, err := c.GetResource("", "Deployment", config.KubePolicyNamespace, config.KubePolicyDeploymentName)
if err != nil {
return nil, err
}
@ -97,13 +97,13 @@ func (c *Client) GetCSRInterface() (csrtype.CertificateSigningRequestInterface,
return c.kclient.CertificatesV1beta1().CertificateSigningRequests(), nil
}
func (c *Client) getInterface(resource string) dynamic.NamespaceableResourceInterface {
return c.client.Resource(c.getGroupVersionMapper(resource))
func (c *Client) getInterface(apiVersion string, kind string) dynamic.NamespaceableResourceInterface {
return c.client.Resource(c.getGroupVersionMapper(apiVersion, kind))
}
func (c *Client) getResourceInterface(kind string, namespace string) dynamic.ResourceInterface {
func (c *Client) getResourceInterface(apiVersion string, kind string, namespace string) dynamic.ResourceInterface {
// Get the resource interface from kind
namespaceableInterface := c.getInterface(kind)
namespaceableInterface := c.getInterface(apiVersion, kind)
// Get the namespacable interface
var resourceInteface dynamic.ResourceInterface
if namespace != "" {
@ -115,18 +115,22 @@ func (c *Client) getResourceInterface(kind string, namespace string) dynamic.Res
}
// Keep this a stateful as the resource list will be based on the kubernetes version we connect to
func (c *Client) getGroupVersionMapper(kind string) schema.GroupVersionResource {
func (c *Client) getGroupVersionMapper(apiVersion string, kind string) schema.GroupVersionResource {
if apiVersion == "" {
return c.DiscoveryClient.GetGVRFromKind(kind)
}
return c.DiscoveryClient.GetGVRFromAPIVersionKind(apiVersion, kind)
}
// GetResource returns the resource in unstructured/json format
func (c *Client) GetResource(kind string, namespace string, name string, subresources ...string) (*unstructured.Unstructured, error) {
return c.getResourceInterface(kind, namespace).Get(name, meta.GetOptions{}, subresources...)
func (c *Client) GetResource(apiVersion string, kind string, namespace string, name string, subresources ...string) (*unstructured.Unstructured, error) {
return c.getResourceInterface(apiVersion, kind, namespace).Get(name, meta.GetOptions{}, subresources...)
}
//PatchResource patches the resource
func (c *Client) PatchResource(kind string, namespace string, name string, patch []byte) (*unstructured.Unstructured, error) {
return c.getResourceInterface(kind, namespace).Patch(name, patchTypes.JSONPatchType, patch, meta.PatchOptions{})
func (c *Client) PatchResource(apiVersion string, kind string, namespace string, name string, patch []byte) (*unstructured.Unstructured, error) {
return c.getResourceInterface(apiVersion, kind, namespace).Patch(name, patchTypes.JSONPatchType, patch, meta.PatchOptions{})
}
// GetDynamicInterface fetches underlying dynamic interface
@ -136,59 +140,59 @@ func (c *Client) GetDynamicInterface() dynamic.Interface {
// ListResource returns the list of resources in unstructured/json format
// Access items using []Items
func (c *Client) ListResource(kind string, namespace string, lselector *meta.LabelSelector) (*unstructured.UnstructuredList, error) {
func (c *Client) ListResource(apiVersion string, kind string, namespace string, lselector *meta.LabelSelector) (*unstructured.UnstructuredList, error) {
options := meta.ListOptions{}
if lselector != nil {
options = meta.ListOptions{LabelSelector: helperv1.FormatLabelSelector(lselector)}
}
return c.getResourceInterface(kind, namespace).List(options)
return c.getResourceInterface(apiVersion, kind, namespace).List(options)
}
// DeleteResource deletes the specified resource
func (c *Client) DeleteResource(kind string, namespace string, name string, dryRun bool) error {
func (c *Client) DeleteResource(apiVersion string, kind string, namespace string, name string, dryRun bool) error {
options := meta.DeleteOptions{}
if dryRun {
options = meta.DeleteOptions{DryRun: []string{meta.DryRunAll}}
}
return c.getResourceInterface(kind, namespace).Delete(name, &options)
return c.getResourceInterface(apiVersion, kind, namespace).Delete(name, &options)
}
// CreateResource creates object for the specified resource/namespace
func (c *Client) CreateResource(kind string, namespace string, obj interface{}, dryRun bool) (*unstructured.Unstructured, error) {
func (c *Client) CreateResource(apiVersion string, kind string, namespace string, obj interface{}, dryRun bool) (*unstructured.Unstructured, error) {
options := meta.CreateOptions{}
if dryRun {
options = meta.CreateOptions{DryRun: []string{meta.DryRunAll}}
}
// convert typed to unstructured obj
if unstructuredObj := convertToUnstructured(obj); unstructuredObj != nil {
return c.getResourceInterface(kind, namespace).Create(unstructuredObj, options)
return c.getResourceInterface(apiVersion, kind, namespace).Create(unstructuredObj, options)
}
return nil, fmt.Errorf("Unable to create resource ")
}
// UpdateResource updates object for the specified resource/namespace
func (c *Client) UpdateResource(kind string, namespace string, obj interface{}, dryRun bool) (*unstructured.Unstructured, error) {
func (c *Client) UpdateResource(apiVersion string, kind string, namespace string, obj interface{}, dryRun bool) (*unstructured.Unstructured, error) {
options := meta.UpdateOptions{}
if dryRun {
options = meta.UpdateOptions{DryRun: []string{meta.DryRunAll}}
}
// convert typed to unstructured obj
if unstructuredObj := convertToUnstructured(obj); unstructuredObj != nil {
return c.getResourceInterface(kind, namespace).Update(unstructuredObj, options)
return c.getResourceInterface(apiVersion, kind, namespace).Update(unstructuredObj, options)
}
return nil, fmt.Errorf("Unable to update resource ")
}
// UpdateStatusResource updates the resource "status" subresource
func (c *Client) UpdateStatusResource(kind string, namespace string, obj interface{}, dryRun bool) (*unstructured.Unstructured, error) {
func (c *Client) UpdateStatusResource(apiVersion string, kind string, namespace string, obj interface{}, dryRun bool) (*unstructured.Unstructured, error) {
options := meta.UpdateOptions{}
if dryRun {
options = meta.UpdateOptions{DryRun: []string{meta.DryRunAll}}
}
// convert typed to unstructured obj
if unstructuredObj := convertToUnstructured(obj); unstructuredObj != nil {
return c.getResourceInterface(kind, namespace).UpdateStatus(unstructuredObj, options)
return c.getResourceInterface(apiVersion, kind, namespace).UpdateStatus(unstructuredObj, options)
}
return nil, fmt.Errorf("Unable to update resource ")
}
@ -221,8 +225,9 @@ func convertToCSR(obj *unstructured.Unstructured) (*certificates.CertificateSign
//IDiscovery provides interface to mange Kind and GVR mapping
type IDiscovery interface {
FindResource(kind string) (*meta.APIResource, schema.GroupVersionResource, error)
FindResource(apiVersion string, kind string) (*meta.APIResource, schema.GroupVersionResource, error)
GetGVRFromKind(kind string) schema.GroupVersionResource
GetGVRFromAPIVersionKind(apiVersion string, kind string) schema.GroupVersionResource
GetServerVersion() (*version.Info, error)
OpenAPISchema() (*openapi_v2.Document, error)
}
@ -265,7 +270,7 @@ func (c ServerPreferredResources) OpenAPISchema() (*openapi_v2.Document, error)
// GetGVRFromKind get the Group Version Resource from kind
func (c ServerPreferredResources) GetGVRFromKind(kind string) schema.GroupVersionResource {
_, gvr, err := c.FindResource(kind)
_, gvr, err := c.FindResource("", kind)
if err != nil {
c.log.Info("schema not found", "kind", kind)
return schema.GroupVersionResource{}
@ -274,6 +279,17 @@ func (c ServerPreferredResources) GetGVRFromKind(kind string) schema.GroupVersio
return gvr
}
// GetGVRFromAPIVersionKind get the Group Version Resource from APIVersion and kind
func (c ServerPreferredResources) GetGVRFromAPIVersionKind(apiVersion string, kind string) schema.GroupVersionResource {
_, gvr, err := c.FindResource(apiVersion, kind)
if err != nil {
c.log.Info("schema not found", "kind", kind, "apiVersion", apiVersion, "Error : ", err)
return schema.GroupVersionResource{}
}
return gvr
}
// GetServerVersion returns the server version of the cluster
func (c ServerPreferredResources) GetServerVersion() (*version.Info, error) {
return c.cachedClient.ServerVersion()
@ -281,15 +297,15 @@ func (c ServerPreferredResources) GetServerVersion() (*version.Info, error) {
// FindResource finds an API resource that matches 'kind'. If the resource is not
// found and the Cache is not fresh, the cache is invalidated and a retry is attempted
func (c ServerPreferredResources) FindResource(kind string) (*meta.APIResource, schema.GroupVersionResource, error) {
r, gvr, err := c.findResource(kind)
func (c ServerPreferredResources) FindResource(apiVersion string, kind string) (*meta.APIResource, schema.GroupVersionResource, error) {
r, gvr, err := c.findResource(apiVersion, kind)
if err == nil {
return r, gvr, nil
}
if !c.cachedClient.Fresh() {
c.cachedClient.Invalidate()
if r, gvr, err = c.findResource(kind); err == nil {
if r, gvr, err = c.findResource(apiVersion, kind); err == nil {
return r, gvr, nil
}
}
@ -297,18 +313,29 @@ func (c ServerPreferredResources) FindResource(kind string) (*meta.APIResource,
return nil, schema.GroupVersionResource{}, err
}
func (c ServerPreferredResources) findResource(k string) (*meta.APIResource, schema.GroupVersionResource, error) {
serverresources, err := c.cachedClient.ServerPreferredResources()
func (c ServerPreferredResources) findResource(apiVersion string, kind string) (*meta.APIResource, schema.GroupVersionResource, error) {
var serverresources []*meta.APIResourceList
var err error
if apiVersion == "" {
serverresources, err = c.cachedClient.ServerPreferredResources()
} else {
serverresources, err = c.cachedClient.ServerResources()
}
if err != nil {
c.log.Error(err, "failed to get registered preferred resources")
return nil, schema.GroupVersionResource{}, err
}
for _, serverresource := range serverresources {
if apiVersion != "" && serverresource.GroupVersion != apiVersion {
continue
}
for _, resource := range serverresource.APIResources {
// skip the resource names with "/", to avoid comparison with subresources
if resource.Kind == k && !strings.Contains(resource.Name, "/") {
if resource.Kind == kind && !strings.Contains(resource.Name, "/") {
gv, err := schema.ParseGroupVersion(serverresource.GroupVersion)
if err != nil {
c.log.Error(err, "failed to parse groupVersion", "groupVersion", serverresource.GroupVersion)
@ -320,5 +347,5 @@ func (c ServerPreferredResources) findResource(k string) (*meta.APIResource, sch
}
}
return nil, schema.GroupVersionResource{}, fmt.Errorf("kind '%s' not found", k)
return nil, schema.GroupVersionResource{}, fmt.Errorf("kind '%s' not found in apiVersion '%s'", kind, apiVersion)
}

View file

@ -63,32 +63,32 @@ func newFixture(t *testing.T) *fixture {
func TestCRUDResource(t *testing.T) {
f := newFixture(t)
// Get Resource
_, err := f.client.GetResource("thekind", "ns-foo", "name-foo")
_, err := f.client.GetResource("", "thekind", "ns-foo", "name-foo")
if err != nil {
t.Errorf("GetResource not working: %s", err)
}
// List Resources
_, err = f.client.ListResource("thekind", "ns-foo", nil)
_, err = f.client.ListResource("", "thekind", "ns-foo", nil)
if err != nil {
t.Errorf("ListResource not working: %s", err)
}
// DeleteResouce
err = f.client.DeleteResource("thekind", "ns-foo", "name-bar", false)
err = f.client.DeleteResource("", "thekind", "ns-foo", "name-bar", false)
if err != nil {
t.Errorf("DeleteResouce not working: %s", err)
}
// CreateResource
_, err = f.client.CreateResource("thekind", "ns-foo", newUnstructured("group/version", "TheKind", "ns-foo", "name-foo1"), false)
_, err = f.client.CreateResource("", "thekind", "ns-foo", newUnstructured("group/version", "TheKind", "ns-foo", "name-foo1"), false)
if err != nil {
t.Errorf("CreateResource not working: %s", err)
}
// UpdateResource
_, err = f.client.UpdateResource("thekind", "ns-foo", newUnstructuredWithSpec("group/version", "TheKind", "ns-foo", "name-foo1", map[string]interface{}{"foo": "bar"}), false)
_, err = f.client.UpdateResource("", "thekind", "ns-foo", newUnstructuredWithSpec("group/version", "TheKind", "ns-foo", "name-foo1", map[string]interface{}{"foo": "bar"}), false)
if err != nil {
t.Errorf("UpdateResource not working: %s", err)
}
// UpdateStatusResource
_, err = f.client.UpdateStatusResource("thekind", "ns-foo", newUnstructuredWithSpec("group/version", "TheKind", "ns-foo", "name-foo1", map[string]interface{}{"foo": "status"}), false)
_, err = f.client.UpdateStatusResource("", "thekind", "ns-foo", newUnstructuredWithSpec("group/version", "TheKind", "ns-foo", "name-foo1", map[string]interface{}{"foo": "status"}), false)
if err != nil {
t.Errorf("UpdateStatusResource not working: %s", err)
}

View file

@ -78,7 +78,12 @@ func (c *fakeDiscoveryClient) GetGVRFromKind(kind string) schema.GroupVersionRes
return c.getGVR(resource)
}
func (c *fakeDiscoveryClient) FindResource(kind string) (*meta.APIResource, schema.GroupVersionResource, error) {
func (c *fakeDiscoveryClient) GetGVRFromAPIVersionKind(apiVersion string, kind string) schema.GroupVersionResource {
resource := strings.ToLower(kind) + "s"
return c.getGVR(resource)
}
func (c *fakeDiscoveryClient) FindResource(apiVersion string, kind string) (*meta.APIResource, schema.GroupVersionResource, error) {
return nil, schema.GroupVersionResource{}, fmt.Errorf("Not implemented")
}

View file

@ -184,7 +184,7 @@ func (gen *Generator) syncHandler(key Info) error {
return err
}
default:
robj, err = gen.client.GetResource(key.Kind, key.Namespace, key.Name)
robj, err = gen.client.GetResource("", key.Kind, key.Namespace, key.Name)
if err != nil {
logger.Error(err, "failed to get resource", "kind", key.Kind, "name", key.Name, "namespace", key.Namespace)
return err

View file

@ -26,7 +26,7 @@ func (c *Controller) processGR(gr kyverno.GenerateRequest) error {
}
func ownerResourceExists(log logr.Logger, client *dclient.Client, gr kyverno.GenerateRequest) bool {
_, err := client.GetResource(gr.Spec.Resource.Kind, gr.Spec.Resource.Namespace, gr.Spec.Resource.Name)
_, err := client.GetResource("", gr.Spec.Resource.Kind, gr.Spec.Resource.Namespace, gr.Spec.Resource.Name)
// trigger resources has been deleted
if apierrors.IsNotFound(err) {
return false
@ -41,7 +41,7 @@ func ownerResourceExists(log logr.Logger, client *dclient.Client, gr kyverno.Gen
func deleteGeneratedResources(log logr.Logger, client *dclient.Client, gr kyverno.GenerateRequest) error {
for _, genResource := range gr.Status.GeneratedResources {
err := client.DeleteResource(genResource.Kind, genResource.Namespace, genResource.Name, false)
err := client.DeleteResource("", genResource.Kind, genResource.Namespace, genResource.Name, false)
if apierrors.IsNotFound(err) {
log.Error(err, "resource not foundl will not delete", "genKind", gr.Spec.Resource.Kind, "genNamespace", gr.Spec.Resource.Namespace, "genName", gr.Spec.Resource.Name)
continue

View file

@ -18,7 +18,7 @@ import (
)
func (c *Controller) processGR(gr *kyverno.GenerateRequest) error {
logger := c.log.WithValues("name", gr.Name, "policy", gr.Spec.Policy, "kind", gr.Spec.Resource.Kind, "namespace", gr.Spec.Resource.Namespace, "name", gr.Spec.Resource.Name)
logger := c.log.WithValues("name", gr.Name, "policy", gr.Spec.Policy, "kind", gr.Spec.Resource.Kind, "apiVersion", gr.Spec.Resource.APIVersion, "namespace", gr.Spec.Resource.Namespace, "name", gr.Spec.Resource.Name)
var err error
var resource *unstructured.Unstructured
var genResources []kyverno.ResourceSpec
@ -43,7 +43,7 @@ func (c *Controller) processGR(gr *kyverno.GenerateRequest) error {
}
func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyverno.GenerateRequest) ([]kyverno.ResourceSpec, error) {
logger := c.log.WithValues("name", gr.Name, "policy", gr.Spec.Policy, "kind", gr.Spec.Resource.Kind, "namespace", gr.Spec.Resource.Namespace, "name", gr.Spec.Resource.Name)
logger := c.log.WithValues("name", gr.Name, "policy", gr.Spec.Policy, "kind", gr.Spec.Resource.Kind, "apiVersion", gr.Spec.Resource.APIVersion, "namespace", gr.Spec.Resource.Namespace, "name", gr.Spec.Resource.Name)
// Get the list of rules to be applied
// get policy
// build context
@ -53,14 +53,14 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern
if err != nil {
if apierrors.IsNotFound(err) {
for _, e := range gr.Status.GeneratedResources {
resp, err := c.client.GetResource(e.Kind, e.Namespace, e.Name)
resp, err := c.client.GetResource(e.APIVersion, e.Kind, e.Namespace, e.Name)
if err != nil {
logger.Error(err, "Generated resource failed to get", "Resource", e.Name)
}
labels := resp.GetLabels()
if labels["policy.kyverno.io/synchronize"] == "enable" {
if err := c.client.DeleteResource(resp.GetKind(), resp.GetNamespace(), resp.GetName(), false); err != nil {
if err := c.client.DeleteResource(resp.GetAPIVersion(), resp.GetKind(), resp.GetNamespace(), resp.GetName(), false); err != nil {
logger.Error(err, "Generated resource is not deleted", "Resource", e.Name)
}
}
@ -231,8 +231,14 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
return noGenResource, err
}
genAPIVersion, _, err := unstructured.NestedString(genUnst.Object, "apiVersion")
if err != nil {
return noGenResource, err
}
// Resource to be generated
newGenResource := kyverno.ResourceSpec{
APIVersion: genAPIVersion,
Kind: genKind,
Namespace: genNamespace,
Name: genName,
@ -247,9 +253,9 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
}
if genData != nil {
rdata, mode, err = manageData(log, genKind, genNamespace, genName, genData, client, resource)
rdata, mode, err = manageData(log, genAPIVersion, genKind, genNamespace, genName, genData, client, resource)
} else {
rdata, mode, err = manageClone(log, genKind, genNamespace, genName, genCopy, client, resource)
rdata, mode, err = manageClone(log, genAPIVersion, genKind, genNamespace, genName, genCopy, client, resource)
}
if err != nil {
return noGenResource, err
@ -275,12 +281,13 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
if newResource.GetKind() == "" {
newResource.SetKind(genKind)
}
newResource.SetAPIVersion(genAPIVersion)
// manage labels
// - app.kubernetes.io/managed-by: kyverno
// - kyverno.io/generated-by: kind/namespace/name (trigger resource)
manageLabels(newResource, resource)
logger := log.WithValues("genKind", genKind, "genNamespace", genNamespace, "genName", genName)
logger := log.WithValues("genKind", genKind, "genAPIVersion", genAPIVersion, "genNamespace", genNamespace, "genName", genName)
// Add Synchronize label
label := newResource.GetLabels()
@ -297,7 +304,7 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
newResource.SetResourceVersion("")
// Create the resource
logger.V(4).Info("creating new resource")
_, err = client.CreateResource(genKind, genNamespace, newResource, false)
_, err = client.CreateResource(genAPIVersion, genKind, genNamespace, newResource, false)
if err != nil {
// Failed to create resource
return noGenResource, err
@ -310,7 +317,7 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
if rule.Generation.Synchronize {
logger.V(4).Info("updating existing resource")
// Update the resource
_, err := client.UpdateResource(genKind, genNamespace, newResource, false)
_, err := client.UpdateResource(genAPIVersion, genKind, genNamespace, newResource, false)
if err != nil {
logger.Error(err, "updating existing resource")
// Failed to update resource
@ -328,11 +335,11 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou
return newGenResource, nil
}
func manageData(log logr.Logger, kind, namespace, name string, data map[string]interface{}, client *dclient.Client, resource unstructured.Unstructured) (map[string]interface{}, ResourceMode, error) {
func manageData(log logr.Logger, apiVersion, kind, namespace, name string, data map[string]interface{}, client *dclient.Client, resource unstructured.Unstructured) (map[string]interface{}, ResourceMode, error) {
// check if resource to be generated exists
obj, err := client.GetResource(kind, namespace, name)
obj, err := client.GetResource(apiVersion, kind, namespace, name)
if apierrors.IsNotFound(err) {
log.Error(err, "resource does not exist, will try to create", "genKind", kind, "genNamespace", namespace, "genName", name)
log.Error(err, "resource does not exist, will try to create", "genKind", kind, "genAPIVersion", apiVersion, "genNamespace", namespace, "genName", name)
return data, Create, nil
}
if err != nil {
@ -346,12 +353,12 @@ func manageData(log logr.Logger, kind, namespace, name string, data map[string]i
// Existing resource does contain the mentioned configuration in spec, skip processing the resource as it is already in expected state
return nil, Skip, nil
}
log.Info("to be generated resoruce already exists, but is missing the specifeid configurations, will try to update", "genKind", kind, "genNamespace", namespace, "genName", name)
log.Info("to be generated resoruce already exists, but is missing the specifeid configurations, will try to update", "genKind", kind, "genAPIVersion", apiVersion, "genNamespace", namespace, "genName", name)
return data, Update, nil
}
func manageClone(log logr.Logger, kind, namespace, name string, clone map[string]interface{}, client *dclient.Client, resource unstructured.Unstructured) (map[string]interface{}, ResourceMode, error) {
func manageClone(log logr.Logger, apiVersion, kind, namespace, name string, clone map[string]interface{}, client *dclient.Client, resource unstructured.Unstructured) (map[string]interface{}, ResourceMode, error) {
newRNs, _, err := unstructured.NestedString(clone, "namespace")
if err != nil {
return nil, Skip, err
@ -360,6 +367,7 @@ func manageClone(log logr.Logger, kind, namespace, name string, clone map[string
if err != nil {
return nil, Skip, err
}
// Short-circuit if the resource to be generated and the clone is the same
if newRNs == namespace && newRName == name {
// attempting to clone it self, this will fail -> short-ciruit it
@ -367,13 +375,13 @@ func manageClone(log logr.Logger, kind, namespace, name string, clone map[string
}
// check if the resource as reference in clone exists?
obj, err := client.GetResource(kind, newRNs, newRName)
obj, err := client.GetResource(apiVersion, kind, newRNs, newRName)
if err != nil {
return nil, Skip, fmt.Errorf("reference clone resource %s/%s/%s not found. %v", kind, newRNs, newRName, err)
return nil, Skip, fmt.Errorf("reference clone resource %s/%s/%s/%s not found. %v", apiVersion, kind, newRNs, newRName, err)
}
// check if resource to be generated exists
newResource, err := client.GetResource(kind, namespace, name)
newResource, err := client.GetResource(apiVersion, kind, namespace, name)
if err == nil {
obj.SetUID(newResource.GetUID())
obj.SetSelfLink(newResource.GetSelfLink())
@ -388,7 +396,7 @@ func manageClone(log logr.Logger, kind, namespace, name string, clone map[string
//TODO: check this
if !apierrors.IsNotFound(err) {
log.Error(err, "reference/clone resource is not found", "genKind", kind, "genNamespace", namespace, "genName", name)
log.Error(err, "reference/clone resource is not found", "genKind", kind, "genAPIVersion", apiVersion, "genNamespace", namespace, "genName", name)
//something wrong while fetching resource
return nil, Skip, err
}

View file

@ -7,5 +7,5 @@ import (
)
func getResource(client *dclient.Client, resourceSpec kyverno.ResourceSpec) (*unstructured.Unstructured, error) {
return client.GetResource(resourceSpec.Kind, resourceSpec.Namespace, resourceSpec.Name)
return client.GetResource(resourceSpec.APIVersion, resourceSpec.Kind, resourceSpec.Namespace, resourceSpec.Name)
}

View file

@ -190,7 +190,7 @@ func getResourcesOfTypeFromCluster(resourceTypes []string, dClient *client.Clien
var resources []*unstructured.Unstructured
for _, kind := range resourceTypes {
resourceList, err := dClient.ListResource(kind, "", nil)
resourceList, err := dClient.ListResource("", kind, "", nil)
if err != nil {
return nil, err
}

View file

@ -65,7 +65,7 @@ func (pc *PolicyController) listResources(policy *kyverno.ClusterPolicy) map[str
for _, rule := range policy.Spec.Rules {
for _, k := range rule.MatchResources.Kinds {
resourceSchema, _, err := pc.client.DiscoveryClient.FindResource(k)
resourceSchema, _, err := pc.client.DiscoveryClient.FindResource("", k)
if err != nil {
pc.log.Error(err, "failed to find resource", "kind", k)
continue
@ -179,7 +179,7 @@ func getResourcesPerNamespace(kind string, client *client.Client, namespace stri
namespace = ""
}
list, err := client.ListResource(kind, namespace, ls)
list, err := client.ListResource("", kind, namespace, ls)
if err != nil {
log.Error(err, "failed to list resources", "kind", kind, "namespace", namespace)
return nil

View file

@ -44,7 +44,7 @@ func retryGetResource(client *client.Client, rspec kyverno.ResourceSpec) (*unstr
var obj *unstructured.Unstructured
var err error
getResource := func() error {
obj, err = client.GetResource(rspec.Kind, rspec.Namespace, rspec.Name)
obj, err = client.GetResource("", rspec.Kind, rspec.Namespace, rspec.Name)
log.Log.V(4).Info(fmt.Sprintf("retry %v getting %s/%s/%s", i, rspec.Kind, rspec.Namespace, rspec.Name))
i++
return err

View file

@ -169,14 +169,14 @@ func runTestCase(t *testing.T, tc scaseT) bool {
}
func createNamespace(client *client.Client, ns *unstructured.Unstructured) error {
_, err := client.CreateResource("Namespace", "", ns, false)
_, err := client.CreateResource("", "Namespace", "", ns, false)
return err
}
func validateGeneratedResources(t *testing.T, client *client.Client, policy kyverno.ClusterPolicy, namespace string, expected []kyverno.ResourceSpec) {
t.Log("--validate if resources are generated---")
// list of expected generated resources
for _, resource := range expected {
if _, err := client.GetResource(resource.Kind, namespace, resource.Name); err != nil {
if _, err := client.GetResource("", resource.Kind, namespace, resource.Name); err != nil {
t.Errorf("generated resource %s/%s/%s not found. %v", resource.Kind, namespace, resource.Name, err)
}
}

View file

@ -88,7 +88,7 @@ func CleanupOldCrd(client *dclient.Client, log logr.Logger) {
logger := log.WithName("CleanupOldCrd")
gvr := client.DiscoveryClient.GetGVRFromKind("NamespacedPolicyViolation")
if !reflect.DeepEqual(gvr, (schema.GroupVersionResource{})) {
if err := client.DeleteResource("CustomResourceDefinition", "", "namespacedpolicyviolations.kyverno.io", false); err != nil {
if err := client.DeleteResource("", "CustomResourceDefinition", "", "namespacedpolicyviolations.kyverno.io", false); err != nil {
logger.Error(err, "Failed to remove prevous CRD", "kind", "namespacedpolicyviolation")
}
}

View file

@ -70,7 +70,7 @@ func (wrc *WebhookRegistrationClient) removeVerifyWebhookMutatingWebhookConfig(w
}
logger := wrc.log.WithValues("name", mutatingConfig)
err = wrc.client.DeleteResource(MutatingWebhookConfigurationKind, "", mutatingConfig, false)
err = wrc.client.DeleteResource("", MutatingWebhookConfigurationKind, "", mutatingConfig, false)
if errorsapi.IsNotFound(err) {
logger.V(5).Info("verify webhook configuration not found")
return

View file

@ -112,7 +112,7 @@ func (wrc *WebhookRegistrationClient) CreateResourceMutatingWebhookConfiguration
// clientConfig - service
config = wrc.constructMutatingWebhookConfig(caData)
}
_, err := wrc.client.CreateResource(MutatingWebhookConfigurationKind, "", *config, false)
_, err := wrc.client.CreateResource("", MutatingWebhookConfigurationKind, "", *config, false)
if errorsapi.IsAlreadyExists(err) {
logger.V(6).Info("resource mutating webhook configuration already exists", "name", config.Name)
return nil
@ -143,7 +143,7 @@ func (wrc *WebhookRegistrationClient) CreateResourceValidatingWebhookConfigurati
}
logger := wrc.log.WithValues("kind", ValidatingWebhookConfigurationKind, "name", config.Name)
_, err := wrc.client.CreateResource(ValidatingWebhookConfigurationKind, "", *config, false)
_, err := wrc.client.CreateResource("", ValidatingWebhookConfigurationKind, "", *config, false)
if errorsapi.IsAlreadyExists(err) {
logger.V(6).Info("resource validating webhook configuration already exists", "name", config.Name)
return nil
@ -179,7 +179,7 @@ func (wrc *WebhookRegistrationClient) createPolicyValidatingWebhookConfiguration
logger := wrc.log.WithValues("kind", ValidatingWebhookConfigurationKind, "name", config.Name)
// create validating webhook configuration resource
if _, err := wrc.client.CreateResource(ValidatingWebhookConfigurationKind, "", *config, false); err != nil {
if _, err := wrc.client.CreateResource("", ValidatingWebhookConfigurationKind, "", *config, false); err != nil {
return err
}
logger.V(4).Info("created resource")
@ -207,7 +207,7 @@ func (wrc *WebhookRegistrationClient) createPolicyMutatingWebhookConfiguration()
}
// create mutating webhook configuration resource
if _, err := wrc.client.CreateResource(MutatingWebhookConfigurationKind, "", *config, false); err != nil {
if _, err := wrc.client.CreateResource("", MutatingWebhookConfigurationKind, "", *config, false); err != nil {
return err
}
wrc.log.V(4).Info("reated Mutating Webhook Configuration", "name", config.Name)
@ -236,7 +236,7 @@ func (wrc *WebhookRegistrationClient) createVerifyMutatingWebhookConfiguration()
}
// create mutating webhook configuration resource
if _, err := wrc.client.CreateResource(MutatingWebhookConfigurationKind, "", *config, false); err != nil {
if _, err := wrc.client.CreateResource("", MutatingWebhookConfigurationKind, "", *config, false); err != nil {
return err
}
@ -295,7 +295,7 @@ func (wrc *WebhookRegistrationClient) removePolicyMutatingWebhookConfiguration(w
}
logger := wrc.log.WithValues("name", mutatingConfig)
err := wrc.client.DeleteResource(MutatingWebhookConfigurationKind, "", mutatingConfig, false)
err := wrc.client.DeleteResource("", MutatingWebhookConfigurationKind, "", mutatingConfig, false)
if errorsapi.IsNotFound(err) {
logger.V(5).Info("policy mutating webhook configuration not found")
return
@ -321,7 +321,7 @@ func (wrc *WebhookRegistrationClient) removePolicyValidatingWebhookConfiguration
logger := wrc.log.WithValues("name", validatingConfig)
logger.V(4).Info("removing validating webhook configuration")
err := wrc.client.DeleteResource(ValidatingWebhookConfigurationKind, "", validatingConfig, false)
err := wrc.client.DeleteResource("", ValidatingWebhookConfigurationKind, "", validatingConfig, false)
if errorsapi.IsNotFound(err) {
logger.V(5).Info("policy validating webhook configuration not found")
return

View file

@ -70,7 +70,7 @@ func (wrc *WebhookRegistrationClient) RemoveResourceMutatingWebhookConfiguration
configName := wrc.GetResourceMutatingWebhookConfigName()
logger := wrc.log.WithValues("kind", MutatingWebhookConfigurationKind, "name", configName)
// delete webhook configuration
err := wrc.client.DeleteResource(MutatingWebhookConfigurationKind, "", configName, false)
err := wrc.client.DeleteResource("", MutatingWebhookConfigurationKind, "", configName, false)
if errors.IsNotFound(err) {
logger.V(4).Info("webhook configuration not found")
return
@ -144,7 +144,7 @@ func (wrc *WebhookRegistrationClient) GetResourceValidatingWebhookConfigName() s
func (wrc *WebhookRegistrationClient) RemoveResourceValidatingWebhookConfiguration() {
configName := wrc.GetResourceValidatingWebhookConfigName()
logger := wrc.log.WithValues("kind", ValidatingWebhookConfigurationKind, "name", configName)
err := wrc.client.DeleteResource(ValidatingWebhookConfigurationKind, "", configName, false)
err := wrc.client.DeleteResource("", ValidatingWebhookConfigurationKind, "", configName, false)
if errors.IsNotFound(err) {
logger.V(5).Info("webhook configuration not found")
return