Skip to content

restored api-conversion implementation#4075

Open
olamilekan000 wants to merge 1 commit into
kcp-dev:mainfrom
olamilekan000:re-implemt-api-conversions
Open

restored api-conversion implementation#4075
olamilekan000 wants to merge 1 commit into
kcp-dev:mainfrom
olamilekan000:re-implemt-api-conversions

Conversation

@olamilekan000
Copy link
Copy Markdown
Contributor

@olamilekan000 olamilekan000 commented Apr 27, 2026

Summary

changes restores the  APIConversion  implementation

Screenshot 2026-04-27 at 19 44 51
Screenshot 2026-04-27 at 19 45 22
Screenshot 2026-04-27 at 17 53 16
Screenshot 2026-04-27 at 19 17 27
Screenshot 2026-04-27 at 19 18 10

What Type of PR Is This?

/kind feature

Related Issue(s)

Fixes 3427

Release Notes

added APIConversion implementation

@kcp-ci-bot kcp-ci-bot added release-note Denotes a PR that will be considered when it comes time to generate release notes. dco-signoff: yes Indicates the PR's author has signed the DCO. kind/feature Categorizes issue or PR as related to a new feature. kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API labels Apr 27, 2026
@kcp-ci-bot
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign embik for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kcp-ci-bot kcp-ci-bot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Apr 27, 2026
@olamilekan000 olamilekan000 force-pushed the re-implemt-api-conversions branch 2 times, most recently from 262acd0 to 6d14148 Compare April 27, 2026 17:22
@olamilekan000 olamilekan000 requested a review from mjudeikis April 27, 2026 17:24
@olamilekan000
Copy link
Copy Markdown
Contributor Author

olamilekan000 commented Apr 27, 2026

While testing the API conversions, the conversion from one api to the other was failing for standard local CRDs because the admission plugin strictly required an APIResourceSchema to exist. Since pure local CRDs don't generate those schemas (it has to be generated through apibinding and apiexport), the apiconversion webhook was rejecting them with a NotFound error. To fix this, I added a provision in the admission validator using the dynamic client to check if a matching CustomResourceDefinition exists locally instead. If it does, we gracefully bypass the strict schema mapping and let the CEL interpreter handle the validation at runtime.

@olamilekan000 olamilekan000 force-pushed the re-implemt-api-conversions branch 3 times, most recently from cfcdaf9 to 6165992 Compare April 27, 2026 19:10
Copy link
Copy Markdown
Contributor

@mjudeikis mjudeikis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How much of this is original implementation and how much is your change? I feel like original implementation had few corners cut :/ Tried to leave few comments but I suspect there will be more

Comment thread pkg/conversion/deferred_converter.go Outdated
defer f.lock.Unlock()

if f.delegate != nil {
return f.delegate, nil
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we update APIResources post create (but dont update CRD) - Think this will return stale converter?

The problem in plain terms: once the first conversion happens, f.delegate is populated with a *Converter whose CEL programs were compiled against whatever APIConversion existed at that moment. There's no read of the lister on subsequent calls, no resourceVersion check, no event handler — so a kubectl edit apiconversion ... does nothing for already-running converters in this process.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to track APIConversion RV to see if converted is still valid.

// to use pure local CRDs with the CEL engine. This fallback natively inspects the local Virtual Workspace
// for a raw CustomResourceDefinition matching the conversion rule.
if crdErr == nil {
klog.FromContext(ctx).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this would allow not to skip?

if crdErr == nil {
    crdU, _ := o.dynamicClient.Cluster(...).Resource(gvr).Get(...)   // already retrieved above so we have the object already
    crd := &apiextensionsv1.CustomResourceDefinition{}
    if err := runtime.DefaultUnstructuredConverter.FromUnstructured(crdU.Object, crd); err != nil {
        return admission.NewForbidden(a, fmt.Errorf("decoding CRD: %w", err))
    }
    structuralSchemas, err := buildStructuralSchemasFromCRD(crd.Spec.Versions)
    if err != nil {
        return admission.NewForbidden(a, err)
    }
    apiConversion := &apisv1alpha1.APIConversion{}
    if err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.Object, apiConversion); err != nil {
        return fmt.Errorf("failed to convert unstructured to APIConversion: %w", err)
    }
    if _, err := conversion.Compile(apiConversion, structuralSchemas); err != nil {
        return fmt.Errorf("error compiling conversion rules: %w", err)
    }
    return nil
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so we don't need for the validation?

Comment thread pkg/server/config.go Outdated
if err != nil {
return nil, err
}
_ = authInfoResolver
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we do this? It's not used?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this also be caught by the linter?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was trying to retain some of the changes from the old PR, hence why I left it that way. I think it can be removed

Comment thread pkg/cache/server/config.go Outdated
ConversionFactory: &nopCRConversionFactory{},
ConversionFactory: kcpconversion.NewCRConverterFactory(
c.KcpSharedInformerFactory.Apis().V1alpha1().APIConversions(),
5*time.Second,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

opts.Extra.ConversionCELTransformationTimeout ?

Comment thread pkg/conversion/conversion_rules.go Outdated
func compileRule(rulePath *field.Path, rule apisv1alpha1.APIConversionRule, schema *structuralschema.Structural) (*CompiledRule, error) {
// if rule.Field starts with a ".", such as .spec.fieldName, strip the leading "."
fromPath := rule.Field
if fromPath[0] == '.' {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is called from Compile, and from NewConverter, hence toPath and fromPath never checked for len

Comment thread pkg/conversion/deferred_converter.go Outdated
if errors.IsNotFound(err) {
switch f.crd.Spec.Conversion.Strategy {
case apiextensionsv1.NoneConverter:
return conversion.NewNOPConverter(), nil
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should be setting f.delegate = conversion.NewNOPConverter() else this code path will be hot on every request

@@ -0,0 +1,83 @@
metadata:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this even used?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's used in the unit tests.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes

@olamilekan000
Copy link
Copy Markdown
Contributor Author

How much of this is original implementation and how much is your change? I feel like original implementation had few corners cut :/ Tried to leave few comments but I suspect there will be more

Almost all is from the original PR. I only refactored the CEL flow to use EnvSet and StoredExpressionsEnv, and also updated the admission plugin with that dynamic client fallback so it also handles local CRDs instead of just looking for APIResourceSchemas.

Copy link
Copy Markdown
Member

@ntnn ntnn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this skips the .ConvertToVersion that is implemented for kcp's native types, or?
The old conversion webhook in pkg/server (that did this conversion) should be refactored into the new conversion factory.

Comment thread pkg/server/config.go Outdated
if err != nil {
return nil, err
}
_ = authInfoResolver
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this also be caught by the linter?

@@ -0,0 +1,83 @@
metadata:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's used in the unit tests.

Comment thread pkg/conversion/deferred_converter.go Outdated
@ntnn ntnn added this to tbd May 4, 2026
@ntnn ntnn moved this to Reviewing in tbd May 4, 2026
@olamilekan000 olamilekan000 force-pushed the re-implemt-api-conversions branch from 6165992 to a89c072 Compare May 6, 2026 00:12
@olamilekan000 olamilekan000 requested review from mjudeikis and ntnn May 6, 2026 00:13
Signed-off-by: olalekan odukoya <odukoyaonline@gmail.com>
@olamilekan000 olamilekan000 force-pushed the re-implemt-api-conversions branch from a89c072 to b76ced7 Compare May 6, 2026 00:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dco-signoff: yes Indicates the PR's author has signed the DCO. kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API kind/feature Categorizes issue or PR as related to a new feature. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feature: re-implement APIConversions

4 participants