Skip to content

Commit 6a6732c

Browse files
authored
✨ Install GH into a brownfield (#1319)
* Install GH into a brownfield Signed-off-by: clyang82 <[email protected]> * Increase code coverage Signed-off-by: clyang82 <[email protected]> * Rename to InstallAgentOnLocal Signed-off-by: clyang82 <[email protected]> --------- Signed-off-by: clyang82 <[email protected]>
1 parent 0ee723f commit 6a6732c

8 files changed

+120
-7
lines changed

operator/api/operator/v1alpha4/multiclusterglobalhub_types.go

+7
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,13 @@ type MulticlusterGlobalHubSpec struct {
107107
// +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:booleanSwitch"}
108108
// +optional
109109
EnableMetrics bool `json:"enableMetrics"`
110+
// InstallAgentOnLocal determines whether deploy the Global Hub Agent on the local hub cluster or not.
111+
// If set to true, the Global Hub Agent will be installed on the local hub cluster only.
112+
// If set to false, the Global Hub Agent will not be installed on the local hub cluster.
113+
// Currently, switching the value of this field is not supported after the Global Hub is installed.
114+
// +kubebuilder:default=false
115+
// +optional
116+
InstallAgentOnLocal bool `json:"InstallAgentOnLocal,omitempty"`
110117
}
111118

112119
type AdvancedSpec struct {

operator/bundle/manifests/operator.open-cluster-management.io_multiclusterglobalhubs.yaml

+8
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ spec:
5555
retention: 18m
5656
description: Spec specifies the desired state of multicluster global hub
5757
properties:
58+
InstallAgentOnLocal:
59+
default: false
60+
description: |-
61+
InstallAgentOnLocal determines whether deploy the Global Hub Agent on the local hub cluster or not.
62+
If set to true, the Global Hub Agent will be installed on the local hub cluster only.
63+
If set to false, the Global Hub Agent will not be installed on the local hub cluster.
64+
Currently, switching the value of this field is not supported after the Global Hub is installed.
65+
type: boolean
5866
advanced:
5967
description: AdvancedSpec specifies the advanced configurations for
6068
the multicluster global hub

operator/config/crd/bases/operator.open-cluster-management.io_multiclusterglobalhubs.yaml

+8
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,14 @@ spec:
5555
retention: 18m
5656
description: Spec specifies the desired state of multicluster global hub
5757
properties:
58+
InstallAgentOnLocal:
59+
default: false
60+
description: |-
61+
InstallAgentOnLocal determines whether deploy the Global Hub Agent on the local hub cluster or not.
62+
If set to true, the Global Hub Agent will be installed on the local hub cluster only.
63+
If set to false, the Global Hub Agent will not be installed on the local hub cluster.
64+
Currently, switching the value of this field is not supported after the Global Hub is installed.
65+
type: boolean
5866
advanced:
5967
description: AdvancedSpec specifies the advanced configurations for
6068
the multicluster global hub

operator/pkg/controllers/agent/default_agent_controller.go

+19-3
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,24 @@ func (r *DefaultAgentController) Reconcile(ctx context.Context, req ctrl.Request
261261
return ctrl.Result{}, nil
262262
}
263263

264-
return ctrl.Result{}, r.reconcileAddonAndResources(ctx, cluster, clusterManagementAddOn)
264+
if mgh.Spec.InstallAgentOnLocal {
265+
// if installed agent on hub cluster, global hub is installed in a brownfield cluster
266+
if cluster.GetName() == constants.LocalClusterName ||
267+
cluster.Labels[constants.LocalClusterName] == "true" ||
268+
deployMode == operatorconstants.GHAgentDeployModeDefault ||
269+
deployMode == operatorconstants.GHAgentDeployModeHosted {
270+
return ctrl.Result{}, r.reconcileAddonAndResources(ctx, cluster, clusterManagementAddOn)
271+
}
272+
} else {
273+
// if not installed agent on hub cluster, global hub is installed in a greenfield cluster
274+
if cluster.GetName() == constants.LocalClusterName ||
275+
cluster.Labels[constants.LocalClusterName] == "true" {
276+
return ctrl.Result{}, nil
277+
}
278+
return ctrl.Result{}, r.reconcileAddonAndResources(ctx, cluster, clusterManagementAddOn)
279+
}
280+
281+
return ctrl.Result{}, nil
265282
}
266283

267284
func (r *DefaultAgentController) deleteClusterManagementAddon(ctx context.Context) error {
@@ -457,6 +474,5 @@ func GetAllManagedHubNames(ctx context.Context, c client.Client) ([]string, erro
457474

458475
func filterManagedCluster(obj client.Object) bool {
459476
return obj.GetLabels()["vendor"] != "OpenShift" ||
460-
obj.GetLabels()["openshiftVersion"] == "3" ||
461-
obj.GetName() == constants.LocalClusterName
477+
obj.GetLabels()["openshiftVersion"] == "3"
462478
}

test/integration/operator/controllers/agent/cluster_default_addon_test.go

+55-1
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,12 @@ import (
1111
clusterv1 "open-cluster-management.io/api/cluster/v1"
1212
workv1 "open-cluster-management.io/api/work/v1"
1313

14+
globalhubv1alpha4 "github.com/stolostron/multicluster-global-hub/operator/api/operator/v1alpha4"
1415
operatorconstants "github.com/stolostron/multicluster-global-hub/operator/pkg/constants"
1516
"github.com/stolostron/multicluster-global-hub/pkg/constants"
1617
)
1718

18-
// go test ./test/integration/operator/agent -ginkgo.focus "deploy default addon" -v
19+
// go test ./test/integration/operator/controllers/agent -ginkgo.focus "deploy default addon" -v
1920
var _ = Describe("deploy default addon", func() {
2021
It("Should create agent when importing an bare OCP", func() {
2122
clusterName := fmt.Sprintf("hub-%s", rand.String(6))
@@ -132,4 +133,57 @@ var _ = Describe("deploy default addon", func() {
132133
// contains both the ACM and the Global Hub manifests
133134
Expect(len(work.Spec.Workload.Manifests)).Should(Equal(17))
134135
})
136+
137+
It("Should create agent for the local-cluster", func() {
138+
By("set InstallAgentOnLocal to true")
139+
mghLookupKey := types.NamespacedName{Namespace: "default", Name: MGHName}
140+
existingMGH := &globalhubv1alpha4.MulticlusterGlobalHub{}
141+
Eventually(func() bool {
142+
err := runtimeClient.Get(ctx, mghLookupKey, existingMGH)
143+
return err == nil
144+
}, timeout, interval).Should(BeTrue())
145+
existingMGH.Spec.InstallAgentOnLocal = true
146+
Expect(runtimeClient.Update(ctx, existingMGH)).Should(Succeed())
147+
148+
clusterName := fmt.Sprintf("hub-%s", rand.String(6))
149+
workName := fmt.Sprintf("addon-%s-deploy-0",
150+
constants.GHManagedClusterAddonName)
151+
152+
By("By preparing an OCP Managed Clusters")
153+
prepareCluster(clusterName,
154+
map[string]string{"vendor": "OpenShift", "local-cluster": "true"},
155+
map[string]string{},
156+
[]clusterv1.ManagedClusterClaim{},
157+
clusterAvailableCondition)
158+
159+
By("By checking the addon CR is is created in the cluster ns")
160+
addon := &addonv1alpha1.ManagedClusterAddOn{}
161+
Eventually(func() error {
162+
return runtimeClient.Get(ctx, types.NamespacedName{
163+
Name: constants.GHManagedClusterAddonName,
164+
Namespace: clusterName,
165+
}, addon)
166+
}, timeout, interval).ShouldNot(HaveOccurred())
167+
168+
Expect(len(addon.GetAnnotations())).Should(Equal(0))
169+
170+
By("By checking the agent manifestworks are created for the local cluster")
171+
work := &workv1.ManifestWork{}
172+
Eventually(func() error {
173+
return runtimeClient.Get(ctx, types.NamespacedName{
174+
Name: workName,
175+
Namespace: clusterName,
176+
}, work)
177+
}, timeout, interval).ShouldNot(HaveOccurred())
178+
179+
Expect(len(work.Spec.Workload.Manifests)).Should(Equal(8))
180+
181+
By("set InstallAgentOnLocal to false as a default value")
182+
Eventually(func() bool {
183+
err := runtimeClient.Get(ctx, mghLookupKey, existingMGH)
184+
return err == nil
185+
}, timeout, interval).Should(BeTrue())
186+
existingMGH.Spec.InstallAgentOnLocal = false
187+
Expect(runtimeClient.Update(ctx, existingMGH)).Should(Succeed())
188+
})
135189
})

test/integration/operator/controllers/agent/cluster_hosted_addon_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
"github.com/stolostron/multicluster-global-hub/pkg/constants"
1616
)
1717

18-
// go test ./test/integration/operator/agent -ginkgo.focus "deploy hosted addon" -v
18+
// go test ./test/integration/operator/controllers/agent -ginkgo.focus "deploy hosted addon" -v
1919
var _ = Describe("deploy hosted addon", func() {
2020
It("Should create hosted addon in OCP", func() {
2121
clusterName := fmt.Sprintf("hub-%s", rand.String(6)) // managed hub cluster -> enable local cluster

test/integration/operator/controllers/agent/cluster_none_addon_test.go

+21-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"k8s.io/apimachinery/pkg/api/errors"
1111
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1212
"k8s.io/apimachinery/pkg/runtime"
13+
"k8s.io/apimachinery/pkg/types"
1314
"k8s.io/apimachinery/pkg/util/rand"
1415
addonv1alpha1 "open-cluster-management.io/api/addon/v1alpha1"
1516
clusterv1 "open-cluster-management.io/api/cluster/v1"
@@ -67,7 +68,7 @@ func prepareCluster(name string, labels, annotations map[string]string,
6768
})).Should(Succeed())
6869
}
6970

70-
// go test ./test/integration/operator/agent -ginkgo.focus "none addon" -v
71+
// go test ./test/integration/operator/controllers/agent -ginkgo.focus "none addon" -v
7172
var _ = Describe("none addon", func() {
7273
It("Should not create addon in these cases", func() {
7374
By("By preparing a non-OCP with deployMode label Managed Clusters")
@@ -146,4 +147,23 @@ var _ = Describe("none addon", func() {
146147
return fmt.Errorf("check again %v", checkCount)
147148
}, timeout, interval).ShouldNot(HaveOccurred())
148149
})
150+
151+
It("Should not create agent for the local-cluster", func() {
152+
clusterName := fmt.Sprintf("hub-%s", rand.String(6))
153+
By("By preparing an OCP Managed Clusters")
154+
prepareCluster(clusterName,
155+
map[string]string{"vendor": "OpenShift", "local-cluster": "true"},
156+
map[string]string{},
157+
[]clusterv1.ManagedClusterClaim{},
158+
clusterAvailableCondition)
159+
160+
By("By checking the addon CR is is created in the cluster ns")
161+
addon := &addonv1alpha1.ManagedClusterAddOn{}
162+
Eventually(func() error {
163+
return runtimeClient.Get(ctx, types.NamespacedName{
164+
Name: constants.GHManagedClusterAddonName,
165+
Namespace: clusterName,
166+
}, addon)
167+
}, duration, interval).Should(HaveOccurred())
168+
})
149169
})

test/integration/operator/controllers/agent/hosted_managedhub/mgh_hosted_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ var hostedMGH = globalhubv1alpha4.MulticlusterGlobalHub{
9090
// hosted: put the acm agent cluster control plane into acm hub cluster
9191
// global hub -> managed-hub(local-cluster)
9292

93-
// go test ./test/integration/operator/agent -ginkgo.focus "other addons in hosted mode test" -v
93+
// go test ./test/integration/operator/controllers/agent -ginkgo.focus "other addons in hosted mode test" -v
9494
var _ = Describe("other addons in hosted mode test", Ordered, func() {
9595
var hostedAddonReconciler *agent.HostedAgentController
9696
BeforeAll(func() {

0 commit comments

Comments
 (0)