1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-31 03:45:17 +00:00

update namespace trigger + update documentation

This commit is contained in:
shivdudhani 2019-06-03 16:02:34 -07:00
parent f5d9b039ec
commit ecca97b2a0
8 changed files with 108 additions and 90 deletions

View file

@ -98,12 +98,14 @@ spec:
selector: selector:
matchExpressions: matchExpressions:
- {key: kafka, operator: Exists} - {key: kafka, operator: Exists}
generate: generate:
kind: ConfigMap kind: ConfigMap
name: zk-kafka-address name: zk-kafka-address
data: data:
ZK_ADDRESS: "192.168.10.10:2181,192.168.10.11:2181,192.168.10.12:2181" kind: ConfigMap
KAFKA_ADDRESS: "192.168.10.13:9092,192.168.10.14:9092,192.168.10.15:9092" 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"
```` ````
### 4. More examples ### 4. More examples

View file

@ -102,14 +102,11 @@ spec:
required: required:
- kind - kind
- name - name
- namespace
properties: properties:
kind: kind:
type: string type: string
name: name:
type: string type: string
namespace:
type: string
clone: clone:
type: object type: object
required: required:

View file

@ -2,47 +2,82 @@
# Generate Configurations # 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. ```generate``` 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 ## Example 1
````yaml ````yaml
apiVersion : kyverno.io/v1alpha1 apiVersion: kyverno.io/v1alpha1
kind : Policy kind: Policy
metadata : metadata:
name : basic-policy name: basic-policy
spec : spec:
rules: rules:
- name: "Basic confog generator for all namespaces" - name: "Basic config generator for all namespaces"
resource: resource:
kind: Namespace kinds:
- Namespace
selector:
matchLabels:
LabelForSelector : "namespace2"
generate: generate:
# For now the next kinds are supported: kind: ConfigMap
# ConfigMap
# Secret
- kind: ConfigMap
name: default-config name: default-config
copyFrom: clone:
namespace: default namespace: default
name: config-template name: config-template
data: - name: "Basic config generator for all namespaces"
DB_ENDPOINT: mongodb://mydomain.ua/db_stage:27017 resource:
labels: kinds:
purpose: mongo - Namespace
- kind: Secret selector:
matchLabels:
LabelForSelector : "namespace2"
generate:
kind: Secret
name: mongo-creds name: mongo-creds
data: data:
DB_USER: YWJyYWthZGFicmE= data:
DB_PASSWORD: YXBwc3dvcmQ= DB_USER: YWJyYWthZGFicmE=
labels: DB_PASSWORD: YXBwc3dvcmQ=
purpose: mongo metadata:
labels:
purpose: mongo
```` ````
In this example, when this policy is applied, any new namespace will receive 2 new resources after its creation: In this example, when this policy is applied, any new namespace that satisfies the label selector will receive 2 new resources after its creation:
* ConfigMap copied from default/config-template with added value DB_ENDPOINT. * ConfigMap copied from default/config-template.
* Secret with values DB_USER and DB_PASSWORD. * Secret with values DB_USER and DB_PASSWORD, and label ```purpose: mongo```.
Both resources will contain a label ```purpose: mongo```
## Example 2
````yaml
apiVersion: kyverno.io/v1alpha1
kind: Policy
metadata:
name: "default"
spec:
rules:
- name: "deny-all-traffic"
resource:
kinds:
- Namespace
name: "*"
generate:
kind: NetworkPolicy
name: deny-all-traffic
data:
spec:
podSelector:
matchLabels: {}
matchExpressions: []
policyTypes: []
metadata:
annotations: {}
labels:
policyname: "default"
````
In this example, when this policy is applied, any new namespace will receive a new NetworkPolicy resource based on the specified template that by default denies all inbound and outbound traffic.
--- ---
<small>*Read Next >> [Testing Policies](/documentation/testing-policies.md)*</small> <small>*Read Next >> [Testing Policies](/documentation/testing-policies.md)*</small>

View file

@ -14,21 +14,21 @@ spec:
generate : generate :
kind: ConfigMap kind: ConfigMap
name : copied-cm name : copied-cm
copyFrom : clone:
namespace : default namespace : default
name : game-config name : game-config
data :
secretData: "data from cmg"
- name: "zk-kafka-address" - name: "zk-kafka-address"
resource: resource:
kinds: kinds:
- Namespace - Namespace
selector: selector:
matchExpressions: matchExpressions:
- {key: LabelForSelector, operator: In, values: [namespace2]} - {key: LabelForSelector, operator: In, values: [namespace2]}
generate: generate:
kind: ConfigMap kind: ConfigMap
name: zk-kafka-address name: zk-kafka-address
data: data:
ZK_ADDRESS: "192.168.10.10:2181,192.168.10.11:2181,192.168.10.12:2181" kind: ConfigMap
KAFKA_ADDRESS: "192.168.10.13:9092,192.168.10.14:9092,192.168.10.15:9092" 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"

