Files
open-cluster-management/vendor/open-cluster-management.io/api/addon/v1beta1/conversion.go
Qing Hao c516beffa6
Some checks failed
Post / images (amd64, addon-manager) (push) Failing after 46s
Post / images (amd64, placement) (push) Failing after 41s
Post / images (amd64, registration-operator) (push) Failing after 39s
Post / images (amd64, work) (push) Failing after 42s
Post / images (arm64, addon-manager) (push) Failing after 39s
Post / images (arm64, placement) (push) Failing after 39s
Post / images (arm64, registration) (push) Failing after 40s
Post / images (arm64, registration-operator) (push) Failing after 42s
Post / images (arm64, work) (push) Failing after 39s
Post / images (amd64, registration) (push) Failing after 7m46s
Post / image manifest (addon-manager) (push) Has been skipped
Post / image manifest (placement) (push) Has been skipped
Post / image manifest (registration) (push) Has been skipped
Post / image manifest (registration-operator) (push) Has been skipped
Post / image manifest (work) (push) Has been skipped
Post / trigger clusteradm e2e (push) Has been skipped
Post / coverage (push) Failing after 14m33s
Scorecard supply-chain security / Scorecard analysis (push) Failing after 1m25s
Close stale issues and PRs / stale (push) Successful in 46s
Add addon conversion webhook for v1alpha1/v1beta1 API migration (#1289)
* Add addon conversion webhook for v1alpha1/v1beta1 API migration

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Qing Hao <qhao@redhat.com>

* Fix GroupVersion compatibility issues after API dependency update

This commit fixes compilation and test errors introduced by updating
the API dependency to use native conversion functions from PR #411.

Changes include:

1. Fix GroupVersion type mismatches across the codebase:
   - Updated OwnerReference creation to use schema.GroupVersion
   - Fixed webhook scheme registration to use proper GroupVersion type
   - Applied fixes to addon, placement, migration, work, and registration controllers

2. Enhance addon conversion webhook:
   - Use native API conversion functions from addon/v1beta1/conversion.go
   - Fix InstallNamespace annotation key to match expected format
   - Add custom logic to populate deprecated ConfigReferent field in ConfigReferences
   - Properly preserve annotations during v1alpha1 <-> v1beta1 conversion

3. Remove duplicate conversion code:
   - Deleted pkg/addon/webhook/conversion/ directory (~500 lines)
   - Now using native conversion functions from the API repository

4. Patch vendored addon-framework:
   - Fixed GroupVersion errors in agentdeploy utils

All unit tests pass successfully (97 packages, 0 failures).

Signed-off-by: Qing Hao <qhao@redhat.com>

---------

Signed-off-by: Qing Hao <qhao@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-24 08:26:35 +00:00

175 lines
5.6 KiB
Go

// Copyright Contributors to the Open Cluster Management project
package v1beta1
import (
"fmt"
certificates "k8s.io/api/certificates/v1"
"k8s.io/apimachinery/pkg/conversion"
"open-cluster-management.io/api/addon/v1alpha1"
)
const (
// ReservedNoDefaultConfigName is a reserved sentinel value used internally during API version conversion.
// It indicates that a v1alpha1 ConfigMeta had no defaultConfig when converting to v1beta1.
// This value is intentionally invalid as a Kubernetes resource name (starts with "__") to prevent
// collision with legitimate user-provided config names and ensure data integrity on round-trip conversions.
// WARNING: This value is reserved and MUST NOT be used as a real config name.
ReservedNoDefaultConfigName = "__reserved_no_default__"
)
// nolint:staticcheck
func Convert_v1beta1_ClusterManagementAddOnSpec_To_v1alpha1_ClusterManagementAddOnSpec(in *ClusterManagementAddOnSpec, out *v1alpha1.ClusterManagementAddOnSpec, s conversion.Scope) error {
if err := autoConvert_v1beta1_ClusterManagementAddOnSpec_To_v1alpha1_ClusterManagementAddOnSpec(in, out, s); err != nil {
return err
}
config := []v1alpha1.ConfigMeta{}
for _, inConfig := range in.DefaultConfigs {
c := v1alpha1.ConfigMeta{
ConfigGroupResource: v1alpha1.ConfigGroupResource{
Group: inConfig.Group,
Resource: inConfig.Resource,
},
}
// If there's a config referent and it's not the reserved sentinel, convert it to default config
// The reserved sentinel indicates there was no defaultConfig in the original v1alpha1
if inConfig.Name != "" && inConfig.Name != ReservedNoDefaultConfigName {
c.DefaultConfig = &v1alpha1.ConfigReferent{
Namespace: inConfig.Namespace,
Name: inConfig.Name,
}
}
config = append(config, c)
}
out.SupportedConfigs = config
return nil
}
// nolint:staticcheck
func Convert_v1alpha1_ClusterManagementAddOnSpec_To_v1beta1_ClusterManagementAddOnSpec(in *v1alpha1.ClusterManagementAddOnSpec, out *ClusterManagementAddOnSpec, s conversion.Scope) error {
if err := autoConvert_v1alpha1_ClusterManagementAddOnSpec_To_v1beta1_ClusterManagementAddOnSpec(in, out, s); err != nil {
return err
}
configs := []AddOnConfig{}
for _, inConfig := range in.SupportedConfigs {
c := AddOnConfig{
ConfigGroupResource: ConfigGroupResource{
Resource: inConfig.Resource,
Group: inConfig.Group,
},
}
if inConfig.DefaultConfig != nil {
c.ConfigReferent = ConfigReferent{
Name: inConfig.DefaultConfig.Name,
Namespace: inConfig.DefaultConfig.Namespace,
}
} else {
c.ConfigReferent = ConfigReferent{
Name: ReservedNoDefaultConfigName,
}
}
configs = append(configs, c)
}
out.DefaultConfigs = configs
return nil
}
func Convert_v1alpha1_ConfigReference_To_v1beta1_ConfigReference(in *v1alpha1.ConfigReference, out *ConfigReference, s conversion.Scope) error {
if err := autoConvert_v1alpha1_ConfigReference_To_v1beta1_ConfigReference(in, out, s); err != nil {
return err
}
return nil
}
func Convert_v1alpha1_ManagedClusterAddOnSpec_To_v1beta1_ManagedClusterAddOnSpec(in *v1alpha1.ManagedClusterAddOnSpec, out *ManagedClusterAddOnSpec, s conversion.Scope) error {
// installNamespace should be treated outside this converter since it will be set on annotation
for _, inConfig := range in.Configs {
outConfig := AddOnConfig{}
if err := Convert_v1alpha1_AddOnConfig_To_v1beta1_AddOnConfig(&inConfig, &outConfig, s); err != nil {
return err
}
out.Configs = append(out.Configs, outConfig)
}
return nil
}
func Convert_v1alpha1_ManagedClusterAddOnStatus_To_v1beta1_ManagedClusterAddOnStatus(in *v1alpha1.ManagedClusterAddOnStatus, out *ManagedClusterAddOnStatus, s conversion.Scope) error {
if err := autoConvert_v1alpha1_ManagedClusterAddOnStatus_To_v1beta1_ManagedClusterAddOnStatus(in, out, s); err != nil {
return err
}
return nil
}
// nolint:staticcheck
func Convert_v1beta1_RegistrationConfig_To_v1alpha1_RegistrationConfig(in *RegistrationConfig, out *v1alpha1.RegistrationConfig, s conversion.Scope) error {
if in.Type == KubeClient {
out.SignerName = certificates.KubeAPIServerClientSignerName
if in.KubeClient == nil {
return fmt.Errorf("nil KubeClient")
}
out.Subject = v1alpha1.Subject{
User: in.KubeClient.Subject.User,
Groups: in.KubeClient.Subject.Groups,
}
} else {
if in.CSR == nil {
return fmt.Errorf("nil CSR")
}
out.SignerName = in.CSR.SignerName
if err := Convert_v1beta1_Subject_To_v1alpha1_Subject(&in.CSR.Subject, &out.Subject, s); err != nil {
return err
}
}
return nil
}
// nolint:staticcheck
func Convert_v1alpha1_RegistrationConfig_To_v1beta1_RegistrationConfig(in *v1alpha1.RegistrationConfig, out *RegistrationConfig, s conversion.Scope) error {
if in.SignerName == certificates.KubeAPIServerClientSignerName {
out.Type = KubeClient
out.KubeClient = &KubeClientConfig{
Subject: KubeClientSubject{
BaseSubject{
User: in.Subject.User,
Groups: in.Subject.Groups,
},
},
}
} else {
out.Type = CSR
out.CSR = &CSRConfig{
SignerName: in.SignerName,
Subject: Subject{
BaseSubject: BaseSubject{
User: in.Subject.User,
Groups: in.Subject.Groups,
},
OrganizationUnits: in.Subject.OrganizationUnits,
},
}
}
return nil
}
func Convert_v1beta1_Subject_To_v1alpha1_Subject(in *Subject, out *v1alpha1.Subject, s conversion.Scope) error {
out.User = in.User
out.Groups = in.Groups
out.OrganizationUnits = in.OrganizationUnits
return nil
}
func Convert_v1alpha1_Subject_To_v1beta1_Subject(in *v1alpha1.Subject, out *Subject, s conversion.Scope) error {
out.User = in.User
out.Groups = in.Groups
out.OrganizationUnits = in.OrganizationUnits
return nil
}