From 1b707f10a04bbeb2aac469fa52a6ba57ed8cbf0a Mon Sep 17 00:00:00 2001
From: shravan <shravan.ss@zopsmart.com>
Date: Fri, 24 Jan 2020 22:27:21 +0530
Subject: [PATCH] 522 added ability to override default openAPI document

---
 cmd/kyverno/main.go      | 18 ++++++++++++++++++
 pkg/policy/validation.go | 30 ++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/cmd/kyverno/main.go b/cmd/kyverno/main.go
index 61013df4fb..4e4669d9f7 100644
--- a/cmd/kyverno/main.go
+++ b/cmd/kyverno/main.go
@@ -5,6 +5,8 @@ import (
 	"flag"
 	"time"
 
+	"k8s.io/client-go/discovery"
+
 	"github.com/golang/glog"
 	"github.com/nirmata/kyverno/pkg/checker"
 	kyvernoclient "github.com/nirmata/kyverno/pkg/client/clientset/versioned"
@@ -198,6 +200,22 @@ func main() {
 		glog.Fatalf("Failed registering Admission Webhooks: %v\n", err)
 	}
 
+	// OpenAPI document
+	// Getting openApi document from kubernetes and overriding default openapi document
+	restClient, err := discovery.NewDiscoveryClientForConfig(clientConfig)
+	if err != nil {
+		glog.Fatalf("Could not get rest client to get openApi doc: %v\n", err)
+	}
+
+	openApiDoc, err := restClient.RESTClient().Get().RequestURI("/openapi/v2").Do().Raw()
+	if err != nil {
+		glog.Fatalf("OpenApiDoc request failed: %v\n", err)
+	}
+
+	if err := policy.UseCustomOpenApiDocument(openApiDoc); err != nil {
+		glog.Fatalf("Could not set custom OpenApi document: %v\n", err)
+	}
+
 	// WEBHOOOK
 	// - https server to provide endpoints called based on rules defined in Mutating & Validation webhook configuration
 	// - reports the results based on the response from the policy engine:
diff --git a/pkg/policy/validation.go b/pkg/policy/validation.go
index f1b7ce36ce..310be7c74f 100644
--- a/pkg/policy/validation.go
+++ b/pkg/policy/validation.go
@@ -39,6 +39,36 @@ func init() {
 	}
 }
 
+func UseCustomOpenApiDocument(customDoc []byte) error {
+	var spec yaml.MapSlice
+	err := yaml.Unmarshal(customDoc, &spec)
+	if err != nil {
+		return err
+	}
+
+	validationGlobalState.document, err = openapi_v2.NewDocument(spec, compiler.NewContext("$root", nil))
+	if err != nil {
+		return err
+	}
+
+	validationGlobalState.definitions = make(map[string]*openapi_v2.Schema)
+	validationGlobalState.kindToDefinitionName = make(map[string]string)
+	for _, definition := range validationGlobalState.document.GetDefinitions().AdditionalProperties {
+		validationGlobalState.definitions[definition.GetName()] = definition.GetValue()
+		path := strings.Split(definition.GetName(), ".")
+		validationGlobalState.kindToDefinitionName[path[len(path)-1]] = definition.GetName()
+	}
+
+	validationGlobalState.models, err = proto.NewOpenAPIData(validationGlobalState.document)
+	if err != nil {
+		return err
+	}
+
+	validationGlobalState.isSet = true
+
+	return nil
+}
+
 func ValidatePolicyMutation(policy v1.ClusterPolicy) error {
 	if !validationGlobalState.isSet {
 		glog.V(4).Info("Cannot Validate policy: Validation global state not set")