mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-05 15:37:19 +00:00
NK-23: Improved comments, commited crd with status subresource.
This commit is contained in:
parent
0a939e44dc
commit
898652b9a2
6 changed files with 41 additions and 28 deletions
|
@ -85,15 +85,19 @@ func (c *PolicyController) GetPolicies() []types.Policy {
|
||||||
return policies
|
return policies
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Writes error message to the policy logs in status section
|
||||||
func (c *PolicyController) LogPolicyError(name, text string) {
|
func (c *PolicyController) LogPolicyError(name, text string) {
|
||||||
c.addPolicyLog(name, "[ERROR] "+text)
|
c.addPolicyLog(name, "[ERROR] "+text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Writes info message to the policy logs in status section
|
||||||
func (c *PolicyController) LogPolicyInfo(name, text string) {
|
func (c *PolicyController) LogPolicyInfo(name, text string) {
|
||||||
c.addPolicyLog(name, "[ INFO] "+text)
|
c.addPolicyLog(name, "[ INFO] "+text)
|
||||||
}
|
}
|
||||||
|
|
||||||
const policyLogMaxRecords int = 10
|
// This is the maximum number of records that can be written to the log object of the policy.
|
||||||
|
// If this number is exceeded, the older entries will be deleted.
|
||||||
|
const policyLogMaxRecords int = 50
|
||||||
|
|
||||||
// Appends given log text to the status/logs array.
|
// Appends given log text to the status/logs array.
|
||||||
func (c *PolicyController) addPolicyLog(name, text string) {
|
func (c *PolicyController) addPolicyLog(name, text string) {
|
||||||
|
@ -125,7 +129,6 @@ func (c *PolicyController) addPolicyLog(name, text string) {
|
||||||
func (c *PolicyController) createPolicyHandler(resource interface{}) {
|
func (c *PolicyController) createPolicyHandler(resource interface{}) {
|
||||||
key := c.getResourceKey(resource)
|
key := c.getResourceKey(resource)
|
||||||
c.logger.Printf("Policy created: %s", key)
|
c.logger.Printf("Policy created: %s", key)
|
||||||
c.addPolicyLog(key, "Added")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PolicyController) updatePolicyHandler(oldResource, newResource interface{}) {
|
func (c *PolicyController) updatePolicyHandler(oldResource, newResource interface{}) {
|
||||||
|
@ -133,7 +136,6 @@ func (c *PolicyController) updatePolicyHandler(oldResource, newResource interfac
|
||||||
newKey := c.getResourceKey(newResource)
|
newKey := c.getResourceKey(newResource)
|
||||||
|
|
||||||
c.logger.Printf("Policy %s updated to %s", oldKey, newKey)
|
c.logger.Printf("Policy %s updated to %s", oldKey, newKey)
|
||||||
c.addPolicyLog(newKey, "Updated")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PolicyController) deletePolicyHandler(resource interface{}) {
|
func (c *PolicyController) deletePolicyHandler(resource interface{}) {
|
||||||
|
|
|
@ -13,3 +13,6 @@ spec:
|
||||||
kind: Policy
|
kind: Policy
|
||||||
plural: policies
|
plural: policies
|
||||||
singular: policy
|
singular: policy
|
||||||
|
subresources:
|
||||||
|
status: {}
|
||||||
|
|
||||||
|
|
|
@ -13,11 +13,13 @@ import (
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// KubeClient is the api-client for core Kubernetes objects
|
||||||
type KubeClient struct {
|
type KubeClient struct {
|
||||||
logger *log.Logger
|
logger *log.Logger
|
||||||
client *kubernetes.Clientset
|
client *kubernetes.Clientset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Checks parameters and creates new instance of KubeClient
|
||||||
func NewKubeClient(config *rest.Config, logger *log.Logger) (*KubeClient, error) {
|
func NewKubeClient(config *rest.Config, logger *log.Logger) (*KubeClient, error) {
|
||||||
if logger == nil {
|
if logger == nil {
|
||||||
logger = log.New(os.Stdout, "Policy Controller: ", log.LstdFlags|log.Lshortfile)
|
logger = log.New(os.Stdout, "Policy Controller: ", log.LstdFlags|log.Lshortfile)
|
||||||
|
@ -34,6 +36,8 @@ func NewKubeClient(config *rest.Config, logger *log.Logger) (*KubeClient, error)
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generates new ConfigMap in given namespace. If the namespace does not exists yet,
|
||||||
|
// waits until it is created for maximum namespaceCreationMaxWaitTime (see below)
|
||||||
func (kc *KubeClient) GenerateConfigMap(generator types.PolicyConfigGenerator, namespace string) error {
|
func (kc *KubeClient) GenerateConfigMap(generator types.PolicyConfigGenerator, namespace string) error {
|
||||||
kc.logger.Printf("Preparing to create configmap %s/%s", namespace, generator.Name)
|
kc.logger.Printf("Preparing to create configmap %s/%s", namespace, generator.Name)
|
||||||
configMap := &v1.ConfigMap{}
|
configMap := &v1.ConfigMap{}
|
||||||
|
@ -67,6 +71,8 @@ func (kc *KubeClient) GenerateConfigMap(generator types.PolicyConfigGenerator, n
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generates new Secret in given namespace. If the namespace does not exists yet,
|
||||||
|
// waits until it is created for maximum namespaceCreationMaxWaitTime (see below)
|
||||||
func (kc *KubeClient) GenerateSecret(generator types.PolicyConfigGenerator, namespace string) error {
|
func (kc *KubeClient) GenerateSecret(generator types.PolicyConfigGenerator, namespace string) error {
|
||||||
kc.logger.Printf("Preparing to create secret %s/%s", namespace, generator.Name)
|
kc.logger.Printf("Preparing to create secret %s/%s", namespace, generator.Name)
|
||||||
secret := &v1.Secret{}
|
secret := &v1.Secret{}
|
||||||
|
|
|
@ -79,6 +79,7 @@ func NewWebhookServer(config WebhookServerConfig, logger *log.Logger) (*WebhookS
|
||||||
return ws, nil
|
return ws, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Main server endpoint for all requests
|
||||||
func (ws *WebhookServer) serve(w http.ResponseWriter, r *http.Request) {
|
func (ws *WebhookServer) serve(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.URL.Path == "/mutate" {
|
if r.URL.Path == "/mutate" {
|
||||||
admissionReview := ws.parseAdmissionReview(r, w)
|
admissionReview := ws.parseAdmissionReview(r, w)
|
||||||
|
@ -148,8 +149,7 @@ func (ws *WebhookServer) parseAdmissionReview(request *http.Request, writer http
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunAsync runs TLS server in separate
|
// Runs TLS server in separate thread and returns control immediately
|
||||||
// thread and returns control immediately
|
|
||||||
func (ws *WebhookServer) RunAsync() {
|
func (ws *WebhookServer) RunAsync() {
|
||||||
go func(ws *WebhookServer) {
|
go func(ws *WebhookServer) {
|
||||||
err := ws.server.ListenAndServeTLS("", "")
|
err := ws.server.ListenAndServeTLS("", "")
|
||||||
|
@ -159,7 +159,7 @@ func (ws *WebhookServer) RunAsync() {
|
||||||
}(ws)
|
}(ws)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Stop stops TLS server
|
// Stops TLS server and returns control after the server is shut down
|
||||||
func (ws *WebhookServer) Stop() {
|
func (ws *WebhookServer) Stop() {
|
||||||
err := ws.server.Shutdown(context.Background())
|
err := ws.server.Shutdown(context.Background())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -66,7 +66,7 @@ func (mw *MutationWebhook) Mutate(request *v1beta1.AdmissionRequest) *v1beta1.Ad
|
||||||
if stopOnError {
|
if stopOnError {
|
||||||
mw.logger.Printf("/!\\ Denying the request according to FailurePolicy spec /!\\")
|
mw.logger.Printf("/!\\ Denying the request according to FailurePolicy spec /!\\")
|
||||||
}
|
}
|
||||||
return errorToResponse(err, !stopOnError)
|
return errorToAdmissionResponse(err, !stopOnError)
|
||||||
}
|
}
|
||||||
if rulePatches != nil {
|
if rulePatches != nil {
|
||||||
allPatches = append(allPatches, rulePatches...)
|
allPatches = append(allPatches, rulePatches...)
|
||||||
|
@ -78,7 +78,7 @@ func (mw *MutationWebhook) Mutate(request *v1beta1.AdmissionRequest) *v1beta1.Ad
|
||||||
patchesBytes, err := SerializePatches(allPatches)
|
patchesBytes, err := SerializePatches(allPatches)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mw.logger.Printf("Error occerred while serializing JSONPathch: %v", err)
|
mw.logger.Printf("Error occerred while serializing JSONPathch: %v", err)
|
||||||
return errorToResponse(err, true)
|
return errorToAdmissionResponse(err, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &v1beta1.AdmissionResponse{
|
return &v1beta1.AdmissionResponse{
|
||||||
|
@ -108,12 +108,14 @@ func (mw *MutationWebhook) applyRule(request *v1beta1.AdmissionRequest, rule typ
|
||||||
return rulePatches, err
|
return rulePatches, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets patches from "patch" section in PolicyRule
|
||||||
func (mw *MutationWebhook) applyRulePatches(request *v1beta1.AdmissionRequest, rule types.PolicyRule) ([]types.PolicyPatch, error) {
|
func (mw *MutationWebhook) applyRulePatches(request *v1beta1.AdmissionRequest, rule types.PolicyRule) ([]types.PolicyPatch, error) {
|
||||||
var patches []types.PolicyPatch
|
var patches []types.PolicyPatch
|
||||||
patches = append(patches, rule.Patches...)
|
patches = append(patches, rule.Patches...)
|
||||||
return patches, nil
|
return patches, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Applies "configMapGenerator" and "secretGenerator" described in PolicyRule
|
||||||
func (mw *MutationWebhook) applyRuleGenerators(request *v1beta1.AdmissionRequest, rule types.PolicyRule) error {
|
func (mw *MutationWebhook) applyRuleGenerators(request *v1beta1.AdmissionRequest, rule types.PolicyRule) error {
|
||||||
// configMapGenerator and secretGenerator can be applied only to namespaces
|
// configMapGenerator and secretGenerator can be applied only to namespaces
|
||||||
if request.Kind.Kind == "Namespace" {
|
if request.Kind.Kind == "Namespace" {
|
||||||
|
@ -156,7 +158,7 @@ func (mw *MutationWebhook) applyConfigGenerator(generator *types.PolicyConfigGen
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SerializePatches converts JSON patches to byte array
|
// Converts JSON patches to byte array
|
||||||
func SerializePatches(patches []types.PolicyPatch) ([]byte, error) {
|
func SerializePatches(patches []types.PolicyPatch) ([]byte, error) {
|
||||||
var result []byte
|
var result []byte
|
||||||
if len(patches) == 0 {
|
if len(patches) == 0 {
|
||||||
|
@ -183,7 +185,7 @@ func SerializePatches(patches []types.PolicyPatch) ([]byte, error) {
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func errorToResponse(err error, allowed bool) *v1beta1.AdmissionResponse {
|
func errorToAdmissionResponse(err error, allowed bool) *v1beta1.AdmissionResponse {
|
||||||
return &v1beta1.AdmissionResponse{
|
return &v1beta1.AdmissionResponse{
|
||||||
Result: &metav1.Status{
|
Result: &metav1.Status{
|
||||||
Message: err.Error(),
|
Message: err.Error(),
|
||||||
|
|
|
@ -1,38 +1,38 @@
|
||||||
package webhooks_test
|
package webhooks_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func assertEq(t *testing.T, expected interface{}, actual interface{}) {
|
func assertEq(t *testing.T, expected interface{}, actual interface{}) {
|
||||||
if expected != actual {
|
if expected != actual {
|
||||||
t.Errorf("%s != %s", expected, actual)
|
t.Errorf("%s != %s", expected, actual)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertNe(t *testing.T, expected interface{}, actual interface{}) {
|
func assertNe(t *testing.T, expected interface{}, actual interface{}) {
|
||||||
if expected == actual {
|
if expected == actual {
|
||||||
t.Errorf("%s != %s", expected, actual)
|
t.Errorf("%s != %s", expected, actual)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertEqDataImpl(t *testing.T, expected, actual []byte, formatModifier string) {
|
func assertEqDataImpl(t *testing.T, expected, actual []byte, formatModifier string) {
|
||||||
if len(expected) != len(actual) {
|
if len(expected) != len(actual) {
|
||||||
t.Errorf("len(expected) != len(actual): %d != %d\n1:"+formatModifier+"\n2:"+formatModifier, len(expected), len(actual), expected, actual)
|
t.Errorf("len(expected) != len(actual): %d != %d\n1:"+formatModifier+"\n2:"+formatModifier, len(expected), len(actual), expected, actual)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx, val := range actual {
|
for idx, val := range actual {
|
||||||
if val != expected[idx] {
|
if val != expected[idx] {
|
||||||
t.Errorf("Slices not equal at index %d:\n1:"+formatModifier+"\n2:"+formatModifier, idx, expected, actual)
|
t.Errorf("Slices not equal at index %d:\n1:"+formatModifier+"\n2:"+formatModifier, idx, expected, actual)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertEqData(t *testing.T, expected, actual []byte) {
|
func assertEqData(t *testing.T, expected, actual []byte) {
|
||||||
assertEqDataImpl(t, expected, actual, "%x")
|
assertEqDataImpl(t, expected, actual, "%x")
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertEqStringAndData(t *testing.T, str string, data []byte) {
|
func assertEqStringAndData(t *testing.T, str string, data []byte) {
|
||||||
assertEqDataImpl(t, []byte(str), data, "%s")
|
assertEqDataImpl(t, []byte(str), data, "%s")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue