Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ require (
k8s.io/component-base v0.33.3
k8s.io/klog/v2 v2.130.1
k8s.io/utils v0.0.0-20241210054802-24370beab758
open-cluster-management.io/api v1.0.1-0.20251009064814-48b723491429
open-cluster-management.io/api v1.0.1-0.20251016015403-f042545132a3
open-cluster-management.io/sdk-go v1.0.1-0.20250811075710-18b20e146feb
sigs.k8s.io/controller-runtime v0.20.2
)
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -448,8 +448,8 @@ k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUy
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0=
k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
open-cluster-management.io/api v1.0.1-0.20251009064814-48b723491429 h1:jU4r3zijNA+Ab17oF7lBck0YHc7f7wM8r2RqZJw6ZSs=
open-cluster-management.io/api v1.0.1-0.20251009064814-48b723491429/go.mod h1:lEc5Wkc9ON5ym/qAtIqNgrE7NW7IEOCOC611iQMlnKM=
open-cluster-management.io/api v1.0.1-0.20251016015403-f042545132a3 h1:PXT0zdNZ4T+3GwCjlY/0Xt5O2hxuEcBgRDvuxtkUy7c=
open-cluster-management.io/api v1.0.1-0.20251016015403-f042545132a3/go.mod h1:lEc5Wkc9ON5ym/qAtIqNgrE7NW7IEOCOC611iQMlnKM=
open-cluster-management.io/sdk-go v1.0.1-0.20250811075710-18b20e146feb h1:voE6JR6Xi8wNTSkhADHP19FpGICUpqt1/lEREQt7TVU=
open-cluster-management.io/sdk-go v1.0.1-0.20250811075710-18b20e146feb/go.mod h1:sHOVhUgA286ceEq3IjFWqxobt9Lu+VBCAUZByFgN0oM=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.2 h1:jpcvIRr3GLoUoEKRkHKSmGjxb6lWwrBlJsXc+eUYQHM=
Expand Down
41 changes: 41 additions & 0 deletions pkg/utils/addon_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ func (g *defaultAddOnDeploymentConfigGetter) Get(
// AgentInstallNamespaceFromDeploymentConfigFunc returns an agent install namespace helper function which will get the
// namespace from the addon deployment config. If the addon does not support addon deployment config or there is no
// matched addon deployment config, it will return an empty string.
// Note: For backward compatibility, if the config exists but AgentInstallNamespace is empty, it returns the default
// namespace "open-cluster-management-agent-addon". For template-type addons that need the raw value including
// explicit empty strings, use AgentInstallNamespaceFromDeploymentConfigRawFunc instead.
func AgentInstallNamespaceFromDeploymentConfigFunc(
adcgetter AddOnDeploymentConfigGetter,
) func(*addonapiv1alpha1.ManagedClusterAddOn) (string, error) {
Expand All @@ -58,6 +61,44 @@ func AgentInstallNamespaceFromDeploymentConfigFunc(
return "", nil
}

// For backward compatibility: if AgentInstallNamespace is empty, return the default namespace.
// This ensures existing addons continue to work as before.
// Template-type addons that want to use empty string should use AgentInstallNamespaceFromDeploymentConfigRawFunc.
if len(config.Spec.AgentInstallNamespace) == 0 {
return "open-cluster-management-agent-addon", nil
}

return config.Spec.AgentInstallNamespace, nil
}
}

