Skip to content

Commit

Permalink
Add ConstraintTemplate v1
Browse files Browse the repository at this point in the history
We recently upgraded Constraint Framework to produce v1 CRDs when
creating Constraint kind CRDs.  This was in preparation for the release
of k8s 1.22, which removes the `v1beta1` CRD version.  See
open-policy-agent/gatekeeper#550 for more info.

As v1beta1 ConstraintTemplate did _not_ required any user-entered schema
information to be structural, transformation logic was implemented to
"structuralize" the user-inputted schema information as needed.

The new v1 ConstraintTemplate version purposefully does _no_
transformation, as it is meant to put the ConstraintTemplate creation
experience in line with that of a v1 CRDs.  Any schema information added
by the user is expected to be structural.  If non-structural schema info
is added, an error should be returned.

Signed-off-by: juliankatz <juliankatz@google.com>
  • Loading branch information
julianKatz committed Jun 9, 2021
1 parent 642ced2 commit dc2a818
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 179 deletions.
23 changes: 23 additions & 0 deletions constraint/pkg/apis/addtoscheme_templates_v1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package apis

import v1 "github.com/open-policy-agent/frameworks/constraint/pkg/apis/templates/v1"

func init() {
// Register the types with the Scheme so the components can map objects to GroupVersionKinds and back
AddToSchemes = append(AddToSchemes, v1.AddToScheme)
}
215 changes: 76 additions & 139 deletions constraint/pkg/apis/templates/v1/constrainttemplate_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,16 @@ limitations under the License.
package v1

import (
"reflect"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/onsi/gomega"
"github.com/open-policy-agent/frameworks/constraint/pkg/core/templates"
"golang.org/x/net/context"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
)

Expand Down Expand Up @@ -54,142 +59,74 @@ func TestStorageConstraintTemplate(t *testing.T) {
g.Expect(c.Get(context.TODO(), key, fetched)).To(gomega.HaveOccurred())
}

// func TestTypeConversion(t *testing.T) {
// scheme := runtime.NewScheme()
// if err := AddToScheme(scheme); err != nil {
// t.Fatalf("Could not add to scheme: %v", err)
// }
// versioned := &ConstraintTemplate{
// TypeMeta: metav1.TypeMeta{
// Kind: "ConstraintTemplate",
// APIVersion: "templates.gatekeeper.sh/v1beta1",
// },
// ObjectMeta: metav1.ObjectMeta{
// Name: "MustHaveMoreCats",
// },
// Spec: ConstraintTemplateSpec{
// CRD: CRD{
// Spec: CRDSpec{
// Names: Names{
// Kind: "MustHaveMoreCats",
// ShortNames: []string{"mhmc"},
// },
// Validation: &Validation{
// OpenAPIV3Schema: &apiextensionsv1beta1.JSONSchemaProps{
// Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
// "message": {
// Type: "string",
// },
// "labels": {
// Type: "array",
// Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{
// Schema: &apiextensionsv1beta1.JSONSchemaProps{
// Type: "object",
// Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
// "key": {Type: "string"},
// "allowedRegex": {Type: "string"},
// },
// },
// },
// },
// },
// },
// },
// },
// },
// Targets: []Target{
// {
// Target: "sometarget",
// Rego: `package hello ; violation[{"msg": "msg"}] { true }`,
// },
// },
// },
// }
// versionedCopy := versioned.DeepCopy()
// // Kind and API Version do not survive the conversion process
// versionedCopy.Kind = ""
// versionedCopy.APIVersion = ""
//
// unversioned := &templates.ConstraintTemplate{}
// if err := scheme.Convert(versioned, unversioned, nil); err != nil {
// t.Fatalf("Conversion error: %v", err)
// }
// recast := &ConstraintTemplate{}
// if err := scheme.Convert(unversioned, recast, nil); err != nil {
// t.Fatalf("Recast conversion error: %v", err)
// }
// }

