mirror of
https://github.com/kyverno/kyverno.git
synced 2024-12-14 11:57:48 +00:00
9a8e35d787
* feature: Add LabelSelector as a field of resource spec to allow fetching by labels
Signed-off-by: aerosouund <aerosound161@gmail.com>
* chore: Generate CRDs
Signed-off-by: aerosouund <aerosound161@gmail.com>
* feat: Add the capability to fetch with label selector
- Add the label selector as a parameter to GetResources of the engine api client and the dclient.
- Use the label selector with list options in the dclient.
- convert a metav1.LabelSelector to a labels.Selector before fetching to be able to convert it to a string to be used with ListOptions.
Signed-off-by: aerosouund <aerosound161@gmail.com>
* feat: Pass label selector to the GetResources method
Signed-off-by: aerosouund <aerosound161@gmail.com>
* feat: Return the resource selector when resolving spec
Signed-off-by: aerosouund <aerosound161@gmail.com>
* fix: Instantiate the fake client schema using the passed gvrToListKind map and by inferring schema from passed resources
All tests that use List will fail because the fake client doesn't infer the schema from the passed resources.
gvrToListKind can't be fully deprecated as some parts of kyverno use the fake client without passing resources to it (resource generation). And so both approaches have to be supported.
References:
- https://github.com/kubernetes/client-go/issues/983
- 46c1ad3baa
Signed-off-by: aerosouund <aerosound161@gmail.com>
* test: Add labelSelector unit test to mutate existing test.
- Remove the unwanted call to GetResource.
- Pass an empty map of GVR to string to the fake client constructor.
Signed-off-by: aerosouund <aerosound161@gmail.com>
* test: Add chainsaw test
Signed-off-by: aerosouund <aerosound161@gmail.com>
* chore: Run codegen
Signed-off-by: aerosouund <aerosound161@gmail.com>
* chore: Generate helm CRDs
Signed-off-by: aerosouund <aerosound161@gmail.com>
* refactor: Put the LabelSelector in a separate struct
Many types use the ResourceSpec struct and not all of them support label selectors.
This removes the field into a separate schema dedicated to target selection called TargetSelector.
It has the ResourceSpec and the selector.
Signed-off-by: aerosouund <aerosound161@gmail.com>
* chore: Run codegen after modifying selector comment
Signed-off-by: aerosouund <aerosound161@gmail.com>
* chore: Run codegen
Signed-off-by: aerosouund <aerosound161@gmail.com>
---------
Signed-off-by: aerosouund <aerosound161@gmail.com>
Co-authored-by: shuting <shuting@nirmata.com>
79 lines
2.8 KiB
Go
79 lines
2.8 KiB
Go
package adapters
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
|
|
"github.com/kyverno/kyverno/pkg/auth"
|
|
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
|
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
|
corev1 "k8s.io/api/core/v1"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
)
|
|
|
|
type dclientAdapter struct {
|
|
client dclient.Interface
|
|
}
|
|
|
|
func Client(client dclient.Interface) engineapi.Client {
|
|
return &dclientAdapter{client}
|
|
}
|
|
|
|
func (a *dclientAdapter) RawAbsPath(ctx context.Context, path, method string, dataReader io.Reader) ([]byte, error) {
|
|
return a.client.RawAbsPath(ctx, path, method, dataReader)
|
|
}
|
|
|
|
func (a *dclientAdapter) GetResources(ctx context.Context, group, version, kind, subresource, namespace, name string, lselector *metav1.LabelSelector) ([]engineapi.Resource, error) {
|
|
resources, err := dclient.GetResources(ctx, a.client, group, version, kind, subresource, namespace, name, lselector)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
result := make([]engineapi.Resource, 0, len(resources))
|
|
for _, resource := range resources {
|
|
result = append(result, engineapi.Resource{
|
|
Group: resource.Group,
|
|
Version: resource.Version,
|
|
Resource: resource.Resource,
|
|
SubResource: resource.SubResource,
|
|
Unstructured: resource.Unstructured,
|
|
})
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (a *dclientAdapter) GetResource(ctx context.Context, apiVersion, kind, namespace, name string, subresources ...string) (*unstructured.Unstructured, error) {
|
|
return a.client.GetResource(ctx, apiVersion, kind, namespace, name, subresources...)
|
|
}
|
|
|
|
func (a *dclientAdapter) GetNamespace(ctx context.Context, name string, opts metav1.GetOptions) (*corev1.Namespace, error) {
|
|
return a.client.GetKubeClient().CoreV1().Namespaces().Get(ctx, name, opts)
|
|
}
|
|
|
|
func (a *dclientAdapter) ListResource(ctx context.Context, apiVersion string, kind string, namespace string, lselector *metav1.LabelSelector) (*unstructured.UnstructuredList, error) {
|
|
return a.client.ListResource(ctx, apiVersion, kind, namespace, lselector)
|
|
}
|
|
|
|
func (a *dclientAdapter) IsNamespaced(group, version, kind string) (bool, error) {
|
|
gvrss, err := a.client.Discovery().FindResources(group, version, kind, "")
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if len(gvrss) != 1 {
|
|
return false, fmt.Errorf("function IsNamespaced expects only one resource, got (%d)", len(gvrss))
|
|
}
|
|
for _, apiResource := range gvrss {
|
|
return apiResource.Namespaced, nil
|
|
}
|
|
return false, nil
|
|
}
|
|
|
|
func (a *dclientAdapter) CanI(ctx context.Context, kind, namespace, verb, subresource, user string) (bool, string, error) {
|
|
canI := auth.NewCanI(a.client.Discovery(), a.client.GetKubeClient().AuthorizationV1().SubjectAccessReviews(), kind, namespace, "", verb, subresource, user)
|
|
ok, reason, err := canI.RunAccessCheck(ctx)
|
|
if err != nil {
|
|
return false, reason, err
|
|
}
|
|
return ok, reason, nil
|
|
}
|