-
Notifications
You must be signed in to change notification settings - Fork 15
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
Revamp schemagen logic #143
Conversation
bad0c99
to
06dfe8c
Compare
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #143 +/- ##
==========================================
- Coverage 79.45% 78.10% -1.36%
==========================================
Files 17 17
Lines 740 708 -32
==========================================
- Hits 588 553 -35
+ Misses 88 87 -1
- Partials 64 68 +4 ☔ View full report in Codecov by Sentry. |
11fff64
to
614c8a6
Compare
@@ -7,6 +7,7 @@ import ( | |||
"io" | |||
"strings" | |||
|
|||
extensionv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes in this file is related to switch from storing an unstructured object to a typed CRD object.
@@ -27,27 +26,15 @@ const nodejsMetaPath = "meta/v1.ts" | |||
const nodejsMetaFile = `import * as k8s from "@pulumi/kubernetes"; | |||
|
|||
export type ObjectMeta = k8s.types.input.meta.v1.ObjectMeta; | |||
export type ObjectMetaPatch = k8s.types.input.meta.v1.ObjectMetaPatch; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We now generate Patch variants so need to update our imports to address this.
@@ -16,18 +16,26 @@ package codegen | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most of the schemagen changes occur here. This is where we flatten OpenAPI specs.
pkg.Name = oldName | ||
delete(pkg.Language, langName) | ||
|
||
buffers = map[string]*bytes.Buffer{} | ||
for path, code := range files { | ||
newPath, _ := filepath.Rel(name, path) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixing Go code generated in the wrong folder. See #89
Also needed to ensure tests can find the right folder to compile generated Go code.
@@ -15,21 +15,30 @@ | |||
package codegen |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Integrating with p-k schemagen to generate the package spec.
614c8a6
to
2c843f7
Compare
t.Run(lang, func(t *testing.T) { | ||
t.Parallel() | ||
execCrd2Pulumi(t, lang, tt.url, nil) | ||
if lang == "dotnet" && (tt.name == "CertManager" || tt.name == "GKEManagedCerts") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GKEManagedCerts is working for dotnet locally and in a separate docker container I have. I have also manually validated it, with a Pulumi program that can create these CRs. I am skipping for now to unblock this PR while I hunt down what's happening.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting - how many files does it generate? I wonder if it's got some nested types that are functionally identical but are now getting treated as unique top-level things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is beautiful!
// Schemas represents a mapping from each version in the `spec.versions` | ||
// list to its corresponding `openAPIV3Schema` field in the CRD YAML | ||
Schemas map[string]map[string]any | ||
Schemas map[string]spec.Swagger |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does k8s just happen to use older type names for back-compact? I guess it probably pre-dates the Swagger→OpenAPI change so it would make sense. I just want to double check we're using whatever the most recent/relevant logic is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Newer k8 versions provide both v2 and v3 specs, so it might be nice to upgrade to v3 specs in the future for p-k schemagen. Also should note that p-k merges schemas from a range of Kubernetes versions, so we may not want to do this in the short term unless we drop support for these older versions that do not serve a v3 spec.
// flattenOpenAPI recursively finds all nested objects in the OpenAPI spec and flattens them into a single object as definitions. | ||
func flattenOpenAPI(sw *spec.Swagger) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great -- the surface area for potential issues is signifcantly smaller. If we have bugs they'll almost certainly either live in this flattening logic or the upstream p-p or p-k codegen.
return currSpec, nil | ||
} | ||
|
||
func sanitizeReferenceName(fieldName string) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this basically responsible for ensuring the ref name is a valid token in all of our target languages?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes! Previously, in crd2pulumi, we need to do this in a number of locations which resulted in harder to maintain code, and the bugs we saw. For package name sanitization, that resides in the p-k schemagen logic.
t.Run(lang, func(t *testing.T) { | ||
t.Parallel() | ||
execCrd2Pulumi(t, lang, tt.url, nil) | ||
if lang == "dotnet" && (tt.name == "CertManager" || tt.name == "GKEManagedCerts") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interesting - how many files does it generate? I wonder if it's got some nested types that are functionally identical but are now getting treated as unique top-level things.
b28b757
to
e13c547
Compare
Pulumi Kubernetes provider has robust schemagen logic that is immune to the bugs identified in crd2pulumi. To enable interoperability, we need to handle the conversion of CRD manifests to their OpenAPI v2 equivalents. remove extra generated kubernetes types An OpenAPI spec generated from a CRD manifest will contain additional Kubernetes meta types (statuses etc). This commit removes those extra generated files/resources to debloat the final output.
Our mocked CRDs for testing purposes were very minimal and not completely valid since previous codegen logic only needed a subset of fields. As we have updated our implementation to do codegen on an OpenAPI spec, we need fully formed CRD manifests for this conversion to occur.
e13c547
to
c80d232
Compare
This PR has been shipped in release v1.5.0. |
All of our languages except NodeJS use `SchemaPackageWithObjectMetaType`. As a result, Node exposes only input types for object metadata which makes it awkward to consume downstream. I'm assuming #143 didn't change this for backwards-compatibility reasons, or maybe it was overlooked. I _think_ it is safe to continue generating the `ObjectMeta` type alias (in case users are importing it) but use the input/output types (matching the upstream k8s types) on resources. Edit: > // schemaPackageWithObjectMetaType is the Pulumi schema package used to > // generate code for languages that need an ObjectMeta type (Python, Go, and .NET) So this seems intentional. For whatever reason, using this with Node has the effect of generating input/output types matching upstream's types, which seems desirable. Fixes #158
Proposed Changes:
This PR significantly enhances the underlying code generation logic by leveraging the Pulumi Kubernetes provider’s advanced schema generation capabilities. The Kubernetes provider’s schema generation has been thoroughly tested over multiple Kubernetes version releases, and used in production environments, making it a robust solution. By adopting this approach, we can efficiently resolve several codegen related bugs in
crd2pulumi
without needing numerous fragile targeted fixes within the current codebase.Technical Changes
User Facing Changes
This PR maintains backward compatibility as much as possible, though some behavior changes are expected:
--goPath
flag if provided, ensuring code is generated at the specified path, aligning Go with other languages in terms of folder structure.Related Issues
Resolves #142, resolves #141, resolves #115, resolves #113, resolves #110, resolves #104, resolves #103, resolves #100, resolves #97, resolves #89, resolves #70, resolves #49, resolves #34, resolves #30, resolves #26, resolves #21, resolves #111, resolves #50