// // function works, and also that it adds in the x-kubernetes-preserve-unknown-fields information
// // that we require for v1 CRD support
// func TestValidationVersionConversionAndTransformation(t *testing.T) {
// trueBool := true
// testCases := []struct {
// name string
// v *Validation
// exp *templates.Validation
// error bool
// }{
// {
// name: "Two deep properties",
// v: &Validation{
// OpenAPIV3Schema: &apiextensionsv1beta1.JSONSchemaProps{
// Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
// "message": {
// Type: "string",
// },
// "labels": {
// Type: "array",
// Items: &apiextensionsv1beta1.JSONSchemaPropsOrArray{
// Schema: &apiextensionsv1beta1.JSONSchemaProps{
// Type: "object",
// Properties: map[string]apiextensionsv1beta1.JSONSchemaProps{
// "key": {Type: "string"},
// "allowedRegex": {Type: "string"},
// },
// },
// },
// },
// },
// },
// },
// exp: &templates.Validation{
// OpenAPIV3Schema: &apiextensions.JSONSchemaProps{
// XPreserveUnknownFields: &trueBool,
// Properties: map[string]apiextensions.JSONSchemaProps{
// "message": {
// Type: "string",
// },
// "labels": {
// Type: "array",
// Items: &apiextensions.JSONSchemaPropsOrArray{
// Schema: &apiextensions.JSONSchemaProps{
// Type: "object",
// XPreserveUnknownFields: &trueBool,
// Properties: map[string]apiextensions.JSONSchemaProps{
// "key": {Type: "string"},
// "allowedRegex": {Type: "string"},
// },
// },
// },
// },
// },
// },
// },
// error: false,
// },
// }
//
// for _, tc := range testCases {
// t.Run(tc.name, func(t *testing.T) {
// out := &templates.Validation{}
// if err := Convert_v1beta1_Validation_To_templates_Validation(tc.v, out, nil); err != nil {
// t.Fatalf("Conversion error: %v", err)
// }
//
// if !reflect.DeepEqual(out, tc.exp) {
// t.Fatalf("Conversion does not match expected result: %v", cmp.Diff(out, tc.exp))
// }
// })
// }
// }
func TestTypeConversion(t *testing.T) {
scheme := runtime.NewScheme()
if err := AddToScheme(scheme); err != nil {
t.Fatalf("Could not add to scheme: %v", err)
}
versioned := &ConstraintTemplate{
TypeMeta: metav1.TypeMeta{
Kind: "ConstraintTemplate",
APIVersion: "templates.gatekeeper.sh/v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "MustHaveMoreCats",
},
Spec: ConstraintTemplateSpec{
CRD: CRD{
Spec: CRDSpec{
Names: Names{
Kind: "MustHaveMoreCats",
ShortNames: []string{"mhmc"},
},
Validation: &Validation{
OpenAPIV3Schema: &apiextensionsv1.JSONSchemaProps{
Type: "object",
Properties: map[string]apiextensionsv1.JSONSchemaProps{
"message": {
Type: "string",
},
"labels": {
Type: "array",
Items: &apiextensionsv1.JSONSchemaPropsOrArray{
Schema: &apiextensionsv1.JSONSchemaProps{
Type: "object",
Properties: map[string]apiextensionsv1.JSONSchemaProps{
"key": {Type: "string"},
"allowedRegex": {Type: "string"},
},
},
},
},
},
},
},
},
},
Targets: []Target{
{
Target: "sometarget",
Rego: `package hello ; violation[{"msg": "msg"}] { true }`,
},
},
},
}
versionedCopy := versioned.DeepCopy()
// Kind and API Version do not survive the conversion process
versionedCopy.Kind = ""
versionedCopy.APIVersion = ""

unversioned := &templates.ConstraintTemplate{}
if err := scheme.Convert(versioned, unversioned, nil); err != nil {
t.Fatalf("Conversion error: %v", err)
}

recast := &ConstraintTemplate{}
if err := scheme.Convert(unversioned, recast, nil); err != nil {
t.Fatalf("Recast conversion error: %v", err)
}

if !reflect.DeepEqual(versionedCopy, recast) {
t.Fatalf("Unexpected template difference. Diff: %v", cmp.Diff(versionedCopy, recast))
}
}
36 changes: 0 additions & 36 deletions constraint/pkg/apis/templates/v1/conversion.go

This file was deleted.

27 changes: 23 additions & 4 deletions constraint/pkg/apis/templates/v1/zz_generated.conversion.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit dc2a818

Please sign in to comment.