Skip to content

Commit

Permalink
Merge pull request #3044 from justinsb/multiple_crd_versions_2
Browse files Browse the repository at this point in the history
chore: update client generation to generate multiple CRD versions
  • Loading branch information
google-oss-prow[bot] authored Nov 1, 2024
2 parents b090f61 + 52c9171 commit 9ddb92e
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 41 deletions.
14 changes: 7 additions & 7 deletions pkg/crd/fielddesc/fielddesc.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ type FieldDescription struct {
AdditionalProperties []FieldDescription
}

func GetSpecDescription(crd *apiextensions.CustomResourceDefinition) FieldDescription {
crdDesc := getCRDFieldDescription(crd)
func GetSpecDescription(crd *apiextensions.CustomResourceDefinition, version string) FieldDescription {
crdDesc := getCRDFieldDescription(crd, version)
spec, ok := getChildFieldDesc(crdDesc, "spec")
if !ok {
// this occurs when a CRD has an empty spec, such as ComputeSharedVPCHostProject
Expand All @@ -56,9 +56,9 @@ func GetSpecDescription(crd *apiextensions.CustomResourceDefinition) FieldDescri
return *spec
}

func GetStatusDescription(crd *apiextensions.CustomResourceDefinition) (FieldDescription, error) {
func GetStatusDescription(crd *apiextensions.CustomResourceDefinition, version string) (FieldDescription, error) {
statusPropertyName := "status"
crdDesc := getCRDFieldDescription(crd)
crdDesc := getCRDFieldDescription(crd, version)
status, ok := getChildFieldDesc(crdDesc, statusPropertyName)
if !ok {
return FieldDescription{}, fmt.Errorf("unexpected missing '%v' on crd '%v'", statusPropertyName, crd.Spec.Names.Kind)
Expand All @@ -75,13 +75,13 @@ func getChildFieldDesc(description FieldDescription, childName string) (*FieldDe
return nil, false
}

func getCRDFieldDescription(crd *apiextensions.CustomResourceDefinition) FieldDescription {
func getCRDFieldDescription(crd *apiextensions.CustomResourceDefinition, version string) FieldDescription {
customResourceDesc := FieldDescription{
Type: "object",
RequirementLevel: RequiredRequirementLevel,
}
schema := k8s.GetOpenAPIV3SchemaFromCRD(crd)
return propsToDescription(*schema, customResourceDesc, "", true)
crdVersionDefinition := k8s.GetCRDVersionDefinition(crd, version)
return propsToDescription(*crdVersionDefinition.Schema.OpenAPIV3Schema, customResourceDesc, "", true)
}

func propsToDescription(props apiextensions.JSONSchemaProps, parent FieldDescription, name string, required bool) FieldDescription {
Expand Down
28 changes: 16 additions & 12 deletions pkg/crd/fielddesc/fielddesc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/crd/crdloader"
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/crd/fielddesc"
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s"
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test"

"gopkg.in/yaml.v2"
Expand All @@ -33,14 +34,16 @@ func TestAllCRDsGetSpecAndStatusDescription(t *testing.T) {
t.Fatalf("error loading crds: %v", err)
}
for _, crd := range crds {
fd := fielddesc.GetSpecDescription(&crd)
expectedType := "object"
if fd.Type != expectedType {
t.Fatalf("unexpected type: got '%v', want' %v'", fd.Type, expectedType)
}
fd = getStatusDescription(t, &crd)
if fd.Type != expectedType {
t.Fatalf("unexpected type: got '%v', want' %v'", fd.Type, expectedType)
for _, version := range crd.Spec.Versions {
fd := fielddesc.GetSpecDescription(&crd, version.Name)
expectedType := "object"
if fd.Type != expectedType {
t.Fatalf("unexpected type: got '%v', want' %v'", fd.Type, expectedType)
}
fd = getStatusDescription(t, &crd, version.Name)
if fd.Type != expectedType {
t.Fatalf("unexpected type: got '%v', want' %v'", fd.Type, expectedType)
}
}
}
}
Expand All @@ -58,16 +61,17 @@ func testOutputMatches(t *testing.T, resourceKind string) {
if err != nil {
t.Fatalf("error getting crd '%v': %v", resourceKind, err)
}
fd := fielddesc.GetSpecDescription(crd)
version := k8s.PreferredVersion(crd)
fd := fielddesc.GetSpecDescription(crd, version.Name)
fieldDescYAML := fieldDescToYAML(t, fd)
test.CompareGoldenFile(t, fmt.Sprintf("testdata/%v-spec.golden.yaml", strings.ToLower(resourceKind)), string(fieldDescYAML), test.IgnoreLeadingComments)
fd = getStatusDescription(t, crd)
fd = getStatusDescription(t, crd, version.Name)
fieldDescYAML = fieldDescToYAML(t, fd)
test.CompareGoldenFile(t, fmt.Sprintf("testdata/%v-status.golden.yaml", strings.ToLower(resourceKind)), string(fieldDescYAML), test.IgnoreLeadingComments)
}

func getStatusDescription(t *testing.T, crd *apiextensions.CustomResourceDefinition) fielddesc.FieldDescription {
fd, err := fielddesc.GetStatusDescription(crd)
func getStatusDescription(t *testing.T, crd *apiextensions.CustomResourceDefinition, version string) fielddesc.FieldDescription {
fd, err := fielddesc.GetStatusDescription(crd, version)
if err != nil {
t.Fatalf("error getting status description")
}
Expand Down
11 changes: 10 additions & 1 deletion pkg/k8s/crds.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,17 @@ func GetVersionFromCRD(crd *apiextensions.CustomResourceDefinition) string {
return PreferredVersion(crd).Name
}

func GetCRDVersionDefinition(crd *apiextensions.CustomResourceDefinition, version string) *apiextensions.CustomResourceDefinitionVersion {
for _, v := range crd.Spec.Versions {
if v.Name == version {
return &v
}
}
panic(fmt.Sprintf("version %q not found", version))
}

// Deprecated: only returns the preferred version
func GetOpenAPIV3SchemaFromCRD(crd *apiextensions.CustomResourceDefinition) *apiextensions.JSONSchemaProps {
panicIfNoVersionPresent(crd)
// Currently KCC CRDs only support one version.
return PreferredVersion(crd).Schema.OpenAPIV3Schema
}
Expand Down
48 changes: 31 additions & 17 deletions scripts/generate-go-crd-clients/generate-types-file.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s"
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/util/repo"
apiextensions "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/klog/v2"
)

Expand Down Expand Up @@ -74,7 +75,7 @@ type svkMap struct {
}

func main() {
resources := make(map[string]*resourceDefinition)
var resources []*resourceDefinition
registerKinds := make(map[string]*svkMap)
crdsDir := repo.GetCRDsPath()
crdsPath, err := filepath.Abs(crdsDir)
Expand All @@ -87,8 +88,7 @@ func main() {
}

for _, crdFile := range crdFiles {
fileName := strings.TrimSuffix(crdFile.Name(), ".yaml")
resources[fileName] = constructResourceDefinition(crdsPath, crdFile.Name())
resources = append(resources, constructResourceDefinitions(crdsPath, crdFile.Name())...)
}

for _, rd := range resources {
Expand Down Expand Up @@ -261,8 +261,7 @@ func checkAndCreateFolder(dir string) {
}
}

func constructResourceDefinition(crdsPath, crdFile string) *resourceDefinition {
r := &resourceDefinition{}
func constructResourceDefinitions(crdsPath, crdFile string) []*resourceDefinition {
crdFilePath, err := filepath.Abs(path.Join(crdsPath, crdFile))
if err != nil {
log.Fatalf("error getting the absolute representation of path for directory '%v': %v", crdFile, err)
Expand All @@ -272,25 +271,40 @@ func constructResourceDefinition(crdsPath, crdFile string) *resourceDefinition {
log.Fatalf("error loading crd from filepath %v: %v", crdFilePath, err)
}

r.CRD = crd
r.Name = crd.Spec.Names.Kind
if err = buildFieldProperties(r, crd); err != nil {
log.Fatalf("error building field properties for %v: %v", r.Name, err)
versionNames := sets.NewString()
for _, crdVersion := range crd.Spec.Versions {
versionNames.Insert(crdVersion.Name)
}
r.Service = strings.TrimSuffix(crd.Spec.Group, k8s.APIDomainSuffix)
r.Kind = strings.ToLower(crd.Spec.Names.Kind)

// TODO: Should we handle multiple versions?
r.Version = k8s.PreferredVersion(crd)
return r
var resources []*resourceDefinition
for _, versionName := range versionNames.List() {
// Don't generate alpha version if we have a beta
if versionName == "v1alpha1" && versionNames.Has("v1beta1") {
continue
}
crdVersionDefinition := k8s.GetCRDVersionDefinition(crd, versionName)

r := &resourceDefinition{}
r.CRD = crd
r.Name = crd.Spec.Names.Kind
if err = buildFieldProperties(r, crd, crdVersionDefinition.Name); err != nil {
log.Fatalf("error building field properties for %v: %v", r.Name, err)
}
r.Service = strings.TrimSuffix(crd.Spec.Group, k8s.APIDomainSuffix)
r.Kind = strings.ToLower(crd.Spec.Names.Kind)

r.Version = crdVersionDefinition
resources = append(resources, r)
}
return resources
}

func buildFieldProperties(r *resourceDefinition, crd *apiextensions.CustomResourceDefinition) error {
specDesc := fielddesc.GetSpecDescription(crd)
func buildFieldProperties(r *resourceDefinition, crd *apiextensions.CustomResourceDefinition, version string) error {
specDesc := fielddesc.GetSpecDescription(crd, version)
specDescriptions := dropRootAndFlattenChildrenDescriptions(specDesc)
r.SpecNestedStructs = make(map[string][]*fieldProperties)
organizeSpecFieldDescriptions(specDescriptions, r)
statusDesc, err := fielddesc.GetStatusDescription(crd)
statusDesc, err := fielddesc.GetStatusDescription(crd, version)
if err != nil {
return fmt.Errorf("error getting status descriptions: %w", err)
}
Expand Down
8 changes: 4 additions & 4 deletions scripts/generate-google3-docs/resource-reference/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ func constructResourceForGVK(gvk schema.GroupVersionKind, smLoader *servicemappi
return nil, fmt.Errorf("error converting status to YAML: %w", err)
}
r.Status = string(statusYaml)
if err = buildFieldDescriptions(r, crd); err != nil {
if err = buildFieldDescriptions(r, crd, gvk.Version); err != nil {
return nil, fmt.Errorf("buildFieldDescriptions: %w", err)
}
r.DefaultReconcileInterval = uint32(reconciliationinterval.MeanReconcileReenqueuePeriod(gvk, smLoader, serviceMetadataLoader).Seconds())
Expand Down Expand Up @@ -545,12 +545,12 @@ func stripHeader(sample string) string {
return strings.Trim(res, "\n")
}

func buildFieldDescriptions(r *resource, crd *apiextensions.CustomResourceDefinition) error {
specDesc := fielddesc.GetSpecDescription(crd)
func buildFieldDescriptions(r *resource, crd *apiextensions.CustomResourceDefinition, version string) error {
specDesc := fielddesc.GetSpecDescription(crd, version)
specDescriptions := dropRootAndFlattenChildrenDescriptions(specDesc)
r.SpecDescriptions = fieldDescriptionsToHumanReadable(specDescriptions)
r.SpecDescriptionContainsRequiredIfParentPresent = atLeastOneFieldHasRequiredWhenParentPresentRequirementLevel(specDesc)
statusDesc, err := fielddesc.GetStatusDescription(crd)
statusDesc, err := fielddesc.GetStatusDescription(crd, version)
if err != nil {
return fmt.Errorf("error getting status descriptions: %w", err)
}
Expand Down

0 comments on commit 9ddb92e

Please sign in to comment.