// AgentInstallNamespaceFromDeploymentConfigRawFunc returns an agent install namespace helper function which will get the
// raw namespace value from the addon deployment config, including empty string.
// This function is useful for template-type addons where an empty string signals to use the namespace
// defined in the template manifest itself, rather than applying a default namespace.
// If the addon does not support addon deployment config or there is no matched addon deployment config,
// it will return an empty string.
func AgentInstallNamespaceFromDeploymentConfigRawFunc(
Copy link
Member

Choose a reason for hiding this comment

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

should this be defined in ocm given it is only used for addonTemplate?

Copy link
Member Author

Choose a reason for hiding this comment

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

Not 100% sure if this could be used by other cases.

Copy link
Member

Choose a reason for hiding this comment

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

AgentInstallNamespaceFromDeploymentConfigRawFunc the name is a big confused. Why RawFunc?

Copy link
Member Author

Choose a reason for hiding this comment

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

This is compared with AgentInstallNamespaceFromDeploymentConfigFunc, AgentInstallNamespaceFromDeploymentConfigFunc returns the default open-cluster-management-agent-addon if the addondeploymentconfig.spec.installnamespace is empty, AgentInstallNamespaceFromDeploymentConfigRawFunc returns empty directly.

adcgetter AddOnDeploymentConfigGetter,
) func(*addonapiv1alpha1.ManagedClusterAddOn) (string, error) {
return func(addon *addonapiv1alpha1.ManagedClusterAddOn) (string, error) {
if addon == nil {
return "", fmt.Errorf("failed to get addon install namespace, addon is nil")
}

config, err := GetDesiredAddOnDeploymentConfig(addon, adcgetter)
if err != nil {
return "", fmt.Errorf("failed to get deployment config for addon %s: %v", addon.Name, err)
}

if config == nil {
klog.V(4).InfoS("Addon deployment config is nil, return an empty string for agent install namespace",
"addonNamespace", addon.Namespace, "addonName", addon.Name)
return "", nil
}

// Return the raw value including empty string - this allows template-type addons to
// signal "use template namespace" by setting agentInstallNamespace: ""
return config.Spec.AgentInstallNamespace, nil
}
}
Expand Down
156 changes: 156 additions & 0 deletions pkg/utils/addon_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,41 @@ func TestAgentInstallNamespaceFromDeploymentConfigFunc(t *testing.T) {
// },
// expected: "",
// },
{
name: "addon deployment config with empty AgentInstallNamespace returns default",
getter: newTestAddOnDeploymentConfigGetter(
&addonapiv1alpha1.AddOnDeploymentConfig{
ObjectMeta: metav1.ObjectMeta{
Name: "test1",
},
Spec: addonapiv1alpha1.AddOnDeploymentConfigSpec{
AgentInstallNamespace: "",
},
}),
mca: &addonapiv1alpha1.ManagedClusterAddOn{
ObjectMeta: metav1.ObjectMeta{
Name: "test1",
Namespace: "cluster1",
},
Status: addonapiv1alpha1.ManagedClusterAddOnStatus{
ConfigReferences: []addonapiv1alpha1.ConfigReference{
{
ConfigGroupResource: addonapiv1alpha1.ConfigGroupResource{
Group: "addon.open-cluster-management.io",
Resource: "addondeploymentconfigs",
},
ConfigReferent: addonapiv1alpha1.ConfigReferent{
Name: "test1",
},
DesiredConfig: &addonapiv1alpha1.ConfigSpecHash{
SpecHash: "44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
},
},
},
},
},
expected: "open-cluster-management-agent-addon",
},
{
name: "addon deployment config reference spec hash match",
getter: newTestAddOnDeploymentConfigGetter(
Expand Down Expand Up @@ -173,3 +208,124 @@ func TestAgentInstallNamespaceFromDeploymentConfigFunc(t *testing.T) {
})
}
}

