Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cherry Pick #1218 [Validation generation] #1228

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions pkg/apis/svcneg/v1beta1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
// ServiceNetworkEndpointGroup represents a group of Network Endpoint Groups associated with a service.

// +genclient
// +genclient:noStatus
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
//
// +k8s:openapi-gen=true
Expand All @@ -37,15 +36,19 @@ type ServiceNetworkEndpointGroup struct {
}

// ServiceNetworkEndpointGroupSpec is the spec for a ServiceNetworkEndpointGroup resource
// +k8s:openapi-gen=true
type ServiceNetworkEndpointGroupSpec struct{}

// ServiceNetworkEndpointGroupStatus is the status for a ServiceNetworkEndpointGroup resource
// +k8s:openapi-gen=true
type ServiceNetworkEndpointGroupStatus struct {
// +listType=map
// +listMapKey=id
NetworkEndpointGroups []NegObjectReference `json:"networkEndpointGroups,omitempty"`

// Last time the NEG syncer syncs associated NEGs.
// +optional
// +listType=map
// +listMapKey=type
Conditions []Condition `json:"conditions,omitempty"`

// Last time the NEG syncer syncs associated NEGs.
Expand All @@ -54,9 +57,10 @@ type ServiceNetworkEndpointGroupStatus struct {
}

// NegObjectReference is the object reference to the NEG resource in GCE
// +k8s:openapi-gen=true
type NegObjectReference struct {
// The unique identifier for the NEG resource in GCE API.
Id uint64 `json:"id,omitempty,string"`
Id string `json:"id,omitempty"`

// SelfLink is the GCE Server-defined fully-qualified URL for the GCE NEG resource
SelfLink string `json:"selfLink,omitempty"`
Expand All @@ -66,6 +70,7 @@ type NegObjectReference struct {
NetworkEndpointType NetworkEndpointType `json:"networkEndpointType,omitempty"`
}

// +k8s:openapi-gen=true
type NetworkEndpointType string

const (
Expand All @@ -76,6 +81,7 @@ const (

// TODO: Replace Condition with standard Condition
// NegCondition contains details for the current condition of this NEG.
// +k8s:openapi-gen=true
type Condition struct {
// Type is the type of the condition.
// +required
Expand Down
152 changes: 148 additions & 4 deletions pkg/apis/svcneg/v1beta1/zz_generated.openapi.go

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

42 changes: 40 additions & 2 deletions pkg/crd/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,22 @@ import (

spec "github.com/go-openapi/spec"
apiextensionsv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kube-openapi/pkg/common"
)

var metav1OpenAPISpec = map[string]common.OpenAPIDefinition{
"k8s.io/apimachinery/pkg/apis/meta/v1.Time": common.OpenAPIDefinition{
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Type: metav1.Time{}.OpenAPISchemaType(),
Format: metav1.Time{}.OpenAPISchemaFormat(),
Nullable: true,
},
},
},
}

// validation returns a validation specification based on OpenAPI schema's.
func validation(typeSource string, fn common.GetOpenAPIDefinitions) (*apiextensionsv1beta1.CustomResourceValidation, error) {
openapiSpec := fn(spec.MustCreateRef)
Expand All @@ -47,10 +60,21 @@ func validation(typeSource string, fn common.GetOpenAPIDefinitions) (*apiextensi
func condenseSchema(currentSchema spec.Schema, openapiSpec map[string]common.OpenAPIDefinition) spec.Schema {
currentSchemaProperties := currentSchema.SchemaProps.Properties
for property, propertySchema := range currentSchemaProperties {

if propertySchema.SchemaProps.Type.Contains("array") {
ref := propertySchema.Items.Schema.SchemaProps.Ref.String()
if ref != "" {
referencedSchema := getReferenceSchema(ref, propertySchema, openapiSpec)
condensedRefSchema := condenseSchema(referencedSchema, openapiSpec)
propertySchema.SchemaProps.Items.Schema.SchemaProps = condensedRefSchema.SchemaProps
currentSchemaProperties[property] = propertySchema
}
continue
}

ref := propertySchema.SchemaProps.Ref.String()
if ref != "" {
referencedSchema := openapiSpec[ref].Schema
referencedSchema.SchemaProps.Type = spec.StringOrArray{"object"}
referencedSchema := getReferenceSchema(ref, propertySchema, openapiSpec)
propertySchema.SchemaProps = referencedSchema.SchemaProps
currentSchemaProperties[property] = propertySchema
condenseSchema(propertySchema, openapiSpec)
Expand All @@ -60,3 +84,17 @@ func condenseSchema(currentSchema spec.Schema, openapiSpec map[string]common.Ope
currentSchema.AdditionalProperties = nil
return currentSchema
}

func getReferenceSchema(ref string, propertySchema spec.Schema, openapiSpec map[string]common.OpenAPIDefinition) spec.Schema {
var referencedSchema spec.Schema
// Check if reference exists in existing metav1 specs, otherwise look in provided openapi specs
if refDef, ok := metav1OpenAPISpec[ref]; ok {
referencedSchema = refDef.Schema
referencedSchema.SchemaProps.Description = propertySchema.SchemaProps.Description
} else {
// If ref doesn't exist in either map, this will generate standard object one
referencedSchema = openapiSpec[ref].Schema
referencedSchema.SchemaProps.Type = spec.StringOrArray{"object"}
}
return referencedSchema
}
50 changes: 50 additions & 0 deletions pkg/crd/validation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,23 @@ var (
Ref: spec.MustCreateRef("Baz"),
},
},
"quuxs": {
SchemaProps: spec.SchemaProps{
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Ref: spec.MustCreateRef("Quux"),
},
},
},
},
},
"ts": {
SchemaProps: spec.SchemaProps{
Ref: spec.MustCreateRef("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
},
},
},
},
},
Expand Down Expand Up @@ -88,6 +105,20 @@ var (
},
},
},
"Quux": {
Schema: spec.Schema{
SchemaProps: spec.SchemaProps{
Description: "Quux",
Properties: map[string]spec.Schema{
"qux": {
SchemaProps: spec.SchemaProps{
Ref: spec.MustCreateRef("Qux"),
},
},
},
},
},
},
}
)

