diff --git a/.codeclimate.yml b/.codeclimate.yml deleted file mode 100644 index 95a96cfddb..0000000000 --- a/.codeclimate.yml +++ /dev/null @@ -1,18 +0,0 @@ -engines: - govet: - enabled: true - golint: - enabled: false - gofmt: - enabled: true - -ratings: - paths: - - "**.go" - -exclude_paths: -- documentation/ -- definitions -- gh-pages -- samples -- scripts \ No newline at end of file diff --git a/.golangci.yml b/.golangci.yml deleted file mode 100644 index a589a168f3..0000000000 --- a/.golangci.yml +++ /dev/null @@ -1,17 +0,0 @@ -linters: - enable: - - gosec - - errcheck - - gosimple - - bodyclose - - staticcheck - disable: - - ineffassign - - deadcode - - unused - - structcheck - -run: - skip-files: - - ".+_test.go" - - ".+_test_.+.go" \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 3f9676cdb2..917a026a0c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,11 +2,6 @@ language: go go: - "1.13" -cache: - directories: - - $HOME/.cache/go-build - - $GOPATH/pkg/mod - # safelist branches: only: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9941e08dd5..be104b5dc2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1 @@ -# Contributing to Kyverno - -## Code Style - -We follow the community provided standard [code structure](https://github.com/golang-standards/project-layout). - -See : https://github.com/nirmata/kyverno#contributing +See: https://github.com/nirmata/kyverno#contributing diff --git a/README.md b/README.md index 2335a3b78f..df3ec092d1 100644 --- a/README.md +++ b/README.md @@ -171,6 +171,5 @@ See [Milestones](https://github.com/nirmata/kyverno/milestones) and [Issues](htt Thanks for your interest in contributing! * Please review and agree to abide with the [Code of Conduct](/CODE_OF_CONDUCT.md) before contributing. - * We encourage all contributions and encourage you to read our [contribution guidelines](./CONTRIBUTING.md). * See the [Wiki](https://github.com/nirmata/kyverno/wiki) for developer documentation. * Browse through the [open issues](https://github.com/nirmata/kyverno/issues) diff --git a/cmd/initContainer/main.go b/cmd/initContainer/main.go index e9e377cb7f..9c5a9141ba 100644 --- a/cmd/initContainer/main.go +++ b/cmd/initContainer/main.go @@ -5,27 +5,23 @@ package main import ( "flag" - "fmt" "os" "regexp" "strconv" "sync" "time" + "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/config" client "github.com/nirmata/kyverno/pkg/dclient" "github.com/nirmata/kyverno/pkg/signal" "k8s.io/apimachinery/pkg/api/errors" rest "k8s.io/client-go/rest" clientcmd "k8s.io/client-go/tools/clientcmd" - "k8s.io/klog" - "k8s.io/klog/klogr" - "sigs.k8s.io/controller-runtime/pkg/log" ) var ( kubeconfig string - setupLog = log.Log.WithName("setup") ) const ( @@ -34,30 +30,20 @@ const ( ) func main() { - klog.InitFlags(nil) - log.SetLogger(klogr.New()) - // arguments - flag.StringVar(&kubeconfig, "kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.") - if err := flag.Set("v", "2"); err != nil { - klog.Fatalf("failed to set log level: %v", err) - } - flag.Parse() - + defer glog.Flush() // os signal handler stopCh := signal.SetupSignalHandler() // create client config clientConfig, err := createClientConfig(kubeconfig) if err != nil { - setupLog.Error(err, "Failed to build kubeconfig") - os.Exit(1) + glog.Fatalf("Error building kubeconfig: %v\n", err) } // DYNAMIC CLIENT // - client for all registered resources - client, err := client.NewClient(clientConfig, 10*time.Second, stopCh, log.Log) + client, err := client.NewClient(clientConfig, 10*time.Second, stopCh) if err != nil { - setupLog.Error(err, "Failed to create client") - os.Exit(1) + glog.Fatalf("Error creating client: %v\n", err) } // Exit for unsupported version of kubernetes cluster @@ -92,46 +78,53 @@ func main() { for err := range merge(done, stopCh, p1, p2) { if err != nil { failure = true - log.Log.Error(err, "failed to cleanup resource") + glog.Errorf("failed to cleanup: %v", err) } } // if there is any failure then we fail process if failure { - log.Log.Info("failed to cleanup webhook configurations") + glog.Errorf("failed to cleanup webhook configurations") os.Exit(1) } } +func init() { + // arguments + flag.StringVar(&kubeconfig, "kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.") + flag.Set("logtostderr", "true") + flag.Set("stderrthreshold", "WARNING") + flag.Set("v", "2") + flag.Parse() +} + func removeWebhookIfExists(client *client.Client, kind string, name string) error { - logger := log.Log.WithName("removeExistingWebhook").WithValues("kind", kind, "name", name) var err error // Get resource _, err = client.GetResource(kind, "", name) if errors.IsNotFound(err) { - logger.V(4).Info("resource not found") + glog.V(4).Infof("%s(%s) not found", name, kind) return nil } if err != nil { - logger.Error(err, "failed to get resource") + glog.Errorf("failed to get resource %s(%s)", name, kind) return err } // Delete resource err = client.DeleteResource(kind, "", name, false) if err != nil { - logger.Error(err, "failed to delete resource") + glog.Errorf("failed to delete resource %s(%s)", name, kind) return err } - logger.Info("removed the resource") + glog.Infof("cleaned up resource %s(%s)", name, kind) return nil } func createClientConfig(kubeconfig string) (*rest.Config, error) { - logger := log.Log if kubeconfig == "" { - logger.Info("Using in-cluster configuration") + glog.Info("Using in-cluster configuration") return rest.InClusterConfig() } - logger.Info(fmt.Sprintf("Using configuration from '%s'", kubeconfig)) + glog.Infof("Using configuration from '%s'", kubeconfig) return clientcmd.BuildConfigFromFlags("", kubeconfig) } @@ -170,7 +163,6 @@ func gen(done <-chan struct{}, stopCh <-chan struct{}, requests ...request) <-ch // processes the requests func process(client *client.Client, done <-chan struct{}, stopCh <-chan struct{}, requests <-chan request) <-chan error { - logger := log.Log.WithName("process") out := make(chan error) go func() { defer close(out) @@ -178,10 +170,10 @@ func process(client *client.Client, done <-chan struct{}, stopCh <-chan struct{} select { case out <- removeWebhookIfExists(client, req.kind, req.name): case <-done: - logger.Info("done") + println("done process") return case <-stopCh: - logger.Info("shutting down") + println("shutting down process") return } } @@ -191,7 +183,6 @@ func process(client *client.Client, done <-chan struct{}, stopCh <-chan struct{} // waits for all processes to be complete and merges result func merge(done <-chan struct{}, stopCh <-chan struct{}, processes ...<-chan error) <-chan error { - logger := log.Log.WithName("merge") var wg sync.WaitGroup out := make(chan error) // gets the output from each process @@ -201,10 +192,10 @@ func merge(done <-chan struct{}, stopCh <-chan struct{}, processes ...<-chan err select { case out <- err: case <-done: - logger.Info("done") + println("done merge") return case <-stopCh: - logger.Info("shutting down") + println("shutting down merge") return } } @@ -224,37 +215,30 @@ func merge(done <-chan struct{}, stopCh <-chan struct{}, processes ...<-chan err } func isVersionSupported(client *client.Client) { - logger := log.Log serverVersion, err := client.DiscoveryClient.GetServerVersion() if err != nil { - logger.Error(err, "Failed to get kubernetes server version") - os.Exit(1) + glog.Fatalf("Failed to get kubernetes server version: %v\n", err) } exp := regexp.MustCompile(`v(\d*).(\d*).(\d*)`) groups := exp.FindAllStringSubmatch(serverVersion.String(), -1) if len(groups) != 1 || len(groups[0]) != 4 { - logger.Error(err, "Failed to extract kubernetes server version", "serverVersion", serverVersion) - os.Exit(1) + glog.Fatalf("Failed to extract kubernetes server version: %v.err %v\n", serverVersion, err) } // convert string to int // assuming the version are always intergers major, err := strconv.Atoi(groups[0][1]) if err != nil { - logger.Error(err, "Failed to extract kubernetes major server version", "serverVersion", serverVersion) - os.Exit(1) + glog.Fatalf("Failed to extract kubernetes major server version: %v.err %v\n", serverVersion, err) } minor, err := strconv.Atoi(groups[0][2]) if err != nil { - logger.Error(err, "Failed to extract kubernetes minor server version", "serverVersion", serverVersion) - os.Exit(1) + glog.Fatalf("Failed to extract kubernetes minor server version: %v.err %v\n", serverVersion, err) } sub, err := strconv.Atoi(groups[0][3]) if err != nil { - logger.Error(err, "Failed to extract kubernetes sub minor server version", "serverVersion", serverVersion) - os.Exit(1) + glog.Fatalf("Failed to extract kubernetes sub minor server version:%v. err %v\n", serverVersion, err) } if major <= 1 && minor <= 12 && sub < 7 { - logger.Info("Unsupported kubernetes server version %s. Kyverno is supported from version v1.12.7+", "serverVersion", serverVersion) - os.Exit(1) + glog.Fatalf("Unsupported kubernetes server version %s. Kyverno is supported from version v1.12.7+", serverVersion) } } diff --git a/cmd/kyverno/main.go b/cmd/kyverno/main.go index 3bb05a3b39..7087d41832 100644 --- a/cmd/kyverno/main.go +++ b/cmd/kyverno/main.go @@ -3,12 +3,11 @@ package main import ( "context" "flag" - "fmt" - "os" "time" "github.com/nirmata/kyverno/pkg/openapi" + "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/checker" kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned" kyvernoinformer "github.com/nirmata/kyverno/pkg/client/informers/externalversions" @@ -28,9 +27,6 @@ import ( "github.com/nirmata/kyverno/pkg/webhooks" webhookgenerate "github.com/nirmata/kyverno/pkg/webhooks/generate" kubeinformers "k8s.io/client-go/informers" - "k8s.io/klog" - "k8s.io/klog/klogr" - log "sigs.k8s.io/controller-runtime/pkg/log" ) var ( @@ -42,38 +38,20 @@ var ( // will be removed in future and the configuration will be set only via configmaps filterK8Resources string // User FQDN as CSR CN - fqdncn bool - setupLog = log.Log.WithName("setup") + fqdncn bool ) func main() { - klog.InitFlags(nil) - log.SetLogger(klogr.New()) - flag.StringVar(&filterK8Resources, "filterK8Resources", "", "k8 resource in format [kind,namespace,name] where policy is not evaluated by the admission webhook. example --filterKind \"[Deployment, kyverno, kyverno]\" --filterKind \"[Deployment, kyverno, kyverno],[Events, *, *]\"") - flag.IntVar(&webhookTimeout, "webhooktimeout", 3, "timeout for webhook configurations") - flag.StringVar(&kubeconfig, "kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.") - flag.StringVar(&serverIP, "serverIP", "", "IP address where Kyverno controller runs. Only required if out-of-cluster.") - flag.StringVar(&runValidationInMutatingWebhook, "runValidationInMutatingWebhook", "", "Validation will also be done using the mutation webhook, set to 'true' to enable. Older kubernetes versions do not work properly when a validation webhook is registered.") - if err := flag.Set("v", "2"); err != nil { - setupLog.Error(err, "failed to set log level") - os.Exit(1) - } - - // Generate CSR with CN as FQDN due to https://github.com/nirmata/kyverno/issues/542 - flag.BoolVar(&fqdncn, "fqdn-as-cn", false, "use FQDN as Common Name in CSR") - - flag.Parse() - - version.PrintVersionInfo(log.Log) + defer glog.Flush() + version.PrintVersionInfo() // cleanUp Channel cleanUp := make(chan struct{}) // handle os signals stopCh := signal.SetupSignalHandler() // CLIENT CONFIG - clientConfig, err := config.CreateClientConfig(kubeconfig, log.Log) + clientConfig, err := config.CreateClientConfig(kubeconfig) if err != nil { - setupLog.Error(err, "Failed to build kubeconfig") - os.Exit(1) + glog.Fatalf("Error building kubeconfig: %v\n", err) } // KYVENO CRD CLIENT @@ -82,33 +60,29 @@ func main() { // - PolicyViolation pclient, err := kyvernoclient.NewForConfig(clientConfig) if err != nil { - setupLog.Error(err, "Failed to create client") - os.Exit(1) + glog.Fatalf("Error creating client: %v\n", err) } // DYNAMIC CLIENT // - client for all registered resources // - invalidate local cache of registered resource every 10 seconds - client, err := dclient.NewClient(clientConfig, 10*time.Second, stopCh, log.Log) + client, err := dclient.NewClient(clientConfig, 10*time.Second, stopCh) if err != nil { - setupLog.Error(err, "Failed to create client") - os.Exit(1) + glog.Fatalf("Error creating client: %v\n", err) } // CRD CHECK // - verify if the CRD for Policy & PolicyViolation are available - if !utils.CRDInstalled(client.DiscoveryClient, log.Log) { - setupLog.Error(fmt.Errorf("pre-requisite CRDs not installed"), "Failed to create watch on kyverno CRDs") - os.Exit(1) + if !utils.CRDInstalled(client.DiscoveryClient) { + glog.Fatalf("Required CRDs unavailable") } // KUBERNETES CLIENT kubeClient, err := utils.NewKubeClient(clientConfig) if err != nil { - setupLog.Error(err, "Failed to create kubernetes client") - os.Exit(1) + glog.Fatalf("Error creating kubernetes client: %v\n", err) } // TODO(shuting): To be removed for v1.2.0 - utils.CleanupOldCrd(client, log.Log) + utils.CleanupOldCrd(client) // KUBERNETES RESOURCES INFORMER // watches namespace resource @@ -125,18 +99,16 @@ func main() { clientConfig, client, serverIP, - int32(webhookTimeout), - log.Log) + int32(webhookTimeout)) // Resource Mutating Webhook Watcher - lastReqTime := checker.NewLastReqTime(log.Log.WithName("LastReqTime")) + lastReqTime := checker.NewLastReqTime() rWebhookWatcher := webhookconfig.NewResourceWebhookRegister( lastReqTime, kubeInformer.Admissionregistration().V1beta1().MutatingWebhookConfigurations(), kubeInformer.Admissionregistration().V1beta1().ValidatingWebhookConfigurations(), webhookRegistrationClient, runValidationInMutatingWebhook, - log.Log.WithName("ResourceWebhookRegister"), ) // KYVERNO CRD INFORMER @@ -155,19 +127,16 @@ func main() { configData := config.NewConfigData( kubeClient, kubeInformer.Core().V1().ConfigMaps(), - filterK8Resources, - log.Log.WithName("ConfigData"), - ) + filterK8Resources) // Policy meta-data store - policyMetaStore := policystore.NewPolicyStore(pInformer.Kyverno().V1().ClusterPolicies(), log.Log.WithName("PolicyStore")) + policyMetaStore := policystore.NewPolicyStore(pInformer.Kyverno().V1().ClusterPolicies()) // EVENT GENERATOR // - generate event with retry mechanism egen := event.NewEventGenerator( client, - pInformer.Kyverno().V1().ClusterPolicies(), - log.Log.WithName("EventGenerator")) + pInformer.Kyverno().V1().ClusterPolicies()) // Policy Status Handler - deals with all logic related to policy status statusSync := policystatus.NewSync( @@ -180,9 +149,7 @@ func main() { client, pInformer.Kyverno().V1().ClusterPolicyViolations(), pInformer.Kyverno().V1().PolicyViolations(), - statusSync.Listener, - log.Log.WithName("PolicyViolationGenerator"), - ) + statusSync.Listener) // POLICY CONTROLLER // - reconciliation policy and policy violation @@ -198,16 +165,13 @@ func main() { egen, pvgen, policyMetaStore, - rWebhookWatcher, - log.Log.WithName("PolicyController"), - ) + rWebhookWatcher) if err != nil { - setupLog.Error(err, "Failed to create policy controller") - os.Exit(1) + glog.Fatalf("error creating policy controller: %v\n", err) } // GENERATE REQUEST GENERATOR - grgen := webhookgenerate.NewGenerator(pclient, stopCh, log.Log.WithName("GenerateRequestGenerator")) + grgen := webhookgenerate.NewGenerator(pclient, stopCh) // GENERATE CONTROLLER // - applies generate rules on resources based on generate requests created by webhook @@ -220,7 +184,6 @@ func main() { pvgen, kubedynamicInformer, statusSync.Listener, - log.Log.WithName("GenerateController"), ) // GENERATE REQUEST CLEANUP // -- cleans up the generate requests that have not been processed(i.e. state = [Pending, Failed]) for more than defined timeout @@ -230,14 +193,12 @@ func main() { pInformer.Kyverno().V1().ClusterPolicies(), pInformer.Kyverno().V1().GenerateRequests(), kubedynamicInformer, - log.Log.WithName("GenerateCleanUpController"), ) // CONFIGURE CERTIFICATES tlsPair, err := client.InitTLSPemPair(clientConfig, fqdncn) if err != nil { - setupLog.Error(err, "Failed to initialize TLS key/certificate pair") - os.Exit(1) + glog.Fatalf("Failed to initialize TLS key/certificate pair: %v\n", err) } // WEBHOOK REGISTRATION @@ -246,8 +207,7 @@ func main() { // resource webhook confgiuration is generated dynamically in the webhook server and policy controller // based on the policy resources created if err = webhookRegistrationClient.Register(); err != nil { - setupLog.Error(err, "Failed to register Admission webhooks") - os.Exit(1) + glog.Fatalf("Failed registering Admission Webhooks: %v\n", err) } // Sync openAPI definitions of resources @@ -274,12 +234,9 @@ func main() { pvgen, grgen, rWebhookWatcher, - cleanUp, - log.Log.WithName("WebhookServer"), - ) + cleanUp) if err != nil { - setupLog.Error(err, "Failed to create webhook server") - os.Exit(1) + glog.Fatalf("Unable to create webhook server: %v\n", err) } // Start the components pInformer.Start(stopCh) @@ -317,5 +274,18 @@ func main() { // resource cleanup // remove webhook configurations <-cleanUp - setupLog.Info("Kyverno shutdown successful") + glog.Info("successful shutdown of kyverno controller") +} + +func init() { + flag.StringVar(&filterK8Resources, "filterK8Resources", "", "k8 resource in format [kind,namespace,name] where policy is not evaluated by the admission webhook. example --filterKind \"[Deployment, kyverno, kyverno]\" --filterKind \"[Deployment, kyverno, kyverno],[Events, *, *]\"") + flag.IntVar(&webhookTimeout, "webhooktimeout", 3, "timeout for webhook configurations") + flag.StringVar(&kubeconfig, "kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.") + flag.StringVar(&serverIP, "serverIP", "", "IP address where Kyverno controller runs. Only required if out-of-cluster.") + flag.StringVar(&runValidationInMutatingWebhook, "runValidationInMutatingWebhook", "", "Validation will also be done using the mutation webhook, set to 'true' to enable. Older kubernetes versions do not work properly when a validation webhook is registered.") + + // Generate CSR with CN as FQDN due to https://github.com/nirmata/kyverno/issues/542 + flag.BoolVar(&fqdncn, "fqdn-as-cn", false, "use FQDN as Common Name in CSR") + config.LogDefaultFlags() + flag.Parse() } diff --git a/api/swaggerDoc.go b/data/swaggerDoc.go similarity index 100% rename from api/swaggerDoc.go rename to data/swaggerDoc.go diff --git a/definitions/install.yaml b/definitions/install.yaml index 3e7825e878..be688d3d97 100644 --- a/definitions/install.yaml +++ b/definitions/install.yaml @@ -109,6 +109,8 @@ spec: type: string exclude: type: object + required: + - resources properties: roles: type: array diff --git a/definitions/install_debug.yaml b/definitions/install_debug.yaml index bf9194246d..efc62b5a44 100644 --- a/definitions/install_debug.yaml +++ b/definitions/install_debug.yaml @@ -109,6 +109,8 @@ spec: type: string exclude: type: object + required: + - resources properties: roles: type: array diff --git a/go.mod b/go.mod index f5ba937e12..593b08fdef 100644 --- a/go.mod +++ b/go.mod @@ -5,37 +5,39 @@ go 1.13 require ( github.com/cenkalti/backoff v2.2.1+incompatible github.com/evanphx/json-patch v4.5.0+incompatible - github.com/go-logr/logr v0.1.0 + github.com/gogo/protobuf v1.3.1 // indirect + github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7 // indirect github.com/googleapis/gnostic v0.3.1 + github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/hashicorp/golang-lru v0.5.3 // indirect github.com/imdario/mergo v0.3.8 // indirect github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af github.com/json-iterator/go v1.1.9 // indirect github.com/minio/minio v0.0.0-20200114012931-30922148fbb5 + github.com/ory/go-acc v0.1.0 // indirect + github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/spf13/cobra v0.0.5 + github.com/spf13/pflag v1.0.5 // indirect github.com/tevino/abool v0.0.0-20170917061928-9b9efcf221b5 + golang.org/x/crypto v0.0.0-20200109152110-61a87790db17 // indirect golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 // indirect golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect golang.org/x/sys v0.0.0-20200113162924-86b910548bc1 // indirect golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect google.golang.org/appengine v1.6.5 // indirect - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect - gopkg.in/yaml.v2 v2.2.8 + gopkg.in/inf.v0 v0.9.1 // indirect + gopkg.in/yaml.v2 v2.2.7 gotest.tools v2.2.0+incompatible - k8s.io/api v0.17.4 - k8s.io/apimachinery v0.17.4 - k8s.io/cli-runtime v0.17.4 - k8s.io/client-go v0.17.4 - k8s.io/klog v1.0.0 - k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c + k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b + k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d + k8s.io/cli-runtime v0.0.0-20191004110135-b9eb767d2e1a + k8s.io/client-go v11.0.1-0.20190516230509-ae8359b20417+incompatible + k8s.io/klog v1.0.0 // indirect + k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a k8s.io/utils v0.0.0-20200109141947-94aeca20bf09 // indirect - sigs.k8s.io/controller-runtime v0.5.0 + sigs.k8s.io/kustomize v2.0.3+incompatible // indirect ) // Added for go1.13 migration https://github.com/golang/go/issues/32805 -replace ( - github.com/gorilla/rpc v1.2.0+incompatible => github.com/gorilla/rpc v1.2.0 - k8s.io/code-generator => k8s.io/code-generator v0.0.0-20200306081859-6a048a382944 - k8s.io/component-base => k8s.io/component-base v0.0.0-20190612130303-4062e14deebe -) +replace github.com/gorilla/rpc v1.2.0+incompatible => github.com/gorilla/rpc v1.2.0 diff --git a/go.sum b/go.sum index 99c5af7f3b..9b6fc04130 100644 --- a/go.sum +++ b/go.sum @@ -15,13 +15,6 @@ github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiU github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-autorest v11.7.1+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= -github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= -github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= -github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= @@ -33,29 +26,21 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.0.0 h1:0GoNN3taZV6QI81IXgCbxMyEaJDXMSIjArYBCYzVVvs= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2 h1:JCHLVE3B+kJde7bIEo5N4J+ZbLhp0J1Fs+ulyRws4gE= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/sarama v1.24.1/go.mod h1:fGP8eQ6PugKEI0iUETYYtnP6d1pH/bdDMTel1X5ajsU= github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/ajg/form v0.0.0-20160822230020-523a5da1a92f/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= github.com/alecthomas/participle v0.2.1/go.mod h1:SW6HZGeZgSIpcUWX3fXpfZhuaWHnmoD5KCVaqSaNTkk= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8= -github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-sdk-go v1.20.21/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-sdk-go v1.23.19/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= github.com/aws/aws-xray-sdk-go v0.9.4/go.mod h1:XtMKdBQfpVut+tJEwI7+dJFRxxRdxHDyVNp2tHXRq04= @@ -65,7 +50,6 @@ github.com/beevik/ntp v0.2.0/go.mod h1:hIHWr+l3+/clUnF44zdK+CWW7fO8dR5cIylAQ76NR github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= -github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps= github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= @@ -80,7 +64,6 @@ github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0= github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= @@ -90,16 +73,11 @@ github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkE github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.12+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= -github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= -github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= @@ -107,13 +85,9 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/djherbis/atime v1.0.0/go.mod h1:5W+KBIuTwVGcqjIfaTwt+KSYX1o6uep8dtevevQP/f8= -github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v0.0.0-20180713052910-9f541cc9db5d/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= @@ -122,14 +96,9 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1 github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts= github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= -github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20181003060214-f58a169a71a5/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633 h1:H2pdYOb3KQ1/YsqVWoWNLQO+fusocsw354rqGTZtAgw= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk= -github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/evanphx/json-patch v0.0.0-20190203023257-5858425f7550/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= @@ -144,68 +113,21 @@ github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2H github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= -github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= -github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-bindata/go-bindata v3.1.1+incompatible/go.mod h1:xK8Dsgwmeed+BBsSy2XTopBn/8uK2HWuGSnA11C3Joo= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logr/logr v0.1.0 h1:M1Tv3VzNlEHg6uyACnRdtrploV2P7wZqH8BoQMtz0cg= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/zapr v0.1.0/go.mod h1:tabnROwaDl0UNxkVeFRbY8bwB37GwRv0P8lg6aAiEnk= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= -github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= -github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= -github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= -github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk= -github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU= -github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= -github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0= -github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1 h1:wSt/4CYxs70xbATrGXhokKF1i0tZjENLOo1ioIO13zk= github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0= -github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= -github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= -github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9 h1:tF+augKRWlWx0J0B7ZyyKSiTyV6E1zZe+7b3qQlcEf8= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= -github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= -github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= -github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o= -github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= -github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= -github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs= -github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk= -github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA= -github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64= -github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501 h1:C1JKChikHGpXwT5UQDFaryIpDtyyGL/CR6C2kB7F1oc= github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc= -github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= -github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= -github.com/go-openapi/spec v0.19.3 h1:0XRyw8kguri6Yw4SxhsQA/atC88yqrk0+G4YhI2wabc= -github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= -github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= -github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= -github.com/go-openapi/strfmt v0.19.3/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87 h1:zP3nY8Tk2E6RTkqGYrarZXuzh+ffyLDljLxCy1iJw80= github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I= -github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= -github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= -github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= -github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= -github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -379,18 +301,14 @@ github.com/gobuffalo/x v0.0.0-20181003152136-452098b06085/go.mod h1:WevpGD+5YOre github.com/gobuffalo/x v0.0.0-20181007152206-913e47c59ca7/go.mod h1:9rDPXaB3kXdKWzMc4odGQQdG2e2DIEmANy5aSJ9yesY= github.com/gofrs/uuid v3.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/protobuf v0.0.0-20171007142547-342cbe0a0415/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/golang/gddo v0.0.0-20180828051604-96d2a289f41e/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4= github.com/golang/gddo v0.0.0-20190904175337-72a348e765d2/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7 h1:5ZkaAPbicIKTF2I64qf5Fh8Aa83Q/dnOafMYV0OMwjA= @@ -415,7 +333,6 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= -github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= @@ -424,13 +341,11 @@ github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OI github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.0 h1:Jf4mxPC/ziBnoPIdpQdPJ9OeiomAUHLvxmPRSPH9m4s= github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk= github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU= -github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gopherjs/gopherjs v0.0.0-20181004151105-1babbf986f6f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20190328170749-bb2674552d8f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -443,12 +358,9 @@ github.com/gorilla/rpc v1.2.0/go.mod h1:V4h9r+4sF5HnzqbwIez0fKSpANP0zlYd3qR7p36j github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= github.com/gorilla/sessions v1.1.2/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= github.com/gorilla/sessions v1.1.3/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= -github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= @@ -456,7 +368,6 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= @@ -488,8 +399,6 @@ github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvh github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg= @@ -506,10 +415,7 @@ github.com/joho/godotenv v1.2.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqx github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v0.0.0-20180701071628-ab8a2e0c74be/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= @@ -539,14 +445,11 @@ github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kurin/blazer v0.5.4-0.20190613185654-cf2f27cc0be3/go.mod h1:4FCXMUWo9DllR2Do4TtBd377ezyAJ51vB5uTBjt0pGU= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= -github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/luna-duclos/instrumentedsql v1.1.2/go.mod h1:4LGbEqDnopzNAiyxPPDXhLspyunZxgPTMJBKtC6U0BQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= @@ -554,12 +457,6 @@ github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20180730094502-03f2033d19d5 h1:0x4qcEHDpruK6ML/m/YSlFUUu0UpRD3I2PHsNCuGnyA= github.com/mailru/easyjson v0.0.0-20180730094502-03f2033d19d5/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM= -github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/markbates/deplist v1.0.4/go.mod h1:gRRbPbbuA8TmMiRvaOzUlRfzfjeCCBqX2A6arxN01MM= github.com/markbates/deplist v1.0.5/go.mod h1:gRRbPbbuA8TmMiRvaOzUlRfzfjeCCBqX2A6arxN01MM= github.com/markbates/going v1.0.2/go.mod h1:UWCk3zm0UKefHZ7l8BNqi26UyiEMniznk8naLdTcy6c= @@ -586,7 +483,6 @@ github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= @@ -629,9 +525,7 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwd github.com/monoculum/formam v0.0.0-20180901015400-4e68be1d79ba/go.mod h1:RKgILGEJq24YyJ2ban8EO0RUVSJlF1pGsEvoLEACr/Q= github.com/moul/http2curl v0.0.0-20170919181001-9ac6cf4d929b/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/nats-io/gnatsd v1.4.1/go.mod h1:nqco77VO78hLCJpIcVfygDP2rPGfsEHkGTUk94uh5DQ= github.com/nats-io/go-nats v1.7.2/go.mod h1:+t7RHT5ApZebkrQdnn6AhQJmhJJiKAvJUio1PiiCtj0= github.com/nats-io/go-nats-streaming v0.4.4/go.mod h1:gfq4R3c9sKAINOpelo0gn/b9QDMBZnmrttcsNF+lqyo= @@ -651,21 +545,15 @@ github.com/nsqio/go-nsq v1.0.7/go.mod h1:XP5zaUs3pqf+Q71EqUJs3HYfBIqfK6G83WQMdNN github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= github.com/oleiade/reflections v1.0.0/go.mod h1:RbATFBbKYkVdqmSFtx13Bb/tVhR0lgOBXunWTZKeL4w= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c h1:Hww8mOyEKTeON4bZn7FrlLismspbPc1teNRUVH7wLQ8= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c h1:eSfnfIuwhxZyULg1NNuZycJcYkjYVGYe7FczwQReM6U= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v0.0.0-20190113212917-5533ce8a0da3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= @@ -703,12 +591,10 @@ github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= -github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -716,12 +602,10 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20190704165056-9c2d0518ed81/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= @@ -782,7 +666,6 @@ github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb6 github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -794,7 +677,6 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= @@ -808,7 +690,6 @@ github.com/tidwall/gjson v1.3.5/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJH github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/sjson v1.0.4/go.mod h1:bURseu1nuBkFpIES5cz6zBtjmYeOQmEESshn7VpF15Y= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/uber-go/atomic v1.3.2/go.mod h1:/Ct5t2lcmbJ4OSe/waGBoaVvVqtO0bmtfVNex1PFV8g= @@ -820,10 +701,8 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT github.com/ugorji/go/codec v1.1.5-pre/go.mod h1:tULtS6Gy1AE1yCENaw4Vb//HLH5njI2tfCQDUqRd8fI= github.com/unrolled/secure v0.0.0-20180918153822-f340ee86eb8b/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA= github.com/unrolled/secure v0.0.0-20181005190816-ff9db2ff917f/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= -github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I= github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -833,10 +712,6 @@ github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c/go.mod h1:UrdRz5enIKZ63M github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= -go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA= @@ -859,22 +734,15 @@ golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85/go.mod h1:6SG95UA2DQfeDnf golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190102171810-8d7daa0c54b3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190513172903-22d7a77e9e5f/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191117063200-497ca9f6d64f/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200109152110-61a87790db17 h1:nVJ3guKA9qdkEQ3TUdXI9QSINo2CUPM/cySEvw2w8I0= golang.org/x/crypto v0.0.0-20200109152110-61a87790db17/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo= -golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= @@ -903,22 +771,16 @@ golang.org/x/net v0.0.0-20181207154023-610586996380/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190206173232-65e2d4e15006/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -960,11 +822,9 @@ golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190116161447-11f53e031339/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -972,10 +832,8 @@ golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191105231009-c1f44814a5cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1 h1:gZpLHxUX5BdYLA08Lj4YCJNN/jk7KtquiArPoeX0WvA= @@ -986,7 +844,6 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3 golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= @@ -1018,7 +875,6 @@ golang.org/x/tools v0.0.0-20190104182027-498d95493402/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190111214448-fc1d57b08d7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190118193359-16909d206f00/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -1028,14 +884,9 @@ golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624190245-7f2218787638/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190711191110-9a621aea19f8/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= -golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.0.1/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.5.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -1067,7 +918,6 @@ google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiq google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk= @@ -1075,15 +925,12 @@ gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUy gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw= gopkg.in/gorp.v1 v1.7.2/go.mod h1:Wo3h+DBQZIxATwftsglhdD/62zRFPhGhTiu5jUJmCaw= -gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -1095,7 +942,6 @@ gopkg.in/jcmturner/gokrb5.v7 v7.2.3/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuv gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8= gopkg.in/ldap.v3 v3.0.3/go.mod h1:oxD7NyBuxchC+SgJDE1Q5Od05eGt29SDQVBmV+HYbzw= gopkg.in/mail.v2 v2.0.0-20180731213649-a0242b2233b4/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw= -gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/olivere/elastic.v5 v5.0.80/go.mod h1:uhHoB4o3bvX5sorxBU29rPcmBQdV2Qfg0FBrx5D6pV0= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.1.9/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= @@ -1109,8 +955,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1119,53 +963,24 @@ honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b h1:aBGgKJUM9Hk/3AE8WaZIApnTxG35kbuQba2w+SXqezo= k8s.io/api v0.0.0-20190409021203-6e4e0e4f393b/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA= -k8s.io/api v0.17.2/go.mod h1:BS9fjjLc4CMuqfSO8vgbHPKMt5+SF0ET6u/RVDihTo4= -k8s.io/api v0.17.4 h1:HbwOhDapkguO8lTAE8OX3hdF2qp8GtpC9CW/MQATXXo= -k8s.io/api v0.17.4/go.mod h1:5qxx6vjmwUVG2nHQTKGlLts8Tbok8PzHl4vHtVFuZCA= -k8s.io/apiextensions-apiserver v0.17.2/go.mod h1:4KdMpjkEjjDI2pPfBA15OscyNldHWdBCfsWMDWAmSTs= k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d h1:Jmdtdt1ZnoGfWWIIik61Z7nKYgO3J+swQJtPYsP9wHA= k8s.io/apimachinery v0.0.0-20190404173353-6a84e37a896d/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0= -k8s.io/apimachinery v0.0.0-20190612125636-6a5db36e93ad/go.mod h1:I4A+glKBHiTgiEjQiCCQfCAIcIMFGt291SmsvcrFzJA= -k8s.io/apimachinery v0.17.2/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg= -k8s.io/apimachinery v0.17.4 h1:UzM+38cPUJnzqSQ+E1PY4YxMHIzQyCg29LOoGfo79Zw= -k8s.io/apimachinery v0.17.4/go.mod h1:gxLnyZcGNdZTCLnq3fgzyg2A5BVCHTNDFrw8AmuJ+0g= -k8s.io/apiserver v0.17.2/go.mod h1:lBmw/TtQdtxvrTk0e2cgtOxHizXI+d0mmGQURIHQZlo= k8s.io/cli-runtime v0.0.0-20191004110135-b9eb767d2e1a h1:REMzGxu+NpG9dPRsE9my/fw9iYIecz1S8UFFl6hbe18= k8s.io/cli-runtime v0.0.0-20191004110135-b9eb767d2e1a/go.mod h1:qWnH3/b8sp/l7EvlDh7ulDU3UWA4P4N1NFbEEP791tM= -k8s.io/cli-runtime v0.17.4 h1:ZIJdxpBEszZqUhydrCoiI5rLXS2J/1AF5xFok2QJ9bc= -k8s.io/cli-runtime v0.17.4/go.mod h1:IVW4zrKKx/8gBgNNkhiUIc7nZbVVNhc1+HcQh+PiNHc= -k8s.io/client-go v0.17.2/go.mod h1:QAzRgsa0C2xl4/eVpeVAZMvikCn8Nm81yqVx3Kk9XYI= -k8s.io/client-go v0.17.4 h1:VVdVbpTY70jiNHS1eiFkUt7ZIJX3txd29nDxxXH4en8= -k8s.io/client-go v0.17.4/go.mod h1:ouF6o5pz3is8qU0/qYL2RnoxOPqgfuidYLowytyLJmc= k8s.io/client-go v11.0.1-0.20190516230509-ae8359b20417+incompatible h1:bK03DJulJi9j05gwnXUufcs2j7h4M85YFvJ0dIlQ9k4= k8s.io/client-go v11.0.1-0.20190516230509-ae8359b20417+incompatible/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s= -k8s.io/code-generator v0.0.0-20200306081859-6a048a382944/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= -k8s.io/component-base v0.0.0-20190612130303-4062e14deebe/go.mod h1:MmIDXnint3qMN0cqXHKrSiJ2XQKo3J1BPIz7in7NvO0= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= -k8s.io/kube-openapi v0.0.0-20190228160746-b3a7cee44a30/go.mod h1:BXM9ceUBTj2QnfH2MK1odQs778ajze1RxcmP6S8RVVc= k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a h1:UcxjrRMyNx/i/y8G7kPvLyy7rfbeuf1PYyBf973pgyU= k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E= -k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c h1:/KUFqjjqAcY4Us6luF5RDNZ16KJtb49HfR3ZHB9qYXM= -k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= -k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0= -k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20200109141947-94aeca20bf09 h1:sz6xjn8QP74104YNmJpzLbJ+a3ZtHt0tkD0g8vpdWNw= k8s.io/utils v0.0.0-20200109141947-94aeca20bf09/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -sigs.k8s.io/controller-runtime v0.5.0 h1:CbqIy5fbUX+4E9bpnBFd204YAzRYlM9SWW77BbrcDQo= -sigs.k8s.io/controller-runtime v0.5.0/go.mod h1:REiJzC7Y00U+2YkMbT8wxgrsX5USpXKGhb2sCtAXiT8= sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= -sigs.k8s.io/structured-merge-diff v1.0.1-0.20191108220359-b1b620dd3f06/go.mod h1:/ULNhyfzRopfcjskuui0cTITekDduZ7ycKN3oUT9R18= -sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= diff --git a/pkg/api/kyverno/v1/zz_generated.deepcopy.go b/pkg/api/kyverno/v1/zz_generated.deepcopy.go index ff1a7c63e4..d4d7cc6820 100644 --- a/pkg/api/kyverno/v1/zz_generated.deepcopy.go +++ b/pkg/api/kyverno/v1/zz_generated.deepcopy.go @@ -74,7 +74,7 @@ func (in *ClusterPolicy) DeepCopyObject() runtime.Object { func (in *ClusterPolicyList) DeepCopyInto(out *ClusterPolicyList) { *out = *in out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) + out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]ClusterPolicy, len(*in)) @@ -135,7 +135,7 @@ func (in *ClusterPolicyViolation) DeepCopyObject() runtime.Object { func (in *ClusterPolicyViolationList) DeepCopyInto(out *ClusterPolicyViolationList) { *out = *in out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) + out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]ClusterPolicyViolation, len(*in)) @@ -241,7 +241,7 @@ func (in *GenerateRequestContext) DeepCopy() *GenerateRequestContext { func (in *GenerateRequestList) DeepCopyInto(out *GenerateRequestList) { *out = *in out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) + out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]GenerateRequest, len(*in)) @@ -420,7 +420,7 @@ func (in *PolicyViolation) DeepCopyObject() runtime.Object { func (in *PolicyViolationList) DeepCopyInto(out *PolicyViolationList) { *out = *in out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) + out.ListMeta = in.ListMeta if in.Items != nil { in, out := &in.Items, &out.Items *out = make([]PolicyViolation, len(*in)) diff --git a/pkg/auth/auth.go b/pkg/auth/auth.go deleted file mode 100644 index 8f1ef24e1e..0000000000 --- a/pkg/auth/auth.go +++ /dev/null @@ -1,108 +0,0 @@ -package auth - -import ( - "fmt" - "reflect" - - "github.com/go-logr/logr" - client "github.com/nirmata/kyverno/pkg/dclient" - authorizationv1 "k8s.io/api/authorization/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -//CanIOptions provides utility ti check if user has authorization for the given operation -type CanIOptions struct { - namespace string - verb string - kind string - client *client.Client - log logr.Logger -} - -//NewCanI returns a new instance of operation access controler evaluator -func NewCanI(client *client.Client, kind, namespace, verb string, log logr.Logger) *CanIOptions { - o := CanIOptions{ - client: client, - log: log, - } - - o.namespace = namespace - o.kind = kind - o.verb = verb - - return &o -} - -//RunAccessCheck checks if the caller can perform the operation -// - operation is a combination of namespace, kind, verb -// - can only evaluate a single verb -// - group version resource is determined from the kind using the discovery client REST mapper -// - If disallowed, the reason and evaluationError is avialable in the logs -// - each can generates a SelfSubjectAccessReview resource and response is evaluated for permissions -func (o *CanIOptions) RunAccessCheck() (bool, error) { - // get GroupVersionResource from RESTMapper - // get GVR from kind - gvr := o.client.DiscoveryClient.GetGVRFromKind(o.kind) - if reflect.DeepEqual(gvr, schema.GroupVersionResource{}) { - // cannot find GVR - return false, fmt.Errorf("failed to get the Group Version Resource for kind %s", o.kind) - } - - sar := &authorizationv1.SelfSubjectAccessReview{ - Spec: authorizationv1.SelfSubjectAccessReviewSpec{ - ResourceAttributes: &authorizationv1.ResourceAttributes{ - Namespace: o.namespace, - Verb: o.verb, - Group: gvr.Group, - Resource: gvr.Resource, - }, - }, - } - // Set self subject access review - // - namespace - // - verb - // - resource - // - subresource - logger := o.log.WithValues("kind", sar.Kind, "namespace", sar.Namespace, "name", sar.Name) - - // Create the Resource - resp, err := o.client.CreateResource("SelfSubjectAccessReview", "", sar, false) - if err != nil { - logger.Error(err, "failed to create resource") - return false, err - } - - // status.allowed - allowed, ok, err := unstructured.NestedBool(resp.Object, "status", "allowed") - if !ok { - if err != nil { - logger.Error(err, "failed to get the field", "field", "status.allowed") - } - logger.Info("field not found", "field", "status.allowed") - } - - if !allowed { - // status.reason - reason, ok, err := unstructured.NestedString(resp.Object, "status", "reason") - if !ok { - if err != nil { - logger.Error(err, "failed to get the field", "field", "status.reason") - } - logger.Info("field not found", "field", "status.reason") - } - // status.evaluationError - evaluationError, ok, err := unstructured.NestedString(resp.Object, "status", "evaludationError") - if !ok { - if err != nil { - logger.Error(err, "failed to get the field", "field", "status.evaluationError") - } - logger.Info("field not found", "field", "status.evaluationError") - } - - // Reporting ? (just logs) - logger.Info("disallowed operation", "reason", reason, "evaluationError", evaluationError) - } - - return allowed, nil -} diff --git a/pkg/auth/auth_test.go b/pkg/auth/auth_test.go deleted file mode 100644 index 6dbc800285..0000000000 --- a/pkg/auth/auth_test.go +++ /dev/null @@ -1,48 +0,0 @@ -package auth - -// import ( -// "testing" -// "time" - -// "github.com/golang/glog" -// "github.com/nirmata/kyverno/pkg/config" -// dclient "github.com/nirmata/kyverno/pkg/dclient" -// "github.com/nirmata/kyverno/pkg/signal" -// ) - -// func Test_Auth_pass(t *testing.T) { -// // needs running cluster -// var kubeconfig string -// stopCh := signal.SetupSignalHandler() -// kubeconfig = "/Users/shivd/.kube/config" -// clientConfig, err := config.CreateClientConfig(kubeconfig) -// if err != nil { -// glog.Fatalf("Error building kubeconfig: %v\n", err) -// } - -// // DYNAMIC CLIENT -// // - client for all registered resources -// // - invalidate local cache of registered resource every 10 seconds -// client, err := dclient.NewClient(clientConfig, 10*time.Second, stopCh) -// if err != nil { -// glog.Fatalf("Error creating client: %v\n", err) -// } - -// // Can i authenticate - -// kind := "Deployment" -// namespace := "default" -// verb := "test" -// canI := NewCanI(client, kind, namespace, verb) -// ok, err := canI.RunAccessCheck() -// if err != nil { -// t.Error(err) -// } -// if ok { -// t.Log("allowed") -// } else { -// t.Log("notallowed") -// } -// t.FailNow() - -// } diff --git a/pkg/checker/checker.go b/pkg/checker/checker.go index 16b8276d40..762776dffd 100644 --- a/pkg/checker/checker.go +++ b/pkg/checker/checker.go @@ -4,7 +4,7 @@ import ( "sync" "time" - "github.com/go-logr/logr" + "github.com/golang/glog" kyvernolister "github.com/nirmata/kyverno/pkg/client/listers/kyverno/v1" dclient "github.com/nirmata/kyverno/pkg/dclient" "github.com/nirmata/kyverno/pkg/event" @@ -20,9 +20,8 @@ const ( // LastReqTime stores the lastrequest times for incoming api-requests type LastReqTime struct { - t time.Time - mu sync.RWMutex - log logr.Logger + t time.Time + mu sync.RWMutex } //Time returns the lastrequest time @@ -40,17 +39,16 @@ func (t *LastReqTime) SetTime(tm time.Time) { } //NewLastReqTime returns a new instance of LastRequestTime store -func NewLastReqTime(log logr.Logger) *LastReqTime { +func NewLastReqTime() *LastReqTime { return &LastReqTime{ - t: time.Now(), - log: log, + t: time.Now(), } } -func checkIfPolicyWithMutateAndGenerateExists(pLister kyvernolister.ClusterPolicyLister, log logr.Logger) bool { +func checkIfPolicyWithMutateAndGenerateExists(pLister kyvernolister.ClusterPolicyLister) bool { policies, err := pLister.ListResources(labels.NewSelector()) if err != nil { - log.Error(err, "failed to list cluster policies") + glog.Error() } for _, policy := range policies { if policy.HasMutateOrValidateOrGenerate() { @@ -64,16 +62,15 @@ func checkIfPolicyWithMutateAndGenerateExists(pLister kyvernolister.ClusterPolic //Run runs the checker and verify the resource update func (t *LastReqTime) Run(pLister kyvernolister.ClusterPolicyLister, eventGen event.Interface, client *dclient.Client, defaultResync time.Duration, deadline time.Duration, stopCh <-chan struct{}) { - logger := t.log - logger.V(2).Info("tarting default resync for webhook checker", "resyncTime", defaultResync) + glog.V(2).Infof("starting default resync for webhook checker with resync time %d nanoseconds", defaultResync) maxDeadline := deadline * time.Duration(MaxRetryCount) ticker := time.NewTicker(defaultResync) /// interface to update and increment kyverno webhook status via annotations - statuscontrol := NewVerifyControl(client, eventGen, logger.WithName("StatusControl")) + statuscontrol := NewVerifyControl(client, eventGen) // send the initial update status - if checkIfPolicyWithMutateAndGenerateExists(pLister, logger) { + if checkIfPolicyWithMutateAndGenerateExists(pLister) { if err := statuscontrol.SuccessStatus(); err != nil { - logger.Error(err, "failed to set 'success' status") + glog.Error(err) } } @@ -87,36 +84,36 @@ func (t *LastReqTime) Run(pLister kyvernolister.ClusterPolicyLister, eventGen ev case <-ticker.C: // if there are no policies then we dont have a webhook on resource. // we indirectly check if the resource - if !checkIfPolicyWithMutateAndGenerateExists(pLister, logger) { + if !checkIfPolicyWithMutateAndGenerateExists(pLister) { continue } // get current time timeDiff := time.Since(t.Time()) if timeDiff > maxDeadline { - logger.Info("request exceeded max deadline", "deadline", maxDeadline) - logger.Info("Admission Control failing: Webhook is not receiving requests forwarded by api-server as per webhook configurations") + glog.Infof("failed to receive any request for more than %v ", maxDeadline) + glog.Info("Admission Control failing: Webhook is not receiving requests forwarded by api-server as per webhook configurations") // set the status unavailable if err := statuscontrol.FailedStatus(); err != nil { - logger.Error(err, "failed to set 'failed' status") + glog.Error(err) } continue } if timeDiff > deadline { - logger.Info("Admission Control failing: Webhook is not receiving requests forwarded by api-server as per webhook configurations") + glog.Info("Admission Control failing: Webhook is not receiving requests forwarded by api-server as per webhook configurations") // send request to update the kyverno deployment if err := statuscontrol.IncrementAnnotation(); err != nil { - logger.Error(err, "failed to increment annotation") + glog.Error(err) } continue } // if the status was false before then we update it to true // send request to update the kyverno deployment if err := statuscontrol.SuccessStatus(); err != nil { - logger.Error(err, "failed to update success status") + glog.Error(err) } case <-stopCh: // handler termination signal - logger.V(2).Info("stopping default resync for webhook checker") + glog.V(2).Infof("stopping default resync for webhook checker") return } } diff --git a/pkg/checker/status.go b/pkg/checker/status.go index 110abf8eef..39b19189dd 100644 --- a/pkg/checker/status.go +++ b/pkg/checker/status.go @@ -4,7 +4,7 @@ import ( "fmt" "strconv" - "github.com/go-logr/logr" + "github.com/golang/glog" dclient "github.com/nirmata/kyverno/pkg/dclient" "github.com/nirmata/kyverno/pkg/event" ) @@ -29,7 +29,6 @@ type StatusInterface interface { type StatusControl struct { client *dclient.Client eventGen event.Interface - log logr.Logger } //SuccessStatus ... @@ -43,22 +42,20 @@ func (vc StatusControl) FailedStatus() error { } // NewVerifyControl ... -func NewVerifyControl(client *dclient.Client, eventGen event.Interface, log logr.Logger) *StatusControl { +func NewVerifyControl(client *dclient.Client, eventGen event.Interface) *StatusControl { return &StatusControl{ client: client, eventGen: eventGen, - log: log, } } func (vc StatusControl) setStatus(status string) error { - logger := vc.log - logger.Info(fmt.Sprintf("setting deployment %s in ns %s annotation %s to %s", deployName, deployNamespace, annWebhookStats, status)) + glog.Infof("setting deployment %s in ns %s annotation %s to %s", deployName, deployNamespace, annWebhookStats, status) var ann map[string]string var err error deploy, err := vc.client.GetResource("Deployment", deployNamespace, deployName) if err != nil { - logger.Error(err, "failed to get deployment resource") + glog.V(4).Infof("failed to get deployment %s in namespace %s: %v", deployName, deployNamespace, err) return err } ann = deploy.GetAnnotations() @@ -70,7 +67,7 @@ func (vc StatusControl) setStatus(status string) error { if ok { // annotatiaion is present if webhookAction == status { - logger.V(4).Info(fmt.Sprintf("annotation %s already set to '%s'", annWebhookStats, status)) + glog.V(4).Infof("annotation %s already set to '%s'", annWebhookStats, status) return nil } } @@ -80,7 +77,7 @@ func (vc StatusControl) setStatus(status string) error { // update counter _, err = vc.client.UpdateResource("Deployment", deployNamespace, deploy, false) if err != nil { - logger.Error(err, fmt.Sprintf("failed to update annotation %s for deployment %s in namespace %s", annWebhookStats, deployName, deployNamespace)) + glog.V(4).Infof("failed to update annotation %s for deployment %s in namespace %s: %v", annWebhookStats, deployName, deployNamespace, err) return err } // create event on kyverno deployment @@ -100,13 +97,12 @@ func createStatusUpdateEvent(status string, eventGen event.Interface) { //IncrementAnnotation ... func (vc StatusControl) IncrementAnnotation() error { - logger := vc.log - logger.Info(fmt.Sprintf("setting deployment %s in ns %s annotation %s", deployName, deployNamespace, annCounter)) + glog.Infof("setting deployment %s in ns %s annotation %s", deployName, deployNamespace, annCounter) var ann map[string]string var err error deploy, err := vc.client.GetResource("Deployment", deployNamespace, deployName) if err != nil { - logger.Error(err, "failed to get deployment %s in namespace %s", deployName, deployNamespace) + glog.V(4).Infof("failed to get deployment %s in namespace %s: %v", deployName, deployNamespace, err) return err } ann = deploy.GetAnnotations() @@ -116,18 +112,18 @@ func (vc StatusControl) IncrementAnnotation() error { } counter, err := strconv.Atoi(ann[annCounter]) if err != nil { - logger.Error(err, "Failed to parse string") + glog.V(4).Infof("failed to parse string: %v", err) return err } // increment counter counter++ ann[annCounter] = strconv.Itoa(counter) - logger.Info("incrementing annotation", "old", annCounter, "new", counter) + glog.Infof("incrementing annotation %s counter to %d", annCounter, counter) deploy.SetAnnotations(ann) // update counter _, err = vc.client.UpdateResource("Deployment", deployNamespace, deploy, false) if err != nil { - logger.Error(err, fmt.Sprintf("failed to update annotation %s for deployment %s in namespace %s", annCounter, deployName, deployNamespace)) + glog.V(4).Infof("failed to update annotation %s for deployment %s in namespace %s: %v", annCounter, deployName, deployNamespace, err) return err } return nil diff --git a/pkg/client/clientset/versioned/clientset.go b/pkg/client/clientset/versioned/clientset.go index 8aa7b0e529..5fbce444ff 100644 --- a/pkg/client/clientset/versioned/clientset.go +++ b/pkg/client/clientset/versioned/clientset.go @@ -19,8 +19,6 @@ limitations under the License. package versioned import ( - "fmt" - kyvernov1 "github.com/nirmata/kyverno/pkg/client/clientset/versioned/typed/kyverno/v1" discovery "k8s.io/client-go/discovery" rest "k8s.io/client-go/rest" @@ -53,14 +51,9 @@ func (c *Clientset) Discovery() discovery.DiscoveryInterface { } // NewForConfig creates a new Clientset for the given config. -// If config's RateLimiter is not set and QPS and Burst are acceptable, -// NewForConfig will generate a rate-limiter in configShallowCopy. func NewForConfig(c *rest.Config) (*Clientset, error) { configShallowCopy := *c if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { - if configShallowCopy.Burst <= 0 { - return nil, fmt.Errorf("Burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0") - } configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) } var cs Clientset diff --git a/pkg/client/clientset/versioned/fake/clientset_generated.go b/pkg/client/clientset/versioned/fake/clientset_generated.go index c3264dcb64..215b1d997a 100644 --- a/pkg/client/clientset/versioned/fake/clientset_generated.go +++ b/pkg/client/clientset/versioned/fake/clientset_generated.go @@ -41,7 +41,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { } } - cs := &Clientset{tracker: o} + 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) { @@ -63,17 +63,12 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset { type Clientset struct { testing.Fake discovery *fakediscovery.FakeDiscovery - tracker testing.ObjectTracker } func (c *Clientset) Discovery() discovery.DiscoveryInterface { return c.discovery } -func (c *Clientset) Tracker() testing.ObjectTracker { - return c.tracker -} - var _ clientset.Interface = &Clientset{} // KyvernoV1 retrieves the KyvernoV1Client diff --git a/pkg/client/clientset/versioned/fake/register.go b/pkg/client/clientset/versioned/fake/register.go index 482e66ffc7..4a90cf5ba8 100644 --- a/pkg/client/clientset/versioned/fake/register.go +++ b/pkg/client/clientset/versioned/fake/register.go @@ -29,8 +29,7 @@ import ( var scheme = runtime.NewScheme() var codecs = serializer.NewCodecFactory(scheme) - -// var parameterCodec = runtime.NewParameterCodec(scheme) +var parameterCodec = runtime.NewParameterCodec(scheme) var localSchemeBuilder = runtime.SchemeBuilder{ kyvernov1.AddToScheme, } diff --git a/pkg/client/clientset/versioned/typed/kyverno/v1/kyverno_client.go b/pkg/client/clientset/versioned/typed/kyverno/v1/kyverno_client.go index 8c1b5a0ea8..54d8944680 100644 --- a/pkg/client/clientset/versioned/typed/kyverno/v1/kyverno_client.go +++ b/pkg/client/clientset/versioned/typed/kyverno/v1/kyverno_client.go @@ -21,6 +21,7 @@ package v1 import ( v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/client/clientset/versioned/scheme" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" rest "k8s.io/client-go/rest" ) @@ -85,7 +86,7 @@ func setConfigDefaults(config *rest.Config) error { gv := v1.SchemeGroupVersion config.GroupVersion = &gv config.APIPath = "/apis" - config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs} if config.UserAgent == "" { config.UserAgent = rest.DefaultKubernetesUserAgent() diff --git a/pkg/config/config.go b/pkg/config/config.go index 2d6ccdcb68..241728a2c7 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -1,7 +1,9 @@ package config import ( - "github.com/go-logr/logr" + "flag" + + "github.com/golang/glog" rest "k8s.io/client-go/rest" clientcmd "k8s.io/client-go/tools/clientcmd" ) @@ -72,13 +74,29 @@ var ( VerifyMutatingWebhookServicePath = "/verifymutate" ) +//LogDefaultFlags sets default glog flags +func LogDefaultFlags() { + var err error + err = flag.Set("logtostderr", "true") + if err != nil { + glog.Fatalf("failed to set flag 'logtostderr' to 'true':%v", err) + } + err = flag.Set("stderrthreshold", "WARNING") + if err != nil { + glog.Fatalf("failed to set flag 'stderrthreshold' to 'WARNING':%v", err) + } + flag.Set("v", "2") + if err != nil { + glog.Fatalf("failed to set flag 'v' to '2':%v", err) + } +} + //CreateClientConfig creates client config -func CreateClientConfig(kubeconfig string, log logr.Logger) (*rest.Config, error) { - logger := log.WithName("CreateClientConfig") +func CreateClientConfig(kubeconfig string) (*rest.Config, error) { if kubeconfig == "" { - logger.Info("Using in-cluster configuration") + glog.Info("Using in-cluster configuration") return rest.InClusterConfig() } - logger.V(4).Info("Using specified kubeconfig", "kubeconfig", kubeconfig) + glog.V(4).Infof("Using configuration from '%s'", kubeconfig) return clientcmd.BuildConfigFromFlags("", kubeconfig) } diff --git a/pkg/config/dynamicconfig.go b/pkg/config/dynamicconfig.go index 1787f67bd9..6bf624e7bb 100644 --- a/pkg/config/dynamicconfig.go +++ b/pkg/config/dynamicconfig.go @@ -1,13 +1,14 @@ package config import ( + "fmt" "os" "reflect" "regexp" "strings" "sync" - "github.com/go-logr/logr" + "github.com/golang/glog" "github.com/minio/minio/pkg/wildcard" v1 "k8s.io/api/core/v1" informers "k8s.io/client-go/informers/core/v1" @@ -30,7 +31,6 @@ type ConfigData struct { filters []k8Resource // hasynced cmSycned cache.InformerSynced - log logr.Logger } // ToFilter checks if the given resource is set to be filtered in the configuration @@ -51,21 +51,20 @@ type Interface interface { } // NewConfigData ... -func NewConfigData(rclient kubernetes.Interface, cmInformer informers.ConfigMapInformer, filterK8Resources string, log logr.Logger) *ConfigData { +func NewConfigData(rclient kubernetes.Interface, cmInformer informers.ConfigMapInformer, filterK8Resources string) *ConfigData { // environment var is read at start only if cmNameEnv == "" { - log.Info("ConfigMap name not defined in env:INIT_CONFIG: loading no default configuration") + glog.Info("ConfigMap name not defined in env:INIT_CONFIG: loading no default configuration") } cd := ConfigData{ client: rclient, cmName: os.Getenv(cmNameEnv), cmSycned: cmInformer.Informer().HasSynced, - log: log, } //TODO: this has been added to backward support command line arguments // will be removed in future and the configuration will be set only via configmaps if filterK8Resources != "" { - cd.log.Info("init configuration from commandline arguments") + glog.Info("Init configuration from commandline arguments") cd.initFilters(filterK8Resources) } @@ -79,10 +78,9 @@ func NewConfigData(rclient kubernetes.Interface, cmInformer informers.ConfigMapI //Run checks syncing func (cd *ConfigData) Run(stopCh <-chan struct{}) { - logger := cd.log // wait for cache to populate first time if !cache.WaitForCacheSync(stopCh, cd.cmSycned) { - logger.Info("configuration: failed to sync informer cache") + glog.Error("configuration: failed to sync informer cache") } } @@ -105,17 +103,16 @@ func (cd *ConfigData) updateCM(old, cur interface{}) { } func (cd *ConfigData) deleteCM(obj interface{}) { - logger := cd.log cm, ok := obj.(*v1.ConfigMap) if !ok { tombstone, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { - logger.Info("failed to get object from tombstone") + glog.Info(fmt.Errorf("Couldn't get object from tombstone %#v", obj)) return } _, ok = tombstone.Obj.(*v1.ConfigMap) if !ok { - logger.Info("Tombstone contained object that is not a ConfigMap", "object", obj) + glog.Info(fmt.Errorf("Tombstone contained object that is not a ConfigMap %#v", obj)) return } } @@ -128,20 +125,19 @@ func (cd *ConfigData) deleteCM(obj interface{}) { } func (cd *ConfigData) load(cm v1.ConfigMap) { - logger := cd.log.WithValues("name", cm.Name, "namespace", cm.Namespace) if cm.Data == nil { - logger.V(4).Info("configuration: No data defined in ConfigMap") + glog.V(4).Infof("Configuration: No data defined in ConfigMap %s", cm.Name) return } // get resource filters filters, ok := cm.Data["resourceFilters"] if !ok { - logger.V(4).Info("configuration: No resourceFilters defined in ConfigMap") + glog.V(4).Infof("Configuration: No resourceFilters defined in ConfigMap %s", cm.Name) return } // filters is a string if filters == "" { - logger.V(4).Info("configuration: resourceFilters is empty in ConfigMap") + glog.V(4).Infof("Configuration: resourceFilters is empty in ConfigMap %s", cm.Name) return } // parse and load the configuration @@ -150,10 +146,11 @@ func (cd *ConfigData) load(cm v1.ConfigMap) { newFilters := parseKinds(filters) if reflect.DeepEqual(newFilters, cd.filters) { - logger.V(4).Info("resourceFilters did not change") + glog.V(4).Infof("Configuration: resourceFilters did not change in ConfigMap %s", cm.Name) return } - logger.V(4).Info(" Updated resource filters", "oldFilters", cd.filters, "newFilters", newFilters) + glog.V(4).Infof("Configuration: Old resource filters %v", cd.filters) + glog.Infof("Configuration: New resource filters to %v", newFilters) // update filters cd.filters = newFilters } @@ -161,20 +158,20 @@ func (cd *ConfigData) load(cm v1.ConfigMap) { //TODO: this has been added to backward support command line arguments // will be removed in future and the configuration will be set only via configmaps func (cd *ConfigData) initFilters(filters string) { - logger := cd.log // parse and load the configuration cd.mux.Lock() defer cd.mux.Unlock() newFilters := parseKinds(filters) - logger.Info("Init resource filters", "filters", newFilters) + glog.Infof("Configuration: Init resource filters to %v", newFilters) // update filters cd.filters = newFilters } func (cd *ConfigData) unload(cm v1.ConfigMap) { - logger := cd.log - logger.Info("ConfigMap deleted, removing configuration filters", "name", cm.Name, "namespace", cm.Namespace) + // TODO pick one msg + glog.Infof("Configuration: ConfigMap %s deleted, removing configuration filters", cm.Name) + glog.Infof("Configuration: Removing all resource filters as ConfigMap %s deleted", cm.Name) cd.mux.Lock() defer cd.mux.Unlock() cd.filters = []k8Resource{} diff --git a/pkg/dclient/certificates.go b/pkg/dclient/certificates.go index 125dc7cec3..76b3cda819 100644 --- a/pkg/dclient/certificates.go +++ b/pkg/dclient/certificates.go @@ -6,6 +6,7 @@ import ( "net/url" "time" + "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/config" tls "github.com/nirmata/kyverno/pkg/tls" certificates "k8s.io/api/certificates/v1beta1" @@ -18,14 +19,13 @@ import ( // Created pair is stored in cluster's secret. // Returns struct with key/certificate pair. func (c *Client) InitTLSPemPair(configuration *rest.Config, fqdncn bool) (*tls.TlsPemPair, error) { - logger := c.log certProps, err := c.GetTLSCertProps(configuration) if err != nil { return nil, err } tlsPair := c.ReadTlsPair(certProps) if tls.IsTLSPairShouldBeUpdated(tlsPair) { - logger.Info("Generating new key/certificate pair for TLS") + glog.Info("Generating new key/certificate pair for TLS") tlsPair, err = c.generateTLSPemPair(certProps, fqdncn) if err != nil { return nil, err @@ -35,7 +35,8 @@ func (c *Client) InitTLSPemPair(configuration *rest.Config, fqdncn bool) (*tls.T } return tlsPair, nil } - logger.Info("Using existing TLS key/certificate pair") + + glog.Infoln("Using existing TLS key/certificate pair") return tlsPair, nil } @@ -70,7 +71,6 @@ func (c *Client) generateTLSPemPair(props tls.TlsCertificateProps, fqdncn bool) // Submits and approves certificate request, returns request which need to be fetched func (c *Client) submitAndApproveCertificateRequest(req *certificates.CertificateSigningRequest) (*certificates.CertificateSigningRequest, error) { - logger := c.log.WithName("submitAndApproveCertificateRequest") certClient, err := c.GetCSRInterface() if err != nil { return nil, err @@ -86,7 +86,7 @@ func (c *Client) submitAndApproveCertificateRequest(req *certificates.Certificat if err != nil { return nil, fmt.Errorf("Unable to delete existing certificate request: %v", err) } - logger.Info("Old certificate request is deleted") + glog.Info("Old certificate request is deleted") break } } @@ -95,7 +95,7 @@ func (c *Client) submitAndApproveCertificateRequest(req *certificates.Certificat if err != nil { return nil, err } - logger.Info("Certificate request created", "name", unstrRes.GetName()) + glog.Infof("Certificate request %s is created", unstrRes.GetName()) res, err := convertToCSR(unstrRes) if err != nil { @@ -110,7 +110,7 @@ func (c *Client) submitAndApproveCertificateRequest(req *certificates.Certificat if err != nil { return nil, fmt.Errorf("Unable to approve certificate request: %v", err) } - logger.Info("Certificate request is approved", "name", res.ObjectMeta.Name) + glog.Infof("Certificate request %s is approved", res.ObjectMeta.Name) return res, nil } @@ -144,10 +144,9 @@ func (c *Client) fetchCertificateFromRequest(req *certificates.CertificateSignin //ReadRootCASecret returns the RootCA from the pre-defined secret func (c *Client) ReadRootCASecret() (result []byte) { - logger := c.log.WithName("ReadRootCASecret") certProps, err := c.GetTLSCertProps(c.clientConfig) if err != nil { - logger.Error(err, "failed to get TLS Cert Properties") + glog.Error(err) return result } sname := generateRootCASecretName(certProps) @@ -157,16 +156,16 @@ func (c *Client) ReadRootCASecret() (result []byte) { } tlsca, err := convertToSecret(stlsca) if err != nil { - logger.Error(err, "failed to convert secret", "name", sname, "namespace", certProps.Namespace) + glog.Error(err) return result } result = tlsca.Data[rootCAKey] if len(result) == 0 { - logger.Info("root CA certificate not found in secret", "name", tlsca.Name, "namespace", certProps.Namespace) + glog.Warningf("root CA certificate not found in secret %s/%s", certProps.Namespace, tlsca.Name) return result } - logger.V(4).Info("using CA bundle defined in secret to validate the webhook's server certificate", "name", tlsca.Name, "namespace", certProps.Namespace) + glog.V(4).Infof("using CA bundle defined in secret %s/%s to validate the webhook's server certificate", certProps.Namespace, tlsca.Name) return result } @@ -175,11 +174,10 @@ const rootCAKey string = "rootCA.crt" //ReadTlsPair Reads the pair of TLS certificate and key from the specified secret. func (c *Client) ReadTlsPair(props tls.TlsCertificateProps) *tls.TlsPemPair { - logger := c.log.WithName("ReadTlsPair") sname := generateTLSPairSecretName(props) unstrSecret, err := c.GetResource(Secrets, props.Namespace, sname) if err != nil { - logger.Error(err, "Failed to get secret", "name", sname, "namespace", props.Namespace) + glog.Warningf("Unable to get secret %s/%s: %s", props.Namespace, sname, err) return nil } @@ -190,7 +188,7 @@ func (c *Client) ReadTlsPair(props tls.TlsCertificateProps) *tls.TlsPemPair { sname := generateRootCASecretName(props) _, err := c.GetResource(Secrets, props.Namespace, sname) if err != nil { - logger.Error(err, "Root CA secret is required while using self-signed certificates TLS pair, defaulting to generating new TLS pair", "name", sname, "namespace", props.Namespace) + glog.Errorf("Root CA secret %s/%s is required while using self-signed certificates TLS pair, defaulting to generating new TLS pair", props.Namespace, sname) return nil } } @@ -203,11 +201,11 @@ func (c *Client) ReadTlsPair(props tls.TlsCertificateProps) *tls.TlsPemPair { PrivateKey: secret.Data[v1.TLSPrivateKeyKey], } if len(pemPair.Certificate) == 0 { - logger.Info("TLS Certificate not found in secret", "name", sname, "namespace", props.Namespace) + glog.Warningf("TLS Certificate not found in secret %s/%s", props.Namespace, sname) return nil } if len(pemPair.PrivateKey) == 0 { - logger.Info("TLS PrivateKey not found in secret", "name", sname, "namespace", props.Namespace) + glog.Warningf("TLS PrivateKey not found in secret %s/%s", props.Namespace, sname) return nil } return &pemPair @@ -216,7 +214,6 @@ func (c *Client) ReadTlsPair(props tls.TlsCertificateProps) *tls.TlsPemPair { //WriteTlsPair Writes the pair of TLS certificate and key to the specified secret. // Updates existing secret or creates new one. func (c *Client) WriteTlsPair(props tls.TlsCertificateProps, pemPair *tls.TlsPemPair) error { - logger := c.log.WithName("WriteTlsPair") name := generateTLSPairSecretName(props) _, err := c.GetResource(Secrets, props.Namespace, name) if err != nil { @@ -238,7 +235,7 @@ func (c *Client) WriteTlsPair(props tls.TlsCertificateProps, pemPair *tls.TlsPem _, err := c.CreateResource(Secrets, props.Namespace, secret, false) if err == nil { - logger.Info("secret created", "name", name, "namespace", props.Namespace) + glog.Infof("Secret %s is created", name) } return err } @@ -254,7 +251,7 @@ func (c *Client) WriteTlsPair(props tls.TlsCertificateProps, pemPair *tls.TlsPem if err != nil { return err } - logger.Info("secret updated", "name", name, "namespace", props.Namespace) + glog.Infof("Secret %s is updated", name) return nil } diff --git a/pkg/dclient/client.go b/pkg/dclient/client.go index 557059bc15..6cacaeaf9a 100644 --- a/pkg/dclient/client.go +++ b/pkg/dclient/client.go @@ -5,8 +5,9 @@ import ( "strings" "time" - "github.com/go-logr/logr" openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2" + + "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/config" apps "k8s.io/api/apps/v1" certificates "k8s.io/api/certificates/v1beta1" @@ -31,15 +32,13 @@ import ( //Client enables interaction with k8 resource type Client struct { client dynamic.Interface - log logr.Logger clientConfig *rest.Config kclient kubernetes.Interface DiscoveryClient IDiscovery } //NewClient creates new instance of client -func NewClient(config *rest.Config, resync time.Duration, stopCh <-chan struct{}, log logr.Logger) (*Client, error) { - +func NewClient(config *rest.Config, resync time.Duration, stopCh <-chan struct{}) (*Client, error) { dclient, err := dynamic.NewForConfig(config) if err != nil { return nil, err @@ -52,10 +51,9 @@ func NewClient(config *rest.Config, resync time.Duration, stopCh <-chan struct{} client: dclient, clientConfig: config, kclient: kclient, - log: log.WithName("Client"), } // Set discovery client - discoveryClient := ServerPreferredResources{cachedClient: memory.NewMemCacheClient(kclient.Discovery()), log: client.log} + discoveryClient := ServerPreferredResources{memory.NewMemCacheClient(kclient.Discovery())} // client will invalidate registered resources cache every x seconds, // As there is no way to identify if the registered resource is available or not // we will be invalidating the local cache, so the next request get a fresh cache @@ -191,6 +189,7 @@ func (c *Client) UpdateStatusResource(kind string, namespace string, obj interfa func convertToUnstructured(obj interface{}) *unstructured.Unstructured { unstructuredObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&obj) if err != nil { + glog.Errorf("Unable to convert : %v", err) return nil } return &unstructured.Unstructured{Object: unstructuredObj} @@ -229,24 +228,22 @@ func (c *Client) SetDiscovery(discoveryClient IDiscovery) { //ServerPreferredResources stores the cachedClient instance for discovery client type ServerPreferredResources struct { cachedClient discovery.CachedDiscoveryInterface - log logr.Logger } //Poll will keep invalidate the local cache func (c ServerPreferredResources) Poll(resync time.Duration, stopCh <-chan struct{}) { - logger := c.log.WithName("Poll") // start a ticker ticker := time.NewTicker(resync) defer func() { ticker.Stop() }() - logger.Info("starting registered resources sync", "period", resync) + glog.Infof("Starting registered resources sync: every %d seconds", resync) for { select { case <-stopCh: - logger.Info("stopping registered resources sync") + glog.Info("Stopping registered resources sync") return case <-ticker.C: // set cache as stale - logger.V(6).Info("invalidating local client cache for registered resources") + glog.V(6).Info("invalidating local client cache for registered resources") c.cachedClient.Invalidate() } } @@ -264,12 +261,12 @@ func (c ServerPreferredResources) OpenAPISchema() (*openapi_v2.Document, error) func (c ServerPreferredResources) GetGVRFromKind(kind string) schema.GroupVersionResource { var gvr schema.GroupVersionResource var err error - gvr, err = loadServerResources(kind, c.cachedClient, c.log) + gvr, err = loadServerResources(kind, c.cachedClient) if err != nil && !c.cachedClient.Fresh() { // invalidate cahce & re-try once more c.cachedClient.Invalidate() - gvr, err = loadServerResources(kind, c.cachedClient, c.log) + gvr, err = loadServerResources(kind, c.cachedClient) if err == nil { return gvr } @@ -282,12 +279,11 @@ func (c ServerPreferredResources) GetServerVersion() (*version.Info, error) { return c.cachedClient.ServerVersion() } -func loadServerResources(k string, cdi discovery.CachedDiscoveryInterface, log logr.Logger) (schema.GroupVersionResource, error) { - logger := log.WithName("loadServerResources") - emptyGVR := schema.GroupVersionResource{} +func loadServerResources(k string, cdi discovery.CachedDiscoveryInterface) (schema.GroupVersionResource, error) { serverresources, err := cdi.ServerPreferredResources() + emptyGVR := schema.GroupVersionResource{} if err != nil { - logger.Error(err, "failed to get registered preferred resources") + glog.Error(err) return emptyGVR, err } for _, serverresource := range serverresources { @@ -297,7 +293,7 @@ func loadServerResources(k string, cdi discovery.CachedDiscoveryInterface, log l if resource.Kind == k && !strings.Contains(resource.Name, "/") { gv, err := schema.ParseGroupVersion(serverresource.GroupVersion) if err != nil { - logger.Error(err, "failed to parse groupVersion from schema", "groupVersion", serverresource.GroupVersion) + glog.Error(err) return emptyGVR, err } return gv.WithResource(resource.Name), nil diff --git a/pkg/engine/anchor/anchor.go b/pkg/engine/anchor/anchor.go index 9dccab3577..2d81a068ec 100644 --- a/pkg/engine/anchor/anchor.go +++ b/pkg/engine/anchor/anchor.go @@ -4,8 +4,7 @@ import ( "fmt" "strconv" - "github.com/go-logr/logr" - "sigs.k8s.io/controller-runtime/pkg/log" + "github.com/golang/glog" ) //ValidationHandler for element processes @@ -13,7 +12,7 @@ type ValidationHandler interface { Handle(handler resourceElementHandler, resourceMap map[string]interface{}, originPattern interface{}) (string, error) } -type resourceElementHandler = func(log logr.Logger, resourceElement, patternElement, originPattern interface{}, path string) (string, error) +type resourceElementHandler = func(resourceElement, patternElement, originPattern interface{}, path string) (string, error) //CreateElementHandler factory to process elements func CreateElementHandler(element string, pattern interface{}, path string) ValidationHandler { @@ -83,7 +82,7 @@ func (eh EqualityHandler) Handle(handler resourceElementHandler, resourceMap map // check if anchor is present in resource if value, ok := resourceMap[anchorKey]; ok { // validate the values of the pattern - returnPath, err := handler(log.Log, value, eh.pattern, originPattern, currentPath) + returnPath, err := handler(value, eh.pattern, originPattern, currentPath) if err != nil { return returnPath, err } @@ -116,7 +115,7 @@ func (dh DefaultHandler) Handle(handler resourceElementHandler, resourceMap map[ } else if dh.pattern == "*" && resourceMap[dh.element] == nil { return dh.path, fmt.Errorf("Validation rule failed at %s, Field %s is not present", dh.path, dh.element) } else { - path, err := handler(log.Log, resourceMap[dh.element], dh.pattern, originPattern, currentPath) + path, err := handler(resourceMap[dh.element], dh.pattern, originPattern, currentPath) if err != nil { return path, err } @@ -147,7 +146,7 @@ func (ch ConditionAnchorHandler) Handle(handler resourceElementHandler, resource // check if anchor is present in resource if value, ok := resourceMap[anchorKey]; ok { // validate the values of the pattern - returnPath, err := handler(log.Log, value, ch.pattern, originPattern, currentPath) + returnPath, err := handler(value, ch.pattern, originPattern, currentPath) if err != nil { return returnPath, err } @@ -195,6 +194,7 @@ func (eh ExistenceHandler) Handle(handler resourceElementHandler, resourceMap ma } return validateExistenceListResource(handler, typedResource, typedPatternMap, originPattern, currentPath) default: + glog.Error("Invalid type: Existence ^ () anchor can be used only on list/array type resource") return currentPath, fmt.Errorf("Invalid resource type %T: Existence ^ () anchor can be used only on list/array type resource", value) } } @@ -206,9 +206,10 @@ func validateExistenceListResource(handler resourceElementHandler, resourceList // if non satisfy then throw an error for i, resourceElement := range resourceList { currentPath := path + strconv.Itoa(i) + "/" - _, err := handler(log.Log, resourceElement, patternMap, originPattern, currentPath) + _, err := handler(resourceElement, patternMap, originPattern, currentPath) if err == nil { // condition is satisfied, dont check further + glog.V(4).Infof("Existence check satisfied at path %s, for pattern %v", currentPath, patternMap) return "", nil } } diff --git a/pkg/engine/context/context.go b/pkg/engine/context/context.go index 163e81fef0..05805a0a91 100644 --- a/pkg/engine/context/context.go +++ b/pkg/engine/context/context.go @@ -6,9 +6,8 @@ import ( "sync" jsonpatch "github.com/evanphx/json-patch" - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" - "sigs.k8s.io/controller-runtime/pkg/log" ) //Interface to manage context operations @@ -34,7 +33,6 @@ type Context struct { mu sync.RWMutex jsonRaw []byte whiteListVars []string - log logr.Logger } //NewContext returns a new context @@ -44,7 +42,6 @@ func NewContext(whiteListVars ...string) *Context { // data: map[string]interface{}{}, jsonRaw: []byte(`{}`), // empty json struct whiteListVars: whiteListVars, - log: log.Log.WithName("context"), } return &ctx } @@ -57,7 +54,7 @@ func (ctx *Context) AddJSON(dataRaw []byte) error { // merge json ctx.jsonRaw, err = jsonpatch.MergePatch(ctx.jsonRaw, dataRaw) if err != nil { - ctx.log.Error(err, "failed to merge JSON data") + glog.V(4).Infof("failed to merge JSON data: %v", err) return err } return nil @@ -69,7 +66,7 @@ func (ctx *Context) AddResource(dataRaw []byte) error { // unmarshall the resource struct var data interface{} if err := json.Unmarshal(dataRaw, &data); err != nil { - ctx.log.Error(err, "failed to unmarshall the resource") + glog.V(4).Infof("failed to unmarshall the context data: %v", err) return err } @@ -85,7 +82,7 @@ func (ctx *Context) AddResource(dataRaw []byte) error { objRaw, err := json.Marshal(modifiedResource) if err != nil { - ctx.log.Error(err, "failed to marshal the resource") + glog.V(4).Infof("failed to marshall the updated context data") return err } return ctx.AddJSON(objRaw) @@ -101,7 +98,7 @@ func (ctx *Context) AddUserInfo(userRequestInfo kyverno.RequestInfo) error { objRaw, err := json.Marshal(modifiedResource) if err != nil { - ctx.log.Error(err, "failed to marshal the UserInfo") + glog.V(4).Infof("failed to marshall the updated context data") return err } return ctx.AddJSON(objRaw) @@ -121,6 +118,8 @@ func (ctx *Context) AddSA(userName string) error { // filter namespace groups := strings.Split(sa, ":") if len(groups) >= 2 { + glog.V(4).Infof("serviceAccount namespace: %s", groups[0]) + glog.V(4).Infof("serviceAccount name: %s", groups[1]) saName = groups[1] saNamespace = groups[0] } @@ -132,7 +131,7 @@ func (ctx *Context) AddSA(userName string) error { } saNameRaw, err := json.Marshal(saNameObj) if err != nil { - ctx.log.Error(err, "failed to marshal the SA") + glog.V(4).Infof("failed to marshall the updated context data") return err } if err := ctx.AddJSON(saNameRaw); err != nil { @@ -146,7 +145,7 @@ func (ctx *Context) AddSA(userName string) error { } saNsRaw, err := json.Marshal(saNsObj) if err != nil { - ctx.log.Error(err, "failed to marshal the SA namespace") + glog.V(4).Infof("failed to marshall the updated context data") return err } if err := ctx.AddJSON(saNsRaw); err != nil { diff --git a/pkg/engine/context/evaluate.go b/pkg/engine/context/evaluate.go index f15a8a1e17..78f9643497 100644 --- a/pkg/engine/context/evaluate.go +++ b/pkg/engine/context/evaluate.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" + "github.com/golang/glog" jmespath "github.com/jmespath/go-jmespath" ) @@ -18,7 +19,7 @@ func (ctx *Context) Query(query string) (interface{}, error) { // compile the query queryPath, err := jmespath.Compile(query) if err != nil { - ctx.log.Error(err, "incorrect query", "query", query) + glog.V(4).Infof("incorrect query %s: %v", query, err) return emptyResult, fmt.Errorf("incorrect query %s: %v", query, err) } // search @@ -27,13 +28,13 @@ func (ctx *Context) Query(query string) (interface{}, error) { var data interface{} if err := json.Unmarshal(ctx.jsonRaw, &data); err != nil { - ctx.log.Error(err, "failed to unmarshal context") + glog.V(4).Infof("failed to unmarshall context: %v", err) return emptyResult, fmt.Errorf("failed to unmarshall context: %v", err) } result, err := queryPath.Search(data) if err != nil { - ctx.log.Error(err, "failed to search query", "query", query) + glog.V(4).Infof("failed to search query %s: %v", query, err) return emptyResult, fmt.Errorf("failed to search query %s: %v", query, err) } return result, nil diff --git a/pkg/engine/forceMutate.go b/pkg/engine/forceMutate.go index 9453109742..14ba42c468 100644 --- a/pkg/engine/forceMutate.go +++ b/pkg/engine/forceMutate.go @@ -12,7 +12,6 @@ import ( "github.com/nirmata/kyverno/pkg/engine/utils" "github.com/nirmata/kyverno/pkg/engine/variables" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sigs.k8s.io/controller-runtime/pkg/log" ) func mutateResourceWithOverlay(resource unstructured.Unstructured, overlay interface{}) (unstructured.Unstructured, error) { @@ -58,7 +57,7 @@ func ForceMutate(ctx context.EvalInterface, policy kyverno.ClusterPolicy, resour if mutation.Overlay != nil { overlay := mutation.Overlay if ctx != nil { - if overlay, err = variables.SubstituteVars(log.Log, ctx, overlay); err != nil { + if overlay, err = variables.SubstituteVars(ctx, overlay); err != nil { return unstructured.Unstructured{}, err } } else { @@ -73,7 +72,7 @@ func ForceMutate(ctx context.EvalInterface, policy kyverno.ClusterPolicy, resour if rule.Mutation.Patches != nil { var resp response.RuleResponse - resp, resource = mutate.ProcessPatches(log.Log, rule, resource) + resp, resource = mutate.ProcessPatches(rule, resource) if !resp.Success { return unstructured.Unstructured{}, fmt.Errorf(resp.Message) } diff --git a/pkg/engine/generation.go b/pkg/engine/generation.go index 552bbc3a4d..0f8cea1937 100644 --- a/pkg/engine/generation.go +++ b/pkg/engine/generation.go @@ -3,14 +3,12 @@ package engine import ( "time" - "github.com/go-logr/logr" - + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine/context" "github.com/nirmata/kyverno/pkg/engine/response" "github.com/nirmata/kyverno/pkg/engine/variables" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sigs.k8s.io/controller-runtime/pkg/log" ) // Generate checks for validity of generate rule on the resource @@ -22,11 +20,10 @@ func Generate(policyContext PolicyContext) (resp response.EngineResponse) { resource := policyContext.NewResource admissionInfo := policyContext.AdmissionInfo ctx := policyContext.Context - logger := log.Log.WithName("Generate").WithValues("policy", policy.Name, "kind", resource.GetKind(), "namespace", resource.GetNamespace(), "name", resource.GetName()) - return filterRules(policy, resource, admissionInfo, ctx, logger) + return filterRules(policy, resource, admissionInfo, ctx) } -func filterRule(rule kyverno.Rule, resource unstructured.Unstructured, admissionInfo kyverno.RequestInfo, ctx context.EvalInterface, log logr.Logger) *response.RuleResponse { +func filterRule(rule kyverno.Rule, resource unstructured.Unstructured, admissionInfo kyverno.RequestInfo, ctx context.EvalInterface) *response.RuleResponse { if !rule.HasGenerate() { return nil } @@ -34,14 +31,15 @@ func filterRule(rule kyverno.Rule, resource unstructured.Unstructured, admission startTime := time.Now() if err := MatchesResourceDescription(resource, rule, admissionInfo); err != nil { + glog.V(4).Infof(err.Error()) return nil } // operate on the copy of the conditions, as we perform variable substitution copyConditions := copyConditions(rule.Conditions) // evaluate pre-conditions - if !variables.EvaluateConditions(log, ctx, copyConditions) { - log.V(4).Info("preconditions not satisfied, skipping rule", "rule", rule.Name) + if !variables.EvaluateConditions(ctx, copyConditions) { + glog.V(4).Infof("resource %s/%s does not satisfy the conditions for the rule ", resource.GetNamespace(), resource.GetName()) return nil } // build rule Response @@ -55,7 +53,7 @@ func filterRule(rule kyverno.Rule, resource unstructured.Unstructured, admission } } -func filterRules(policy kyverno.ClusterPolicy, resource unstructured.Unstructured, admissionInfo kyverno.RequestInfo, ctx context.EvalInterface, log logr.Logger) response.EngineResponse { +func filterRules(policy kyverno.ClusterPolicy, resource unstructured.Unstructured, admissionInfo kyverno.RequestInfo, ctx context.EvalInterface) response.EngineResponse { resp := response.EngineResponse{ PolicyResponse: response.PolicyResponse{ Policy: policy.Name, @@ -68,7 +66,7 @@ func filterRules(policy kyverno.ClusterPolicy, resource unstructured.Unstructure } for _, rule := range policy.Spec.Rules { - if ruleResp := filterRule(rule, resource, admissionInfo, ctx, log); ruleResp != nil { + if ruleResp := filterRule(rule, resource, admissionInfo, ctx); ruleResp != nil { resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, *ruleResp) } } diff --git a/pkg/engine/mutate/overlay.go b/pkg/engine/mutate/overlay.go index 5e4982260e..3b76f30c74 100644 --- a/pkg/engine/mutate/overlay.go +++ b/pkg/engine/mutate/overlay.go @@ -10,53 +10,51 @@ import ( "strings" "time" + "github.com/golang/glog" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sigs.k8s.io/controller-runtime/pkg/log" jsonpatch "github.com/evanphx/json-patch" - "github.com/go-logr/logr" "github.com/nirmata/kyverno/pkg/engine/anchor" "github.com/nirmata/kyverno/pkg/engine/response" "github.com/nirmata/kyverno/pkg/engine/utils" ) // ProcessOverlay processes mutation overlay on the resource -func ProcessOverlay(log logr.Logger, ruleName string, overlay interface{}, resource unstructured.Unstructured) (resp response.RuleResponse, patchedResource unstructured.Unstructured) { +func ProcessOverlay(ruleName string, overlay interface{}, resource unstructured.Unstructured) (resp response.RuleResponse, patchedResource unstructured.Unstructured) { startTime := time.Now() - logger := log.WithValues("rule", ruleName) - logger.V(4).Info("started applying overlay rule ", "startTime", startTime) + glog.V(4).Infof("started applying overlay rule %q (%v)", ruleName, startTime) resp.Name = ruleName resp.Type = utils.Mutation.String() defer func() { resp.RuleStats.ProcessingTime = time.Since(startTime) - logger.V(4).Info("finished applying overlay rule", "processingTime", resp.RuleStats.ProcessingTime) + glog.V(4).Infof("finished applying overlay rule %q (%v)", resp.Name, resp.RuleStats.ProcessingTime) }() - patches, overlayerr := processOverlayPatches(logger, resource.UnstructuredContent(), overlay) + patches, overlayerr := processOverlayPatches(resource.UnstructuredContent(), overlay) // resource does not satisfy the overlay pattern, we don't apply this rule if !reflect.DeepEqual(overlayerr, overlayError{}) { switch overlayerr.statusCode { // condition key is not present in the resource, don't apply this rule // consider as success case conditionNotPresent: - logger.V(3).Info("skip applying rule") + glog.V(3).Infof("Skip applying rule '%s' on resource '%s/%s/%s': %s", ruleName, resource.GetKind(), resource.GetNamespace(), resource.GetName(), overlayerr.ErrorMsg()) resp.Success = true return resp, resource // conditions are not met, don't apply this rule case conditionFailure: - logger.V(3).Info("skip applying rule") + glog.V(3).Infof("Skip applying rule '%s' on resource '%s/%s/%s': %s", ruleName, resource.GetKind(), resource.GetNamespace(), resource.GetName(), overlayerr.ErrorMsg()) //TODO: send zero response and not consider this as applied? resp.Success = true resp.Message = overlayerr.ErrorMsg() return resp, resource // rule application failed case overlayFailure: - logger.Info("failed to process overlay") + glog.Errorf("Resource %s/%s/%s: failed to process overlay: %v in the rule %s", resource.GetKind(), resource.GetNamespace(), resource.GetName(), overlayerr.ErrorMsg(), ruleName) resp.Success = false resp.Message = fmt.Sprintf("failed to process overlay: %v", overlayerr.ErrorMsg()) return resp, resource default: - logger.Info("failed to process overlay") + glog.Errorf("Resource %s/%s/%s: Unknown type of error: %v", resource.GetKind(), resource.GetNamespace(), resource.GetName(), overlayerr.Error()) resp.Success = false resp.Message = fmt.Sprintf("Unknown type of error: %v", overlayerr.Error()) return resp, resource @@ -72,7 +70,7 @@ func ProcessOverlay(log logr.Logger, ruleName string, overlay interface{}, resou resourceRaw, err := resource.MarshalJSON() if err != nil { resp.Success = false - logger.Error(err, "failed to marshal resource") + glog.Infof("unable to marshall resource: %v", err) resp.Message = fmt.Sprintf("failed to process JSON patches: %v", err) return resp, resource } @@ -81,7 +79,7 @@ func ProcessOverlay(log logr.Logger, ruleName string, overlay interface{}, resou patchResource, err = utils.ApplyPatches(resourceRaw, patches) if err != nil { msg := fmt.Sprintf("failed to apply JSON patches: %v", err) - logger.V(2).Info("applying patches", "patches", string(utils.JoinPatches(patches))) + glog.V(2).Infof("%s, patches=%s", msg, string(utils.JoinPatches(patches))) resp.Success = false resp.Message = msg return resp, resource @@ -89,7 +87,7 @@ func ProcessOverlay(log logr.Logger, ruleName string, overlay interface{}, resou err = patchedResource.UnmarshalJSON(patchResource) if err != nil { - logger.Error(err, "failed to unmarshal resource") + glog.Infof("failed to unmarshall resource to undstructured: %v", err) resp.Success = false resp.Message = fmt.Sprintf("failed to process JSON patches: %v", err) return resp, resource @@ -103,17 +101,17 @@ func ProcessOverlay(log logr.Logger, ruleName string, overlay interface{}, resou return resp, patchedResource } -func processOverlayPatches(log logr.Logger, resource, overlay interface{}) ([][]byte, overlayError) { - if path, overlayerr := meetConditions(log, resource, overlay); !reflect.DeepEqual(overlayerr, overlayError{}) { +func processOverlayPatches(resource, overlay interface{}) ([][]byte, overlayError) { + if path, overlayerr := meetConditions(resource, overlay); !reflect.DeepEqual(overlayerr, overlayError{}) { switch overlayerr.statusCode { // anchor key does not exist in the resource, skip applying policy case conditionNotPresent: - log.V(4).Info("skip applying policy", "path", path, "error", overlayerr) + glog.V(4).Infof("Mutate rule: skip applying policy: %v at %s", overlayerr, path) return nil, newOverlayError(overlayerr.statusCode, fmt.Sprintf("Policy not applied, condition tag not present: %v at %s", overlayerr.ErrorMsg(), path)) // anchor key is not satisfied in the resource, skip applying policy case conditionFailure: // anchor key is not satisfied in the resource, skip applying policy - log.V(4).Info("failed to validate condition", "path", path, "error", overlayerr) + glog.V(4).Infof("Mutate rule: failed to validate condition at %s, err: %v", path, overlayerr) return nil, newOverlayError(overlayerr.statusCode, fmt.Sprintf("Policy not applied, conditions are not met at %s, %v", path, overlayerr)) } } @@ -385,7 +383,7 @@ func prepareJSONValue(overlay interface{}) string { overlayWithoutAnchors := removeAnchorFromSubTree(overlay) jsonOverlay, err := json.Marshal(overlayWithoutAnchors) if err != nil || hasOnlyAnchors(overlay) { - log.Log.Error(err, "failed to marshall withoutanchors or has only anchors") + glog.V(3).Info(err) return "" } @@ -411,7 +409,7 @@ func removeAnchorFromSubTree(overlay interface{}) interface{} { } func removeAnchroFromMap(overlay map[string]interface{}) map[string]interface{} { - result := make(map[string]interface{}) + result := make(map[string]interface{}, 0) for k, v := range overlay { result[getRawKeyIfWrappedWithAttributes(k)] = removeAnchorFromSubTree(v) } diff --git a/pkg/engine/mutate/overlayCondition.go b/pkg/engine/mutate/overlayCondition.go index 56b19de4e9..134cc23cc0 100755 --- a/pkg/engine/mutate/overlayCondition.go +++ b/pkg/engine/mutate/overlayCondition.go @@ -5,18 +5,17 @@ import ( "reflect" "strconv" - "github.com/go-logr/logr" + "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/engine/anchor" "github.com/nirmata/kyverno/pkg/engine/validate" - "sigs.k8s.io/controller-runtime/pkg/log" ) -func meetConditions(log logr.Logger, resource, overlay interface{}) (string, overlayError) { - return checkConditions(log, resource, overlay, "/") +func meetConditions(resource, overlay interface{}) (string, overlayError) { + return checkConditions(resource, overlay, "/") } // resource and overlay should be the same type -func checkConditions(log logr.Logger, resource, overlay interface{}, path string) (string, overlayError) { +func checkConditions(resource, overlay interface{}, path string) (string, overlayError) { // overlay has no anchor, return true if !hasNestedAnchors(overlay) { return "", overlayError{} @@ -27,7 +26,7 @@ func checkConditions(log logr.Logger, resource, overlay interface{}, path string // condition never be true in this case if reflect.TypeOf(resource) != reflect.TypeOf(overlay) { if hasNestedAnchors(overlay) { - log.V(4).Info(fmt.Sprintf("Found anchor on different types of element at path %s: overlay %T, resource %T", path, overlay, resource)) + glog.V(4).Infof("Found anchor on different types of element at path %s: overlay %T, resource %T", path, overlay, resource) return path, newOverlayError(conditionFailure, fmt.Sprintf("Found anchor on different types of element at path %s: overlay %T %v, resource %T %v", path, overlay, overlay, resource, resource)) @@ -45,7 +44,7 @@ func checkConditions(log logr.Logger, resource, overlay interface{}, path string default: // anchor on non map/array is invalid: // - anchor defined on values - log.Info("Found invalid conditional anchor: anchor defined on values") + glog.Warningln("Found invalid conditional anchor: anchor defined on values") return "", overlayError{} } } @@ -69,12 +68,12 @@ func checkConditionOnMap(resourceMap, overlayMap map[string]interface{}, path st func checkConditionOnArray(resource, overlay []interface{}, path string) (string, overlayError) { if 0 == len(overlay) { - log.Log.V(4).Info("Mutate overlay pattern is empty", "path", path) + glog.Infof("Mutate overlay pattern is empty, path %s", path) return "", overlayError{} } if reflect.TypeOf(resource[0]) != reflect.TypeOf(overlay[0]) { - log.Log.V(4).Info(fmt.Sprintf("Overlay array and resource array have elements of different types: %T and %T", overlay[0], resource[0])) + glog.V(4).Infof("Overlay array and resource array have elements of different types: %T and %T", overlay[0], resource[0]) return path, newOverlayError(conditionFailure, fmt.Sprintf("Overlay array and resource array have elements of different types: %T and %T", overlay[0], resource[0])) } @@ -112,7 +111,7 @@ func validateConditionAnchorMap(resourceMap, anchors map[string]interface{}, pat // resource - A: B2 func compareOverlay(resource, overlay interface{}, path string) (string, overlayError) { if reflect.TypeOf(resource) != reflect.TypeOf(overlay) { - log.Log.V(4).Info("Found anchor on different types of element: overlay %T, resource %T", overlay, resource) + glog.V(4).Infof("Found anchor on different types of element: overlay %T, resource %T", overlay, resource) return path, newOverlayError(conditionFailure, fmt.Sprintf("Found anchor on different types of element: overlay %T, resource %T", overlay, resource)) } @@ -140,8 +139,8 @@ func compareOverlay(resource, overlay interface{}, path string) (string, overlay } } case string, float64, int, int64, bool, nil: - if !validate.ValidateValueWithPattern(log.Log, resource, overlay) { - log.Log.V(4).Info(fmt.Sprintf("Mutate rule: failed validating value %v with overlay %v", resource, overlay)) + if !validate.ValidateValueWithPattern(resource, overlay) { + glog.V(4).Infof("Mutate rule: failed validating value %v with overlay %v", resource, overlay) return path, newOverlayError(conditionFailure, fmt.Sprintf("Failed validating value %v with overlay %v", resource, overlay)) } default: @@ -166,7 +165,7 @@ func validateNonAnchorOverlayMap(resourceMap, overlayWithoutAnchor map[string]in continue } } - if newPath, err := checkConditions(log.Log, resourceValue, overlayValue, curPath); !reflect.DeepEqual(err, overlayError{}) { + if newPath, err := checkConditions(resourceValue, overlayValue, curPath); !reflect.DeepEqual(err, overlayError{}) { return newPath, err } } @@ -180,7 +179,7 @@ func checkConditionsOnArrayOfSameTypes(resource, overlay []interface{}, path str default: for i, overlayElement := range overlay { curPath := path + strconv.Itoa(i) + "/" - path, err := checkConditions(log.Log, resource[i], overlayElement, curPath) + path, err := checkConditions(resource[i], overlayElement, curPath) if !reflect.DeepEqual(err, overlayError{}) { return path, err } diff --git a/pkg/engine/mutate/overlayCondition_test.go b/pkg/engine/mutate/overlayCondition_test.go index 8da6eefee9..b898acfbcd 100644 --- a/pkg/engine/mutate/overlayCondition_test.go +++ b/pkg/engine/mutate/overlayCondition_test.go @@ -7,7 +7,6 @@ import ( "testing" "gotest.tools/assert" - "sigs.k8s.io/controller-runtime/pkg/log" ) func TestMeetConditions_NoAnchor(t *testing.T) { @@ -27,11 +26,9 @@ func TestMeetConditions_NoAnchor(t *testing.T) { }`) var overlay interface{} - err := json.Unmarshal(overlayRaw, &overlay) - assert.Assert(t, reflect.DeepEqual(err, nil)) - - _, err = meetConditions(log.Log, nil, overlay) + json.Unmarshal(overlayRaw, &overlay) + _, err := meetConditions(nil, overlay) assert.Assert(t, reflect.DeepEqual(err, overlayError{})) } @@ -81,12 +78,10 @@ func TestMeetConditions_conditionalAnchorOnMap(t *testing.T) { var resource, overlay interface{} - err := json.Unmarshal(resourceRaw, &resource) - assert.NilError(t, err) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(resourceRaw, &resource) + json.Unmarshal(overlayRaw, &overlay) - _, err = meetConditions(log.Log, resource, overlay) + _, err := meetConditions(resource, overlay) assert.Assert(t, !reflect.DeepEqual(err, overlayError{})) overlayRaw = []byte(` @@ -104,10 +99,9 @@ func TestMeetConditions_conditionalAnchorOnMap(t *testing.T) { ] }`) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(overlayRaw, &overlay) - _, overlayerr := meetConditions(log.Log, resource, overlay) + _, overlayerr := meetConditions(resource, overlay) assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{})) } @@ -142,14 +136,11 @@ func TestMeetConditions_DifferentTypes(t *testing.T) { }`) var resource, overlay interface{} - err := json.Unmarshal(resourceRaw, &resource) - assert.NilError(t, err) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(resourceRaw, &resource) + json.Unmarshal(overlayRaw, &overlay) // anchor exist - - _, err = meetConditions(log.Log, resource, overlay) + _, err := meetConditions(resource, overlay) assert.Assert(t, strings.Contains(err.Error(), "Found anchor on different types of element at path /subsets/")) } @@ -199,12 +190,10 @@ func TestMeetConditions_anchosInSameObject(t *testing.T) { var resource, overlay interface{} - err := json.Unmarshal(resourceRaw, &resource) - assert.NilError(t, err) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(resourceRaw, &resource) + json.Unmarshal(overlayRaw, &overlay) - _, err = meetConditions(log.Log, resource, overlay) + _, err := meetConditions(resource, overlay) assert.Error(t, err, "[overlayError:0] Failed validating value 443 with overlay 444") } @@ -259,13 +248,10 @@ func TestMeetConditions_anchorOnPeer(t *testing.T) { var resource, overlay interface{} - err := json.Unmarshal(resourceRaw, &resource) - assert.NilError(t, err) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) - - _, err = meetConditions(log.Log, resource, overlay) + json.Unmarshal(resourceRaw, &resource) + json.Unmarshal(overlayRaw, &overlay) + _, err := meetConditions(resource, overlay) assert.Assert(t, reflect.DeepEqual(err, overlayError{})) } @@ -339,13 +325,10 @@ func TestMeetConditions_anchorsOnMetaAndSpec(t *testing.T) { var resource, overlay interface{} - err := json.Unmarshal(resourceRaw, &resource) - assert.NilError(t, err) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) - - _, err = meetConditions(log.Log, resource, overlay) + json.Unmarshal(resourceRaw, &resource) + json.Unmarshal(overlayRaw, &overlay) + _, err := meetConditions(resource, overlay) assert.Assert(t, reflect.DeepEqual(err, overlayError{})) } @@ -423,13 +406,10 @@ func TestMeetConditions_anchorsOnPeer_single(t *testing.T) { var resource, overlay interface{} - err := json.Unmarshal(resourceRawAnchorOnPeers, &resource) - assert.NilError(t, err) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) - - _, err = meetConditions(log.Log, resource, overlay) + json.Unmarshal(resourceRawAnchorOnPeers, &resource) + json.Unmarshal(overlayRaw, &overlay) + _, err := meetConditions(resource, overlay) assert.Assert(t, reflect.DeepEqual(err, overlayError{})) } @@ -460,13 +440,10 @@ func TestMeetConditions_anchorsOnPeer_two(t *testing.T) { var resource, overlay interface{} - err := json.Unmarshal(resourceRawAnchorOnPeers, &resource) - assert.NilError(t, err) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) - - _, err = meetConditions(log.Log, resource, overlay) + json.Unmarshal(resourceRawAnchorOnPeers, &resource) + json.Unmarshal(overlayRaw, &overlay) + _, err := meetConditions(resource, overlay) assert.Error(t, err, "[overlayError:0] Failed validating value true with overlay false") overlayRaw = []byte(`{ @@ -493,10 +470,9 @@ func TestMeetConditions_anchorsOnPeer_two(t *testing.T) { } }`) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(overlayRaw, &overlay) - _, err = meetConditions(log.Log, resource, overlay) + _, err = meetConditions(resource, overlay) assert.Assert(t, reflect.DeepEqual(err, overlayError{})) overlayRaw = []byte(`{ @@ -523,10 +499,9 @@ func TestMeetConditions_anchorsOnPeer_two(t *testing.T) { } }`) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(overlayRaw, &overlay) - _, err = meetConditions(log.Log, resource, overlay) + _, err = meetConditions(resource, overlay) assert.Assert(t, reflect.DeepEqual(err, overlayError{})) } @@ -557,13 +532,10 @@ func TestMeetConditions_anchorsOnPeer_multiple(t *testing.T) { var resource, overlay interface{} - err := json.Unmarshal(resourceRawAnchorOnPeers, &resource) - assert.NilError(t, err) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) - - _, err = meetConditions(log.Log, resource, overlay) + json.Unmarshal(resourceRawAnchorOnPeers, &resource) + json.Unmarshal(overlayRaw, &overlay) + _, err := meetConditions(resource, overlay) assert.Assert(t, reflect.DeepEqual(err, overlayError{})) overlayRaw = []byte(`{ @@ -590,10 +562,9 @@ func TestMeetConditions_anchorsOnPeer_multiple(t *testing.T) { } }`) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(overlayRaw, &overlay) - _, err = meetConditions(log.Log, resource, overlay) + _, err = meetConditions(resource, overlay) assert.Assert(t, reflect.DeepEqual(err, overlayError{})) overlayRaw = []byte(`{ @@ -620,10 +591,9 @@ func TestMeetConditions_anchorsOnPeer_multiple(t *testing.T) { } }`) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(overlayRaw, &overlay) - _, err = meetConditions(log.Log, resource, overlay) + _, err = meetConditions(resource, overlay) assert.Error(t, err, "[overlayError:0] Failed validating value ENV_VALUE with overlay ENV_VALUE1") } @@ -679,13 +649,10 @@ func TestMeetConditions_AtleastOneExist(t *testing.T) { var resource, overlay interface{} - err := json.Unmarshal(resourceRaw, &resource) - assert.NilError(t, err) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) - - path, err := meetConditions(log.Log, resource, overlay) + json.Unmarshal(resourceRaw, &resource) + json.Unmarshal(overlayRaw, &overlay) + path, err := meetConditions(resource, overlay) assert.Assert(t, reflect.DeepEqual(err, overlayError{})) assert.Assert(t, len(path) == 0) } diff --git a/pkg/engine/mutate/overlay_test.go b/pkg/engine/mutate/overlay_test.go index a7c8890039..8c062fe58d 100644 --- a/pkg/engine/mutate/overlay_test.go +++ b/pkg/engine/mutate/overlay_test.go @@ -8,7 +8,6 @@ import ( jsonpatch "github.com/evanphx/json-patch" "github.com/nirmata/kyverno/pkg/engine/utils" "gotest.tools/assert" - "sigs.k8s.io/controller-runtime/pkg/log" ) func compareJSONAsMap(t *testing.T, expected, actual []byte) { @@ -64,12 +63,10 @@ func TestProcessOverlayPatches_NestedListWithAnchor(t *testing.T) { var resource, overlay interface{} - err := json.Unmarshal(resourceRaw, &resource) - assert.NilError(t, err) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(resourceRaw, &resource) + json.Unmarshal(overlayRaw, &overlay) - patches, overlayerr := processOverlayPatches(log.Log, resource, overlay) + patches, overlayerr := processOverlayPatches(resource, overlay) assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{})) assert.Assert(t, patches != nil) @@ -166,12 +163,10 @@ func TestProcessOverlayPatches_InsertIntoArray(t *testing.T) { var resource, overlay interface{} - err := json.Unmarshal(resourceRaw, &resource) - assert.NilError(t, err) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(resourceRaw, &resource) + json.Unmarshal(overlayRaw, &overlay) - patches, overlayerr := processOverlayPatches(log.Log, resource, overlay) + patches, overlayerr := processOverlayPatches(resource, overlay) assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{})) assert.Assert(t, patches != nil) @@ -289,12 +284,10 @@ func TestProcessOverlayPatches_TestInsertToArray(t *testing.T) { var resource, overlay interface{} - err := json.Unmarshal(resourceRaw, &resource) - assert.NilError(t, err) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(resourceRaw, &resource) + json.Unmarshal(overlayRaw, &overlay) - patches, overlayerr := processOverlayPatches(log.Log, resource, overlay) + patches, overlayerr := processOverlayPatches(resource, overlay) assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{})) assert.Assert(t, patches != nil) @@ -374,12 +367,10 @@ func TestProcessOverlayPatches_ImagePullPolicy(t *testing.T) { var resource, overlay interface{} - err := json.Unmarshal(resourceRaw, &resource) - assert.NilError(t, err) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(resourceRaw, &resource) + json.Unmarshal(overlayRaw, &overlay) - patches, overlayerr := processOverlayPatches(log.Log, resource, overlay) + patches, overlayerr := processOverlayPatches(resource, overlay) assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{})) assert.Assert(t, len(patches) != 0) @@ -465,10 +456,9 @@ func TestProcessOverlayPatches_ImagePullPolicy(t *testing.T) { } }`) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(overlayRaw, &overlay) - patches, err = processOverlayPatches(log.Log, resource, overlay) + patches, err = processOverlayPatches(resource, overlay) assert.Assert(t, reflect.DeepEqual(err, overlayError{})) assert.Assert(t, len(patches) != 0) @@ -502,10 +492,9 @@ func TestProcessOverlayPatches_ImagePullPolicy(t *testing.T) { } }`) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(overlayRaw, &overlay) - patches, err = processOverlayPatches(log.Log, resource, overlay) + patches, err = processOverlayPatches(resource, overlay) assert.Error(t, err, "[overlayError:0] Policy not applied, conditions are not met at /spec/template/metadata/labels/app/, [overlayError:0] Failed validating value nginx with overlay nginx1") assert.Assert(t, len(patches) == 0) } @@ -531,12 +520,10 @@ func TestProcessOverlayPatches_AddingAnchor(t *testing.T) { var resource, overlay interface{} - err := json.Unmarshal(resourceRaw, &resource) - assert.NilError(t, err) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(resourceRaw, &resource) + json.Unmarshal(overlayRaw, &overlay) - patches, overlayerr := processOverlayPatches(log.Log, resource, overlay) + patches, overlayerr := processOverlayPatches(resource, overlay) assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{})) assert.Assert(t, len(patches) != 0) @@ -618,12 +605,10 @@ func TestProcessOverlayPatches_AddingAnchorInsideListElement(t *testing.T) { var resource, overlay interface{} - err := json.Unmarshal(resourceRaw, &resource) - assert.NilError(t, err) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(resourceRaw, &resource) + json.Unmarshal(overlayRaw, &overlay) - patches, overlayerr := processOverlayPatches(log.Log, resource, overlay) + patches, overlayerr := processOverlayPatches(resource, overlay) assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{})) assert.Assert(t, len(patches) != 0) @@ -699,10 +684,9 @@ func TestProcessOverlayPatches_AddingAnchorInsideListElement(t *testing.T) { } }`) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(overlayRaw, &overlay) - patches, err = processOverlayPatches(log.Log, resource, overlay) + patches, err = processOverlayPatches(resource, overlay) assert.Assert(t, reflect.DeepEqual(err, overlayError{})) assert.Assert(t, len(patches) != 0) @@ -763,12 +747,10 @@ func TestProcessOverlayPatches_anchorOnPeer(t *testing.T) { var resource, overlay interface{} - err := json.Unmarshal(resourceRaw, &resource) - assert.NilError(t, err) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(resourceRaw, &resource) + json.Unmarshal(overlayRaw, &overlay) - patches, overlayerr := processOverlayPatches(log.Log, resource, overlay) + patches, overlayerr := processOverlayPatches(resource, overlay) assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{})) assert.Assert(t, len(patches) != 0) @@ -823,10 +805,9 @@ func TestProcessOverlayPatches_anchorOnPeer(t *testing.T) { ] }`) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(overlayRaw, &overlay) - patches, err = processOverlayPatches(log.Log, resource, overlay) + patches, err = processOverlayPatches(resource, overlay) assert.Error(t, err, "[overlayError:0] Policy not applied, conditions are not met at /subsets/0/ports/0/port/, [overlayError:0] Failed validating value 443 with overlay 444") assert.Assert(t, len(patches) == 0) } @@ -905,12 +886,10 @@ func TestProcessOverlayPatches_insertWithCondition(t *testing.T) { var resource, overlay interface{} - err := json.Unmarshal(resourceRaw, &resource) - assert.NilError(t, err) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(resourceRaw, &resource) + json.Unmarshal(overlayRaw, &overlay) - patches, overlayerr := processOverlayPatches(log.Log, resource, overlay) + patches, overlayerr := processOverlayPatches(resource, overlay) assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{})) assert.Assert(t, len(patches) != 0) @@ -1018,12 +997,10 @@ func TestProcessOverlayPatches_InsertIfNotPresentWithConditions(t *testing.T) { var resource, overlay interface{} - err := json.Unmarshal(resourceRaw, &resource) - assert.NilError(t, err) - err = json.Unmarshal(overlayRaw, &overlay) - assert.NilError(t, err) + json.Unmarshal(resourceRaw, &resource) + json.Unmarshal(overlayRaw, &overlay) - patches, overlayerr := processOverlayPatches(log.Log, resource, overlay) + patches, overlayerr := processOverlayPatches(resource, overlay) assert.Assert(t, reflect.DeepEqual(overlayerr, overlayError{})) assert.Assert(t, len(patches) != 0) diff --git a/pkg/engine/mutate/patches.go b/pkg/engine/mutate/patches.go index 7b294bbca9..61fc93ecea 100644 --- a/pkg/engine/mutate/patches.go +++ b/pkg/engine/mutate/patches.go @@ -6,7 +6,7 @@ import ( "strings" "time" - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine/response" "github.com/nirmata/kyverno/pkg/engine/utils" @@ -20,22 +20,21 @@ func applyPatch(resource []byte, patchRaw []byte) ([]byte, error) { } //ProcessPatches applies the patches on the resource and returns the patched resource -func ProcessPatches(log logr.Logger, rule kyverno.Rule, resource unstructured.Unstructured) (resp response.RuleResponse, patchedResource unstructured.Unstructured) { - logger := log.WithValues("rule", rule.Name) +func ProcessPatches(rule kyverno.Rule, resource unstructured.Unstructured) (resp response.RuleResponse, patchedResource unstructured.Unstructured) { startTime := time.Now() - logger.V(4).Info("started JSON patch", "startTime", startTime) + glog.V(4).Infof("started JSON patch rule %q (%v)", rule.Name, startTime) resp.Name = rule.Name resp.Type = utils.Mutation.String() defer func() { resp.RuleStats.ProcessingTime = time.Since(startTime) - logger.V(4).Info("finished JSON patch", "processingTime", resp.RuleStats.ProcessingTime) + glog.V(4).Infof("finished JSON patch rule %q (%v)", resp.Name, resp.RuleStats.ProcessingTime) }() // convert to RAW resourceRaw, err := resource.MarshalJSON() if err != nil { resp.Success = false - logger.Error(err, "failed to marshal resource") + glog.Infof("unable to marshall resource: %v", err) resp.Message = fmt.Sprintf("failed to process JSON patches: %v", err) return resp, resource } @@ -46,14 +45,14 @@ func ProcessPatches(log logr.Logger, rule kyverno.Rule, resource unstructured.Un // JSON patch patchRaw, err := json.Marshal(patch) if err != nil { - logger.Error(err, "failed to marshal JSON patch") + glog.V(4).Infof("failed to marshall JSON patch %v: %v", patch, err) errs = append(errs, err) continue } patchResource, err := applyPatch(resourceRaw, patchRaw) // TODO: continue on error if one of the patches fails, will add the failure event in such case if err != nil && patch.Operation == "remove" { - log.Error(err, "failed to process JSON path or patch is a 'remove' operation") + glog.Info(err) continue } if err != nil { @@ -78,7 +77,7 @@ func ProcessPatches(log logr.Logger, rule kyverno.Rule, resource unstructured.Un } err = patchedResource.UnmarshalJSON(resourceRaw) if err != nil { - logger.Error(err, "failed to unmmarshal resource") + glog.Infof("failed to unmarshall resource to undstructured: %v", err) resp.Success = false resp.Message = fmt.Sprintf("failed to process JSON patches: %v", err) return resp, resource diff --git a/pkg/engine/mutate/patches_test.go b/pkg/engine/mutate/patches_test.go index 1b617d5517..f38b68d2c4 100644 --- a/pkg/engine/mutate/patches_test.go +++ b/pkg/engine/mutate/patches_test.go @@ -5,7 +5,6 @@ import ( "gotest.tools/assert" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sigs.k8s.io/controller-runtime/pkg/log" types "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine/utils" @@ -42,7 +41,7 @@ func TestProcessPatches_EmptyPatches(t *testing.T) { if err != nil { t.Error(err) } - rr, _ := ProcessPatches(log.Log, emptyRule, *resourceUnstructured) + rr, _ := ProcessPatches(emptyRule, *resourceUnstructured) assert.Check(t, rr.Success) assert.Assert(t, len(rr.Patches) == 0) } @@ -71,14 +70,14 @@ func makeRuleWithPatches(patches []types.Patch) types.Rule { func TestProcessPatches_EmptyDocument(t *testing.T) { rule := makeRuleWithPatch(makeAddIsMutatedLabelPatch()) - rr, _ := ProcessPatches(log.Log, rule, unstructured.Unstructured{}) + rr, _ := ProcessPatches(rule, unstructured.Unstructured{}) assert.Assert(t, !rr.Success) assert.Assert(t, len(rr.Patches) == 0) } func TestProcessPatches_AllEmpty(t *testing.T) { emptyRule := types.Rule{} - rr, _ := ProcessPatches(log.Log, emptyRule, unstructured.Unstructured{}) + rr, _ := ProcessPatches(emptyRule, unstructured.Unstructured{}) assert.Check(t, !rr.Success) assert.Assert(t, len(rr.Patches) == 0) } @@ -91,7 +90,7 @@ func TestProcessPatches_AddPathDoesntExist(t *testing.T) { if err != nil { t.Error(err) } - rr, _ := ProcessPatches(log.Log, rule, *resourceUnstructured) + rr, _ := ProcessPatches(rule, *resourceUnstructured) assert.Check(t, !rr.Success) assert.Assert(t, len(rr.Patches) == 0) } @@ -103,7 +102,7 @@ func TestProcessPatches_RemovePathDoesntExist(t *testing.T) { if err != nil { t.Error(err) } - rr, _ := ProcessPatches(log.Log, rule, *resourceUnstructured) + rr, _ := ProcessPatches(rule, *resourceUnstructured) assert.Check(t, rr.Success) assert.Assert(t, len(rr.Patches) == 0) } @@ -116,7 +115,7 @@ func TestProcessPatches_AddAndRemovePathsDontExist_EmptyResult(t *testing.T) { if err != nil { t.Error(err) } - rr, _ := ProcessPatches(log.Log, rule, *resourceUnstructured) + rr, _ := ProcessPatches(rule, *resourceUnstructured) assert.Check(t, !rr.Success) assert.Assert(t, len(rr.Patches) == 0) } @@ -130,7 +129,7 @@ func TestProcessPatches_AddAndRemovePathsDontExist_ContinueOnError_NotEmptyResul if err != nil { t.Error(err) } - rr, _ := ProcessPatches(log.Log, rule, *resourceUnstructured) + rr, _ := ProcessPatches(rule, *resourceUnstructured) assert.Check(t, rr.Success) assert.Assert(t, len(rr.Patches) != 0) assertEqStringAndData(t, `{"path":"/metadata/labels/label3","op":"add","value":"label3Value"}`, rr.Patches[0]) @@ -143,7 +142,7 @@ func TestProcessPatches_RemovePathDoesntExist_EmptyResult(t *testing.T) { if err != nil { t.Error(err) } - rr, _ := ProcessPatches(log.Log, rule, *resourceUnstructured) + rr, _ := ProcessPatches(rule, *resourceUnstructured) assert.Check(t, rr.Success) assert.Assert(t, len(rr.Patches) == 0) } @@ -156,7 +155,7 @@ func TestProcessPatches_RemovePathDoesntExist_NotEmptyResult(t *testing.T) { if err != nil { t.Error(err) } - rr, _ := ProcessPatches(log.Log, rule, *resourceUnstructured) + rr, _ := ProcessPatches(rule, *resourceUnstructured) assert.Check(t, rr.Success) assert.Assert(t, len(rr.Patches) == 1) assertEqStringAndData(t, `{"path":"/metadata/labels/label2","op":"add","value":"label2Value"}`, rr.Patches[0]) diff --git a/pkg/engine/mutation.go b/pkg/engine/mutation.go index b147f5b490..d1fab46211 100644 --- a/pkg/engine/mutation.go +++ b/pkg/engine/mutation.go @@ -5,13 +5,12 @@ import ( "strings" "time" - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine/mutate" "github.com/nirmata/kyverno/pkg/engine/response" "github.com/nirmata/kyverno/pkg/engine/variables" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sigs.k8s.io/controller-runtime/pkg/log" ) const ( @@ -29,25 +28,26 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) { policy := policyContext.Policy resource := policyContext.NewResource ctx := policyContext.Context - logger := log.Log.WithName("Mutate").WithValues("policy", policy.Name, "kind", resource.GetKind(), "namespace", resource.GetNamespace(), "name", resource.GetName()) - logger.V(4).Info("start processing", "startTime", startTime) + startMutateResultResponse(&resp, policy, resource) - defer endMutateResultResponse(logger, &resp, startTime) + glog.V(4).Infof("started applying mutation rules of policy %q (%v)", policy.Name, startTime) + defer endMutateResultResponse(&resp, startTime) patchedResource := policyContext.NewResource for _, rule := range policy.Spec.Rules { var ruleResponse response.RuleResponse - logger := logger.WithValues("rule", rule.Name) //TODO: to be checked before calling the resources as well if !rule.HasMutate() && !strings.Contains(PodControllers, resource.GetKind()) { continue } + startTime := time.Now() + glog.V(4).Infof("Time: Mutate matchAdmissionInfo %v", time.Since(startTime)) // check if the resource satisfies the filter conditions defined in the rule //TODO: this needs to be extracted, to filter the resource so that we can avoid passing resources that // dont statisfy a policy rule resource description if err := MatchesResourceDescription(resource, rule, policyContext.AdmissionInfo); err != nil { - logger.V(4).Info("resource fails the match description") + glog.V(4).Infof("resource %s/%s does not satisfy the resource description for the rule:\n%s", resource.GetNamespace(), resource.GetName(), err.Error()) continue } @@ -55,8 +55,8 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) { copyConditions := copyConditions(rule.Conditions) // evaluate pre-conditions // - handle variable subsitutions - if !variables.EvaluateConditions(logger, ctx, copyConditions) { - logger.V(4).Info("resource fails the preconditions") + if !variables.EvaluateConditions(ctx, copyConditions) { + glog.V(4).Infof("resource %s/%s does not satisfy the conditions for the rule ", resource.GetNamespace(), resource.GetName()) continue } @@ -66,7 +66,7 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) { overlay := mutation.Overlay // subsiitue the variables var err error - if overlay, err = variables.SubstituteVars(logger, ctx, overlay); err != nil { + if overlay, err = variables.SubstituteVars(ctx, overlay); err != nil { // variable subsitution failed ruleResponse.Success = false ruleResponse.Message = err.Error() @@ -74,13 +74,15 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) { continue } - ruleResponse, patchedResource = mutate.ProcessOverlay(logger, rule.Name, overlay, patchedResource) + ruleResponse, patchedResource = mutate.ProcessOverlay(rule.Name, overlay, patchedResource) if ruleResponse.Success { // - overlay pattern does not match the resource conditions if ruleResponse.Patches == nil { + glog.V(4).Infof(ruleResponse.Message) continue } - logger.V(4).Info("overlay applied succesfully") + + glog.V(4).Infof("Mutate overlay in rule '%s' successfully applied on %s/%s/%s", rule.Name, resource.GetKind(), resource.GetNamespace(), resource.GetName()) } resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, ruleResponse) @@ -90,8 +92,8 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) { // Process Patches if rule.Mutation.Patches != nil { var ruleResponse response.RuleResponse - ruleResponse, patchedResource = mutate.ProcessPatches(logger, rule, patchedResource) - logger.V(4).Info("patches applied successfully") + ruleResponse, patchedResource = mutate.ProcessPatches(rule, patchedResource) + glog.Infof("Mutate patches in rule '%s' successfully applied on %s/%s/%s", rule.Name, resource.GetKind(), resource.GetNamespace(), resource.GetName()) resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, ruleResponse) incrementAppliedRuleCount(&resp) } @@ -104,14 +106,14 @@ func Mutate(policyContext PolicyContext) (resp response.EngineResponse) { if strings.Contains(PodControllers, resource.GetKind()) { var ruleResponse response.RuleResponse - ruleResponse, patchedResource = mutate.ProcessOverlay(logger, rule.Name, podTemplateRule, patchedResource) + ruleResponse, patchedResource = mutate.ProcessOverlay(rule.Name, podTemplateRule, patchedResource) if !ruleResponse.Success { - logger.Info("failed to insert annotation for podTemplate", "error", ruleResponse.Message) + glog.Errorf("Failed to insert annotation to podTemplate of %s/%s/%s: %s", resource.GetKind(), resource.GetNamespace(), resource.GetName(), ruleResponse.Message) continue } if ruleResponse.Success && ruleResponse.Patches != nil { - logger.V(2).Info("inserted annotation for podTemplate") + glog.V(2).Infof("Inserted annotation to podTemplate of %s/%s/%s: %s", resource.GetKind(), resource.GetNamespace(), resource.GetName(), ruleResponse.Message) resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, ruleResponse) } } @@ -135,9 +137,10 @@ func startMutateResultResponse(resp *response.EngineResponse, policy kyverno.Clu // TODO(shuting): set response with mutationFailureAction } -func endMutateResultResponse(logger logr.Logger, resp *response.EngineResponse, startTime time.Time) { +func endMutateResultResponse(resp *response.EngineResponse, startTime time.Time) { resp.PolicyResponse.ProcessingTime = time.Since(startTime) - logger.V(4).Info("finshed processing", "processingTime", resp.PolicyResponse.ProcessingTime, "mutationRulesApplied", resp.PolicyResponse.RulesAppliedCount) + glog.V(4).Infof("finished applying mutation rules policy %v (%v)", resp.PolicyResponse.Policy, resp.PolicyResponse.ProcessingTime) + glog.V(4).Infof("Mutation Rules appplied count %v for policy %q", resp.PolicyResponse.RulesAppliedCount, resp.PolicyResponse.Policy) } // podTemplateRule mutate pod template with annotation diff --git a/pkg/engine/mutation_test.go b/pkg/engine/mutation_test.go index 07f345e265..278d9672f2 100644 --- a/pkg/engine/mutation_test.go +++ b/pkg/engine/mutation_test.go @@ -67,17 +67,11 @@ func Test_VariableSubstitutionOverlay(t *testing.T) { expectedPatch := []byte(`{ "op": "add", "path": "/metadata/labels", "value":{"appname":"check-root-user"} }`) var policy kyverno.ClusterPolicy - err := json.Unmarshal(rawPolicy, &policy) - if err != nil { - t.Error(err) - } + json.Unmarshal(rawPolicy, &policy) resourceUnstructured, err := utils.ConvertToUnstructured(rawResource) assert.NilError(t, err) ctx := context.NewContext() - err = ctx.AddResource(rawResource) - if err != nil { - t.Error(err) - } + ctx.AddResource(rawResource) value, err := ctx.Query("request.object.metadata.name") t.Log(value) if err != nil { @@ -145,14 +139,12 @@ func Test_variableSubstitutionPathNotExist(t *testing.T) { }`) var policy kyverno.ClusterPolicy - err := json.Unmarshal(policyraw, &policy) - assert.NilError(t, err) + json.Unmarshal(policyraw, &policy) resourceUnstructured, err := utils.ConvertToUnstructured(resourceRaw) assert.NilError(t, err) ctx := context.NewContext() - err = ctx.AddResource(resourceRaw) - assert.NilError(t, err) + ctx.AddResource(resourceRaw) policyContext := PolicyContext{ Policy: policy, diff --git a/pkg/engine/utils.go b/pkg/engine/utils.go index 1ee8449d23..c97b2eccb8 100644 --- a/pkg/engine/utils.go +++ b/pkg/engine/utils.go @@ -9,7 +9,8 @@ import ( "github.com/nirmata/kyverno/pkg/utils" authenticationv1 "k8s.io/api/authentication/v1" rbacv1 "k8s.io/api/rbac/v1" - "sigs.k8s.io/controller-runtime/pkg/log" + + "github.com/golang/glog" "github.com/minio/minio/pkg/wildcard" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" @@ -52,7 +53,7 @@ func checkNameSpace(namespaces []string, resourceNameSpace string) bool { func checkSelector(labelSelector *metav1.LabelSelector, resourceLabels map[string]string) (bool, error) { selector, err := metav1.LabelSelectorAsSelector(labelSelector) if err != nil { - log.Log.Error(err, "failed to build label selector") + glog.Error(err) return false, err } diff --git a/pkg/engine/validate/pattern.go b/pkg/engine/validate/pattern.go index 7779f9b6ca..e7b37283bd 100644 --- a/pkg/engine/validate/pattern.go +++ b/pkg/engine/validate/pattern.go @@ -1,13 +1,12 @@ package validate import ( - "fmt" "math" "regexp" "strconv" "strings" - "github.com/go-logr/logr" + "github.com/golang/glog" "github.com/minio/minio/pkg/wildcard" "github.com/nirmata/kyverno/pkg/engine/operator" apiresource "k8s.io/apimachinery/pkg/api/resource" @@ -22,52 +21,52 @@ const ( ) // ValidateValueWithPattern validates value with operators and wildcards -func ValidateValueWithPattern(log logr.Logger, value, pattern interface{}) bool { +func ValidateValueWithPattern(value, pattern interface{}) bool { switch typedPattern := pattern.(type) { case bool: typedValue, ok := value.(bool) if !ok { - log.V(4).Info("Expected type bool", "type", fmt.Sprintf("%T", value), "value", value) + glog.V(4).Infof("Expected bool, found %T", value) return false } return typedPattern == typedValue case int: - return validateValueWithIntPattern(log, value, int64(typedPattern)) + return validateValueWithIntPattern(value, int64(typedPattern)) case int64: - return validateValueWithIntPattern(log, value, typedPattern) + return validateValueWithIntPattern(value, typedPattern) case float64: - return validateValueWithFloatPattern(log, value, typedPattern) + return validateValueWithFloatPattern(value, typedPattern) case string: - return validateValueWithStringPatterns(log, value, typedPattern) + return validateValueWithStringPatterns(value, typedPattern) case nil: - return validateValueWithNilPattern(log, value) + return validateValueWithNilPattern(value) case map[string]interface{}: // TODO: check if this is ever called? - return validateValueWithMapPattern(log, value, typedPattern) + return validateValueWithMapPattern(value, typedPattern) case []interface{}: // TODO: check if this is ever called? - log.Info("arrays as patterns is not supported") + glog.Warning("Arrays as patterns are not supported") return false default: - log.Info("Unkown type", "type", fmt.Sprintf("%T", typedPattern), "value", typedPattern) + glog.Warningf("Unknown type as pattern: %v", typedPattern) return false } } -func validateValueWithMapPattern(log logr.Logger, value interface{}, typedPattern map[string]interface{}) bool { +func validateValueWithMapPattern(value interface{}, typedPattern map[string]interface{}) bool { // verify the type of the resource value is map[string]interface, // we only check for existence of object, not the equality of content and value //TODO: check if adding _, ok := value.(map[string]interface{}) if !ok { - log.Info("Expected type map[string]interface{}", "type", fmt.Sprintf("%T", value), "value", value) + glog.Warningf("Expected map[string]interface{}, found %T\n", value) return false } return true } // Handler for int values during validation process -func validateValueWithIntPattern(log logr.Logger, value interface{}, pattern int64) bool { +func validateValueWithIntPattern(value interface{}, pattern int64) bool { switch typedValue := value.(type) { case int: return int64(typedValue) == pattern @@ -79,38 +78,38 @@ func validateValueWithIntPattern(log logr.Logger, value interface{}, pattern int return int64(typedValue) == pattern } - log.Info("Expected type int", "type", fmt.Sprintf("%T", typedValue), "value", typedValue) + glog.Warningf("Expected int, found float: %f\n", typedValue) return false case string: // extract int64 from string int64Num, err := strconv.ParseInt(typedValue, 10, 64) if err != nil { - log.Error(err, "Failed to parse int64 from string") + glog.Warningf("Failed to parse int64 from string: %v", err) return false } return int64Num == pattern default: - log.Info("Expected type int", "type", fmt.Sprintf("%T", value), "value", value) + glog.Warningf("Expected int, found: %T\n", value) return false } } // Handler for float values during validation process -func validateValueWithFloatPattern(log logr.Logger, value interface{}, pattern float64) bool { +func validateValueWithFloatPattern(value interface{}, pattern float64) bool { switch typedValue := value.(type) { case int: // check that float has no fraction if pattern == math.Trunc(pattern) { return int(pattern) == value } - log.Info("Expected type float", "type", fmt.Sprintf("%T", typedValue), "value", typedValue) + glog.Warningf("Expected float, found int: %d\n", typedValue) return false case int64: // check that float has no fraction if pattern == math.Trunc(pattern) { return int64(pattern) == value } - log.Info("Expected type float", "type", fmt.Sprintf("%T", typedValue), "value", typedValue) + glog.Warningf("Expected float, found int: %d\n", typedValue) return false case float64: return typedValue == pattern @@ -118,18 +117,18 @@ func validateValueWithFloatPattern(log logr.Logger, value interface{}, pattern f // extract float64 from string float64Num, err := strconv.ParseFloat(typedValue, 64) if err != nil { - log.Error(err, "Failed to parse float64 from string") + glog.Warningf("Failed to parse float64 from string: %v", err) return false } return float64Num == pattern default: - log.Info("Expected type float", "type", fmt.Sprintf("%T", value), "value", value) + glog.Warningf("Expected float, found: %T\n", value) return false } } // Handler for nil values during validation process -func validateValueWithNilPattern(log logr.Logger, value interface{}) bool { +func validateValueWithNilPattern(value interface{}) bool { switch typed := value.(type) { case float64: return typed == 0.0 @@ -144,20 +143,20 @@ func validateValueWithNilPattern(log logr.Logger, value interface{}) bool { case nil: return true case map[string]interface{}, []interface{}: - log.Info("Maps and arrays could not be checked with nil pattern") + glog.Warningf("Maps and arrays could not be checked with nil pattern") return false default: - log.Info("Unknown type as value when checking for nil pattern", "type", fmt.Sprintf("%T", value), "value", value) + glog.Warningf("Unknown type as value when checking for nil pattern: %T\n", value) return false } } // Handler for pattern values during validation process -func validateValueWithStringPatterns(log logr.Logger, value interface{}, pattern string) bool { +func validateValueWithStringPatterns(value interface{}, pattern string) bool { statements := strings.Split(pattern, "|") for _, statement := range statements { statement = strings.Trim(statement, " ") - if validateValueWithStringPattern(log, value, statement) { + if validateValueWithStringPattern(value, statement) { return true } } @@ -167,24 +166,24 @@ func validateValueWithStringPatterns(log logr.Logger, value interface{}, pattern // Handler for single pattern value during validation process // Detects if pattern has a number -func validateValueWithStringPattern(log logr.Logger, value interface{}, pattern string) bool { +func validateValueWithStringPattern(value interface{}, pattern string) bool { operator := operator.GetOperatorFromStringPattern(pattern) pattern = pattern[len(operator):] number, str := getNumberAndStringPartsFromPattern(pattern) if "" == number { - return validateString(log, value, str, operator) + return validateString(value, str, operator) } - return validateNumberWithStr(log, value, pattern, operator) + return validateNumberWithStr(value, pattern, operator) } // Handler for string values -func validateString(log logr.Logger, value interface{}, pattern string, operatorVariable operator.Operator) bool { +func validateString(value interface{}, pattern string, operatorVariable operator.Operator) bool { if operator.NotEqual == operatorVariable || operator.Equal == operatorVariable { strValue, ok := value.(string) if !ok { - log.Info("Expected type string", "type", fmt.Sprintf("%T", value), "value", value) + glog.Warningf("Expected string, found %T\n", value) return false } @@ -196,16 +195,17 @@ func validateString(log logr.Logger, value interface{}, pattern string, operator return wildcardResult } - log.Info("Operators >, >=, <, <= are not applicable to strings") + + glog.Warningf("Operators >, >=, <, <= are not applicable to strings") return false } // validateNumberWithStr compares quantity if pattern type is quantity // or a wildcard match to pattern string -func validateNumberWithStr(log logr.Logger, value interface{}, pattern string, operator operator.Operator) bool { +func validateNumberWithStr(value interface{}, pattern string, operator operator.Operator) bool { typedValue, err := convertToString(value) if err != nil { - log.Error(err, "failed to convert to string") + glog.Warning(err) return false } @@ -214,7 +214,7 @@ func validateNumberWithStr(log logr.Logger, value interface{}, pattern string, o if err == nil { valueQuan, err := apiresource.ParseQuantity(typedValue) if err != nil { - log.Error(err, "invalid quantity in resource", "type", fmt.Sprintf("%T", typedValue), "value", typedValue) + glog.Warningf("Invalid quantity in resource %s, err: %v\n", typedValue, err) return false } @@ -223,7 +223,7 @@ func validateNumberWithStr(log logr.Logger, value interface{}, pattern string, o // 2. wildcard match if !wildcard.Match(pattern, typedValue) { - log.Info("value failed wildcard check", "type", fmt.Sprintf("%T", typedValue), "value", typedValue, "check", pattern) + glog.Warningf("Value '%s' has not passed wildcard check: %s", typedValue, pattern) return false } return true diff --git a/pkg/engine/validate/pattern_test.go b/pkg/engine/validate/pattern_test.go index 8d8d437d2b..8ee4e34881 100644 --- a/pkg/engine/validate/pattern_test.go +++ b/pkg/engine/validate/pattern_test.go @@ -6,14 +6,13 @@ import ( "github.com/nirmata/kyverno/pkg/engine/operator" "gotest.tools/assert" - "sigs.k8s.io/controller-runtime/pkg/log" ) func TestValidateValueWithPattern_Bool(t *testing.T) { - assert.Assert(t, ValidateValueWithPattern(log.Log, true, true)) - assert.Assert(t, !ValidateValueWithPattern(log.Log, true, false)) - assert.Assert(t, !ValidateValueWithPattern(log.Log, false, true)) - assert.Assert(t, ValidateValueWithPattern(log.Log, false, false)) + assert.Assert(t, ValidateValueWithPattern(true, true)) + assert.Assert(t, !ValidateValueWithPattern(true, false)) + assert.Assert(t, !ValidateValueWithPattern(false, true)) + assert.Assert(t, ValidateValueWithPattern(false, false)) } func TestValidateString_AsteriskTest(t *testing.T) { @@ -21,8 +20,8 @@ func TestValidateString_AsteriskTest(t *testing.T) { value := "anything" empty := "" - assert.Assert(t, validateString(log.Log, value, pattern, operator.Equal)) - assert.Assert(t, validateString(log.Log, empty, pattern, operator.Equal)) + assert.Assert(t, validateString(value, pattern, operator.Equal)) + assert.Assert(t, validateString(empty, pattern, operator.Equal)) } func TestValidateString_LeftAsteriskTest(t *testing.T) { @@ -30,32 +29,32 @@ func TestValidateString_LeftAsteriskTest(t *testing.T) { value := "leftright" right := "right" - assert.Assert(t, validateString(log.Log, value, pattern, operator.Equal)) - assert.Assert(t, validateString(log.Log, right, pattern, operator.Equal)) + assert.Assert(t, validateString(value, pattern, operator.Equal)) + assert.Assert(t, validateString(right, pattern, operator.Equal)) value = "leftmiddle" middle := "middle" - assert.Assert(t, !validateString(log.Log, value, pattern, operator.Equal)) - assert.Assert(t, !validateString(log.Log, middle, pattern, operator.Equal)) + assert.Assert(t, !validateString(value, pattern, operator.Equal)) + assert.Assert(t, !validateString(middle, pattern, operator.Equal)) } func TestValidateString_MiddleAsteriskTest(t *testing.T) { pattern := "ab*ba" value := "abbeba" - assert.Assert(t, validateString(log.Log, value, pattern, operator.Equal)) + assert.Assert(t, validateString(value, pattern, operator.Equal)) value = "abbca" - assert.Assert(t, !validateString(log.Log, value, pattern, operator.Equal)) + assert.Assert(t, !validateString(value, pattern, operator.Equal)) } func TestValidateString_QuestionMark(t *testing.T) { pattern := "ab?ba" value := "abbba" - assert.Assert(t, validateString(log.Log, value, pattern, operator.Equal)) + assert.Assert(t, validateString(value, pattern, operator.Equal)) value = "abbbba" - assert.Assert(t, !validateString(log.Log, value, pattern, operator.Equal)) + assert.Assert(t, !validateString(value, pattern, operator.Equal)) } func TestValidateValueWithPattern_BoolInJson(t *testing.T) { @@ -77,7 +76,7 @@ func TestValidateValueWithPattern_BoolInJson(t *testing.T) { err = json.Unmarshal(rawValue, &value) assert.Assert(t, err) - assert.Assert(t, ValidateValueWithPattern(log.Log, value["key"], pattern["key"])) + assert.Assert(t, ValidateValueWithPattern(value["key"], pattern["key"])) } func TestValidateValueWithPattern_NullPatternStringValue(t *testing.T) { @@ -99,7 +98,7 @@ func TestValidateValueWithPattern_NullPatternStringValue(t *testing.T) { err = json.Unmarshal(rawValue, &value) assert.Assert(t, err) - assert.Assert(t, !ValidateValueWithPattern(log.Log, value["key"], pattern["key"])) + assert.Assert(t, !ValidateValueWithPattern(value["key"], pattern["key"])) } func TestValidateValueWithPattern_NullPatternDefaultString(t *testing.T) { @@ -121,7 +120,7 @@ func TestValidateValueWithPattern_NullPatternDefaultString(t *testing.T) { err = json.Unmarshal(rawValue, &value) assert.Assert(t, err) - assert.Assert(t, ValidateValueWithPattern(log.Log, value["key"], pattern["key"])) + assert.Assert(t, ValidateValueWithPattern(value["key"], pattern["key"])) } func TestValidateValueWithPattern_NullPatternDefaultFloat(t *testing.T) { @@ -143,7 +142,7 @@ func TestValidateValueWithPattern_NullPatternDefaultFloat(t *testing.T) { err = json.Unmarshal(rawValue, &value) assert.Assert(t, err) - assert.Assert(t, ValidateValueWithPattern(log.Log, value["key"], pattern["key"])) + assert.Assert(t, ValidateValueWithPattern(value["key"], pattern["key"])) } func TestValidateValueWithPattern_NullPatternDefaultInt(t *testing.T) { @@ -165,7 +164,7 @@ func TestValidateValueWithPattern_NullPatternDefaultInt(t *testing.T) { err = json.Unmarshal(rawValue, &value) assert.Assert(t, err) - assert.Assert(t, ValidateValueWithPattern(log.Log, value["key"], pattern["key"])) + assert.Assert(t, ValidateValueWithPattern(value["key"], pattern["key"])) } func TestValidateValueWithPattern_NullPatternDefaultBool(t *testing.T) { @@ -187,77 +186,77 @@ func TestValidateValueWithPattern_NullPatternDefaultBool(t *testing.T) { err = json.Unmarshal(rawValue, &value) assert.Assert(t, err) - assert.Assert(t, ValidateValueWithPattern(log.Log, value["key"], pattern["key"])) + assert.Assert(t, ValidateValueWithPattern(value["key"], pattern["key"])) } func TestValidateValueWithPattern_StringsLogicalOr(t *testing.T) { pattern := "192.168.88.1 | 10.100.11.*" value := "10.100.11.54" - assert.Assert(t, ValidateValueWithPattern(log.Log, value, pattern)) + assert.Assert(t, ValidateValueWithPattern(value, pattern)) } func TestValidateValueWithPattern_EqualTwoFloats(t *testing.T) { - assert.Assert(t, ValidateValueWithPattern(log.Log, 7.0, 7.000)) + assert.Assert(t, ValidateValueWithPattern(7.0, 7.000)) } func TestValidateValueWithNilPattern_NullPatternStringValue(t *testing.T) { - assert.Assert(t, !validateValueWithNilPattern(log.Log, "value")) + assert.Assert(t, !validateValueWithNilPattern("value")) } func TestValidateValueWithNilPattern_NullPatternDefaultString(t *testing.T) { - assert.Assert(t, validateValueWithNilPattern(log.Log, "")) + assert.Assert(t, validateValueWithNilPattern("")) } func TestValidateValueWithNilPattern_NullPatternDefaultFloat(t *testing.T) { - assert.Assert(t, validateValueWithNilPattern(log.Log, 0.0)) + assert.Assert(t, validateValueWithNilPattern(0.0)) } func TestValidateValueWithNilPattern_NullPatternFloat(t *testing.T) { - assert.Assert(t, !validateValueWithNilPattern(log.Log, 0.1)) + assert.Assert(t, !validateValueWithNilPattern(0.1)) } func TestValidateValueWithNilPattern_NullPatternDefaultInt(t *testing.T) { - assert.Assert(t, validateValueWithNilPattern(log.Log, 0)) + assert.Assert(t, validateValueWithNilPattern(0)) } func TestValidateValueWithNilPattern_NullPatternInt(t *testing.T) { - assert.Assert(t, !validateValueWithNilPattern(log.Log, 1)) + assert.Assert(t, !validateValueWithNilPattern(1)) } func TestValidateValueWithNilPattern_NullPatternDefaultBool(t *testing.T) { - assert.Assert(t, validateValueWithNilPattern(log.Log, false)) + assert.Assert(t, validateValueWithNilPattern(false)) } func TestValidateValueWithNilPattern_NullPatternTrueBool(t *testing.T) { - assert.Assert(t, !validateValueWithNilPattern(log.Log, true)) + assert.Assert(t, !validateValueWithNilPattern(true)) } func TestValidateValueWithFloatPattern_FloatValue(t *testing.T) { - assert.Assert(t, validateValueWithFloatPattern(log.Log, 7.9914, 7.9914)) + assert.Assert(t, validateValueWithFloatPattern(7.9914, 7.9914)) } func TestValidateValueWithFloatPattern_FloatValueNotPass(t *testing.T) { - assert.Assert(t, !validateValueWithFloatPattern(log.Log, 7.9914, 7.99141)) + assert.Assert(t, !validateValueWithFloatPattern(7.9914, 7.99141)) } func TestValidateValueWithFloatPattern_FloatPatternWithoutFractionIntValue(t *testing.T) { - assert.Assert(t, validateValueWithFloatPattern(log.Log, 7, 7.000000)) + assert.Assert(t, validateValueWithFloatPattern(7, 7.000000)) } func TestValidateValueWithFloatPattern_FloatPatternWithoutFraction(t *testing.T) { - assert.Assert(t, validateValueWithFloatPattern(log.Log, 7.000000, 7.000000)) + assert.Assert(t, validateValueWithFloatPattern(7.000000, 7.000000)) } func TestValidateValueWithIntPattern_FloatValueWithoutFraction(t *testing.T) { - assert.Assert(t, validateValueWithFloatPattern(log.Log, 7.000000, 7)) + assert.Assert(t, validateValueWithFloatPattern(7.000000, 7)) } func TestValidateValueWithIntPattern_FloatValueWitFraction(t *testing.T) { - assert.Assert(t, !validateValueWithFloatPattern(log.Log, 7.000001, 7)) + assert.Assert(t, !validateValueWithFloatPattern(7.000001, 7)) } func TestValidateValueWithIntPattern_NotPass(t *testing.T) { - assert.Assert(t, !validateValueWithFloatPattern(log.Log, 8, 7)) + assert.Assert(t, !validateValueWithFloatPattern(8, 7)) } func TestGetNumberAndStringPartsFromPattern_NumberAndString(t *testing.T) { @@ -291,35 +290,35 @@ func TestGetNumberAndStringPartsFromPattern_Empty(t *testing.T) { } func TestValidateNumberWithStr_LessFloatAndInt(t *testing.T) { - assert.Assert(t, validateNumberWithStr(log.Log, 7.00001, "7.000001", operator.More)) - assert.Assert(t, validateNumberWithStr(log.Log, 7.00001, "7", operator.NotEqual)) + assert.Assert(t, validateNumberWithStr(7.00001, "7.000001", operator.More)) + assert.Assert(t, validateNumberWithStr(7.00001, "7", operator.NotEqual)) - assert.Assert(t, validateNumberWithStr(log.Log, 7.0000, "7", operator.Equal)) - assert.Assert(t, !validateNumberWithStr(log.Log, 6.000000001, "6", operator.Less)) + assert.Assert(t, validateNumberWithStr(7.0000, "7", operator.Equal)) + assert.Assert(t, !validateNumberWithStr(6.000000001, "6", operator.Less)) } func TestValidateQuantity_InvalidQuantity(t *testing.T) { - assert.Assert(t, !validateNumberWithStr(log.Log, "1024Gi", "", operator.Equal)) - assert.Assert(t, !validateNumberWithStr(log.Log, "gii", "1024Gi", operator.Equal)) + assert.Assert(t, !validateNumberWithStr("1024Gi", "", operator.Equal)) + assert.Assert(t, !validateNumberWithStr("gii", "1024Gi", operator.Equal)) } func TestValidateQuantity_Equal(t *testing.T) { - assert.Assert(t, validateNumberWithStr(log.Log, "1024Gi", "1024Gi", operator.Equal)) - assert.Assert(t, validateNumberWithStr(log.Log, "1024Mi", "1Gi", operator.Equal)) - assert.Assert(t, validateNumberWithStr(log.Log, "0.2", "200m", operator.Equal)) - assert.Assert(t, validateNumberWithStr(log.Log, "500", "500", operator.Equal)) - assert.Assert(t, !validateNumberWithStr(log.Log, "2048", "1024", operator.Equal)) - assert.Assert(t, validateNumberWithStr(log.Log, 1024, "1024", operator.Equal)) + assert.Assert(t, validateNumberWithStr("1024Gi", "1024Gi", operator.Equal)) + assert.Assert(t, validateNumberWithStr("1024Mi", "1Gi", operator.Equal)) + assert.Assert(t, validateNumberWithStr("0.2", "200m", operator.Equal)) + assert.Assert(t, validateNumberWithStr("500", "500", operator.Equal)) + assert.Assert(t, !validateNumberWithStr("2048", "1024", operator.Equal)) + assert.Assert(t, validateNumberWithStr(1024, "1024", operator.Equal)) } func TestValidateQuantity_Operation(t *testing.T) { - assert.Assert(t, validateNumberWithStr(log.Log, "1Gi", "1000Mi", operator.More)) - assert.Assert(t, validateNumberWithStr(log.Log, "1G", "1Gi", operator.Less)) - assert.Assert(t, validateNumberWithStr(log.Log, "500m", "0.5", operator.MoreEqual)) - assert.Assert(t, validateNumberWithStr(log.Log, "1", "500m", operator.MoreEqual)) - assert.Assert(t, validateNumberWithStr(log.Log, "0.5", ".5", operator.LessEqual)) - assert.Assert(t, validateNumberWithStr(log.Log, "0.2", ".5", operator.LessEqual)) - assert.Assert(t, validateNumberWithStr(log.Log, "0.2", ".5", operator.NotEqual)) + assert.Assert(t, validateNumberWithStr("1Gi", "1000Mi", operator.More)) + assert.Assert(t, validateNumberWithStr("1G", "1Gi", operator.Less)) + assert.Assert(t, validateNumberWithStr("500m", "0.5", operator.MoreEqual)) + assert.Assert(t, validateNumberWithStr("1", "500m", operator.MoreEqual)) + assert.Assert(t, validateNumberWithStr("0.5", ".5", operator.LessEqual)) + assert.Assert(t, validateNumberWithStr("0.2", ".5", operator.LessEqual)) + assert.Assert(t, validateNumberWithStr("0.2", ".5", operator.NotEqual)) } func TestGetOperatorFromStringPattern_OneChar(t *testing.T) { diff --git a/pkg/engine/validate/validate.go b/pkg/engine/validate/validate.go index 6e3d40da7d..9d94f07789 100644 --- a/pkg/engine/validate/validate.go +++ b/pkg/engine/validate/validate.go @@ -8,15 +8,15 @@ import ( "strconv" "strings" - "github.com/go-logr/logr" + "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/engine/anchor" "github.com/nirmata/kyverno/pkg/engine/operator" ) // ValidateResourceWithPattern is a start of element-by-element validation process // It assumes that validation is started from root, so "/" is passed -func ValidateResourceWithPattern(log logr.Logger, resource, pattern interface{}) (string, error) { - path, err := validateResourceElement(log, resource, pattern, pattern, "/") +func ValidateResourceWithPattern(resource, pattern interface{}) (string, error) { + path, err := validateResourceElement(resource, pattern, pattern, "/") if err != nil { return path, err } @@ -27,44 +27,44 @@ func ValidateResourceWithPattern(log logr.Logger, resource, pattern interface{}) // validateResourceElement detects the element type (map, array, nil, string, int, bool, float) // and calls corresponding handler // Pattern tree and resource tree can have different structure. In this case validation fails -func validateResourceElement(log logr.Logger, resourceElement, patternElement, originPattern interface{}, path string) (string, error) { +func validateResourceElement(resourceElement, patternElement, originPattern interface{}, path string) (string, error) { var err error switch typedPatternElement := patternElement.(type) { // map case map[string]interface{}: typedResourceElement, ok := resourceElement.(map[string]interface{}) if !ok { - log.V(4).Info("Pattern and resource have different structures.", "path", path, "expected", fmt.Sprintf("%T", patternElement), "current", fmt.Sprintf("%T", resourceElement)) + glog.V(4).Infof("Pattern and resource have different structures. Path: %s. Expected %T, found %T", path, patternElement, resourceElement) return path, fmt.Errorf("Pattern and resource have different structures. Path: %s. Expected %T, found %T", path, patternElement, resourceElement) } - return validateMap(log, typedResourceElement, typedPatternElement, originPattern, path) + return validateMap(typedResourceElement, typedPatternElement, originPattern, path) // array case []interface{}: typedResourceElement, ok := resourceElement.([]interface{}) if !ok { - log.V(4).Info("Pattern and resource have different structures.", "path", path, "expected", fmt.Sprintf("%T", patternElement), "current", fmt.Sprintf("%T", resourceElement)) + glog.V(4).Infof("Pattern and resource have different structures. Path: %s. Expected %T, found %T", path, patternElement, resourceElement) return path, fmt.Errorf("Validation rule Failed at path %s, resource does not satisfy the expected overlay pattern", path) } - return validateArray(log, typedResourceElement, typedPatternElement, originPattern, path) + return validateArray(typedResourceElement, typedPatternElement, originPattern, path) // elementary values case string, float64, int, int64, bool, nil: /*Analyze pattern */ if checkedPattern := reflect.ValueOf(patternElement); checkedPattern.Kind() == reflect.String { if isStringIsReference(checkedPattern.String()) { //check for $ anchor - patternElement, err = actualizePattern(log, originPattern, checkedPattern.String(), path) + patternElement, err = actualizePattern(originPattern, checkedPattern.String(), path) if err != nil { return path, err } } } - if !ValidateValueWithPattern(log, resourceElement, patternElement) { + if !ValidateValueWithPattern(resourceElement, patternElement) { return path, fmt.Errorf("Validation rule failed at '%s' to validate value '%v' with pattern '%v'", path, resourceElement, patternElement) } default: - log.V(4).Info("Pattern contains unknown type", "path", path, "current", fmt.Sprintf("%T", patternElement)) + glog.V(4).Infof("Pattern contains unknown type %T. Path: %s", patternElement, path) return path, fmt.Errorf("Validation rule failed at '%s', pattern contains unknown type", path) } return "", nil @@ -72,7 +72,7 @@ func validateResourceElement(log logr.Logger, resourceElement, patternElement, o // If validateResourceElement detects map element inside resource and pattern trees, it goes to validateMap // For each element of the map we must detect the type again, so we pass these elements to validateResourceElement -func validateMap(log logr.Logger, resourceMap, patternMap map[string]interface{}, origPattern interface{}, path string) (string, error) { +func validateMap(resourceMap, patternMap map[string]interface{}, origPattern interface{}, path string) (string, error) { // check if there is anchor in pattern // Phase 1 : Evaluate all the anchors // Phase 2 : Evaluate non-anchors @@ -91,7 +91,7 @@ func validateMap(log logr.Logger, resourceMap, patternMap map[string]interface{} if err != nil { // If Conditional anchor fails then we dont process the resources if anchor.IsConditionAnchor(key) { - log.Error(err, "condition anchor did not satisfy, wont process the resource") + glog.V(4).Infof("condition anchor did not satisfy, wont process the resources: %s", err) return "", nil } return handlerPath, err @@ -109,7 +109,7 @@ func validateMap(log logr.Logger, resourceMap, patternMap map[string]interface{} return "", nil } -func validateArray(log logr.Logger, resourceArray, patternArray []interface{}, originPattern interface{}, path string) (string, error) { +func validateArray(resourceArray, patternArray []interface{}, originPattern interface{}, path string) (string, error) { if 0 == len(patternArray) { return path, fmt.Errorf("Pattern Array empty") @@ -119,7 +119,7 @@ func validateArray(log logr.Logger, resourceArray, patternArray []interface{}, o case map[string]interface{}: // This is special case, because maps in arrays can have anchors that must be // processed with the special way affecting the entire array - path, err := validateArrayOfMaps(log, resourceArray, typedPatternElement, originPattern, path) + path, err := validateArrayOfMaps(resourceArray, typedPatternElement, originPattern, path) if err != nil { return path, err } @@ -127,7 +127,7 @@ func validateArray(log logr.Logger, resourceArray, patternArray []interface{}, o // In all other cases - detect type and handle each array element with validateResourceElement for i, patternElement := range patternArray { currentPath := path + strconv.Itoa(i) + "/" - path, err := validateResourceElement(log, resourceArray[i], patternElement, originPattern, currentPath) + path, err := validateResourceElement(resourceArray[i], patternElement, originPattern, currentPath) if err != nil { return path, err } @@ -137,7 +137,7 @@ func validateArray(log logr.Logger, resourceArray, patternArray []interface{}, o return "", nil } -func actualizePattern(log logr.Logger, origPattern interface{}, referencePattern, absolutePath string) (interface{}, error) { +func actualizePattern(origPattern interface{}, referencePattern, absolutePath string) (interface{}, error) { var foundValue interface{} referencePattern = strings.Trim(referencePattern, "$()") @@ -155,7 +155,7 @@ func actualizePattern(log logr.Logger, origPattern interface{}, referencePattern // value := actualPath := formAbsolutePath(referencePattern, absolutePath) - valFromReference, err := getValueFromReference(log, origPattern, actualPath) + valFromReference, err := getValueFromReference(origPattern, actualPath) if err != nil { return err, nil } @@ -196,15 +196,15 @@ func formAbsolutePath(referencePath, absolutePath string) string { } //Prepares original pattern, path to value, and call traverse function -func getValueFromReference(log logr.Logger, origPattern interface{}, reference string) (interface{}, error) { +func getValueFromReference(origPattern interface{}, reference string) (interface{}, error) { originalPatternMap := origPattern.(map[string]interface{}) reference = reference[1:] statements := strings.Split(reference, "/") - return getValueFromPattern(log, originalPatternMap, statements, 0) + return getValueFromPattern(originalPatternMap, statements, 0) } -func getValueFromPattern(log logr.Logger, patternMap map[string]interface{}, keys []string, currentKeyIndex int) (interface{}, error) { +func getValueFromPattern(patternMap map[string]interface{}, keys []string, currentKeyIndex int) (interface{}, error) { for key, pattern := range patternMap { rawKey := getRawKeyIfWrappedWithAttributes(key) @@ -221,21 +221,19 @@ func getValueFromPattern(log logr.Logger, patternMap map[string]interface{}, key for i, value := range typedPattern { resourceMap, ok := value.(map[string]interface{}) if !ok { - log.V(4).Info("Pattern and resource have different structures.", "expected", fmt.Sprintf("%T", pattern), "current", fmt.Sprintf("%T", value)) + glog.V(4).Infof("Pattern and resource have different structures. Expected %T, found %T", pattern, value) return nil, fmt.Errorf("Validation rule failed, resource does not have expected pattern %v", patternMap) } if keys[currentKeyIndex+1] == strconv.Itoa(i) { - return getValueFromPattern(log, resourceMap, keys, currentKeyIndex+2) + return getValueFromPattern(resourceMap, keys, currentKeyIndex+2) } - // TODO : SA4004: the surrounding loop is unconditionally terminated (staticcheck) return nil, errors.New("Reference to non-existent place in the document") } - return nil, nil // Just a hack to fix the lint } return nil, errors.New("Reference to non-existent place in the document") case map[string]interface{}: if keys[currentKeyIndex] == rawKey { - return getValueFromPattern(log, typedPattern, keys, currentKeyIndex+1) + return getValueFromPattern(typedPattern, keys, currentKeyIndex+1) } return nil, errors.New("Reference to non-existent place in the document") case string, float64, int, int64, bool, nil: @@ -253,12 +251,12 @@ func getValueFromPattern(log logr.Logger, patternMap map[string]interface{}, key // validateArrayOfMaps gets anchors from pattern array map element, applies anchors logic // and then validates each map due to the pattern -func validateArrayOfMaps(log logr.Logger, resourceMapArray []interface{}, patternMap map[string]interface{}, originPattern interface{}, path string) (string, error) { +func validateArrayOfMaps(resourceMapArray []interface{}, patternMap map[string]interface{}, originPattern interface{}, path string) (string, error) { for i, resourceElement := range resourceMapArray { // check the types of resource element // expect it to be map, but can be anything ?:( currentPath := path + strconv.Itoa(i) + "/" - returnpath, err := validateResourceElement(log, resourceElement, patternMap, originPattern, currentPath) + returnpath, err := validateResourceElement(resourceElement, patternMap, originPattern, currentPath) if err != nil { return returnpath, err } diff --git a/pkg/engine/validate/validate_test.go b/pkg/engine/validate/validate_test.go index 7f916239e0..acabd87ac1 100644 --- a/pkg/engine/validate/validate_test.go +++ b/pkg/engine/validate/validate_test.go @@ -5,7 +5,6 @@ import ( "testing" "gotest.tools/assert" - "sigs.k8s.io/controller-runtime/pkg/log" ) func TestValidateMap(t *testing.T) { @@ -101,7 +100,7 @@ func TestValidateMap(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) assert.Assert(t, json.Unmarshal(rawMap, &resource)) - path, err := validateMap(log.Log, resource, pattern, pattern, "/") + path, err := validateMap(resource, pattern, pattern, "/") assert.Equal(t, path, "") assert.NilError(t, err) } @@ -197,7 +196,7 @@ func TestValidateMap_AsteriskForInt(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) assert.Assert(t, json.Unmarshal(rawMap, &resource)) - path, err := validateMap(log.Log, resource, pattern, pattern, "/") + path, err := validateMap(resource, pattern, pattern, "/") t.Log(path) assert.NilError(t, err) } @@ -290,7 +289,7 @@ func TestValidateMap_AsteriskForMap(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) assert.Assert(t, json.Unmarshal(rawMap, &resource)) - path, err := validateMap(log.Log, resource, pattern, pattern, "/") + path, err := validateMap(resource, pattern, pattern, "/") assert.Equal(t, path, "") assert.NilError(t, err) } @@ -378,7 +377,7 @@ func TestValidateMap_AsteriskForArray(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) assert.Assert(t, json.Unmarshal(rawMap, &resource)) - path, err := validateMap(log.Log, resource, pattern, pattern, "/") + path, err := validateMap(resource, pattern, pattern, "/") assert.Equal(t, path, "") assert.NilError(t, err) } @@ -469,7 +468,7 @@ func TestValidateMap_AsteriskFieldIsMissing(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) assert.Assert(t, json.Unmarshal(rawMap, &resource)) - path, err := validateMap(log.Log, resource, pattern, pattern, "/") + path, err := validateMap(resource, pattern, pattern, "/") assert.Equal(t, path, "/spec/template/spec/containers/0/") assert.Assert(t, err != nil) } @@ -558,10 +557,9 @@ func TestValidateMap_livenessProbeIsNull(t *testing.T) { var pattern, resource map[string]interface{} assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) - err := json.Unmarshal(rawMap, &resource) - assert.NilError(t, err) + json.Unmarshal(rawMap, &resource) - path, err := validateMap(log.Log, resource, pattern, pattern, "/") + path, err := validateMap(resource, pattern, pattern, "/") assert.Equal(t, path, "") assert.NilError(t, err) } @@ -651,7 +649,7 @@ func TestValidateMap_livenessProbeIsMissing(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) assert.Assert(t, json.Unmarshal(rawMap, &resource)) - path, err := validateMap(log.Log, resource, pattern, pattern, "/") + path, err := validateMap(resource, pattern, pattern, "/") assert.Equal(t, path, "") assert.NilError(t, err) } @@ -697,7 +695,7 @@ func TestValidateMapElement_TwoElementsInArrayOnePass(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) assert.Assert(t, json.Unmarshal(rawMap, &resource)) - path, err := validateResourceElement(log.Log, resource, pattern, pattern, "/") + path, err := validateResourceElement(resource, pattern, pattern, "/") assert.Equal(t, path, "") // assert.Equal(t, path, "/1/object/0/key2/") // assert.NilError(t, err) @@ -732,7 +730,7 @@ func TestValidateMapElement_OneElementInArrayPass(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) assert.Assert(t, json.Unmarshal(rawMap, &resource)) - path, err := validateResourceElement(log.Log, resource, pattern, pattern, "/") + path, err := validateResourceElement(resource, pattern, pattern, "/") assert.Equal(t, path, "") assert.NilError(t, err) } @@ -786,7 +784,7 @@ func TestValidateMap_CorrectRelativePathInConfig(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) assert.Assert(t, json.Unmarshal(rawMap, &resource)) - path, err := validateResourceElement(log.Log, resource, pattern, pattern, "/") + path, err := validateResourceElement(resource, pattern, pattern, "/") assert.Equal(t, path, "") assert.NilError(t, err) } @@ -840,7 +838,7 @@ func TestValidateMap_RelativePathDoesNotExists(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) assert.Assert(t, json.Unmarshal(rawMap, &resource)) - path, err := validateResourceElement(log.Log, resource, pattern, pattern, "/") + path, err := validateResourceElement(resource, pattern, pattern, "/") assert.Equal(t, path, "/spec/containers/0/resources/requests/memory/") assert.Assert(t, err != nil) } @@ -894,7 +892,7 @@ func TestValidateMap_OnlyAnchorsInPath(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) assert.Assert(t, json.Unmarshal(rawMap, &resource)) - path, err := validateResourceElement(log.Log, resource, pattern, pattern, "/") + path, err := validateResourceElement(resource, pattern, pattern, "/") assert.Equal(t, path, "/spec/containers/0/resources/requests/memory/") assert.Assert(t, err != nil) } @@ -948,7 +946,7 @@ func TestValidateMap_MalformedReferenceOnlyDolarMark(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) assert.Assert(t, json.Unmarshal(rawMap, &resource)) - path, err := validateResourceElement(log.Log, resource, pattern, pattern, "/") + path, err := validateResourceElement(resource, pattern, pattern, "/") assert.Equal(t, path, "/spec/containers/0/resources/requests/memory/") assert.Assert(t, err != nil) } @@ -1002,7 +1000,7 @@ func TestValidateMap_RelativePathWithParentheses(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) assert.Assert(t, json.Unmarshal(rawMap, &resource)) - path, err := validateResourceElement(log.Log, resource, pattern, pattern, "/") + path, err := validateResourceElement(resource, pattern, pattern, "/") assert.Equal(t, path, "") assert.NilError(t, err) } @@ -1056,7 +1054,7 @@ func TestValidateMap_MalformedPath(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) assert.Assert(t, json.Unmarshal(rawMap, &resource)) - path, err := validateResourceElement(log.Log, resource, pattern, pattern, "/") + path, err := validateResourceElement(resource, pattern, pattern, "/") assert.Equal(t, path, "/spec/containers/0/resources/requests/memory/") assert.Assert(t, err != nil) } @@ -1110,7 +1108,7 @@ func TestValidateMap_AbosolutePathExists(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) assert.Assert(t, json.Unmarshal(rawMap, &resource)) - path, err := validateResourceElement(log.Log, resource, pattern, pattern, "/") + path, err := validateResourceElement(resource, pattern, pattern, "/") assert.Equal(t, path, "") assert.Assert(t, err == nil) } @@ -1151,7 +1149,7 @@ func TestValidateMap_AbsolutePathToMetadata(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) assert.Assert(t, json.Unmarshal(rawMap, &resource)) - path, err := validateResourceElement(log.Log, resource, pattern, pattern, "/") + path, err := validateResourceElement(resource, pattern, pattern, "/") assert.Equal(t, path, "") assert.Assert(t, err == nil) } @@ -1193,7 +1191,7 @@ func TestValidateMap_AbsolutePathToMetadata_fail(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) assert.Assert(t, json.Unmarshal(rawMap, &resource)) - path, err := validateResourceElement(log.Log, resource, pattern, pattern, "/") + path, err := validateResourceElement(resource, pattern, pattern, "/") assert.Equal(t, path, "/spec/containers/0/image/") assert.Assert(t, err != nil) } @@ -1247,7 +1245,7 @@ func TestValidateMap_AbosolutePathDoesNotExists(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) assert.Assert(t, json.Unmarshal(rawMap, &resource)) - path, err := validateResourceElement(log.Log, resource, pattern, pattern, "/") + path, err := validateResourceElement(resource, pattern, pattern, "/") assert.Equal(t, path, "/spec/containers/0/resources/requests/memory/") assert.Assert(t, err != nil) } @@ -1278,7 +1276,7 @@ func TestActualizePattern_GivenRelativePathThatExists(t *testing.T) { assert.Assert(t, json.Unmarshal(rawPattern, &pattern)) - pattern, err := actualizePattern(log.Log, pattern, referencePath, absolutePath) + pattern, err := actualizePattern(pattern, referencePath, absolutePath) assert.Assert(t, err == nil) } @@ -1346,12 +1344,10 @@ func TestValidateMapElement_OneElementInArrayNotPass(t *testing.T) { ]`) var pattern, resource interface{} - err := json.Unmarshal(rawPattern, &pattern) - assert.NilError(t, err) - err = json.Unmarshal(rawMap, &resource) - assert.NilError(t, err) + json.Unmarshal(rawPattern, &pattern) + json.Unmarshal(rawMap, &resource) - path, err := validateResourceElement(log.Log, resource, pattern, pattern, "/") + path, err := validateResourceElement(resource, pattern, pattern, "/") assert.Equal(t, path, "/0/object/0/key2/") assert.Assert(t, err != nil) } diff --git a/pkg/engine/validation.go b/pkg/engine/validation.go index 00c32f6791..fc4e89bf1c 100644 --- a/pkg/engine/validation.go +++ b/pkg/engine/validation.go @@ -5,7 +5,7 @@ import ( "reflect" "time" - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine/context" "github.com/nirmata/kyverno/pkg/engine/response" @@ -13,7 +13,6 @@ import ( "github.com/nirmata/kyverno/pkg/engine/validate" "github.com/nirmata/kyverno/pkg/engine/variables" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sigs.k8s.io/controller-runtime/pkg/log" ) //Validate applies validation rules from policy on the resource @@ -24,18 +23,17 @@ func Validate(policyContext PolicyContext) (resp response.EngineResponse) { oldR := policyContext.OldResource ctx := policyContext.Context admissionInfo := policyContext.AdmissionInfo - logger := log.Log.WithName("Validate").WithValues("policy", policy.Name, "kind", newR.GetKind(), "namespace", newR.GetNamespace(), "name", newR.GetName()) // policy information - logger.V(4).Info("start processing", "startTime", startTime) + glog.V(4).Infof("started applying validation rules of policy %q (%v)", policy.Name, startTime) // Process new & old resource if reflect.DeepEqual(oldR, unstructured.Unstructured{}) { // Create Mode // Operate on New Resource only - resp := validateResource(logger, ctx, policy, newR, admissionInfo) + resp := validateResource(ctx, policy, newR, admissionInfo) startResultResponse(resp, policy, newR) - defer endResultResponse(logger, resp, startTime) + defer endResultResponse(resp, startTime) // set PatchedResource with origin resource if empty // in order to create policy violation if reflect.DeepEqual(resp.PatchedResource, unstructured.Unstructured{}) { @@ -46,14 +44,14 @@ func Validate(policyContext PolicyContext) (resp response.EngineResponse) { // Update Mode // Operate on New and Old Resource only // New resource - oldResponse := validateResource(logger, ctx, policy, oldR, admissionInfo) - newResponse := validateResource(logger, ctx, policy, newR, admissionInfo) + oldResponse := validateResource(ctx, policy, oldR, admissionInfo) + newResponse := validateResource(ctx, policy, newR, admissionInfo) // if the old and new response is same then return empty response if !isSameResponse(oldResponse, newResponse) { // there are changes send response startResultResponse(newResponse, policy, newR) - defer endResultResponse(logger, newResponse, startTime) + defer endResultResponse(newResponse, startTime) if reflect.DeepEqual(newResponse.PatchedResource, unstructured.Unstructured{}) { newResponse.PatchedResource = newR } @@ -75,9 +73,10 @@ func startResultResponse(resp *response.EngineResponse, policy kyverno.ClusterPo resp.PolicyResponse.ValidationFailureAction = policy.Spec.ValidationFailureAction } -func endResultResponse(log logr.Logger, resp *response.EngineResponse, startTime time.Time) { +func endResultResponse(resp *response.EngineResponse, startTime time.Time) { resp.PolicyResponse.ProcessingTime = time.Since(startTime) - log.V(4).Info("finshed processing", "processingTime", resp.PolicyResponse.ProcessingTime, "validationRulesApplied", resp.PolicyResponse.RulesAppliedCount) + glog.V(4).Infof("Finished applying validation rules policy %v (%v)", resp.PolicyResponse.Policy, resp.PolicyResponse.ProcessingTime) + glog.V(4).Infof("Validation Rules appplied successfully count %v for policy %q", resp.PolicyResponse.RulesAppliedCount, resp.PolicyResponse.Policy) } func incrementAppliedCount(resp *response.EngineResponse) { @@ -85,18 +84,20 @@ func incrementAppliedCount(resp *response.EngineResponse) { resp.PolicyResponse.RulesAppliedCount++ } -func validateResource(log logr.Logger, ctx context.EvalInterface, policy kyverno.ClusterPolicy, resource unstructured.Unstructured, admissionInfo kyverno.RequestInfo) *response.EngineResponse { +func validateResource(ctx context.EvalInterface, policy kyverno.ClusterPolicy, resource unstructured.Unstructured, admissionInfo kyverno.RequestInfo) *response.EngineResponse { resp := &response.EngineResponse{} for _, rule := range policy.Spec.Rules { if !rule.HasValidate() { continue } + startTime := time.Now() + glog.V(4).Infof("Time: Validate matchAdmissionInfo %v", time.Since(startTime)) // check if the resource satisfies the filter conditions defined in the rule // TODO: this needs to be extracted, to filter the resource so that we can avoid passing resources that // dont statisfy a policy rule resource description if err := MatchesResourceDescription(resource, rule, admissionInfo); err != nil { - log.V(4).Info("resource fails the match description") + glog.V(4).Infof("resource %s/%s does not satisfy the resource description for the rule:\n%s", resource.GetNamespace(), resource.GetName(), err.Error()) continue } @@ -104,13 +105,13 @@ func validateResource(log logr.Logger, ctx context.EvalInterface, policy kyverno copyConditions := copyConditions(rule.Conditions) // evaluate pre-conditions // - handle variable subsitutions - if !variables.EvaluateConditions(log, ctx, copyConditions) { - log.V(4).Info("resource fails the preconditions") + if !variables.EvaluateConditions(ctx, copyConditions) { + glog.V(4).Infof("resource %s/%s does not satisfy the conditions for the rule ", resource.GetNamespace(), resource.GetName()) continue } if rule.Validation.Pattern != nil || rule.Validation.AnyPattern != nil { - ruleResponse := validatePatterns(log, ctx, resource, rule) + ruleResponse := validatePatterns(ctx, resource, rule) incrementAppliedCount(resp) resp.PolicyResponse.Rules = append(resp.PolicyResponse.Rules, ruleResponse) } @@ -158,15 +159,14 @@ func isSameRules(oldRules []response.RuleResponse, newRules []response.RuleRespo } // validatePatterns validate pattern and anyPattern -func validatePatterns(log logr.Logger, ctx context.EvalInterface, resource unstructured.Unstructured, rule kyverno.Rule) (resp response.RuleResponse) { +func validatePatterns(ctx context.EvalInterface, resource unstructured.Unstructured, rule kyverno.Rule) (resp response.RuleResponse) { startTime := time.Now() - logger := log.WithValues("rule", rule.Name) - logger.V(4).Info("start processing rule", "startTime", startTime) + glog.V(4).Infof("started applying validation rule %q (%v)", rule.Name, startTime) resp.Name = rule.Name resp.Type = utils.Validation.String() defer func() { resp.RuleStats.ProcessingTime = time.Since(startTime) - logger.V(4).Info("finshed processing", "processingTime", resp.RuleStats.ProcessingTime) + glog.V(4).Infof("finished applying validation rule %q (%v)", resp.Name, resp.RuleStats.ProcessingTime) }() // work on a copy of validation rule validationRule := rule.Validation.DeepCopy() @@ -176,7 +176,7 @@ func validatePatterns(log logr.Logger, ctx context.EvalInterface, resource unstr // substitute variables in the pattern pattern := validationRule.Pattern var err error - if pattern, err = variables.SubstituteVars(logger, ctx, pattern); err != nil { + if pattern, err = variables.SubstituteVars(ctx, pattern); err != nil { // variable subsitution failed resp.Success = false resp.Message = fmt.Sprintf("Validation error: %s; Validation rule '%s' failed. '%s'", @@ -184,7 +184,7 @@ func validatePatterns(log logr.Logger, ctx context.EvalInterface, resource unstr return resp } - if path, err := validate.ValidateResourceWithPattern(logger, resource.Object, pattern); err != nil { + if path, err := validate.ValidateResourceWithPattern(resource.Object, pattern); err != nil { // validation failed resp.Success = false resp.Message = fmt.Sprintf("Validation error: %s; Validation rule '%s' failed at path '%s'", @@ -192,7 +192,7 @@ func validatePatterns(log logr.Logger, ctx context.EvalInterface, resource unstr return resp } // rule application successful - logger.V(4).Info("successfully processed rule") + glog.V(4).Infof("rule %s pattern validated successfully on resource %s/%s/%s", rule.Name, resource.GetKind(), resource.GetNamespace(), resource.GetName()) resp.Success = true resp.Message = fmt.Sprintf("Validation rule '%s' succeeded.", rule.Name) return resp @@ -203,18 +203,19 @@ func validatePatterns(log logr.Logger, ctx context.EvalInterface, resource unstr var failedAnyPatternsErrors []error var err error for idx, pattern := range validationRule.AnyPattern { - if pattern, err = variables.SubstituteVars(logger, ctx, pattern); err != nil { + if pattern, err = variables.SubstituteVars(ctx, pattern); err != nil { // variable subsitution failed failedSubstitutionsErrors = append(failedSubstitutionsErrors, err) continue } - _, err := validate.ValidateResourceWithPattern(logger, resource.Object, pattern) + _, err := validate.ValidateResourceWithPattern(resource.Object, pattern) if err == nil { resp.Success = true resp.Message = fmt.Sprintf("Validation rule '%s' anyPattern[%d] succeeded.", rule.Name, idx) return resp } - logger.V(4).Info(fmt.Sprintf("validation rule failed for anyPattern[%d]", idx), "message", rule.Validation.Message) + glog.V(4).Infof("Validation error: %s; Validation rule %s anyPattern[%d] for %s/%s/%s", + rule.Validation.Message, rule.Name, idx, resource.GetKind(), resource.GetNamespace(), resource.GetName()) patternErr := fmt.Errorf("anyPattern[%d] failed; %s", idx, err) failedAnyPatternsErrors = append(failedAnyPatternsErrors, patternErr) } @@ -233,7 +234,7 @@ func validatePatterns(log logr.Logger, ctx context.EvalInterface, resource unstr errorStr = append(errorStr, err.Error()) } resp.Success = false - log.V(4).Info(fmt.Sprintf("Validation rule '%s' failed. %s", rule.Name, errorStr)) + glog.V(4).Infof("Validation rule '%s' failed. %s", rule.Name, errorStr) if rule.Validation.Message == "" { resp.Message = fmt.Sprintf("Validation rule '%s' has failed", rule.Name) } else { diff --git a/pkg/engine/validation_test.go b/pkg/engine/validation_test.go index fb6f272966..5a77d81b69 100644 --- a/pkg/engine/validation_test.go +++ b/pkg/engine/validation_test.go @@ -23,8 +23,7 @@ func TestGetAnchorsFromMap_ThereAreAnchors(t *testing.T) { }`) var unmarshalled map[string]interface{} - err := json.Unmarshal(rawMap, &unmarshalled) - assert.NilError(t, err) + json.Unmarshal(rawMap, &unmarshalled) actualMap := utils.GetAnchorsFromMap(unmarshalled) assert.Equal(t, len(actualMap), 2) @@ -115,8 +114,7 @@ func TestValidate_image_tag_fail(t *testing.T) { `) var policy kyverno.ClusterPolicy - err := json.Unmarshal(rawPolicy, &policy) - assert.NilError(t, err) + json.Unmarshal(rawPolicy, &policy) resourceUnstructured, err := utils.ConvertToUnstructured(rawResource) assert.NilError(t, err) @@ -214,8 +212,7 @@ func TestValidate_image_tag_pass(t *testing.T) { `) var policy kyverno.ClusterPolicy - err := json.Unmarshal(rawPolicy, &policy) - assert.NilError(t, err) + json.Unmarshal(rawPolicy, &policy) resourceUnstructured, err := utils.ConvertToUnstructured(rawResource) assert.NilError(t, err) @@ -292,8 +289,7 @@ func TestValidate_Fail_anyPattern(t *testing.T) { `) var policy kyverno.ClusterPolicy - err := json.Unmarshal(rawPolicy, &policy) - assert.NilError(t, err) + json.Unmarshal(rawPolicy, &policy) resourceUnstructured, err := utils.ConvertToUnstructured(rawResource) assert.NilError(t, err) @@ -374,8 +370,7 @@ func TestValidate_host_network_port(t *testing.T) { `) var policy kyverno.ClusterPolicy - err := json.Unmarshal(rawPolicy, &policy) - assert.NilError(t, err) + json.Unmarshal(rawPolicy, &policy) resourceUnstructured, err := utils.ConvertToUnstructured(rawResource) assert.NilError(t, err) @@ -464,8 +459,7 @@ func TestValidate_anchor_arraymap_pass(t *testing.T) { } `) var policy kyverno.ClusterPolicy - err := json.Unmarshal(rawPolicy, &policy) - assert.NilError(t, err) + json.Unmarshal(rawPolicy, &policy) resourceUnstructured, err := utils.ConvertToUnstructured(rawResource) assert.NilError(t, err) @@ -553,8 +547,8 @@ func TestValidate_anchor_arraymap_fail(t *testing.T) { } `) var policy kyverno.ClusterPolicy - err := json.Unmarshal(rawPolicy, &policy) - assert.NilError(t, err) + json.Unmarshal(rawPolicy, &policy) + resourceUnstructured, err := utils.ConvertToUnstructured(rawResource) assert.NilError(t, err) er := Validate(PolicyContext{Policy: policy, NewResource: *resourceUnstructured}) @@ -622,8 +616,7 @@ func TestValidate_anchor_map_notfound(t *testing.T) { `) var policy kyverno.ClusterPolicy - err := json.Unmarshal(rawPolicy, &policy) - assert.NilError(t, err) + json.Unmarshal(rawPolicy, &policy) resourceUnstructured, err := utils.ConvertToUnstructured(rawResource) assert.NilError(t, err) @@ -695,8 +688,7 @@ func TestValidate_anchor_map_found_valid(t *testing.T) { `) var policy kyverno.ClusterPolicy - err := json.Unmarshal(rawPolicy, &policy) - assert.NilError(t, err) + json.Unmarshal(rawPolicy, &policy) resourceUnstructured, err := utils.ConvertToUnstructured(rawResource) assert.NilError(t, err) @@ -768,8 +760,7 @@ func TestValidate_anchor_map_found_invalid(t *testing.T) { `) var policy kyverno.ClusterPolicy - err := json.Unmarshal(rawPolicy, &policy) - assert.NilError(t, err) + json.Unmarshal(rawPolicy, &policy) resourceUnstructured, err := utils.ConvertToUnstructured(rawResource) assert.NilError(t, err) @@ -843,8 +834,7 @@ func TestValidate_AnchorList_pass(t *testing.T) { `) var policy kyverno.ClusterPolicy - err := json.Unmarshal(rawPolicy, &policy) - assert.NilError(t, err) + json.Unmarshal(rawPolicy, &policy) resourceUnstructured, err := utils.ConvertToUnstructured(rawResource) assert.NilError(t, err) @@ -918,8 +908,7 @@ func TestValidate_AnchorList_fail(t *testing.T) { `) var policy kyverno.ClusterPolicy - err := json.Unmarshal(rawPolicy, &policy) - assert.NilError(t, err) + json.Unmarshal(rawPolicy, &policy) resourceUnstructured, err := utils.ConvertToUnstructured(rawResource) assert.NilError(t, err) @@ -993,8 +982,7 @@ func TestValidate_existenceAnchor_fail(t *testing.T) { `) var policy kyverno.ClusterPolicy - err := json.Unmarshal(rawPolicy, &policy) - assert.NilError(t, err) + json.Unmarshal(rawPolicy, &policy) resourceUnstructured, err := utils.ConvertToUnstructured(rawResource) assert.NilError(t, err) @@ -1069,8 +1057,7 @@ func TestValidate_existenceAnchor_pass(t *testing.T) { `) var policy kyverno.ClusterPolicy - err := json.Unmarshal(rawPolicy, &policy) - assert.NilError(t, err) + json.Unmarshal(rawPolicy, &policy) resourceUnstructured, err := utils.ConvertToUnstructured(rawResource) assert.NilError(t, err) @@ -1157,8 +1144,7 @@ func TestValidate_negationAnchor_deny(t *testing.T) { } `) var policy kyverno.ClusterPolicy - err := json.Unmarshal(rawPolicy, &policy) - assert.NilError(t, err) + json.Unmarshal(rawPolicy, &policy) resourceUnstructured, err := utils.ConvertToUnstructured(rawResource) assert.NilError(t, err) @@ -1244,8 +1230,7 @@ func TestValidate_negationAnchor_pass(t *testing.T) { `) var policy kyverno.ClusterPolicy - err := json.Unmarshal(rawPolicy, &policy) - assert.NilError(t, err) + json.Unmarshal(rawPolicy, &policy) resourceUnstructured, err := utils.ConvertToUnstructured(rawResource) assert.NilError(t, err) @@ -1312,14 +1297,12 @@ func Test_VariableSubstitutionPathNotExistInPattern(t *testing.T) { }`) var policy kyverno.ClusterPolicy - err := json.Unmarshal(policyraw, &policy) - assert.NilError(t, err) + json.Unmarshal(policyraw, &policy) resourceUnstructured, err := utils.ConvertToUnstructured(resourceRaw) assert.NilError(t, err) ctx := context.NewContext() - err = ctx.AddResource(resourceRaw) - assert.NilError(t, err) + ctx.AddResource(resourceRaw) policyContext := PolicyContext{ Policy: policy, @@ -1409,8 +1392,7 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_OnePatternStatisfies(t *t assert.NilError(t, err) ctx := context.NewContext() - err = ctx.AddResource(resourceRaw) - assert.NilError(t, err) + ctx.AddResource(resourceRaw) policyContext := PolicyContext{ Policy: policy, @@ -1500,8 +1482,7 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathNotPresent(t *test assert.NilError(t, err) ctx := context.NewContext() - err = ctx.AddResource(resourceRaw) - assert.NilError(t, err) + ctx.AddResource(resourceRaw) policyContext := PolicyContext{ Policy: policy, @@ -1591,8 +1572,7 @@ func Test_VariableSubstitutionPathNotExistInAnyPattern_AllPathPresent_NonePatter assert.NilError(t, err) ctx := context.NewContext() - err = ctx.AddResource(resourceRaw) - assert.NilError(t, err) + ctx.AddResource(resourceRaw) policyContext := PolicyContext{ Policy: policy, diff --git a/pkg/engine/variables/common.go b/pkg/engine/variables/common.go deleted file mode 100644 index 292b82d988..0000000000 --- a/pkg/engine/variables/common.go +++ /dev/null @@ -1,10 +0,0 @@ -package variables - -import "regexp" - -//IsVariable returns true if the element contains a 'valid' variable {{}} -func IsVariable(element string) bool { - validRegex := regexp.MustCompile(variableRegex) - groups := validRegex.FindAllStringSubmatch(element, -1) - return len(groups) != 0 -} diff --git a/pkg/engine/variables/evaluate.go b/pkg/engine/variables/evaluate.go index d0ebf7ed74..519a909d01 100644 --- a/pkg/engine/variables/evaluate.go +++ b/pkg/engine/variables/evaluate.go @@ -1,16 +1,16 @@ package variables import ( - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine/context" "github.com/nirmata/kyverno/pkg/engine/variables/operator" ) //Evaluate evaluates the condition -func Evaluate(log logr.Logger, ctx context.EvalInterface, condition kyverno.Condition) bool { +func Evaluate(ctx context.EvalInterface, condition kyverno.Condition) bool { // get handler for the operator - handle := operator.CreateOperatorHandler(log, ctx, condition.Operator, SubstituteVars) + handle := operator.CreateOperatorHandler(ctx, condition.Operator, SubstituteVars) if handle == nil { return false } @@ -18,10 +18,11 @@ func Evaluate(log logr.Logger, ctx context.EvalInterface, condition kyverno.Cond } //EvaluateConditions evaluates multiple conditions -func EvaluateConditions(log logr.Logger, ctx context.EvalInterface, conditions []kyverno.Condition) bool { +func EvaluateConditions(ctx context.EvalInterface, conditions []kyverno.Condition) bool { // AND the conditions for _, condition := range conditions { - if !Evaluate(log, ctx, condition) { + if !Evaluate(ctx, condition) { + glog.V(4).Infof("condition %v failed", condition) return false } } diff --git a/pkg/engine/variables/evaluate_test.go b/pkg/engine/variables/evaluate_test.go index d7d409b8f5..33b3a4f2b7 100644 --- a/pkg/engine/variables/evaluate_test.go +++ b/pkg/engine/variables/evaluate_test.go @@ -6,7 +6,6 @@ import ( kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine/context" - "sigs.k8s.io/controller-runtime/pkg/log" ) // STRINGS @@ -19,7 +18,7 @@ func Test_Eval_Equal_Const_String_Pass(t *testing.T) { Value: "name", } - if !Evaluate(log.Log, ctx, condition) { + if !Evaluate(ctx, condition) { t.Error("expected to pass") } } @@ -33,7 +32,7 @@ func Test_Eval_Equal_Const_String_Fail(t *testing.T) { Value: "name1", } - if Evaluate(log.Log, ctx, condition) { + if Evaluate(ctx, condition) { t.Error("expected to fail") } } @@ -47,7 +46,7 @@ func Test_Eval_NoEqual_Const_String_Pass(t *testing.T) { Value: "name1", } - if !Evaluate(log.Log, ctx, condition) { + if !Evaluate(ctx, condition) { t.Error("expected to pass") } } @@ -61,7 +60,7 @@ func Test_Eval_NoEqual_Const_String_Fail(t *testing.T) { Value: "name", } - if Evaluate(log.Log, ctx, condition) { + if Evaluate(ctx, condition) { t.Error("expected to fail") } } @@ -77,7 +76,7 @@ func Test_Eval_Equal_Const_Bool_Pass(t *testing.T) { Value: true, } - if !Evaluate(log.Log, ctx, condition) { + if !Evaluate(ctx, condition) { t.Error("expected to pass") } } @@ -91,7 +90,7 @@ func Test_Eval_Equal_Const_Bool_Fail(t *testing.T) { Value: false, } - if Evaluate(log.Log, ctx, condition) { + if Evaluate(ctx, condition) { t.Error("expected to fail") } } @@ -105,7 +104,7 @@ func Test_Eval_NoEqual_Const_Bool_Pass(t *testing.T) { Value: false, } - if !Evaluate(log.Log, ctx, condition) { + if !Evaluate(ctx, condition) { t.Error("expected to pass") } } @@ -119,7 +118,7 @@ func Test_Eval_NoEqual_Const_Bool_Fail(t *testing.T) { Value: true, } - if Evaluate(log.Log, ctx, condition) { + if Evaluate(ctx, condition) { t.Error("expected to fail") } } @@ -134,7 +133,7 @@ func Test_Eval_Equal_Const_int_Pass(t *testing.T) { Value: 1, } - if !Evaluate(log.Log, ctx, condition) { + if !Evaluate(ctx, condition) { t.Error("expected to pass") } } @@ -148,7 +147,7 @@ func Test_Eval_Equal_Const_int_Fail(t *testing.T) { Value: 2, } - if Evaluate(log.Log, ctx, condition) { + if Evaluate(ctx, condition) { t.Error("expected to fail") } } @@ -162,7 +161,7 @@ func Test_Eval_NoEqual_Const_int_Pass(t *testing.T) { Value: 2, } - if !Evaluate(log.Log, ctx, condition) { + if !Evaluate(ctx, condition) { t.Error("expected to pass") } } @@ -176,7 +175,7 @@ func Test_Eval_NoEqual_Const_int_Fail(t *testing.T) { Value: 1, } - if Evaluate(log.Log, ctx, condition) { + if Evaluate(ctx, condition) { t.Error("expected to fail") } } @@ -191,7 +190,7 @@ func Test_Eval_Equal_Const_int64_Pass(t *testing.T) { Value: int64(1), } - if !Evaluate(log.Log, ctx, condition) { + if !Evaluate(ctx, condition) { t.Error("expected to pass") } } @@ -205,7 +204,7 @@ func Test_Eval_Equal_Const_int64_Fail(t *testing.T) { Value: int64(2), } - if Evaluate(log.Log, ctx, condition) { + if Evaluate(ctx, condition) { t.Error("expected to fail") } } @@ -219,7 +218,7 @@ func Test_Eval_NoEqual_Const_int64_Pass(t *testing.T) { Value: int64(2), } - if !Evaluate(log.Log, ctx, condition) { + if !Evaluate(ctx, condition) { t.Error("expected to pass") } } @@ -233,7 +232,7 @@ func Test_Eval_NoEqual_Const_int64_Fail(t *testing.T) { Value: int64(1), } - if Evaluate(log.Log, ctx, condition) { + if Evaluate(ctx, condition) { t.Error("expected to fail") } } @@ -249,7 +248,7 @@ func Test_Eval_Equal_Const_float64_Pass(t *testing.T) { Value: 1.5, } - if !Evaluate(log.Log, ctx, condition) { + if !Evaluate(ctx, condition) { t.Error("expected to pass") } } @@ -263,7 +262,7 @@ func Test_Eval_Equal_Const_float64_Fail(t *testing.T) { Value: 1.6, } - if Evaluate(log.Log, ctx, condition) { + if Evaluate(ctx, condition) { t.Error("expected to fail") } } @@ -277,7 +276,7 @@ func Test_Eval_NoEqual_Const_float64_Pass(t *testing.T) { Value: 1.6, } - if !Evaluate(log.Log, ctx, condition) { + if !Evaluate(ctx, condition) { t.Error("expected to pass") } } @@ -291,7 +290,7 @@ func Test_Eval_NoEqual_Const_float64_Fail(t *testing.T) { Value: 1.5, } - if Evaluate(log.Log, ctx, condition) { + if Evaluate(ctx, condition) { t.Error("expected to fail") } } @@ -321,7 +320,7 @@ func Test_Eval_Equal_Const_object_Pass(t *testing.T) { Value: obj2, } - if !Evaluate(log.Log, ctx, condition) { + if !Evaluate(ctx, condition) { t.Error("expected to pass") } } @@ -349,7 +348,7 @@ func Test_Eval_Equal_Const_object_Fail(t *testing.T) { Value: obj2, } - if Evaluate(log.Log, ctx, condition) { + if Evaluate(ctx, condition) { t.Error("expected to fail") } } @@ -377,7 +376,7 @@ func Test_Eval_NotEqual_Const_object_Pass(t *testing.T) { Value: obj2, } - if !Evaluate(log.Log, ctx, condition) { + if !Evaluate(ctx, condition) { t.Error("expected to pass") } } @@ -405,7 +404,7 @@ func Test_Eval_NotEqual_Const_object_Fail(t *testing.T) { Value: obj2, } - if Evaluate(log.Log, ctx, condition) { + if Evaluate(ctx, condition) { t.Error("expected to fail") } } @@ -435,7 +434,7 @@ func Test_Eval_Equal_Const_list_Pass(t *testing.T) { Value: obj2, } - if !Evaluate(log.Log, ctx, condition) { + if !Evaluate(ctx, condition) { t.Error("expected to pass") } } @@ -461,7 +460,7 @@ func Test_Eval_Equal_Const_list_Fail(t *testing.T) { Value: obj2, } - if Evaluate(log.Log, ctx, condition) { + if Evaluate(ctx, condition) { t.Error("expected to fail") } } @@ -487,7 +486,7 @@ func Test_Eval_NotEqual_Const_list_Pass(t *testing.T) { Value: obj2, } - if !Evaluate(log.Log, ctx, condition) { + if !Evaluate(ctx, condition) { t.Error("expected to pass") } } @@ -513,7 +512,7 @@ func Test_Eval_NotEqual_Const_list_Fail(t *testing.T) { Value: obj2, } - if Evaluate(log.Log, ctx, condition) { + if Evaluate(ctx, condition) { t.Error("expected to fail") } } @@ -546,7 +545,7 @@ func Test_Eval_Equal_Var_Pass(t *testing.T) { Value: "temp", } - if !Evaluate(log.Log, ctx, condition) { + if !Evaluate(ctx, condition) { t.Error("expected to pass") } } @@ -577,7 +576,7 @@ func Test_Eval_Equal_Var_Fail(t *testing.T) { Value: "temp1", } - if Evaluate(log.Log, ctx, condition) { + if Evaluate(ctx, condition) { t.Error("expected to fail") } } diff --git a/pkg/engine/variables/operator/equal.go b/pkg/engine/variables/operator/equal.go index 1bc181f0f8..81ea80c621 100644 --- a/pkg/engine/variables/operator/equal.go +++ b/pkg/engine/variables/operator/equal.go @@ -1,21 +1,19 @@ package operator import ( - "fmt" "math" "reflect" "strconv" - "github.com/go-logr/logr" + "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/engine/context" ) //NewEqualHandler returns handler to manage Equal operations -func NewEqualHandler(log logr.Logger, ctx context.EvalInterface, subHandler VariableSubstitutionHandler) OperatorHandler { +func NewEqualHandler(ctx context.EvalInterface, subHandler VariableSubstitutionHandler) OperatorHandler { return EqualHandler{ ctx: ctx, subHandler: subHandler, - log: log, } } @@ -23,7 +21,6 @@ func NewEqualHandler(log logr.Logger, ctx context.EvalInterface, subHandler Vari type EqualHandler struct { ctx context.EvalInterface subHandler VariableSubstitutionHandler - log logr.Logger } //Evaluate evaluates expression with Equal Operator @@ -31,14 +28,14 @@ func (eh EqualHandler) Evaluate(key, value interface{}) bool { var err error //TODO: decouple variables from evaluation // substitute the variables - if key, err = eh.subHandler(eh.log, eh.ctx, key); err != nil { + if key, err = eh.subHandler(eh.ctx, key); err != nil { // Failed to resolve the variable - eh.log.Error(err, "Failed to resolve variable", "variable", key) + glog.Infof("Failed to resolve variables in key: %s: %v", key, err) return false } - if value, err = eh.subHandler(eh.log, eh.ctx, value); err != nil { + if value, err = eh.subHandler(eh.ctx, value); err != nil { // Failed to resolve the variable - eh.log.Error(err, "Failed to resolve variable", "variable", value) + glog.Infof("Failed to resolve variables in value: %s: %v", value, err) return false } @@ -59,7 +56,7 @@ func (eh EqualHandler) Evaluate(key, value interface{}) bool { case []interface{}: return eh.validateValueWithSlicePattern(typedKey, value) default: - eh.log.Info("Unsupported type", "value", typedKey, "type", fmt.Sprintf("%T", typedKey)) + glog.Errorf("Unsupported type %v", typedKey) return false } } @@ -68,7 +65,7 @@ func (eh EqualHandler) validateValueWithSlicePattern(key []interface{}, value in if val, ok := value.([]interface{}); ok { return reflect.DeepEqual(key, val) } - eh.log.Info("Expected type []interface{}", "value", value, "type", fmt.Sprintf("%T", value)) + glog.Warningf("Expected []interface{}, %v is of type %T", value, value) return false } @@ -76,7 +73,7 @@ func (eh EqualHandler) validateValueWithMapPattern(key map[string]interface{}, v if val, ok := value.(map[string]interface{}); ok { return reflect.DeepEqual(key, val) } - eh.log.Info("Expected type map[string]interface{}", "value", value, "type", fmt.Sprintf("%T", value)) + glog.Warningf("Expected map[string]interface{}, %v is of type %T", value, value) return false } @@ -84,8 +81,7 @@ func (eh EqualHandler) validateValuewithStringPattern(key string, value interfac if val, ok := value.(string); ok { return key == val } - - eh.log.Info("Expected type string", "value", value, "type", fmt.Sprintf("%T", value)) + glog.Warningf("Expected string, %v is of type %T", value, value) return false } @@ -96,25 +92,25 @@ func (eh EqualHandler) validateValuewithFloatPattern(key float64, value interfac if key == math.Trunc(key) { return int(key) == typedValue } - eh.log.Info("Expected type float, found int", "typedValue", typedValue) + glog.Warningf("Expected float, found int: %d\n", typedValue) case int64: // check that float has not fraction if key == math.Trunc(key) { return int64(key) == typedValue } - eh.log.Info("Expected type float, found int", "typedValue", typedValue) + glog.Warningf("Expected float, found int: %d\n", typedValue) case float64: return typedValue == key case string: // extract float from string float64Num, err := strconv.ParseFloat(typedValue, 64) if err != nil { - eh.log.Error(err, "Failed to parse float64 from string") + glog.Warningf("Failed to parse float64 from string: %v", err) return false } return float64Num == key default: - eh.log.Info("Expected type float", "value", value, "type", fmt.Sprintf("%T", value)) + glog.Warningf("Expected float, found: %T\n", value) return false } return false @@ -123,7 +119,7 @@ func (eh EqualHandler) validateValuewithFloatPattern(key float64, value interfac func (eh EqualHandler) validateValuewithBoolPattern(key bool, value interface{}) bool { typedValue, ok := value.(bool) if !ok { - eh.log.Info("Expected type bool", "value", value, "type", fmt.Sprintf("%T", value)) + glog.Error("Expected bool, found %V", value) return false } return key == typedValue @@ -140,18 +136,18 @@ func (eh EqualHandler) validateValuewithIntPattern(key int64, value interface{}) if typedValue == math.Trunc(typedValue) { return int64(typedValue) == key } - eh.log.Info("Expected type int, found float", "value", typedValue, "type", fmt.Sprintf("%T", typedValue)) + glog.Warningf("Expected int, found float: %f", typedValue) return false case string: // extract in64 from string int64Num, err := strconv.ParseInt(typedValue, 10, 64) if err != nil { - eh.log.Error(err, "Failed to parse int64 from string") + glog.Warningf("Failed to parse int64 from string: %v", err) return false } return int64Num == key default: - eh.log.Info("Expected type int", "value", value, "type", fmt.Sprintf("%T", value)) + glog.Warningf("Expected int, %v is of type %T", value, value) return false } } diff --git a/pkg/engine/variables/operator/notequal.go b/pkg/engine/variables/operator/notequal.go index ce9b4e87f8..9af9e891f3 100644 --- a/pkg/engine/variables/operator/notequal.go +++ b/pkg/engine/variables/operator/notequal.go @@ -1,21 +1,19 @@ package operator import ( - "fmt" "math" "reflect" "strconv" - "github.com/go-logr/logr" + "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/engine/context" ) //NewNotEqualHandler returns handler to manage NotEqual operations -func NewNotEqualHandler(log logr.Logger, ctx context.EvalInterface, subHandler VariableSubstitutionHandler) OperatorHandler { +func NewNotEqualHandler(ctx context.EvalInterface, subHandler VariableSubstitutionHandler) OperatorHandler { return NotEqualHandler{ ctx: ctx, subHandler: subHandler, - log: log, } } @@ -23,7 +21,6 @@ func NewNotEqualHandler(log logr.Logger, ctx context.EvalInterface, subHandler V type NotEqualHandler struct { ctx context.EvalInterface subHandler VariableSubstitutionHandler - log logr.Logger } //Evaluate evaluates expression with NotEqual Operator @@ -31,14 +28,14 @@ func (neh NotEqualHandler) Evaluate(key, value interface{}) bool { var err error //TODO: decouple variables from evaluation // substitute the variables - if key, err = neh.subHandler(neh.log, neh.ctx, key); err != nil { + if key, err = neh.subHandler(neh.ctx, key); err != nil { // Failed to resolve the variable - neh.log.Error(err, "Failed to resolve variable", "variable", key) + glog.Infof("Failed to resolve variables in key: %s: %v", key, err) return false } - if value, err = neh.subHandler(neh.log, neh.ctx, value); err != nil { + if value, err = neh.subHandler(neh.ctx, value); err != nil { // Failed to resolve the variable - neh.log.Error(err, "Failed to resolve variable", "variable", value) + glog.Infof("Failed to resolve variables in value: %s: %v", value, err) return false } // key and value need to be of same type @@ -58,7 +55,7 @@ func (neh NotEqualHandler) Evaluate(key, value interface{}) bool { case []interface{}: return neh.validateValueWithSlicePattern(typedKey, value) default: - neh.log.Info("Unsupported type", "value", typedKey, "type", fmt.Sprintf("%T", typedKey)) + glog.Error("Unsupported type %V", typedKey) return false } } @@ -67,7 +64,7 @@ func (neh NotEqualHandler) validateValueWithSlicePattern(key []interface{}, valu if val, ok := value.([]interface{}); ok { return !reflect.DeepEqual(key, val) } - neh.log.Info("Expected type []interface{}", "value", value, "type", fmt.Sprintf("%T", value)) + glog.Warningf("Expected []interface{}, %v is of type %T", value, value) return false } @@ -75,7 +72,7 @@ func (neh NotEqualHandler) validateValueWithMapPattern(key map[string]interface{ if val, ok := value.(map[string]interface{}); ok { return !reflect.DeepEqual(key, val) } - neh.log.Info("Expected type map[string]interface{}", "value", value, "type", fmt.Sprintf("%T", value)) + glog.Warningf("Expected map[string]interface{}, %v is of type %T", value, value) return false } @@ -83,7 +80,7 @@ func (neh NotEqualHandler) validateValuewithStringPattern(key string, value inte if val, ok := value.(string); ok { return key != val } - neh.log.Info("Expected type string", "value", value, "type", fmt.Sprintf("%T", value)) + glog.Warningf("Expected string, %v is of type %T", value, value) return false } @@ -94,25 +91,25 @@ func (neh NotEqualHandler) validateValuewithFloatPattern(key float64, value inte if key == math.Trunc(key) { return int(key) != typedValue } - neh.log.Info("Expected type float, found int", "typedValue", typedValue) + glog.Warningf("Expected float, found int: %d\n", typedValue) case int64: // check that float has not fraction if key == math.Trunc(key) { return int64(key) != typedValue } - neh.log.Info("Expected type float, found int", "typedValue", typedValue) + glog.Warningf("Expected float, found int: %d\n", typedValue) case float64: return typedValue != key case string: // extract float from string float64Num, err := strconv.ParseFloat(typedValue, 64) if err != nil { - neh.log.Error(err, "Failed to parse float64 from string") + glog.Warningf("Failed to parse float64 from string: %v", err) return false } return float64Num != key default: - neh.log.Info("Expected type float", "value", value, "type", fmt.Sprintf("%T", value)) + glog.Warningf("Expected float, found: %T\n", value) return false } return false @@ -121,7 +118,7 @@ func (neh NotEqualHandler) validateValuewithFloatPattern(key float64, value inte func (neh NotEqualHandler) validateValuewithBoolPattern(key bool, value interface{}) bool { typedValue, ok := value.(bool) if !ok { - neh.log.Info("Expected type bool", "value", value, "type", fmt.Sprintf("%T", value)) + glog.Error("Expected bool, found %V", value) return false } return key != typedValue @@ -138,18 +135,18 @@ func (neh NotEqualHandler) validateValuewithIntPattern(key int64, value interfac if typedValue == math.Trunc(typedValue) { return int64(typedValue) != key } - neh.log.Info("Expected type int, found float", "value", typedValue, "type", fmt.Sprintf("%T", typedValue)) + glog.Warningf("Expected int, found float: %f\n", typedValue) return false case string: // extract in64 from string int64Num, err := strconv.ParseInt(typedValue, 10, 64) if err != nil { - neh.log.Error(err, "Failed to parse int64 from string") + glog.Warningf("Failed to parse int64 from string: %v", err) return false } return int64Num != key default: - neh.log.Info("Expected type int", "value", value, "type", fmt.Sprintf("%T", value)) + glog.Warningf("Expected int, %v is of type %T", value, value) return false } } diff --git a/pkg/engine/variables/operator/operator.go b/pkg/engine/variables/operator/operator.go index adafe69982..2b3f9ce7a1 100644 --- a/pkg/engine/variables/operator/operator.go +++ b/pkg/engine/variables/operator/operator.go @@ -1,7 +1,7 @@ package operator import ( - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine/context" ) @@ -17,17 +17,17 @@ type OperatorHandler interface { } //VariableSubstitutionHandler defines the handler function for variable substitution -type VariableSubstitutionHandler = func(log logr.Logger, ctx context.EvalInterface, pattern interface{}) (interface{}, error) +type VariableSubstitutionHandler = func(ctx context.EvalInterface, pattern interface{}) (interface{}, error) //CreateOperatorHandler returns the operator handler based on the operator used in condition -func CreateOperatorHandler(log logr.Logger, ctx context.EvalInterface, op kyverno.ConditionOperator, subHandler VariableSubstitutionHandler) OperatorHandler { +func CreateOperatorHandler(ctx context.EvalInterface, op kyverno.ConditionOperator, subHandler VariableSubstitutionHandler) OperatorHandler { switch op { case kyverno.Equal: - return NewEqualHandler(log, ctx, subHandler) + return NewEqualHandler(ctx, subHandler) case kyverno.NotEqual: - return NewNotEqualHandler(log, ctx, subHandler) + return NewNotEqualHandler(ctx, subHandler) default: - log.Info("operator not supported", "operator", string(op)) + glog.Errorf("unsupported operator: %s", string(op)) } return nil } diff --git a/pkg/engine/variables/variables_test.go b/pkg/engine/variables/variables_test.go index e01bf4f820..6d2eb7c60c 100644 --- a/pkg/engine/variables/variables_test.go +++ b/pkg/engine/variables/variables_test.go @@ -7,7 +7,6 @@ import ( kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" authenticationv1 "k8s.io/api/authentication/v1" - "sigs.k8s.io/controller-runtime/pkg/log" "github.com/nirmata/kyverno/pkg/engine/context" ) @@ -85,7 +84,7 @@ func Test_variablesub1(t *testing.T) { t.Error(err) } - if _, err := SubstituteVars(log.Log, ctx, patternCopy); err != nil { + if _, err := SubstituteVars(ctx, patternCopy); err != nil { t.Error(err) } resultRaw, err := json.Marshal(patternCopy) @@ -175,7 +174,7 @@ func Test_variablesub_multiple(t *testing.T) { t.Error(err) } - if _, err := SubstituteVars(log.Log, ctx, patternCopy); err != nil { + if _, err := SubstituteVars(ctx, patternCopy); err != nil { t.Error(err) } resultRaw, err := json.Marshal(patternCopy) @@ -262,7 +261,7 @@ func Test_variablesubstitution(t *testing.T) { t.Error(err) } - if _, err := SubstituteVars(log.Log, ctx, patternCopy); err != nil { + if _, err := SubstituteVars(ctx, patternCopy); err != nil { t.Error(err) } resultRaw, err := json.Marshal(patternCopy) @@ -323,7 +322,7 @@ func Test_variableSubstitutionValue(t *testing.T) { t.Error(err) } - if _, err := SubstituteVars(log.Log, ctx, patternCopy); err != nil { + if _, err := SubstituteVars(ctx, patternCopy); err != nil { t.Error(err) } resultRaw, err := json.Marshal(patternCopy) @@ -381,7 +380,7 @@ func Test_variableSubstitutionValueOperatorNotEqual(t *testing.T) { t.Error(err) } - if _, err := SubstituteVars(log.Log, ctx, patternCopy); err != nil { + if _, err := SubstituteVars(ctx, patternCopy); err != nil { t.Error(err) } resultRaw, err := json.Marshal(patternCopy) @@ -440,7 +439,7 @@ func Test_variableSubstitutionValueFail(t *testing.T) { t.Error(err) } - if _, err := SubstituteVars(log.Log, ctx, patternCopy); err == nil { + if _, err := SubstituteVars(ctx, patternCopy); err == nil { t.Log("expected to fails") t.Fail() } @@ -498,7 +497,7 @@ func Test_variableSubstitutionObject(t *testing.T) { t.Error(err) } - if _, err := SubstituteVars(log.Log, ctx, patternCopy); err != nil { + if _, err := SubstituteVars(ctx, patternCopy); err != nil { t.Error(err) } resultRaw, err := json.Marshal(patternCopy) @@ -562,7 +561,7 @@ func Test_variableSubstitutionObjectOperatorNotEqualFail(t *testing.T) { t.Error(err) } - if _, err := SubstituteVars(log.Log, ctx, patternCopy); err == nil { + if _, err := SubstituteVars(ctx, patternCopy); err == nil { t.Error(err) } @@ -621,7 +620,7 @@ func Test_variableSubstitutionMultipleObject(t *testing.T) { t.Error(err) } - if _, err := SubstituteVars(log.Log, ctx, patternCopy); err != nil { + if _, err := SubstituteVars(ctx, patternCopy); err != nil { t.Error(err) } resultRaw, err := json.Marshal(patternCopy) diff --git a/pkg/engine/variables/vars.go b/pkg/engine/variables/vars.go index 59fd8f7fd5..4c336f2ede 100644 --- a/pkg/engine/variables/vars.go +++ b/pkg/engine/variables/vars.go @@ -6,7 +6,7 @@ import ( "strconv" "strings" - "github.com/go-logr/logr" + "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/engine/context" ) @@ -17,9 +17,9 @@ const ( //SubstituteVars replaces the variables with the values defined in the context // - if any variable is invaid or has nil value, it is considered as a failed varable substitution -func SubstituteVars(log logr.Logger, ctx context.EvalInterface, pattern interface{}) (interface{}, error) { +func SubstituteVars(ctx context.EvalInterface, pattern interface{}) (interface{}, error) { errs := []error{} - pattern = subVars(log, ctx, pattern, "", &errs) + pattern = subVars(ctx, pattern, "", &errs) if len(errs) == 0 { // no error while parsing the pattern return pattern, nil @@ -27,40 +27,40 @@ func SubstituteVars(log logr.Logger, ctx context.EvalInterface, pattern interfac return pattern, fmt.Errorf("%v", errs) } -func subVars(log logr.Logger, ctx context.EvalInterface, pattern interface{}, path string, errs *[]error) interface{} { +func subVars(ctx context.EvalInterface, pattern interface{}, path string, errs *[]error) interface{} { switch typedPattern := pattern.(type) { case map[string]interface{}: - return subMap(log, ctx, typedPattern, path, errs) + return subMap(ctx, typedPattern, path, errs) case []interface{}: - return subArray(log, ctx, typedPattern, path, errs) + return subArray(ctx, typedPattern, path, errs) case string: - return subValR(log, ctx, typedPattern, path, errs) + return subValR(ctx, typedPattern, path, errs) default: return pattern } } -func subMap(log logr.Logger, ctx context.EvalInterface, patternMap map[string]interface{}, path string, errs *[]error) map[string]interface{} { +func subMap(ctx context.EvalInterface, patternMap map[string]interface{}, path string, errs *[]error) map[string]interface{} { for key, patternElement := range patternMap { curPath := path + "/" + key - value := subVars(log, ctx, patternElement, curPath, errs) + value := subVars(ctx, patternElement, curPath, errs) patternMap[key] = value } return patternMap } -func subArray(log logr.Logger, ctx context.EvalInterface, patternList []interface{}, path string, errs *[]error) []interface{} { +func subArray(ctx context.EvalInterface, patternList []interface{}, path string, errs *[]error) []interface{} { for idx, patternElement := range patternList { curPath := path + "/" + strconv.Itoa(idx) - value := subVars(log, ctx, patternElement, curPath, errs) + value := subVars(ctx, patternElement, curPath, errs) patternList[idx] = value } return patternList } // subValR resolves the variables if defined -func subValR(log logr.Logger, ctx context.EvalInterface, valuePattern string, path string, errs *[]error) interface{} { +func subValR(ctx context.EvalInterface, valuePattern string, path string, errs *[]error) interface{} { // variable values can be scalar values(string,int, float) or they can be obects(map,slice) // - {{variable}} @@ -73,7 +73,7 @@ func subValR(log logr.Logger, ctx context.EvalInterface, valuePattern string, pa // since this might be a potential place for error, required better error reporting and handling // object values are only suported for single variable substitution - if ok, retVal := processIfSingleVariable(log, ctx, valuePattern, path, errs); ok { + if ok, retVal := processIfSingleVariable(ctx, valuePattern, path, errs); ok { return retVal } // var emptyInterface interface{} @@ -82,7 +82,7 @@ func subValR(log logr.Logger, ctx context.EvalInterface, valuePattern string, pa for { valueStr := valuePattern if len(failedVars) != 0 { - log.Info("failed to resolve variablesl short-circuiting") + glog.Info("some failed variables short-circuiting") break } // get variables at this level @@ -123,7 +123,7 @@ func subValR(log logr.Logger, ctx context.EvalInterface, valuePattern string, pa continue } // if type is not scalar then consider this as a failed variable - log.Info("variable resolves to non-scalar value. Non-Scalar values are not supported for nested variables", "variable", k, "value", v) + glog.Infof("variable %s resolves to non-scalar value %v. Non-Scalar values are not supported for nested variables", k, v) failedVars = append(failedVars, k) } valuePattern = newVal @@ -143,10 +143,10 @@ func subValR(log logr.Logger, ctx context.EvalInterface, valuePattern string, pa // if the value can be evaluted return the value // -> return value can be scalar or object type // -> if the variable is not present in the context then add an error and dont process further -func processIfSingleVariable(log logr.Logger, ctx context.EvalInterface, valuePattern interface{}, path string, errs *[]error) (bool, interface{}) { +func processIfSingleVariable(ctx context.EvalInterface, valuePattern interface{}, path string, errs *[]error) (bool, interface{}) { valueStr, ok := valuePattern.(string) if !ok { - log.Info("failed to convert to string", "pattern", valuePattern) + glog.Infof("failed to convert %v to string", valuePattern) return false, nil } // get variables at this level diff --git a/pkg/engine/variables/vars_test.go b/pkg/engine/variables/vars_test.go index aae517a082..171c62ace4 100644 --- a/pkg/engine/variables/vars_test.go +++ b/pkg/engine/variables/vars_test.go @@ -6,7 +6,6 @@ import ( "github.com/nirmata/kyverno/pkg/engine/context" "gotest.tools/assert" - "sigs.k8s.io/controller-runtime/pkg/log" ) func Test_subVars_success(t *testing.T) { @@ -65,7 +64,7 @@ func Test_subVars_success(t *testing.T) { t.Error(err) } - if _, err := SubstituteVars(log.Log, ctx, pattern); err != nil { + if _, err := SubstituteVars(ctx, pattern); err != nil { t.Error(err) } } @@ -126,7 +125,7 @@ func Test_subVars_failed(t *testing.T) { t.Error(err) } - if _, err := SubstituteVars(log.Log, ctx, pattern); err == nil { + if _, err := SubstituteVars(ctx, pattern); err == nil { t.Error("error is expected") } } @@ -153,5 +152,5 @@ func Test_SubvarRecursive(t *testing.T) { ctx := context.NewContext() assert.Assert(t, ctx.AddResource(resourceRaw)) errs := []error{} - subValR(log.Log, ctx, string(patternRaw), "/", &errs) + subValR(ctx, string(patternRaw), "/", &errs) } diff --git a/pkg/event/controller.go b/pkg/event/controller.go index a33e50f756..aa98d09e42 100644 --- a/pkg/event/controller.go +++ b/pkg/event/controller.go @@ -3,7 +3,7 @@ package event import ( "time" - "github.com/go-logr/logr" + "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/client/clientset/versioned/scheme" kyvernoinformer "github.com/nirmata/kyverno/pkg/client/informers/externalversions/kyverno/v1" @@ -17,7 +17,6 @@ import ( "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/record" "k8s.io/client-go/util/workqueue" - "k8s.io/klog" ) //Generator generate events @@ -35,7 +34,6 @@ type Generator struct { admissionCtrRecorder record.EventRecorder // events generated at namespaced policy controller to process 'generate' rule genPolicyRecorder record.EventRecorder - log logr.Logger } //Interface to generate event @@ -44,33 +42,32 @@ type Interface interface { } //NewEventGenerator to generate a new event controller -func NewEventGenerator(client *client.Client, pInformer kyvernoinformer.ClusterPolicyInformer, log logr.Logger) *Generator { +func NewEventGenerator(client *client.Client, pInformer kyvernoinformer.ClusterPolicyInformer) *Generator { gen := Generator{ client: client, pLister: pInformer.Lister(), queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), eventWorkQueueName), pSynced: pInformer.Informer().HasSynced, - policyCtrRecorder: initRecorder(client, PolicyController, log), - admissionCtrRecorder: initRecorder(client, AdmissionController, log), - genPolicyRecorder: initRecorder(client, GeneratePolicyController, log), - log: log, + policyCtrRecorder: initRecorder(client, PolicyController), + admissionCtrRecorder: initRecorder(client, AdmissionController), + genPolicyRecorder: initRecorder(client, GeneratePolicyController), } return &gen } -func initRecorder(client *client.Client, eventSource Source, log logr.Logger) record.EventRecorder { +func initRecorder(client *client.Client, eventSource Source) record.EventRecorder { // Initliaze Event Broadcaster err := scheme.AddToScheme(scheme.Scheme) if err != nil { - log.Error(err, "failed to add to scheme") + glog.Error(err) return nil } eventBroadcaster := record.NewBroadcaster() - eventBroadcaster.StartLogging(klog.Infof) + eventBroadcaster.StartLogging(glog.V(4).Infof) eventInterface, err := client.GetEventsInterface() if err != nil { - log.Error(err, "failed to get event interface for logging") + glog.Error(err) // TODO: add more specific error return nil } eventBroadcaster.StartRecordingToSink( @@ -84,12 +81,11 @@ func initRecorder(client *client.Client, eventSource Source, log logr.Logger) re //Add queues an event for generation func (gen *Generator) Add(infos ...Info) { - logger := gen.log for _, info := range infos { if info.Name == "" { // dont create event for resources with generateName // as the name is not generated yet - logger.V(4).Info("not creating an event as the resource has not been assigned a name yet", "kind", info.Kind, "name", info.Name, "namespace", info.Namespace) + glog.V(4).Infof("received info %v, not creating an event as the resource has not been assigned a name yet", info) continue } gen.queue.Add(info) @@ -98,14 +94,12 @@ func (gen *Generator) Add(infos ...Info) { // Run begins generator func (gen *Generator) Run(workers int, stopCh <-chan struct{}) { - logger := gen.log defer utilruntime.HandleCrash() - - logger.Info("start") - defer logger.Info("shutting down") + glog.Info("Starting event generator") + defer glog.Info("Shutting down event generator") if !cache.WaitForCacheSync(stopCh, gen.pSynced) { - logger.Info("failed to sync informer cache") + glog.Error("event generator: failed to sync informer cache") } for i := 0; i < workers; i++ { @@ -120,25 +114,24 @@ func (gen *Generator) runWorker() { } func (gen *Generator) handleErr(err error, key interface{}) { - logger := gen.log if err == nil { gen.queue.Forget(key) return } // This controller retries if something goes wrong. After that, it stops trying. if gen.queue.NumRequeues(key) < workQueueRetryLimit { - logger.Error(err, "Error syncing events;re-queuing request,the resource might not have been created yet", "key", key) + glog.Warningf("Error syncing events %v(re-queuing request, the resource might not have been created yet): %v", key, err) // Re-enqueue the key rate limited. Based on the rate limiter on the // queue and the re-enqueue history, the key will be processed later again. gen.queue.AddRateLimited(key) return } gen.queue.Forget(key) - logger.Error(err, "dropping the key out of queue", "key", key) + glog.Error(err) + glog.Warningf("Dropping the key out of the queue: %v", err) } func (gen *Generator) processNextWorkItem() bool { - logger := gen.log obj, shutdown := gen.queue.Get() if shutdown { return false @@ -151,7 +144,7 @@ func (gen *Generator) processNextWorkItem() bool { if key, ok = obj.(Info); !ok { gen.queue.Forget(obj) - logger.Info("Incorrect type; expected type 'info'", "obj", obj) + glog.Warningf("Expecting type info by got %v\n", obj) return nil } err := gen.syncHandler(key) @@ -159,14 +152,13 @@ func (gen *Generator) processNextWorkItem() bool { return nil }(obj) if err != nil { - logger.Error(err, "failed to process next work item") + glog.Error(err) return true } return true } func (gen *Generator) syncHandler(key Info) error { - logger := gen.log var robj runtime.Object var err error switch key.Kind { @@ -174,13 +166,13 @@ func (gen *Generator) syncHandler(key Info) error { //TODO: policy is clustered resource so wont need namespace robj, err = gen.pLister.Get(key.Name) if err != nil { - logger.Error(err, "failed to get policy", "name", key.Name) + glog.V(4).Infof("Error creating event: unable to get policy %s, will retry ", key.Name) return err } default: robj, err = gen.client.GetResource(key.Kind, key.Namespace, key.Name) if err != nil { - logger.Error(err, "failed to get resource", "kind", key.Kind, "name", key.Name, "namespace", key.Namespace) + glog.V(4).Infof("Error creating event: unable to get resource %s/%s/%s, will retry ", key.Kind, key.Namespace, key.Name) return err } } @@ -200,14 +192,13 @@ func (gen *Generator) syncHandler(key Info) error { case GeneratePolicyController: gen.genPolicyRecorder.Event(robj, eventType, key.Reason, key.Message) default: - logger.Info("info.source not defined for the request") + glog.Info("info.source not defined for the event generator request") } return nil } //NewEvent builds a event creation request func NewEvent( - log logr.Logger, rkind, rapiVersion, rnamespace, @@ -218,7 +209,7 @@ func NewEvent( args ...interface{}) Info { msgText, err := getEventMsg(message, args...) if err != nil { - log.Error(err, "failed to get event message") + glog.Error(err) } return Info{ Kind: rkind, diff --git a/pkg/generate/cleanup/cleanup.go b/pkg/generate/cleanup/cleanup.go index de1758aeba..d25fddd44e 100644 --- a/pkg/generate/cleanup/cleanup.go +++ b/pkg/generate/cleanup/cleanup.go @@ -1,20 +1,19 @@ package cleanup import ( - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" dclient "github.com/nirmata/kyverno/pkg/dclient" apierrors "k8s.io/apimachinery/pkg/api/errors" ) func (c *Controller) processGR(gr kyverno.GenerateRequest) error { - logger := c.log.WithValues("kind", gr.Kind, "namespace", gr.Namespace, "name", gr.Name) // 1- Corresponding policy has been deleted // then we dont delete the generated resources // 2- The trigger resource is deleted, then delete the generated resources - if !ownerResourceExists(logger, c.client, gr) { - if err := deleteGeneratedResources(logger, c.client, gr); err != nil { + if !ownerResourceExists(c.client, gr) { + if err := deleteGeneratedResources(c.client, gr); err != nil { return err } // - trigger-resource is deleted @@ -25,25 +24,25 @@ func (c *Controller) processGR(gr kyverno.GenerateRequest) error { return nil } -func ownerResourceExists(log logr.Logger, client *dclient.Client, gr kyverno.GenerateRequest) bool { +func ownerResourceExists(client *dclient.Client, gr kyverno.GenerateRequest) bool { _, err := client.GetResource(gr.Spec.Resource.Kind, gr.Spec.Resource.Namespace, gr.Spec.Resource.Name) // trigger resources has been deleted if apierrors.IsNotFound(err) { return false } if err != nil { - log.Error(err, "failed to get resource", "genKind", gr.Spec.Resource.Kind, "genNamespace", gr.Spec.Resource.Namespace, "genName", gr.Spec.Resource.Name) + glog.V(4).Infof("Failed to get resource %s/%s/%s: error : %s", gr.Spec.Resource.Kind, gr.Spec.Resource.Namespace, gr.Spec.Resource.Name, err) } // if there was an error while querying the resources we dont delete the generated resources // but expect the deletion in next reconciliation loop return true } -func deleteGeneratedResources(log logr.Logger, client *dclient.Client, gr kyverno.GenerateRequest) error { +func deleteGeneratedResources(client *dclient.Client, gr kyverno.GenerateRequest) error { for _, genResource := range gr.Status.GeneratedResources { err := client.DeleteResource(genResource.Kind, genResource.Namespace, genResource.Name, false) if apierrors.IsNotFound(err) { - log.Error(err, "resource not foundl will not delete", "genKind", gr.Spec.Resource.Kind, "genNamespace", gr.Spec.Resource.Namespace, "genName", gr.Spec.Resource.Name) + glog.V(4).Infof("resource %s/%s/%s not found, will no delete", genResource.Kind, genResource.Namespace, genResource.Name) continue } if err != nil { diff --git a/pkg/generate/cleanup/controller.go b/pkg/generate/cleanup/controller.go index 2c31254219..396058a346 100644 --- a/pkg/generate/cleanup/controller.go +++ b/pkg/generate/cleanup/controller.go @@ -1,9 +1,11 @@ package cleanup import ( + "fmt" "time" - "github.com/go-logr/logr" + "github.com/golang/glog" + kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned" kyvernoinformer "github.com/nirmata/kyverno/pkg/client/informers/externalversions/kyverno/v1" @@ -51,7 +53,6 @@ type Controller struct { //TODO: list of generic informers // only support Namespaces for deletion of resource nsInformer informers.GenericInformer - log logr.Logger } //NewController returns a new controller instance to manage generate-requests @@ -61,7 +62,6 @@ func NewController( pInformer kyvernoinformer.ClusterPolicyInformer, grInformer kyvernoinformer.GenerateRequestInformer, dynamicInformer dynamicinformer.DynamicSharedInformerFactory, - log logr.Logger, ) *Controller { c := Controller{ kyvernoClient: kyvernoclient, @@ -70,7 +70,6 @@ func NewController( // as we dont want a deleted GR to be re-queue queue: workqueue.NewNamedRateLimitingQueue(workqueue.NewItemExponentialFailureRateLimiter(1, 30), "generate-request-cleanup"), dynamicInformer: dynamicInformer, - log: log, } c.control = Control{client: kyvernoclient} c.enqueueGR = c.enqueue @@ -103,11 +102,10 @@ func NewController( } func (c *Controller) deleteGenericResource(obj interface{}) { - logger := c.log r := obj.(*unstructured.Unstructured) grs, err := c.grLister.GetGenerateRequestsForResource(r.GetKind(), r.GetNamespace(), r.GetName()) if err != nil { - logger.Error(err, "failed to get generate request CR for resource", "kind", r.GetKind(), "namespace", r.GetNamespace(), "name", r.GetName()) + glog.Errorf("failed to Generate Requests for resource %s/%s/%s: %v", r.GetKind(), r.GetNamespace(), r.GetName(), err) return } // re-evaluate the GR as the resource was deleted @@ -117,27 +115,26 @@ func (c *Controller) deleteGenericResource(obj interface{}) { } func (c *Controller) deletePolicy(obj interface{}) { - logger := c.log p, ok := obj.(*kyverno.ClusterPolicy) if !ok { tombstone, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { - logger.Info("ouldn't get object from tombstone", "obj", obj) + glog.Info(fmt.Errorf("Couldn't get object from tombstone %#v", obj)) return } _, ok = tombstone.Obj.(*kyverno.ClusterPolicy) if !ok { - logger.Info("Tombstone contained object that is not a Generate Request", "obj", obj) + glog.Info(fmt.Errorf("Tombstone contained object that is not a Generate Request %#v", obj)) return } } - logger.V(4).Info("deleting policy", "name", p.Name) + glog.V(4).Infof("Deleting Policy %s", p.Name) // clean up the GR // Get the corresponding GR // get the list of GR for the current Policy version grs, err := c.grLister.GetGenerateRequestsForClusterPolicy(p.Name) if err != nil { - logger.Error(err, "failed to generate request CR for the policy", "name", p.Name) + glog.Errorf("failed to Generate Requests for policy %s: %v", p.Name, err) return } for _, gr := range grs { @@ -156,46 +153,44 @@ func (c *Controller) updateGR(old, cur interface{}) { } func (c *Controller) deleteGR(obj interface{}) { - logger := c.log gr, ok := obj.(*kyverno.GenerateRequest) if !ok { tombstone, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { - logger.Info("Couldn't get object from tombstone", "obj", obj) + glog.Info(fmt.Errorf("Couldn't get object from tombstone %#v", obj)) return } _, ok = tombstone.Obj.(*kyverno.GenerateRequest) if !ok { - logger.Info("ombstone contained object that is not a Generate Request", "obj", obj) + glog.Info(fmt.Errorf("Tombstone contained object that is not a Generate Request %#v", obj)) return } } - logger.V(4).Info("deleting Generate Request CR", "name", gr.Name) + glog.V(4).Infof("Deleting GR %s", gr.Name) // sync Handler will remove it from the queue c.enqueueGR(gr) } func (c *Controller) enqueue(gr *kyverno.GenerateRequest) { - logger := c.log key, err := cache.MetaNamespaceKeyFunc(gr) if err != nil { - logger.Error(err, "failed to extract key") + glog.Error(err) return } - logger.V(4).Info("eneque generate request", "name", gr.Name) + glog.V(4).Infof("cleanup enqueu: %v", gr.Name) c.queue.Add(key) } //Run starts the generate-request re-conciliation loop func (c *Controller) Run(workers int, stopCh <-chan struct{}) { - logger := c.log defer utilruntime.HandleCrash() defer c.queue.ShutDown() - logger.Info("starting") - defer logger.Info("shutting down") + + glog.Info("Starting generate-policy-cleanup controller") + defer glog.Info("Shutting down generate-policy-cleanup controller") if !cache.WaitForCacheSync(stopCh, c.pSynced, c.grSynced) { - logger.Info("failed to sync informer cache") + glog.Error("generate-policy-cleanup controller: failed to sync informer cache") return } for i := 0; i < workers; i++ { @@ -224,33 +219,31 @@ func (c *Controller) processNextWorkItem() bool { } func (c *Controller) handleErr(err error, key interface{}) { - logger := c.log if err == nil { c.queue.Forget(key) return } if c.queue.NumRequeues(key) < maxRetries { - logger.Error(err, "failed to sync generate request", "key", key) + glog.Errorf("Error syncing Generate Request %v: %v", key, err) c.queue.AddRateLimited(key) return } utilruntime.HandleError(err) - logger.Error(err, "dropping generate request out of the queue", "key", key) + glog.Infof("Dropping generate request %q out of the queue: %v", key, err) c.queue.Forget(key) } func (c *Controller) syncGenerateRequest(key string) error { - logger := c.log.WithValues("key", key) var err error startTime := time.Now() - logger.Info("started syncing generate request", "startTime", startTime) + glog.V(4).Infof("Started syncing GR %q (%v)", key, startTime) defer func() { - logger.V(4).Info("finished syncying generate request", "processingTIme", time.Since(startTime)) + glog.V(4).Infof("Finished syncing GR %q (%v)", key, time.Since(startTime)) }() _, grName, err := cache.SplitMetaNamespaceKey(key) if errors.IsNotFound(err) { - logger.Info("generate request has been deleted") + glog.Infof("Generate Request %s has been deleted", key) return nil } if err != nil { diff --git a/pkg/generate/controller.go b/pkg/generate/controller.go index b848609177..d40ed2af0d 100644 --- a/pkg/generate/controller.go +++ b/pkg/generate/controller.go @@ -1,9 +1,10 @@ package generate import ( + "fmt" "time" - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned" kyvernoinformer "github.com/nirmata/kyverno/pkg/client/informers/externalversions/kyverno/v1" @@ -56,9 +57,9 @@ type Controller struct { dynamicInformer dynamicinformer.DynamicSharedInformerFactory //TODO: list of generic informers // only support Namespaces for re-evalutation on resource updates - nsInformer informers.GenericInformer + nsInformer informers.GenericInformer + policyStatusListener policystatus.Listener - log logr.Logger } //NewController returns an instance of the Generate-Request Controller @@ -71,7 +72,6 @@ func NewController( pvGenerator policyviolation.GeneratorInterface, dynamicInformer dynamicinformer.DynamicSharedInformerFactory, policyStatus policystatus.Listener, - log logr.Logger, ) *Controller { c := Controller{ client: client, @@ -82,7 +82,6 @@ func NewController( // as we dont want a deleted GR to be re-queue queue: workqueue.NewNamedRateLimitingQueue(workqueue.NewItemExponentialFailureRateLimiter(1, 30), "generate-request"), dynamicInformer: dynamicInformer, - log: log, policyStatusListener: policyStatus, } c.statusControl = StatusControl{client: kyvernoclient} @@ -118,12 +117,11 @@ func NewController( } func (c *Controller) updateGenericResource(old, cur interface{}) { - logger := c.log curR := cur.(*unstructured.Unstructured) grs, err := c.grLister.GetGenerateRequestsForResource(curR.GetKind(), curR.GetNamespace(), curR.GetName()) if err != nil { - logger.Error(err, "failed to get generate request CR for the resoource", "kind", curR.GetKind(), "name", curR.GetName(), "namespace", curR.GetNamespace()) + glog.Errorf("failed to Generate Requests for resource %s/%s/%s: %v", curR.GetKind(), curR.GetNamespace(), curR.GetName(), err) return } // re-evaluate the GR as the resource was updated @@ -136,14 +134,13 @@ func (c *Controller) updateGenericResource(old, cur interface{}) { func (c *Controller) enqueue(gr *kyverno.GenerateRequest) { key, err := cache.MetaNamespaceKeyFunc(gr) if err != nil { - c.log.Error(err, "failed to extract name") + glog.Error(err) return } c.queue.Add(key) } func (c *Controller) updatePolicy(old, cur interface{}) { - logger := c.log oldP := old.(*kyverno.ClusterPolicy) curP := cur.(*kyverno.ClusterPolicy) if oldP.ResourceVersion == curP.ResourceVersion { @@ -151,11 +148,11 @@ func (c *Controller) updatePolicy(old, cur interface{}) { // Two different versions of the same replica set will always have different RVs. return } - logger.V(4).Info("updating policy", "name", oldP.Name) + glog.V(4).Infof("Updating Policy %s", oldP.Name) // get the list of GR for the current Policy version grs, err := c.grLister.GetGenerateRequestsForClusterPolicy(curP.Name) if err != nil { - logger.Error(err, "failed to generate request for policy", "name", curP.Name) + glog.Errorf("failed to Generate Requests for policy %s: %v", curP.Name, err) return } // re-evaluate the GR as the policy was updated @@ -186,36 +183,34 @@ func (c *Controller) updateGR(old, cur interface{}) { } func (c *Controller) deleteGR(obj interface{}) { - logger := c.log gr, ok := obj.(*kyverno.GenerateRequest) if !ok { tombstone, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { - logger.Info("Couldn't get object from tombstone", "obj", obj) + glog.Info(fmt.Errorf("Couldn't get object from tombstone %#v", obj)) return } _, ok = tombstone.Obj.(*kyverno.GenerateRequest) if !ok { - logger.Info("tombstone contained object that is not a Generate Request CR", "obj", obj) + glog.Info(fmt.Errorf("Tombstone contained object that is not a Generate Request %#v", obj)) return } } - logger.Info("deleting generate request", "name", gr.Name) + glog.V(4).Infof("Deleting GR %s", gr.Name) // sync Handler will remove it from the queue c.enqueueGR(gr) } //Run ... func (c *Controller) Run(workers int, stopCh <-chan struct{}) { - logger := c.log defer utilruntime.HandleCrash() defer c.queue.ShutDown() - logger.Info("starting") - defer logger.Info("shutting down") + glog.Info("Starting generate-policy controller") + defer glog.Info("Shutting down generate-policy controller") if !cache.WaitForCacheSync(stopCh, c.pSynced, c.grSynced) { - logger.Info("failed to sync informer cache") + glog.Error("generate-policy controller: failed to sync informer cache") return } for i := 0; i < workers; i++ { @@ -244,29 +239,27 @@ func (c *Controller) processNextWorkItem() bool { } func (c *Controller) handleErr(err error, key interface{}) { - logger := c.log if err == nil { c.queue.Forget(key) return } if c.queue.NumRequeues(key) < maxRetries { - logger.Error(err, "failed to sync generate request", "key", key) + glog.Errorf("Error syncing Generate Request %v: %v", key, err) c.queue.AddRateLimited(key) return } utilruntime.HandleError(err) - logger.Error(err, "Dropping generate request from the queue", "key", key) + glog.Infof("Dropping generate request %q out of the queue: %v", key, err) c.queue.Forget(key) } func (c *Controller) syncGenerateRequest(key string) error { - logger := c.log var err error startTime := time.Now() - logger.Info("started sync", "key", key, "startTime", startTime) + glog.V(4).Infof("Started syncing GR %q (%v)", key, startTime) defer func() { - logger.V(4).Info("finished sync", "key", key, "processingTime", time.Since(startTime)) + glog.V(4).Infof("Finished syncing GR %q (%v)", key, time.Since(startTime)) }() _, grName, err := cache.SplitMetaNamespaceKey(key) if err != nil { @@ -275,7 +268,7 @@ func (c *Controller) syncGenerateRequest(key string) error { gr, err := c.grLister.Get(grName) if err != nil { - logger.Error(err, "failed to list generate requests") + glog.V(4).Info(err) return err } return c.processGR(gr) diff --git a/pkg/generate/generate.go b/pkg/generate/generate.go index 9f3edc4bc8..bff1dbbca6 100644 --- a/pkg/generate/generate.go +++ b/pkg/generate/generate.go @@ -5,7 +5,7 @@ import ( "fmt" "time" - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" dclient "github.com/nirmata/kyverno/pkg/dclient" "github.com/nirmata/kyverno/pkg/engine" @@ -17,7 +17,6 @@ import ( ) func (c *Controller) processGR(gr *kyverno.GenerateRequest) error { - logger := c.log.WithValues("name", gr.Name, "policy", gr.Spec.Policy, "kind", gr.Spec.Resource.Kind, "namespace", gr.Spec.Resource.Namespace, "name", gr.Spec.Resource.Name) var err error var resource *unstructured.Unstructured var genResources []kyverno.ResourceSpec @@ -25,46 +24,45 @@ func (c *Controller) processGR(gr *kyverno.GenerateRequest) error { resource, err = getResource(c.client, gr.Spec.Resource) if err != nil { // Dont update status - logger.Error(err, "resource does not exist or is yet to be created, requeueing") + glog.V(4).Infof("resource does not exist or is yet to be created, requeuing: %v", err) return err } // 2 - Apply the generate policy on the resource genResources, err = c.applyGenerate(*resource, *gr) // 3 - Report Events - reportEvents(logger, err, c.eventGen, *gr, *resource) + reportEvents(err, c.eventGen, *gr, *resource) // 4 - Update Status return updateStatus(c.statusControl, *gr, err, genResources) } func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyverno.GenerateRequest) ([]kyverno.ResourceSpec, error) { - logger := c.log.WithValues("name", gr.Name, "policy", gr.Spec.Policy, "kind", gr.Spec.Resource.Kind, "namespace", gr.Spec.Resource.Namespace, "name", gr.Spec.Resource.Name) // Get the list of rules to be applied // get policy policy, err := c.pLister.Get(gr.Spec.Policy) if err != nil { - logger.Error(err, "policy not found") + glog.V(4).Infof("policy %s not found: %v", gr.Spec.Policy, err) return nil, nil } // build context ctx := context.NewContext() resourceRaw, err := resource.MarshalJSON() if err != nil { - logger.Error(err, "failed to marshal resource") + glog.V(4).Infof("failed to marshal resource: %v", err) return nil, err } err = ctx.AddResource(resourceRaw) if err != nil { - logger.Error(err, "failed to load resource in context") + glog.Infof("Failed to load resource in context: %v", err) return nil, err } err = ctx.AddUserInfo(gr.Spec.Context.UserRequestInfo) if err != nil { - logger.Error(err, "failed to load SA in context") + glog.Infof("Failed to load userInfo in context: %v", err) return nil, err } err = ctx.AddSA(gr.Spec.Context.UserRequestInfo.AdmissionUserInfo.Username) if err != nil { - logger.Error(err, "failed to load UserInfo in context") + glog.Infof("Failed to load serviceAccount in context: %v", err) return nil, err } @@ -78,12 +76,12 @@ func (c *Controller) applyGenerate(resource unstructured.Unstructured, gr kyvern // check if the policy still applies to the resource engineResponse := engine.Generate(policyContext) if len(engineResponse.PolicyResponse.Rules) == 0 { - logger.V(4).Info("policy does not apply to resource") + glog.V(4).Infof("policy %s, dont not apply to resource %v", gr.Spec.Policy, gr.Spec.Resource) return nil, fmt.Errorf("policy %s, dont not apply to resource %v", gr.Spec.Policy, gr.Spec.Resource) } // Apply the generate rule on resource - return c.applyGeneratePolicy(logger, policyContext, gr) + return c.applyGeneratePolicy(policyContext, gr) } func updateStatus(statusControl StatusControlInterface, gr kyverno.GenerateRequest, err error, genResources []kyverno.ResourceSpec) error { @@ -95,7 +93,7 @@ func updateStatus(statusControl StatusControlInterface, gr kyverno.GenerateReque return statusControl.Success(gr, genResources) } -func (c *Controller) applyGeneratePolicy(log logr.Logger, policyContext engine.PolicyContext, gr kyverno.GenerateRequest) ([]kyverno.ResourceSpec, error) { +func (c *Controller) applyGeneratePolicy(policyContext engine.PolicyContext, gr kyverno.GenerateRequest) ([]kyverno.ResourceSpec, error) { // List of generatedResources var genResources []kyverno.ResourceSpec // Get the response as the actions to be performed on the resource @@ -115,8 +113,9 @@ func (c *Controller) applyGeneratePolicy(log logr.Logger, policyContext engine.P if !rule.HasGenerate() { continue } + startTime := time.Now() - genResource, err := applyRule(log, c.client, rule, resource, ctx, processExisting) + genResource, err := applyRule(c.client, rule, resource, ctx, processExisting) if err != nil { return nil, err } @@ -173,7 +172,7 @@ func updateGenerateExecutionTime(newTime time.Duration, oldAverageTimeString str return time.Duration(newAverageTimeInNanoSeconds) * time.Nanosecond } -func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, processExisting bool) (kyverno.ResourceSpec, error) { +func applyRule(client *dclient.Client, rule kyverno.Rule, resource unstructured.Unstructured, ctx context.EvalInterface, processExisting bool) (kyverno.ResourceSpec, error) { var rdata map[string]interface{} var err error var mode ResourceMode @@ -188,7 +187,7 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou // format : {{ results in error and rule is not applied // - valid variables are replaced with the values - if _, err := variables.SubstituteVars(log, ctx, genUnst.Object); err != nil { + if _, err := variables.SubstituteVars(ctx, genUnst.Object); err != nil { return noGenResource, err } genKind, _, err := unstructured.NestedString(genUnst.Object, "kind") @@ -220,9 +219,9 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou } if genData != nil { - rdata, mode, err = manageData(log, genKind, genNamespace, genName, genData, client, resource) + rdata, mode, err = manageData(genKind, genNamespace, genName, genData, client, resource) } else { - rdata, mode, err = manageClone(log, genKind, genNamespace, genName, genCopy, client, resource) + rdata, mode, err = manageClone(genKind, genNamespace, genName, genCopy, client, resource) } if err != nil { return noGenResource, err @@ -249,38 +248,38 @@ func applyRule(log logr.Logger, client *dclient.Client, rule kyverno.Rule, resou // - app.kubernetes.io/managed-by: kyverno // - kyverno.io/generated-by: kind/namespace/name (trigger resource) manageLabels(newResource, resource) - logger := log.WithValues("genKind", genKind, "genNamespace", genNamespace, "genName", genName) + if mode == Create { // Reset resource version newResource.SetResourceVersion("") // Create the resource - logger.V(4).Info("creating new resource") + glog.V(4).Infof("Creating new resource %s/%s/%s", genKind, genNamespace, genName) _, err = client.CreateResource(genKind, genNamespace, newResource, false) if err != nil { // Failed to create resource return noGenResource, err } - logger.V(4).Info("created new resource") + glog.V(4).Infof("Created new resource %s/%s/%s", genKind, genNamespace, genName) } else if mode == Update { - logger.V(4).Info("updating existing resource") + glog.V(4).Infof("Updating existing resource %s/%s/%s", genKind, genNamespace, genName) // Update the resource _, err := client.UpdateResource(genKind, genNamespace, newResource, false) if err != nil { // Failed to update resource return noGenResource, err } - logger.V(4).Info("updated new resource") + glog.V(4).Infof("Updated existing resource %s/%s/%s", genKind, genNamespace, genName) } return newGenResource, nil } -func manageData(log logr.Logger, kind, namespace, name string, data map[string]interface{}, client *dclient.Client, resource unstructured.Unstructured) (map[string]interface{}, ResourceMode, error) { +func manageData(kind, namespace, name string, data map[string]interface{}, client *dclient.Client, resource unstructured.Unstructured) (map[string]interface{}, ResourceMode, error) { // check if resource to be generated exists obj, err := client.GetResource(kind, namespace, name) if apierrors.IsNotFound(err) { - log.Error(err, "resource does not exist, will try to create", "genKind", kind, "genNamespace", namespace, "genName", name) + glog.V(4).Infof("Resource %s/%s/%s does not exists, will try to create", kind, namespace, name) return data, Create, nil } if err != nil { @@ -289,17 +288,18 @@ func manageData(log logr.Logger, kind, namespace, name string, data map[string]i return nil, Skip, err } // Resource exists; verfiy the content of the resource - err = checkResource(log, data, obj) + err = checkResource(data, obj) if err == nil { // Existing resource does contain the mentioned configuration in spec, skip processing the resource as it is already in expected state return nil, Skip, nil } - log.Info("to be generated resoruce already exists, but is missing the specifeid configurations, will try to update", "genKind", kind, "genNamespace", namespace, "genName", name) + + glog.V(4).Infof("Resource %s/%s/%s exists but missing required configuration, will try to update", kind, namespace, name) return data, Update, nil } -func manageClone(log logr.Logger, kind, namespace, name string, clone map[string]interface{}, client *dclient.Client, resource unstructured.Unstructured) (map[string]interface{}, ResourceMode, error) { +func manageClone(kind, namespace, name string, clone map[string]interface{}, client *dclient.Client, resource unstructured.Unstructured) (map[string]interface{}, ResourceMode, error) { // check if resource to be generated exists _, err := client.GetResource(kind, namespace, name) if err == nil { @@ -308,7 +308,6 @@ func manageClone(log logr.Logger, kind, namespace, name string, clone map[string } //TODO: check this if !apierrors.IsNotFound(err) { - log.Error(err, "reference/clone resource is not found", "genKind", kind, "genNamespace", namespace, "genName", name) //something wrong while fetching resource return nil, Skip, err } @@ -326,6 +325,8 @@ func manageClone(log logr.Logger, kind, namespace, name string, clone map[string // attempting to clone it self, this will fail -> short-ciruit it return nil, Skip, nil } + + glog.V(4).Infof("check if resource %s/%s/%s exists", kind, newRNs, newRName) // check if the resource as reference in clone exists? obj, err := client.GetResource(kind, newRNs, newRName) if err != nil { @@ -348,10 +349,10 @@ const ( Update = "UPDATE" ) -func checkResource(log logr.Logger, newResourceSpec interface{}, resource *unstructured.Unstructured) error { +func checkResource(newResourceSpec interface{}, resource *unstructured.Unstructured) error { // check if the resource spec if a subset of the resource - if path, err := validate.ValidateResourceWithPattern(log, resource.Object, newResourceSpec); err != nil { - log.Error(err, "Failed to match the resource ", "path", path) + if path, err := validate.ValidateResourceWithPattern(resource.Object, newResourceSpec); err != nil { + glog.V(4).Infof("Failed to match the resource at path %s: err %v", path, err) return err } return nil diff --git a/pkg/generate/labels.go b/pkg/generate/labels.go index c7d67b5a55..282caf55fa 100644 --- a/pkg/generate/labels.go +++ b/pkg/generate/labels.go @@ -3,8 +3,8 @@ package generate import ( "fmt" + "github.com/golang/glog" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sigs.k8s.io/controller-runtime/pkg/log" ) func manageLabels(unstr *unstructured.Unstructured, triggerResource unstructured.Unstructured) { @@ -30,7 +30,7 @@ func managedBy(labels map[string]string) { val, ok := labels[key] if ok { if val != value { - log.Log.Info(fmt.Sprintf("resource managed by %s, kyverno wont over-ride the label", val)) + glog.Infof("resource managed by %s, kyverno wont over-ride the label", val) return } } @@ -46,7 +46,7 @@ func generatedBy(labels map[string]string, triggerResource unstructured.Unstruct val, ok := labels[key] if ok { if val != value { - log.Log.Info(fmt.Sprintf("resource generated by %s, kyverno wont over-ride the label", val)) + glog.Infof("resource generated by %s, kyverno wont over-ride the label", val) return } } diff --git a/pkg/generate/report.go b/pkg/generate/report.go index f9d24fcc10..eaa5939e41 100644 --- a/pkg/generate/report.go +++ b/pkg/generate/report.go @@ -3,13 +3,13 @@ package generate import ( "fmt" - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/event" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) -func reportEvents(log logr.Logger, err error, eventGen event.Interface, gr kyverno.GenerateRequest, resource unstructured.Unstructured) { +func reportEvents(err error, eventGen event.Interface, gr kyverno.GenerateRequest, resource unstructured.Unstructured) { if err == nil { // Success Events // - resource -> policy rule applied successfully @@ -18,6 +18,7 @@ func reportEvents(log logr.Logger, err error, eventGen event.Interface, gr kyver eventGen.Add(events...) return } + glog.V(4).Infof("reporing events for %v", err) events := failedEvents(err, gr, resource) eventGen.Add(events...) } diff --git a/pkg/generate/status.go b/pkg/generate/status.go index db0182f89a..70d9539053 100644 --- a/pkg/generate/status.go +++ b/pkg/generate/status.go @@ -1,9 +1,9 @@ package generate import ( + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned" - "sigs.k8s.io/controller-runtime/pkg/log" ) //StatusControlInterface provides interface to update status subresource @@ -25,10 +25,10 @@ func (sc StatusControl) Failed(gr kyverno.GenerateRequest, message string, genRe gr.Status.GeneratedResources = genResources _, err := sc.client.KyvernoV1().GenerateRequests("kyverno").UpdateStatus(&gr) if err != nil { - log.Log.Error(err, "failed to update generate request status", "name", gr.Name) + glog.V(4).Infof("FAILED: updated gr %s status to %s", gr.Name, string(kyverno.Failed)) return err } - log.Log.Info("updated generate request status", "name", gr.Name, "status", string(kyverno.Failed)) + glog.V(4).Infof("updated gr %s status to %s", gr.Name, string(kyverno.Failed)) return nil } @@ -41,9 +41,9 @@ func (sc StatusControl) Success(gr kyverno.GenerateRequest, genResources []kyver _, err := sc.client.KyvernoV1().GenerateRequests("kyverno").UpdateStatus(&gr) if err != nil { - log.Log.Error(err, "failed to update generate request status", "name", gr.Name) + glog.V(4).Infof("FAILED: updated gr %s status to %s", gr.Name, string(kyverno.Completed)) return err } - log.Log.Info("updated generate request status", "name", gr.Name, "status", string(kyverno.Completed)) + glog.V(4).Infof("updated gr %s status to %s", gr.Name, string(kyverno.Completed)) return nil } diff --git a/pkg/kyverno/apply/command.go b/pkg/kyverno/apply/command.go index 26023c43e1..95e0f241cd 100644 --- a/pkg/kyverno/apply/command.go +++ b/pkg/kyverno/apply/command.go @@ -13,6 +13,8 @@ import ( policy2 "github.com/nirmata/kyverno/pkg/policy" + "github.com/golang/glog" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/discovery" @@ -32,7 +34,6 @@ import ( yamlv2 "gopkg.in/yaml.v2" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/client-go/kubernetes/scheme" - log "sigs.k8s.io/controller-runtime/pkg/log" ) func Command() *cobra.Command { @@ -50,7 +51,7 @@ func Command() *cobra.Command { defer func() { if err != nil { if !sanitizedError.IsErrorSanitized(err) { - log.Log.Error(err, "failed to sanitize") + glog.V(4).Info(err) err = fmt.Errorf("Internal error") } } @@ -70,7 +71,7 @@ func Command() *cobra.Command { } for _, policy := range policies { - err := policy2.Validate(utils.MarshalPolicy(*policy), nil, true) + err := policy2.Validate(utils.MarshalPolicy(*policy)) if err != nil { return sanitizedError.New(fmt.Sprintf("Policy %v is not valid", policy.Name)) } diff --git a/pkg/kyverno/main.go b/pkg/kyverno/main.go index 6424a57ddc..d0d1163ef6 100644 --- a/pkg/kyverno/main.go +++ b/pkg/kyverno/main.go @@ -9,9 +9,6 @@ import ( "github.com/nirmata/kyverno/pkg/kyverno/apply" "github.com/nirmata/kyverno/pkg/kyverno/version" - "k8s.io/klog" - "k8s.io/klog/klogr" - log "sigs.k8s.io/controller-runtime/pkg/log" "github.com/spf13/cobra" ) @@ -22,7 +19,7 @@ func CLI() { Short: "kyverno manages native policies of Kubernetes", } - configurelog(cli) + configureGlog(cli) commands := []*cobra.Command{ version.Command(), @@ -39,9 +36,9 @@ func CLI() { } } -func configurelog(cli *cobra.Command) { - klog.InitFlags(nil) - log.SetLogger(klogr.New()) +func configureGlog(cli *cobra.Command) { + flag.Parse() + _ = flag.Set("logtostderr", "true") cli.PersistentFlags().AddGoFlagSet(flag.CommandLine) _ = cli.PersistentFlags().MarkHidden("alsologtostderr") diff --git a/pkg/kyverno/validate/command.go b/pkg/kyverno/validate/command.go index 82863aa397..dce6e7dc32 100644 --- a/pkg/kyverno/validate/command.go +++ b/pkg/kyverno/validate/command.go @@ -11,12 +11,13 @@ import ( "github.com/nirmata/kyverno/pkg/kyverno/sanitizedError" + "github.com/golang/glog" + policyvalidate "github.com/nirmata/kyverno/pkg/policy" v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/spf13/cobra" "k8s.io/apimachinery/pkg/util/yaml" - log "sigs.k8s.io/controller-runtime/pkg/log" ) func Command() *cobra.Command { @@ -28,7 +29,7 @@ func Command() *cobra.Command { defer func() { if err != nil { if !sanitizedError.IsErrorSanitized(err) { - log.Log.Error(err, "failed to sanitize") + glog.V(4).Info(err) err = fmt.Errorf("Internal error") } } @@ -44,7 +45,7 @@ func Command() *cobra.Command { } for _, policy := range policies { - err = policyvalidate.Validate(utils.MarshalPolicy(*policy), nil, true) + err = policyvalidate.Validate(utils.MarshalPolicy(*policy)) if err != nil { fmt.Println("Policy " + policy.Name + " is invalid") } else { diff --git a/pkg/openapi/crdSync.go b/pkg/openapi/crdSync.go index 2c8f3023e4..61c32c45d3 100644 --- a/pkg/openapi/crdSync.go +++ b/pkg/openapi/crdSync.go @@ -6,12 +6,13 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "github.com/golang/glog" + "gopkg.in/yaml.v2" "github.com/googleapis/gnostic/compiler" openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2" - log "sigs.k8s.io/controller-runtime/pkg/log" client "github.com/nirmata/kyverno/pkg/dclient" "k8s.io/apimachinery/pkg/util/wait" @@ -43,12 +44,12 @@ func NewCRDSync(client *client.Client) *crdSync { func (c *crdSync) Run(workers int, stopCh <-chan struct{}) { newDoc, err := c.client.DiscoveryClient.OpenAPISchema() if err != nil { - log.Log.Error(err, "cannot get openapi schema") + glog.V(4).Infof("cannot get openapi schema: %v", err) } err = useOpenApiDocument(newDoc) if err != nil { - log.Log.Error(err, "Could not set custom OpenApi document") + glog.V(4).Infof("Could not set custom OpenApi document: %v\n", err) } // Sync CRD before kyverno starts @@ -62,7 +63,7 @@ func (c *crdSync) Run(workers int, stopCh <-chan struct{}) { func (c *crdSync) sync() { crds, err := c.client.ListResource("CustomResourceDefinition", "", nil) if err != nil { - log.Log.Error(err, "could not fetch crd's from server") + glog.V(4).Infof("could not fetch crd's from server: %v", err) return } @@ -92,7 +93,7 @@ func parseCRD(crd unstructured.Unstructured) { crdName := crdDefinition.Spec.Names.Kind if len(crdDefinition.Spec.Versions) < 1 { - log.Log.V(4).Info("could not parse crd schema, no versions present") + glog.V(4).Infof("could not parse crd schema, no versions present") return } @@ -103,7 +104,7 @@ func parseCRD(crd unstructured.Unstructured) { parsedSchema, err := openapi_v2.NewSchema(schema, compiler.NewContext("schema", nil)) if err != nil { - log.Log.Error(err, "could not parse crd schema:") + glog.V(4).Infof("could not parse crd schema:%v", err) return } diff --git a/pkg/openapi/validation.go b/pkg/openapi/validation.go index 01ea226b0f..bb724b9d0e 100644 --- a/pkg/openapi/validation.go +++ b/pkg/openapi/validation.go @@ -8,9 +8,12 @@ import ( "strings" "sync" - data "github.com/nirmata/kyverno/api" "github.com/nirmata/kyverno/pkg/engine/utils" + "github.com/nirmata/kyverno/data" + + "github.com/golang/glog" + "github.com/nirmata/kyverno/pkg/engine" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -20,7 +23,6 @@ import ( "github.com/googleapis/gnostic/compiler" "k8s.io/kube-openapi/pkg/util/proto" "k8s.io/kube-openapi/pkg/util/proto/validation" - log "sigs.k8s.io/controller-runtime/pkg/log" "gopkg.in/yaml.v2" ) @@ -118,7 +120,7 @@ func validatePolicyMutation(policy v1.ClusterPolicy) error { newPolicy.Spec.Rules = rules resource, _ := generateEmptyResource(openApiGlobalState.definitions[openApiGlobalState.kindToDefinitionName[kind]]).(map[string]interface{}) if resource == nil { - log.Log.V(4).Info(fmt.Sprintf("Cannot Validate policy: openApi definition now found for %v", kind)) + glog.V(4).Infof("Cannot Validate policy: openApi definition now found for %v", kind) return nil } newResource := unstructured.Unstructured{Object: resource} diff --git a/pkg/policy/actions.go b/pkg/policy/actions.go deleted file mode 100644 index 4442113cd4..0000000000 --- a/pkg/policy/actions.go +++ /dev/null @@ -1,61 +0,0 @@ -package policy - -import ( - "fmt" - - kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" - dclient "github.com/nirmata/kyverno/pkg/dclient" - "github.com/nirmata/kyverno/pkg/policy/generate" - "github.com/nirmata/kyverno/pkg/policy/mutate" - "github.com/nirmata/kyverno/pkg/policy/validate" - "sigs.k8s.io/controller-runtime/pkg/log" -) - -//Validation provides methods to validate a rule -type Validation interface { - Validate() (string, error) -} - -//validateAction performs validation on the rule actions -// - Mutate -// - Validation -// - Generate -func validateActions(idx int, rule kyverno.Rule, client *dclient.Client, mock bool) error { - var checker Validation - - // Mutate - if rule.HasMutate() { - checker = mutate.NewMutateFactory(rule.Mutation) - if path, err := checker.Validate(); err != nil { - return fmt.Errorf("path: spec.rules[%d].mutate.%s.: %v", idx, path, err) - } - } - - // Validate - if rule.HasValidate() { - checker = validate.NewValidateFactory(rule.Validation) - if path, err := checker.Validate(); err != nil { - return fmt.Errorf("path: spec.rules[%d].validate.%s.: %v", idx, path, err) - } - } - - // Generate - if rule.HasGenerate() { - //TODO: this check is there to support offline validations - // generate uses selfSubjectReviews to verify actions - // this need to modified to use different implementation for online and offline mode - if mock { - checker = generate.NewFakeGenerate(rule.Generation) - if path, err := checker.Validate(); err != nil { - return fmt.Errorf("path: spec.rules[%d].generate.%s.: %v", idx, path, err) - } - } else { - checker = generate.NewGenerateFactory(client, rule.Generation, log.Log) - if path, err := checker.Validate(); err != nil { - return fmt.Errorf("path: spec.rules[%d].generate.%s.: %v", idx, path, err) - } - } - } - - return nil -} diff --git a/pkg/policy/apply.go b/pkg/policy/apply.go index ad60ad5d6d..32d654346c 100644 --- a/pkg/policy/apply.go +++ b/pkg/policy/apply.go @@ -8,7 +8,7 @@ import ( "time" jsonpatch "github.com/evanphx/json-patch" - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine" "github.com/nirmata/kyverno/pkg/engine/context" @@ -19,12 +19,12 @@ import ( // applyPolicy applies policy on a resource //TODO: generation rules -func applyPolicy(policy kyverno.ClusterPolicy, resource unstructured.Unstructured, logger logr.Logger) (responses []response.EngineResponse) { +func applyPolicy(policy kyverno.ClusterPolicy, resource unstructured.Unstructured) (responses []response.EngineResponse) { startTime := time.Now() - logger.Info("start applying policy", "startTime", startTime) + glog.V(4).Infof("Started apply policy %s on resource %s/%s/%s (%v)", policy.Name, resource.GetKind(), resource.GetNamespace(), resource.GetName(), startTime) defer func() { - logger.Info("finisnhed applying policy", "processingTime", time.Since(startTime)) + glog.V(4).Infof("Finished applying %s on resource %s/%s/%s (%v)", policy.Name, resource.GetKind(), resource.GetNamespace(), resource.GetName(), time.Since(startTime)) }() var engineResponses []response.EngineResponse @@ -32,15 +32,13 @@ func applyPolicy(policy kyverno.ClusterPolicy, resource unstructured.Unstructure var err error // build context ctx := context.NewContext() - err = ctx.AddResource(transformResource(resource)) - if err != nil { - logger.Error(err, "enable to add transform resource to ctx") - } + ctx.AddResource(transformResource(resource)) + //MUTATION - engineResponse, err = mutation(policy, resource, ctx, logger) + engineResponse, err = mutation(policy, resource, ctx) engineResponses = append(engineResponses, engineResponse) if err != nil { - logger.Error(err, "failed to process mutation rule") + glog.Errorf("unable to process mutation rules: %v", err) } //VALIDATION @@ -50,52 +48,52 @@ func applyPolicy(policy kyverno.ClusterPolicy, resource unstructured.Unstructure //TODO: GENERATION return engineResponses } -func mutation(policy kyverno.ClusterPolicy, resource unstructured.Unstructured, ctx context.EvalInterface, log logr.Logger) (response.EngineResponse, error) { +func mutation(policy kyverno.ClusterPolicy, resource unstructured.Unstructured, ctx context.EvalInterface) (response.EngineResponse, error) { engineResponse := engine.Mutate(engine.PolicyContext{Policy: policy, NewResource: resource, Context: ctx}) if !engineResponse.IsSuccesful() { - log.V(4).Info("failed to apply mutation rules; reporting them") + glog.V(4).Infof("mutation had errors reporting them") return engineResponse, nil } // Verify if the JSON pathes returned by the Mutate are already applied to the resource if reflect.DeepEqual(resource, engineResponse.PatchedResource) { // resources matches - log.V(4).Info("resource already satisfys the policy") + glog.V(4).Infof("resource %s/%s/%s satisfies policy %s", engineResponse.PolicyResponse.Resource.Kind, engineResponse.PolicyResponse.Resource.Namespace, engineResponse.PolicyResponse.Resource.Name, engineResponse.PolicyResponse.Policy) return engineResponse, nil } - return getFailedOverallRuleInfo(resource, engineResponse, log) + return getFailedOverallRuleInfo(resource, engineResponse) } // getFailedOverallRuleInfo gets detailed info for over-all mutation failure -func getFailedOverallRuleInfo(resource unstructured.Unstructured, engineResponse response.EngineResponse, log logr.Logger) (response.EngineResponse, error) { +func getFailedOverallRuleInfo(resource unstructured.Unstructured, engineResponse response.EngineResponse) (response.EngineResponse, error) { rawResource, err := resource.MarshalJSON() if err != nil { - log.Error(err, "faield to marshall resource") + glog.V(4).Infof("unable to marshal resource: %v\n", err) return response.EngineResponse{}, err } // resource does not match so there was a mutation rule violated for index, rule := range engineResponse.PolicyResponse.Rules { - log.V(4).Info("veriying if policy rule was applied before", "rule", rule.Name) + glog.V(4).Infof("veriying if policy %s rule %s was applied before to resource %s/%s/%s", engineResponse.PolicyResponse.Policy, rule.Name, engineResponse.PolicyResponse.Resource.Kind, engineResponse.PolicyResponse.Resource.Namespace, engineResponse.PolicyResponse.Resource.Name) if len(rule.Patches) == 0 { continue } patch, err := jsonpatch.DecodePatch(utils.JoinPatches(rule.Patches)) if err != nil { - log.Error(err, "failed to decode JSON patch", "patches", rule.Patches) + glog.V(4).Infof("unable to decode patch %s: %v", rule.Patches, err) return response.EngineResponse{}, err } // apply the patches returned by mutate to the original resource patchedResource, err := patch.Apply(rawResource) if err != nil { - log.Error(err, "failed to apply JSON patch", "patches", rule.Patches) + glog.V(4).Infof("unable to apply patch %s: %v", rule.Patches, err) return response.EngineResponse{}, err } if !jsonpatch.Equal(patchedResource, rawResource) { - log.V(4).Info("policy rule conditions not satisfied by resource", "rule", rule.Name) + glog.V(4).Infof("policy %s rule %s condition not satisfied by existing resource", engineResponse.PolicyResponse.Policy, rule.Name) engineResponse.PolicyResponse.Rules[index].Success = false - engineResponse.PolicyResponse.Rules[index].Message = fmt.Sprintf("mutation json patches not found at resource path %s", extractPatchPath(rule.Patches, log)) + engineResponse.PolicyResponse.Rules[index].Message = fmt.Sprintf("mutation json patches not found at resource path %s", extractPatchPath(rule.Patches)) } } return engineResponse, nil @@ -107,14 +105,14 @@ type jsonPatch struct { Value interface{} `json:"value"` } -func extractPatchPath(patches [][]byte, log logr.Logger) string { +func extractPatchPath(patches [][]byte) string { var resultPath []string // extract the patch path and value for _, patch := range patches { - log.V(4).Info("expected json patch not found in resource", "patch", string(patch)) + glog.V(4).Infof("expected json patch not found in resource: %s", string(patch)) var data jsonPatch if err := json.Unmarshal(patch, &data); err != nil { - log.Error(err, "failed to decode the generate patch", "patch", string(patch)) + glog.V(4).Infof("Failed to decode the generated patch %v: Error %v", string(patch), err) continue } resultPath = append(resultPath, data.Path) diff --git a/pkg/policy/background.go b/pkg/policy/background.go index 2331359534..423fc51c4d 100644 --- a/pkg/policy/background.go +++ b/pkg/policy/background.go @@ -6,7 +6,6 @@ import ( kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine/context" "github.com/nirmata/kyverno/pkg/engine/variables" - "sigs.k8s.io/controller-runtime/pkg/log" ) //ContainsUserInfo returns error is userInfo is defined @@ -36,23 +35,23 @@ func ContainsUserInfo(policy kyverno.ClusterPolicy) error { filterVars := []string{"request.userInfo*", "serviceAccountName", "serviceAccountNamespace"} ctx := context.NewContext(filterVars...) for condIdx, condition := range rule.Conditions { - if condition.Key, err = variables.SubstituteVars(log.Log, ctx, condition.Key); err != nil { + if condition.Key, err = variables.SubstituteVars(ctx, condition.Key); err != nil { return fmt.Errorf("userInfo variable used at spec/rules[%d]/condition[%d]/key", idx, condIdx) } - if condition.Value, err = variables.SubstituteVars(log.Log, ctx, condition.Value); err != nil { + if condition.Value, err = variables.SubstituteVars(ctx, condition.Value); err != nil { return fmt.Errorf("userInfo variable used at spec/rules[%d]/condition[%d]/value", idx, condIdx) } } - if rule.Mutation.Overlay, err = variables.SubstituteVars(log.Log, ctx, rule.Mutation.Overlay); err != nil { + if rule.Mutation.Overlay, err = variables.SubstituteVars(ctx, rule.Mutation.Overlay); err != nil { return fmt.Errorf("userInfo variable used at spec/rules[%d]/mutate/overlay", idx) } - if rule.Validation.Pattern, err = variables.SubstituteVars(log.Log, ctx, rule.Validation.Pattern); err != nil { + if rule.Validation.Pattern, err = variables.SubstituteVars(ctx, rule.Validation.Pattern); err != nil { return fmt.Errorf("userInfo variable used at spec/rules[%d]/validate/pattern", idx) } for idx2, pattern := range rule.Validation.AnyPattern { - if rule.Validation.AnyPattern[idx2], err = variables.SubstituteVars(log.Log, ctx, pattern); err != nil { + if rule.Validation.AnyPattern[idx2], err = variables.SubstituteVars(ctx, pattern); err != nil { return fmt.Errorf("userInfo variable used at spec/rules[%d]/validate/anyPattern[%d]", idx, idx2) } } diff --git a/pkg/policy/cleanup.go b/pkg/policy/cleanup.go index 40394c2785..6a41c579ba 100644 --- a/pkg/policy/cleanup.go +++ b/pkg/policy/cleanup.go @@ -4,71 +4,57 @@ import ( "fmt" "reflect" - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" kyvernolister "github.com/nirmata/kyverno/pkg/client/listers/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine/response" "k8s.io/apimachinery/pkg/labels" ) -func (pc *PolicyController) cleanUp(ers []response.EngineResponse) { - for _, er := range ers { - if !er.IsSuccesful() { - continue - } - if len(er.PolicyResponse.Rules) == 0 { - continue - } - // clean up after the policy has been corrected - pc.cleanUpPolicyViolation(er.PolicyResponse) - } -} - func (pc *PolicyController) cleanUpPolicyViolation(pResponse response.PolicyResponse) { - logger := pc.log // - check if there is violation on resource (label:Selector) if pResponse.Resource.Namespace == "" { - pv, err := getClusterPV(pc.cpvLister, pResponse.Policy, pResponse.Resource.Kind, pResponse.Resource.Name, logger) + pv, err := getClusterPV(pc.cpvLister, pResponse.Policy, pResponse.Resource.Kind, pResponse.Resource.Name) if err != nil { - logger.Error(err, "failed to get cluster policy violation on policy and resource", "policy", pResponse.Policy, "kind", pResponse.Resource.Kind, "name", pResponse.Resource.Name) + glog.Errorf("failed to cleanUp violations: %v", err) return } if reflect.DeepEqual(pv, kyverno.ClusterPolicyViolation{}) { return } + + glog.V(4).Infof("cleanup cluster violation %s on %s", pv.Name, pv.Spec.ResourceSpec.ToKey()) if err := pc.pvControl.DeleteClusterPolicyViolation(pv.Name); err != nil { - logger.Error(err, "failed to delete cluster policy violation", "name", pv.Name) - } else { - logger.Info("deleted cluster policy violation", "name", pv.Name) + glog.Errorf("failed to delete cluster policy violation %s on %s: %v", pv.Name, pv.Spec.ResourceSpec.ToKey(), err) } + return } // namespace policy violation - nspv, err := getNamespacedPV(pc.nspvLister, pResponse.Policy, pResponse.Resource.Kind, pResponse.Resource.Namespace, pResponse.Resource.Name, logger) + nspv, err := getNamespacedPV(pc.nspvLister, pResponse.Policy, pResponse.Resource.Kind, pResponse.Resource.Namespace, pResponse.Resource.Name) if err != nil { - logger.Error(err, "failed to get namespaced policy violation on policy and resource", "policy", pResponse.Policy, "kind", pResponse.Resource.Kind, "namespace", pResponse.Resource.Namespace, "name", pResponse.Resource.Name) + glog.Error(err) return } if reflect.DeepEqual(nspv, kyverno.PolicyViolation{}) { return } + glog.V(4).Infof("cleanup namespaced violation %s on %s.%s", nspv.Name, pResponse.Resource.Namespace, nspv.Spec.ResourceSpec.ToKey()) if err := pc.pvControl.DeleteNamespacedPolicyViolation(nspv.Namespace, nspv.Name); err != nil { - logger.Error(err, "failed to delete cluster policy violation", "name", nspv.Name, "namespace", nspv.Namespace) - } else { - logger.Info("deleted namespaced policy violation", "name", nspv.Name, "namespace", nspv.Namespace) + glog.Errorf("failed to delete namespaced policy violation %s on %s: %v", nspv.Name, nspv.Spec.ResourceSpec.ToKey(), err) } } // Wont do the claiming of objects, just lookup based on selectors -func getClusterPV(pvLister kyvernolister.ClusterPolicyViolationLister, policyName, rkind, rname string, log logr.Logger) (kyverno.ClusterPolicyViolation, error) { +func getClusterPV(pvLister kyvernolister.ClusterPolicyViolationLister, policyName, rkind, rname string) (kyverno.ClusterPolicyViolation, error) { var err error // Check Violation on resource pvs, err := pvLister.List(labels.Everything()) if err != nil { - log.Error(err, "failed to list cluster policy violations") + glog.V(2).Infof("unable to list policy violations : %v", err) return kyverno.ClusterPolicyViolation{}, fmt.Errorf("failed to list cluster pv: %v", err) } @@ -83,10 +69,10 @@ func getClusterPV(pvLister kyvernolister.ClusterPolicyViolationLister, policyNam return kyverno.ClusterPolicyViolation{}, nil } -func getNamespacedPV(nspvLister kyvernolister.PolicyViolationLister, policyName, rkind, rnamespace, rname string, log logr.Logger) (kyverno.PolicyViolation, error) { +func getNamespacedPV(nspvLister kyvernolister.PolicyViolationLister, policyName, rkind, rnamespace, rname string) (kyverno.PolicyViolation, error) { nspvs, err := nspvLister.PolicyViolations(rnamespace).List(labels.Everything()) if err != nil { - log.Error(err, "failed to list namespaced policy violation") + glog.V(2).Infof("failed to list namespaced pv: %v", err) return kyverno.PolicyViolation{}, fmt.Errorf("failed to list namespaced pv: %v", err) } diff --git a/pkg/policy/clusterpv.go b/pkg/policy/clusterpv.go index 35704f72d8..0f9f2564ae 100644 --- a/pkg/policy/clusterpv.go +++ b/pkg/policy/clusterpv.go @@ -1,13 +1,15 @@ package policy import ( + "fmt" + + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "k8s.io/client-go/tools/cache" ) func (pc *PolicyController) addClusterPolicyViolation(obj interface{}) { pv := obj.(*kyverno.ClusterPolicyViolation) - logger := pc.log.WithValues("kind", pv.Kind, "namespace", pv.Namespace, "name", pv.Name) if pv.DeletionTimestamp != nil { // On a restart of the controller manager, it's possible for an object to @@ -20,15 +22,15 @@ func (pc *PolicyController) addClusterPolicyViolation(obj interface{}) { ps := pc.getPolicyForClusterPolicyViolation(pv) if len(ps) == 0 { // there is no cluster policy for this violation, so we can delete this cluster policy violation - logger.V(4).Info("Cluster Policy Violation does not belong to an active policy, will be cleanedup") + glog.V(4).Infof("Cluster Policy Violation %s does not belong to an active policy, will be cleanedup", pv.Name) if err := pc.pvControl.DeleteClusterPolicyViolation(pv.Name); err != nil { - logger.Error(err, "failed to delete resource") + glog.Errorf("Failed to deleted cluster policy violation %s: %v", pv.Name, err) return } - logger.V(4).Info("resource deleted") + glog.V(4).Infof("Cluster Policy Violation %s deleted", pv.Name) return } - logger.V(4).Info("resource added") + glog.V(4).Infof("Cluster Policy Violation %s added.", pv.Name) for _, p := range ps { pc.enqueuePolicy(p) } @@ -42,20 +44,19 @@ func (pc *PolicyController) updateClusterPolicyViolation(old, cur interface{}) { // Two different versions of the same replica set will always have different RVs. return } - logger := pc.log.WithValues("kind", curPV.Kind, "namespace", curPV.Namespace, "name", curPV.Name) ps := pc.getPolicyForClusterPolicyViolation(curPV) if len(ps) == 0 { // there is no cluster policy for this violation, so we can delete this cluster policy violation - logger.V(4).Info("Cluster Policy Violation does not belong to an active policy, will be cleanedup") + glog.V(4).Infof("Cluster Policy Violation %s does not belong to an active policy, will be cleanedup", curPV.Name) if err := pc.pvControl.DeleteClusterPolicyViolation(curPV.Name); err != nil { - logger.Error(err, "failed to delete resource") + glog.Errorf("Failed to deleted cluster policy violation %s: %v", curPV.Name, err) return } - logger.V(4).Info("resource deleted") + glog.V(4).Infof("PolicyViolation %s deleted", curPV.Name) return } - logger.V(4).Info("resource updated") + glog.V(4).Infof("Cluster PolicyViolation %s updated", curPV.Name) for _, p := range ps { pc.enqueuePolicy(p) } @@ -66,7 +67,6 @@ func (pc *PolicyController) updateClusterPolicyViolation(old, cur interface{}) { // a DeletionFinalStateUnknown marker item. func (pc *PolicyController) deleteClusterPolicyViolation(obj interface{}) { - logger := pc.log pv, ok := obj.(*kyverno.ClusterPolicyViolation) // When a delete is dropped, the relist will notice a PolicyViolation in the store not // in the list, leading to the insertion of a tombstone object which contains @@ -75,35 +75,33 @@ func (pc *PolicyController) deleteClusterPolicyViolation(obj interface{}) { if !ok { tombstone, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { - logger.Info("Couldn't get object from tombstone", "obj", obj) + glog.Info(fmt.Errorf("Couldn't get object from tombstone %#v", obj)) return } pv, ok = tombstone.Obj.(*kyverno.ClusterPolicyViolation) if !ok { - logger.Info("Couldn't get object from tombstone", "obj", obj) + glog.Info(fmt.Errorf("Couldn't get object from tombstone %#v", obj)) return } } - logger = logger.WithValues("kind", pv.Kind, "namespace", pv.Namespace, "name", pv.Name) ps := pc.getPolicyForClusterPolicyViolation(pv) if len(ps) == 0 { // there is no cluster policy for this violation, so we can delete this cluster policy violation - logger.V(4).Info("Cluster Policy Violation does not belong to an active policy, will be cleanedup") + glog.V(4).Infof("Cluster Policy Violation %s does not belong to an active policy, will be cleanedup", pv.Name) if err := pc.pvControl.DeleteClusterPolicyViolation(pv.Name); err != nil { - logger.Error(err, "failed to delete resource") + glog.Errorf("Failed to deleted cluster policy violation %s: %v", pv.Name, err) return } - logger.V(4).Info("resource deleted") + glog.V(4).Infof("Cluster Policy Violation %s deleted", pv.Name) return } - logger.V(4).Info("resource updated") + glog.V(4).Infof("Cluster PolicyViolation %s updated", pv.Name) for _, p := range ps { pc.enqueuePolicy(p) } } func (pc *PolicyController) getPolicyForClusterPolicyViolation(pv *kyverno.ClusterPolicyViolation) []*kyverno.ClusterPolicy { - logger := pc.log.WithValues("kind", pv.Kind, "namespace", pv.Namespace, "name", pv.Name) policies, err := pc.pLister.GetPolicyForPolicyViolation(pv) if err != nil || len(policies) == 0 { return nil @@ -115,7 +113,8 @@ func (pc *PolicyController) getPolicyForClusterPolicyViolation(pv *kyverno.Clust if len(policies) > 1 { // ControllerRef will ensure we don't do anything crazy, but more than one // item in this list nevertheless constitutes user error. - logger.V(4).Info("user error! more than one policy is selecting policy violation", "labels", pv.Labels, "policy", policies[0].Name) + glog.V(4).Infof("user error! more than one policy is selecting policy violation %s with labels: %#v, returning %s", + pv.Name, pv.Labels, policies[0].Name) } return policies } diff --git a/pkg/policy/common.go b/pkg/policy/common.go index cb99b9dd2f..b4d6155abc 100644 --- a/pkg/policy/common.go +++ b/pkg/policy/common.go @@ -3,10 +3,10 @@ package policy import ( "fmt" + "github.com/golang/glog" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" - "sigs.k8s.io/controller-runtime/pkg/log" ) func buildPolicyLabel(policyName string) (labels.Selector, error) { @@ -27,7 +27,7 @@ func buildPolicyLabel(policyName string) (labels.Selector, error) { func transformResource(resource unstructured.Unstructured) []byte { data, err := resource.MarshalJSON() if err != nil { - log.Log.Error(err, "failed to marshal resource") + glog.Errorf("failed to marshall resource %v: %v", resource, err) return nil } return data diff --git a/pkg/policy/common/common.go b/pkg/policy/common/common.go deleted file mode 100644 index 35bc132007..0000000000 --- a/pkg/policy/common/common.go +++ /dev/null @@ -1,85 +0,0 @@ -package common - -import ( - "fmt" - "regexp" - "strconv" - - "github.com/nirmata/kyverno/pkg/engine/anchor" -) - -//ValidatePattern validates the pattern -func ValidatePattern(patternElement interface{}, path string, supportedAnchors []anchor.IsAnchor) (string, error) { - switch typedPatternElement := patternElement.(type) { - case map[string]interface{}: - return validateMap(typedPatternElement, path, supportedAnchors) - case []interface{}: - return validateArray(typedPatternElement, path, supportedAnchors) - case string, float64, int, int64, bool, nil: - //TODO? check operator - return "", nil - default: - return path, fmt.Errorf("Validation rule failed at '%s', pattern contains unknown type", path) - } -} -func validateMap(patternMap map[string]interface{}, path string, supportedAnchors []anchor.IsAnchor) (string, error) { - // check if anchors are defined - for key, value := range patternMap { - // if key is anchor - // check regex () -> this is anchor - // () - // single char () - re, err := regexp.Compile(`^.?\(.+\)$`) - if err != nil { - return path + "/" + key, fmt.Errorf("Unable to parse the field %s: %v", key, err) - } - - matched := re.MatchString(key) - // check the type of anchor - if matched { - // some type of anchor - // check if valid anchor - if !checkAnchors(key, supportedAnchors) { - return path + "/" + key, fmt.Errorf("Unsupported anchor %s", key) - } - - // addition check for existence anchor - // value must be of type list - if anchor.IsExistenceAnchor(key) { - typedValue, ok := value.([]interface{}) - if !ok { - return path + "/" + key, fmt.Errorf("Existence anchor should have value of type list") - } - // validate there is only one entry in the list - if len(typedValue) == 0 || len(typedValue) > 1 { - return path + "/" + key, fmt.Errorf("Existence anchor: single value expected, multiple specified") - } - } - } - // lets validate the values now :) - if errPath, err := ValidatePattern(value, path+"/"+key, supportedAnchors); err != nil { - return errPath, err - } - } - return "", nil -} - -func validateArray(patternArray []interface{}, path string, supportedAnchors []anchor.IsAnchor) (string, error) { - for i, patternElement := range patternArray { - currentPath := path + strconv.Itoa(i) + "/" - // lets validate the values now :) - if errPath, err := ValidatePattern(patternElement, currentPath, supportedAnchors); err != nil { - return errPath, err - } - } - return "", nil -} - -func checkAnchors(key string, supportedAnchors []anchor.IsAnchor) bool { - for _, f := range supportedAnchors { - if f(key) { - return true - } - } - return false -} diff --git a/pkg/policy/controller.go b/pkg/policy/controller.go index 2a471a37fe..d303bebf52 100644 --- a/pkg/policy/controller.go +++ b/pkg/policy/controller.go @@ -1,9 +1,10 @@ package policy import ( + "fmt" "time" - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned" "github.com/nirmata/kyverno/pkg/client/clientset/versioned/scheme" @@ -71,7 +72,6 @@ type PolicyController struct { pvGenerator policyviolation.GeneratorInterface // resourceWebhookWatcher queues the webhook creation request, creates the webhook resourceWebhookWatcher *webhookconfig.ResourceWebhookRegister - log logr.Logger } // NewPolicyController create a new PolicyController @@ -84,11 +84,10 @@ func NewPolicyController(kyvernoClient *kyvernoclient.Clientset, eventGen event.Interface, pvGenerator policyviolation.GeneratorInterface, pMetaStore policystore.UpdateInterface, - resourceWebhookWatcher *webhookconfig.ResourceWebhookRegister, - log logr.Logger) (*PolicyController, error) { + resourceWebhookWatcher *webhookconfig.ResourceWebhookRegister) (*PolicyController, error) { // Event broad caster eventBroadcaster := record.NewBroadcaster() - eventBroadcaster.StartLogging(log.Info) + eventBroadcaster.StartLogging(glog.Infof) eventInterface, err := client.GetEventsInterface() if err != nil { return nil, err @@ -105,7 +104,6 @@ func NewPolicyController(kyvernoClient *kyvernoclient.Clientset, pMetaStore: pMetaStore, pvGenerator: pvGenerator, resourceWebhookWatcher: resourceWebhookWatcher, - log: log, } pc.pvControl = RealPVControl{Client: kyvernoClient, Recorder: pc.eventRecorder} @@ -147,7 +145,6 @@ func NewPolicyController(kyvernoClient *kyvernoclient.Clientset, } func (pc *PolicyController) addPolicy(obj interface{}) { - logger := pc.log p := obj.(*kyverno.ClusterPolicy) // Only process policies that are enabled for "background" execution // policy.spec.background -> "True" @@ -171,19 +168,19 @@ func (pc *PolicyController) addPolicy(obj interface{}) { return } } - logger.V(4).Info("adding policy", "name", p.Name) + + glog.V(4).Infof("Adding Policy %s", p.Name) pc.enqueuePolicy(p) } func (pc *PolicyController) updatePolicy(old, cur interface{}) { - logger := pc.log oldP := old.(*kyverno.ClusterPolicy) curP := cur.(*kyverno.ClusterPolicy) // TODO: optimize this : policy meta-store // Update policy-> (remove,add) err := pc.pMetaStore.UnRegister(*oldP) if err != nil { - logger.Error(err, "failed to unregister policy", "name", oldP.Name) + glog.Infof("Failed to unregister policy %s", oldP.Name) } pc.pMetaStore.Register(*curP) @@ -206,29 +203,28 @@ func (pc *PolicyController) updatePolicy(old, cur interface{}) { return } } - logger.V(4).Info("updating policy", "name", oldP.Name) + glog.V(4).Infof("Updating Policy %s", oldP.Name) pc.enqueuePolicy(curP) } func (pc *PolicyController) deletePolicy(obj interface{}) { - logger := pc.log p, ok := obj.(*kyverno.ClusterPolicy) if !ok { tombstone, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { - logger.Info("couldnt get object from tomstone", "obj", obj) + glog.Info(fmt.Errorf("Couldn't get object from tombstone %#v", obj)) return } p, ok = tombstone.Obj.(*kyverno.ClusterPolicy) if !ok { - logger.Info("tombstone container object that is not a policy", "obj", obj) + glog.Info(fmt.Errorf("Tombstone contained object that is not a Policy %#v", obj)) return } } - logger.V(4).Info("deleting policy", "name", p.Name) + glog.V(4).Infof("Deleting Policy %s", p.Name) // Unregister from policy meta-store if err := pc.pMetaStore.UnRegister(*p); err != nil { - logger.Error(err, "failed to unregister policy", "name", p.Name) + glog.Infof("failed to unregister policy %s", p.Name) } // we process policies that are not set of background processing as we need to perform policy violation // cleanup when a policy is deleted. @@ -236,10 +232,9 @@ func (pc *PolicyController) deletePolicy(obj interface{}) { } func (pc *PolicyController) enqueue(policy *kyverno.ClusterPolicy) { - logger := pc.log key, err := cache.MetaNamespaceKeyFunc(policy) if err != nil { - logger.Error(err, "failed to enqueu policy") + glog.Error(err) return } pc.queue.Add(key) @@ -247,16 +242,15 @@ func (pc *PolicyController) enqueue(policy *kyverno.ClusterPolicy) { // Run begins watching and syncing. func (pc *PolicyController) Run(workers int, stopCh <-chan struct{}) { - logger := pc.log defer utilruntime.HandleCrash() defer pc.queue.ShutDown() - logger.Info("starting") - defer logger.Info("shutting down") + glog.Info("Starting policy controller") + defer glog.Info("Shutting down policy controller") if !cache.WaitForCacheSync(stopCh, pc.pListerSynced, pc.cpvListerSynced, pc.nspvListerSynced) { - logger.Info("failed to sync informer cache") + glog.Error("failed to sync informer cache") return } @@ -291,33 +285,31 @@ func (pc *PolicyController) processNextWorkItem() bool { } func (pc *PolicyController) handleErr(err error, key interface{}) { - logger := pc.log if err == nil { pc.queue.Forget(key) return } if pc.queue.NumRequeues(key) < maxRetries { - logger.Error(err, "failed to sync policy", "key", key) + glog.V(2).Infof("Error syncing Policy %v: %v", key, err) pc.queue.AddRateLimited(key) return } utilruntime.HandleError(err) - logger.V(2).Info("dropping policy out of queue", "key", key) + glog.V(2).Infof("Dropping policy %q out of the queue: %v", key, err) pc.queue.Forget(key) } func (pc *PolicyController) syncPolicy(key string) error { - logger := pc.log startTime := time.Now() - logger.V(4).Info("started syncing policy", "key", key, "startTime", startTime) + glog.V(4).Infof("Started syncing policy %q (%v)", key, startTime) defer func() { - logger.V(4).Info("finished syncing policy", "key", key, "processingTime", time.Since(startTime)) + glog.V(4).Infof("Finished syncing policy %q (%v)", key, time.Since(startTime)) }() policy, err := pc.pLister.Get(key) if errors.IsNotFound(err) { - logger.V(2).Info("policy deleted", "key", key) + glog.V(2).Infof("Policy %v has been deleted", key) // delete cluster policy violation if err := pc.deleteClusterPolicyViolations(key); err != nil { return err @@ -330,7 +322,8 @@ func (pc *PolicyController) syncPolicy(key string) error { // remove webhook configurations if there are no policies if err := pc.removeResourceWebhookConfiguration(); err != nil { // do not fail, if unable to delete resource webhook config - logger.Error(err, "failed to remove resource webhook configurations") + glog.V(4).Infof("failed to remove resource webhook configuration: %v", err) + glog.Errorln(err) } return nil } diff --git a/pkg/policy/existing.go b/pkg/policy/existing.go index af8dfc09c6..97c09affac 100644 --- a/pkg/policy/existing.go +++ b/pkg/policy/existing.go @@ -5,7 +5,7 @@ import ( "sync" "time" - "github.com/go-logr/logr" + "github.com/golang/glog" "github.com/minio/minio/pkg/wildcard" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/config" @@ -19,27 +19,27 @@ import ( ) func (pc *PolicyController) processExistingResources(policy kyverno.ClusterPolicy) []response.EngineResponse { - logger := pc.log.WithValues("policy", policy.Name) // Parse through all the resources // drops the cache after configured rebuild time pc.rm.Drop() var engineResponses []response.EngineResponse // get resource that are satisfy the resource description defined in the rules - resourceMap := listResources(pc.client, policy, pc.configHandler, logger) + resourceMap := listResources(pc.client, policy, pc.configHandler) for _, resource := range resourceMap { // pre-processing, check if the policy and resource version has been processed before if !pc.rm.ProcessResource(policy.Name, policy.ResourceVersion, resource.GetKind(), resource.GetNamespace(), resource.GetName(), resource.GetResourceVersion()) { - logger.V(4).Info("policy and resource already processed", "policyResourceVersion", policy.ResourceVersion, "resourceResourceVersion", resource.GetResourceVersion(), "kind", resource.GetKind(), "namespace", resource.GetNamespace(), "name", resource.GetName()) + glog.V(4).Infof("policy %s with resource version %s already processed on resource %s/%s/%s with resource version %s", policy.Name, policy.ResourceVersion, resource.GetKind(), resource.GetNamespace(), resource.GetName(), resource.GetResourceVersion()) continue } // skip reporting violation on pod which has annotation pod-policies.kyverno.io/autogen-applied - if skipPodApplication(resource, logger) { + if skipPodApplication(resource) { continue } // apply the policy on each - engineResponse := applyPolicy(policy, resource, logger) + glog.V(4).Infof("apply policy %s with resource version %s on resource %s/%s/%s with resource version %s", policy.Name, policy.ResourceVersion, resource.GetKind(), resource.GetNamespace(), resource.GetName(), resource.GetResourceVersion()) + engineResponse := applyPolicy(policy, resource) // get engine response for mutation & validation independently engineResponses = append(engineResponses, engineResponse...) // post-processing, register the resource as processed @@ -48,26 +48,36 @@ func (pc *PolicyController) processExistingResources(policy kyverno.ClusterPolic return engineResponses } -func listResources(client *client.Client, policy kyverno.ClusterPolicy, configHandler config.Interface, log logr.Logger) map[string]unstructured.Unstructured { +func listResources(client *client.Client, policy kyverno.ClusterPolicy, configHandler config.Interface) map[string]unstructured.Unstructured { // key uid resourceMap := map[string]unstructured.Unstructured{} for _, rule := range policy.Spec.Rules { // resources that match for _, k := range rule.MatchResources.Kinds { + // if kindIsExcluded(k, rule.ExcludeResources.Kinds) { + // glog.V(4).Infof("processing policy %s rule %s: kind %s is exluded", policy.Name, rule.Name, k) + // continue + // } var namespaces []string + if k == "Namespace" { + // TODO + // this is handled by generator controller + glog.V(4).Infof("skipping processing policy %s rule %s for kind Namespace", policy.Name, rule.Name) + continue + } if len(rule.MatchResources.Namespaces) > 0 { namespaces = append(namespaces, rule.MatchResources.Namespaces...) - log.V(4).Info("namespaces included", "namespaces", rule.MatchResources.Namespaces) + glog.V(4).Infof("namespaces specified for inclusion: %v", rule.MatchResources.Namespaces) } else { - log.V(4).Info("processing all namespaces", "rule", rule.Name) + glog.V(4).Infof("processing policy %s rule %s, namespace not defined, getting all namespaces ", policy.Name, rule.Name) // get all namespaces - namespaces = getAllNamespaces(client, log) + namespaces = getAllNamespaces(client) } // get resources in the namespaces for _, ns := range namespaces { - rMap := getResourcesPerNamespace(k, client, ns, rule, configHandler, log) + rMap := getResourcesPerNamespace(k, client, ns, rule, configHandler) mergeresources(resourceMap, rMap) } @@ -76,16 +86,16 @@ func listResources(client *client.Client, policy kyverno.ClusterPolicy, configHa return resourceMap } -func getResourcesPerNamespace(kind string, client *client.Client, namespace string, rule kyverno.Rule, configHandler config.Interface, log logr.Logger) map[string]unstructured.Unstructured { +func getResourcesPerNamespace(kind string, client *client.Client, namespace string, rule kyverno.Rule, configHandler config.Interface) map[string]unstructured.Unstructured { resourceMap := map[string]unstructured.Unstructured{} // merge include and exclude label selector values ls := rule.MatchResources.Selector // ls := mergeLabelSectors(rule.MatchResources.Selector, rule.ExcludeResources.Selector) // list resources - log.V(4).Info("list resources to be processed") + glog.V(4).Infof("get resources for kind %s, namespace %s, selector %v", kind, namespace, rule.MatchResources.Selector) list, err := client.ListResource(kind, namespace, ls) if err != nil { - log.Error(err, "failed to list resources", "kind", kind) + glog.Infof("unable to get resources: err %v", err) return nil } // filter based on name @@ -93,6 +103,7 @@ func getResourcesPerNamespace(kind string, client *client.Client, namespace stri // match name if rule.MatchResources.Name != "" { if !wildcard.Match(rule.MatchResources.Name, r.GetName()) { + glog.V(4).Infof("skipping resource %s/%s due to include condition name=%s mistatch", r.GetNamespace(), r.GetName(), rule.MatchResources.Name) continue } } @@ -107,11 +118,12 @@ func getResourcesPerNamespace(kind string, client *client.Client, namespace stri // exclude the resources // skip resources to be filtered - excludeResources(resourceMap, rule.ExcludeResources.ResourceDescription, configHandler, log) + excludeResources(resourceMap, rule.ExcludeResources.ResourceDescription, configHandler) + // glog.V(4).Infof("resource map: %v", resourceMap) return resourceMap } -func excludeResources(included map[string]unstructured.Unstructured, exclude kyverno.ResourceDescription, configHandler config.Interface, log logr.Logger) { +func excludeResources(included map[string]unstructured.Unstructured, exclude kyverno.ResourceDescription, configHandler config.Interface) { if reflect.DeepEqual(exclude, (kyverno.ResourceDescription{})) { return } @@ -142,7 +154,7 @@ func excludeResources(included map[string]unstructured.Unstructured, exclude kyv selector, err := metav1.LabelSelectorAsSelector(exclude.Selector) // if the label selector is incorrect, should be fail or if err != nil { - log.Error(err, "failed to build label selector") + glog.Error(err) return Skip } if selector.Matches(labels.Set(labelsMap)) { @@ -193,6 +205,8 @@ func excludeResources(included map[string]unstructured.Unstructured, exclude kyv } // exclude the filtered resources if configHandler.ToFilter(resource.GetKind(), resource.GetNamespace(), resource.GetName()) { + //TODO: improve the text + glog.V(4).Infof("excluding resource %s/%s/%s as its satisfies the filtered resources", resource.GetKind(), resource.GetNamespace(), resource.GetName()) delete(included, uid) continue } @@ -230,13 +244,12 @@ func mergeresources(a, b map[string]unstructured.Unstructured) { } } -func getAllNamespaces(client *client.Client, log logr.Logger) []string { - +func getAllNamespaces(client *client.Client) []string { var namespaces []string // get all namespaces nsList, err := client.ListResource("Namespace", "", nil) if err != nil { - log.Error(err, "failed to list namespaces") + glog.Error(err) return namespaces } for _, ns := range nsList.Items { @@ -278,11 +291,14 @@ type resourceManager interface { //TODO: or drop based on the size func (rm *ResourceManager) Drop() { timeSince := time.Since(rm.time) + glog.V(4).Infof("time since last cache reset time %v is %v", rm.time, timeSince) + glog.V(4).Infof("cache rebuild time %v", time.Duration(rm.rebuildTime)*time.Second) if timeSince > time.Duration(rm.rebuildTime)*time.Second { rm.mux.Lock() defer rm.mux.Unlock() rm.data = map[string]interface{}{} rm.time = time.Now() + glog.V(4).Infof("dropping cache at time %v", rm.time) } } @@ -311,14 +327,14 @@ func buildKey(policy, pv, kind, ns, name, rv string) string { return policy + "/" + pv + "/" + kind + "/" + ns + "/" + name + "/" + rv } -func skipPodApplication(resource unstructured.Unstructured, log logr.Logger) bool { +func skipPodApplication(resource unstructured.Unstructured) bool { if resource.GetKind() != "Pod" { return false } annotation := resource.GetAnnotations() if _, ok := annotation[engine.PodTemplateAnnotation]; ok { - log.V(4).Info("Policies already processed on pod controllers, skip processing policy on Pod", "kind", resource.GetKind(), "namespace", resource.GetNamespace(), "name", resource.GetName()) + glog.V(4).Infof("Policies already processed on pod controllers, skip processing policy on Pod/%s/%s", resource.GetNamespace(), resource.GetName()) return true } diff --git a/pkg/policy/generate/auth.go b/pkg/policy/generate/auth.go deleted file mode 100644 index 3da64a4289..0000000000 --- a/pkg/policy/generate/auth.go +++ /dev/null @@ -1,74 +0,0 @@ -package generate - -import ( - "github.com/go-logr/logr" - "github.com/nirmata/kyverno/pkg/auth" - dclient "github.com/nirmata/kyverno/pkg/dclient" -) - -//Operations provides methods to performing operations on resource -type Operations interface { - // CanICreate returns 'true' if self can 'create' resource - CanICreate(kind, namespace string) (bool, error) - // CanIUpdate returns 'true' if self can 'update' resource - CanIUpdate(kind, namespace string) (bool, error) - // CanIDelete returns 'true' if self can 'delete' resource - CanIDelete(kind, namespace string) (bool, error) - // CanIGet returns 'true' if self can 'get' resource - CanIGet(kind, namespace string) (bool, error) -} - -//Auth provides implementation to check if caller/self/kyverno has access to perofrm operations -type Auth struct { - client *dclient.Client - log logr.Logger -} - -//NewAuth returns a new instance of Auth for operations -func NewAuth(client *dclient.Client, log logr.Logger) *Auth { - a := Auth{ - client: client, - log: log, - } - return &a -} - -// CanICreate returns 'true' if self can 'create' resource -func (a *Auth) CanICreate(kind, namespace string) (bool, error) { - canI := auth.NewCanI(a.client, kind, namespace, "create", a.log) - ok, err := canI.RunAccessCheck() - if err != nil { - return false, err - } - return ok, nil -} - -// CanIUpdate returns 'true' if self can 'update' resource -func (a *Auth) CanIUpdate(kind, namespace string) (bool, error) { - canI := auth.NewCanI(a.client, kind, namespace, "update", a.log) - ok, err := canI.RunAccessCheck() - if err != nil { - return false, err - } - return ok, nil -} - -// CanIDelete returns 'true' if self can 'delete' resource -func (a *Auth) CanIDelete(kind, namespace string) (bool, error) { - canI := auth.NewCanI(a.client, kind, namespace, "delete", a.log) - ok, err := canI.RunAccessCheck() - if err != nil { - return false, err - } - return ok, nil -} - -// CanIGet returns 'true' if self can 'get' resource -func (a *Auth) CanIGet(kind, namespace string) (bool, error) { - canI := auth.NewCanI(a.client, kind, namespace, "get", a.log) - ok, err := canI.RunAccessCheck() - if err != nil { - return false, err - } - return ok, nil -} diff --git a/pkg/policy/generate/fake.go b/pkg/policy/generate/fake.go deleted file mode 100644 index 0d561c7a94..0000000000 --- a/pkg/policy/generate/fake.go +++ /dev/null @@ -1,21 +0,0 @@ -package generate - -import ( - kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" - "github.com/nirmata/kyverno/pkg/policy/generate/fake" -) - -//FakeGenerate provides implementation for generate rule processing -// with mocks/fakes for cluster interactions -type FakeGenerate struct { - Generate -} - -//NewFakeGenerate returns a new instance of generatecheck that uses -// fake/mock implementation for operation access(always returns true) -func NewFakeGenerate(rule kyverno.Generation) *FakeGenerate { - g := FakeGenerate{} - g.rule = rule - g.authCheck = fake.NewFakeAuth() - return &g -} diff --git a/pkg/policy/generate/fake/auth.go b/pkg/policy/generate/fake/auth.go deleted file mode 100644 index 3e7467bf06..0000000000 --- a/pkg/policy/generate/fake/auth.go +++ /dev/null @@ -1,31 +0,0 @@ -package fake - -//FakeAuth providers implementation for testing, retuning true for all operations -type FakeAuth struct { -} - -//NewFakeAuth returns a new instance of Fake Auth that returns true for each operation -func NewFakeAuth() *FakeAuth { - a := FakeAuth{} - return &a -} - -// CanICreate returns 'true' -func (a *FakeAuth) CanICreate(kind, namespace string) (bool, error) { - return true, nil -} - -// CanIUpdate returns 'true' -func (a *FakeAuth) CanIUpdate(kind, namespace string) (bool, error) { - return true, nil -} - -// CanIDelete returns 'true' -func (a *FakeAuth) CanIDelete(kind, namespace string) (bool, error) { - return true, nil -} - -// CanIGet returns 'true' -func (a *FakeAuth) CanIGet(kind, namespace string) (bool, error) { - return true, nil -} diff --git a/pkg/policy/generate/validate.go b/pkg/policy/generate/validate.go deleted file mode 100644 index 460842ea98..0000000000 --- a/pkg/policy/generate/validate.go +++ /dev/null @@ -1,151 +0,0 @@ -package generate - -import ( - "fmt" - "reflect" - - "github.com/go-logr/logr" - kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" - dclient "github.com/nirmata/kyverno/pkg/dclient" - "github.com/nirmata/kyverno/pkg/engine/anchor" - "github.com/nirmata/kyverno/pkg/engine/variables" - "github.com/nirmata/kyverno/pkg/policy/common" -) - -// Generate provides implementation to validate 'generate' rule -type Generate struct { - // rule to hold 'generate' rule specifications - rule kyverno.Generation - // authCheck to check access for operations - authCheck Operations - //logger - log logr.Logger -} - -//NewGenerateFactory returns a new instance of Generate validation checker -func NewGenerateFactory(client *dclient.Client, rule kyverno.Generation, log logr.Logger) *Generate { - g := Generate{ - rule: rule, - authCheck: NewAuth(client, log), - log: log, - } - - return &g -} - -//Validate validates the 'generate' rule -func (g *Generate) Validate() (string, error) { - rule := g.rule - if rule.Data == nil && rule.Clone == (kyverno.CloneFrom{}) { - return "", fmt.Errorf("clone or data are required") - } - if rule.Data != nil && rule.Clone != (kyverno.CloneFrom{}) { - return "", fmt.Errorf("only one operation allowed per generate rule(data or clone)") - } - kind, name, namespace := rule.Kind, rule.Name, rule.Namespace - - if name == "" { - return "name", fmt.Errorf("name cannot be empty") - } - if kind == "" { - return "kind", fmt.Errorf("kind cannot be empty") - } - // Can I generate resource - - if !reflect.DeepEqual(rule.Clone, kyverno.CloneFrom{}) { - if path, err := g.validateClone(rule.Clone, kind); err != nil { - return fmt.Sprintf("clone.%s", path), err - } - } - if rule.Data != nil { - //TODO: is this required ?? as anchors can only be on pattern and not resource - // we can add this check by not sure if its needed here - if path, err := common.ValidatePattern(rule.Data, "/", []anchor.IsAnchor{}); err != nil { - return fmt.Sprintf("data.%s", path), fmt.Errorf("anchors not supported on generate resources: %v", err) - } - } - - // Kyverno generate-controller create/update/deletes the resources specified in generate rule of policy - // kyverno uses SA 'kyverno-service-account' and has default ClusterRoles and ClusterRoleBindings - // instuctions to modify the RBAC for kyverno are mentioned at https://github.com/nirmata/kyverno/blob/master/documentation/installation.md - // - operations required: create/update/delete/get - // If kind and namespace contain variables, then we cannot resolve then so we skip the processing - if err := g.canIGenerate(kind, namespace); err != nil { - return "", err - } - return "", nil -} - -func (g *Generate) validateClone(c kyverno.CloneFrom, kind string) (string, error) { - if c.Name == "" { - return "name", fmt.Errorf("name cannot be empty") - } - if c.Namespace == "" { - return "namespace", fmt.Errorf("namespace cannot be empty") - } - namespace := c.Namespace - // Skip if there is variable defined - if !variables.IsVariable(kind) && !variables.IsVariable(namespace) { - // GET - ok, err := g.authCheck.CanIGet(kind, namespace) - if err != nil { - return "", err - } - if !ok { - return "", fmt.Errorf("kyverno does not have permissions to 'get' resource %s/%s. Update permissions in ClusterRole 'kyverno:generatecontroller'", kind, namespace) - } - } else { - g.log.V(4).Info("name & namespace uses variables, so cannot be resolved. Skipping Auth Checks.") - } - return "", nil -} - -//canIGenerate returns a error if kyverno cannot perform oprations -func (g *Generate) canIGenerate(kind, namespace string) error { - // Skip if there is variable defined - authCheck := g.authCheck - if !variables.IsVariable(kind) && !variables.IsVariable(namespace) { - // CREATE - ok, err := authCheck.CanICreate(kind, namespace) - if err != nil { - // machinery error - return err - } - if !ok { - return fmt.Errorf("kyverno does not have permissions to 'create' resource %s/%s. Update permissions in ClusterRole 'kyverno:generatecontroller'", kind, namespace) - } - // UPDATE - ok, err = authCheck.CanIUpdate(kind, namespace) - if err != nil { - // machinery error - return err - } - if !ok { - return fmt.Errorf("kyverno does not have permissions to 'update' resource %s/%s. Update permissions in ClusterRole 'kyverno:generatecontroller'", kind, namespace) - } - // GET - ok, err = authCheck.CanIGet(kind, namespace) - if err != nil { - // machinery error - return err - } - if !ok { - return fmt.Errorf("kyverno does not have permissions to 'get' resource %s/%s. Update permissions in ClusterRole 'kyverno:generatecontroller'", kind, namespace) - } - - // DELETE - ok, err = authCheck.CanIDelete(kind, namespace) - if err != nil { - // machinery error - return err - } - if !ok { - return fmt.Errorf("kyverno does not have permissions to 'delete' resource %s/%s. Update permissions in ClusterRole 'kyverno:generatecontroller'", kind, namespace) - } - - } else { - g.log.V(4).Info("name & namespace uses variables, so cannot be resolved. Skipping Auth Checks.") - } - - return nil -} diff --git a/pkg/policy/generate/validate_test.go b/pkg/policy/generate/validate_test.go deleted file mode 100644 index 631aac6ed3..0000000000 --- a/pkg/policy/generate/validate_test.go +++ /dev/null @@ -1,89 +0,0 @@ -package generate - -import ( - "encoding/json" - "testing" - - kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" - "gotest.tools/assert" -) - -func Test_Validate_Generate(t *testing.T) { - rawGenerate := []byte(` - { - "kind": "NetworkPolicy", - "name": "defaultnetworkpolicy", - "data": { - "spec": { - "podSelector": {}, - "policyTypes": [ - "Ingress", - "Egress" - ], - "ingress": [ - {} - ], - "egress": [ - {} - ] - } - } - }`) - - var genRule kyverno.Generation - err := json.Unmarshal(rawGenerate, &genRule) - assert.NilError(t, err) - checker := NewFakeGenerate(genRule) - if _, err := checker.Validate(); err != nil { - assert.Assert(t, err != nil) - } -} - -func Test_Validate_Generate_HasAnchors(t *testing.T) { - var err error - rawGenerate := []byte(` - { - "kind": "NetworkPolicy", - "name": "defaultnetworkpolicy", - "data": { - "spec": { - "(podSelector)": {}, - "policyTypes": [ - "Ingress", - "Egress" - ], - "ingress": [ - {} - ], - "egress": [ - {} - ] - } - } - }`) - - var genRule kyverno.Generation - err = json.Unmarshal(rawGenerate, &genRule) - assert.NilError(t, err) - checker := NewFakeGenerate(genRule) - if _, err := checker.Validate(); err != nil { - assert.Assert(t, err != nil) - } - - rawGenerate = []byte(` - { - "kind": "ConfigMap", - "name": "copied-cm", - "clone": { - "^(namespace)": "default", - "name": "game" - } - }`) - - err = json.Unmarshal(rawGenerate, &genRule) - assert.NilError(t, err) - checker = NewFakeGenerate(genRule) - if _, err := checker.Validate(); err != nil { - assert.Assert(t, err != nil) - } -} diff --git a/pkg/policy/mutate/validate.go b/pkg/policy/mutate/validate.go deleted file mode 100644 index 6a24c3d388..0000000000 --- a/pkg/policy/mutate/validate.go +++ /dev/null @@ -1,63 +0,0 @@ -package mutate - -import ( - "errors" - "fmt" - - kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" - "github.com/nirmata/kyverno/pkg/engine/anchor" - "github.com/nirmata/kyverno/pkg/policy/common" -) - -// Mutate provides implementation to validate 'mutate' rule -type Mutate struct { - // rule to hold 'mutate' rule specifications - rule kyverno.Mutation -} - -//NewMutateFactory returns a new instance of Mutate validation checker -func NewMutateFactory(rule kyverno.Mutation) *Mutate { - m := Mutate{ - rule: rule, - } - return &m -} - -//Validate validates the 'mutate' rule -func (m *Mutate) Validate() (string, error) { - rule := m.rule - // JSON Patches - if len(rule.Patches) != 0 { - for i, patch := range rule.Patches { - if err := validatePatch(patch); err != nil { - return fmt.Sprintf("patch[%d]", i), err - } - } - } - // Overlay - if rule.Overlay != nil { - path, err := common.ValidatePattern(rule.Overlay, "/", []anchor.IsAnchor{anchor.IsConditionAnchor, anchor.IsAddingAnchor}) - if err != nil { - return path, err - } - } - return "", nil -} - -// Validate if all mandatory PolicyPatch fields are set -func validatePatch(pp kyverno.Patch) error { - if pp.Path == "" { - return errors.New("JSONPatch field 'path' is mandatory") - } - if pp.Operation == "add" || pp.Operation == "replace" { - if pp.Value == nil { - return fmt.Errorf("JSONPatch field 'value' is mandatory for operation '%s'", pp.Operation) - } - - return nil - } else if pp.Operation == "remove" { - return nil - } - - return fmt.Errorf("Unsupported JSONPatch operation '%s'", pp.Operation) -} diff --git a/pkg/policy/mutate/validate_test.go b/pkg/policy/mutate/validate_test.go deleted file mode 100644 index 84ff0e59b7..0000000000 --- a/pkg/policy/mutate/validate_test.go +++ /dev/null @@ -1,151 +0,0 @@ -package mutate - -import ( - "encoding/json" - "testing" - - kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" - "gotest.tools/assert" -) - -func Test_Validate_Mutate_ConditionAnchor(t *testing.T) { - rawMutate := []byte(` - { - "overlay": { - "spec": { - "(serviceAccountName)": "*", - "automountServiceAccountToken": false - } - } - }`) - - var mutate kyverno.Mutation - err := json.Unmarshal(rawMutate, &mutate) - assert.NilError(t, err) - checker := NewMutateFactory(mutate) - if _, err := checker.Validate(); err != nil { - assert.NilError(t, err) - } -} - -func Test_Validate_Mutate_PlusAnchor(t *testing.T) { - rawMutate := []byte(` - { - "overlay": { - "spec": { - "+(serviceAccountName)": "*", - "automountServiceAccountToken": false - } - } - }`) - - var mutate kyverno.Mutation - err := json.Unmarshal(rawMutate, &mutate) - assert.NilError(t, err) - - checker := NewMutateFactory(mutate) - if _, err := checker.Validate(); err != nil { - assert.NilError(t, err) - } -} - -func Test_Validate_Mutate_Mismatched(t *testing.T) { - rawMutate := []byte(` - { - "overlay": { - "spec": { - "^(serviceAccountName)": "*", - "automountServiceAccountToken": false - } - } - }`) - - var mutateExistence kyverno.Mutation - err := json.Unmarshal(rawMutate, &mutateExistence) - assert.NilError(t, err) - - checker := NewMutateFactory(mutateExistence) - if _, err := checker.Validate(); err != nil { - assert.Assert(t, err != nil) - } - - var mutateEqual kyverno.Mutation - rawMutate = []byte(` - { - "overlay": { - "spec": { - "=(serviceAccountName)": "*", - "automountServiceAccountToken": false - } - } - }`) - - err = json.Unmarshal(rawMutate, &mutateEqual) - assert.NilError(t, err) - - checker = NewMutateFactory(mutateEqual) - if _, err := checker.Validate(); err != nil { - assert.Assert(t, err != nil) - } - - var mutateNegation kyverno.Mutation - rawMutate = []byte(` - { - "overlay": { - "spec": { - "X(serviceAccountName)": "*", - "automountServiceAccountToken": false - } - } - }`) - - err = json.Unmarshal(rawMutate, &mutateNegation) - assert.NilError(t, err) - - checker = NewMutateFactory(mutateEqual) - if _, err := checker.Validate(); err != nil { - assert.Assert(t, err != nil) - } -} - -func Test_Validate_Mutate_Unsupported(t *testing.T) { - var err error - var mutate kyverno.Mutation - // case 1 - rawMutate := []byte(` - { - "overlay": { - "spec": { - "!(serviceAccountName)": "*", - "automountServiceAccountToken": false - } - } - }`) - - err = json.Unmarshal(rawMutate, &mutate) - assert.NilError(t, err) - - checker := NewMutateFactory(mutate) - if _, err := checker.Validate(); err != nil { - assert.Assert(t, err != nil) - } - - // case 2 - rawMutate = []byte(` - { - "overlay": { - "spec": { - "~(serviceAccountName)": "*", - "automountServiceAccountToken": false - } - } - }`) - - err = json.Unmarshal(rawMutate, &mutate) - assert.NilError(t, err) - - checker = NewMutateFactory(mutate) - if _, err := checker.Validate(); err != nil { - assert.Assert(t, err != nil) - } -} diff --git a/pkg/policy/namespacedpv.go b/pkg/policy/namespacedpv.go index 8dd83d1f12..654343d7df 100644 --- a/pkg/policy/namespacedpv.go +++ b/pkg/policy/namespacedpv.go @@ -1,13 +1,13 @@ package policy import ( + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" cache "k8s.io/client-go/tools/cache" ) func (pc *PolicyController) addNamespacedPolicyViolation(obj interface{}) { pv := obj.(*kyverno.PolicyViolation) - logger := pc.log.WithValues("kind", pv.Kind, "namespace", pv.Namespace, "name", pv.Name) if pv.DeletionTimestamp != nil { // On a restart of the controller manager, it's possible for an object to @@ -20,16 +20,15 @@ func (pc *PolicyController) addNamespacedPolicyViolation(obj interface{}) { ps := pc.getPolicyForNamespacedPolicyViolation(pv) if len(ps) == 0 { // there is no cluster policy for this violation, so we can delete this cluster policy violation - logger.V(4).Info("namepaced policy violation does not belong to an active policy, will be cleanedup") + glog.V(4).Infof("PolicyViolation %s does not belong to an active policy, will be cleanedup", pv.Name) if err := pc.pvControl.DeleteNamespacedPolicyViolation(pv.Namespace, pv.Name); err != nil { - logger.Error(err, "failed to delete resource") + glog.Errorf("Failed to deleted policy violation %s: %v", pv.Name, err) return } - logger.V(4).Info("resource deleted") + glog.V(4).Infof("PolicyViolation %s deleted", pv.Name) return } - - logger.V(4).Info("resource added") + glog.V(4).Infof("Orphan Policy Violation %s added.", pv.Name) for _, p := range ps { pc.enqueuePolicy(p) } @@ -43,20 +42,19 @@ func (pc *PolicyController) updateNamespacedPolicyViolation(old, cur interface{} // Two different versions of the same replica set will always have different RVs. return } - logger := pc.log.WithValues("kind", curPV.Kind, "namespace", curPV.Namespace, "name", curPV.Name) ps := pc.getPolicyForNamespacedPolicyViolation(curPV) if len(ps) == 0 { // there is no namespaced policy for this violation, so we can delete this cluster policy violation - logger.V(4).Info("nameapced policy violation does not belong to an active policy, will be cleanedup") + glog.V(4).Infof("Namespaced Policy Violation %s does not belong to an active policy, will be cleanedup", curPV.Name) if err := pc.pvControl.DeleteNamespacedPolicyViolation(curPV.Namespace, curPV.Name); err != nil { - logger.Error(err, "failed to delete resource") + glog.Errorf("Failed to deleted namespaced policy violation %s: %v", curPV.Name, err) return } - logger.V(4).Info("resource deleted") + glog.V(4).Infof("Namespaced Policy Violation %s deleted", curPV.Name) return } - logger.V(4).Info("resource updated") + glog.V(4).Infof("Namespaced Policy sViolation %s updated", curPV.Name) for _, p := range ps { pc.enqueuePolicy(p) } @@ -64,7 +62,6 @@ func (pc *PolicyController) updateNamespacedPolicyViolation(old, cur interface{} } func (pc *PolicyController) deleteNamespacedPolicyViolation(obj interface{}) { - logger := pc.log pv, ok := obj.(*kyverno.PolicyViolation) // When a delete is dropped, the relist will notice a PolicyViolation in the store not // in the list, leading to the insertion of a tombstone object which contains @@ -73,36 +70,34 @@ func (pc *PolicyController) deleteNamespacedPolicyViolation(obj interface{}) { if !ok { tombstone, ok := obj.(cache.DeletedFinalStateUnknown) if !ok { - logger.Info("Couldn't get object from tombstone", "obj", obj) + glog.Infof("Couldn't get object from tombstone %#v", obj) return } pv, ok = tombstone.Obj.(*kyverno.PolicyViolation) if !ok { - logger.Info("Couldn't get object from tombstone", "obj", obj) + glog.Infof("Couldn't get object from tombstone %#v", obj) return } } - logger = logger.WithValues("kind", pv.Kind, "namespace", pv.Namespace, "name", pv.Name) ps := pc.getPolicyForNamespacedPolicyViolation(pv) if len(ps) == 0 { // there is no cluster policy for this violation, so we can delete this cluster policy violation - logger.V(4).Info("nameapced policy violation does not belong to an active policy, will be cleanedup") + glog.V(4).Infof("Namespaced Policy Violation %s does not belong to an active policy, will be cleanedup", pv.Name) if err := pc.pvControl.DeleteNamespacedPolicyViolation(pv.Namespace, pv.Name); err != nil { - logger.Error(err, "failed to delete resource") + glog.Errorf("Failed to deleted namespaced policy violation %s: %v", pv.Name, err) return } - logger.V(4).Info("resource deleted") + glog.V(4).Infof("Namespaced Policy Violation %s deleted", pv.Name) return } - logger.V(4).Info("resource updated") + glog.V(4).Infof("Namespaced PolicyViolation %s updated", pv.Name) for _, p := range ps { pc.enqueuePolicy(p) } } func (pc *PolicyController) getPolicyForNamespacedPolicyViolation(pv *kyverno.PolicyViolation) []*kyverno.ClusterPolicy { - logger := pc.log.WithValues("kind", pv.Kind, "namespace", pv.Namespace, "name", pv.Name) policies, err := pc.pLister.GetPolicyForNamespacedPolicyViolation(pv) if err != nil || len(policies) == 0 { return nil @@ -114,7 +109,8 @@ func (pc *PolicyController) getPolicyForNamespacedPolicyViolation(pv *kyverno.Po if len(policies) > 1 { // ControllerRef will ensure we don't do anything crazy, but more than one // item in this list nevertheless constitutes user error. - logger.V(4).Info("user error! more than one policy is selecting policy violation", "labels", pv.Labels, "policy", policies[0].Name) + glog.V(4).Infof("user error! more than one policy is selecting policy violation %s with labels: %#v, returning %s", + pv.Name, pv.Labels, policies[0].Name) } return policies } diff --git a/pkg/policy/report.go b/pkg/policy/report.go index 476e07abb9..3614da9b32 100644 --- a/pkg/policy/report.go +++ b/pkg/policy/report.go @@ -3,7 +3,7 @@ package policy import ( "fmt" - "github.com/go-logr/logr" + "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/engine/response" "github.com/nirmata/kyverno/pkg/event" "github.com/nirmata/kyverno/pkg/policyviolation" @@ -13,12 +13,11 @@ import ( // - has violation -> report // - no violation -> cleanup policy violations func (pc *PolicyController) cleanupAndReport(engineResponses []response.EngineResponse) { - logger := pc.log // generate Events - eventInfos := generateEvents(pc.log, engineResponses) + eventInfos := generateEvents(engineResponses) pc.eventGen.Add(eventInfos...) // create policy violation - pvInfos := policyviolation.GeneratePVsFromEngineResponse(engineResponses, logger) + pvInfos := policyviolation.GeneratePVsFromEngineResponse(engineResponses) for i := range pvInfos { pvInfos[i].FromSync = true } @@ -30,27 +29,39 @@ func (pc *PolicyController) cleanupAndReport(engineResponses []response.EngineRe pc.cleanUp(engineResponses) } -func generateEvents(log logr.Logger, ers []response.EngineResponse) []event.Info { +func (pc *PolicyController) cleanUp(ers []response.EngineResponse) { + for _, er := range ers { + if !er.IsSuccesful() { + continue + } + if len(er.PolicyResponse.Rules) == 0 { + continue + } + // clean up after the policy has been corrected + pc.cleanUpPolicyViolation(er.PolicyResponse) + } +} + +func generateEvents(ers []response.EngineResponse) []event.Info { var eventInfos []event.Info for _, er := range ers { if er.IsSuccesful() { continue } - eventInfos = append(eventInfos, generateEventsPerEr(log, er)...) + eventInfos = append(eventInfos, generateEventsPerEr(er)...) } return eventInfos } -func generateEventsPerEr(log logr.Logger, er response.EngineResponse) []event.Info { - logger := log.WithValues("policy", er.PolicyResponse.Policy, "kind", er.PolicyResponse.Resource.Kind, "namespace", er.PolicyResponse.Resource.Namespace, "name", er.PolicyResponse.Resource.Name) +func generateEventsPerEr(er response.EngineResponse) []event.Info { var eventInfos []event.Info - logger.V(4).Info("reporting results for policy") + glog.V(4).Infof("reporting results for policy '%s' application on resource '%s/%s/%s'", er.PolicyResponse.Policy, er.PolicyResponse.Resource.Kind, er.PolicyResponse.Resource.Namespace, er.PolicyResponse.Resource.Name) for _, rule := range er.PolicyResponse.Rules { if rule.Success { continue } // generate event on resource for each failed rule - logger.V(4).Info("generating event on resource") + glog.V(4).Infof("generation event on resource '%s/%s/%s' for policy '%s'", er.PolicyResponse.Resource.Kind, er.PolicyResponse.Resource.Namespace, er.PolicyResponse.Resource.Name, er.PolicyResponse.Policy) e := event.Info{} e.Kind = er.PolicyResponse.Resource.Kind e.Namespace = er.PolicyResponse.Resource.Namespace @@ -65,7 +76,7 @@ func generateEventsPerEr(log logr.Logger, er response.EngineResponse) []event.In } // generate a event on policy for all failed rules - logger.V(4).Info("generating event on policy") + glog.V(4).Infof("generation event on policy '%s'", er.PolicyResponse.Policy) e := event.Info{} e.Kind = "ClusterPolicy" e.Namespace = "" diff --git a/pkg/policy/validate.go b/pkg/policy/validate.go index cffa69fe68..9dec98a2c9 100644 --- a/pkg/policy/validate.go +++ b/pkg/policy/validate.go @@ -5,12 +5,16 @@ import ( "errors" "fmt" "reflect" + "regexp" + "strconv" "strings" + "github.com/golang/glog" + "github.com/nirmata/kyverno/pkg/openapi" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" - dclient "github.com/nirmata/kyverno/pkg/dclient" + "github.com/nirmata/kyverno/pkg/engine/anchor" rbacv1 "k8s.io/api/rbac/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -18,10 +22,11 @@ import ( // Validate does some initial check to verify some conditions // - One operation per rule // - ResourceDescription mandatory checks -func Validate(policyRaw []byte, client *dclient.Client, mock bool) error { +func Validate(policyRaw []byte) error { var p kyverno.ClusterPolicy err := json.Unmarshal(policyRaw, &p) if err != nil { + glog.Errorf("Failed to unmarshal policy admission request, err %v\n", err) return fmt.Errorf("failed to unmarshal policy admission request err %v", err) } @@ -57,12 +62,24 @@ func Validate(policyRaw []byte, client *dclient.Client, mock bool) error { // as there are more than 1 operation in rule, not need to evaluate it further return fmt.Errorf("path: spec.rules[%d]: %v", i, err) } - // validate rule actions - // - Mutate - // - Validate - // - Generate - if err := validateActions(i, rule, client, mock); err != nil { - return err + // Operation Validation + // Mutation + if rule.HasMutate() { + if path, err := validateMutation(rule.Mutation); err != nil { + return fmt.Errorf("path: spec.rules[%d].mutate.%s.: %v", i, path, err) + } + } + // Validation + if rule.HasValidate() { + if path, err := validateValidation(rule.Validation); err != nil { + return fmt.Errorf("path: spec.rules[%d].validate.%s.: %v", i, path, err) + } + } + // Generation + if rule.HasGenerate() { + if path, err := validateGeneration(rule.Generation); err != nil { + return fmt.Errorf("path: spec.rules[%d].generate.%s.: %v", i, path, err) + } } // If a rules match block does not match any kind, @@ -261,3 +278,193 @@ func validateResourceDescription(rd kyverno.ResourceDescription) error { } return nil } + +func validateMutation(m kyverno.Mutation) (string, error) { + // JSON Patches + if len(m.Patches) != 0 { + for i, patch := range m.Patches { + if err := validatePatch(patch); err != nil { + return fmt.Sprintf("patch[%d]", i), err + } + } + } + // Overlay + if m.Overlay != nil { + path, err := validatePattern(m.Overlay, "/", []anchor.IsAnchor{anchor.IsConditionAnchor, anchor.IsAddingAnchor}) + if err != nil { + return path, err + } + } + return "", nil +} + +// Validate if all mandatory PolicyPatch fields are set +func validatePatch(pp kyverno.Patch) error { + if pp.Path == "" { + return errors.New("JSONPatch field 'path' is mandatory") + } + if pp.Operation == "add" || pp.Operation == "replace" { + if pp.Value == nil { + return fmt.Errorf("JSONPatch field 'value' is mandatory for operation '%s'", pp.Operation) + } + + return nil + } else if pp.Operation == "remove" { + return nil + } + + return fmt.Errorf("Unsupported JSONPatch operation '%s'", pp.Operation) +} + +func validateValidation(v kyverno.Validation) (string, error) { + if err := validateOverlayPattern(v); err != nil { + // no need to proceed ahead + return "", err + } + + if v.Pattern != nil { + if path, err := validatePattern(v.Pattern, "/", []anchor.IsAnchor{anchor.IsConditionAnchor, anchor.IsExistenceAnchor, anchor.IsEqualityAnchor, anchor.IsNegationAnchor}); err != nil { + return fmt.Sprintf("pattern.%s", path), err + } + } + + if len(v.AnyPattern) != 0 { + for i, pattern := range v.AnyPattern { + if path, err := validatePattern(pattern, "/", []anchor.IsAnchor{anchor.IsConditionAnchor, anchor.IsExistenceAnchor, anchor.IsEqualityAnchor, anchor.IsNegationAnchor}); err != nil { + return fmt.Sprintf("anyPattern[%d].%s", i, path), err + } + } + } + return "", nil +} + +// validateOverlayPattern checks one of pattern/anyPattern must exist +func validateOverlayPattern(v kyverno.Validation) error { + if v.Pattern == nil && len(v.AnyPattern) == 0 { + return fmt.Errorf("a pattern or anyPattern must be specified") + } + + if v.Pattern != nil && len(v.AnyPattern) != 0 { + return fmt.Errorf("only one operation allowed per validation rule(pattern or anyPattern)") + } + + return nil +} + +// Validate returns error if generator is configured incompletely +func validateGeneration(gen kyverno.Generation) (string, error) { + + if gen.Data == nil && gen.Clone == (kyverno.CloneFrom{}) { + return "", fmt.Errorf("clone or data are required") + } + if gen.Data != nil && gen.Clone != (kyverno.CloneFrom{}) { + return "", fmt.Errorf("only one operation allowed per generate rule(data or clone)") + } + // check kind is non empty + // check name is non empty + if gen.Name == "" { + return "name", fmt.Errorf("name cannot be empty") + } + if gen.Kind == "" { + return "kind", fmt.Errorf("kind cannot be empty") + } + if !reflect.DeepEqual(gen.Clone, kyverno.CloneFrom{}) { + if path, err := validateClone(gen.Clone); err != nil { + return fmt.Sprintf("clone.%s", path), err + } + } + if gen.Data != nil { + //TODO: is this required ?? as anchors can only be on pattern and not resource + // we can add this check by not sure if its needed here + if path, err := validatePattern(gen.Data, "/", []anchor.IsAnchor{}); err != nil { + return fmt.Sprintf("data.%s", path), fmt.Errorf("anchors not supported on generate resources: %v", err) + } + } + return "", nil +} + +func validateClone(c kyverno.CloneFrom) (string, error) { + if c.Name == "" { + return "name", fmt.Errorf("name cannot be empty") + } + if c.Namespace == "" { + return "namespace", fmt.Errorf("namespace cannot be empty") + } + return "", nil +} + +func validatePattern(patternElement interface{}, path string, supportedAnchors []anchor.IsAnchor) (string, error) { + switch typedPatternElement := patternElement.(type) { + case map[string]interface{}: + return validateMap(typedPatternElement, path, supportedAnchors) + case []interface{}: + return validateArray(typedPatternElement, path, supportedAnchors) + case string, float64, int, int64, bool, nil: + //TODO? check operator + return "", nil + default: + return path, fmt.Errorf("Validation rule failed at '%s', pattern contains unknown type", path) + } +} + +func validateMap(patternMap map[string]interface{}, path string, supportedAnchors []anchor.IsAnchor) (string, error) { + // check if anchors are defined + for key, value := range patternMap { + // if key is anchor + // check regex () -> this is anchor + // () + // single char () + re, err := regexp.Compile(`^.?\(.+\)$`) + if err != nil { + return path + "/" + key, fmt.Errorf("Unable to parse the field %s: %v", key, err) + } + + matched := re.MatchString(key) + // check the type of anchor + if matched { + // some type of anchor + // check if valid anchor + if !checkAnchors(key, supportedAnchors) { + return path + "/" + key, fmt.Errorf("Unsupported anchor %s", key) + } + + // addition check for existence anchor + // value must be of type list + if anchor.IsExistenceAnchor(key) { + typedValue, ok := value.([]interface{}) + if !ok { + return path + "/" + key, fmt.Errorf("Existence anchor should have value of type list") + } + // validate there is only one entry in the list + if len(typedValue) == 0 || len(typedValue) > 1 { + return path + "/" + key, fmt.Errorf("Existence anchor: single value expected, multiple specified") + } + } + } + // lets validate the values now :) + if errPath, err := validatePattern(value, path+"/"+key, supportedAnchors); err != nil { + return errPath, err + } + } + return "", nil +} + +func validateArray(patternArray []interface{}, path string, supportedAnchors []anchor.IsAnchor) (string, error) { + for i, patternElement := range patternArray { + currentPath := path + strconv.Itoa(i) + "/" + // lets validate the values now :) + if errPath, err := validatePattern(patternElement, currentPath, supportedAnchors); err != nil { + return errPath, err + } + } + return "", nil +} + +func checkAnchors(key string, supportedAnchors []anchor.IsAnchor) bool { + for _, f := range supportedAnchors { + if f(key) { + return true + } + } + return false +} diff --git a/pkg/policy/validate/validate.go b/pkg/policy/validate/validate.go deleted file mode 100644 index 3889f9f163..0000000000 --- a/pkg/policy/validate/validate.go +++ /dev/null @@ -1,61 +0,0 @@ -package validate - -import ( - "fmt" - - kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" - "github.com/nirmata/kyverno/pkg/engine/anchor" - "github.com/nirmata/kyverno/pkg/policy/common" -) - -// Validate provides implementation to validate 'validate' rule -type Validate struct { - // rule to hold 'validate' rule specifications - rule kyverno.Validation -} - -//NewValidateFactory returns a new instance of Mutate validation checker -func NewValidateFactory(rule kyverno.Validation) *Validate { - m := Validate{ - rule: rule, - } - return &m -} - -//Validate validates the 'validate' rule -func (v *Validate) Validate() (string, error) { - rule := v.rule - if err := v.validateOverlayPattern(); err != nil { - // no need to proceed ahead - return "", err - } - - if rule.Pattern != nil { - if path, err := common.ValidatePattern(rule.Pattern, "/", []anchor.IsAnchor{anchor.IsConditionAnchor, anchor.IsExistenceAnchor, anchor.IsEqualityAnchor, anchor.IsNegationAnchor}); err != nil { - return fmt.Sprintf("pattern.%s", path), err - } - } - - if len(rule.AnyPattern) != 0 { - for i, pattern := range rule.AnyPattern { - if path, err := common.ValidatePattern(pattern, "/", []anchor.IsAnchor{anchor.IsConditionAnchor, anchor.IsExistenceAnchor, anchor.IsEqualityAnchor, anchor.IsNegationAnchor}); err != nil { - return fmt.Sprintf("anyPattern[%d].%s", i, path), err - } - } - } - return "", nil -} - -// validateOverlayPattern checks one of pattern/anyPattern must exist -func (v *Validate) validateOverlayPattern() error { - rule := v.rule - if rule.Pattern == nil && len(rule.AnyPattern) == 0 { - return fmt.Errorf("a pattern or anyPattern must be specified") - } - - if rule.Pattern != nil && len(rule.AnyPattern) != 0 { - return fmt.Errorf("only one operation allowed per validation rule(pattern or anyPattern)") - } - - return nil -} diff --git a/pkg/policy/validate/validate_test.go b/pkg/policy/validate/validate_test.go deleted file mode 100644 index ee83204707..0000000000 --- a/pkg/policy/validate/validate_test.go +++ /dev/null @@ -1,381 +0,0 @@ -package validate - -import ( - "encoding/json" - "testing" - - kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" - "gotest.tools/assert" -) - -func Test_Validate_OverlayPattern_Empty(t *testing.T) { - rawValidation := []byte(` - {}`) - - var validation kyverno.Validation - err := json.Unmarshal(rawValidation, &validation) - assert.NilError(t, err) - - checker := NewValidateFactory(validation) - if _, err := checker.Validate(); err != nil { - assert.Assert(t, err != nil) - } -} -func Test_Validate_OverlayPattern_Nil_PatternAnypattern(t *testing.T) { - rawValidation := []byte(` - { "message": "Privileged mode is not allowed. Set allowPrivilegeEscalation and privileged to false" - } - `) - - var validation kyverno.Validation - err := json.Unmarshal(rawValidation, &validation) - assert.NilError(t, err) - checker := NewValidateFactory(validation) - if _, err := checker.Validate(); err != nil { - assert.Assert(t, err != nil) - } -} - -func Test_Validate_OverlayPattern_Exist_PatternAnypattern(t *testing.T) { - rawValidation := []byte(` - { - "message": "Privileged mode is not allowed. Set allowPrivilegeEscalation and privileged to false", - "anyPattern": [ - { - "spec": { - "securityContext": { - "allowPrivilegeEscalation": false, - "privileged": false - } - } - } - ], - "pattern": { - "spec": { - "containers": [ - { - "name": "*", - "securityContext": { - "allowPrivilegeEscalation": false, - "privileged": false - } - } - ] - } - } - }`) - - var validation kyverno.Validation - err := json.Unmarshal(rawValidation, &validation) - assert.NilError(t, err) - checker := NewValidateFactory(validation) - if _, err := checker.Validate(); err != nil { - assert.Assert(t, err != nil) - } -} -func Test_Validate_OverlayPattern_Valid(t *testing.T) { - rawValidation := []byte(` - { - "message": "Privileged mode is not allowed. Set allowPrivilegeEscalation and privileged to false", - "anyPattern": [ - { - "spec": { - "securityContext": { - "allowPrivilegeEscalation": false, - "privileged": false - } - } - }, - { - "spec": { - "containers": [ - { - "name": "*", - "securityContext": { - "allowPrivilegeEscalation": false, - "privileged": false - } - } - ] - } - } - ] - } -`) - - var validation kyverno.Validation - err := json.Unmarshal(rawValidation, &validation) - assert.NilError(t, err) - checker := NewValidateFactory(validation) - if _, err := checker.Validate(); err != nil { - assert.NilError(t, err) - } -} - -func Test_Validate_ExistingAnchor_AnchorOnMap(t *testing.T) { - rawValidation := []byte(` - { - "message": "validate container security contexts", - "anyPattern": [ - { - "spec": { - "template": { - "spec": { - "containers": [ - { - "^(securityContext)": { - "runAsNonRoot": true - } - } - ] - } - } - } - } - ] - } -`) - - var validation kyverno.Validation - err := json.Unmarshal(rawValidation, &validation) - assert.NilError(t, err) - checker := NewValidateFactory(validation) - if _, err := checker.Validate(); err != nil { - assert.Assert(t, err != nil) - } -} - -func Test_Validate_ExistingAnchor_AnchorOnString(t *testing.T) { - rawValidation := []byte(`{ - "message": "validate container security contexts", - "pattern": { - "spec": { - "template": { - "spec": { - "containers": [ - { - "securityContext": { - "allowPrivilegeEscalation": "^(false)" - } - } - ] - } - } - } - } - } - `) - - var validation kyverno.Validation - err := json.Unmarshal(rawValidation, &validation) - assert.NilError(t, err) - checker := NewValidateFactory(validation) - if _, err := checker.Validate(); err != nil { - assert.Assert(t, err != nil) - } -} - -func Test_Validate_ExistingAnchor_Valid(t *testing.T) { - var err error - var validation kyverno.Validation - rawValidation := []byte(` - { - "message": "validate container security contexts", - "anyPattern": [ - { - "spec": { - "template": { - "spec": { - "^(containers)": [ - { - "securityContext": { - "runAsNonRoot": "true" - } - } - ] - } - } - } - } - ] - }`) - - err = json.Unmarshal(rawValidation, &validation) - assert.NilError(t, err) - checker := NewValidateFactory(validation) - if _, err := checker.Validate(); err != nil { - assert.Assert(t, err != nil) - } - rawValidation = []byte(` - { - "message": "validate container security contexts", - "pattern": { - "spec": { - "template": { - "spec": { - "^(containers)": [ - { - "securityContext": { - "allowPrivilegeEscalation": "false" - } - } - ] - } - } - } - } - } `) - err = json.Unmarshal(rawValidation, &validation) - assert.NilError(t, err) - checker = NewValidateFactory(validation) - if _, err := checker.Validate(); err != nil { - assert.Assert(t, err != nil) - } - -} - -func Test_Validate_Validate_ValidAnchor(t *testing.T) { - var err error - var validate kyverno.Validation - var rawValidate []byte - // case 1 - rawValidate = []byte(` - { - "message": "Root user is not allowed. Set runAsNonRoot to true.", - "anyPattern": [ - { - "spec": { - "securityContext": { - "(runAsNonRoot)": true - } - } - }, - { - "spec": { - "^(containers)": [ - { - "name": "*", - "securityContext": { - "runAsNonRoot": true - } - } - ] - } - } - ] - }`) - - err = json.Unmarshal(rawValidate, &validate) - assert.NilError(t, err) - - checker := NewValidateFactory(validate) - if _, err := checker.Validate(); err != nil { - assert.NilError(t, err) - } - - // case 2 - validate = kyverno.Validation{} - rawValidate = []byte(` - { - "message": "Root user is not allowed. Set runAsNonRoot to true.", - "pattern": { - "spec": { - "=(securityContext)": { - "runAsNonRoot": "true" - } - } - } - }`) - - err = json.Unmarshal(rawValidate, &validate) - assert.NilError(t, err) - - checker = NewValidateFactory(validate) - if _, err := checker.Validate(); err != nil { - assert.NilError(t, err) - } -} - -func Test_Validate_Validate_Mismatched(t *testing.T) { - rawValidate := []byte(` - { - "message": "Root user is not allowed. Set runAsNonRoot to true.", - "pattern": { - "spec": { - "containers": [ - { - "name": "*", - "securityContext": { - "+(runAsNonRoot)": true - } - } - ] - } - } - }`) - - var validate kyverno.Validation - err := json.Unmarshal(rawValidate, &validate) - assert.NilError(t, err) - checker := NewValidateFactory(validate) - if _, err := checker.Validate(); err != nil { - assert.Assert(t, err != nil) - } -} - -func Test_Validate_Validate_Unsupported(t *testing.T) { - var err error - var validate kyverno.Validation - - // case 1 - rawValidate := []byte(` - { - "message": "Root user is not allowed. Set runAsNonRoot to true.", - "pattern": { - "spec": { - "containers": [ - { - "name": "*", - "securityContext": { - "!(runAsNonRoot)": true - } - } - ] - } - } - }`) - - err = json.Unmarshal(rawValidate, &validate) - assert.NilError(t, err) - checker := NewValidateFactory(validate) - if _, err := checker.Validate(); err != nil { - assert.Assert(t, err != nil) - } - - // case 2 - rawValidate = []byte(` - { - "message": "Root user is not allowed. Set runAsNonRoot to true.", - "pattern": { - "spec": { - "containers": [ - { - "name": "*", - "securityContext": { - "~(runAsNonRoot)": true - } - } - ] - } - } - }`) - - err = json.Unmarshal(rawValidate, &validate) - assert.NilError(t, err) - - checker = NewValidateFactory(validate) - if _, err := checker.Validate(); err != nil { - assert.Assert(t, err != nil) - } - -} diff --git a/pkg/policy/validate_test.go b/pkg/policy/validate_test.go index bd239995cc..9082e9322a 100644 --- a/pkg/policy/validate_test.go +++ b/pkg/policy/validate_test.go @@ -287,6 +287,369 @@ func Test_Validate_ResourceDescription_InvalidSelector(t *testing.T) { assert.Assert(t, err != nil) } +func Test_Validate_OverlayPattern_Empty(t *testing.T) { + rawValidation := []byte(` + {}`) + + var validation kyverno.Validation + err := json.Unmarshal(rawValidation, &validation) + assert.NilError(t, err) + + if _, err := validateValidation(validation); err != nil { + assert.Assert(t, err != nil) + } +} + +func Test_Validate_OverlayPattern_Nil_PatternAnypattern(t *testing.T) { + rawValidation := []byte(` + { "message": "Privileged mode is not allowed. Set allowPrivilegeEscalation and privileged to false" + } + `) + + var validation kyverno.Validation + err := json.Unmarshal(rawValidation, &validation) + assert.NilError(t, err) + if _, err := validateValidation(validation); err != nil { + assert.Assert(t, err != nil) + } +} + +func Test_Validate_OverlayPattern_Exist_PatternAnypattern(t *testing.T) { + rawValidation := []byte(` + { + "message": "Privileged mode is not allowed. Set allowPrivilegeEscalation and privileged to false", + "anyPattern": [ + { + "spec": { + "securityContext": { + "allowPrivilegeEscalation": false, + "privileged": false + } + } + } + ], + "pattern": { + "spec": { + "containers": [ + { + "name": "*", + "securityContext": { + "allowPrivilegeEscalation": false, + "privileged": false + } + } + ] + } + } + }`) + + var validation kyverno.Validation + err := json.Unmarshal(rawValidation, &validation) + assert.NilError(t, err) + if _, err := validateValidation(validation); err != nil { + assert.Assert(t, err != nil) + } +} + +func Test_Validate_OverlayPattern_Valid(t *testing.T) { + rawValidation := []byte(` + { + "message": "Privileged mode is not allowed. Set allowPrivilegeEscalation and privileged to false", + "anyPattern": [ + { + "spec": { + "securityContext": { + "allowPrivilegeEscalation": false, + "privileged": false + } + } + }, + { + "spec": { + "containers": [ + { + "name": "*", + "securityContext": { + "allowPrivilegeEscalation": false, + "privileged": false + } + } + ] + } + } + ] + } +`) + + var validation kyverno.Validation + err := json.Unmarshal(rawValidation, &validation) + assert.NilError(t, err) + if _, err := validateValidation(validation); err != nil { + assert.NilError(t, err) + } + +} + +func Test_Validate_ExistingAnchor_AnchorOnMap(t *testing.T) { + rawValidation := []byte(` + { + "message": "validate container security contexts", + "anyPattern": [ + { + "spec": { + "template": { + "spec": { + "containers": [ + { + "^(securityContext)": { + "runAsNonRoot": true + } + } + ] + } + } + } + } + ] + } +`) + + var validation kyverno.Validation + err := json.Unmarshal(rawValidation, &validation) + assert.NilError(t, err) + if _, err := validateValidation(validation); err != nil { + assert.Assert(t, err != nil) + } + +} + +func Test_Validate_ExistingAnchor_AnchorOnString(t *testing.T) { + rawValidation := []byte(`{ + "message": "validate container security contexts", + "pattern": { + "spec": { + "template": { + "spec": { + "containers": [ + { + "securityContext": { + "allowPrivilegeEscalation": "^(false)" + } + } + ] + } + } + } + } + } + `) + + var validation kyverno.Validation + err := json.Unmarshal(rawValidation, &validation) + assert.NilError(t, err) + if _, err := validateValidation(validation); err != nil { + assert.Assert(t, err != nil) + } +} + +func Test_Validate_ExistingAnchor_Valid(t *testing.T) { + var err error + var validation kyverno.Validation + rawValidation := []byte(` + { + "message": "validate container security contexts", + "anyPattern": [ + { + "spec": { + "template": { + "spec": { + "^(containers)": [ + { + "securityContext": { + "runAsNonRoot": "true" + } + } + ] + } + } + } + } + ] + }`) + + err = json.Unmarshal(rawValidation, &validation) + assert.NilError(t, err) + if _, err := validateValidation(validation); err != nil { + assert.Assert(t, err != nil) + } + rawValidation = []byte(` + { + "message": "validate container security contexts", + "pattern": { + "spec": { + "template": { + "spec": { + "^(containers)": [ + { + "securityContext": { + "allowPrivilegeEscalation": "false" + } + } + ] + } + } + } + } + } `) + err = json.Unmarshal(rawValidation, &validation) + assert.NilError(t, err) + if _, err := validateValidation(validation); err != nil { + assert.Assert(t, err != nil) + } + +} + +func Test_Validate_Validate_ValidAnchor(t *testing.T) { + var err error + var validate kyverno.Validation + var rawValidate []byte + // case 1 + rawValidate = []byte(` + { + "message": "Root user is not allowed. Set runAsNonRoot to true.", + "anyPattern": [ + { + "spec": { + "securityContext": { + "(runAsNonRoot)": true + } + } + }, + { + "spec": { + "^(containers)": [ + { + "name": "*", + "securityContext": { + "runAsNonRoot": true + } + } + ] + } + } + ] + }`) + + err = json.Unmarshal(rawValidate, &validate) + assert.NilError(t, err) + + if _, err := validateValidation(validate); err != nil { + assert.NilError(t, err) + } + + // case 2 + validate = kyverno.Validation{} + rawValidate = []byte(` + { + "message": "Root user is not allowed. Set runAsNonRoot to true.", + "pattern": { + "spec": { + "=(securityContext)": { + "runAsNonRoot": "true" + } + } + } + }`) + + err = json.Unmarshal(rawValidate, &validate) + assert.NilError(t, err) + + if _, err := validateValidation(validate); err != nil { + assert.NilError(t, err) + } +} + +func Test_Validate_Validate_Mismatched(t *testing.T) { + rawValidate := []byte(` + { + "message": "Root user is not allowed. Set runAsNonRoot to true.", + "pattern": { + "spec": { + "containers": [ + { + "name": "*", + "securityContext": { + "+(runAsNonRoot)": true + } + } + ] + } + } + }`) + + var validate kyverno.Validation + err := json.Unmarshal(rawValidate, &validate) + assert.NilError(t, err) + if _, err := validateValidation(validate); err != nil { + assert.Assert(t, err != nil) + } +} + +func Test_Validate_Validate_Unsupported(t *testing.T) { + var err error + var validate kyverno.Validation + + // case 1 + rawValidate := []byte(` + { + "message": "Root user is not allowed. Set runAsNonRoot to true.", + "pattern": { + "spec": { + "containers": [ + { + "name": "*", + "securityContext": { + "!(runAsNonRoot)": true + } + } + ] + } + } + }`) + + err = json.Unmarshal(rawValidate, &validate) + assert.NilError(t, err) + if _, err := validateValidation(validate); err != nil { + assert.Assert(t, err != nil) + } + + // case 2 + rawValidate = []byte(` + { + "message": "Root user is not allowed. Set runAsNonRoot to true.", + "pattern": { + "spec": { + "containers": [ + { + "name": "*", + "securityContext": { + "~(runAsNonRoot)": true + } + } + ] + } + } + }`) + + err = json.Unmarshal(rawValidate, &validate) + assert.NilError(t, err) + + if _, err := validateValidation(validate); err != nil { + assert.Assert(t, err != nil) + } + +} + func Test_Validate_Policy(t *testing.T) { rawPolicy := []byte(` { @@ -369,10 +732,225 @@ func Test_Validate_Policy(t *testing.T) { } }`) - err := Validate(rawPolicy, nil, true) + err := Validate(rawPolicy) assert.NilError(t, err) } +func Test_Validate_Mutate_ConditionAnchor(t *testing.T) { + rawMutate := []byte(` + { + "overlay": { + "spec": { + "(serviceAccountName)": "*", + "automountServiceAccountToken": false + } + } + }`) + + var mutate kyverno.Mutation + err := json.Unmarshal(rawMutate, &mutate) + assert.NilError(t, err) + if _, err := validateMutation(mutate); err != nil { + assert.NilError(t, err) + } +} + +func Test_Validate_Mutate_PlusAnchor(t *testing.T) { + rawMutate := []byte(` + { + "overlay": { + "spec": { + "+(serviceAccountName)": "*", + "automountServiceAccountToken": false + } + } + }`) + + var mutate kyverno.Mutation + err := json.Unmarshal(rawMutate, &mutate) + assert.NilError(t, err) + + if _, err := validateMutation(mutate); err != nil { + assert.NilError(t, err) + } +} + +func Test_Validate_Mutate_Mismatched(t *testing.T) { + rawMutate := []byte(` + { + "overlay": { + "spec": { + "^(serviceAccountName)": "*", + "automountServiceAccountToken": false + } + } + }`) + + var mutateExistence kyverno.Mutation + err := json.Unmarshal(rawMutate, &mutateExistence) + assert.NilError(t, err) + + if _, err := validateMutation(mutateExistence); err != nil { + assert.Assert(t, err != nil) + } + + var mutateEqual kyverno.Mutation + rawMutate = []byte(` + { + "overlay": { + "spec": { + "=(serviceAccountName)": "*", + "automountServiceAccountToken": false + } + } + }`) + + err = json.Unmarshal(rawMutate, &mutateEqual) + assert.NilError(t, err) + + if _, err := validateMutation(mutateEqual); err != nil { + assert.Assert(t, err != nil) + } + + var mutateNegation kyverno.Mutation + rawMutate = []byte(` + { + "overlay": { + "spec": { + "X(serviceAccountName)": "*", + "automountServiceAccountToken": false + } + } + }`) + + err = json.Unmarshal(rawMutate, &mutateNegation) + assert.NilError(t, err) + + if _, err := validateMutation(mutateEqual); err != nil { + assert.Assert(t, err != nil) + } +} + +func Test_Validate_Mutate_Unsupported(t *testing.T) { + var err error + var mutate kyverno.Mutation + // case 1 + rawMutate := []byte(` + { + "overlay": { + "spec": { + "!(serviceAccountName)": "*", + "automountServiceAccountToken": false + } + } + }`) + + err = json.Unmarshal(rawMutate, &mutate) + assert.NilError(t, err) + + if _, err := validateMutation(mutate); err != nil { + assert.Assert(t, err != nil) + } + + // case 2 + rawMutate = []byte(` + { + "overlay": { + "spec": { + "~(serviceAccountName)": "*", + "automountServiceAccountToken": false + } + } + }`) + + err = json.Unmarshal(rawMutate, &mutate) + assert.NilError(t, err) + + if _, err := validateMutation(mutate); err != nil { + assert.Assert(t, err != nil) + } +} + +func Test_Validate_Generate(t *testing.T) { + rawGenerate := []byte(` + { + "kind": "NetworkPolicy", + "name": "defaultnetworkpolicy", + "data": { + "spec": { + "podSelector": {}, + "policyTypes": [ + "Ingress", + "Egress" + ], + "ingress": [ + {} + ], + "egress": [ + {} + ] + } + } + }`) + + var generate kyverno.Generation + err := json.Unmarshal(rawGenerate, &generate) + assert.NilError(t, err) + + if _, err := validateGeneration(generate); err != nil { + assert.Assert(t, err != nil) + } +} + +func Test_Validate_Generate_HasAnchors(t *testing.T) { + var err error + var generate kyverno.Generation + rawGenerate := []byte(` + { + "kind": "NetworkPolicy", + "name": "defaultnetworkpolicy", + "data": { + "spec": { + "(podSelector)": {}, + "policyTypes": [ + "Ingress", + "Egress" + ], + "ingress": [ + {} + ], + "egress": [ + {} + ] + } + } + }`) + + err = json.Unmarshal(rawGenerate, &generate) + assert.NilError(t, err) + if _, err := validateGeneration(generate); err != nil { + assert.Assert(t, err != nil) + } + + rawGenerate = []byte(` + { + "kind": "ConfigMap", + "name": "copied-cm", + "clone": { + "^(namespace)": "default", + "name": "game" + } + }`) + + errNew := json.Unmarshal(rawGenerate, &generate) + assert.NilError(t, errNew) + err = json.Unmarshal(rawGenerate, &generate) + assert.NilError(t, err) + if _, err := validateGeneration(generate); err != nil { + assert.Assert(t, err != nil) + } +} + func Test_Validate_ErrorFormat(t *testing.T) { rawPolicy := []byte(` { @@ -511,7 +1089,7 @@ func Test_Validate_ErrorFormat(t *testing.T) { } `) - err := Validate(rawPolicy, nil, true) + err := Validate(rawPolicy) assert.Assert(t, err != nil) } diff --git a/pkg/policy/webhookregistration.go b/pkg/policy/webhookregistration.go index 5c8fc0aa69..f4b2188b2a 100644 --- a/pkg/policy/webhookregistration.go +++ b/pkg/policy/webhookregistration.go @@ -1,25 +1,25 @@ package policy import ( + "github.com/golang/glog" "k8s.io/apimachinery/pkg/labels" ) func (pc *PolicyController) removeResourceWebhookConfiguration() error { - logger := pc.log var err error // get all existing policies policies, err := pc.pLister.List(labels.NewSelector()) if err != nil { - logger.Error(err, "failed to list policies") + glog.V(4).Infof("failed to list policies: %v", err) return err } if len(policies) == 0 { - logger.V(4).Info("no policies loaded, removing resource webhook configuration if one exists") + glog.V(4).Info("no policies loaded, removing resource webhook configuration if one exists") return pc.resourceWebhookWatcher.RemoveResourceWebhookConfiguration() } - logger.V(4).Info("no policies with mutating or validating webhook configurations, remove resource webhook configuration if one exists") + glog.V(4).Info("no policies with mutating or validating webhook configurations, remove resource webhook configuration if one exists") return pc.resourceWebhookWatcher.RemoveResourceWebhookConfiguration() } diff --git a/pkg/policystatus/main.go b/pkg/policystatus/main.go index b21ff2e505..3e633aaf82 100644 --- a/pkg/policystatus/main.go +++ b/pkg/policystatus/main.go @@ -2,16 +2,16 @@ package policystatus import ( "encoding/json" - "fmt" "sync" "time" + "github.com/golang/glog" + "k8s.io/apimachinery/pkg/util/wait" "github.com/nirmata/kyverno/pkg/client/clientset/versioned" v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1" - log "sigs.k8s.io/controller-runtime/pkg/log" ) // Policy status implementation works in the following way, @@ -111,7 +111,8 @@ func (s *Sync) updateStatusCache(stopCh <-chan struct{}) { s.cache.keyToMutex.Get(statusUpdater.PolicyName()).Unlock() oldStatus, _ := json.Marshal(status) newStatus, _ := json.Marshal(updatedStatus) - log.Log.V(4).Info(fmt.Sprintf("\nupdated status of policy - %v\noldStatus:\n%v\nnewStatus:\n%v\n", statusUpdater.PolicyName(), string(oldStatus), string(newStatus))) + + glog.V(4).Infof("\nupdated status of policy - %v\noldStatus:\n%v\nnewStatus:\n%v\n", statusUpdater.PolicyName(), string(oldStatus), string(newStatus)) case <-stopCh: return } @@ -139,7 +140,7 @@ func (s *Sync) updatePolicyStatus() { s.cache.dataMu.Lock() delete(s.cache.data, policyName) s.cache.dataMu.Unlock() - log.Log.Error(err, "failed to update policy status") + glog.V(4).Info(err) } } } diff --git a/pkg/policystore/policystore.go b/pkg/policystore/policystore.go index 0ecfd5ea32..f8a8e30874 100644 --- a/pkg/policystore/policystore.go +++ b/pkg/policystore/policystore.go @@ -3,11 +3,12 @@ package policystore import ( "sync" - "github.com/go-logr/logr" + "k8s.io/apimachinery/pkg/labels" + + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" kyvernoinformer "github.com/nirmata/kyverno/pkg/client/informers/externalversions/kyverno/v1" kyvernolister "github.com/nirmata/kyverno/pkg/client/listers/kyverno/v1" - "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/tools/cache" ) @@ -23,7 +24,6 @@ type PolicyStore struct { pLister kyvernolister.ClusterPolicyLister // returns true if the cluster policy store has been synced at least once pSynched cache.InformerSynced - log logr.Logger } //UpdateInterface provides api to update policies @@ -40,29 +40,25 @@ type LookupInterface interface { } // NewPolicyStore returns a new policy store -func NewPolicyStore(pInformer kyvernoinformer.ClusterPolicyInformer, - log logr.Logger) *PolicyStore { +func NewPolicyStore(pInformer kyvernoinformer.ClusterPolicyInformer) *PolicyStore { ps := PolicyStore{ data: make(kindMap), pLister: pInformer.Lister(), pSynched: pInformer.Informer().HasSynced, - log: log, } return &ps } //Run checks syncing func (ps *PolicyStore) Run(stopCh <-chan struct{}) { - logger := ps.log if !cache.WaitForCacheSync(stopCh, ps.pSynched) { - logger.Info("failed to sync informer cache") + glog.Error("policy meta store: failed to sync informer cache") } } //Register a new policy func (ps *PolicyStore) Register(policy kyverno.ClusterPolicy) { - logger := ps.log - logger.V(4).Info("adding policy", "name", policy.Name) + glog.V(4).Infof("adding resources %s", policy.Name) ps.mu.Lock() defer ps.mu.Unlock() var pmap policyMap diff --git a/pkg/policyviolation/builder.go b/pkg/policyviolation/builder.go index da556697be..1de366eb66 100644 --- a/pkg/policyviolation/builder.go +++ b/pkg/policyviolation/builder.go @@ -3,23 +3,24 @@ package policyviolation import ( "fmt" - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine/response" ) //GeneratePVsFromEngineResponse generate Violations from engine responses -func GeneratePVsFromEngineResponse(ers []response.EngineResponse, log logr.Logger) (pvInfos []Info) { +func GeneratePVsFromEngineResponse(ers []response.EngineResponse) (pvInfos []Info) { for _, er := range ers { // ignore creation of PV for resources that are yet to be assigned a name if er.PolicyResponse.Resource.Name == "" { - log.V(4).Info("resource does no have a name assigned yet, not creating a policy violation", "resource", er.PolicyResponse.Resource) + glog.V(4).Infof("resource %v, has not been assigned a name, not creating a policy violation for it", er.PolicyResponse.Resource) continue } // skip when response succeed if er.IsSuccesful() { continue } + glog.V(4).Infof("Building policy violation for engine response %v", er) // build policy violation info pvInfos = append(pvInfos, buildPVInfo(er)) } diff --git a/pkg/policyviolation/builder_test.go b/pkg/policyviolation/builder_test.go index a44314f9f2..bd3f8c97f0 100644 --- a/pkg/policyviolation/builder_test.go +++ b/pkg/policyviolation/builder_test.go @@ -5,7 +5,6 @@ import ( "github.com/nirmata/kyverno/pkg/engine/response" "gotest.tools/assert" - "sigs.k8s.io/controller-runtime/pkg/log" ) func Test_GeneratePVsFromEngineResponse_PathNotExist(t *testing.T) { @@ -53,6 +52,6 @@ func Test_GeneratePVsFromEngineResponse_PathNotExist(t *testing.T) { }, } - pvInfos := GeneratePVsFromEngineResponse(ers, log.Log) + pvInfos := GeneratePVsFromEngineResponse(ers) assert.Assert(t, len(pvInfos) == 1) } diff --git a/pkg/policyviolation/clusterpv.go b/pkg/policyviolation/clusterpv.go index 4cb26ea216..c9336f8059 100644 --- a/pkg/policyviolation/clusterpv.go +++ b/pkg/policyviolation/clusterpv.go @@ -4,7 +4,7 @@ import ( "fmt" "reflect" - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" kyvernov1 "github.com/nirmata/kyverno/pkg/client/clientset/versioned/typed/kyverno/v1" kyvernolister "github.com/nirmata/kyverno/pkg/client/listers/kyverno/v1" @@ -21,13 +21,11 @@ type clusterPV struct { cpvLister kyvernolister.ClusterPolicyViolationLister // policy violation interface kyvernoInterface kyvernov1.KyvernoV1Interface - // logger - log logr.Logger // update policy stats with violationCount policyStatusListener policystatus.Listener } -func newClusterPV(log logr.Logger, dclient *client.Client, +func newClusterPV(dclient *client.Client, cpvLister kyvernolister.ClusterPolicyViolationLister, kyvernoInterface kyvernov1.KyvernoV1Interface, policyStatus policystatus.Listener, @@ -36,7 +34,6 @@ func newClusterPV(log logr.Logger, dclient *client.Client, dclient: dclient, cpvLister: cpvLister, kyvernoInterface: kyvernoInterface, - log: log, policyStatusListener: policyStatus, } return &cpv @@ -59,7 +56,6 @@ func (cpv *clusterPV) create(pv kyverno.PolicyViolationTemplate) error { } func (cpv *clusterPV) getExisting(newPv kyverno.ClusterPolicyViolation) (*kyverno.ClusterPolicyViolation, error) { - logger := cpv.log.WithValues("namespace", newPv.Namespace, "name", newPv.Name) var err error // use labels policyLabelmap := map[string]string{"policy": newPv.Spec.Policy, "resource": newPv.Spec.ResourceSpec.ToKey()} @@ -70,7 +66,7 @@ func (cpv *clusterPV) getExisting(newPv kyverno.ClusterPolicyViolation) (*kyvern pvs, err := cpv.cpvLister.List(ls) if err != nil { - logger.Error(err, "failed to list cluster policy violations") + glog.Errorf("unable to list cluster policy violations : %v", err) return nil, err } @@ -87,8 +83,7 @@ func (cpv *clusterPV) getExisting(newPv kyverno.ClusterPolicyViolation) (*kyvern func (cpv *clusterPV) createPV(newPv *kyverno.ClusterPolicyViolation) error { var err error - logger := cpv.log.WithValues("policy", newPv.Spec.Policy, "kind", newPv.Spec.ResourceSpec.Kind, "namespace", newPv.Spec.ResourceSpec.Namespace, "name", newPv.Spec.ResourceSpec.Name) - logger.V(4).Info("creating new policy violation") + glog.V(4).Infof("creating new policy violation for policy %s & resource %s/%s", newPv.Spec.Policy, newPv.Spec.ResourceSpec.Kind, newPv.Spec.ResourceSpec.Name) obj, err := retryGetResource(cpv.dclient, newPv.Spec.ResourceSpec) if err != nil { return fmt.Errorf("failed to retry getting resource for policy violation %s/%s: %v", newPv.Name, newPv.Spec.Policy, err) @@ -100,7 +95,7 @@ func (cpv *clusterPV) createPV(newPv *kyverno.ClusterPolicyViolation) error { // create resource _, err = cpv.kyvernoInterface.ClusterPolicyViolations().Create(newPv) if err != nil { - logger.Error(err, "failed to create cluster policy violation") + glog.V(4).Infof("failed to create Cluster Policy Violation: %v", err) return err } @@ -108,16 +103,15 @@ func (cpv *clusterPV) createPV(newPv *kyverno.ClusterPolicyViolation) error { cpv.policyStatusListener.Send(violationCount{policyName: newPv.Spec.Policy, violatedRules: newPv.Spec.ViolatedRules}) } - logger.Info("cluster policy violation created") + glog.Infof("policy violation created for resource %v", newPv.Spec.ResourceSpec) return nil } func (cpv *clusterPV) updatePV(newPv, oldPv *kyverno.ClusterPolicyViolation) error { - logger := cpv.log.WithValues("policy", newPv.Spec.Policy, "kind", newPv.Spec.ResourceSpec.Kind, "namespace", newPv.Spec.ResourceSpec.Namespace, "name", newPv.Spec.ResourceSpec.Name) var err error // check if there is any update if reflect.DeepEqual(newPv.Spec, oldPv.Spec) { - logger.V(4).Info("policy violation spec did not change, not upadating the resource") + glog.V(4).Infof("policy violation spec %v did not change so not updating it", newPv.Spec) return nil } // set name @@ -129,7 +123,7 @@ func (cpv *clusterPV) updatePV(newPv, oldPv *kyverno.ClusterPolicyViolation) err if err != nil { return fmt.Errorf("failed to update cluster policy violation: %v", err) } - logger.Info("cluster policy violation created") + glog.Infof("cluster policy violation updated for resource %v", newPv.Spec.ResourceSpec) if newPv.Annotations["fromSync"] != "true" { cpv.policyStatusListener.Send(violationCount{policyName: newPv.Spec.Policy, violatedRules: newPv.Spec.ViolatedRules}) diff --git a/pkg/policyviolation/common.go b/pkg/policyviolation/common.go index e2211edb13..6f077b25b8 100644 --- a/pkg/policyviolation/common.go +++ b/pkg/policyviolation/common.go @@ -5,13 +5,13 @@ import ( "time" backoff "github.com/cenkalti/backoff" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1" client "github.com/nirmata/kyverno/pkg/dclient" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/labels" - "sigs.k8s.io/controller-runtime/pkg/log" ) func createOwnerReference(resource *unstructured.Unstructured) metav1.OwnerReference { @@ -34,7 +34,7 @@ func retryGetResource(client *client.Client, rspec kyverno.ResourceSpec) (*unstr var err error getResource := func() error { obj, err = client.GetResource(rspec.Kind, rspec.Namespace, rspec.Name) - log.Log.V(4).Info(fmt.Sprintf("retry %v getting %s/%s/%s", i, rspec.Kind, rspec.Namespace, rspec.Name)) + glog.V(4).Infof("retry %v getting %s/%s/%s", i, rspec.Kind, rspec.Namespace, rspec.Name) i++ return err } diff --git a/pkg/policyviolation/generator.go b/pkg/policyviolation/generator.go index ed3ffe76a2..db5ca63fcd 100644 --- a/pkg/policyviolation/generator.go +++ b/pkg/policyviolation/generator.go @@ -8,7 +8,7 @@ import ( "sync" "time" - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned" kyvernov1 "github.com/nirmata/kyverno/pkg/client/clientset/versioned/typed/kyverno/v1" @@ -38,7 +38,6 @@ type Generator struct { // returns true if the cluster policy store has been synced at least once pvSynced cache.InformerSynced // returns true if the namespaced cluster policy store has been synced at at least once - log logr.Logger nspvSynced cache.InformerSynced queue workqueue.RateLimitingInterface dataStore *dataStore @@ -108,8 +107,7 @@ func NewPVGenerator(client *kyvernoclient.Clientset, dclient *dclient.Client, pvInformer kyvernoinformer.ClusterPolicyViolationInformer, nspvInformer kyvernoinformer.PolicyViolationInformer, - policyStatus policystatus.Listener, - log logr.Logger) *Generator { + policyStatus policystatus.Listener) *Generator { gen := Generator{ kyvernoInterface: client.KyvernoV1(), dclient: dclient, @@ -119,7 +117,6 @@ func NewPVGenerator(client *kyvernoclient.Clientset, nspvSynced: nspvInformer.Informer().HasSynced, queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), workQueueName), dataStore: newDataStore(), - log: log, policyStatusListener: policyStatus, } return &gen @@ -138,18 +135,18 @@ func (gen *Generator) enqueue(info Info) { func (gen *Generator) Add(infos ...Info) { for _, info := range infos { gen.enqueue(info) + glog.V(3).Infof("Added policy violation: %s", info.toKey()) } } // Run starts the workers func (gen *Generator) Run(workers int, stopCh <-chan struct{}) { - logger := gen.log defer utilruntime.HandleCrash() - logger.Info("start") - defer logger.Info("shutting down") + glog.Info("Start policy violation generator") + defer glog.Info("Shutting down policy violation generator") if !cache.WaitForCacheSync(stopCh, gen.pvSynced, gen.nspvSynced) { - logger.Info("failed to sync informer cache") + glog.Error("policy violation generator: failed to sync informer cache") } for i := 0; i < workers; i++ { @@ -164,7 +161,6 @@ func (gen *Generator) runWorker() { } func (gen *Generator) handleErr(err error, key interface{}) { - logger := gen.log if err == nil { gen.queue.Forget(key) return @@ -172,22 +168,23 @@ func (gen *Generator) handleErr(err error, key interface{}) { // retires requests if there is error if gen.queue.NumRequeues(key) < workQueueRetryLimit { - logger.Error(err, "failed to sync policy violation", "key", key) + glog.V(4).Infof("Error syncing policy violation %v: %v", key, err) // Re-enqueue the key rate limited. Based on the rate limiter on the // queue and the re-enqueue history, the key will be processed later again. gen.queue.AddRateLimited(key) return } gen.queue.Forget(key) + glog.Error(err) // remove from data store if keyHash, ok := key.(string); ok { gen.dataStore.delete(keyHash) } - logger.Error(err, "dropping key out of the queue", "key", key) + + glog.Warningf("Dropping the key out of the queue: %v", err) } func (gen *Generator) processNextWorkitem() bool { - logger := gen.log obj, shutdown := gen.queue.Get() if shutdown { return false @@ -199,7 +196,7 @@ func (gen *Generator) processNextWorkitem() bool { var ok bool if keyHash, ok = obj.(string); !ok { gen.queue.Forget(obj) - logger.Info("incorrect type; expecting type 'string'", "obj", obj) + glog.Warningf("Expecting type string but got %v\n", obj) return nil } // lookup data store @@ -207,7 +204,7 @@ func (gen *Generator) processNextWorkitem() bool { if reflect.DeepEqual(info, Info{}) { // empty key gen.queue.Forget(obj) - logger.Info("empty key") + glog.Warningf("Got empty key %v\n", obj) return nil } err := gen.syncHandler(info) @@ -215,22 +212,22 @@ func (gen *Generator) processNextWorkitem() bool { return nil }(obj) if err != nil { - logger.Error(err, "failed to process item") + glog.Error(err) return true } return true } func (gen *Generator) syncHandler(info Info) error { - logger := gen.log + glog.V(4).Infof("received info:%v", info) var handler pvGenerator builder := newPvBuilder() if info.Resource.GetNamespace() == "" { // cluster scope resource generate a clusterpolicy violation - handler = newClusterPV(gen.log.WithName("ClusterPV"), gen.dclient, gen.cpvLister, gen.kyvernoInterface, gen.policyStatusListener) + handler = newClusterPV(gen.dclient, gen.cpvLister, gen.kyvernoInterface, gen.policyStatusListener) } else { // namespaced resources generated a namespaced policy violation in the namespace of the resource - handler = newNamespacedPV(gen.log.WithName("NamespacedPV"), gen.dclient, gen.nspvLister, gen.kyvernoInterface, gen.policyStatusListener) + handler = newNamespacedPV(gen.dclient, gen.nspvLister, gen.kyvernoInterface, gen.policyStatusListener) } failure := false @@ -243,12 +240,12 @@ func (gen *Generator) syncHandler(info Info) error { } // Create Policy Violations - logger.V(4).Info("creating policy violation", "key", info.toKey()) + glog.V(3).Infof("Creating policy violation: %s", info.toKey()) if err := handler.create(pv); err != nil { failure = true - logger.Error(err, "failed to create policy violation") + glog.V(3).Infof("Failed to create policy violation: %v", err) } else { - logger.Info("created policy violation", "key", info.toKey()) + glog.V(3).Infof("Policy violation created: %s", info.toKey()) } if failure { diff --git a/pkg/policyviolation/namespacedpv.go b/pkg/policyviolation/namespacedpv.go index 3b0202c6df..ff32748d0b 100644 --- a/pkg/policyviolation/namespacedpv.go +++ b/pkg/policyviolation/namespacedpv.go @@ -4,7 +4,7 @@ import ( "fmt" "reflect" - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" kyvernov1 "github.com/nirmata/kyverno/pkg/client/clientset/versioned/typed/kyverno/v1" kyvernolister "github.com/nirmata/kyverno/pkg/client/listers/kyverno/v1" @@ -21,13 +21,11 @@ type namespacedPV struct { nspvLister kyvernolister.PolicyViolationLister // policy violation interface kyvernoInterface kyvernov1.KyvernoV1Interface - // logger - log logr.Logger // update policy status with violationCount policyStatusListener policystatus.Listener } -func newNamespacedPV(log logr.Logger, dclient *client.Client, +func newNamespacedPV(dclient *client.Client, nspvLister kyvernolister.PolicyViolationLister, kyvernoInterface kyvernov1.KyvernoV1Interface, policyStatus policystatus.Listener, @@ -36,7 +34,6 @@ func newNamespacedPV(log logr.Logger, dclient *client.Client, dclient: dclient, nspvLister: nspvLister, kyvernoInterface: kyvernoInterface, - log: log, policyStatusListener: policyStatus, } return &nspv @@ -59,7 +56,6 @@ func (nspv *namespacedPV) create(pv kyverno.PolicyViolationTemplate) error { } func (nspv *namespacedPV) getExisting(newPv kyverno.PolicyViolation) (*kyverno.PolicyViolation, error) { - logger := nspv.log.WithValues("namespace", newPv.Namespace, "name", newPv.Name) var err error // use labels policyLabelmap := map[string]string{"policy": newPv.Spec.Policy, "resource": newPv.Spec.ResourceSpec.ToKey()} @@ -69,7 +65,7 @@ func (nspv *namespacedPV) getExisting(newPv kyverno.PolicyViolation) (*kyverno.P } pvs, err := nspv.nspvLister.PolicyViolations(newPv.GetNamespace()).List(ls) if err != nil { - logger.Error(err, "failed to list namespaced policy violations") + glog.Errorf("unable to list namespaced policy violations : %v", err) return nil, err } @@ -86,8 +82,7 @@ func (nspv *namespacedPV) getExisting(newPv kyverno.PolicyViolation) (*kyverno.P func (nspv *namespacedPV) createPV(newPv *kyverno.PolicyViolation) error { var err error - logger := nspv.log.WithValues("policy", newPv.Spec.Policy, "kind", newPv.Spec.ResourceSpec.Kind, "namespace", newPv.Spec.ResourceSpec.Namespace, "name", newPv.Spec.ResourceSpec.Name) - logger.V(4).Info("creating new policy violation") + glog.V(4).Infof("creating new policy violation for policy %s & resource %s/%s/%s", newPv.Spec.Policy, newPv.Spec.ResourceSpec.Kind, newPv.Spec.ResourceSpec.Namespace, newPv.Spec.ResourceSpec.Name) obj, err := retryGetResource(nspv.dclient, newPv.Spec.ResourceSpec) if err != nil { return fmt.Errorf("failed to retry getting resource for policy violation %s/%s: %v", newPv.Name, newPv.Spec.Policy, err) @@ -99,23 +94,22 @@ func (nspv *namespacedPV) createPV(newPv *kyverno.PolicyViolation) error { // create resource _, err = nspv.kyvernoInterface.PolicyViolations(newPv.GetNamespace()).Create(newPv) if err != nil { - logger.Error(err, "failed to create namespaced policy violation") + glog.V(4).Infof("failed to create Cluster Policy Violation: %v", err) return err } if newPv.Annotations["fromSync"] != "true" { nspv.policyStatusListener.Send(violationCount{policyName: newPv.Spec.Policy, violatedRules: newPv.Spec.ViolatedRules}) } - logger.Info("namespaced policy violation created") + glog.Infof("policy violation created for resource %v", newPv.Spec.ResourceSpec) return nil } func (nspv *namespacedPV) updatePV(newPv, oldPv *kyverno.PolicyViolation) error { - logger := nspv.log.WithValues("policy", newPv.Spec.Policy, "kind", newPv.Spec.ResourceSpec.Kind, "namespace", newPv.Spec.ResourceSpec.Namespace, "name", newPv.Spec.ResourceSpec.Name) var err error // check if there is any update if reflect.DeepEqual(newPv.Spec, oldPv.Spec) { - logger.V(4).Info("policy violation spec did not change, not upadating the resource") + glog.V(4).Infof("policy violation spec %v did not change so not updating it", newPv.Spec) return nil } // set name @@ -130,6 +124,6 @@ func (nspv *namespacedPV) updatePV(newPv, oldPv *kyverno.PolicyViolation) error if newPv.Annotations["fromSync"] != "true" { nspv.policyStatusListener.Send(violationCount{policyName: newPv.Spec.Policy, violatedRules: newPv.Spec.ViolatedRules}) } - logger.Info("namespaced policy violation created") + glog.Infof("namespaced policy violation updated for resource %v", newPv.Spec.ResourceSpec) return nil } diff --git a/pkg/testrunner/scenario.go b/pkg/testrunner/scenario.go index 6ca1ed583a..39eaeb7257 100644 --- a/pkg/testrunner/scenario.go +++ b/pkg/testrunner/scenario.go @@ -3,6 +3,7 @@ package testrunner import ( "bytes" "encoding/json" + "flag" "io/ioutil" "os" ospath "path" @@ -18,6 +19,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes/scheme" + "github.com/golang/glog" "gopkg.in/yaml.v2" apiyaml "k8s.io/apimachinery/pkg/util/yaml" ) @@ -306,7 +308,7 @@ func loadPolicyResource(t *testing.T, file string) *unstructured.Unstructured { func getClient(t *testing.T, files []string) *client.Client { var objects []runtime.Object if files != nil { - + glog.V(4).Infof("loading resources: %v", files) for _, file := range files { objects = loadObjects(t, file) } @@ -402,7 +404,7 @@ func loadPolicy(t *testing.T, path string) *kyverno.ClusterPolicy { policy := kyverno.ClusterPolicy{} pBytes, err := apiyaml.ToJSON(p) if err != nil { - t.Error(err) + glog.Error(err) continue } @@ -425,8 +427,7 @@ func loadPolicy(t *testing.T, path string) *kyverno.ClusterPolicy { } func testScenario(t *testing.T, path string) { - - // flag.Set("logtostderr", "true") + flag.Set("logtostderr", "true") // flag.Set("v", "8") scenario, err := loadScenario(t, path) diff --git a/pkg/testrunner/utils.go b/pkg/testrunner/utils.go index 6fdfb91c78..d888cdcdc6 100644 --- a/pkg/testrunner/utils.go +++ b/pkg/testrunner/utils.go @@ -4,8 +4,8 @@ import ( "io/ioutil" "os" + "github.com/golang/glog" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sigs.k8s.io/controller-runtime/pkg/log" ) const ( @@ -42,7 +42,7 @@ func ConvertToUnstructured(data []byte) (*unstructured.Unstructured, error) { resource := &unstructured.Unstructured{} err := resource.UnmarshalJSON(data) if err != nil { - log.Log.Error(err, "failed to unmarshal resource") + glog.V(4).Infof("failed to unmarshall resource: %v", err) return nil, err } return resource, nil diff --git a/pkg/tls/tls.go b/pkg/tls/tls.go index 4acc08272d..c91c9b922c 100644 --- a/pkg/tls/tls.go +++ b/pkg/tls/tls.go @@ -142,6 +142,5 @@ func IsTLSPairShouldBeUpdated(tlsPair *TlsPemPair) bool { return true } - // TODO : should use time.Until instead of t.Sub(time.Now()) (gosimple) return expirationDate.Sub(time.Now()) < timeReserveBeforeCertificateExpiration } diff --git a/pkg/userinfo/roleRef.go b/pkg/userinfo/roleRef.go index d813f07f4e..ac089bc041 100644 --- a/pkg/userinfo/roleRef.go +++ b/pkg/userinfo/roleRef.go @@ -4,12 +4,12 @@ import ( "fmt" "strings" + "github.com/golang/glog" v1beta1 "k8s.io/api/admission/v1beta1" authenticationv1 "k8s.io/api/authentication/v1" rbacv1 "k8s.io/api/rbac/v1" labels "k8s.io/apimachinery/pkg/labels" rbaclister "k8s.io/client-go/listers/rbac/v1" - "sigs.k8s.io/controller-runtime/pkg/log" ) const ( @@ -101,7 +101,7 @@ func matchSubjectsMap(subject rbacv1.Subject, userInfo authenticationv1.UserInfo func matchServiceAccount(subject rbacv1.Subject, userInfo authenticationv1.UserInfo) bool { subjectServiceAccount := subject.Namespace + ":" + subject.Name if userInfo.Username[len(SaPrefix):] != subjectServiceAccount { - log.Log.V(3).Info(fmt.Sprintf("service account not match, expect %s, got %s", subjectServiceAccount, userInfo.Username[len(SaPrefix):])) + glog.V(3).Infof("service account not match, expect %s, got %s", subjectServiceAccount, userInfo.Username[len(SaPrefix):]) return false } @@ -117,6 +117,6 @@ func matchUserOrGroup(subject rbacv1.Subject, userInfo authenticationv1.UserInfo } } - log.Log.V(3).Info(fmt.Sprintf("user/group '%v' info not found in request userInfo: %v", subject.Name, keys)) + glog.V(3).Infof("user/group '%v' info not found in request userInfo: %v", subject.Name, keys) return false } diff --git a/pkg/userinfo/roleRef_test.go b/pkg/userinfo/roleRef_test.go index 003bbe2cd6..3929c38577 100644 --- a/pkg/userinfo/roleRef_test.go +++ b/pkg/userinfo/roleRef_test.go @@ -1,6 +1,7 @@ package userinfo import ( + "flag" "reflect" "testing" @@ -152,10 +153,9 @@ func newRoleBinding(name, ns string, subjects []rbacv1.Subject, roles rbacv1.Rol } func Test_getRoleRefByRoleBindings(t *testing.T) { - - // flag.Parse() - // flag.Set("logtostderr", "true") - // flag.Set("v", "3") + flag.Parse() + flag.Set("logtostderr", "true") + flag.Set("v", "3") list := make([]*rbacv1.RoleBinding, 2) diff --git a/pkg/utils/util.go b/pkg/utils/util.go index 5fe0602e71..c6c41f4be0 100644 --- a/pkg/utils/util.go +++ b/pkg/utils/util.go @@ -3,7 +3,8 @@ package utils import ( "reflect" - "github.com/go-logr/logr" + "github.com/golang/glog" + "github.com/minio/minio/pkg/wildcard" client "github.com/nirmata/kyverno/pkg/dclient" dclient "github.com/nirmata/kyverno/pkg/dclient" @@ -58,15 +59,14 @@ func Btoi(b bool) int { } //CRDInstalled to check if the CRD is installed or not -func CRDInstalled(discovery client.IDiscovery, log logr.Logger) bool { - logger := log.WithName("CRDInstalled") +func CRDInstalled(discovery client.IDiscovery) bool { check := func(kind string) bool { gvr := discovery.GetGVRFromKind(kind) if reflect.DeepEqual(gvr, (schema.GroupVersionResource{})) { - logger.Info("CRD not installed", "kind", kind) + glog.Errorf("%s CRD not installed", kind) return false } - logger.Info("CRD found", "kind", kind) + glog.Infof("CRD %s found ", kind) return true } if !check("ClusterPolicy") || !check("ClusterPolicyViolation") || !check("PolicyViolation") { @@ -77,12 +77,11 @@ func CRDInstalled(discovery client.IDiscovery, log logr.Logger) bool { //CleanupOldCrd deletes any existing NamespacedPolicyViolation resources in cluster // If resource violates policy, new Violations will be generated -func CleanupOldCrd(client *dclient.Client, log logr.Logger) { - logger := log.WithName("CleanupOldCrd") +func CleanupOldCrd(client *dclient.Client) { gvr := client.DiscoveryClient.GetGVRFromKind("NamespacedPolicyViolation") if !reflect.DeepEqual(gvr, (schema.GroupVersionResource{})) { if err := client.DeleteResource("CustomResourceDefinition", "", "namespacedpolicyviolations.kyverno.io", false); err != nil { - logger.Error(err, "Failed to remove prevous CRD", "kind", "namespacedpolicyviolation") + glog.Infof("Failed to remove previous CRD namespacedpolicyviolations: %v", err) } } } diff --git a/pkg/version/version.go b/pkg/version/version.go index 8d9303d204..ef768a35bf 100644 --- a/pkg/version/version.go +++ b/pkg/version/version.go @@ -1,7 +1,7 @@ package version import ( - "github.com/go-logr/logr" + "github.com/golang/glog" ) // These fields are set during an official build @@ -13,8 +13,8 @@ var ( ) //PrintVersionInfo displays the kyverno version - git version -func PrintVersionInfo(log logr.Logger) { - log.Info("Kyverno", "Version", BuildVersion) - log.Info("Kyverno", "BuildHash", BuildHash) - log.Info("Kyverno", "BuildTime", BuildTime) +func PrintVersionInfo() { + glog.Infof("Kyverno version: %s\n", BuildVersion) + glog.Infof("Kyverno BuildHash: %s\n", BuildHash) + glog.Infof("Kyverno BuildTime: %s\n", BuildTime) } diff --git a/pkg/webhookconfig/checker.go b/pkg/webhookconfig/checker.go index db1e765629..ee85f36c35 100644 --- a/pkg/webhookconfig/checker.go +++ b/pkg/webhookconfig/checker.go @@ -4,6 +4,7 @@ import ( "fmt" "sync" + "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/config" admregapi "k8s.io/api/admissionregistration/v1beta1" errorsapi "k8s.io/apimachinery/pkg/api/errors" @@ -18,8 +19,8 @@ func (wrc *WebhookRegistrationClient) constructVerifyMutatingWebhookConfig(caDat wrc.constructOwner(), }, }, - Webhooks: []admregapi.MutatingWebhook{ - generateMutatingWebhook( + Webhooks: []admregapi.Webhook{ + generateWebhook( config.VerifyMutatingWebhookName, config.VerifyMutatingWebhookServicePath, caData, @@ -35,15 +36,14 @@ func (wrc *WebhookRegistrationClient) constructVerifyMutatingWebhookConfig(caDat } func (wrc *WebhookRegistrationClient) constructDebugVerifyMutatingWebhookConfig(caData []byte) *admregapi.MutatingWebhookConfiguration { - logger := wrc.log url := fmt.Sprintf("https://%s%s", wrc.serverIP, config.VerifyMutatingWebhookServicePath) - logger.V(4).Info("Debug VerifyMutatingWebhookConfig is registered with url", "url", url) + glog.V(4).Infof("Debug VerifyMutatingWebhookConfig is registered with url %s\n", url) return &admregapi.MutatingWebhookConfiguration{ ObjectMeta: v1.ObjectMeta{ Name: config.VerifyMutatingWebhookConfigurationDebugName, }, - Webhooks: []admregapi.MutatingWebhook{ - generateDebugMutatingWebhook( + Webhooks: []admregapi.Webhook{ + generateDebugWebhook( config.VerifyMutatingWebhookName, url, caData, @@ -68,14 +68,13 @@ func (wrc *WebhookRegistrationClient) removeVerifyWebhookMutatingWebhookConfig(w } else { mutatingConfig = config.VerifyMutatingWebhookConfigurationName } - logger := wrc.log.WithValues("name", mutatingConfig) - logger.V(4).Info("removing webhook configuration") + glog.V(4).Infof("removing webhook configuration %s", mutatingConfig) err = wrc.client.DeleteResource(MutatingWebhookConfigurationKind, "", mutatingConfig, false) if errorsapi.IsNotFound(err) { - logger.Error(err, "verify webhook configuration, does not exits. not deleting") + glog.V(4).Infof("verify webhook configuration %s, does not exits. not deleting", mutatingConfig) } else if err != nil { - logger.Error(err, "failed to delete verify wwebhook configuration") + glog.Errorf("failed to delete verify webhook configuration %s: %v", mutatingConfig, err) } else { - logger.V(4).Info("successfully deleted verify webhook configuration") + glog.V(4).Infof("successfully deleted verify webhook configuration %s", mutatingConfig) } } diff --git a/pkg/webhookconfig/common.go b/pkg/webhookconfig/common.go index 2b1c17f6e0..d73fcafb13 100644 --- a/pkg/webhookconfig/common.go +++ b/pkg/webhookconfig/common.go @@ -3,6 +3,7 @@ package webhookconfig import ( "io/ioutil" + "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/config" admregapi "k8s.io/api/admissionregistration/v1beta1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -10,21 +11,20 @@ import ( ) func (wrc *WebhookRegistrationClient) readCaData() []byte { - logger := wrc.log var caData []byte // Check if ca is defined in the secret tls-ca // assume the key and signed cert have been defined in secret tls.kyverno if caData = wrc.client.ReadRootCASecret(); len(caData) != 0 { - logger.V(4).Info("read CA from secret") + glog.V(4).Infof("read CA from secret") return caData } - logger.V(4).Info("failed to read CA from secret, reading from kubeconfig") + glog.V(4).Infof("failed to read CA from secret, reading from kubeconfig") // load the CA from kubeconfig if caData = extractCA(wrc.clientConfig); len(caData) != 0 { - logger.V(4).Info("read CA from kubeconfig") + glog.V(4).Infof("read CA from kubeconfig") return caData } - logger.V(4).Info("failed to read CA from kubeconfig") + glog.V(4).Infof("failed to read CA from kubeconfig") return nil } @@ -46,11 +46,10 @@ func extractCA(config *rest.Config) (result []byte) { } func (wrc *WebhookRegistrationClient) constructOwner() v1.OwnerReference { - logger := wrc.log kubePolicyDeployment, err := wrc.client.GetKubePolicyDeployment() if err != nil { - logger.Error(err, "failed to construct OwnerReference") + glog.Errorf("Error when constructing OwnerReference, err: %v\n", err) return v1.OwnerReference{} } @@ -62,11 +61,10 @@ func (wrc *WebhookRegistrationClient) constructOwner() v1.OwnerReference { } } -// debug mutating webhook -func generateDebugMutatingWebhook(name, url string, caData []byte, validate bool, timeoutSeconds int32, resource, apiGroups, apiVersions string, operationTypes []admregapi.OperationType) admregapi.MutatingWebhook { +func generateDebugWebhook(name, url string, caData []byte, validate bool, timeoutSeconds int32, resource, apiGroups, apiVersions string, operationTypes []admregapi.OperationType) admregapi.Webhook { sideEffect := admregapi.SideEffectClassNoneOnDryRun failurePolicy := admregapi.Ignore - return admregapi.MutatingWebhook{ + return admregapi.Webhook{ Name: name, ClientConfig: admregapi.WebhookClientConfig{ URL: &url, @@ -95,116 +93,10 @@ func generateDebugMutatingWebhook(name, url string, caData []byte, validate bool } } -func generateDebugValidatingWebhook(name, url string, caData []byte, validate bool, timeoutSeconds int32, resource, apiGroups, apiVersions string, operationTypes []admregapi.OperationType) admregapi.ValidatingWebhook { +func generateWebhook(name, servicePath string, caData []byte, validation bool, timeoutSeconds int32, resource, apiGroups, apiVersions string, operationTypes []admregapi.OperationType) admregapi.Webhook { sideEffect := admregapi.SideEffectClassNoneOnDryRun failurePolicy := admregapi.Ignore - return admregapi.ValidatingWebhook{ - Name: name, - ClientConfig: admregapi.WebhookClientConfig{ - URL: &url, - CABundle: caData, - }, - SideEffects: &sideEffect, - Rules: []admregapi.RuleWithOperations{ - admregapi.RuleWithOperations{ - Operations: operationTypes, - Rule: admregapi.Rule{ - APIGroups: []string{ - apiGroups, - }, - APIVersions: []string{ - apiVersions, - }, - Resources: []string{ - resource, - }, - }, - }, - }, - AdmissionReviewVersions: []string{"v1beta1"}, - TimeoutSeconds: &timeoutSeconds, - FailurePolicy: &failurePolicy, - } -} - -// func generateWebhook(name, servicePath string, caData []byte, validation bool, timeoutSeconds int32, resource, apiGroups, apiVersions string, operationTypes []admregapi.OperationType) admregapi.Webhook { -// sideEffect := admregapi.SideEffectClassNoneOnDryRun -// failurePolicy := admregapi.Ignore -// return admregapi.Webhook{ -// Name: name, -// ClientConfig: admregapi.WebhookClientConfig{ -// Service: &admregapi.ServiceReference{ -// Namespace: config.KubePolicyNamespace, -// Name: config.WebhookServiceName, -// Path: &servicePath, -// }, -// CABundle: caData, -// }, -// SideEffects: &sideEffect, -// Rules: []admregapi.RuleWithOperations{ -// admregapi.RuleWithOperations{ -// Operations: operationTypes, -// Rule: admregapi.Rule{ -// APIGroups: []string{ -// apiGroups, -// }, -// APIVersions: []string{ -// apiVersions, -// }, -// Resources: []string{ -// resource, -// }, -// }, -// }, -// }, -// AdmissionReviewVersions: []string{"v1beta1"}, -// TimeoutSeconds: &timeoutSeconds, -// FailurePolicy: &failurePolicy, -// } -// } - -// mutating webhook -func generateMutatingWebhook(name, servicePath string, caData []byte, validation bool, timeoutSeconds int32, resource, apiGroups, apiVersions string, operationTypes []admregapi.OperationType) admregapi.MutatingWebhook { - sideEffect := admregapi.SideEffectClassNoneOnDryRun - failurePolicy := admregapi.Ignore - return admregapi.MutatingWebhook{ - Name: name, - ClientConfig: admregapi.WebhookClientConfig{ - Service: &admregapi.ServiceReference{ - Namespace: config.KubePolicyNamespace, - Name: config.WebhookServiceName, - Path: &servicePath, - }, - CABundle: caData, - }, - SideEffects: &sideEffect, - Rules: []admregapi.RuleWithOperations{ - admregapi.RuleWithOperations{ - Operations: operationTypes, - Rule: admregapi.Rule{ - APIGroups: []string{ - apiGroups, - }, - APIVersions: []string{ - apiVersions, - }, - Resources: []string{ - resource, - }, - }, - }, - }, - AdmissionReviewVersions: []string{"v1beta1"}, - TimeoutSeconds: &timeoutSeconds, - FailurePolicy: &failurePolicy, - } -} - -// validating webhook -func generateValidatingWebhook(name, servicePath string, caData []byte, validation bool, timeoutSeconds int32, resource, apiGroups, apiVersions string, operationTypes []admregapi.OperationType) admregapi.ValidatingWebhook { - sideEffect := admregapi.SideEffectClassNoneOnDryRun - failurePolicy := admregapi.Ignore - return admregapi.ValidatingWebhook{ + return admregapi.Webhook{ Name: name, ClientConfig: admregapi.WebhookClientConfig{ Service: &admregapi.ServiceReference{ diff --git a/pkg/webhookconfig/policy.go b/pkg/webhookconfig/policy.go index da9fa0fa8a..d1798a54e5 100644 --- a/pkg/webhookconfig/policy.go +++ b/pkg/webhookconfig/policy.go @@ -3,6 +3,7 @@ package webhookconfig import ( "fmt" + "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/config" admregapi "k8s.io/api/admissionregistration/v1beta1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -17,8 +18,8 @@ func (wrc *WebhookRegistrationClient) contructPolicyValidatingWebhookConfig(caDa wrc.constructOwner(), }, }, - Webhooks: []admregapi.ValidatingWebhook{ - generateValidatingWebhook( + Webhooks: []admregapi.Webhook{ + generateWebhook( config.PolicyValidatingWebhookName, config.PolicyValidatingWebhookServicePath, caData, @@ -34,16 +35,15 @@ func (wrc *WebhookRegistrationClient) contructPolicyValidatingWebhookConfig(caDa } func (wrc *WebhookRegistrationClient) contructDebugPolicyValidatingWebhookConfig(caData []byte) *admregapi.ValidatingWebhookConfiguration { - logger := wrc.log url := fmt.Sprintf("https://%s%s", wrc.serverIP, config.PolicyValidatingWebhookServicePath) - logger.V(4).Info("Debug PolicyValidatingWebhookConfig is registered with url ", "url", url) + glog.V(4).Infof("Debug PolicyValidatingWebhookConfig is registered with url %s\n", url) return &admregapi.ValidatingWebhookConfiguration{ ObjectMeta: v1.ObjectMeta{ Name: config.PolicyValidatingWebhookConfigurationDebugName, }, - Webhooks: []admregapi.ValidatingWebhook{ - generateDebugValidatingWebhook( + Webhooks: []admregapi.Webhook{ + generateDebugWebhook( config.PolicyValidatingWebhookName, url, caData, @@ -66,8 +66,8 @@ func (wrc *WebhookRegistrationClient) contructPolicyMutatingWebhookConfig(caData wrc.constructOwner(), }, }, - Webhooks: []admregapi.MutatingWebhook{ - generateMutatingWebhook( + Webhooks: []admregapi.Webhook{ + generateWebhook( config.PolicyMutatingWebhookName, config.PolicyMutatingWebhookServicePath, caData, @@ -82,16 +82,15 @@ func (wrc *WebhookRegistrationClient) contructPolicyMutatingWebhookConfig(caData } } func (wrc *WebhookRegistrationClient) contructDebugPolicyMutatingWebhookConfig(caData []byte) *admregapi.MutatingWebhookConfiguration { - logger := wrc.log url := fmt.Sprintf("https://%s%s", wrc.serverIP, config.PolicyMutatingWebhookServicePath) - logger.V(4).Info("Debug PolicyMutatingWebhookConfig is registered with url ", "url", url) + glog.V(4).Infof("Debug PolicyMutatingWebhookConfig is registered with url %s\n", url) return &admregapi.MutatingWebhookConfiguration{ ObjectMeta: v1.ObjectMeta{ Name: config.PolicyMutatingWebhookConfigurationDebugName, }, - Webhooks: []admregapi.MutatingWebhook{ - generateDebugMutatingWebhook( + Webhooks: []admregapi.Webhook{ + generateDebugWebhook( config.PolicyMutatingWebhookName, url, caData, diff --git a/pkg/webhookconfig/registration.go b/pkg/webhookconfig/registration.go index 8124ad39d4..8db0cba73c 100644 --- a/pkg/webhookconfig/registration.go +++ b/pkg/webhookconfig/registration.go @@ -2,11 +2,10 @@ package webhookconfig import ( "errors" - "fmt" "sync" "time" - "github.com/go-logr/logr" + "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/config" client "github.com/nirmata/kyverno/pkg/dclient" admregapi "k8s.io/api/admissionregistration/v1beta1" @@ -28,7 +27,6 @@ type WebhookRegistrationClient struct { // serverIP should be used if running Kyverno out of clutser serverIP string timeoutSeconds int32 - log logr.Logger } // NewWebhookRegistrationClient creates new WebhookRegistrationClient instance @@ -36,22 +34,19 @@ func NewWebhookRegistrationClient( clientConfig *rest.Config, client *client.Client, serverIP string, - webhookTimeout int32, - log logr.Logger) *WebhookRegistrationClient { + webhookTimeout int32) *WebhookRegistrationClient { return &WebhookRegistrationClient{ clientConfig: clientConfig, client: client, serverIP: serverIP, timeoutSeconds: webhookTimeout, - log: log.WithName("WebhookRegistrationClient"), } } // Register creates admission webhooks configs on cluster func (wrc *WebhookRegistrationClient) Register() error { - logger := wrc.log.WithName("Register") if wrc.serverIP != "" { - logger.Info("Registering webhook", "url", fmt.Sprintf("https://%s", wrc.serverIP)) + glog.Infof("Registering webhook with url https://%s\n", wrc.serverIP) } // For the case if cluster already has this configs @@ -93,7 +88,6 @@ func (wrc *WebhookRegistrationClient) RemoveWebhookConfigurations(cleanUp chan<- // used to forward request to kyverno webhooks to apply policeis // Mutationg webhook is be used for Mutating purpose func (wrc *WebhookRegistrationClient) CreateResourceMutatingWebhookConfiguration() error { - logger := wrc.log var caData []byte var config *admregapi.MutatingWebhookConfiguration @@ -114,17 +108,16 @@ func (wrc *WebhookRegistrationClient) CreateResourceMutatingWebhookConfiguration } _, err := wrc.client.CreateResource(MutatingWebhookConfigurationKind, "", *config, false) if errorsapi.IsAlreadyExists(err) { - logger.V(4).Info("resource mutating webhook configuration already exists. not creating one", "name", config.Name) + glog.V(4).Infof("resource mutating webhook configuration %s, already exists. not creating one", config.Name) return nil } if err != nil { - logger.Error(err, "failed to create resource mutating webhook configuration", "name", config.Name) + glog.V(4).Infof("failed to create resource mutating webhook configuration %s: %v", config.Name, err) return err } return nil } -//CreateResourceValidatingWebhookConfiguration ... func (wrc *WebhookRegistrationClient) CreateResourceValidatingWebhookConfiguration() error { var caData []byte var config *admregapi.ValidatingWebhookConfiguration @@ -141,15 +134,14 @@ func (wrc *WebhookRegistrationClient) CreateResourceValidatingWebhookConfigurati // clientConfig - service config = wrc.constructValidatingWebhookConfig(caData) } - logger := wrc.log.WithValues("kind", ValidatingWebhookConfigurationKind, "name", config.Name) _, err := wrc.client.CreateResource(ValidatingWebhookConfigurationKind, "", *config, false) if errorsapi.IsAlreadyExists(err) { - logger.V(4).Info("resource already exists. not create one") + glog.V(4).Infof("resource validating webhook configuration %s, already exists. not creating one", config.Name) return nil } if err != nil { - logger.Error(err, "failed to create resource") + glog.V(4).Infof("failed to create resource validating webhook configuration %s: %v", config.Name, err) return err } return nil @@ -176,19 +168,20 @@ func (wrc *WebhookRegistrationClient) createPolicyValidatingWebhookConfiguration // clientConfig - service config = wrc.contructPolicyValidatingWebhookConfig(caData) } - logger := wrc.log.WithValues("kind", ValidatingWebhookConfigurationKind, "name", config.Name) // create validating webhook configuration resource if _, err := wrc.client.CreateResource(ValidatingWebhookConfigurationKind, "", *config, false); err != nil { return err } - logger.V(4).Info("created resource") + + glog.V(4).Infof("created Validating Webhook Configuration %s ", config.Name) return nil } func (wrc *WebhookRegistrationClient) createPolicyMutatingWebhookConfiguration() error { var caData []byte var config *admregapi.MutatingWebhookConfiguration + // read CA data from // 1) secret(config) // 2) kubeconfig @@ -210,7 +203,8 @@ func (wrc *WebhookRegistrationClient) createPolicyMutatingWebhookConfiguration() if _, err := wrc.client.CreateResource(MutatingWebhookConfigurationKind, "", *config, false); err != nil { return err } - wrc.log.V(4).Info("reated Mutating Webhook Configuration", "name", config.Name) + + glog.V(4).Infof("created Mutating Webhook Configuration %s ", config.Name) return nil } @@ -240,7 +234,7 @@ func (wrc *WebhookRegistrationClient) createVerifyMutatingWebhookConfiguration() return err } - wrc.log.V(4).Info("reated Mutating Webhook Configuration", "name", config.Name) + glog.V(4).Infof("created Mutating Webhook Configuration %s ", config.Name) return nil } @@ -249,9 +243,9 @@ func (wrc *WebhookRegistrationClient) createVerifyMutatingWebhookConfiguration() // Register will fail if the config exists, so there is no need to fail on error func (wrc *WebhookRegistrationClient) removeWebhookConfigurations() { startTime := time.Now() - wrc.log.Info("Started cleaning up webhookconfigurations") + glog.V(4).Infof("Started cleaning up webhookconfigurations") defer func() { - wrc.log.V(4).Info("Finished cleaning up webhookcongfigurations", "processingTime", time.Since(startTime)) + glog.V(4).Infof("Finished cleaning up webhookcongfigurations (%v)", time.Since(startTime)) }() var wg sync.WaitGroup @@ -275,13 +269,13 @@ func (wrc *WebhookRegistrationClient) removeWebhookConfigurations() { func (wrc *WebhookRegistrationClient) removeResourceMutatingWebhookConfiguration(wg *sync.WaitGroup) { defer wg.Done() if err := wrc.RemoveResourceMutatingWebhookConfiguration(); err != nil { - wrc.log.Error(err, "failed to remove resource mutating webhook configuration") + glog.Error(err) } } func (wrc *WebhookRegistrationClient) removeResourceValidatingWebhookConfiguration(wg *sync.WaitGroup) { defer wg.Done() if err := wrc.RemoveResourceValidatingWebhookConfiguration(); err != nil { - wrc.log.Error(err, "failed to remove resource validation webhook configuration") + glog.Error(err) } } @@ -296,15 +290,15 @@ func (wrc *WebhookRegistrationClient) removePolicyMutatingWebhookConfiguration(w } else { mutatingConfig = config.PolicyMutatingWebhookConfigurationName } - logger := wrc.log.WithValues("name", mutatingConfig) - logger.V(4).Info("removing mutating webhook configuration") + + glog.V(4).Infof("removing webhook configuration %s", mutatingConfig) err := wrc.client.DeleteResource(MutatingWebhookConfigurationKind, "", mutatingConfig, false) if errorsapi.IsNotFound(err) { - logger.Error(err, "policy mutating webhook configuration does not exist, not deleting") + glog.V(4).Infof("policy webhook configuration %s, does not exits. not deleting", mutatingConfig) } else if err != nil { - logger.Error(err, "failed to delete policy mutating webhook configuration") + glog.Errorf("failed to delete policy webhook configuration %s: %v", mutatingConfig, err) } else { - logger.V(4).Info("successfully deleted policy mutating webhook configutation") + glog.V(4).Infof("successfully deleted policy webhook configuration %s", mutatingConfig) } } @@ -319,14 +313,13 @@ func (wrc *WebhookRegistrationClient) removePolicyValidatingWebhookConfiguration } else { validatingConfig = config.PolicyValidatingWebhookConfigurationName } - logger := wrc.log.WithValues("name", validatingConfig) - logger.V(4).Info("removing validating webhook configuration") + glog.V(4).Infof("removing webhook configuration %s", validatingConfig) err := wrc.client.DeleteResource(ValidatingWebhookConfigurationKind, "", validatingConfig, false) if errorsapi.IsNotFound(err) { - logger.Error(err, "policy validating webhook configuration does not exist, not deleting") + glog.V(4).Infof("policy webhook configuration %s, does not exits. not deleting", validatingConfig) } else if err != nil { - logger.Error(err, "failed to delete policy validating webhook configuration") + glog.Errorf("failed to delete policy webhook configuration %s: %v", validatingConfig, err) } else { - logger.V(4).Info("successfully deleted policy validating webhook configutation") + glog.V(4).Infof("successfully deleted policy webhook configuration %s", validatingConfig) } } diff --git a/pkg/webhookconfig/resource.go b/pkg/webhookconfig/resource.go index 050517da0a..090c33636a 100644 --- a/pkg/webhookconfig/resource.go +++ b/pkg/webhookconfig/resource.go @@ -3,6 +3,7 @@ package webhookconfig import ( "fmt" + "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/config" admregapi "k8s.io/api/admissionregistration/v1beta1" "k8s.io/apimachinery/pkg/api/errors" @@ -10,15 +11,15 @@ import ( ) func (wrc *WebhookRegistrationClient) constructDebugMutatingWebhookConfig(caData []byte) *admregapi.MutatingWebhookConfiguration { - logger := wrc.log url := fmt.Sprintf("https://%s%s", wrc.serverIP, config.MutatingWebhookServicePath) - logger.V(4).Info("Debug MutatingWebhookConfig registed", "url", url) + glog.V(4).Infof("Debug MutatingWebhookConfig is registered with url %s\n", url) + return &admregapi.MutatingWebhookConfiguration{ ObjectMeta: v1.ObjectMeta{ Name: config.MutatingWebhookConfigurationDebugName, }, - Webhooks: []admregapi.MutatingWebhook{ - generateDebugMutatingWebhook( + Webhooks: []admregapi.Webhook{ + generateDebugWebhook( config.MutatingWebhookName, url, caData, @@ -41,8 +42,8 @@ func (wrc *WebhookRegistrationClient) constructMutatingWebhookConfig(caData []by wrc.constructOwner(), }, }, - Webhooks: []admregapi.MutatingWebhook{ - generateMutatingWebhook( + Webhooks: []admregapi.Webhook{ + generateWebhook( config.MutatingWebhookName, config.MutatingWebhookServicePath, caData, @@ -67,31 +68,32 @@ func (wrc *WebhookRegistrationClient) GetResourceMutatingWebhookConfigName() str //RemoveResourceMutatingWebhookConfiguration removes mutating webhook configuration for all resources func (wrc *WebhookRegistrationClient) RemoveResourceMutatingWebhookConfiguration() error { + configName := wrc.GetResourceMutatingWebhookConfigName() - logger := wrc.log.WithValues("kind", MutatingWebhookConfigurationKind, "name", configName) // delete webhook configuration err := wrc.client.DeleteResource(MutatingWebhookConfigurationKind, "", configName, false) if errors.IsNotFound(err) { - logger.Error(err, "resource does not exit") + glog.V(4).Infof("resource webhook configuration %s does not exits, so not deleting", configName) return nil } if err != nil { - logger.V(4).Info("failed to delete resource") + glog.V(4).Infof("failed to delete resource webhook configuration %s: %v", configName, err) return err } - logger.V(4).Info("deleted resource") + glog.V(4).Infof("deleted resource webhook configuration %s", configName) return nil } func (wrc *WebhookRegistrationClient) constructDebugValidatingWebhookConfig(caData []byte) *admregapi.ValidatingWebhookConfiguration { url := fmt.Sprintf("https://%s%s", wrc.serverIP, config.ValidatingWebhookServicePath) + glog.V(4).Infof("Debug ValidatingWebhookConfig is registered with url %s\n", url) return &admregapi.ValidatingWebhookConfiguration{ ObjectMeta: v1.ObjectMeta{ Name: config.ValidatingWebhookConfigurationDebugName, }, - Webhooks: []admregapi.ValidatingWebhook{ - generateDebugValidatingWebhook( + Webhooks: []admregapi.Webhook{ + generateDebugWebhook( config.ValidatingWebhookName, url, caData, @@ -114,8 +116,8 @@ func (wrc *WebhookRegistrationClient) constructValidatingWebhookConfig(caData [] wrc.constructOwner(), }, }, - Webhooks: []admregapi.ValidatingWebhook{ - generateValidatingWebhook( + Webhooks: []admregapi.Webhook{ + generateWebhook( config.ValidatingWebhookName, config.ValidatingWebhookServicePath, caData, @@ -139,16 +141,15 @@ func (wrc *WebhookRegistrationClient) GetResourceValidatingWebhookConfigName() s func (wrc *WebhookRegistrationClient) RemoveResourceValidatingWebhookConfiguration() error { configName := wrc.GetResourceValidatingWebhookConfigName() - logger := wrc.log.WithValues("kind", ValidatingWebhookConfigurationKind, "name", configName) err := wrc.client.DeleteResource(ValidatingWebhookConfigurationKind, "", configName, false) if errors.IsNotFound(err) { - logger.Error(err, "resource does not exist; deleted already") + glog.V(4).Infof("resource webhook configuration %s does not exits, so not deleting", configName) return nil } if err != nil { - logger.Error(err, "failed to delete the resource") + glog.V(4).Infof("failed to delete resource webhook configuration %s: %v", configName, err) return err } - logger.Info("resource deleted") + glog.V(4).Infof("deleted resource webhook configuration %s", configName) return nil } diff --git a/pkg/webhookconfig/rwebhookregister.go b/pkg/webhookconfig/rwebhookregister.go index a312e07277..aacdc72b9f 100644 --- a/pkg/webhookconfig/rwebhookregister.go +++ b/pkg/webhookconfig/rwebhookregister.go @@ -3,7 +3,7 @@ package webhookconfig import ( "time" - "github.com/go-logr/logr" + "github.com/golang/glog" checker "github.com/nirmata/kyverno/pkg/checker" "github.com/tevino/abool" mconfiginformer "k8s.io/client-go/informers/admissionregistration/v1beta1" @@ -23,7 +23,6 @@ type ResourceWebhookRegister struct { vWebhookConfigLister mconfiglister.ValidatingWebhookConfigurationLister webhookRegistrationClient *WebhookRegistrationClient RunValidationInMutatingWebhook string - log logr.Logger } // NewResourceWebhookRegister returns a new instance of ResourceWebhookRegister manager @@ -33,7 +32,6 @@ func NewResourceWebhookRegister( vconfigwebhookinformer mconfiginformer.ValidatingWebhookConfigurationInformer, webhookRegistrationClient *WebhookRegistrationClient, runValidationInMutatingWebhook string, - log logr.Logger, ) *ResourceWebhookRegister { return &ResourceWebhookRegister{ pendingCreation: abool.New(), @@ -44,54 +42,52 @@ func NewResourceWebhookRegister( vWebhookConfigLister: vconfigwebhookinformer.Lister(), webhookRegistrationClient: webhookRegistrationClient, RunValidationInMutatingWebhook: runValidationInMutatingWebhook, - log: log, } } //RegisterResourceWebhook registers a resource webhook func (rww *ResourceWebhookRegister) RegisterResourceWebhook() { - logger := rww.log // drop the request if creation is in processing if rww.pendingCreation.IsSet() { - logger.V(3).Info("resource webhook configuration is in pending creation, skip the request") + glog.V(3).Info("resource webhook configuration is in pending creation, skip the request") return } timeDiff := time.Since(rww.LastReqTime.Time()) if timeDiff < checker.DefaultDeadline { - logger.V(3).Info("verified webhook status, creating webhook configuration") + glog.V(3).Info("Verified webhook status, creating webhook configuration") go func() { mutatingConfigName := rww.webhookRegistrationClient.GetResourceMutatingWebhookConfigName() mutatingConfig, _ := rww.mWebhookConfigLister.Get(mutatingConfigName) if mutatingConfig != nil { - logger.V(4).Info("mutating webhoook configuration already exists") + glog.V(4).Info("mutating webhoook configuration already exists") } else { rww.pendingCreation.Set() err1 := rww.webhookRegistrationClient.CreateResourceMutatingWebhookConfiguration() rww.pendingCreation.UnSet() if err1 != nil { - logger.Error(err1, "failed to create resource mutating webhook configuration, re-queue creation request") + glog.Errorf("failed to create resource mutating webhook configuration: %v, re-queue creation request", err1) rww.RegisterResourceWebhook() return } - logger.V(3).Info("successfully created mutating webhook configuration for resources") + glog.V(3).Info("Successfully created mutating webhook configuration for resources") } if rww.RunValidationInMutatingWebhook != "true" { validatingConfigName := rww.webhookRegistrationClient.GetResourceValidatingWebhookConfigName() validatingConfig, _ := rww.vWebhookConfigLister.Get(validatingConfigName) if validatingConfig != nil { - logger.V(4).Info("validating webhoook configuration already exists") + glog.V(4).Info("validating webhoook configuration already exists") } else { rww.pendingCreation.Set() err2 := rww.webhookRegistrationClient.CreateResourceValidatingWebhookConfiguration() rww.pendingCreation.UnSet() if err2 != nil { - logger.Error(err2, "failed to create resource validating webhook configuration; re-queue creation request") + glog.Errorf("failed to create resource validating webhook configuration: %v, re-queue creation request", err2) rww.RegisterResourceWebhook() return } - logger.V(3).Info("successfully created validating webhook configuration for resources") + glog.V(3).Info("Successfully created validating webhook configuration for resources") } } }() @@ -100,20 +96,19 @@ func (rww *ResourceWebhookRegister) RegisterResourceWebhook() { //Run starts the ResourceWebhookRegister manager func (rww *ResourceWebhookRegister) Run(stopCh <-chan struct{}) { - logger := rww.log // wait for cache to populate first time if !cache.WaitForCacheSync(stopCh, rww.mwebhookconfigSynced, rww.vwebhookconfigSynced) { - logger.Info("configuration: failed to sync webhook informer cache") + glog.Error("configuration: failed to sync webhook informer cache") } + } // RemoveResourceWebhookConfiguration removes the resource webhook configurations func (rww *ResourceWebhookRegister) RemoveResourceWebhookConfiguration() error { - logger := rww.log mutatingConfigName := rww.webhookRegistrationClient.GetResourceMutatingWebhookConfigName() mutatingConfig, err := rww.mWebhookConfigLister.Get(mutatingConfigName) if err != nil { - logger.Error(err, "failed to list mutating webhook config") + glog.V(4).Infof("failed to list mutating webhook config: %v", err) return err } if mutatingConfig != nil { @@ -121,14 +116,14 @@ func (rww *ResourceWebhookRegister) RemoveResourceWebhookConfiguration() error { if err != nil { return err } - logger.V(3).Info("emoved mutating resource webhook configuration") + glog.V(3).Info("removed mutating resource webhook configuration") } if rww.RunValidationInMutatingWebhook != "true" { validatingConfigName := rww.webhookRegistrationClient.GetResourceValidatingWebhookConfigName() validatingConfig, err := rww.vWebhookConfigLister.Get(validatingConfigName) if err != nil { - logger.Error(err, "failed to list validating webhook config") + glog.V(4).Infof("failed to list validating webhook config: %v", err) return err } if validatingConfig != nil { @@ -136,7 +131,7 @@ func (rww *ResourceWebhookRegister) RemoveResourceWebhookConfiguration() error { if err != nil { return err } - logger.V(3).Info("removed validating resource webhook configuration") + glog.V(3).Info("removed validating resource webhook configuration") } } return nil diff --git a/pkg/webhooks/admission_test.go b/pkg/webhooks/admission_test.go new file mode 100644 index 0000000000..d753352a72 --- /dev/null +++ b/pkg/webhooks/admission_test.go @@ -0,0 +1 @@ +package webhooks_test diff --git a/pkg/webhooks/annotations.go b/pkg/webhooks/annotations.go index eddded1cde..34d3e10468 100644 --- a/pkg/webhooks/annotations.go +++ b/pkg/webhooks/annotations.go @@ -7,7 +7,7 @@ import ( yamlv2 "gopkg.in/yaml.v2" jsonpatch "github.com/evanphx/json-patch" - "github.com/go-logr/logr" + "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/engine" "github.com/nirmata/kyverno/pkg/engine/response" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" @@ -38,7 +38,7 @@ var operationToPastTense = map[string]string{ "test": "tested", } -func generateAnnotationPatches(engineResponses []response.EngineResponse, log logr.Logger) []byte { +func generateAnnotationPatches(engineResponses []response.EngineResponse) []byte { var annotations map[string]string for _, er := range engineResponses { @@ -53,7 +53,7 @@ func generateAnnotationPatches(engineResponses []response.EngineResponse, log lo } var patchResponse annresponse - value := annotationFromEngineResponses(engineResponses, log) + value := annotationFromEngineResponses(engineResponses) if value == nil { // no patches or error while processing patches return nil @@ -90,21 +90,21 @@ func generateAnnotationPatches(engineResponses []response.EngineResponse, log lo // check the patch _, err := jsonpatch.DecodePatch([]byte("[" + string(patchByte) + "]")) if err != nil { - log.Error(err, "failed o build JSON patch for annotation", "patch", string(patchByte)) + glog.Errorf("Failed to make patch from annotation'%s', err: %v\n ", string(patchByte), err) } return patchByte } -func annotationFromEngineResponses(engineResponses []response.EngineResponse, log logr.Logger) []byte { +func annotationFromEngineResponses(engineResponses []response.EngineResponse) []byte { var annotationContent = make(map[string]string) for _, engineResponse := range engineResponses { if !engineResponse.IsSuccesful() { - log.V(3).Info("skip building annotation; policy failed to apply", "policy", engineResponse.PolicyResponse.Policy) + glog.V(3).Infof("Policy %s failed, skip preparing annotation\n", engineResponse.PolicyResponse.Policy) continue } - rulePatches := annotationFromPolicyResponse(engineResponse.PolicyResponse, log) + rulePatches := annotationFromPolicyResponse(engineResponse.PolicyResponse) if rulePatches == nil { continue } @@ -126,13 +126,13 @@ func annotationFromEngineResponses(engineResponses []response.EngineResponse, lo return result } -func annotationFromPolicyResponse(policyResponse response.PolicyResponse, log logr.Logger) []rulePatch { +func annotationFromPolicyResponse(policyResponse response.PolicyResponse) []rulePatch { var rulePatches []rulePatch for _, ruleInfo := range policyResponse.Rules { for _, patch := range ruleInfo.Patches { var patchmap map[string]interface{} if err := json.Unmarshal(patch, &patchmap); err != nil { - log.Error(err, "Failed to parse JSON patch bytes") + glog.Errorf("Failed to parse patch bytes, err: %v\n", err) continue } @@ -142,12 +142,14 @@ func annotationFromPolicyResponse(policyResponse response.PolicyResponse, log lo Path: patchmap["path"].(string)} rulePatches = append(rulePatches, rp) - log.V(4).Info("annotation value prepared", "patches", rulePatches) + glog.V(4).Infof("Annotation value prepared: %v\n", rulePatches) } } + if len(rulePatches) == 0 { return nil } + return rulePatches } diff --git a/pkg/webhooks/annotations_test.go b/pkg/webhooks/annotations_test.go index d14657b6cb..320e347ea3 100644 --- a/pkg/webhooks/annotations_test.go +++ b/pkg/webhooks/annotations_test.go @@ -6,7 +6,6 @@ import ( "github.com/nirmata/kyverno/pkg/engine/response" "gotest.tools/assert" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sigs.k8s.io/controller-runtime/pkg/log" ) func newPolicyResponse(policy, rule string, patchesStr []string, success bool) response.PolicyResponse { @@ -43,7 +42,7 @@ func Test_empty_annotation(t *testing.T) { patchStr := `{ "op": "replace", "path": "/spec/containers/0/imagePullPolicy", "value": "IfNotPresent" }` engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", []string{patchStr}, true, nil) - annPatches := generateAnnotationPatches([]response.EngineResponse{engineResponse}, log.Log) + annPatches := generateAnnotationPatches([]response.EngineResponse{engineResponse}) expectedPatches := `{"op":"add","path":"/metadata/annotations","value":{"policies.kyverno.io/patches":"default-imagepullpolicy.mutate-container.kyverno.io: replaced /spec/containers/0/imagePullPolicy\n"}}` assert.Assert(t, string(annPatches) == expectedPatches) } @@ -55,7 +54,7 @@ func Test_exist_annotation(t *testing.T) { patchStr := `{ "op": "replace", "path": "/spec/containers/0/imagePullPolicy", "value": "IfNotPresent" }` engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", []string{patchStr}, true, annotation) - annPatches := generateAnnotationPatches([]response.EngineResponse{engineResponse}, log.Log) + annPatches := generateAnnotationPatches([]response.EngineResponse{engineResponse}) expectedPatches := `{"op":"add","path":"/metadata/annotations","value":{"policies.kyverno.io/patches":"default-imagepullpolicy.mutate-container.kyverno.io: replaced /spec/containers/0/imagePullPolicy\n"}}` assert.Assert(t, string(annPatches) == expectedPatches) @@ -68,7 +67,7 @@ func Test_exist_kyverno_annotation(t *testing.T) { patchStr := `{ "op": "replace", "path": "/spec/containers/0/imagePullPolicy", "value": "IfNotPresent" }` engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", []string{patchStr}, true, annotation) - annPatches := generateAnnotationPatches([]response.EngineResponse{engineResponse}, log.Log) + annPatches := generateAnnotationPatches([]response.EngineResponse{engineResponse}) expectedPatches := `{"op":"add","path":"/metadata/annotations","value":{"policies.kyverno.io/patches":"default-imagepullpolicy.mutate-container.kyverno.io: replaced /spec/containers/0/imagePullPolicy\n"}}` assert.Assert(t, string(annPatches) == expectedPatches) @@ -80,11 +79,11 @@ func Test_annotation_nil_patch(t *testing.T) { } engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", nil, true, annotation) - annPatches := generateAnnotationPatches([]response.EngineResponse{engineResponse}, log.Log) + annPatches := generateAnnotationPatches([]response.EngineResponse{engineResponse}) assert.Assert(t, annPatches == nil) engineResponseNew := newEngineResponse("mutate-container", "default-imagepullpolicy", []string{""}, true, annotation) - annPatchesNew := generateAnnotationPatches([]response.EngineResponse{engineResponseNew}, log.Log) + annPatchesNew := generateAnnotationPatches([]response.EngineResponse{engineResponseNew}) assert.Assert(t, annPatchesNew == nil) } @@ -94,7 +93,7 @@ func Test_annotation_failed_Patch(t *testing.T) { } engineResponse := newEngineResponse("mutate-container", "default-imagepullpolicy", nil, false, annotation) - annPatches := generateAnnotationPatches([]response.EngineResponse{engineResponse}, log.Log) + annPatches := generateAnnotationPatches([]response.EngineResponse{engineResponse}) assert.Assert(t, annPatches == nil) } diff --git a/pkg/webhooks/checker.go b/pkg/webhooks/checker.go index 4a52fa7649..e6ccfc41c9 100644 --- a/pkg/webhooks/checker.go +++ b/pkg/webhooks/checker.go @@ -1,12 +1,13 @@ package webhooks import ( + "github.com/golang/glog" "k8s.io/api/admission/v1beta1" ) func (ws *WebhookServer) handleVerifyRequest(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse { - logger := ws.log.WithValues("action", "verify", "uid", request.UID, "kind", request.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation) - logger.V(4).Info("incoming request") + glog.V(4).Infof("Receive request in mutating webhook '/verify': Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s", + request.Kind.Kind, request.Namespace, request.Name, request.UID, request.Operation) return &v1beta1.AdmissionResponse{ Allowed: true, } diff --git a/pkg/webhooks/common.go b/pkg/webhooks/common.go index 476606b468..2ca90049f8 100644 --- a/pkg/webhooks/common.go +++ b/pkg/webhooks/common.go @@ -4,8 +4,9 @@ import ( "fmt" "strings" - "github.com/go-logr/logr" yamlv2 "gopkg.in/yaml.v2" + + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine/response" engineutils "github.com/nirmata/kyverno/pkg/engine/utils" @@ -26,14 +27,14 @@ func isResponseSuccesful(engineReponses []response.EngineResponse) bool { // returns true -> if there is even one policy that blocks resource request // returns false -> if all the policies are meant to report only, we dont block resource request -func toBlockResource(engineReponses []response.EngineResponse, log logr.Logger) bool { +func toBlockResource(engineReponses []response.EngineResponse) bool { for _, er := range engineReponses { if !er.IsSuccesful() && er.PolicyResponse.ValidationFailureAction == Enforce { - log.Info("spec.ValidationFailureAction set to enforcel blocking resource request", "policy", er.PolicyResponse.Policy) + glog.V(4).Infof("ValidationFailureAction set to enforce for policy %s , blocking resource request ", er.PolicyResponse.Policy) return true } } - log.V(4).Info("sepc.ValidationFailureAction set to auit for all applicable policies;allowing resource reques; reporting with policy violation ") + glog.V(4).Infoln("ValidationFailureAction set to audit, allowing resource request, reporting with policy violation") return false } @@ -102,14 +103,14 @@ const ( Audit = "audit" // dont block the request on failure, but report failiures as policy violations ) -func processResourceWithPatches(patch []byte, resource []byte, log logr.Logger) []byte { +func processResourceWithPatches(patch []byte, resource []byte) []byte { if patch == nil { return resource } resource, err := engineutils.ApplyPatchNew(resource, patch) if err != nil { - log.Error(err, "failed to patch resource:") + glog.Errorf("failed to patch resource: %v", err) return nil } return resource diff --git a/pkg/webhooks/generate/generate.go b/pkg/webhooks/generate/generate.go index 3631845541..f120c9fb5d 100644 --- a/pkg/webhooks/generate/generate.go +++ b/pkg/webhooks/generate/generate.go @@ -5,7 +5,7 @@ import ( "time" backoff "github.com/cenkalti/backoff" - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned" utilruntime "k8s.io/apimachinery/pkg/util/runtime" @@ -23,41 +23,37 @@ type Generator struct { ch chan kyverno.GenerateRequestSpec client *kyvernoclient.Clientset stopCh <-chan struct{} - log logr.Logger } //NewGenerator returns a new instance of Generate-Request resource generator -func NewGenerator(client *kyvernoclient.Clientset, stopCh <-chan struct{}, log logr.Logger) *Generator { +func NewGenerator(client *kyvernoclient.Clientset, stopCh <-chan struct{}) *Generator { gen := &Generator{ ch: make(chan kyverno.GenerateRequestSpec, 1000), client: client, stopCh: stopCh, - log: log, } return gen } //Create to create generate request resoruce (blocking call if channel is full) func (g *Generator) Create(gr kyverno.GenerateRequestSpec) error { - logger := g.log - logger.V(4).Info("creating Generate Request", "request", gr) + glog.V(4).Infof("create GR %v", gr) // Send to channel select { case g.ch <- gr: return nil case <-g.stopCh: - logger.Info("shutting down channel") + glog.Info("shutting down channel") return fmt.Errorf("shutting down gr create channel") } } // Run starts the generate request spec func (g *Generator) Run(workers int) { - logger := g.log defer utilruntime.HandleCrash() - logger.V(4).Info("starting") + glog.V(4).Info("Started generate request") defer func() { - logger.V(4).Info("shutting down") + glog.V(4).Info("Shutting down generate request") }() for i := 0; i < workers; i++ { go wait.Until(g.process, time.Second, g.stopCh) @@ -66,18 +62,17 @@ func (g *Generator) Run(workers int) { } func (g *Generator) process() { - logger := g.log for r := range g.ch { - logger.V(4).Info("recieved generate request", "request", r) + glog.V(4).Infof("received generate request %v", r) if err := g.generate(r); err != nil { - logger.Error(err, "failed to generate request CR") + glog.Errorf("Failed to create Generate Request CR: %v", err) } } } func (g *Generator) generate(grSpec kyverno.GenerateRequestSpec) error { // create a generate request - if err := retryCreateResource(g.client, grSpec, g.log); err != nil { + if err := retryCreateResource(g.client, grSpec); err != nil { return err } return nil @@ -86,10 +81,7 @@ func (g *Generator) generate(grSpec kyverno.GenerateRequestSpec) error { // -> receiving channel to take requests to create request // use worker pattern to read and create the CR resource -func retryCreateResource(client *kyvernoclient.Clientset, - grSpec kyverno.GenerateRequestSpec, - log logr.Logger, -) error { +func retryCreateResource(client *kyvernoclient.Clientset, grSpec kyverno.GenerateRequestSpec) error { var i int var err error createResource := func() error { @@ -103,7 +95,7 @@ func retryCreateResource(client *kyvernoclient.Clientset, // gr.Status.State = kyverno.Pending // generate requests created in kyverno namespace _, err = client.KyvernoV1().GenerateRequests("kyverno").Create(&gr) - log.V(4).Info("retrying create generate request CR", "retryCount", i, "name", gr.GetGenerateName(), "namespace", gr.GetNamespace()) + glog.V(4).Infof("retry %v create generate request", i) i++ return err } diff --git a/pkg/webhooks/generation.go b/pkg/webhooks/generation.go index 7f0fc4a692..956c568cac 100644 --- a/pkg/webhooks/generation.go +++ b/pkg/webhooks/generation.go @@ -5,6 +5,7 @@ import ( "sort" "time" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine" @@ -17,19 +18,19 @@ import ( //HandleGenerate handles admission-requests for policies with generate rules func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, policies []kyverno.ClusterPolicy, patchedResource []byte, roles, clusterRoles []string) (bool, string) { - logger := ws.log.WithValues("action", "generation", "uid", request.UID, "kind", request.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation) - logger.V(4).Info("incoming request") var engineResponses []response.EngineResponse // convert RAW to unstructured resource, err := utils.ConvertToUnstructured(request.Object.Raw) if err != nil { //TODO: skip applying the admission control ? - logger.Error(err, "failed to convert RAR resource to unstructured format") + glog.Errorf("unable to convert raw resource to unstructured: %v", err) return true, "" } // CREATE resources, do not have name, assigned in admission-request + glog.V(4).Infof("Handle Generate: Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s", + resource.GetKind(), resource.GetNamespace(), resource.GetName(), request.UID, request.Operation) userRequestInfo := kyverno.RequestInfo{ Roles: roles, @@ -40,16 +41,16 @@ func (ws *WebhookServer) HandleGenerate(request *v1beta1.AdmissionRequest, polic // load incoming resource into the context err = ctx.AddResource(request.Object.Raw) if err != nil { - logger.Error(err, "failed to load incoming resource in context") + glog.Infof("Failed to load resource in context:%v", err) } err = ctx.AddUserInfo(userRequestInfo) if err != nil { - logger.Error(err, "failed to load userInfo in context") + glog.Infof("Failed to load userInfo in context:%v", err) } // load service account in context err = ctx.AddSA(userRequestInfo.AdmissionUserInfo.Username) if err != nil { - logger.Error(err, "failed to load service account in context") + glog.Infof("Failed to load service account in context:%v", err) } policyContext := engine.PolicyContext{ diff --git a/pkg/webhooks/mutation.go b/pkg/webhooks/mutation.go index 68ca58fae1..1991427ebf 100644 --- a/pkg/webhooks/mutation.go +++ b/pkg/webhooks/mutation.go @@ -7,6 +7,7 @@ import ( "github.com/nirmata/kyverno/pkg/openapi" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine" @@ -21,8 +22,8 @@ import ( // HandleMutation handles mutating webhook admission request // return value: generated patches func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest, resource unstructured.Unstructured, policies []kyverno.ClusterPolicy, roles, clusterRoles []string) []byte { - logger := ws.log.WithValues("action", "mutation", "uid", request.UID, "kind", request.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation) - logger.V(4).Info("incoming request") + glog.V(4).Infof("Receive request in mutating webhook: Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s", + request.Kind.Kind, request.Namespace, request.Name, request.UID, request.Operation) var patches [][]byte var engineResponses []response.EngineResponse @@ -38,16 +39,16 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest, resou // load incoming resource into the context err = ctx.AddResource(request.Object.Raw) if err != nil { - logger.Error(err, "failed to load incoming resource in context") + glog.Infof("Failed to load resource in context:%v", err) } err = ctx.AddUserInfo(userRequestInfo) if err != nil { - logger.Error(err, "failed to load userInfo in context") + glog.Infof("Failed to load userInfo in context:%v", err) } err = ctx.AddSA(userRequestInfo.AdmissionUserInfo.Username) if err != nil { - logger.Error(err, "failed to load service account in context") + glog.Infof("Failed to load service account in context:%v", err) } policyContext := engine.PolicyContext{ @@ -57,36 +58,39 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest, resou } for _, policy := range policies { - logger.V(2).Info("evaluating policy", "policy", policy.Name) - + glog.V(2).Infof("Handling mutation for Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s", + resource.GetKind(), resource.GetNamespace(), resource.GetName(), request.UID, request.Operation) policyContext.Policy = policy engineResponse := engine.Mutate(policyContext) engineResponses = append(engineResponses, engineResponse) ws.statusListener.Send(mutateStats{resp: engineResponse}) if !engineResponse.IsSuccesful() { - logger.V(4).Info("failed to apply policy", "policy", policy.Name) + glog.V(4).Infof("Failed to apply policy %s on resource %s/%s\n", policy.Name, resource.GetNamespace(), resource.GetName()) continue } err := openapi.ValidateResource(*engineResponse.PatchedResource.DeepCopy(), engineResponse.PatchedResource.GetKind()) if err != nil { - logger.Error(err, "failed to validate resource") + glog.V(4).Infoln(err) continue } // gather patches patches = append(patches, engineResponse.GetPatches()...) - logger.Info("mutation rules from policy applied succesfully", "policy", policy.Name) + glog.V(4).Infof("Mutation from policy %s has applied successfully to %s %s/%s", policy.Name, request.Kind.Kind, resource.GetNamespace(), resource.GetName()) policyContext.NewResource = engineResponse.PatchedResource } // generate annotations - if annPatches := generateAnnotationPatches(engineResponses, logger); annPatches != nil { + if annPatches := generateAnnotationPatches(engineResponses); annPatches != nil { patches = append(patches, annPatches) } + // report time + reportTime := time.Now() + // AUDIT // generate violation when response fails - pvInfos := policyviolation.GeneratePVsFromEngineResponse(engineResponses, logger) + pvInfos := policyviolation.GeneratePVsFromEngineResponse(engineResponses) ws.pvGenerator.Add(pvInfos...) // REPORTING EVENTS // Scenario 1: @@ -96,21 +100,25 @@ func (ws *WebhookServer) HandleMutation(request *v1beta1.AdmissionRequest, resou // all policies were applied succesfully. // create an event on the resource // ADD EVENTS - events := generateEvents(engineResponses, false, (request.Operation == v1beta1.Update), logger) + events := generateEvents(engineResponses, false, (request.Operation == v1beta1.Update)) ws.eventGen.Add(events...) // debug info func() { if len(patches) != 0 { - logger.V(4).Info("JSON patches generated") + glog.V(4).Infof("Patches generated for %s/%s/%s, operation=%v:\n %v", + resource.GetKind(), resource.GetNamespace(), resource.GetName(), request.Operation, string(engineutils.JoinPatches(patches))) } // if any of the policies fails, print out the error if !isResponseSuccesful(engineResponses) { - logger.Info("failed to apply mutation rules on the resource, reporting policy violation", "errors", getErrorMsg(engineResponses)) + glog.Errorf("Failed to mutate the resource, report as violation: %s\n", getErrorMsg(engineResponses)) } }() + // report time end + glog.V(4).Infof("report: %v %s/%s/%s", time.Since(reportTime), resource.GetKind(), resource.GetNamespace(), resource.GetName()) + // patches holds all the successful patches, if no patch is created, it returns nil return engineutils.JoinPatches(patches) } diff --git a/pkg/webhooks/policymutation.go b/pkg/webhooks/policymutation.go index dea2f87fff..8081528edd 100644 --- a/pkg/webhooks/policymutation.go +++ b/pkg/webhooks/policymutation.go @@ -8,7 +8,7 @@ import ( "strings" jsonpatch "github.com/evanphx/json-patch" - "github.com/go-logr/logr" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine" "github.com/nirmata/kyverno/pkg/utils" @@ -17,13 +17,12 @@ import ( ) func (ws *WebhookServer) handlePolicyMutation(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse { - logger := ws.log.WithValues("action", "policymutation", "uid", request.UID, "kind", request.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation) var policy *kyverno.ClusterPolicy raw := request.Object.Raw //TODO: can this happen? wont this be picked by OpenAPI spec schema ? if err := json.Unmarshal(raw, &policy); err != nil { - logger.Error(err, "faield to unmarshall policy admission request") + glog.Errorf("Failed to unmarshal policy admission request, err %v\n", err) return &v1beta1.AdmissionResponse{ Allowed: true, Result: &metav1.Status{ @@ -32,9 +31,10 @@ func (ws *WebhookServer) handlePolicyMutation(request *v1beta1.AdmissionRequest) } } // Generate JSON Patches for defaults - patches, updateMsgs := generateJSONPatchesForDefaults(policy, logger) + patches, updateMsgs := generateJSONPatchesForDefaults(policy) if patches != nil { patchType := v1beta1.PatchTypeJSONPatch + glog.V(4).Infof("defaulted values %v policy %s", updateMsgs, policy.Name) return &v1beta1.AdmissionResponse{ Allowed: true, Result: &metav1.Status{ @@ -44,34 +44,35 @@ func (ws *WebhookServer) handlePolicyMutation(request *v1beta1.AdmissionRequest) PatchType: &patchType, } } + glog.V(4).Infof("nothing to default for policy %s", policy.Name) return &v1beta1.AdmissionResponse{ Allowed: true, } } -func generateJSONPatchesForDefaults(policy *kyverno.ClusterPolicy, log logr.Logger) ([]byte, []string) { +func generateJSONPatchesForDefaults(policy *kyverno.ClusterPolicy) ([]byte, []string) { var patches [][]byte var updateMsgs []string // default 'ValidationFailureAction' - if patch, updateMsg := defaultvalidationFailureAction(policy, log); patch != nil { + if patch, updateMsg := defaultvalidationFailureAction(policy); patch != nil { patches = append(patches, patch) updateMsgs = append(updateMsgs, updateMsg) } // default 'Background' - if patch, updateMsg := defaultBackgroundFlag(policy, log); patch != nil { + if patch, updateMsg := defaultBackgroundFlag(policy); patch != nil { patches = append(patches, patch) updateMsgs = append(updateMsgs, updateMsg) } - patch, errs := generatePodControllerRule(*policy, log) + patch, errs := generatePodControllerRule(*policy) if len(errs) > 0 { var errMsgs []string for _, err := range errs { errMsgs = append(errMsgs, err.Error()) - log.Error(err, "failed to generate pod controller rule") } + glog.Errorf("failed auto generating rule for pod controllers: %s", errMsgs) updateMsgs = append(updateMsgs, strings.Join(errMsgs, ";")) } @@ -80,11 +81,11 @@ func generateJSONPatchesForDefaults(policy *kyverno.ClusterPolicy, log logr.Logg return utils.JoinPatches(patches), updateMsgs } -func defaultBackgroundFlag(policy *kyverno.ClusterPolicy, log logr.Logger) ([]byte, string) { +func defaultBackgroundFlag(policy *kyverno.ClusterPolicy) ([]byte, string) { // default 'Background' flag to 'true' if not specified defaultVal := true if policy.Spec.Background == nil { - log.V(4).Info("setting default value", "spec.background", true) + glog.V(4).Infof("default policy %s 'Background' to '%s'", policy.Name, strconv.FormatBool(true)) jsonPatch := struct { Path string `json:"path"` Op string `json:"op"` @@ -96,19 +97,19 @@ func defaultBackgroundFlag(policy *kyverno.ClusterPolicy, log logr.Logger) ([]by } patchByte, err := json.Marshal(jsonPatch) if err != nil { - log.Error(err, "failed to set default value", "spec.background", true) + glog.Errorf("failed to set default 'Background' to '%s' for policy %s", strconv.FormatBool(true), policy.Name) return nil, "" } - log.Info("generated JSON Patch to set default", "spec.background", true) + glog.V(4).Infof("generate JSON Patch to set default 'Background' to '%s' for policy %s", strconv.FormatBool(true), policy.Name) return patchByte, fmt.Sprintf("default 'Background' to '%s'", strconv.FormatBool(true)) } return nil, "" } -func defaultvalidationFailureAction(policy *kyverno.ClusterPolicy, log logr.Logger) ([]byte, string) { +func defaultvalidationFailureAction(policy *kyverno.ClusterPolicy) ([]byte, string) { // default ValidationFailureAction to "audit" if not specified if policy.Spec.ValidationFailureAction == "" { - log.V(4).Info("setting defautl value", "spec.validationFailureAction", Audit) + glog.V(4).Infof("defaulting policy %s 'ValidationFailureAction' to '%s'", policy.Name, Audit) jsonPatch := struct { Path string `json:"path"` Op string `json:"op"` @@ -120,10 +121,10 @@ func defaultvalidationFailureAction(policy *kyverno.ClusterPolicy, log logr.Logg } patchByte, err := json.Marshal(jsonPatch) if err != nil { - log.Error(err, "failed to default value", "spec.validationFailureAction", Audit) + glog.Errorf("failed to set default 'ValidationFailureAction' to '%s' for policy %s", Audit, policy.Name) return nil, "" } - log.Info("generated JSON Patch to set default", "spec.validationFailureAction", Audit) + glog.V(4).Infof("generate JSON Patch to set default 'ValidationFailureAction' to '%s' for policy %s", Audit, policy.Name) return patchByte, fmt.Sprintf("default 'ValidationFailureAction' to '%s'", Audit) } return nil, "" @@ -139,7 +140,7 @@ func defaultvalidationFailureAction(policy *kyverno.ClusterPolicy, log logr.Logg // make sure all fields are applicable to pod cotrollers // generatePodControllerRule returns two patches: rulePatches and annotation patch(if necessary) -func generatePodControllerRule(policy kyverno.ClusterPolicy, log logr.Logger) (patches [][]byte, errs []error) { +func generatePodControllerRule(policy kyverno.ClusterPolicy) (patches [][]byte, errs []error) { ann := policy.GetAnnotations() controllers, ok := ann[engine.PodControllersAnnotation] @@ -158,9 +159,10 @@ func generatePodControllerRule(policy kyverno.ClusterPolicy, log logr.Logger) (p if controllers == "none" { return nil, nil } - log.V(3).Info("auto generating rule for pod controllers", "controlers", controllers) - p, err := generateRulePatches(policy, controllers, log) + glog.V(3).Infof("Auto generating rule for pod controller: %s", controllers) + + p, err := generateRulePatches(policy, controllers) patches = append(patches, p...) errs = append(errs, err...) return @@ -195,7 +197,7 @@ func createRuleMap(rules []kyverno.Rule) map[string]kyvernoRule { } // generateRulePatches generates rule for podControllers based on scenario A and C -func generateRulePatches(policy kyverno.ClusterPolicy, controllers string, log logr.Logger) (rulePatches [][]byte, errs []error) { +func generateRulePatches(policy kyverno.ClusterPolicy, controllers string) (rulePatches [][]byte, errs []error) { var genRule kyvernoRule insertIdx := len(policy.Spec.Rules) @@ -208,7 +210,7 @@ func generateRulePatches(policy kyverno.ClusterPolicy, controllers string, log l for _, rule := range policy.Spec.Rules { patchPostion := insertIdx - genRule = generateRuleForControllers(rule, controllers, log) + genRule = generateRuleForControllers(rule, controllers) if reflect.DeepEqual(genRule, kyvernoRule{}) { continue } @@ -270,7 +272,7 @@ type kyvernoRule struct { Validation *kyverno.Validation `json:"validate,omitempty"` } -func generateRuleForControllers(rule kyverno.Rule, controllers string, log logr.Logger) kyvernoRule { +func generateRuleForControllers(rule kyverno.Rule, controllers string) kyvernoRule { if strings.HasPrefix(rule.Name, "autogen-") { return kyvernoRule{} } @@ -290,7 +292,7 @@ func generateRuleForControllers(rule kyverno.Rule, controllers string, log logr. if controllers == "all" { if match.ResourceDescription.Name != "" || match.ResourceDescription.Selector != nil || exclude.ResourceDescription.Name != "" || exclude.ResourceDescription.Selector != nil { - log.Info("skip generating rule on pod controllers: Name / Selector in resource decription may not be applicable.", "rule", rule.Name) + glog.Warningf("Rule '%s' skip generating rule on pod controllers: Name / Selector in resource decription may not be applicable.", rule.Name) return kyvernoRule{} } controllers = engine.PodControllers diff --git a/pkg/webhooks/policymutation_test.go b/pkg/webhooks/policymutation_test.go index d887cd6ee2..0b5af63c59 100644 --- a/pkg/webhooks/policymutation_test.go +++ b/pkg/webhooks/policymutation_test.go @@ -8,7 +8,6 @@ import ( kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine/utils" "gotest.tools/assert" - "sigs.k8s.io/controller-runtime/pkg/log" ) func compareJSONAsMap(t *testing.T, expected, actual []byte) { @@ -29,7 +28,7 @@ func TestGeneratePodControllerRule_NilAnnotation(t *testing.T) { var policy kyverno.ClusterPolicy assert.Assert(t, json.Unmarshal(policyRaw, &policy)) - patches, errs := generatePodControllerRule(policy, log.Log) + patches, errs := generatePodControllerRule(policy) assert.Assert(t, len(errs) == 0) p, err := utils.ApplyPatches(policyRaw, patches) @@ -62,7 +61,7 @@ func TestGeneratePodControllerRule_PredefinedAnnotation(t *testing.T) { var policy kyverno.ClusterPolicy assert.Assert(t, json.Unmarshal(policyRaw, &policy)) - patches, errs := generatePodControllerRule(policy, log.Log) + patches, errs := generatePodControllerRule(policy) assert.Assert(t, len(errs) == 0) assert.Assert(t, len(patches) == 0) } @@ -113,7 +112,7 @@ func TestGeneratePodControllerRule_DisableFeature(t *testing.T) { var policy kyverno.ClusterPolicy assert.Assert(t, json.Unmarshal(policyRaw, &policy)) - patches, errs := generatePodControllerRule(policy, log.Log) + patches, errs := generatePodControllerRule(policy) assert.Assert(t, len(errs) == 0) assert.Assert(t, len(patches) == 0) } @@ -164,7 +163,7 @@ func TestGeneratePodControllerRule_Mutate(t *testing.T) { var policy kyverno.ClusterPolicy assert.Assert(t, json.Unmarshal(policyRaw, &policy)) - patches, errs := generatePodControllerRule(policy, log.Log) + patches, errs := generatePodControllerRule(policy) assert.Assert(t, len(errs) == 0) p, err := utils.ApplyPatches(policyRaw, patches) @@ -262,7 +261,7 @@ func TestGeneratePodControllerRule_ExistOtherAnnotation(t *testing.T) { var policy kyverno.ClusterPolicy assert.Assert(t, json.Unmarshal(policyRaw, &policy)) - patches, errs := generatePodControllerRule(policy, log.Log) + patches, errs := generatePodControllerRule(policy) assert.Assert(t, len(errs) == 0) p, err := utils.ApplyPatches(policyRaw, patches) @@ -334,7 +333,7 @@ func TestGeneratePodControllerRule_ValidateAnyPattern(t *testing.T) { var policy kyverno.ClusterPolicy assert.Assert(t, json.Unmarshal(policyRaw, &policy)) - patches, errs := generatePodControllerRule(policy, log.Log) + patches, errs := generatePodControllerRule(policy) assert.Assert(t, len(errs) == 0) p, err := utils.ApplyPatches(policyRaw, patches) @@ -472,7 +471,7 @@ func TestGeneratePodControllerRule_ValidatePattern(t *testing.T) { var policy kyverno.ClusterPolicy assert.Assert(t, json.Unmarshal(policyRaw, &policy)) - patches, errs := generatePodControllerRule(policy, log.Log) + patches, errs := generatePodControllerRule(policy) assert.Assert(t, len(errs) == 0) p, err := utils.ApplyPatches(policyRaw, patches) diff --git a/pkg/webhooks/policyvalidation.go b/pkg/webhooks/policyvalidation.go index 897bba0de0..d58a22eec9 100644 --- a/pkg/webhooks/policyvalidation.go +++ b/pkg/webhooks/policyvalidation.go @@ -4,14 +4,13 @@ import ( policyvalidate "github.com/nirmata/kyverno/pkg/policy" v1beta1 "k8s.io/api/admission/v1beta1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) //HandlePolicyValidation performs the validation check on policy resource func (ws *WebhookServer) handlePolicyValidation(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse { //TODO: can this happen? wont this be picked by OpenAPI spec schema ? - if err := policyvalidate.Validate(request.Object.Raw, ws.client, false); err != nil { + if err := policyvalidate.Validate(request.Object.Raw); err != nil { return &v1beta1.AdmissionResponse{ Allowed: false, Result: &metav1.Status{ diff --git a/pkg/webhooks/report.go b/pkg/webhooks/report.go index 83e67c5753..035a60688e 100644 --- a/pkg/webhooks/report.go +++ b/pkg/webhooks/report.go @@ -3,7 +3,6 @@ package webhooks import ( "strings" - "github.com/go-logr/logr" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine/response" @@ -11,7 +10,7 @@ import ( ) //generateEvents generates event info for the engine responses -func generateEvents(engineResponses []response.EngineResponse, blocked, onUpdate bool, log logr.Logger) []event.Info { +func generateEvents(engineResponses []response.EngineResponse, blocked, onUpdate bool) []event.Info { var events []event.Info // Scenario 1 // - Admission-Response is SUCCESS && CREATE @@ -27,7 +26,6 @@ func generateEvents(engineResponses []response.EngineResponse, blocked, onUpdate successRulesStr := strings.Join(successRules, ";") // event on resource e := event.NewEvent( - log, er.PolicyResponse.Resource.Kind, er.PolicyResponse.Resource.APIVersion, er.PolicyResponse.Resource.Namespace, @@ -61,7 +59,6 @@ func generateEvents(engineResponses []response.EngineResponse, blocked, onUpdate filedRulesStr := strings.Join(failedRules, ";") // Event on Policy e := event.NewEvent( - log, "ClusterPolicy", kyverno.SchemeGroupVersion.String(), "", @@ -93,7 +90,6 @@ func generateEvents(engineResponses []response.EngineResponse, blocked, onUpdate filedRulesStr := strings.Join(failedRules, ";") // Event on the policy e := event.NewEvent( - log, "ClusterPolicy", kyverno.SchemeGroupVersion.String(), "", @@ -108,7 +104,6 @@ func generateEvents(engineResponses []response.EngineResponse, blocked, onUpdate // Event on the resource // event on resource e = event.NewEvent( - log, er.PolicyResponse.Resource.Kind, er.PolicyResponse.Resource.APIVersion, er.PolicyResponse.Resource.Namespace, diff --git a/pkg/webhooks/server.go b/pkg/webhooks/server.go index fbc8788d0b..b0ca988449 100644 --- a/pkg/webhooks/server.go +++ b/pkg/webhooks/server.go @@ -10,7 +10,7 @@ import ( "net/http" "time" - "github.com/go-logr/logr" + "github.com/golang/glog" "github.com/nirmata/kyverno/pkg/checker" kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned" kyvernoinformer "github.com/nirmata/kyverno/pkg/client/informers/externalversions/kyverno/v1" @@ -69,7 +69,6 @@ type WebhookServer struct { // generate request generator grGenerator *generate.Generator resourceWebhookWatcher *webhookconfig.ResourceWebhookRegister - log logr.Logger } // NewWebhookServer creates new instance of WebhookServer accordingly to given configuration @@ -89,9 +88,7 @@ func NewWebhookServer( pvGenerator policyviolation.GeneratorInterface, grGenerator *generate.Generator, resourceWebhookWatcher *webhookconfig.ResourceWebhookRegister, - cleanUp chan<- struct{}, - log logr.Logger, -) (*WebhookServer, error) { + cleanUp chan<- struct{}) (*WebhookServer, error) { if tlsPair == nil { return nil, errors.New("NewWebhookServer is not initialized properly") @@ -123,7 +120,6 @@ func NewWebhookServer( pMetaStore: pMetaStore, grGenerator: grGenerator, resourceWebhookWatcher: resourceWebhookWatcher, - log: log, } mux := http.NewServeMux() mux.HandleFunc(config.MutatingWebhookServicePath, ws.serve) @@ -152,9 +148,8 @@ func (ws *WebhookServer) serve(w http.ResponseWriter, r *http.Request) { if admissionReview == nil { return } - logger := ws.log.WithValues("kind", admissionReview.Request.Kind, "namespace", admissionReview.Request.Namespace, "name", admissionReview.Request.Name) defer func() { - logger.V(4).Info("request processed", "processingTime", time.Since(startTime)) + glog.V(4).Infof("request: %v %s/%s/%s", time.Since(startTime), admissionReview.Request.Kind, admissionReview.Request.Namespace, admissionReview.Request.Name) }() admissionReview.Response = &v1beta1.AdmissionResponse{ @@ -200,29 +195,31 @@ func (ws *WebhookServer) serve(w http.ResponseWriter, r *http.Request) { } func (ws *WebhookServer) handleMutateAdmissionRequest(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse { - logger := ws.log.WithValues("uid", request.UID, "kind", request.Kind.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation) policies, err := ws.pMetaStore.ListAll() if err != nil { // Unable to connect to policy Lister to access policies - logger.Error(err, "failed to list policies. Policies are NOT being applied") + glog.Errorf("Unable to connect to policy controller to access policies. Policies are NOT being applied: %v", err) return &v1beta1.AdmissionResponse{Allowed: true} } var roles, clusterRoles []string // getRoleRef only if policy has roles/clusterroles defined + startTime := time.Now() if containRBACinfo(policies) { roles, clusterRoles, err = userinfo.GetRoleRef(ws.rbLister, ws.crbLister, request) if err != nil { // TODO(shuting): continue apply policy if error getting roleRef? - logger.Error(err, "failed to get RBAC infromation for request") + glog.Errorf("Unable to get rbac information for request Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s: %v", + request.Kind.Kind, request.Namespace, request.Name, request.UID, request.Operation, err) } } + glog.V(4).Infof("Time: webhook GetRoleRef %v", time.Since(startTime)) // convert RAW to unstructured resource, err := convertResource(request.Object.Raw, request.Kind.Group, request.Kind.Version, request.Kind.Kind, request.Namespace) if err != nil { - logger.Error(err, "failed to convert RAW resource to unstructured format") + glog.Errorf(err.Error()) return &v1beta1.AdmissionResponse{ Allowed: false, @@ -248,13 +245,13 @@ func (ws *WebhookServer) handleMutateAdmissionRequest(request *v1beta1.Admission patches := ws.HandleMutation(request, resource, policies, roles, clusterRoles) // patch the resource with patches before handling validation rules - patchedResource := processResourceWithPatches(patches, request.Object.Raw, logger) + patchedResource := processResourceWithPatches(patches, request.Object.Raw) if ws.resourceWebhookWatcher != nil && ws.resourceWebhookWatcher.RunValidationInMutatingWebhook == "true" { // VALIDATION ok, msg := ws.HandleValidation(request, policies, patchedResource, roles, clusterRoles) if !ok { - logger.Info("admission request denied") + glog.V(4).Infof("Deny admission request: %v/%s/%s", request.Kind, request.Namespace, request.Name) return &v1beta1.AdmissionResponse{ Allowed: false, Result: &metav1.Status{ @@ -272,7 +269,7 @@ func (ws *WebhookServer) handleMutateAdmissionRequest(request *v1beta1.Admission if request.Operation == v1beta1.Create { ok, msg := ws.HandleGenerate(request, policies, patchedResource, roles, clusterRoles) if !ok { - logger.Info("admission request denied") + glog.V(4).Infof("Deny admission request: %v/%s/%s", request.Kind, request.Namespace, request.Name) return &v1beta1.AdmissionResponse{ Allowed: false, Result: &metav1.Status{ @@ -295,29 +292,31 @@ func (ws *WebhookServer) handleMutateAdmissionRequest(request *v1beta1.Admission } func (ws *WebhookServer) handleValidateAdmissionRequest(request *v1beta1.AdmissionRequest) *v1beta1.AdmissionResponse { - logger := ws.log.WithValues("uid", request.UID, "kind", request.Kind.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation) policies, err := ws.pMetaStore.ListAll() if err != nil { // Unable to connect to policy Lister to access policies - logger.Error(err, "failed to list policies. Policies are NOT being applied") + glog.Errorf("Unable to connect to policy controller to access policies. Policies are NOT being applied: %v", err) return &v1beta1.AdmissionResponse{Allowed: true} } var roles, clusterRoles []string // getRoleRef only if policy has roles/clusterroles defined + startTime := time.Now() if containRBACinfo(policies) { roles, clusterRoles, err = userinfo.GetRoleRef(ws.rbLister, ws.crbLister, request) if err != nil { // TODO(shuting): continue apply policy if error getting roleRef? - logger.Error(err, "failed to get RBAC infromation for request") + glog.Errorf("Unable to get rbac information for request Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s: %v", + request.Kind.Kind, request.Namespace, request.Name, request.UID, request.Operation, err) } } + glog.V(4).Infof("Time: webhook GetRoleRef %v", time.Since(startTime)) // VALIDATION ok, msg := ws.HandleValidation(request, policies, nil, roles, clusterRoles) if !ok { - logger.Info("admission request denied") + glog.V(4).Infof("Deny admission request: %v/%s/%s", request.Kind, request.Namespace, request.Name) return &v1beta1.AdmissionResponse{ Allowed: false, Result: &metav1.Status{ @@ -337,28 +336,27 @@ func (ws *WebhookServer) handleValidateAdmissionRequest(request *v1beta1.Admissi // RunAsync TLS server in separate thread and returns control immediately func (ws *WebhookServer) RunAsync(stopCh <-chan struct{}) { - logger := ws.log if !cache.WaitForCacheSync(stopCh, ws.pSynced, ws.rbSynced, ws.crbSynced) { - logger.Info("failed to sync informer cache") + glog.Error("webhook: failed to sync informer cache") } go func(ws *WebhookServer) { - logger.V(3).Info("started serving requests", "addr", ws.server.Addr) + glog.V(3).Infof("serving on %s\n", ws.server.Addr) if err := ws.server.ListenAndServeTLS("", ""); err != http.ErrServerClosed { - logger.Error(err, "failed to listen to requests") + glog.Infof("HTTP server error: %v", err) } }(ws) - logger.Info("starting") + glog.Info("Started Webhook Server") // verifys if the admission control is enabled and active // resync: 60 seconds // deadline: 60 seconds (send request) // max deadline: deadline*3 (set the deployment annotation as false) go ws.lastReqTime.Run(ws.pLister, ws.eventGen, ws.client, checker.DefaultResync, checker.DefaultDeadline, stopCh) + } // Stop TLS server and returns control after the server is shut down func (ws *WebhookServer) Stop(ctx context.Context) { - logger := ws.log // cleanUp // remove the static webhookconfigurations go ws.webhookRegistrationClient.RemoveWebhookConfigurations(ws.cleanUp) @@ -366,7 +364,7 @@ func (ws *WebhookServer) Stop(ctx context.Context) { err := ws.server.Shutdown(ctx) if err != nil { // Error from closing listeners, or context timeout: - logger.Error(err, "shutting down server") + glog.Info("Server Shutdown error: ", err) ws.server.Close() } } @@ -374,7 +372,6 @@ func (ws *WebhookServer) Stop(ctx context.Context) { // bodyToAdmissionReview creates AdmissionReview object from request body // Answers to the http.ResponseWriter if request is not valid func (ws *WebhookServer) bodyToAdmissionReview(request *http.Request, writer http.ResponseWriter) *v1beta1.AdmissionReview { - logger := ws.log var body []byte if request.Body != nil { if data, err := ioutil.ReadAll(request.Body); err == nil { @@ -382,21 +379,21 @@ func (ws *WebhookServer) bodyToAdmissionReview(request *http.Request, writer htt } } if len(body) == 0 { - logger.Info("empty body") + glog.Error("Error: empty body") http.Error(writer, "empty body", http.StatusBadRequest) return nil } contentType := request.Header.Get("Content-Type") if contentType != "application/json" { - logger.Info("invalid Content-Type", "contextType", contentType) + glog.Error("Error: invalid Content-Type: ", contentType) http.Error(writer, "invalid Content-Type, expect `application/json`", http.StatusUnsupportedMediaType) return nil } admissionReview := &v1beta1.AdmissionReview{} if err := json.Unmarshal(body, &admissionReview); err != nil { - logger.Error(err, "failed to decode request body to type 'AdmissionReview") + glog.Errorf("Error: Can't decode body as AdmissionReview: %v", err) http.Error(writer, "Can't decode body as AdmissionReview", http.StatusExpectationFailed) return nil } diff --git a/pkg/webhooks/validation.go b/pkg/webhooks/validation.go index d0b49347ad..54a7fbdf3e 100644 --- a/pkg/webhooks/validation.go +++ b/pkg/webhooks/validation.go @@ -5,6 +5,7 @@ import ( "sort" "time" + "github.com/golang/glog" kyverno "github.com/nirmata/kyverno/pkg/api/kyverno/v1" v1 "github.com/nirmata/kyverno/pkg/api/kyverno/v1" "github.com/nirmata/kyverno/pkg/engine" @@ -18,14 +19,16 @@ import ( // If there are no errors in validating rule we apply generation rules // patchedResource is the (resource + patches) after applying mutation rules func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, policies []kyverno.ClusterPolicy, patchedResource []byte, roles, clusterRoles []string) (bool, string) { - logger := ws.log.WithValues("action", "validation", "uid", request.UID, "kind", request.Kind, "namespace", request.Namespace, "name", request.Name, "operation", request.Operation) - logger.V(4).Info("incoming request") + glog.V(4).Infof("Receive request in validating webhook: Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s", + request.Kind.Kind, request.Namespace, request.Name, request.UID, request.Operation) + + evalTime := time.Now() // Get new and old resource newR, oldR, err := extractResources(patchedResource, request) if err != nil { // as resource cannot be parsed, we skip processing - logger.Error(err, "failed to extract resource") + glog.Error(err) return true, "" } userRequestInfo := kyverno.RequestInfo{ @@ -37,17 +40,17 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, pol // load incoming resource into the context err = ctx.AddResource(request.Object.Raw) if err != nil { - logger.Error(err, "failed to load incoming resource in context") + glog.Infof("Failed to load resource in context:%v", err) } err = ctx.AddUserInfo(userRequestInfo) if err != nil { - logger.Error(err, "failed to load userInfo in context") + glog.Infof("Failed to load userInfo in context:%v", err) } err = ctx.AddSA(userRequestInfo.AdmissionUserInfo.Username) if err != nil { - logger.Error(err, "failed to load service account in context") + glog.Infof("Failed to load service account in context:%v", err) } policyContext := engine.PolicyContext{ @@ -58,7 +61,8 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, pol } var engineResponses []response.EngineResponse for _, policy := range policies { - logger.V(2).Info("evaluating policy", "policy", policy.Name) + glog.V(2).Infof("Handling validation for Kind=%s, Namespace=%s Name=%s UID=%s patchOperation=%s", + newR.GetKind(), newR.GetNamespace(), newR.GetName(), request.UID, request.Operation) policyContext.Policy = policy engineResponse := engine.Validate(policyContext) if reflect.DeepEqual(engineResponse, response.EngineResponse{}) { @@ -71,13 +75,17 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, pol resp: engineResponse, }) if !engineResponse.IsSuccesful() { - logger.V(4).Info("failed to apply policy", "policy", policy.Name) + glog.V(4).Infof("Failed to apply policy %s on resource %s/%s\n", policy.Name, newR.GetNamespace(), newR.GetName()) continue } } + glog.V(4).Infof("eval: %v %s/%s/%s ", time.Since(evalTime), request.Kind, request.Namespace, request.Name) + // report time + reportTime := time.Now() + // If Validation fails then reject the request // no violations will be created on "enforce" - blocked := toBlockResource(engineResponses, logger) + blocked := toBlockResource(engineResponses) // REPORTING EVENTS // Scenario 1: @@ -89,18 +97,19 @@ func (ws *WebhookServer) HandleValidation(request *v1beta1.AdmissionRequest, pol // Scenario 3: // all policies were applied succesfully. // create an event on the resource - events := generateEvents(engineResponses, blocked, (request.Operation == v1beta1.Update), logger) + events := generateEvents(engineResponses, blocked, (request.Operation == v1beta1.Update)) ws.eventGen.Add(events...) if blocked { - logger.V(4).Info("resource blocked") + glog.V(4).Infof("resource %s/%s/%s is blocked\n", newR.GetKind(), newR.GetNamespace(), newR.GetName()) return false, getEnforceFailureErrorMsg(engineResponses) } // ADD POLICY VIOLATIONS // violations are created with resource on "audit" - pvInfos := policyviolation.GeneratePVsFromEngineResponse(engineResponses, logger) + pvInfos := policyviolation.GeneratePVsFromEngineResponse(engineResponses) ws.pvGenerator.Add(pvInfos...) // report time end + glog.V(4).Infof("report: %v %s/%s/%s", time.Since(reportTime), request.Kind, request.Namespace, request.Name) return true, "" } diff --git a/scripts/update-codegen.sh b/scripts/update-codegen.sh index a6f56b314d..686c2cdfe1 100755 --- a/scripts/update-codegen.sh +++ b/scripts/update-codegen.sh @@ -13,10 +13,8 @@ esac NIRMATA_DIR=$(dirname ${BASH_SOURCE})/.. NIRMATA_ROOT=$(${linkutil} -f ${NIRMATA_DIR}) -# instructions to build project https://github.com/nirmata/kyverno/wiki/Building - # get relative path to code generation script -CODEGEN_PKG="${GOPATH}/src/k8s.io/code-generator" +CODEGEN_PKG=${NIRMATA_DIR}/vendor/k8s.io/code-generator # get relative path of nirmata NIRMATA_PKG=${NIRMATA_ROOT#"${GOPATH}/src/"}