mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
commit
682f64a1ee
7881 changed files with 2978753 additions and 449 deletions
.gitignoreREADME.md
client
cmd/kyverno
definitions
documentation
installation.mdtesting-policies-cli.mdtesting-policies-kubectl.mdtesting-policies.mdwriting-policies-generate.mdwriting-policies-mutate.mdwriting-policies-validate.mdwriting-policies.md
examples
CLI/deployment
Validate
check_cpu_memory.yamlcheck_hostpath.yamlcheck_image_version.yamlcheck_nodeport.yamlcheck_not_root.yamlcheck_probe_exists.yamlcheck_probe_intervals.yamlcheck_whitelist_registries.yaml
generate
mutate
pkg
apis/policy
client
clientset/versioned
informers/externalversions
listers/policy/v1alpha1
config
engine
mutation.go
mutation
overlay.gooverlay_test.gopatches.gopatches_test.goutils.govalidation.govalidation_test.gokyverno/apply
sharedinformer
violation
webhooks
scripts
test
ConfigMap
ConfigMapGenerator-SecretGenerator
CronJob
DaemonSet
Deployment
Endpoint
HorizontalPodAutoscaler
Ingress
Job
LimitRange
Namespace
NetworkPolicy
PersistentVolumeClaim
PodDisruptionBudget
PodTemplate
README.mdResourceQuota
Secret
Service
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,9 +1,6 @@
|
|||
vendor
|
||||
pkg/client
|
||||
pkg/apis/policy/v1alpha1/zz_generated.deepcopy.go
|
||||
certs
|
||||
kube-policy
|
||||
Gopkg.lock
|
||||
Dockerfile
|
||||
.vscode
|
||||
gh-pages/public
|
||||
/cmd/kyverno/kyverno
|
||||
|
|
67
README.md
67
README.md
|
@ -10,7 +10,7 @@ Kyverno allows cluster adminstrators to manage environment specific configuratio
|
|||
|
||||
Kyverno policies are Kubernetes resources that can be written in YAML or JSON. Kyverno policies can validate, mutate, and generate any Kubernetes resources.
|
||||
|
||||
Kyverno runs as a [dynamic admission controller](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/) in a Kubernetes cluster. Kyverno receives validating and mutating admission webhook HTTP callbacks from the kube-apiserver and applies matching polcies to return results that enforce admission policies or reject requests.
|
||||
Kyverno runs as a [dynamic admission controller](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/) in a Kubernetes cluster. Kyverno receives validating and mutating admission webhook HTTP callbacks from the kube-apiserver and applies matching policies to return results that enforce admission policies or reject requests.
|
||||
|
||||
Kyverno policies can match resources using the resource kind, name, and label selectors. Wildcards are supported in names.
|
||||
|
||||
|
@ -25,7 +25,7 @@ Policy enforcement is captured using Kubernetes events. Kyverno also reports pol
|
|||
This policy requires that all pods have CPU and memory resource requests and limits:
|
||||
|
||||
````yaml
|
||||
apiVersion: policy.nirmata.io/v1alpha1
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: check-cpu-memory
|
||||
|
@ -33,7 +33,8 @@ spec:
|
|||
rules:
|
||||
- name: check-pod-resources
|
||||
resource:
|
||||
kind: Pod
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "CPU and memory resource requests and limits are required"
|
||||
pattern:
|
||||
|
@ -43,12 +44,13 @@ spec:
|
|||
- name: "*"
|
||||
resources:
|
||||
limits:
|
||||
# '?' requires a value (at least 1 character)
|
||||
memory: "?"
|
||||
cpu: "?"
|
||||
# '?' requires 1 alphanumeric character and '*' means that there can be 0 or more characters.
|
||||
# Using them togther e.g. '?*' requires at least one character.
|
||||
memory: "?*"
|
||||
cpu: "?*"
|
||||
requests:
|
||||
memory: "?"
|
||||
cpu: "?"
|
||||
memory: "?*"
|
||||
cpu: "?*"
|
||||
````
|
||||
|
||||
### 2. Mutating resources
|
||||
|
@ -56,7 +58,7 @@ spec:
|
|||
This policy sets the imagePullPolicy to Always if the image tag is latest:
|
||||
|
||||
````yaml
|
||||
apiVersion: policy.nirmata.io/v1alpha1
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: set-image-pull-policy
|
||||
|
@ -64,15 +66,18 @@ spec:
|
|||
rules:
|
||||
- name: set-image-pull-policy
|
||||
resource:
|
||||
kind: Pod
|
||||
kinds:
|
||||
- Deployment
|
||||
mutate:
|
||||
overlay:
|
||||
spec:
|
||||
containers:
|
||||
# match images which end with :latest
|
||||
- image: "(*:latest)"
|
||||
# set the imagePullPolicy to "Always"
|
||||
imagePullPolicy: "Always"
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
# match images which end with :latest
|
||||
- (image): "*:latest"
|
||||
# set the imagePullPolicy to "Always"
|
||||
imagePullPolicy: "Always"
|
||||
````
|
||||
|
||||
### 3. Generating resources
|
||||
|
@ -80,7 +85,7 @@ spec:
|
|||
This policy sets the Zookeeper and Kafka connection strings for all namespaces with a label key 'kafka'.
|
||||
|
||||
````yaml
|
||||
apiVersion: policy.nirmata.io/v1alpha1
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: "zk-kafka-address"
|
||||
|
@ -88,7 +93,8 @@ spec:
|
|||
rules:
|
||||
- name: "zk-kafka-address"
|
||||
resource:
|
||||
kind : Namespace
|
||||
kinds:
|
||||
- Namespace
|
||||
selector:
|
||||
matchExpressions:
|
||||
- {key: kafka, operator: Exists}
|
||||
|
@ -104,6 +110,17 @@ spec:
|
|||
|
||||
Additional examples are available in [examples](/examples).
|
||||
|
||||
## Alternatives
|
||||
|
||||
### Open Policy Agent
|
||||
|
||||
[Open Policy Agent (OPA)](https://www.openpolicyagent.org/) is a general-purpose policy engine that can be used as a Kubernetes admission controller. It supports a large set of use cases. Policies are written using [Rego](https://www.openpolicyagent.org/docs/latest/how-do-i-write-policies#what-is-rego) a custom query language.
|
||||
|
||||
### External configuration management tools
|
||||
|
||||
Tools like [Kustomize](https://github.com/kubernetes-sigs/kustomize) can be used to manage variations in configurations outside of clusters. There are several advantages to this approach when used to produce variations of the same base configuration. However, such solutions cannot be used to validate or enforce configurations.
|
||||
|
||||
|
||||
## Status
|
||||
|
||||
*Kyverno is under active development and not ready for production use. Key components and policy definitions are likely to change as we complete core features.*
|
||||
|
@ -113,23 +130,23 @@ Additional examples are available in [examples](/examples).
|
|||
|
||||
* [Getting Started](documentation/installation.md)
|
||||
* [Writing Policies](documentation/writing-policies.md)
|
||||
* [Validate](documentation/writing-policies-validate.md)
|
||||
* [Mutate](documentation/writing-policies-mutate.md)
|
||||
* [Validate](documentation/writing-policies-validate.md)
|
||||
* [Generate](documentation/writing-policies-generate.md)
|
||||
* [Testing Policies](documentation/testing-policies.md)
|
||||
* [Using kubectl](documentation/testing-policies-kubectl.md)
|
||||
* [Using the Kyverno CLI](documentation/testing-policies-kyverno-cli.md)
|
||||
* [Using kubectl](documentation/testing-policies.md#Test-using-kubectl)
|
||||
* [Using the Kyverno CLI](documentation/testing-policies.md#Test-using-the-Kyverno-CLI)
|
||||
|
||||
|
||||
## Roadmap
|
||||
|
||||
Here are some the major features we plan on completing before a 1.0 release:
|
||||
|
||||
* Events
|
||||
* Policy Violations
|
||||
* Generate any resource
|
||||
* Conditionals on existing resources
|
||||
* Extend CLI to operate on cluster resources
|
||||
* [Events](https://github.com/nirmata/kyverno/issues/14)
|
||||
* [Policy Violations](https://github.com/nirmata/kyverno/issues/24)
|
||||
* [Generate any resource](https://github.com/nirmata/kyverno/issues/21)
|
||||
* [Conditionals on existing resources](https://github.com/nirmata/kyverno/issues/57)
|
||||
* [Extend CLI to operate on cluster resources ](https://github.com/nirmata/kyverno/issues/25)
|
||||
|
||||
## Getting help
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
152
client/client.go
152
client/client.go
|
@ -4,7 +4,6 @@ import (
|
|||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
types "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
|
||||
|
@ -17,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) {
|
||||
|
@ -39,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
|
||||
}
|
||||
|
||||
|
@ -62,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 != "" {
|
||||
|
@ -96,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 ")
|
||||
}
|
||||
|
@ -176,19 +178,19 @@ func (c *Client) GenerateSecret(generator types.Generation, namespace string) er
|
|||
c.logger.Printf("Preparing to create secret %s/%s", namespace, generator.Name)
|
||||
secret := v1.Secret{}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return err
|
||||
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(Secrets, generator.CopyFrom.Namespace, generator.CopyFrom.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// typed object
|
||||
secret, err = convertToSecret(unstrSecret)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// typed object
|
||||
secret, err = convertToSecret(unstrSecret)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// }
|
||||
|
||||
secret.ObjectMeta = meta.ObjectMeta{
|
||||
Name: generator.Name,
|
||||
|
@ -216,20 +218,20 @@ func (c *Client) GenerateConfigMap(generator types.Generation, namespace string)
|
|||
c.logger.Printf("Preparing to create configmap %s/%s", namespace, generator.Name)
|
||||
configMap := v1.ConfigMap{}
|
||||
|
||||
// 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)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// typed object
|
||||
configMap, err = convertToConfigMap(unstrConfigMap)
|
||||
if err != nil {
|
||||
return err
|
||||
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)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// typed object
|
||||
configMap, err = convertToConfigMap(unstrConfigMap)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// }
|
||||
configMap.ObjectMeta = meta.ObjectMeta{
|
||||
Name: generator.Name,
|
||||
Namespace: namespace,
|
||||
|
@ -276,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)
|
||||
|
@ -286,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)
|
||||
|
@ -299,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
|
||||
}
|
||||
|
@ -308,10 +310,24 @@ func (c *Client) waitUntilNamespaceIsCreated(name string) error {
|
|||
return lastError
|
||||
}
|
||||
|
||||
// KindIsSupported checks if the kind is a registerd GVK
|
||||
func (c *Client) KindIsSupported(kind string) bool {
|
||||
kind = strings.ToLower(kind) + "s"
|
||||
buildGVKMapper(c.clientConfig, false)
|
||||
_, ok := getValue(kind)
|
||||
return ok
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
apiVersion: admissionregistration.k8s.io/v1beta1
|
||||
kind: MutatingWebhookConfiguration
|
||||
metadata:
|
||||
name: nirmata-kube-policy-webhook-cfg
|
||||
name: nirmata-kyverno-webhook-cfg
|
||||
labels:
|
||||
app: kube-policy
|
||||
app: kyverno
|
||||
webhooks:
|
||||
- name: webhook.nirmata.kube-policy
|
||||
- name: webhook.nirmata.kyverno
|
||||
clientConfig:
|
||||
service:
|
||||
name: kube-policy-svc
|
||||
name: kyverno-svc
|
||||
namespace: default
|
||||
path: "/mutate"
|
||||
caBundle: ${CA_BUNDLE}
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
apiVersion: admissionregistration.k8s.io/v1beta1
|
||||
kind: MutatingWebhookConfiguration
|
||||
metadata:
|
||||
name: nirmata-kube-policy-webhook-cfg-debug
|
||||
name: nirmata-kyverno-webhook-cfg-debug
|
||||
labels:
|
||||
app: kube-policy
|
||||
app: kyverno
|
||||
webhooks:
|
||||
- name: webhook.nirmata.kube-policy
|
||||
- name: webhook.nirmata.kyverno
|
||||
clientConfig:
|
||||
url: "https://localhost/mutate"
|
||||
caBundle: ${CA_BUNDLE}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
apiVersion: apiextensions.k8s.io/v1beta1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
name: policies.kubepolicy.nirmata.io
|
||||
name: policies.kyverno.io
|
||||
spec:
|
||||
group: kubepolicy.nirmata.io
|
||||
group: kyverno.io
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
served: true
|
||||
|
@ -35,29 +35,12 @@ spec:
|
|||
resource:
|
||||
type: object
|
||||
required:
|
||||
- kind
|
||||
- kinds
|
||||
properties:
|
||||
kind:
|
||||
type: string
|
||||
enum:
|
||||
- ConfigMap
|
||||
- CronJob
|
||||
- DaemonSet
|
||||
- Deployment
|
||||
- Endpoints
|
||||
- HorizontalPodAutoscaler
|
||||
- Ingress
|
||||
- Job
|
||||
- LimitRange
|
||||
- Namespace
|
||||
- NetworkPolicy
|
||||
- PersistentVolumeClaim
|
||||
- PodDisruptionBudget
|
||||
- PodTemplate
|
||||
- ResourceQuota
|
||||
- Secret
|
||||
- Service
|
||||
- StatefulSet
|
||||
kinds:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
selector:
|
||||
|
@ -143,57 +126,62 @@ spec:
|
|||
additionalProperties:
|
||||
type: string
|
||||
---
|
||||
kind: Namespace
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: "kyverno"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
namespace: kube-system
|
||||
name: kube-policy-svc
|
||||
namespace: kyverno
|
||||
name: kyverno-svc
|
||||
labels:
|
||||
app: kube-policy
|
||||
app: kyverno
|
||||
spec:
|
||||
ports:
|
||||
- port: 443
|
||||
targetPort: 443
|
||||
selector:
|
||||
app: kube-policy
|
||||
app: kyverno
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: kube-policy-service-account
|
||||
namespace: kube-system
|
||||
name: kyverno-service-account
|
||||
namespace: kyverno
|
||||
---
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
metadata:
|
||||
name: kube-policy-admin
|
||||
name: kyverno-admin
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: cluster-admin
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: kube-policy-service-account
|
||||
namespace: kube-system
|
||||
name: kyverno-service-account
|
||||
namespace: kyverno
|
||||
---
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
namespace: kube-system
|
||||
name: kube-policy-deployment
|
||||
namespace: kyverno
|
||||
name: kyverno-deployment
|
||||
labels:
|
||||
app: kube-policy
|
||||
app: kyverno
|
||||
spec:
|
||||
replicas: 1
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: kube-policy
|
||||
app: kyverno
|
||||
spec:
|
||||
serviceAccountName: kube-policy-service-account
|
||||
serviceAccountName: kyverno-service-account
|
||||
containers:
|
||||
- name: kube-policy
|
||||
image: nirmata/kube-policy:latest
|
||||
- name: kyverno
|
||||
image: nirmata/kyverno:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
ports:
|
||||
- containerPort: 443
|
||||
|
|
|
@ -1,23 +1,41 @@
|
|||
<small>*[documentation](/README.md#documentation) / Installation*</small>
|
||||
|
||||
# Installation
|
||||
|
||||
The controller can be installed and operated in two ways: **Outside the cluster** and **Inside the cluster**. The controller **outside** the cluster is much more convenient to debug and verify changes in its code, so we can call it 'debug mode'. The controller **inside** the cluster is designed for use in the real world, and the **QA testing** should be performed when controller operate in this mode.
|
||||
To install Kyverno in your cluster run the following command on a host with kubectl access:
|
||||
|
||||
````sh
|
||||
kubectl create -f https://github.com/nirmata/kyverno/raw/master/definitions/install.yaml
|
||||
````
|
||||
|
||||
To check the Kyverno controller status, run the command:
|
||||
|
||||
````sh
|
||||
kubectl get pods -n kyverno
|
||||
````
|
||||
|
||||
If the Kyverno controller is not running, you can check its status and logs for errors:
|
||||
|
||||
````sh
|
||||
kubectl describe pod <kyverno-pod-name> -n kyverno
|
||||
````
|
||||
|
||||
````sh
|
||||
kubectl logs <kyverno-pod-name> -n kyverno
|
||||
````
|
||||
|
||||
# Installing in a Development Environment
|
||||
|
||||
To build and run Kyverno in a development environment see: https://github.com/nirmata/kyverno/wiki/Building
|
||||
|
||||
To check if the controller is working, find it in the list of kyverno pods:
|
||||
|
||||
`kubectl get pods -n kyverno`
|
||||
|
||||
# Try Kyverno without a Kubernetes cluster
|
||||
|
||||
The [Kyverno CLI](documentation/testing-policies-cli.md) allows you to write and test policies without installing Kyverno in a Kubernetes cluster.
|
||||
|
||||
|
||||
## Inside the cluster (normal use)
|
||||
|
||||
Just execute the command for creating all necesarry resources:
|
||||
`kubectl create -f definitions/install.yaml`
|
||||
|
||||
In this mode controller will get TLS key/certificate pair and loads in-cluster config automatically on start.
|
||||
To check if the controller is working, find it in the list of kube-system pods:
|
||||
|
||||
`kubectl get pods -n kube-system`
|
||||
|
||||
The pod with controller contains **'kube-policy'** in its name. The STATUS column will show the health state of the controller. If controller doesn't start, see its logs:
|
||||
|
||||
`kubectl describe pod <kube-policy-pod-name> -n kube-system`
|
||||
|
||||
or
|
||||
|
||||
`kubectl logs <kube-policy-pod-name> -n kube-system`
|
||||
|
||||
---
|
||||
<small>*Read Next >> [Writing Policies](/documentation/writing-policies.md)*</small>
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
# Kyverno CLI
|
|
@ -1,2 +0,0 @@
|
|||
# Testing using kubectl
|
||||
|
|
@ -1 +1,62 @@
|
|||
<small>*[documentation](/README.md#documentation) / Testing Policies*</small>
|
||||
|
||||
|
||||
# Testing Policies
|
||||
The resources definitions for testing are located in [/test](/test) directory. Each test contains a pair of files: one is the resource definition, and the second is the kyverno policy for this definition.
|
||||
|
||||
## Test using kubectl
|
||||
To do this you should [install kyverno to the cluster](/documentation/installation.md).
|
||||
|
||||
For example, to test the simplest kyverno policy for ConfigMap, create the policy and then the resource itself via kubectl:
|
||||
|
||||
````bash
|
||||
cd test/ConfigMap
|
||||
kubectl create -f policy-CM.yaml
|
||||
kubectl create -f CM.yaml
|
||||
````
|
||||
Then compare the original resource definition in CM.yaml with the actual one:
|
||||
|
||||
````bash
|
||||
kubectl get -f CM.yaml -o yaml
|
||||
````
|
||||
|
||||
## Test using the Kyverno CLI
|
||||
|
||||
The Kyverno Command Line Interface (CLI) tool enables writing and testing policies without requiring Kubernetes clusters and without having to apply local policy changes to a cluster.
|
||||
|
||||
### Building the CLI
|
||||
|
||||
You will need a [Go environment](https://golang.org/doc/install) setup.
|
||||
|
||||
1. Clone the Kyverno repo
|
||||
|
||||
````bash
|
||||
git clone https://github.com/nirmata/kyverno/
|
||||
````
|
||||
|
||||
2. Build the CLI
|
||||
|
||||
````bash
|
||||
cd kyverno/cmd/kyverno
|
||||
go build
|
||||
````
|
||||
|
||||
Or, you can directly build and install the CLI using `go get`:
|
||||
|
||||
````bash
|
||||
go get -u https://github.com/nirmata/kyverno/cmd/kyverno
|
||||
````
|
||||
|
||||
### Using the CLI
|
||||
|
||||
To test a policy using the CLI type:
|
||||
|
||||
`kyverno <policy> <resource YAML file or folder>`
|
||||
|
||||
For example:
|
||||
|
||||
```bash
|
||||
kyverno ../../examples/CLI/policy-deployment.yaml ../../examples/CLI/resources
|
||||
```
|
||||
|
||||
In future releases, the CLI will support complete validation of policies and will allow testing policies against resources in Kubernetes clusters.
|
||||
|
|
|
@ -1 +1,49 @@
|
|||
# Policies that Generate Configurations
|
||||
<small>*[documentation](/README.md#documentation) / [Writing Policies](/documentation/writing-policies.md) / Generate*</small>
|
||||
|
||||
# Generate Configurations
|
||||
|
||||
```generatate``` feature can be applied to created namespaces to create new resources in them. This feature is useful when every namespace in a cluster must contain some basic required resources. The feature is available for policy rules in which the resource kind is Namespace.
|
||||
|
||||
## Example
|
||||
|
||||
````yaml
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : basic-policy
|
||||
spec :
|
||||
rules:
|
||||
- name: "Basic confog generator for all namespaces"
|
||||
resource:
|
||||
kind: Namespace
|
||||
generate:
|
||||
# For now the next kinds are supported:
|
||||
# ConfigMap
|
||||
# Secret
|
||||
- kind: ConfigMap
|
||||
name: default-config
|
||||
copyFrom:
|
||||
namespace: default
|
||||
name: config-template
|
||||
data:
|
||||
DB_ENDPOINT: mongodb://mydomain.ua/db_stage:27017
|
||||
labels:
|
||||
purpose: mongo
|
||||
- kind: Secret
|
||||
name: mongo-creds
|
||||
data:
|
||||
DB_USER: YWJyYWthZGFicmE=
|
||||
DB_PASSWORD: YXBwc3dvcmQ=
|
||||
labels:
|
||||
purpose: mongo
|
||||
````
|
||||
|
||||
In this example, when this policy is applied, any new namespace will receive 2 new resources after its creation:
|
||||
* ConfigMap copied from default/config-template with added value DB_ENDPOINT.
|
||||
* Secret with values DB_USER and DB_PASSWORD.
|
||||
|
||||
Both resources will contain a label ```purpose: mongo```
|
||||
|
||||
---
|
||||
<small>*Read Next >> [Testing Policies](/documentation/testing-policies.md)*</small>
|
||||
|
||||
|
|
|
@ -1 +1,139 @@
|
|||
# Policies that Mutate Configurations
|
||||
<small>*[documentation](/README.md#documentation) / [Writing Policies](/documentation/writing-policies.md) / Mutate*</small>
|
||||
|
||||
# Mutate Configurations
|
||||
|
||||
The ```mutate``` rule contains actions that should be applied to the resource before its creation. Mutation can be made using patches or overlay. Using ```patches``` in the JSONPatch format, you can make point changes to the created resource, and ```overlays``` are designed to bring the resource to the desired view according to a specific pattern.
|
||||
|
||||
Resource mutation occurs before validation, so the validation rules should not contradict the changes set in the mutation section.
|
||||
|
||||
## Patches
|
||||
|
||||
The patches are used to make direct changes in the created resource. In the next example the patch will be applied to all Deployments that contain a word "nirmata" in the name.
|
||||
|
||||
````yaml
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : policy-v1
|
||||
spec :
|
||||
rules:
|
||||
- name: "Deployment of *nirmata* images"
|
||||
resource:
|
||||
kind: Deployment
|
||||
# Name is optional. By default validation policy is applicable to any resource of supported kind.
|
||||
# Name supports wildcards * and ?
|
||||
name: "*nirmata*"
|
||||
mutate:
|
||||
patches:
|
||||
# This patch adds sidecar container to every deployment that matches this policy
|
||||
- path: "/spec/template/spec/containers/0/"
|
||||
op: add
|
||||
value:
|
||||
- image: "nirmata.io/sidecar:latest"
|
||||
imagePullPolicy: "Always"
|
||||
ports:
|
||||
- containerPort: 443
|
||||
````
|
||||
There is one patch in the rule, it will add the new image to the "containers" list with specified parameters. Patch is described in [JSONPatch](http://jsonpatch.com/) format and support the operations ('op' field):
|
||||
* **add**
|
||||
* **replace**
|
||||
* **remove**
|
||||
|
||||
Here is the example with of a patch which removes a label from the secret:
|
||||
````yaml
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : policy-remove-label
|
||||
spec :
|
||||
rules:
|
||||
- name: "Remove unwanted label"
|
||||
resource:
|
||||
# Will be applied to all secrets, because name and selector are not specified
|
||||
kind: Secret
|
||||
mutate:
|
||||
patches:
|
||||
- path: "/metadata/labels/purpose"
|
||||
op: remove
|
||||
````
|
||||
|
||||
Note, that if **remove** operation cannot be applied, then this **remove** operation will be skipped with no error.
|
||||
|
||||
## Overlay
|
||||
|
||||
The Mutation Overlay is the desired form of resource. The existing resource parameters are replaced with the parameters described in the overlay. If there are no such parameters in the target resource, they are copied to the resource from the overlay. The overlay is not used to delete the properties of a resource: use **patches** for this purpose.
|
||||
|
||||
The next overlay will add or change the hard limit for memory to 2 gigabytes in every ResourceQuota with label ```quota: low```:
|
||||
|
||||
````yaml
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : policy-change-memory-limit
|
||||
spec :
|
||||
rules:
|
||||
- name: "Set hard memory limit to 2Gi"
|
||||
resource:
|
||||
# Will be applied to all secrets, because name and selector are not specified
|
||||
kind: ResourceQuota
|
||||
selector:
|
||||
matchLabels:
|
||||
quota: low
|
||||
mutate:
|
||||
overlay:
|
||||
spec:
|
||||
hard:
|
||||
limits.memory: 2Gi
|
||||
````
|
||||
The ```overlay``` keyword under ```mutate``` feature describes the desired form of ResourceQuota.
|
||||
|
||||
### Working with lists
|
||||
|
||||
The application of an overlay to the list without additional settings is pretty straightforward: the new items will be added to the list exсept of those that totally equal to existent items. For example, the next overlay will add IP "192.168.10.172" to all addresses in all Endpoints:
|
||||
|
||||
````yaml
|
||||
apiVersion: policy.nirmata.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: policy-endpoints-
|
||||
spec:
|
||||
rules:
|
||||
- resource:
|
||||
# Applied to all endpoints
|
||||
kind : Endpoints
|
||||
mutate:
|
||||
overlay:
|
||||
subsets:
|
||||
- addresses:
|
||||
- ip: 192.168.10.172
|
||||
````
|
||||
|
||||
You can use overlays to merge objects inside lists using **anchor** items marked by parentheses. For example, this overlay will add/replace port to 6443 in all ports with name that start from the word "secure":
|
||||
````yaml
|
||||
apiVersion : policy.nirmata.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : policy-endpoints-should-be-more-secure
|
||||
spec :
|
||||
rules:
|
||||
- resource:
|
||||
# Applied to all endpoints
|
||||
kind : Endpoints
|
||||
mutate:
|
||||
overlay:
|
||||
subsets:
|
||||
- ports:
|
||||
- (name): "secure*"
|
||||
port: 6443
|
||||
````
|
||||
|
||||
The **anchors** marked in parentheses support **wildcards**:
|
||||
1. `*` - matches zero or more alphanumeric characters
|
||||
2. `?` - matches a single alphanumeric character
|
||||
|
||||
## Details
|
||||
|
||||
The behavior of overlays described more detailed in the project's wiki: [Mutation Overlay](https://github.com/nirmata/kyverno/wiki/Mutation-Overlay)
|
||||
|
||||
---
|
||||
<small>*Read Next >> [Validate](/documentation/writing-policies-validate.md)*</small>
|
||||
|
|
|
@ -1 +1,71 @@
|
|||
# Policies that Validate Configurations
|
||||
<small>*[documentation](/README.md#documentation) / [Writing Policies](/documentation/writing-policies.md) / Validate*</small>
|
||||
|
||||
|
||||
# Validate Configurations
|
||||
|
||||
A validation rule is expressed as an overlay pattern that expresses the desired configuration. Resource configurations must match fields and expressions defined in the pattern to pass the validation rule. The following rules are followed when processing the overlay pattern:
|
||||
|
||||
1. Validation will fail if a field is defined in the pattern and if the field does not exist in the configuration.
|
||||
2. Undefined fields are treated as wildcards.
|
||||
3. A validation pattern field with the wildcard value '*' will match zero or more alphanumeric characters. Empty values or missing fields are matched.
|
||||
4. A validation pattern field with the wildcard value '?' will match any single alphanumeric character. Empty or missing fields are not matched.
|
||||
5. A validation pattern field with the wildcard value '?*' will match any alphanumeric characters and requires the field to be present with non-empty values.
|
||||
6. A validation pattern field with the value `null` or "" (empty string) requires that the field not be defined or has no value.
|
||||
7. The validation of siblings is performed only when one of the field values matches the value defined in the pattern. You can use the parenthesis operator to explictly specify a field value that must be matched. This allows writing rules like 'if fieldA equals X, then fieldB must equal Y'.
|
||||
8. Validation of child values is only performed if the parent matches the pattern.
|
||||
|
||||
## Patterns
|
||||
|
||||
### Wildcards
|
||||
1. `*` - matches zero or more alphanumeric characters
|
||||
2. `?` - matches a single alphanumeric character
|
||||
|
||||
### Operators
|
||||
|
||||
| Operator | Meaning |
|
||||
|------------|---------------------------|
|
||||
| `>` | greater than |
|
||||
| `<` | less than |
|
||||
| `>=` | greater than or equals to |
|
||||
| `<=` | less than or equals to |
|
||||
| `!` | not equals |
|
||||
| \| | logical or |
|
||||
|
||||
There is no operator for `equals` as providing a field value in the pattern requires equality to the value.
|
||||
|
||||
## Example
|
||||
The next rule prevents the creation of Deployment, StatefuleSet and DaemonSet resources without label 'app' in selector:
|
||||
````yaml
|
||||
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : validation-example
|
||||
spec :
|
||||
rules:
|
||||
- resource:
|
||||
# Kind specifies one or more resource types to match
|
||||
kinds:
|
||||
- Deployment
|
||||
- StatefuleSet
|
||||
- DaemonSet
|
||||
# Name is optional and can use wildcards
|
||||
name: *
|
||||
# Selector is optional
|
||||
selector:
|
||||
validate:
|
||||
# Message is optional
|
||||
message: "The label app is required"
|
||||
pattern:
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: "?*"
|
||||
|
||||
````
|
||||
|
||||
Additional examples are available in [examples](/examples/)
|
||||
|
||||
|
||||
---
|
||||
<small>*Read Next >> [Generate](/documentation/writing-policies-generate.md)*</small>
|
||||
|
|
|
@ -1 +1,43 @@
|
|||
<small>*[documentation](/README.md#documentation) / Writing Policies*</small>
|
||||
|
||||
# Writing Policies
|
||||
|
||||
A Kyverno policy contains a set of rules. Each rule matches resources by kind, name, or selectors.
|
||||
|
||||
````yaml
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : policy
|
||||
spec :
|
||||
|
||||
# Each policy has a list of rules applied in declaration order
|
||||
rules:
|
||||
|
||||
# Rules must have a name
|
||||
- name: "check-pod-controller-labels"
|
||||
|
||||
# Each rule matches specific resource described by "resource" field.
|
||||
resource:
|
||||
kind: Deployment, StatefulSet, DaemonSet
|
||||
# Name is optional. By default validation policy is applicable to any resource of supported kinds.
|
||||
# Name supports wildcards * and ?
|
||||
name: "*"
|
||||
# Selector is optional and can be used to match specific resources
|
||||
# Selector values support wildcards * and ?
|
||||
selector:
|
||||
# A selector can use match
|
||||
matchLabels:
|
||||
app: mongodb
|
||||
matchExpressions:
|
||||
- {key: tier, operator: In, values: [database]}
|
||||
|
||||
|
||||
# Each rule can contain a single validate, mutate, or generate directive
|
||||
...
|
||||
````
|
||||
|
||||
Each rule can validate, mutate, or generate configurations of matching resources. A rule definition can contain only a single **mutate**, **validate**, or **generate** child node. These actions are applied to the resource in described order: mutation, validation and then generation.
|
||||
|
||||
---
|
||||
<small>*Read Next >> [Validate](/documentation/writing-policies-validate.md)*</small>
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion : kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : policy-deployment
|
||||
|
@ -6,7 +6,8 @@ spec :
|
|||
rules:
|
||||
- name: deployment-policy
|
||||
resource:
|
||||
kind : Deployment
|
||||
kinds :
|
||||
- Deployment
|
||||
selector :
|
||||
matchLabels :
|
||||
cli: test
|
||||
|
@ -19,12 +20,12 @@ spec :
|
|||
op: replace
|
||||
value: "nginx_is_mutated"
|
||||
validate:
|
||||
message: "The imagePullPolicy shoud set to Always"
|
||||
message: "The imagePullPolicy must be Always when :latest is used as a tag"
|
||||
pattern:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- (name): "*"
|
||||
- (name): "*:latest"
|
||||
imagePullPolicy: Always
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: policy.nirmata.io/v1alpha1
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: check-cpu-memory
|
||||
|
@ -6,7 +6,8 @@ spec:
|
|||
rules:
|
||||
- name: check-defined
|
||||
resource:
|
||||
kind: Deployment
|
||||
kinds:
|
||||
- Deployment
|
||||
validate:
|
||||
message: "Resource requests and limits are required for CPU and memory"
|
||||
pattern:
|
||||
|
@ -22,7 +23,8 @@ spec:
|
|||
cpu: "?"
|
||||
- name: check-memory-in-range
|
||||
resource:
|
||||
kind: Deployment
|
||||
kinds:
|
||||
- Deployment
|
||||
validate:
|
||||
message: "Memory request cannot be greater than 10Gi"
|
||||
pattern:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: policy.nirmata.io/v1alpha1
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: check-host-path
|
||||
|
@ -6,7 +6,8 @@ spec:
|
|||
rules:
|
||||
- name: check-host-path
|
||||
resource:
|
||||
kind: Pod
|
||||
kinds:
|
||||
- Pod
|
||||
validate:
|
||||
message: "Host path volumes are not allowed"
|
||||
pattern:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: policy.nirmata.io/v1alpha1
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: image-pull-policy
|
||||
|
@ -7,7 +7,8 @@ spec:
|
|||
- name: image-pull-policy
|
||||
message: "Image tag ':latest' requires imagePullPolicy 'Always'"
|
||||
resource:
|
||||
kind: Deployment
|
||||
kinds:
|
||||
- Deployment
|
||||
overlay:
|
||||
template:
|
||||
spec:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: policy.nirmata.io/v1alpha1
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: check-host-path
|
||||
|
@ -6,7 +6,8 @@ spec:
|
|||
rules:
|
||||
- name: check-host-path
|
||||
resource:
|
||||
kind: Service
|
||||
kinds:
|
||||
- Service
|
||||
validate:
|
||||
message: "Node port services are not allowed"
|
||||
pattern:
|
||||
|
|
17
examples/Validate/check_not_root.yaml
Normal file
17
examples/Validate/check_not_root.yaml
Normal file
|
@ -0,0 +1,17 @@
|
|||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : check-non-root
|
||||
spec :
|
||||
rules:
|
||||
- name: check-non-root
|
||||
resource:
|
||||
kind: Deployment, StatefuleSet, DaemonSet
|
||||
validate:
|
||||
message: "Root user is not allowed"
|
||||
pattern:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
securityContext:
|
||||
runAsNotRoot: true
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: policy.nirmata.io/v1alpha1
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: check-probe-exists
|
||||
|
@ -6,7 +6,8 @@ spec:
|
|||
rules:
|
||||
- name: check-liveness-probe-exists
|
||||
resource:
|
||||
kind: StatefulSet
|
||||
kinds:
|
||||
- StatefulSet
|
||||
validate:
|
||||
message: "a livenessProbe is required"
|
||||
pattern:
|
||||
|
@ -14,10 +15,11 @@ spec:
|
|||
# In this case every object in containers list will be checked for pattern
|
||||
- name: "*"
|
||||
livenessProbe:
|
||||
periodSeconds: ?
|
||||
periodSeconds: "?"
|
||||
- resource:
|
||||
kind: Deployment
|
||||
name: check-readiness-probe-exists
|
||||
kinds:
|
||||
- Deployment
|
||||
name: check-readinessprobe-exists
|
||||
validate:
|
||||
message: "a readinessProbe is required"
|
||||
pattern:
|
||||
|
@ -25,4 +27,4 @@ spec:
|
|||
# In this case every object in containers list will be checked for pattern
|
||||
- name: "*"
|
||||
readinessProbe:
|
||||
periodSeconds: ?
|
||||
periodSeconds: "?"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: policy.nirmata.io/v1alpha1
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: check-probe-intervals
|
||||
|
@ -6,7 +6,8 @@ spec:
|
|||
rules:
|
||||
- name: check-probe-intervals
|
||||
resource:
|
||||
kind: Deployment
|
||||
kinds:
|
||||
- Deployment
|
||||
validate:
|
||||
message: "livenessProbe must be > 10s"
|
||||
pattern:
|
||||
|
@ -16,7 +17,9 @@ spec:
|
|||
livenessProbe:
|
||||
periodSeconds: ">10"
|
||||
- resource:
|
||||
kind: Deployment
|
||||
kinds:
|
||||
- Deployment
|
||||
name: check-readinessprobe-intervals
|
||||
validate:
|
||||
pattern:
|
||||
message: "readinessProbe must be > 10s"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: policy.nirmata.io/v1alpha1
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: check-whitelist-registries
|
||||
|
@ -7,7 +7,8 @@ spec:
|
|||
- name: check-whitelist-registries
|
||||
message: "Registry is not allowed"
|
||||
resource:
|
||||
kind: Deployment
|
||||
kinds:
|
||||
- Deployment
|
||||
validate:
|
||||
pattern:
|
||||
template:
|
||||
|
|
20
examples/generate/configMap.yaml
Normal file
20
examples/generate/configMap.yaml
Normal file
|
@ -0,0 +1,20 @@
|
|||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: game-config
|
||||
namespace: default
|
||||
labels:
|
||||
originalLabel : isHere
|
||||
data:
|
||||
ui.properties : |
|
||||
color.good=green
|
||||
color.bad=red
|
||||
|
||||
game.properties : |
|
||||
enemies=predators
|
||||
lives=3
|
||||
|
||||
configmap.data: |
|
||||
ns=default
|
||||
labels=originalLabel
|
||||
labelscount=1
|
7
examples/generate/namespace.yaml
Normal file
7
examples/generate/namespace.yaml
Normal file
|
@ -0,0 +1,7 @@
|
|||
kind: Namespace
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: "ns2"
|
||||
labels:
|
||||
LabelForSelector : "namespace2"
|
||||
|
34
examples/generate/policy_generate.yaml
Normal file
34
examples/generate/policy_generate.yaml
Normal file
|
@ -0,0 +1,34 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: "zk-kafka-address"
|
||||
spec:
|
||||
rules:
|
||||
- name: "copy-comfigmap"
|
||||
resource :
|
||||
kinds :
|
||||
- Namespace
|
||||
selector:
|
||||
matchLabels:
|
||||
LabelForSelector : "namespace2"
|
||||
generate :
|
||||
kind: ConfigMap
|
||||
name : copied-cm
|
||||
copyFrom :
|
||||
namespace : default
|
||||
name : game-config
|
||||
data :
|
||||
secretData: "data from cmg"
|
||||
- name: "zk-kafka-address"
|
||||
resource:
|
||||
kinds:
|
||||
- Namespace
|
||||
selector:
|
||||
matchExpressions:
|
||||
- {key: LabelForSelector, operator: In, values: [namespace2]}
|
||||
generate:
|
||||
kind: ConfigMap
|
||||
name: zk-kafka-address
|
||||
data:
|
||||
ZK_ADDRESS: "192.168.10.10:2181,192.168.10.11:2181,192.168.10.12:2181"
|
||||
KAFKA_ADDRESS: "192.168.10.13:9092,192.168.10.14:9092,192.168.10.15:9092"
|
20
examples/mutate/overlay/policy_set_imagePullPolicy.yaml
Normal file
20
examples/mutate/overlay/policy_set_imagePullPolicy.yaml
Normal file
|
@ -0,0 +1,20 @@
|
|||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: set-image-pull-policy
|
||||
spec:
|
||||
rules:
|
||||
- name: set-image-pull-policy
|
||||
resource:
|
||||
kinds:
|
||||
- Deployment
|
||||
mutate:
|
||||
overlay:
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
# match images which end with :latest
|
||||
- (image): "*:latest"
|
||||
# set the imagePullPolicy to "Always"
|
||||
imagePullPolicy: "Always"
|
23
examples/mutate/overlay/set_imagePullPolicy_nginx.yaml
Normal file
23
examples/mutate/overlay/set_imagePullPolicy_nginx.yaml
Normal file
|
@ -0,0 +1,23 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: nginx-deployment
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:latest
|
||||
ports:
|
||||
- containerPort: 80
|
||||
- name: ghost
|
||||
image: ghost:latest
|
13
examples/mutate/patches/endpoints.yaml
Normal file
13
examples/mutate/patches/endpoints.yaml
Normal file
|
@ -0,0 +1,13 @@
|
|||
apiVersion: v1
|
||||
kind: Endpoints
|
||||
metadata:
|
||||
name: test-endpoint
|
||||
labels:
|
||||
label : test
|
||||
subsets:
|
||||
- addresses:
|
||||
- ip: 192.168.10.171
|
||||
ports:
|
||||
- name: secure-connection
|
||||
port: 443
|
||||
protocol: TCP
|
27
examples/mutate/patches/policy_endpoints.yaml
Normal file
27
examples/mutate/patches/policy_endpoints.yaml
Normal file
|
@ -0,0 +1,27 @@
|
|||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : policy-endpoints
|
||||
spec :
|
||||
rules:
|
||||
- name: pEP
|
||||
resource:
|
||||
kinds :
|
||||
- Endpoints
|
||||
selector:
|
||||
matchLabels:
|
||||
label : test
|
||||
mutate:
|
||||
patches:
|
||||
- path : "/subsets/0/ports/0/port"
|
||||
op : replace
|
||||
value: 9663
|
||||
- path : "/subsets/0"
|
||||
op: add
|
||||
value:
|
||||
addresses:
|
||||
- ip: "192.168.10.172"
|
||||
ports:
|
||||
- name: load-balancer-connection
|
||||
port: 80
|
||||
protocol: UDP
|
|
@ -2,5 +2,5 @@ package policy
|
|||
|
||||
const (
|
||||
// GroupName must be the same as specified in Policy CRD
|
||||
GroupName = "kubepolicy.nirmata.io"
|
||||
GroupName = "kyverno.io"
|
||||
)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
// +k8s:deepcopy-gen=package
|
||||
// +groupName=kubepolicy.nirmata.io
|
||||
// +groupName=kyverno.io
|
||||
|
||||
package v1alpha1
|
||||
|
|
|
@ -33,7 +33,7 @@ type Rule struct {
|
|||
|
||||
// ResourceDescription describes the resource to which the PolicyRule will be applied.
|
||||
type ResourceDescription struct {
|
||||
Kind string `json:"kind"`
|
||||
Kinds []string `json:"kinds"`
|
||||
Name *string `json:"name"`
|
||||
Selector *metav1.LabelSelector `json:"selector"`
|
||||
}
|
||||
|
|
|
@ -22,13 +22,11 @@ func (r *Rule) Validate() error {
|
|||
}
|
||||
|
||||
// Validate checks if all necesarry fields are present and have values. Also checks a Selector.
|
||||
// Returns error if resource definition is invalid.
|
||||
// Returns error if
|
||||
// - kinds is not defined
|
||||
func (pr *ResourceDescription) Validate() error {
|
||||
// TBD: selector or name MUST be specified
|
||||
if pr.Kind == "" {
|
||||
if len(pr.Kinds) == 0 {
|
||||
return errors.New("The Kind is not specified")
|
||||
} else if pr.Name == nil && pr.Selector == nil {
|
||||
return errors.New("Neither Name nor Selector is specified")
|
||||
}
|
||||
|
||||
if pr.Selector != nil {
|
||||
|
|
|
@ -9,8 +9,8 @@ import (
|
|||
|
||||
var defaultResourceDescriptionName = "defaultResourceDescription"
|
||||
var defaultResourceDescription = ResourceDescription{
|
||||
Kind: "Deployment",
|
||||
Name: &defaultResourceDescriptionName,
|
||||
Kinds: []string{"Deployment"},
|
||||
Name: &defaultResourceDescriptionName,
|
||||
Selector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{"LabelForSelector": "defaultResourceDescription"},
|
||||
},
|
||||
|
@ -43,7 +43,7 @@ func Test_ResourceDescription_EmptyKind(t *testing.T) {
|
|||
|
||||
func Test_ResourceDescription_EmptyNameAndSelector(t *testing.T) {
|
||||
resourceDescription := ResourceDescription{
|
||||
Kind: "Deployment",
|
||||
Kinds: []string{"Deployment"},
|
||||
}
|
||||
err := resourceDescription.Validate()
|
||||
assert.Assert(t, err != nil)
|
||||
|
|
274
pkg/apis/policy/v1alpha1/zz_generated.deepcopy.go
Normal file
274
pkg/apis/policy/v1alpha1/zz_generated.deepcopy.go
Normal file
|
@ -0,0 +1,274 @@
|
|||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *CopyFrom) DeepCopyInto(out *CopyFrom) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CopyFrom.
|
||||
func (in *CopyFrom) DeepCopy() *CopyFrom {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(CopyFrom)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Generation) DeepCopyInto(out *Generation) {
|
||||
*out = *in
|
||||
if in.CopyFrom != nil {
|
||||
in, out := &in.CopyFrom, &out.CopyFrom
|
||||
*out = new(CopyFrom)
|
||||
**out = **in
|
||||
}
|
||||
if in.Data != nil {
|
||||
in, out := &in.Data, &out.Data
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.Labels != nil {
|
||||
in, out := &in.Labels, &out.Labels
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Generation.
|
||||
func (in *Generation) DeepCopy() *Generation {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Generation)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Mutation.
|
||||
func (in *Mutation) DeepCopy() *Mutation {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Mutation)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Policy) DeepCopyInto(out *Policy) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
in.Status.DeepCopyInto(&out.Status)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Policy.
|
||||
func (in *Policy) DeepCopy() *Policy {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Policy)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *Policy) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *PolicyList) DeepCopyInto(out *PolicyList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
out.ListMeta = in.ListMeta
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]Policy, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PolicyList.
|
||||
func (in *PolicyList) DeepCopy() *PolicyList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(PolicyList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *PolicyList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ResourceDescription) DeepCopyInto(out *ResourceDescription) {
|
||||
*out = *in
|
||||
if in.Name != nil {
|
||||
in, out := &in.Name, &out.Name
|
||||
*out = new(string)
|
||||
**out = **in
|
||||
}
|
||||
if in.Selector != nil {
|
||||
in, out := &in.Selector, &out.Selector
|
||||
*out = new(v1.LabelSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceDescription.
|
||||
func (in *ResourceDescription) DeepCopy() *ResourceDescription {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ResourceDescription)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Rule) DeepCopyInto(out *Rule) {
|
||||
*out = *in
|
||||
in.ResourceDescription.DeepCopyInto(&out.ResourceDescription)
|
||||
if in.Mutation != nil {
|
||||
in, out := &in.Mutation, &out.Mutation
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.Validation != nil {
|
||||
in, out := &in.Validation, &out.Validation
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.Generation != nil {
|
||||
in, out := &in.Generation, &out.Generation
|
||||
*out = new(Generation)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Rule.
|
||||
func (in *Rule) DeepCopy() *Rule {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Rule)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Spec) DeepCopyInto(out *Spec) {
|
||||
*out = *in
|
||||
if in.Rules != nil {
|
||||
in, out := &in.Rules, &out.Rules
|
||||
*out = make([]Rule, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Spec.
|
||||
func (in *Spec) DeepCopy() *Spec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Spec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Status) DeepCopyInto(out *Status) {
|
||||
*out = *in
|
||||
if in.Violations != nil {
|
||||
in, out := &in.Violations, &out.Violations
|
||||
*out = make([]Violation, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Status.
|
||||
func (in *Status) DeepCopy() *Status {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Status)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Validation.
|
||||
func (in *Validation) DeepCopy() *Validation {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Validation)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Violation) DeepCopyInto(out *Violation) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Violation.
|
||||
func (in *Violation) DeepCopy() *Violation {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Violation)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
90
pkg/client/clientset/versioned/clientset.go
Normal file
90
pkg/client/clientset/versioned/clientset.go
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package versioned
|
||||
|
||||
import (
|
||||
kyvernov1alpha1 "github.com/nirmata/kyverno/pkg/client/clientset/versioned/typed/policy/v1alpha1"
|
||||
discovery "k8s.io/client-go/discovery"
|
||||
rest "k8s.io/client-go/rest"
|
||||
flowcontrol "k8s.io/client-go/util/flowcontrol"
|
||||
)
|
||||
|
||||
type Interface interface {
|
||||
Discovery() discovery.DiscoveryInterface
|
||||
KyvernoV1alpha1() kyvernov1alpha1.KyvernoV1alpha1Interface
|
||||
}
|
||||
|
||||
// Clientset contains the clients for groups. Each group has exactly one
|
||||
// version included in a Clientset.
|
||||
type Clientset struct {
|
||||
*discovery.DiscoveryClient
|
||||
kyvernoV1alpha1 *kyvernov1alpha1.KyvernoV1alpha1Client
|
||||
}
|
||||
|
||||
// KyvernoV1alpha1 retrieves the KyvernoV1alpha1Client
|
||||
func (c *Clientset) KyvernoV1alpha1() kyvernov1alpha1.KyvernoV1alpha1Interface {
|
||||
return c.kyvernoV1alpha1
|
||||
}
|
||||
|
||||
// Discovery retrieves the DiscoveryClient
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.DiscoveryClient
|
||||
}
|
||||
|
||||
// NewForConfig creates a new Clientset for the given config.
|
||||
func NewForConfig(c *rest.Config) (*Clientset, error) {
|
||||
configShallowCopy := *c
|
||||
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
|
||||
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
|
||||
}
|
||||
var cs Clientset
|
||||
var err error
|
||||
cs.kyvernoV1alpha1, err = kyvernov1alpha1.NewForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cs, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new Clientset for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *Clientset {
|
||||
var cs Clientset
|
||||
cs.kyvernoV1alpha1 = kyvernov1alpha1.NewForConfigOrDie(c)
|
||||
|
||||
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
|
||||
return &cs
|
||||
}
|
||||
|
||||
// New creates a new Clientset for the given RESTClient.
|
||||
func New(c rest.Interface) *Clientset {
|
||||
var cs Clientset
|
||||
cs.kyvernoV1alpha1 = kyvernov1alpha1.New(c)
|
||||
|
||||
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
|
||||
return &cs
|
||||
}
|
20
pkg/client/clientset/versioned/doc.go
Normal file
20
pkg/client/clientset/versioned/doc.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated clientset.
|
||||
package versioned
|
77
pkg/client/clientset/versioned/fake/clientset_generated.go
Normal file
77
pkg/client/clientset/versioned/fake/clientset_generated.go
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
clientset "github.com/nirmata/kyverno/pkg/client/clientset/versioned"
|
||||
kyvernov1alpha1 "github.com/nirmata/kyverno/pkg/client/clientset/versioned/typed/policy/v1alpha1"
|
||||
fakekyvernov1alpha1 "github.com/nirmata/kyverno/pkg/client/clientset/versioned/typed/policy/v1alpha1/fake"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/discovery"
|
||||
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||
"k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
||||
// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
|
||||
// without applying any validations and/or defaults. It shouldn't be considered a replacement
|
||||
// for a real clientset and is mostly useful in simple unit tests.
|
||||
func NewSimpleClientset(objects ...runtime.Object) *Clientset {
|
||||
o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
|
||||
for _, obj := range objects {
|
||||
if err := o.Add(obj); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
cs := &Clientset{}
|
||||
cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
|
||||
cs.AddReactor("*", "*", testing.ObjectReaction(o))
|
||||
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
|
||||
gvr := action.GetResource()
|
||||
ns := action.GetNamespace()
|
||||
watch, err := o.Watch(gvr, ns)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return true, watch, nil
|
||||
})
|
||||
|
||||
return cs
|
||||
}
|
||||
|
||||
// Clientset implements clientset.Interface. Meant to be embedded into a
|
||||
// struct to get a default implementation. This makes faking out just the method
|
||||
// you want to test easier.
|
||||
type Clientset struct {
|
||||
testing.Fake
|
||||
discovery *fakediscovery.FakeDiscovery
|
||||
}
|
||||
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
return c.discovery
|
||||
}
|
||||
|
||||
var _ clientset.Interface = &Clientset{}
|
||||
|
||||
// KyvernoV1alpha1 retrieves the KyvernoV1alpha1Client
|
||||
func (c *Clientset) KyvernoV1alpha1() kyvernov1alpha1.KyvernoV1alpha1Interface {
|
||||
return &fakekyvernov1alpha1.FakeKyvernoV1alpha1{Fake: &c.Fake}
|
||||
}
|
20
pkg/client/clientset/versioned/fake/doc.go
Normal file
20
pkg/client/clientset/versioned/fake/doc.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated fake clientset.
|
||||
package fake
|
56
pkg/client/clientset/versioned/fake/register.go
Normal file
56
pkg/client/clientset/versioned/fake/register.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
kyvernov1alpha1 "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
)
|
||||
|
||||
var scheme = runtime.NewScheme()
|
||||
var codecs = serializer.NewCodecFactory(scheme)
|
||||
var parameterCodec = runtime.NewParameterCodec(scheme)
|
||||
var localSchemeBuilder = runtime.SchemeBuilder{
|
||||
kyvernov1alpha1.AddToScheme,
|
||||
}
|
||||
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
//
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
var AddToScheme = localSchemeBuilder.AddToScheme
|
||||
|
||||
func init() {
|
||||
v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
|
||||
utilruntime.Must(AddToScheme(scheme))
|
||||
}
|
20
pkg/client/clientset/versioned/scheme/doc.go
Normal file
20
pkg/client/clientset/versioned/scheme/doc.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package contains the scheme of the automatically generated clientset.
|
||||
package scheme
|
56
pkg/client/clientset/versioned/scheme/register.go
Normal file
56
pkg/client/clientset/versioned/scheme/register.go
Normal file
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package scheme
|
||||
|
||||
import (
|
||||
kyvernov1alpha1 "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
)
|
||||
|
||||
var Scheme = runtime.NewScheme()
|
||||
var Codecs = serializer.NewCodecFactory(Scheme)
|
||||
var ParameterCodec = runtime.NewParameterCodec(Scheme)
|
||||
var localSchemeBuilder = runtime.SchemeBuilder{
|
||||
kyvernov1alpha1.AddToScheme,
|
||||
}
|
||||
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
//
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
var AddToScheme = localSchemeBuilder.AddToScheme
|
||||
|
||||
func init() {
|
||||
v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
|
||||
utilruntime.Must(AddToScheme(Scheme))
|
||||
}
|
20
pkg/client/clientset/versioned/typed/policy/v1alpha1/doc.go
Normal file
20
pkg/client/clientset/versioned/typed/policy/v1alpha1/doc.go
Normal file
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated typed clients.
|
||||
package v1alpha1
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha1 "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// FakePolicies implements PolicyInterface
|
||||
type FakePolicies struct {
|
||||
Fake *FakeKyvernoV1alpha1
|
||||
}
|
||||
|
||||
var policiesResource = schema.GroupVersionResource{Group: "kyverno.io", Version: "v1alpha1", Resource: "policies"}
|
||||
|
||||
var policiesKind = schema.GroupVersionKind{Group: "kyverno.io", Version: "v1alpha1", Kind: "Policy"}
|
||||
|
||||
// Get takes name of the policy, and returns the corresponding policy object, and an error if there is any.
|
||||
func (c *FakePolicies) Get(name string, options v1.GetOptions) (result *v1alpha1.Policy, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootGetAction(policiesResource, name), &v1alpha1.Policy{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Policy), err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Policies that match those selectors.
|
||||
func (c *FakePolicies) List(opts v1.ListOptions) (result *v1alpha1.PolicyList, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootListAction(policiesResource, policiesKind, opts), &v1alpha1.PolicyList{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
label, _, _ := testing.ExtractFromListOptions(opts)
|
||||
if label == nil {
|
||||
label = labels.Everything()
|
||||
}
|
||||
list := &v1alpha1.PolicyList{ListMeta: obj.(*v1alpha1.PolicyList).ListMeta}
|
||||
for _, item := range obj.(*v1alpha1.PolicyList).Items {
|
||||
if label.Matches(labels.Set(item.Labels)) {
|
||||
list.Items = append(list.Items, item)
|
||||
}
|
||||
}
|
||||
return list, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested policies.
|
||||
func (c *FakePolicies) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
return c.Fake.
|
||||
InvokesWatch(testing.NewRootWatchAction(policiesResource, opts))
|
||||
}
|
||||
|
||||
// Create takes the representation of a policy and creates it. Returns the server's representation of the policy, and an error, if there is any.
|
||||
func (c *FakePolicies) Create(policy *v1alpha1.Policy) (result *v1alpha1.Policy, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootCreateAction(policiesResource, policy), &v1alpha1.Policy{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Policy), err
|
||||
}
|
||||
|
||||
// Update takes the representation of a policy and updates it. Returns the server's representation of the policy, and an error, if there is any.
|
||||
func (c *FakePolicies) Update(policy *v1alpha1.Policy) (result *v1alpha1.Policy, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateAction(policiesResource, policy), &v1alpha1.Policy{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Policy), err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
func (c *FakePolicies) UpdateStatus(policy *v1alpha1.Policy) (*v1alpha1.Policy, error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootUpdateSubresourceAction(policiesResource, "status", policy), &v1alpha1.Policy{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Policy), err
|
||||
}
|
||||
|
||||
// Delete takes name of the policy and deletes it. Returns an error if one occurs.
|
||||
func (c *FakePolicies) Delete(name string, options *v1.DeleteOptions) error {
|
||||
_, err := c.Fake.
|
||||
Invokes(testing.NewRootDeleteAction(policiesResource, name), &v1alpha1.Policy{})
|
||||
return err
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *FakePolicies) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
action := testing.NewRootDeleteCollectionAction(policiesResource, listOptions)
|
||||
|
||||
_, err := c.Fake.Invokes(action, &v1alpha1.PolicyList{})
|
||||
return err
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched policy.
|
||||
func (c *FakePolicies) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Policy, err error) {
|
||||
obj, err := c.Fake.
|
||||
Invokes(testing.NewRootPatchSubresourceAction(policiesResource, name, pt, data, subresources...), &v1alpha1.Policy{})
|
||||
if obj == nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*v1alpha1.Policy), err
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha1 "github.com/nirmata/kyverno/pkg/client/clientset/versioned/typed/policy/v1alpha1"
|
||||
rest "k8s.io/client-go/rest"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
type FakeKyvernoV1alpha1 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeKyvernoV1alpha1) Policies() v1alpha1.PolicyInterface {
|
||||
return &FakePolicies{c}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeKyvernoV1alpha1) RESTClient() rest.Interface {
|
||||
var ret *rest.RESTClient
|
||||
return ret
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
type PolicyExpansion interface{}
|
180
pkg/client/clientset/versioned/typed/policy/v1alpha1/policy.go
Normal file
180
pkg/client/clientset/versioned/typed/policy/v1alpha1/policy.go
Normal file
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
v1alpha1 "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
|
||||
scheme "github.com/nirmata/kyverno/pkg/client/clientset/versioned/scheme"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// PoliciesGetter has a method to return a PolicyInterface.
|
||||
// A group's client should implement this interface.
|
||||
type PoliciesGetter interface {
|
||||
Policies() PolicyInterface
|
||||
}
|
||||
|
||||
// PolicyInterface has methods to work with Policy resources.
|
||||
type PolicyInterface interface {
|
||||
Create(*v1alpha1.Policy) (*v1alpha1.Policy, error)
|
||||
Update(*v1alpha1.Policy) (*v1alpha1.Policy, error)
|
||||
UpdateStatus(*v1alpha1.Policy) (*v1alpha1.Policy, error)
|
||||
Delete(name string, options *v1.DeleteOptions) error
|
||||
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
|
||||
Get(name string, options v1.GetOptions) (*v1alpha1.Policy, error)
|
||||
List(opts v1.ListOptions) (*v1alpha1.PolicyList, error)
|
||||
Watch(opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Policy, err error)
|
||||
PolicyExpansion
|
||||
}
|
||||
|
||||
// policies implements PolicyInterface
|
||||
type policies struct {
|
||||
client rest.Interface
|
||||
}
|
||||
|
||||
// newPolicies returns a Policies
|
||||
func newPolicies(c *KyvernoV1alpha1Client) *policies {
|
||||
return &policies{
|
||||
client: c.RESTClient(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get takes name of the policy, and returns the corresponding policy object, and an error if there is any.
|
||||
func (c *policies) Get(name string, options v1.GetOptions) (result *v1alpha1.Policy, err error) {
|
||||
result = &v1alpha1.Policy{}
|
||||
err = c.client.Get().
|
||||
Resource("policies").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Policies that match those selectors.
|
||||
func (c *policies) List(opts v1.ListOptions) (result *v1alpha1.PolicyList, err error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
result = &v1alpha1.PolicyList{}
|
||||
err = c.client.Get().
|
||||
Resource("policies").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested policies.
|
||||
func (c *policies) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
var timeout time.Duration
|
||||
if opts.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
|
||||
}
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Resource("policies").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Watch()
|
||||
}
|
||||
|
||||
// Create takes the representation of a policy and creates it. Returns the server's representation of the policy, and an error, if there is any.
|
||||
func (c *policies) Create(policy *v1alpha1.Policy) (result *v1alpha1.Policy, err error) {
|
||||
result = &v1alpha1.Policy{}
|
||||
err = c.client.Post().
|
||||
Resource("policies").
|
||||
Body(policy).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Update takes the representation of a policy and updates it. Returns the server's representation of the policy, and an error, if there is any.
|
||||
func (c *policies) Update(policy *v1alpha1.Policy) (result *v1alpha1.Policy, err error) {
|
||||
result = &v1alpha1.Policy{}
|
||||
err = c.client.Put().
|
||||
Resource("policies").
|
||||
Name(policy.Name).
|
||||
Body(policy).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
|
||||
func (c *policies) UpdateStatus(policy *v1alpha1.Policy) (result *v1alpha1.Policy, err error) {
|
||||
result = &v1alpha1.Policy{}
|
||||
err = c.client.Put().
|
||||
Resource("policies").
|
||||
Name(policy.Name).
|
||||
SubResource("status").
|
||||
Body(policy).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
||||
|
||||
// Delete takes name of the policy and deletes it. Returns an error if one occurs.
|
||||
func (c *policies) Delete(name string, options *v1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Resource("policies").
|
||||
Name(name).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *policies) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
var timeout time.Duration
|
||||
if listOptions.TimeoutSeconds != nil {
|
||||
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
|
||||
}
|
||||
return c.client.Delete().
|
||||
Resource("policies").
|
||||
VersionedParams(&listOptions, scheme.ParameterCodec).
|
||||
Timeout(timeout).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched policy.
|
||||
func (c *policies) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1alpha1.Policy, err error) {
|
||||
result = &v1alpha1.Policy{}
|
||||
err = c.client.Patch(pt).
|
||||
Resource("policies").
|
||||
SubResource(subresources...).
|
||||
Name(name).
|
||||
Body(data).
|
||||
Do().
|
||||
Into(result)
|
||||
return
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
v1alpha1 "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
|
||||
"github.com/nirmata/kyverno/pkg/client/clientset/versioned/scheme"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
type KyvernoV1alpha1Interface interface {
|
||||
RESTClient() rest.Interface
|
||||
PoliciesGetter
|
||||
}
|
||||
|
||||
// KyvernoV1alpha1Client is used to interact with features provided by the kyverno.io group.
|
||||
type KyvernoV1alpha1Client struct {
|
||||
restClient rest.Interface
|
||||
}
|
||||
|
||||
func (c *KyvernoV1alpha1Client) Policies() PolicyInterface {
|
||||
return newPolicies(c)
|
||||
}
|
||||
|
||||
// NewForConfig creates a new KyvernoV1alpha1Client for the given config.
|
||||
func NewForConfig(c *rest.Config) (*KyvernoV1alpha1Client, error) {
|
||||
config := *c
|
||||
if err := setConfigDefaults(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := rest.RESTClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &KyvernoV1alpha1Client{client}, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new KyvernoV1alpha1Client for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *KyvernoV1alpha1Client {
|
||||
client, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// New creates a new KyvernoV1alpha1Client for the given RESTClient.
|
||||
func New(c rest.Interface) *KyvernoV1alpha1Client {
|
||||
return &KyvernoV1alpha1Client{c}
|
||||
}
|
||||
|
||||
func setConfigDefaults(config *rest.Config) error {
|
||||
gv := v1alpha1.SchemeGroupVersion
|
||||
config.GroupVersion = &gv
|
||||
config.APIPath = "/apis"
|
||||
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
|
||||
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *KyvernoV1alpha1Client) RESTClient() rest.Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.restClient
|
||||
}
|
180
pkg/client/informers/externalversions/factory.go
Normal file
180
pkg/client/informers/externalversions/factory.go
Normal file
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package externalversions
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
time "time"
|
||||
|
||||
versioned "github.com/nirmata/kyverno/pkg/client/clientset/versioned"
|
||||
internalinterfaces "github.com/nirmata/kyverno/pkg/client/informers/externalversions/internalinterfaces"
|
||||
policy "github.com/nirmata/kyverno/pkg/client/informers/externalversions/policy"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// SharedInformerOption defines the functional option type for SharedInformerFactory.
|
||||
type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory
|
||||
|
||||
type sharedInformerFactory struct {
|
||||
client versioned.Interface
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
lock sync.Mutex
|
||||
defaultResync time.Duration
|
||||
customResync map[reflect.Type]time.Duration
|
||||
|
||||
informers map[reflect.Type]cache.SharedIndexInformer
|
||||
// startedInformers is used for tracking which informers have been started.
|
||||
// This allows Start() to be called multiple times safely.
|
||||
startedInformers map[reflect.Type]bool
|
||||
}
|
||||
|
||||
// WithCustomResyncConfig sets a custom resync period for the specified informer types.
|
||||
func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
for k, v := range resyncConfig {
|
||||
factory.customResync[reflect.TypeOf(k)] = v
|
||||
}
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory.
|
||||
func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
factory.tweakListOptions = tweakListOptions
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// WithNamespace limits the SharedInformerFactory to the specified namespace.
|
||||
func WithNamespace(namespace string) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
factory.namespace = namespace
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces.
|
||||
func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory {
|
||||
return NewSharedInformerFactoryWithOptions(client, defaultResync)
|
||||
}
|
||||
|
||||
// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory.
|
||||
// Listers obtained via this SharedInformerFactory will be subject to the same filters
|
||||
// as specified here.
|
||||
// Deprecated: Please use NewSharedInformerFactoryWithOptions instead
|
||||
func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory {
|
||||
return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions))
|
||||
}
|
||||
|
||||
// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options.
|
||||
func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory {
|
||||
factory := &sharedInformerFactory{
|
||||
client: client,
|
||||
namespace: v1.NamespaceAll,
|
||||
defaultResync: defaultResync,
|
||||
informers: make(map[reflect.Type]cache.SharedIndexInformer),
|
||||
startedInformers: make(map[reflect.Type]bool),
|
||||
customResync: make(map[reflect.Type]time.Duration),
|
||||
}
|
||||
|
||||
// Apply all options
|
||||
for _, opt := range options {
|
||||
factory = opt(factory)
|
||||
}
|
||||
|
||||
return factory
|
||||
}
|
||||
|
||||
// Start initializes all requested informers.
|
||||
func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
for informerType, informer := range f.informers {
|
||||
if !f.startedInformers[informerType] {
|
||||
go informer.Run(stopCh)
|
||||
f.startedInformers[informerType] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForCacheSync waits for all started informers' cache were synced.
|
||||
func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {
|
||||
informers := func() map[reflect.Type]cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informers := map[reflect.Type]cache.SharedIndexInformer{}
|
||||
for informerType, informer := range f.informers {
|
||||
if f.startedInformers[informerType] {
|
||||
informers[informerType] = informer
|
||||
}
|
||||
}
|
||||
return informers
|
||||
}()
|
||||
|
||||
res := map[reflect.Type]bool{}
|
||||
for informType, informer := range informers {
|
||||
res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// InternalInformerFor returns the SharedIndexInformer for obj using an internal
|
||||
// client.
|
||||
func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informerType := reflect.TypeOf(obj)
|
||||
informer, exists := f.informers[informerType]
|
||||
if exists {
|
||||
return informer
|
||||
}
|
||||
|
||||
resyncPeriod, exists := f.customResync[informerType]
|
||||
if !exists {
|
||||
resyncPeriod = f.defaultResync
|
||||
}
|
||||
|
||||
informer = newFunc(f.client, resyncPeriod)
|
||||
f.informers[informerType] = informer
|
||||
|
||||
return informer
|
||||
}
|
||||
|
||||
// SharedInformerFactory provides shared informers for resources in all known
|
||||
// API group versions.
|
||||
type SharedInformerFactory interface {
|
||||
internalinterfaces.SharedInformerFactory
|
||||
ForResource(resource schema.GroupVersionResource) (GenericInformer, error)
|
||||
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
|
||||
|
||||
Kyverno() policy.Interface
|
||||
}
|
||||
|
||||
func (f *sharedInformerFactory) Kyverno() policy.Interface {
|
||||
return policy.New(f, f.namespace, f.tweakListOptions)
|
||||
}
|
62
pkg/client/informers/externalversions/generic.go
Normal file
62
pkg/client/informers/externalversions/generic.go
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package externalversions
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
v1alpha1 "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// GenericInformer is type of SharedIndexInformer which will locate and delegate to other
|
||||
// sharedInformers based on type
|
||||
type GenericInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() cache.GenericLister
|
||||
}
|
||||
|
||||
type genericInformer struct {
|
||||
informer cache.SharedIndexInformer
|
||||
resource schema.GroupResource
|
||||
}
|
||||
|
||||
// Informer returns the SharedIndexInformer.
|
||||
func (f *genericInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.informer
|
||||
}
|
||||
|
||||
// Lister returns the GenericLister.
|
||||
func (f *genericInformer) Lister() cache.GenericLister {
|
||||
return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource)
|
||||
}
|
||||
|
||||
// ForResource gives generic access to a shared informer of the matching type
|
||||
// TODO extend this to unknown resources with a client pool
|
||||
func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
|
||||
switch resource {
|
||||
// Group=kyverno.io, Version=v1alpha1
|
||||
case v1alpha1.SchemeGroupVersion.WithResource("policies"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Kyverno().V1alpha1().Policies().Informer()}, nil
|
||||
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no informer found for %v", resource)
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package internalinterfaces
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
versioned "github.com/nirmata/kyverno/pkg/client/clientset/versioned"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer.
|
||||
type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer
|
||||
|
||||
// SharedInformerFactory a small interface to allow for adding an informer without an import cycle
|
||||
type SharedInformerFactory interface {
|
||||
Start(stopCh <-chan struct{})
|
||||
InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer
|
||||
}
|
||||
|
||||
// TweakListOptionsFunc is a function that transforms a v1.ListOptions.
|
||||
type TweakListOptionsFunc func(*v1.ListOptions)
|
46
pkg/client/informers/externalversions/policy/interface.go
Normal file
46
pkg/client/informers/externalversions/policy/interface.go
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package kyverno
|
||||
|
||||
import (
|
||||
internalinterfaces "github.com/nirmata/kyverno/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1alpha1 "github.com/nirmata/kyverno/pkg/client/informers/externalversions/policy/v1alpha1"
|
||||
)
|
||||
|
||||
// Interface provides access to each of this group's versions.
|
||||
type Interface interface {
|
||||
// V1alpha1 provides access to shared informers for resources in V1alpha1.
|
||||
V1alpha1() v1alpha1.Interface
|
||||
}
|
||||
|
||||
type group struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
|
||||
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// V1alpha1 returns a new v1alpha1.Interface.
|
||||
func (g *group) V1alpha1() v1alpha1.Interface {
|
||||
return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions)
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
internalinterfaces "github.com/nirmata/kyverno/pkg/client/informers/externalversions/internalinterfaces"
|
||||
)
|
||||
|
||||
// Interface provides access to all the informers in this group version.
|
||||
type Interface interface {
|
||||
// Policies returns a PolicyInformer.
|
||||
Policies() PolicyInformer
|
||||
}
|
||||
|
||||
type version struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
|
||||
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// Policies returns a PolicyInformer.
|
||||
func (v *version) Policies() PolicyInformer {
|
||||
return &policyInformer{factory: v.factory, tweakListOptions: v.tweakListOptions}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
policyv1alpha1 "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
|
||||
versioned "github.com/nirmata/kyverno/pkg/client/clientset/versioned"
|
||||
internalinterfaces "github.com/nirmata/kyverno/pkg/client/informers/externalversions/internalinterfaces"
|
||||
v1alpha1 "github.com/nirmata/kyverno/pkg/client/listers/policy/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// PolicyInformer provides access to a shared informer and lister for
|
||||
// Policies.
|
||||
type PolicyInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() v1alpha1.PolicyLister
|
||||
}
|
||||
|
||||
type policyInformer struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// NewPolicyInformer constructs a new informer for Policy type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewPolicyInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||
return NewFilteredPolicyInformer(client, resyncPeriod, indexers, nil)
|
||||
}
|
||||
|
||||
// NewFilteredPolicyInformer constructs a new informer for Policy type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewFilteredPolicyInformer(client versioned.Interface, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
|
||||
return cache.NewSharedIndexInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.KyvernoV1alpha1().Policies().List(options)
|
||||
},
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.KyvernoV1alpha1().Policies().Watch(options)
|
||||
},
|
||||
},
|
||||
&policyv1alpha1.Policy{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
}
|
||||
|
||||
func (f *policyInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return NewFilteredPolicyInformer(client, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
}
|
||||
|
||||
func (f *policyInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&policyv1alpha1.Policy{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *policyInformer) Lister() v1alpha1.PolicyLister {
|
||||
return v1alpha1.NewPolicyLister(f.Informer().GetIndexer())
|
||||
}
|
23
pkg/client/listers/policy/v1alpha1/expansion_generated.go
Normal file
23
pkg/client/listers/policy/v1alpha1/expansion_generated.go
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
// PolicyListerExpansion allows custom methods to be added to
|
||||
// PolicyLister.
|
||||
type PolicyListerExpansion interface{}
|
65
pkg/client/listers/policy/v1alpha1/policy.go
Normal file
65
pkg/client/listers/policy/v1alpha1/policy.go
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
v1alpha1 "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// PolicyLister helps list Policies.
|
||||
type PolicyLister interface {
|
||||
// List lists all Policies in the indexer.
|
||||
List(selector labels.Selector) (ret []*v1alpha1.Policy, err error)
|
||||
// Get retrieves the Policy from the index for a given name.
|
||||
Get(name string) (*v1alpha1.Policy, error)
|
||||
PolicyListerExpansion
|
||||
}
|
||||
|
||||
// policyLister implements the PolicyLister interface.
|
||||
type policyLister struct {
|
||||
indexer cache.Indexer
|
||||
}
|
||||
|
||||
// NewPolicyLister returns a new PolicyLister.
|
||||
func NewPolicyLister(indexer cache.Indexer) PolicyLister {
|
||||
return &policyLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// List lists all Policies in the indexer.
|
||||
func (s *policyLister) List(selector labels.Selector) (ret []*v1alpha1.Policy, err error) {
|
||||
err = cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
ret = append(ret, m.(*v1alpha1.Policy))
|
||||
})
|
||||
return ret, err
|
||||
}
|
||||
|
||||
// Get retrieves the Policy from the index for a given name.
|
||||
func (s *policyLister) Get(name string) (*v1alpha1.Policy, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(v1alpha1.Resource("policy"), name)
|
||||
}
|
||||
return obj.(*v1alpha1.Policy), nil
|
||||
}
|
|
@ -2,28 +2,28 @@ package config
|
|||
|
||||
const (
|
||||
// These constants MUST be equal to the corresponding names in service definition in definitions/install.yaml
|
||||
KubePolicyNamespace = "kube-system"
|
||||
WebhookServiceName = "kube-policy-svc"
|
||||
KubePolicyNamespace = "kyverno"
|
||||
WebhookServiceName = "kyverno-svc"
|
||||
|
||||
MutatingWebhookConfigurationName = "kube-policy-mutating-webhook-cfg"
|
||||
MutatingWebhookName = "nirmata.kube-policy.mutating-webhook"
|
||||
MutatingWebhookConfigurationName = "kyverno-mutating-webhook-cfg"
|
||||
MutatingWebhookName = "nirmata.kyverno.mutating-webhook"
|
||||
|
||||
ValidatingWebhookConfigurationName = "kube-policy-validating-webhook-cfg"
|
||||
ValidatingWebhookName = "nirmata.kube-policy.validating-webhook"
|
||||
ValidatingWebhookConfigurationName = "kyverno-validating-webhook-cfg"
|
||||
ValidatingWebhookName = "nirmata.kyverno.validating-webhook"
|
||||
|
||||
// Due to kubernetes issue, we must use next literal constants instead of deployment TypeMeta fields
|
||||
// Issue: https://github.com/kubernetes/kubernetes/pull/63972
|
||||
// When the issue is closed, we should use TypeMeta struct instead of this constants
|
||||
DeploymentKind = "Deployment"
|
||||
DeploymentAPIVersion = "extensions/v1beta1"
|
||||
KubePolicyDeploymentName = "kube-policy-deployment"
|
||||
KubePolicyDeploymentName = "kyverno-deployment"
|
||||
)
|
||||
|
||||
var (
|
||||
MutatingWebhookServicePath = "/mutate"
|
||||
ValidatingWebhookServicePath = "/validate"
|
||||
KubePolicyAppLabels = map[string]string{
|
||||
"app": "kube-policy",
|
||||
"app": "kyverno",
|
||||
}
|
||||
|
||||
SupportedKinds = []string{
|
||||
|
|
|
@ -4,15 +4,14 @@ import (
|
|||
"log"
|
||||
|
||||
kubepolicy "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
|
||||
"github.com/nirmata/kyverno/pkg/engine/mutation"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// Mutate performs mutation. Overlay first and then mutation patches
|
||||
// TODO: return events and violations
|
||||
func Mutate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVersionKind) ([]mutation.PatchBytes, []byte) {
|
||||
var policyPatches []mutation.PatchBytes
|
||||
var processedPatches []mutation.PatchBytes
|
||||
func Mutate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVersionKind) ([]PatchBytes, []byte) {
|
||||
var policyPatches []PatchBytes
|
||||
var processedPatches []PatchBytes
|
||||
var err error
|
||||
patchedDocument := rawResource
|
||||
|
||||
|
@ -30,7 +29,7 @@ func Mutate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVersio
|
|||
// Process Overlay
|
||||
|
||||
if rule.Mutation.Overlay != nil {
|
||||
overlayPatches, err := mutation.ProcessOverlay(rule.Mutation.Overlay, rawResource)
|
||||
overlayPatches, err := ProcessOverlay(policy, rawResource, gvk)
|
||||
if err != nil {
|
||||
log.Printf("Overlay application has failed for rule %s in policy %s, err: %v\n", rule.Name, policy.ObjectMeta.Name, err)
|
||||
} else {
|
||||
|
@ -41,7 +40,7 @@ func Mutate(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVersio
|
|||
// Process Patches
|
||||
|
||||
if rule.Mutation.Patches != nil {
|
||||
processedPatches, patchedDocument, err = mutation.ProcessPatches(rule.Mutation.Patches, patchedDocument)
|
||||
processedPatches, patchedDocument, err = ProcessPatches(rule.Mutation.Patches, patchedDocument)
|
||||
if err != nil {
|
||||
log.Printf("Patches application has failed for rule %s in policy %s, err: %v\n", rule.Name, policy.ObjectMeta.Name, err)
|
||||
} else {
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
package mutation
|
||||
|
||||
func ProcessOverlay(overlay interface{}, rawResource []byte) ([]PatchBytes, error) {
|
||||
// TODO: Overlay to be implemented
|
||||
return nil, nil
|
||||
}
|
379
pkg/engine/overlay.go
Normal file
379
pkg/engine/overlay.go
Normal file
|
@ -0,0 +1,379 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
|
||||
kubepolicy "github.com/nirmata/kyverno/pkg/apis/policy/v1alpha1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// ProcessOverlay handles validating admission request
|
||||
// Checks the target resourse for rules defined in the policy
|
||||
func ProcessOverlay(policy kubepolicy.Policy, rawResource []byte, gvk metav1.GroupVersionKind) ([]PatchBytes, []byte) {
|
||||
var resource interface{}
|
||||
json.Unmarshal(rawResource, &resource)
|
||||
|
||||
for _, rule := range policy.Spec.Rules {
|
||||
if rule.Mutation == nil || rule.Mutation.Overlay == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
ok := ResourceMeetsDescription(rawResource, rule.ResourceDescription, gvk)
|
||||
if !ok {
|
||||
log.Printf("Rule \"%s\" is not applicable to resource\n", rule.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
overlay := *rule.Mutation.Overlay
|
||||
if err, _ := applyOverlay(resource, overlay, ""); err != nil {
|
||||
//return fmt.Errorf("%s: %s", *rule.Validation.Message, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func applyOverlay(resource, overlay interface{}, path string) ([]PatchBytes, error) {
|
||||
var appliedPatches []PatchBytes
|
||||
|
||||
// resource item exists but has different type - replace
|
||||
// all subtree within this path by overlay
|
||||
if reflect.TypeOf(resource) != reflect.TypeOf(overlay) {
|
||||
patch, err := replaceSubtree(overlay, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
appliedPatches = append(appliedPatches, patch)
|
||||
return appliedPatches, nil
|
||||
}
|
||||
|
||||
switch typedOverlay := overlay.(type) {
|
||||
case map[string]interface{}:
|
||||
typedResource := resource.(map[string]interface{})
|
||||
|
||||
for key, value := range typedOverlay {
|
||||
if wrappedWithParentheses(key) {
|
||||
key = key[1 : len(key)-1]
|
||||
}
|
||||
currentPath := path + key + "/"
|
||||
resourcePart, ok := typedResource[key]
|
||||
|
||||
if ok {
|
||||
patches, err := applyOverlay(resourcePart, value, currentPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
appliedPatches = append(appliedPatches, patches...)
|
||||
|
||||
} else {
|
||||
patch, err := insertSubtree(value, currentPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
appliedPatches = append(appliedPatches, patch)
|
||||
}
|
||||
}
|
||||
case []interface{}:
|
||||
typedResource := resource.([]interface{})
|
||||
patches, err := applyOverlayToArray(typedResource, typedOverlay, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
appliedPatches = append(appliedPatches, patches...)
|
||||
case string:
|
||||
patch, err := replaceSubtree(overlay, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
appliedPatches = append(appliedPatches, patch)
|
||||
case float64:
|
||||
patch, err := replaceSubtree(overlay, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
appliedPatches = append(appliedPatches, patch)
|
||||
case int64:
|
||||
patch, err := replaceSubtree(overlay, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
appliedPatches = append(appliedPatches, patch)
|
||||
}
|
||||
|
||||
return appliedPatches, nil
|
||||
}
|
||||
|
||||
func applyOverlayToArray(resource, overlay []interface{}, path string) ([]PatchBytes, error) {
|
||||
var appliedPatches []PatchBytes
|
||||
if len(overlay) == 0 {
|
||||
return nil, fmt.Errorf("overlay does not support empty arrays")
|
||||
}
|
||||
|
||||
if len(resource) == 0 {
|
||||
patches, err := fillEmptyArray(overlay, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return patches, nil
|
||||
}
|
||||
|
||||
if reflect.TypeOf(resource[0]) != reflect.TypeOf(overlay[0]) {
|
||||
return nil, fmt.Errorf("overlay array and resource array have elements of different types: %T and %T", overlay[0], resource[0])
|
||||
}
|
||||
|
||||
switch overlay[0].(type) {
|
||||
case map[string]interface{}:
|
||||
for _, overlayElement := range overlay {
|
||||
typedOverlay := overlayElement.(map[string]interface{})
|
||||
anchors := GetAnchorsFromMap(typedOverlay)
|
||||
|
||||
currentPath := path + "0/"
|
||||
for _, resourceElement := range resource {
|
||||
typedResource := resourceElement.(map[string]interface{})
|
||||
if len(anchors) > 0 {
|
||||
if !skipArrayObject(typedResource, anchors) {
|
||||
patches, err := applyOverlay(resourceElement, overlayElement, currentPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
appliedPatches = append(appliedPatches, patches...)
|
||||
}
|
||||
} else {
|
||||
if hasNestedAnchors(overlayElement) {
|
||||
patches, err := applyOverlay(resourceElement, overlayElement, currentPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
appliedPatches = append(appliedPatches, patches...)
|
||||
} else {
|
||||
patch, err := insertSubtree(overlayElement, currentPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
appliedPatches = append(appliedPatches, patch)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
default:
|
||||
path += "0/"
|
||||
for _, value := range overlay {
|
||||
patch, err := insertSubtree(value, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
appliedPatches = append(appliedPatches, patch)
|
||||
}
|
||||
}
|
||||
|
||||
return appliedPatches, nil
|
||||
}
|
||||
|
||||
// In case of empty resource array
|
||||
// append all non-anchor items to front
|
||||
func fillEmptyArray(overlay []interface{}, path string) ([]PatchBytes, error) {
|
||||
var appliedPatches []PatchBytes
|
||||
if len(overlay) == 0 {
|
||||
return nil, fmt.Errorf("overlay does not support empty arrays")
|
||||
}
|
||||
|
||||
path += "0/"
|
||||
|
||||
switch overlay[0].(type) {
|
||||
case map[string]interface{}:
|
||||
for _, overlayElement := range overlay {
|
||||
typedOverlay := overlayElement.(map[string]interface{})
|
||||
anchors := GetAnchorsFromMap(typedOverlay)
|
||||
|
||||
if len(anchors) == 0 {
|
||||
patch, err := insertSubtree(overlayElement, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
appliedPatches = append(appliedPatches, patch)
|
||||
}
|
||||
}
|
||||
default:
|
||||
for _, overlayElement := range overlay {
|
||||
patch, err := insertSubtree(overlayElement, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
appliedPatches = append(appliedPatches, patch)
|
||||
}
|
||||
}
|
||||
|
||||
return appliedPatches, nil
|
||||
}
|
||||
|
||||
func skipArrayObject(object, anchors map[string]interface{}) bool {
|
||||
for key, pattern := range anchors {
|
||||
key = key[1 : len(key)-1]
|
||||
|
||||
value, ok := object[key]
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
if value != pattern {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func insertSubtree(overlay interface{}, path string) ([]byte, error) {
|
||||
return processSubtree(overlay, path, "add")
|
||||
}
|
||||
|
||||
func replaceSubtree(overlay interface{}, path string) ([]byte, error) {
|
||||
return processSubtree(overlay, path, "replace")
|
||||
}
|
||||
|
||||
func processSubtree(overlay interface{}, path string, op string) ([]byte, error) {
|
||||
if len(path) > 1 && path[len(path)-1] == '/' {
|
||||
path = path[:len(path)-1]
|
||||
}
|
||||
|
||||
if path == "" {
|
||||
path = "/"
|
||||
}
|
||||
|
||||
value := prepareJSONValue(overlay)
|
||||
patchStr := fmt.Sprintf(`{ "op": "%s", "path": "%s", "value": %s }`, op, path, value)
|
||||
|
||||
// check the patch
|
||||
_, err := jsonpatch.DecodePatch([]byte("[" + patchStr + "]"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return []byte(patchStr), nil
|
||||
}
|
||||
|
||||
func prepareJSONValue(overlay interface{}) string {
|
||||
switch typed := overlay.(type) {
|
||||
case map[string]interface{}:
|
||||
if len(typed) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
if hasOnlyAnchors(overlay) {
|
||||
return ""
|
||||
}
|
||||
|
||||
result := ""
|
||||
for key, value := range typed {
|
||||
jsonValue := prepareJSONValue(value)
|
||||
|
||||
pair := fmt.Sprintf(`"%s":%s`, key, jsonValue)
|
||||
|
||||
if result != "" {
|
||||
result += ", "
|
||||
}
|
||||
|
||||
result += pair
|
||||
}
|
||||
|
||||
result = fmt.Sprintf(`{ %s }`, result)
|
||||
return result
|
||||
case []interface{}:
|
||||
if len(typed) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
if hasOnlyAnchors(overlay) {
|
||||
return ""
|
||||
}
|
||||
|
||||
result := ""
|
||||
for _, value := range typed {
|
||||
jsonValue := prepareJSONValue(value)
|
||||
|
||||
if result != "" {
|
||||
result += ", "
|
||||
}
|
||||
|
||||
result += jsonValue
|
||||
}
|
||||
|
||||
result = fmt.Sprintf(`[ %s ]`, result)
|
||||
return result
|
||||
case string:
|
||||
return fmt.Sprintf(`"%s"`, typed)
|
||||
case float64:
|
||||
return fmt.Sprintf("%f", typed)
|
||||
case int64:
|
||||
return fmt.Sprintf("%d", typed)
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func hasOnlyAnchors(overlay interface{}) bool {
|
||||
switch typed := overlay.(type) {
|
||||
case map[string]interface{}:
|
||||
if anchors := GetAnchorsFromMap(typed); len(anchors) == len(typed) {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, value := range typed {
|
||||
if !hasOnlyAnchors(value) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
case string:
|
||||
return false
|
||||
case float64:
|
||||
return false
|
||||
case int64:
|
||||
return false
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func hasNestedAnchors(overlay interface{}) bool {
|
||||
switch typed := overlay.(type) {
|
||||
case map[string]interface{}:
|
||||
if anchors := GetAnchorsFromMap(typed); len(anchors) > 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, value := range typed {
|
||||
if hasNestedAnchors(value) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
case string:
|
||||
return false
|
||||
case float64:
|
||||
return false
|
||||
case int64:
|
||||
return false
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
62
pkg/engine/overlay_test.go
Normal file
62
pkg/engine/overlay_test.go
Normal file
|
@ -0,0 +1,62 @@
|
|||
package engine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
func TestApplyOverlay_NestedListWithAnchor(t *testing.T) {
|
||||
resourceRaw := []byte(`{ "apiVersion": "v1", "kind": "Endpoints", "metadata": { "name": "test-endpoint", "labels": { "label": "test" } }, "subsets": [ { "addresses": [ { "ip": "192.168.10.171" } ], "ports": [ { "name": "secure-connection", "port": 443, "protocol": "TCP" } ] } ] }`)
|
||||
overlayRaw := []byte(`{ "subsets": [ { "ports": [ { "(name)": "secure-connection", "port": 444, "protocol": "UDP" } ] } ] }`)
|
||||
|
||||
var resource, overlay interface{}
|
||||
|
||||
json.Unmarshal(resourceRaw, &resource)
|
||||
json.Unmarshal(overlayRaw, &overlay)
|
||||
|
||||
patches, err := applyOverlay(resource, overlay, "/")
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, patches != nil)
|
||||
|
||||
patch := JoinPatches(patches)
|
||||
decoded, err := jsonpatch.DecodePatch(patch)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, decoded != nil)
|
||||
|
||||
patched, err := decoded.Apply(resourceRaw)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, patched != nil)
|
||||
|
||||
expectedResult := []byte(`{"apiVersion":"v1","kind":"Endpoints","metadata":{"name":"test-endpoint","labels":{"label":"test"}},"subsets":[{"addresses":[{"ip":"192.168.10.171"}],"ports":[{"name":"secure-connection","port":444.000000,"protocol":"UDP"}]}]}`)
|
||||
assert.Equal(t, string(expectedResult), string(patched))
|
||||
}
|
||||
|
||||
func TestApplyOverlay_InsertIntoArray(t *testing.T) {
|
||||
resourceRaw := []byte(`{ "apiVersion": "v1", "kind": "Endpoints", "metadata": { "name": "test-endpoint", "labels": { "label": "test" } }, "subsets": [ { "addresses": [ { "ip": "192.168.10.171" } ], "ports": [ { "name": "secure-connection", "port": 443, "protocol": "TCP" } ] } ] }`)
|
||||
overlayRaw := []byte(`{ "subsets": [ { "addresses": [ { "ip": "192.168.10.172" }, { "ip": "192.168.10.173" } ], "ports": [ { "name": "insecure-connection", "port": 80, "protocol": "UDP" } ] } ] }`)
|
||||
|
||||
var resource, overlay interface{}
|
||||
|
||||
json.Unmarshal(resourceRaw, &resource)
|
||||
json.Unmarshal(overlayRaw, &overlay)
|
||||
|
||||
patches, err := applyOverlay(resource, overlay, "/")
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, patches != nil)
|
||||
|
||||
patch := JoinPatches(patches)
|
||||
|
||||
decoded, err := jsonpatch.DecodePatch(patch)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, decoded != nil)
|
||||
|
||||
patched, err := decoded.Apply(resourceRaw)
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, patched != nil)
|
||||
|
||||
expectedResult := []byte(`{"apiVersion":"v1","kind":"Endpoints","metadata":{"name":"test-endpoint","labels":{"label":"test"}},"subsets":[{"addresses":[{"ip":"192.168.10.172"},{"ip":"192.168.10.173"}],"ports":[{"name":"insecure-connection","port":80.000000,"protocol":"UDP"}]},{"addresses":[{"ip":"192.168.10.171"}],"ports":[{"name":"secure-connection","port":443,"protocol":"TCP"}]}]}`)
|
||||
assert.Equal(t, string(expectedResult), string(patched))
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package mutation
|
||||
package engine
|
||||
|
||||
import (
|
||||
"encoding/json"
|
|
@ -1,4 +1,4 @@
|
|||
package mutation
|
||||
package engine
|
||||
|
||||
import (
|
||||
"testing"
|
|
@ -13,7 +13,7 @@ import (
|
|||
|
||||
// ResourceMeetsDescription checks requests kind, name and labels to fit the policy rule
|
||||
func ResourceMeetsDescription(resourceRaw []byte, description kubepolicy.ResourceDescription, gvk metav1.GroupVersionKind) bool {
|
||||
if description.Kind != gvk.Kind {
|
||||
if !findKind(description.Kinds, gvk.Kind) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -104,3 +104,24 @@ func ParseRegexPolicyResourceName(policyResourceName string) (string, bool) {
|
|||
}
|
||||
return strings.Trim(regex[1], " "), true
|
||||
}
|
||||
|
||||
func GetAnchorsFromMap(anchorsMap map[string]interface{}) map[string]interface{} {
|
||||
result := make(map[string]interface{})
|
||||
|
||||
for key, value := range anchorsMap {
|
||||
if wrappedWithParentheses(key) {
|
||||
result[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func findKind(kinds []string, kindGVK string) bool {
|
||||
for _, kind := range kinds {
|
||||
if kind == kindGVK {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -96,10 +96,7 @@ func validateArray(resourcePart, patternPart interface{}) error {
|
|||
|
||||
switch pattern := patternArray[0].(type) {
|
||||
case map[string]interface{}:
|
||||
anchors, err := getAnchorsFromMap(pattern)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
anchors := GetAnchorsFromMap(pattern)
|
||||
|
||||
for _, value := range resourceArray {
|
||||
resource, ok := value.(map[string]interface{})
|
||||
|
@ -107,7 +104,7 @@ func validateArray(resourcePart, patternPart interface{}) error {
|
|||
return fmt.Errorf("expected array, found %T", resourcePart)
|
||||
}
|
||||
|
||||
if skipArrayObject(resource, anchors) {
|
||||
if skipValidatingObject(resource, anchors) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -177,19 +174,7 @@ func validateMapElement(resourcePart, patternPart interface{}) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func getAnchorsFromMap(pattern map[string]interface{}) (map[string]interface{}, error) {
|
||||
result := make(map[string]interface{})
|
||||
|
||||
for key, value := range pattern {
|
||||
if wrappedWithParentheses(key) {
|
||||
result[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func skipArrayObject(object, anchors map[string]interface{}) bool {
|
||||
func skipValidatingObject(object, anchors map[string]interface{}) bool {
|
||||
for key, pattern := range anchors {
|
||||
key = key[1 : len(key)-1]
|
||||
|
||||
|
|
|
@ -306,8 +306,7 @@ func TestGetAnchorsFromMap_ThereAreAnchors(t *testing.T) {
|
|||
var unmarshalled map[string]interface{}
|
||||
json.Unmarshal(rawMap, &unmarshalled)
|
||||
|
||||
actualMap, err := getAnchorsFromMap(unmarshalled)
|
||||
assert.NilError(t, err)
|
||||
actualMap := GetAnchorsFromMap(unmarshalled)
|
||||
assert.Equal(t, len(actualMap), 2)
|
||||
assert.Equal(t, actualMap["(name)"].(string), "nirmata-*")
|
||||
assert.Equal(t, actualMap["(namespace)"].(string), "kube-?olicy")
|
||||
|
@ -319,8 +318,7 @@ func TestGetAnchorsFromMap_ThereAreNoAnchors(t *testing.T) {
|
|||
var unmarshalled map[string]interface{}
|
||||
json.Unmarshal(rawMap, &unmarshalled)
|
||||
|
||||
actualMap, err := getAnchorsFromMap(unmarshalled)
|
||||
assert.NilError(t, err)
|
||||
actualMap := GetAnchorsFromMap(unmarshalled)
|
||||
assert.Assert(t, len(actualMap) == 0)
|
||||
}
|
||||
|
||||
|
@ -358,7 +356,7 @@ func TestValidateMapElement_OneElementInArrayNotPass(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestValidate_ServiceTest(t *testing.T) {
|
||||
rawPolicy := []byte(`{ "apiVersion": "kubepolicy.nirmata.io/v1alpha1", "kind": "Policy", "metadata": { "name": "policy-service" }, "spec": { "rules": [ { "name": "ps1", "resource": { "kind": "Service", "name": "game-service*" }, "mutate": { "patches": [ { "path": "/metadata/labels/isMutated", "op": "add", "value": "true" }, { "path": "/metadata/labels/secretLabel", "op": "replace", "value": "weKnow" }, { "path": "/metadata/labels/originalLabel", "op": "remove" }, { "path": "/spec/selector/app", "op": "replace", "value": "mutedApp" } ] }, "validate": { "message": "This resource is broken", "pattern": { "spec": { "ports": [ { "name": "hs", "protocol": 32 } ] } } } } ] } }`)
|
||||
rawPolicy := []byte(`{ "apiVersion": "kyverno.nirmata.io/v1alpha1", "kind": "Policy", "metadata": { "name": "policy-service" }, "spec": { "rules": [ { "name": "ps1", "resource": { "kind": "Service", "name": "game-service*" }, "mutate": { "patches": [ { "path": "/metadata/labels/isMutated", "op": "add", "value": "true" }, { "path": "/metadata/labels/secretLabel", "op": "replace", "value": "weKnow" }, { "path": "/metadata/labels/originalLabel", "op": "remove" }, { "path": "/spec/selector/app", "op": "replace", "value": "mutedApp" } ] }, "validate": { "message": "This resource is broken", "pattern": { "spec": { "ports": [ { "name": "hs", "protocol": 32 } ] } } } } ] } }`)
|
||||
rawResource := []byte(`{ "kind": "Service", "apiVersion": "v1", "metadata": { "name": "game-service", "labels": { "originalLabel": "isHere", "secretLabel": "thisIsMySecret" } }, "spec": { "selector": { "app": "MyApp" }, "ports": [ { "name": "http", "protocol": "TCP", "port": 80, "targetPort": 9376 } ] } }`)
|
||||
|
||||
var policy kubepolicy.Policy
|
||||
|
@ -372,7 +370,7 @@ func TestValidate_ServiceTest(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestValidate_MapHasFloats(t *testing.T) {
|
||||
rawPolicy := []byte(`{ "apiVersion": "kubepolicy.nirmata.io/v1alpha1", "kind": "Policy", "metadata": { "name": "policy-deployment-changed" }, "spec": { "rules": [ { "name": "First policy v2", "resource": { "kind": "Deployment", "name": "nginx-*" }, "mutate": { "patches": [ { "path": "/metadata/labels/isMutated", "op": "add", "value": "true" }, { "path": "/metadata/labels/app", "op": "replace", "value": "nginx_is_mutated" } ] }, "validate": { "message": "replicas number is wrong", "pattern": { "metadata": { "labels": { "app": "*" } }, "spec": { "replicas": 3 } } } } ] } }`)
|
||||
rawPolicy := []byte(`{ "apiVersion": "kyverno.nirmata.io/v1alpha1", "kind": "Policy", "metadata": { "name": "policy-deployment-changed" }, "spec": { "rules": [ { "name": "First policy v2", "resource": { "kind": "Deployment", "name": "nginx-*" }, "mutate": { "patches": [ { "path": "/metadata/labels/isMutated", "op": "add", "value": "true" }, { "path": "/metadata/labels/app", "op": "replace", "value": "nginx_is_mutated" } ] }, "validate": { "message": "replicas number is wrong", "pattern": { "metadata": { "labels": { "app": "*" } }, "spec": { "replicas": 3 } } } } ] } }`)
|
||||
rawResource := []byte(`{ "apiVersion": "apps/v1", "kind": "Deployment", "metadata": { "name": "nginx-deployment", "labels": { "app": "nginx" } }, "spec": { "replicas": 3, "selector": { "matchLabels": { "app": "nginx" } }, "template": { "metadata": { "labels": { "app": "nginx" } }, "spec": { "containers": [ { "name": "nginx", "image": "nginx:1.7.9", "ports": [ { "containerPort": 80 } ] } ] } } } }`)
|
||||
|
||||
var policy kubepolicy.Policy
|
||||
|
|
|
@ -82,7 +82,7 @@ func complete(args []string) (*kubepolicy.Policy, []*resourceInfo) {
|
|||
func applyPolicy(policy *kubepolicy.Policy, rawResource []byte, gvk *metav1.GroupVersionKind) ([]byte, error) {
|
||||
_, patchedDocument := engine.Mutate(*policy, rawResource, *gvk)
|
||||
|
||||
if err := engine.Validate(*policy, rawResource, *gvk); err != nil {
|
||||
if err := engine.Validate(*policy, patchedDocument, *gvk); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return patchedDocument, nil
|
||||
|
|
|
@ -44,7 +44,7 @@ func (si *sharedInfomer) Run(stopCh <-chan struct{}) {
|
|||
}
|
||||
|
||||
func (si *sharedInfomer) getInfomer() infomertypes.PolicyInformer {
|
||||
return si.policyInformerFactory.Kubepolicy().V1alpha1().Policies()
|
||||
return si.policyInformerFactory.Kyverno().V1alpha1().Policies()
|
||||
}
|
||||
func (si *sharedInfomer) GetInfomer() cache.SharedIndexInformer {
|
||||
return si.getInfomer().Informer()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ import (
|
|||
"github.com/nirmata/kyverno/pkg/client/listers/policy/v1alpha1"
|
||||
"github.com/nirmata/kyverno/pkg/config"
|
||||
engine "github.com/nirmata/kyverno/pkg/engine"
|
||||
"github.com/nirmata/kyverno/pkg/engine/mutation"
|
||||
"github.com/nirmata/kyverno/pkg/sharedinformer"
|
||||
tlsutils "github.com/nirmata/kyverno/pkg/tls"
|
||||
v1beta1 "k8s.io/api/admission/v1beta1"
|
||||
|
@ -87,13 +86,11 @@ func (ws *WebhookServer) serve(w http.ResponseWriter, r *http.Request) {
|
|||
admissionReview.Response = &v1beta1.AdmissionResponse{
|
||||
Allowed: true,
|
||||
}
|
||||
if ws.client.KindIsSupported(admissionReview.Request.Kind.Kind) {
|
||||
switch r.URL.Path {
|
||||
case config.MutatingWebhookServicePath:
|
||||
admissionReview.Response = ws.HandleMutation(admissionReview.Request)
|
||||
case config.ValidatingWebhookServicePath:
|
||||
admissionReview.Response = ws.HandleValidation(admissionReview.Request)
|
||||
}
|
||||
switch r.URL.Path {
|
||||
case config.MutatingWebhookServicePath:
|
||||
admissionReview.Response = ws.HandleMutation(admissionReview.Request)
|
||||
case config.ValidatingWebhookServicePath:
|
||||
admissionReview.Response = ws.HandleValidation(admissionReview.Request)
|
||||
}
|
||||
|
||||
admissionReview.Response.UID = admissionReview.Request.UID
|
||||
|
@ -143,7 +140,7 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest) *v1be
|
|||
return nil
|
||||
}
|
||||
|
||||
var allPatches []mutation.PatchBytes
|
||||
var allPatches []engine.PatchBytes
|
||||
for _, policy := range policies {
|
||||
ws.logger.Printf("Applying policy %s with %d rules\n", policy.ObjectMeta.Name, len(policy.Spec.Rules))
|
||||
|
||||
|
@ -160,7 +157,7 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest) *v1be
|
|||
patchType := v1beta1.PatchTypeJSONPatch
|
||||
return &v1beta1.AdmissionResponse{
|
||||
Allowed: true,
|
||||
Patch: mutation.JoinPatches(allPatches),
|
||||
Patch: engine.JoinPatches(allPatches),
|
||||
PatchType: &patchType,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ Compiles the project to go executable, generates docker image and pushes it to t
|
|||
|
||||
### generate-server-cert.sh ###
|
||||
Generates TLS certificate and key that used by webhook server. Example:
|
||||
`scripts/generate-server-cert.sh --service=kube-policy-svc --namespace=my_namespace --serverIp=192.168.10.117`
|
||||
`scripts/generate-server-cert.sh --service=kyverno-svc --namespace=my_namespace --serverIp=192.168.10.117`
|
||||
* `--service` identifies the service for in-cluster webhook server. Do not specify it if you plan to run webhook server outside the cluster, or cpecify 'localhost' if you want to run controller locally.
|
||||
* `--namespace` identifies the namespace for in-cluster webhook server. Do not specify it if you plan to run controller locally.
|
||||
* `--serverIp` is the IP of master node, it can be found in `~/.kube/config`: clusters.cluster[0].server. You should explicitly specify it.
|
||||
|
@ -18,7 +18,7 @@ Prepares controller for free (local) or in-cluster use. Uses `generate-server-ce
|
|||
* `--namespace` - the target namespace to deploy the controller. Do not specify it if you want to depoloy controller locally.
|
||||
* `--serverIp` means the same as for `generate-server-cert.sh`
|
||||
Examples:
|
||||
`scripts/deploy-controller.sh --service=my-kube-policy --namespace=my_namespace --serverIp=192.168.10.117` - deploy controller to the cluster with master node '192.168.10.117' to the namespace 'my_namespace' as a service 'my-kube-policy'
|
||||
`scripts/deploy-controller.sh --service=my-kyverno --namespace=my_namespace --serverIp=192.168.10.117` - deploy controller to the cluster with master node '192.168.10.117' to the namespace 'my_namespace' as a service 'my-kyverno'
|
||||
`scripts/deploy-controller.sh --service=localhost --serverIp=192.168.10.117` - deploy controller locally for usage in cluster with mnaster node at '192.168.10.117'
|
||||
|
||||
### test-web-hook.sh ###
|
||||
|
|
|
@ -19,7 +19,7 @@ esac
|
|||
done
|
||||
|
||||
hub_user_name="nirmata"
|
||||
project_name="kube-policy"
|
||||
project_name="kyverno"
|
||||
|
||||
if [ -z "${service_name}" ]; then
|
||||
service_name="${project_name}-svc"
|
||||
|
@ -40,7 +40,7 @@ if [ -z "${namespace}" ]; then # controller should be launched locally
|
|||
kubectl delete -f definitions/install.yaml
|
||||
kubectl create -f definitions/install.yaml || exit 3
|
||||
|
||||
echo -e "\n### You can build and run kube-policy project locally.\n### To check its work, run it with parameters -cert, -key and -kubeconfig parameters (see paths of -cert and -key in the log above)."
|
||||
echo -e "\n### You can build and run kyverno project locally.\n### To check its work, run it with parameters -cert, -key and -kubeconfig parameters (see paths of -cert and -key in the log above)."
|
||||
|
||||
else # controller should be launched within a cluster
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion : kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : policy-cm
|
||||
|
@ -6,7 +6,8 @@ spec :
|
|||
rules:
|
||||
- name: pCM1
|
||||
resource:
|
||||
kind : ConfigMap
|
||||
kinds :
|
||||
- ConfigMap
|
||||
name: "game-config"
|
||||
mutate:
|
||||
patches:
|
||||
|
@ -15,7 +16,8 @@ spec :
|
|||
value : newValue
|
||||
- name: pCM2
|
||||
resource:
|
||||
kind : ConfigMap
|
||||
kinds :
|
||||
- ConfigMap
|
||||
name: "game-config"
|
||||
mutate:
|
||||
patches:
|
||||
|
@ -26,7 +28,8 @@ spec :
|
|||
value : "data is replaced"
|
||||
- name: pCM3
|
||||
resource:
|
||||
kind : ConfigMap
|
||||
kinds :
|
||||
- ConfigMap
|
||||
name: "game-config"
|
||||
mutate:
|
||||
patches:
|
||||
|
@ -40,7 +43,8 @@ spec :
|
|||
game.properties: "*enemies=aliens*"
|
||||
- name: pCM4
|
||||
resource:
|
||||
kind : ConfigMap
|
||||
kinds :
|
||||
- ConfigMap
|
||||
name: "game-config"
|
||||
validate:
|
||||
message: "This CM data is broken because it does not have ui.properties"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion : kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata :
|
||||
name: "policy-configmapgenerator-test"
|
||||
|
@ -6,7 +6,8 @@ spec:
|
|||
rules:
|
||||
- name: "copyCM"
|
||||
resource :
|
||||
kind : Namespace
|
||||
kinds :
|
||||
- Namespace
|
||||
selector:
|
||||
matchLabels:
|
||||
LabelForSelector : "namespace2"
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# To apply this policy you need to create secret and configMap in "default" namespace
|
||||
# and then create a namespace
|
||||
|
||||
apiVersion : kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : "policy-ns-patch-cmg-sg"
|
||||
|
@ -11,7 +11,8 @@ spec :
|
|||
rules:
|
||||
- name: "patchNamespace2"
|
||||
resource :
|
||||
kind : Namespace
|
||||
kinds :
|
||||
- Namespace
|
||||
selector:
|
||||
matchLabels:
|
||||
LabelForSelector : "namespace2"
|
||||
|
@ -23,7 +24,8 @@ spec :
|
|||
|
||||
- name: "copyCM"
|
||||
resource :
|
||||
kind : Namespace
|
||||
kinds :
|
||||
- Namespace
|
||||
selector:
|
||||
matchLabels:
|
||||
LabelForSelector : "namespace2"
|
||||
|
@ -38,7 +40,8 @@ spec :
|
|||
|
||||
- name: "generateCM"
|
||||
resource :
|
||||
kind : Namespace
|
||||
kinds :
|
||||
- Namespace
|
||||
selector:
|
||||
matchLabels:
|
||||
LabelForSelector : "namespace2"
|
||||
|
@ -56,7 +59,8 @@ spec :
|
|||
|
||||
- name: "generateSecret"
|
||||
resource :
|
||||
kind : Namespace
|
||||
kinds :
|
||||
- Namespace
|
||||
name: ns2
|
||||
generate :
|
||||
kind: Secret
|
||||
|
@ -72,7 +76,8 @@ spec :
|
|||
|
||||
- name: "copySecret"
|
||||
resource :
|
||||
kind : Namespace
|
||||
kinds :
|
||||
- Namespace
|
||||
name: ns2
|
||||
generate :
|
||||
kind: Secret
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
apiVersion: kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: policy-cronjob
|
||||
spec:
|
||||
rules:
|
||||
- name:
|
||||
- name: pCJ
|
||||
resource:
|
||||
kind : CronJob
|
||||
kinds :
|
||||
- CronJob
|
||||
name: "?ell*"
|
||||
mutate:
|
||||
patches:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: policy-daemonset
|
||||
|
@ -6,7 +6,8 @@ spec:
|
|||
rules:
|
||||
- name: "Patch and Volume validation"
|
||||
resource:
|
||||
kind: DaemonSet
|
||||
kinds:
|
||||
- DaemonSet
|
||||
name: fluentd-elasticsearch
|
||||
mutate:
|
||||
patches:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion : kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : policy-deployment
|
||||
|
@ -6,8 +6,8 @@ spec :
|
|||
rules:
|
||||
- name: "First policy v2"
|
||||
resource:
|
||||
kind : Deployment
|
||||
name: nginx-*
|
||||
kinds :
|
||||
- Deployment
|
||||
mutate:
|
||||
patches:
|
||||
- path: /metadata/labels/isMutated
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
apiVersion : kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : policy-endpoints
|
||||
spec :
|
||||
rules:
|
||||
- name:
|
||||
- name: pEP
|
||||
resource:
|
||||
kind : Endpoints
|
||||
kinds :
|
||||
- Endpoints
|
||||
selector:
|
||||
matchLabels:
|
||||
label : test
|
||||
|
@ -19,7 +20,7 @@ spec :
|
|||
op: add
|
||||
value:
|
||||
addresses:
|
||||
- ip: "192.168.10.171"
|
||||
- ip: "192.168.10.172"
|
||||
ports:
|
||||
- name: load-balancer-connection
|
||||
port: 80
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: policy-hpa
|
||||
|
@ -6,7 +6,8 @@ spec :
|
|||
rules:
|
||||
- name: hpa1
|
||||
resource:
|
||||
kind : HorizontalPodAutoscaler
|
||||
kinds :
|
||||
- HorizontalPodAutoscaler
|
||||
selector:
|
||||
matchLabels:
|
||||
originalLabel: isHere
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata :
|
||||
name : policy-ingress
|
||||
|
@ -6,7 +6,8 @@ spec :
|
|||
rules:
|
||||
- name: ingress1
|
||||
resource:
|
||||
kind : Ingress
|
||||
kinds :
|
||||
- Ingress
|
||||
selector:
|
||||
matchLabels:
|
||||
originalLabel: isHere
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: policy-job-perl-bigint
|
||||
|
@ -6,7 +6,8 @@ spec :
|
|||
rules:
|
||||
- name: job1
|
||||
resource:
|
||||
kind: Job
|
||||
kinds:
|
||||
- Job
|
||||
name: pi
|
||||
mutate:
|
||||
patches:
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
apiVersion : kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : policy-limitrange
|
||||
spec :
|
||||
rules:
|
||||
- name:
|
||||
- name: "rule"
|
||||
resource:
|
||||
kind : LimitRange
|
||||
kinds :
|
||||
- LimitRange
|
||||
selector:
|
||||
matchLabels:
|
||||
containerSize: minimal
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata :
|
||||
name : policy-namespace
|
||||
|
@ -7,7 +7,8 @@ spec :
|
|||
rules:
|
||||
- name: ns1
|
||||
resource:
|
||||
kind : Namespace
|
||||
kinds :
|
||||
- Namespace
|
||||
selector:
|
||||
matchLabels:
|
||||
LabelForSelector : "namespace"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: policy-network-policy
|
||||
|
@ -6,7 +6,8 @@ spec:
|
|||
rules:
|
||||
- name: np1
|
||||
resource:
|
||||
kind : NetworkPolicy
|
||||
kinds :
|
||||
- NetworkPolicy
|
||||
selector:
|
||||
matchLabels:
|
||||
originalLabel: isHere
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: policy-pvc
|
||||
|
@ -6,7 +6,8 @@ spec:
|
|||
rules:
|
||||
- name: pvc1
|
||||
resource:
|
||||
kind : PersistentVolumeClaim
|
||||
kinds :
|
||||
- PersistentVolumeClaim
|
||||
matchLabels:
|
||||
originalLabel: isHere
|
||||
mutate:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: policy-pdb
|
||||
|
@ -6,7 +6,8 @@ spec:
|
|||
rules:
|
||||
- name: pdb1
|
||||
resource:
|
||||
kind : PodDisruptionBudget
|
||||
kinds :
|
||||
- PodDisruptionBudget
|
||||
name: "game-pdb"
|
||||
mutate:
|
||||
patches:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: test-podtemplate
|
||||
|
@ -6,7 +6,8 @@ spec:
|
|||
rules:
|
||||
- name: podtemplate1
|
||||
resource:
|
||||
kind : PodTemplate
|
||||
kinds :
|
||||
- PodTemplate
|
||||
selector:
|
||||
matchLabels:
|
||||
originalLabel: isHere
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
# Examples
|
||||
Examples of policies and resources with which you can play to see the kube-policy in action. There are definitions for each supported resource type and an example policy for the corresponding resource.
|
||||
## How to play
|
||||
First of all, **build and install the policy controller**: see README file in the project's root.
|
||||
Each folder contains a pair of files, one of which is the definition of the resource, and the second is the definition of the policy for this resource. Let's look at an example of the endpoints mutation. Endpoints are listed in file `examples/Endpoints/endpoints.yaml`:
|
||||
# Test samples
|
||||
|
||||
```apiVersion: v1
|
||||
This directory contains policies and resources for testing. There are definitions for each supported resource type and an sample policy for the corresponding resource.
|
||||
|
||||
## How to use
|
||||
|
||||
Currently, the testing is possible only via ```kubectl``` when kyverno is installed to the cluster. So, [build and install the policy controller](/documentation/installation.md) first.
|
||||
|
||||
Each folder contains a pair of files, one of which is the definition of the resource, and the second is the definition of the policy for this resource. Let's look at an example of the endpoints mutation. Endpoints are listed in file `test/Endpoints/endpoints.yaml`:
|
||||
|
||||
````yaml
|
||||
apiVersion: v1
|
||||
kind: Endpoints
|
||||
metadata:
|
||||
name: test-endpoint
|
||||
|
@ -17,25 +22,25 @@ subsets:
|
|||
- name: secure-connection
|
||||
port: 443
|
||||
protocol: TCP
|
||||
```
|
||||
````
|
||||
Create this resource:
|
||||
|
||||
```
|
||||
> kubectl create -f examples/Endpoints/endpoints.yaml
|
||||
````yaml
|
||||
> kubectl create -f test/Endpoints/endpoints.yaml
|
||||
endpoints/test-endpoint created
|
||||
> kubectl get -f examples/Endpoints/endpoints.yaml
|
||||
> kubectl get -f test/Endpoints/endpoints.yaml
|
||||
NAME ENDPOINTS AGE
|
||||
test-endpoint 192.168.10.171:443 6s
|
||||
```
|
||||
````
|
||||
We just created an endpoints resource and made sure that it was created without changes. Let's remove it now and try to create it again, but with an active policy for endpoints resources.
|
||||
```
|
||||
> kubectl delete -f test/endpoints.yaml
|
||||
````bash
|
||||
> kubectl delete -f test/Endpoints/endpoints.yaml
|
||||
endpoints "test-endpoint" deleted
|
||||
```
|
||||
We have this a policy for enpoints (`examples/Endpoints/policy-endpoint.yaml`):
|
||||
````
|
||||
We have this a policy for enpoints ([policy-endpoint.yaml](/test/Endpoints/policy-endpoint.yaml)):
|
||||
|
||||
```
|
||||
apiVersion : kubepolicy.nirmata.io/v1alpha1
|
||||
````yaml
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : policy-endpoints
|
||||
|
@ -43,7 +48,8 @@ spec :
|
|||
rules:
|
||||
- name:
|
||||
resource:
|
||||
kind : Endpoints
|
||||
kinds:
|
||||
- Endpoints
|
||||
selector:
|
||||
matchLabels:
|
||||
label : test
|
||||
|
@ -61,22 +67,22 @@ spec :
|
|||
- name: load-balancer-connection
|
||||
port: 80
|
||||
protocol: UDP
|
||||
```
|
||||
````
|
||||
This policy does 2 patches:
|
||||
|
||||
- **replaces** the first port of the first connection to 6443
|
||||
- **adds** new endpoint with IP 192.168.10.171 and port 80 (UDP)
|
||||
|
||||
Let's apply this policy and create the endpoints again to see the changes:
|
||||
```
|
||||
> kubectl create -f examples/Endpoints/policy-endpoints.yaml
|
||||
````bash
|
||||
> kubectl create -f test/Endpoints/policy-endpoints.yaml
|
||||
policy.policy.nirmata.io/policy-endpoints created
|
||||
> kubectl create -f examples/Endpoints/endpoints.yaml
|
||||
> kubectl create -f test/Endpoints/endpoints.yaml
|
||||
endpoints/test-endpoint created
|
||||
> kubectl get -f examples/Endpoints/endpoints.yaml
|
||||
> kubectl get -f test/Endpoints/endpoints.yaml
|
||||
NAME ENDPOINTS AGE
|
||||
test-endpoint 192.168.10.171:80,192.168.10.171:9663 30s
|
||||
```
|
||||
````
|
||||
As you can see, the endpoints resource was created with changes: a new port 80 was added, and port 443 was changed to 6443.
|
||||
|
||||
**Enjoy :)**
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
apiVersion : kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : policy-quota-low-test-validation
|
||||
spec :
|
||||
rules:
|
||||
- name:
|
||||
- name: "rule1"
|
||||
resource:
|
||||
kind : ResourceQuota
|
||||
kinds :
|
||||
- ResourceQuota
|
||||
selector:
|
||||
matchLabels:
|
||||
quota: low
|
||||
|
@ -16,9 +17,10 @@ spec :
|
|||
spec:
|
||||
hard:
|
||||
memory: "8Gi|12Gi"
|
||||
- name:
|
||||
- name: "rule2"
|
||||
resource:
|
||||
kind : ResourceQuota
|
||||
kinds :
|
||||
- ResourceQuota
|
||||
selector:
|
||||
matchLabels:
|
||||
quota: low
|
||||
|
@ -28,9 +30,10 @@ spec :
|
|||
spec:
|
||||
hard:
|
||||
cpu: <3
|
||||
- name:
|
||||
- name: "rule3"
|
||||
resource:
|
||||
kind : ResourceQuota
|
||||
kinds :
|
||||
- ResourceQuota
|
||||
selector:
|
||||
matchLabels:
|
||||
quota: low
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
apiVersion : kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : policy-quota-low-test
|
||||
spec :
|
||||
rules:
|
||||
- name:
|
||||
- name: "rule"
|
||||
resource:
|
||||
kind : ResourceQuota
|
||||
kinds :
|
||||
- ResourceQuota
|
||||
selector:
|
||||
matchLabels:
|
||||
quota: low
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion: kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion: kyverno.io/v1alpha1
|
||||
kind: Policy
|
||||
metadata:
|
||||
name: policy-secrets
|
||||
|
@ -6,7 +6,8 @@ spec:
|
|||
rules:
|
||||
- name: secret1
|
||||
resource:
|
||||
kind : Secret
|
||||
kinds :
|
||||
- Secret
|
||||
name: "mysecret"
|
||||
mutate:
|
||||
patches:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
apiVersion : kubepolicy.nirmata.io/v1alpha1
|
||||
apiVersion : kyverno.io/v1alpha1
|
||||
kind : Policy
|
||||
metadata :
|
||||
name : policy-service
|
||||
|
@ -6,7 +6,8 @@ spec :
|
|||
rules:
|
||||
- name: ps1
|
||||
resource:
|
||||
kind: Service
|
||||
kinds:
|
||||
- Service
|
||||
name: "game-service*"
|
||||
mutate:
|
||||
patches:
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue