restored api-conversion implementation#4075
Conversation
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
262acd0 to
6d14148
Compare
|
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 |
cfcdaf9 to
6165992
Compare
mjudeikis
left a comment
There was a problem hiding this comment.
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
| defer f.lock.Unlock() | ||
|
|
||
| if f.delegate != nil { | ||
| return f.delegate, nil |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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). |
There was a problem hiding this comment.
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
}
There was a problem hiding this comment.
so we don't need for the validation?
| if err != nil { | ||
| return nil, err | ||
| } | ||
| _ = authInfoResolver |
There was a problem hiding this comment.
Why do we do this? It's not used?
There was a problem hiding this comment.
Shouldn't this also be caught by the linter?
There was a problem hiding this comment.
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
| ConversionFactory: &nopCRConversionFactory{}, | ||
| ConversionFactory: kcpconversion.NewCRConverterFactory( | ||
| c.KcpSharedInformerFactory.Apis().V1alpha1().APIConversions(), | ||
| 5*time.Second, |
There was a problem hiding this comment.
opts.Extra.ConversionCELTransformationTimeout ?
| 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] == '.' { |
There was a problem hiding this comment.
This function is called from Compile, and from NewConverter, hence toPath and fromPath never checked for len
| if errors.IsNotFound(err) { | ||
| switch f.crd.Spec.Conversion.Strategy { | ||
| case apiextensionsv1.NoneConverter: | ||
| return conversion.NewNOPConverter(), nil |
There was a problem hiding this comment.
We should be setting f.delegate = conversion.NewNOPConverter() else this code path will be hot on every request
| @@ -0,0 +1,83 @@ | |||
| metadata: | |||
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. |
ntnn
left a comment
There was a problem hiding this comment.
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.
| if err != nil { | ||
| return nil, err | ||
| } | ||
| _ = authInfoResolver |
There was a problem hiding this comment.
Shouldn't this also be caught by the linter?
| @@ -0,0 +1,83 @@ | |||
| metadata: | |||
6165992 to
a89c072
Compare
Signed-off-by: olalekan odukoya <odukoyaonline@gmail.com>
a89c072 to
b76ced7
Compare
Summary
What Type of PR Is This?
/kind feature
Related Issue(s)
Fixes 3427
Release Notes