1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2024-12-15 17:51:20 +00:00

Merge branch 'release-0.1' into 46_redesign

This commit is contained in:
Denys Bielyshev 2019-05-22 17:17:08 +01:00 committed by GitHub
commit 556e2ddca1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 77 additions and 137 deletions

View file

@ -46,14 +46,14 @@ func (c *Client) submitAndApproveCertificateRequest(req *certificates.Certificat
if err != nil {
return nil, err
}
csrList, err := c.ListResource(CSR, "")
csrList, err := c.ListResource(CSRs, "")
if err != nil {
return nil, errors.New(fmt.Sprintf("Unable to list existing certificate requests: %v", err))
}
for _, csr := range csrList.Items {
if csr.GetName() == req.ObjectMeta.Name {
err := c.DeleteResouce(CSR, "", csr.GetName())
err := c.DeleteResouce(CSRs, "", csr.GetName())
if err != nil {
return nil, errors.New(fmt.Sprintf("Unable to delete existing certificate request: %v", err))
}
@ -62,7 +62,7 @@ func (c *Client) submitAndApproveCertificateRequest(req *certificates.Certificat
}
}
unstrRes, err := c.CreateResource(CSR, "", req)
unstrRes, err := c.CreateResource(CSRs, "", req)
if err != nil {
return nil, err
}
@ -91,7 +91,7 @@ func (c *Client) fetchCertificateFromRequest(req *certificates.CertificateSignin
// TODO: react of SIGINT and SIGTERM
timeStart := time.Now()
for time.Now().Sub(timeStart) < time.Duration(maxWaitSeconds)*time.Second {
unstrR, err := c.GetResource(CSR, "", req.ObjectMeta.Name)
unstrR, err := c.GetResource(CSRs, "", req.ObjectMeta.Name)
if err != nil {
return nil, err
}
@ -119,7 +119,7 @@ const certificateField string = "certificate"
// Reads the pair of TLS certificate and key from the specified secret.
func (c *Client) ReadTlsPair(props tls.TlsCertificateProps) *tls.TlsPemPair {
name := generateSecretName(props)
unstrSecret, err := c.GetResource(Secret, props.Namespace, name)
unstrSecret, err := c.GetResource(Secrets, props.Namespace, name)
if err != nil {
c.logger.Printf("Unable to get secret %s/%s: %s", props.Namespace, name, err)
return nil
@ -147,7 +147,7 @@ func (c *Client) ReadTlsPair(props tls.TlsCertificateProps) *tls.TlsPemPair {
// Updates existing secret or creates new one.
func (c *Client) WriteTlsPair(props tls.TlsCertificateProps, pemPair *tls.TlsPemPair) error {
name := generateSecretName(props)
unstrSecret, err := c.GetResource(Secret, props.Namespace, name)
unstrSecret, err := c.GetResource(Secrets, props.Namespace, name)
if err == nil {
secret, err := convertToSecret(unstrSecret)
if err != nil {
@ -159,7 +159,7 @@ func (c *Client) WriteTlsPair(props tls.TlsCertificateProps, pemPair *tls.TlsPem
}
secret.Data[certificateField] = pemPair.Certificate
secret.Data[privateKeyField] = pemPair.PrivateKey
_, err = c.UpdateResource(Secret, props.Namespace, secret)
_, err = c.UpdateResource(Secrets, props.Namespace, secret)
if err == nil {
c.logger.Printf("Secret %s is updated", name)
}
@ -181,7 +181,7 @@ func (c *Client) WriteTlsPair(props tls.TlsCertificateProps, pemPair *tls.TlsPem
},
}
_, err := c.CreateResource(Secret, props.Namespace, secret)
_, err := c.CreateResource(Secrets, props.Namespace, secret)
if err == nil {
c.logger.Printf("Secret %s is created", name)
}

View file

@ -16,16 +16,21 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/discovery"
"k8s.io/client-go/discovery/cached/memory"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
csrtype "k8s.io/client-go/kubernetes/typed/certificates/v1beta1"
event "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/client-go/rest"
)
type Client struct {
logger *log.Logger
client dynamic.Interface
cachedClient discovery.CachedDiscoveryInterface
logger *log.Logger
clientConfig *rest.Config
kclient *kubernetes.Clientset
}
func NewClient(config *rest.Config, logger *log.Logger) (*Client, error) {
@ -38,10 +43,17 @@ func NewClient(config *rest.Config, logger *log.Logger) (*Client, error) {
logger = log.New(os.Stdout, "Client : ", log.LstdFlags)
}
kclient, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, err
}
return &Client{
logger: logger,
client: client,
clientConfig: config,
kclient: kclient,
cachedClient: memory.NewMemCacheClient(kclient.Discovery()),
}, nil
}
@ -61,29 +73,20 @@ func (c *Client) GetKubePolicyDeployment() (*apps.Deployment, error) {
// or generate a kube client value to access the interface
//GetEventsInterface provides typed interface for events
func (c *Client) GetEventsInterface() (event.EventInterface, error) {
kubeClient, err := newKubeClient(c.clientConfig)
if err != nil {
return nil, err
}
return kubeClient.CoreV1().Events(""), nil
return c.kclient.CoreV1().Events(""), nil
}
func (c *Client) GetCSRInterface() (csrtype.CertificateSigningRequestInterface, error) {
kubeClient, err := newKubeClient(c.clientConfig)
if err != nil {
return nil, err
}
return kubeClient.CertificatesV1beta1().CertificateSigningRequests(), nil
return c.kclient.CertificatesV1beta1().CertificateSigningRequests(), nil
}
func (c *Client) getInterface(kind string) dynamic.NamespaceableResourceInterface {
return c.client.Resource(c.getGroupVersionMapper(kind))
func (c *Client) getInterface(resource string) dynamic.NamespaceableResourceInterface {
return c.client.Resource(c.getGroupVersionMapper(resource))
}
func (c *Client) getResourceInterface(kind string, namespace string) dynamic.ResourceInterface {
func (c *Client) getResourceInterface(resource string, namespace string) dynamic.ResourceInterface {
// Get the resource interface
namespaceableInterface := c.getInterface(kind)
namespaceableInterface := c.getInterface(resource)
// Get the namespacable interface
var resourceInteface dynamic.ResourceInterface
if namespace != "" {
@ -95,52 +98,52 @@ 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 {
//TODO: add checks to see if the kind is supported
//TODO: build the resource list dynamically( by querying the registered resource kinds)
func (c *Client) getGroupVersionMapper(resource string) schema.GroupVersionResource {
//TODO: add checks to see if the resource is supported
//TODO: build the resource list dynamically( by querying the registered resources)
//TODO: the error scenarios
return getGrpVersionMapper(kind, c.clientConfig, false)
return c.getGVR(resource)
}
// GetResource returns the resource in unstructured/json format
func (c *Client) GetResource(kind string, namespace string, name string) (*unstructured.Unstructured, error) {
return c.getResourceInterface(kind, namespace).Get(name, meta.GetOptions{})
func (c *Client) GetResource(resource string, namespace string, name string) (*unstructured.Unstructured, error) {
return c.getResourceInterface(resource, namespace).Get(name, meta.GetOptions{})
}
// ListResource returns the list of resources in unstructured/json format
// Access items using []Items
func (c *Client) ListResource(kind string, namespace string) (*unstructured.UnstructuredList, error) {
return c.getResourceInterface(kind, namespace).List(meta.ListOptions{})
func (c *Client) ListResource(resource string, namespace string) (*unstructured.UnstructuredList, error) {
return c.getResourceInterface(resource, namespace).List(meta.ListOptions{})
}
func (c *Client) DeleteResouce(kind string, namespace string, name string) error {
return c.getResourceInterface(kind, namespace).Delete(name, &meta.DeleteOptions{})
func (c *Client) DeleteResouce(resource string, namespace string, name string) error {
return c.getResourceInterface(resource, namespace).Delete(name, &meta.DeleteOptions{})
}
// CreateResource creates object for the specified kind/namespace
func (c *Client) CreateResource(kind string, namespace string, obj interface{}) (*unstructured.Unstructured, error) {
// CreateResource creates object for the specified resource/namespace
func (c *Client) CreateResource(resource string, namespace string, obj interface{}) (*unstructured.Unstructured, error) {
// convert typed to unstructured obj
if unstructuredObj := convertToUnstructured(obj); unstructuredObj != nil {
return c.getResourceInterface(kind, namespace).Create(unstructuredObj, meta.CreateOptions{})
return c.getResourceInterface(resource, namespace).Create(unstructuredObj, meta.CreateOptions{})
}
return nil, fmt.Errorf("Unable to create resource ")
}
// UpdateResource updates object for the specified kind/namespace
func (c *Client) UpdateResource(kind string, namespace string, obj interface{}) (*unstructured.Unstructured, error) {
// UpdateResource updates object for the specified resource/namespace
func (c *Client) UpdateResource(resource string, namespace string, obj interface{}) (*unstructured.Unstructured, error) {
// convert typed to unstructured obj
if unstructuredObj := convertToUnstructured(obj); unstructuredObj != nil {
return c.getResourceInterface(kind, namespace).Update(unstructuredObj, meta.UpdateOptions{})
return c.getResourceInterface(resource, namespace).Update(unstructuredObj, meta.UpdateOptions{})
}
return nil, fmt.Errorf("Unable to update resource ")
}
// UpdateStatusResource updates the resource "status" subresource
func (c *Client) UpdateStatusResource(kind string, namespace string, obj interface{}) (*unstructured.Unstructured, error) {
func (c *Client) UpdateStatusResource(resource string, namespace string, obj interface{}) (*unstructured.Unstructured, error) {
// convert typed to unstructured obj
if unstructuredObj := convertToUnstructured(obj); unstructuredObj != nil {
return c.getResourceInterface(kind, namespace).UpdateStatus(unstructuredObj, meta.UpdateOptions{})
return c.getResourceInterface(resource, namespace).UpdateStatus(unstructuredObj, meta.UpdateOptions{})
}
return nil, fmt.Errorf("Unable to update resource ")
}
@ -178,7 +181,7 @@ func (c *Client) GenerateSecret(generator types.Generation, namespace string) er
// if generator.CopyFrom != nil {
c.logger.Printf("Copying data from secret %s/%s", generator.CopyFrom.Namespace, generator.CopyFrom.Name)
// Get configMap resource
unstrSecret, err := c.GetResource(Secret, generator.CopyFrom.Namespace, generator.CopyFrom.Name)
unstrSecret, err := c.GetResource(Secrets, generator.CopyFrom.Namespace, generator.CopyFrom.Name)
if err != nil {
return err
}
@ -218,7 +221,7 @@ func (c *Client) GenerateConfigMap(generator types.Generation, namespace string)
// if generator.CopyFrom != nil {
c.logger.Printf("Copying data from configmap %s/%s", generator.CopyFrom.Namespace, generator.CopyFrom.Name)
// Get configMap resource
unstrConfigMap, err := c.GetResource("configmaps", generator.CopyFrom.Namespace, generator.CopyFrom.Name)
unstrConfigMap, err := c.GetResource(ConfigMaps, generator.CopyFrom.Namespace, generator.CopyFrom.Name)
if err != nil {
return err
}
@ -275,7 +278,7 @@ func convertToCSR(obj *unstructured.Unstructured) (*certificates.CertificateSign
func (c *Client) createConfigMapAfterNamespaceIsCreated(configMap v1.ConfigMap, namespace string) {
err := c.waitUntilNamespaceIsCreated(namespace)
if err == nil {
_, err = c.CreateResource("configmaps", namespace, configMap)
_, err = c.CreateResource(ConfigMaps, namespace, configMap)
}
if err != nil {
c.logger.Printf("Can't create a configmap: %s", err)
@ -285,7 +288,7 @@ func (c *Client) createConfigMapAfterNamespaceIsCreated(configMap v1.ConfigMap,
func (c *Client) createSecretAfterNamespaceIsCreated(secret v1.Secret, namespace string) {
err := c.waitUntilNamespaceIsCreated(namespace)
if err == nil {
_, err = c.CreateResource(Secret, namespace, secret)
_, err = c.CreateResource(Secrets, namespace, secret)
}
if err != nil {
c.logger.Printf("Can't create a secret: %s", err)
@ -298,7 +301,7 @@ func (c *Client) waitUntilNamespaceIsCreated(name string) error {
var lastError error = nil
for time.Now().Sub(timeStart) < namespaceCreationMaxWaitTime {
_, lastError = c.GetResource("namespaces", "", name)
_, lastError = c.GetResource(Namespaces, "", name)
if lastError == nil {
break
}
@ -306,3 +309,25 @@ func (c *Client) waitUntilNamespaceIsCreated(name string) error {
}
return lastError
}
func (c *Client) getGVR(resource string) schema.GroupVersionResource {
emptyGVR := schema.GroupVersionResource{}
serverresources, err := c.cachedClient.ServerPreferredResources()
if err != nil {
utilruntime.HandleError(err)
return emptyGVR
}
resources, err := discovery.GroupVersionResources(serverresources)
if err != nil {
utilruntime.HandleError(err)
return emptyGVR
}
//TODO using cached client to support cache validation and invalidation
// iterate over the key to compare the resource
for gvr, _ := range resources {
if gvr.Resource == resource {
return gvr
}
}
return emptyGVR
}

View file

@ -1,99 +1,14 @@
package client
import (
"fmt"
"strings"
"time"
"k8s.io/apimachinery/pkg/runtime/schema"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)
const (
CSR string = "certificatesigningrequests"
Secret string = "secrets"
CSRs string = "certificatesigningrequests"
Secrets string = "secrets"
ConfigMaps string = "configmaps"
Namespaces string = "namespaces"
)
const namespaceCreationMaxWaitTime time.Duration = 30 * time.Second
const namespaceCreationWaitInterval time.Duration = 100 * time.Millisecond
var groupVersionMapper map[string]schema.GroupVersionResource
var kubeClient *kubernetes.Clientset
func getGrpVersionMapper(kind string, clientConfig *rest.Config, refresh bool) schema.GroupVersionResource {
// build the GVK mapper
buildGVKMapper(clientConfig, refresh)
// Query mapper
if val, ok := getValue(kind); ok {
return *val
}
utilruntime.HandleError(fmt.Errorf("Resouce '%s' not registered", kind))
return schema.GroupVersionResource{}
}
func buildGVKMapper(clientConfig *rest.Config, refresh bool) {
if groupVersionMapper == nil || refresh {
groupVersionMapper = make(map[string]schema.GroupVersionResource)
// refresh the mapper
if err := refreshRegisteredResources(groupVersionMapper, clientConfig); err != nil {
utilruntime.HandleError(err)
return
}
}
}
func getValue(kind string) (*schema.GroupVersionResource, bool) {
if groupVersionMapper == nil {
utilruntime.HandleError(fmt.Errorf("GroupVersionKind mapper is not loaded"))
return nil, false
}
if val, ok := groupVersionMapper[kind]; ok {
return &val, true
}
return nil, false
}
func refreshRegisteredResources(mapper map[string]schema.GroupVersionResource, clientConfig *rest.Config) error {
// build kubernetes client
client, err := newKubeClient(clientConfig)
if err != nil {
return err
}
// get registered server groups and resources
_, resourceList, err := client.Discovery().ServerGroupsAndResources()
if err != nil {
return err
}
for _, apiResource := range resourceList {
for _, resource := range apiResource.APIResources {
grpVersion := strings.Split(apiResource.GroupVersion, "/")
if len(grpVersion) == 2 {
mapper[resource.Name] = schema.GroupVersionResource{
Group: grpVersion[0],
Version: grpVersion[1],
Resource: resource.Name,
}
} else {
// resources with only versions
mapper[resource.Name] = schema.GroupVersionResource{
Version: apiResource.GroupVersion,
Resource: resource.Name,
}
}
}
}
return nil
}
func newKubeClient(clientConfig *rest.Config) (*kubernetes.Clientset, error) {
var err error
if kubeClient == nil {
kubeClient, err = kubernetes.NewForConfig(clientConfig)
if err != nil {
return nil, err
}
}
return kubeClient, nil
}

View file

@ -90,7 +90,7 @@ func (b *builder) processViolation(info Info) error {
modifiedPolicy.Status.Violations = modifiedViolations
// Violations are part of the status sub resource, so we can use the Update Status api instead of updating the policy object
_, err = b.client.UpdateStatusResource("policies", namespace, modifiedPolicy)
_, err = b.client.UpdateStatusResource("policies/status", namespace, modifiedPolicy)
if err != nil {
return err
}