View file

@ -0,0 +1,24 @@
apiVersion: kyverno.io/v1alpha1
kind: Policy
metadata:
name: "default"
spec:
rules:
- name: "deny-all-traffic"
resource:
kinds:
- Namespace
name: "*"
generate:
kind: NetworkPolicy
name: deny-all-traffic
data:
spec:
podSelector:
matchLabels: {}
matchExpressions: []
policyTypes: []
metadata:
annotations: {}
labels:
policyname: "default"

View file

@ -61,11 +61,10 @@ type Validation struct {
// Generation describes which resources will be created when other resource is created // Generation describes which resources will be created when other resource is created
type Generation struct { type Generation struct {
Kind string `json:"kind"` Kind string `json:"kind"`
Name string `json:"name"` Name string `json:"name"`
Namespace string `json:"namespace"` Data interface{} `json:"data"`
Data interface{} `json:"data"` Clone *CloneFrom `json:"clone"`
Clone *CloneFrom `json:"clone"`
} }
// CloneFrom - location of a Secret or a ConfigMap // CloneFrom - location of a Secret or a ConfigMap

View file

@ -1,7 +1,6 @@
package client package client
import ( import (
"errors"
"fmt" "fmt"
"strings" "strings"
"time" "time"
@ -166,41 +165,7 @@ func ConvertToRuntimeObject(obj *unstructured.Unstructured) (*runtime.Object, er
return &runtimeObj, nil return &runtimeObj, nil
} }
// only support 2 levels of keys // GenerateResource creates resource of the specified kind(supports 'clone' & 'data')
// To-Do support multiple levels of key
func keysExist(data map[string]interface{}, keys ...string) bool {
var v interface{}
var t map[string]interface{}
var ok bool
for _, key := range keys {
ks := strings.Split(key, ".")
if len(ks) > 2 {
glog.Error("Only support 2 levels of keys from root. Support to be extendend in future")
return false
}
if v, ok = data[ks[0]]; !ok {
glog.Infof("key %s does not exist", key)
return false
}
if len(ks) == 2 {
if t, ok = v.(map[string]interface{}); !ok {
glog.Error("expecting type map[string]interface{}")
}
return keyExist(t, ks[1])
}
}
return true
}
func keyExist(data map[string]interface{}, key string) (ok bool) {
if _, ok = data[key]; !ok {
glog.Infof("key %s does not exist", key)
}
return ok
}
// support mode 'data' -> create resource
// To-Do: support 'from' -> copy/clone the resource
func (c *Client) GenerateResource(generator types.Generation, namespace string) error { func (c *Client) GenerateResource(generator types.Generation, namespace string) error {
var err error var err error
rGVR := c.getGVRFromKind(generator.Kind) rGVR := c.getGVRFromKind(generator.Kind)
@ -214,10 +179,6 @@ func (c *Client) GenerateResource(generator types.Generation, namespace string)
utilruntime.HandleError(err) utilruntime.HandleError(err)
return err return err
} }
// verify if mandatory attributes have been defined
if !keysExist(rdata, "kind", "apiVersion", "metadata.name", "metadata.namespace") {
return errors.New("mandatory keys not defined")
}
} }
// clone -> copy from existing resource // clone -> copy from existing resource
if generator.Clone != nil { if generator.Clone != nil {
@ -230,7 +191,7 @@ func (c *Client) GenerateResource(generator types.Generation, namespace string)
resource.SetUnstructuredContent(rdata) resource.SetUnstructuredContent(rdata)
resource.SetName(generator.Name) resource.SetName(generator.Name)
resource.SetNamespace(generator.Namespace) resource.SetNamespace(namespace)
resource.SetResourceVersion("") resource.SetResourceVersion("")
err = c.waitUntilNamespaceIsCreated(namespace) err = c.waitUntilNamespaceIsCreated(namespace)
@ -238,7 +199,7 @@ func (c *Client) GenerateResource(generator types.Generation, namespace string)
glog.Errorf("Can't create a resource %s: %v", generator.Name, err) glog.Errorf("Can't create a resource %s: %v", generator.Name, err)
return nil return nil
} }
_, err = c.CreateResource(rGVR.Resource, generator.Namespace, resource) _, err = c.CreateResource(rGVR.Resource, namespace, resource)
if err != nil { if err != nil {
return err return err
} }

View file

@ -46,6 +46,6 @@ func applyRuleGenerator(client *client.Client, rawResource []byte, generator *ku
if err != nil { if err != nil {
return fmt.Errorf("Unable to apply generator for %s '%s/%s' : %v", generator.Kind, namespace, generator.Name, err) return fmt.Errorf("Unable to apply generator for %s '%s/%s' : %v", generator.Kind, namespace, generator.Name, err)
} }
glog.Infof("Successfully applied generator %s/%s", generator.Kind, generator.Name) glog.Infof("Successfully applied generator %s '%s/%s'", generator.Kind, namespace, generator.Name)
return nil return nil
} }