Expand All @@ -105,4 +136,23 @@ func TestCondenseSchema(t *testing.T) {
if condensedBarSchema.SchemaProps.Properties["qux"].SchemaProps.Description != "Qux" {
t.Errorf("Expected Foo's schema for Bar to contain the Description for Qux.")
}
if condensedFooSchema.SchemaProps.Properties["quuxs"].SchemaProps.Items.Schema.SchemaProps.Description != "Quux" {
t.Errorf("Expected Foo's schema to contain the Description for Quux.")
}

condensedQuuxSchema := condensedFooSchema.SchemaProps.Properties["quuxs"].SchemaProps.Items.Schema
if condensedQuuxSchema.SchemaProps.Properties["qux"].Description != "Qux" {
t.Errorf("Expected Foo's schema to contain the Description for Qux.")
}

tsProp := condensedFooSchema.SchemaProps.Properties["ts"]
if !tsProp.SchemaProps.Type.Contains("string") {
t.Errorf("Expected Foo's ts property to have type string")
}
if tsProp.SchemaProps.Format != "date-time" {
t.Errorf("Expected Foo's ts property to have format 'date-time'")
}
if !tsProp.SchemaProps.Nullable {
t.Errorf("Expected Foo's ts property to be Nullable")
}
}
2 changes: 1 addition & 1 deletion pkg/neg/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1261,7 +1261,7 @@ func getNegObjectRefs(t *testing.T, cloud negtypes.NetworkEndpointGroupCloud, zo
continue
}
negRefs = append(negRefs, negv1beta1.NegObjectReference{
Id: neg.Id,
Id: fmt.Sprint(neg.Id),
SelfLink: neg.SelfLink,
NetworkEndpointType: negv1beta1.NetworkEndpointType(neg.NetworkEndpointType),
})
Expand Down
6 changes: 3 additions & 3 deletions pkg/neg/syncers/transaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1078,12 +1078,12 @@ func TestUpdateStatus(t *testing.T) {
testNegType := negtypes.VmIpPortEndpointType
testNegRefs := []negv1beta1.NegObjectReference{
negv1beta1.NegObjectReference{
Id: 0,
Id: "0",
SelfLink: "self-link-0",
NetworkEndpointType: "neg-type-0",
},
negv1beta1.NegObjectReference{
Id: 1,
Id: "1",
SelfLink: "self-link-1",
NetworkEndpointType: "neg-type-1",
},
Expand Down Expand Up @@ -1406,7 +1406,7 @@ func negObjectReferences(negs map[*meta.Key]*composite.NetworkEndpointGroup) map
negObjs := make(map[string]negv1beta1.NegObjectReference)
for _, neg := range negs {
negObjs[neg.SelfLink] = negv1beta1.NegObjectReference{
Id: neg.Id,
Id: fmt.Sprint(neg.Id),
SelfLink: neg.SelfLink,
NetworkEndpointType: negv1beta1.NetworkEndpointType(neg.NetworkEndpointType),
}
Expand Down
Loading