func TestAgentInstallNamespaceFromDeploymentConfigRawFunc(t *testing.T) {

cases := []struct {
name string
getter AddOnDeploymentConfigGetter
mca *addonapiv1alpha1.ManagedClusterAddOn
expected string
}{
{
name: "addon is nil",
getter: newTestAddOnDeploymentConfigGetter(
&addonapiv1alpha1.AddOnDeploymentConfig{
ObjectMeta: metav1.ObjectMeta{
Name: "test1",
},
Spec: addonapiv1alpha1.AddOnDeploymentConfigSpec{},
}),
mca: nil,
expected: "",
},
{
name: "addon no deployment config reference",
getter: newTestAddOnDeploymentConfigGetter(
&addonapiv1alpha1.AddOnDeploymentConfig{
ObjectMeta: metav1.ObjectMeta{
Name: "test1",
},
Spec: addonapiv1alpha1.AddOnDeploymentConfigSpec{},
}),
mca: &addonapiv1alpha1.ManagedClusterAddOn{
ObjectMeta: metav1.ObjectMeta{
Name: "test1",
Namespace: "cluster1",
},
Status: addonapiv1alpha1.ManagedClusterAddOnStatus{
ConfigReferences: []addonapiv1alpha1.ConfigReference{},
},
},
expected: "",
},
{
name: "addon deployment config with empty AgentInstallNamespace",
getter: newTestAddOnDeploymentConfigGetter(
&addonapiv1alpha1.AddOnDeploymentConfig{
ObjectMeta: metav1.ObjectMeta{
Name: "test1",
},
Spec: addonapiv1alpha1.AddOnDeploymentConfigSpec{
AgentInstallNamespace: "",
},
}),
mca: &addonapiv1alpha1.ManagedClusterAddOn{
ObjectMeta: metav1.ObjectMeta{
Name: "test1",
Namespace: "cluster1",
},
Status: addonapiv1alpha1.ManagedClusterAddOnStatus{
ConfigReferences: []addonapiv1alpha1.ConfigReference{
{
ConfigGroupResource: addonapiv1alpha1.ConfigGroupResource{
Group: "addon.open-cluster-management.io",
Resource: "addondeploymentconfigs",
},
ConfigReferent: addonapiv1alpha1.ConfigReferent{
Name: "test1",
},
DesiredConfig: &addonapiv1alpha1.ConfigSpecHash{
SpecHash: "44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
},
},
},
},
},
expected: "",
},
{
name: "addon deployment config with non-empty AgentInstallNamespace",
getter: newTestAddOnDeploymentConfigGetter(
&addonapiv1alpha1.AddOnDeploymentConfig{
ObjectMeta: metav1.ObjectMeta{
Name: "test1",
},
Spec: addonapiv1alpha1.AddOnDeploymentConfigSpec{
AgentInstallNamespace: "testns",
},
}),
mca: &addonapiv1alpha1.ManagedClusterAddOn{
ObjectMeta: metav1.ObjectMeta{
Name: "test1",
Namespace: "cluster1",
},
Status: addonapiv1alpha1.ManagedClusterAddOnStatus{
ConfigReferences: []addonapiv1alpha1.ConfigReference{
{
ConfigGroupResource: addonapiv1alpha1.ConfigGroupResource{
Group: "addon.open-cluster-management.io",
Resource: "addondeploymentconfigs",
},
ConfigReferent: addonapiv1alpha1.ConfigReferent{
Name: "test1",
},
DesiredConfig: &addonapiv1alpha1.ConfigSpecHash{
SpecHash: "f97b3f6af1f786ec6f3273e2d6fc8717e45cb7bc9797ba7533663a7de84a5538",
},
},
},
},
},
expected: "testns",
},
}

for _, c := range cases {
t.Run(c.name, func(t *testing.T) {
nsFunc := AgentInstallNamespaceFromDeploymentConfigRawFunc(c.getter)
ns, _ := nsFunc(c.mca)
assert.Equal(t, c.expected, ns, "should be equal")
})
}
}
2 changes: 1 addition & 1 deletion vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1426,7 +1426,7 @@ k8s.io/utils/path
k8s.io/utils/pointer
k8s.io/utils/ptr
k8s.io/utils/trace
# open-cluster-management.io/api v1.0.1-0.20251009064814-48b723491429
# open-cluster-management.io/api v1.0.1-0.20251016015403-f042545132a3
## explicit; go 1.24.0
open-cluster-management.io/api/addon/v1alpha1
open-cluster-management.io/api/client/addon/clientset/versioned
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions vendor/open-cluster-management.io/api/work/v1/types.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading