Skip to content

Commit

Permalink
replace the last applied managed cluster api server url when it chang…
Browse files Browse the repository at this point in the history
…es (stolostron#605)

* update vendor cluster-lifecycle-api

Signed-off-by: zhujian <[email protected]>

* replace the last applied managed cluster api server url when it changes

Signed-off-by: zhujian <[email protected]>

* check last applied url after updating client config

Signed-off-by: zhujian <[email protected]>

---------

Signed-off-by: zhujian <[email protected]>
  • Loading branch information
zhujian7 authored May 11, 2023
1 parent 6b731b4 commit 3bcc084
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 54 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ spec:
desiredVersion:
description: DesiredVersion is the version that the cluster is reconciling towards. Deprecated in release 2.3 and will be removed in the future. User Desired instead.
type: string
lastAppliedAPIServerURL:
description: LastAppliedAPIServerURL is a valid URI with scheme 'https', address and optionally a port (defaulting to 443). it can be used by components like the web console to tell users where to find the Kubernetes API. This is the api server url that has been applied to the managedcluster resource successfully
type: string
managedClusterClientConfig:
description: Controller will sync this field to managedcluster's ManagedClusterClientConfigs
type: object
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ require (
github.com/prometheus/common v0.39.0
github.com/smartystreets/goconvey v1.7.2
github.com/spf13/pflag v1.0.6-0.20210604193023-d5e0c0615ace
github.com/stolostron/cluster-lifecycle-api v0.0.0-20230222063645-5b18b26381ff
github.com/stolostron/cluster-lifecycle-api v0.0.0-20230510064049-824d580bc143
github.com/stretchr/testify v1.8.1
golang.org/x/net v0.8.0
k8s.io/api v0.26.2
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -437,8 +437,8 @@ github.com/spf13/pflag v1.0.6-0.20210604193023-d5e0c0615ace h1:9PNP1jnUjRhfmGMlk
github.com/spf13/pflag v1.0.6-0.20210604193023-d5e0c0615ace/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
github.com/stolostron/cluster-lifecycle-api v0.0.0-20230222063645-5b18b26381ff h1:psHMqHMefkFtr7y4JT5tz8oKwmChvLJe/cHUUM9tcMI=
github.com/stolostron/cluster-lifecycle-api v0.0.0-20230222063645-5b18b26381ff/go.mod h1:pNeVzujoHsTHDloNHVfp1QPYlQy8MkXMuuZme96/x8M=
github.com/stolostron/cluster-lifecycle-api v0.0.0-20230510064049-824d580bc143 h1:lPHc9Kaa3bZs4domKspWKyCZmN5uL4b0RWZXDhEiVgY=
github.com/stolostron/cluster-lifecycle-api v0.0.0-20230510064049-824d580bc143/go.mod h1:pNeVzujoHsTHDloNHVfp1QPYlQy8MkXMuuZme96/x8M=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
Expand Down
57 changes: 38 additions & 19 deletions pkg/controllers/clusterca/clusterca_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/klog"
clusterv1 "open-cluster-management.io/api/cluster/v1"

ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
Expand Down Expand Up @@ -56,50 +55,70 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
}

func (r *ClusterCaReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
clusterinfo := &clusterinfov1beta1.ManagedClusterInfo{}
clusterInfo := &clusterinfov1beta1.ManagedClusterInfo{}

err := r.client.Get(ctx, req.NamespacedName, clusterinfo)
err := r.client.Get(ctx, req.NamespacedName, clusterInfo)
if err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}

cluster := &clusterv1.ManagedCluster{}

err = r.client.Get(ctx, types.NamespacedName{Name: clusterinfo.Name}, cluster)
err = r.client.Get(ctx, types.NamespacedName{Name: clusterInfo.Name}, cluster)
if err != nil {
return ctrl.Result{}, err
}

updatedClientConfig, needUpdate := updateClientConfig(cluster.Spec.ManagedClusterClientConfigs, clusterinfo.Status.DistributionInfo.OCP.ManagedClusterClientConfig)
if !needUpdate {
return ctrl.Result{}, nil
}
updatedClientConfig, needUpdate := updateClientConfig(
cluster.Spec.ManagedClusterClientConfigs,
clusterInfo.Status.DistributionInfo.OCP.ManagedClusterClientConfig,
clusterInfo.Status.DistributionInfo.OCP.LastAppliedAPIServerURL)

cluster.Spec.ManagedClusterClientConfigs = updatedClientConfig
err = r.client.Update(ctx, cluster, &client.UpdateOptions{})
if needUpdate {
cluster.Spec.ManagedClusterClientConfigs = updatedClientConfig
err = r.client.Update(ctx, cluster, &client.UpdateOptions{})
if err != nil {
return ctrl.Result{}, err
}
}

if err != nil {
return ctrl.Result{}, err
if clusterInfo.Status.DistributionInfo.OCP.LastAppliedAPIServerURL !=
clusterInfo.Status.DistributionInfo.OCP.ManagedClusterClientConfig.URL {
clusterInfo.Status.DistributionInfo.OCP.LastAppliedAPIServerURL =
clusterInfo.Status.DistributionInfo.OCP.ManagedClusterClientConfig.URL
err = r.client.Status().Update(ctx, clusterInfo)
if err != nil {
return ctrl.Result{}, err
}
}
return ctrl.Result{}, nil
}

// updateClientConfig merge config from clusterinfoconfigs to clusterconfigs
func updateClientConfig(clusterConfigs []clusterv1.ClientConfig, clusterinfoConfig clusterinfov1beta1.ClientConfig) ([]clusterv1.ClientConfig, bool) {
// updateClientConfig merge config from clusterinfoconfigs to clusterconfigs, it returns 2 parameters:
// - the updated cluster clientConfig
// - whether it is needed to update the managedCluster object
func updateClientConfig(clusterConfigs []clusterv1.ClientConfig, clusterinfoConfig clusterinfov1beta1.ClientConfig,
lastAppliedURL string) ([]clusterv1.ClientConfig, bool) {
// If clusterinfo config is null return clusterconfigs
if len(clusterinfoConfig.URL) == 0 {
return clusterConfigs, false
}

// The lastAppliedURL comes from the value of infrastructures config(status.apiServerURL), if the
// infrastructures config value changes, here we will replace the old clientConfig URL instead of
// prepending a new one.
for i, cluConfig := range clusterConfigs {
if cluConfig.URL != clusterinfoConfig.URL {
if cluConfig.URL != clusterinfoConfig.URL && cluConfig.URL != lastAppliedURL {
continue
}
if !reflect.DeepEqual(cluConfig.CABundle, clusterinfoConfig.CABundle) {
clusterConfigs[i].CABundle = clusterinfoConfig.CABundle
return clusterConfigs, true

if reflect.DeepEqual(cluConfig.CABundle, clusterinfoConfig.CABundle) && cluConfig.URL == clusterinfoConfig.URL {
return clusterConfigs, false
}
return clusterConfigs, false

clusterConfigs[i].URL = clusterinfoConfig.URL
clusterConfigs[i].CABundle = clusterinfoConfig.CABundle
return clusterConfigs, true
}

// do not have ca bundle in cluster config, *prepend* the clusterinfo config to the managed cluster config.
Expand Down
80 changes: 71 additions & 9 deletions pkg/controllers/clusterca/clusterca_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,16 @@ func Test_updateClientConfig(t *testing.T) {
name string
clusterConfig []clusterv1.ClientConfig
clusterinfoConfig clusterinfov1beta1.ClientConfig
lastAppliedURL string
wantConfig []clusterv1.ClientConfig
wantUpdate bool
wantUpdateMC bool
}{
{
name: "all nil",
clusterConfig: []clusterv1.ClientConfig{},
clusterinfoConfig: clusterinfov1beta1.ClientConfig{},
wantConfig: []clusterv1.ClientConfig{},
wantUpdate: false,
wantUpdateMC: false,
},
{
name: "clusterconfig is null",
Expand All @@ -36,7 +37,7 @@ func Test_updateClientConfig(t *testing.T) {
CABundle: []byte("ca data"),
},
},
wantUpdate: true,
wantUpdateMC: true,
},
{
name: "clusterinfoconfig is null",
Expand All @@ -53,7 +54,7 @@ func Test_updateClientConfig(t *testing.T) {
CABundle: []byte("ca data"),
},
},
wantUpdate: false,
wantUpdateMC: false,
},
{
name: "both of them is not null, and order matters",
Expand All @@ -77,7 +78,7 @@ func Test_updateClientConfig(t *testing.T) {
CABundle: []byte("ca data"),
},
},
wantUpdate: true,
wantUpdateMC: true,
},
{
name: "update cluster config",
Expand Down Expand Up @@ -105,17 +106,78 @@ func Test_updateClientConfig(t *testing.T) {
CABundle: []byte("new info data"),
},
},
wantUpdate: true,
wantUpdateMC: true,
},
{
name: "replace the last applied url with new url",
clusterConfig: []clusterv1.ClientConfig{
{
URL: "https:clusterurl.com:443",
CABundle: []byte("ca data"),
},
},
clusterinfoConfig: clusterinfov1beta1.ClientConfig{
URL: "https:infourl.com:443",
CABundle: []byte("ca data"),
},
lastAppliedURL: "https:clusterurl.com:443",
wantConfig: []clusterv1.ClientConfig{
{
URL: "https:infourl.com:443",
CABundle: []byte("ca data"),
},
},
wantUpdateMC: true,
},
{
name: "replace the last applied url with new url, order not change",
clusterConfig: []clusterv1.ClientConfig{
{
URL: "https:clusterurl-1.com:443",
CABundle: []byte("new info data"),
},
{
URL: "https:clusterurl.com:443",
CABundle: []byte("ca data"),
},
{
URL: "https:clusterurl-2.com:443",
CABundle: []byte("new info data"),
},
},
clusterinfoConfig: clusterinfov1beta1.ClientConfig{
URL: "https:infourl.com:443",
CABundle: []byte("ca data"),
},
lastAppliedURL: "https:clusterurl.com:443",
wantConfig: []clusterv1.ClientConfig{
{
URL: "https:clusterurl-1.com:443",
CABundle: []byte("new info data"),
},
{
URL: "https:infourl.com:443",
CABundle: []byte("ca data"),
},
{
URL: "https:clusterurl-2.com:443",
CABundle: []byte("new info data"),
},
},
wantUpdateMC: true,
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
returnConfig, needUpdate := updateClientConfig(test.clusterConfig, test.clusterinfoConfig)
if needUpdate != test.wantUpdate {
t.Errorf("case: %v, needupdate is: %v, wantUpdate is : %v", test.name, needUpdate, test.wantUpdate)
returnConfig, needUpdate := updateClientConfig(
test.clusterConfig, test.clusterinfoConfig, test.lastAppliedURL)
if needUpdate != test.wantUpdateMC {
t.Errorf("case: %v, expected update managed cluster: %v, but got : %v",
test.name, test.wantUpdateMC, needUpdate)
return
}

if !reflect.DeepEqual(returnConfig, test.wantConfig) {
t.Errorf("case:%v, returnConfig:%v, wantConfig:%v.", test.name, returnConfig, test.wantConfig)
}
Expand Down
3 changes: 3 additions & 0 deletions pkg/klusterlet/clusterinfo/distributionInfo_sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func (s *distributionInfoSyncer) sync(ctx context.Context, clusterInfo *clusterv
}

func (s *distributionInfoSyncer) syncOCPDistributionInfo(ctx context.Context, clusterInfoStatus *clusterv1beta1.ClusterInfoStatus) error {
lastAppliedAPIServerURL := clusterInfoStatus.DistributionInfo.OCP.LastAppliedAPIServerURL
clusterInfoStatus.DistributionInfo = clusterv1beta1.DistributionInfo{
Type: clusterv1beta1.DistributionTypeOCP,
}
Expand All @@ -54,6 +55,8 @@ func (s *distributionInfoSyncer) syncOCPDistributionInfo(ctx context.Context, cl
URL: string(clusterVersion.Status.Desired.URL),
Channels: clusterVersion.Status.Desired.Channels,
},
// do not override the LastAppliedAPIServerURL to empty
LastAppliedAPIServerURL: lastAppliedAPIServerURL,
}

availableUpdates := clusterVersion.Status.AvailableUpdates
Expand Down
53 changes: 31 additions & 22 deletions pkg/klusterlet/clusterinfo/distributionInfo_sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,37 +197,45 @@ func newConfigV1Client(version string, failingStatus bool) openshiftclientset.In

func Test_distributionInfo_syncer(t *testing.T) {
tests := []struct {
name string
managedClusterInfo *v1beta1.ManagedClusterInfo
configV1Client openshiftclientset.Interface
expectChannel string
expectDesiredVersion string
expectDesiredChannelLen int
expectUpgradeFail bool
expectAvailableUpdatesLen int
expectChannelAndURL bool
expectHistoryLen int
expectError string
expectVersion string
claims []runtime.Object
name string
managedClusterInfo *v1beta1.ManagedClusterInfo
configV1Client openshiftclientset.Interface
expectChannel string
expectDesiredVersion string
expectDesiredChannelLen int
expectUpgradeFail bool
expectAvailableUpdatesLen int
expectChannelAndURL bool
expectLastAppliedAPIServerURL string
expectHistoryLen int
expectError string
expectVersion string
claims []runtime.Object
}{
{
name: "OCP4.x",
managedClusterInfo: &v1beta1.ManagedClusterInfo{
ObjectMeta: metav1.ObjectMeta{Name: "c1", Namespace: "c1"},
Status: v1beta1.ClusterInfoStatus{
KubeVendor: v1beta1.KubeVendorOpenShift,
DistributionInfo: v1beta1.DistributionInfo{
Type: v1beta1.DistributionTypeOCP,
OCP: v1beta1.OCPDistributionInfo{
LastAppliedAPIServerURL: "http://test-last-applied-url",
},
},
},
},
configV1Client: newConfigV1Client("4.x", false),
expectChannel: "stable-4.5",
expectDesiredVersion: "4.6.8",
expectDesiredChannelLen: 7,
expectUpgradeFail: false,
expectAvailableUpdatesLen: 2,
expectChannelAndURL: true,
expectHistoryLen: 3,
expectError: "",
configV1Client: newConfigV1Client("4.x", false),
expectChannel: "stable-4.5",
expectDesiredVersion: "4.6.8",
expectDesiredChannelLen: 7,
expectUpgradeFail: false,
expectAvailableUpdatesLen: 2,
expectChannelAndURL: true,
expectHistoryLen: 3,
expectLastAppliedAPIServerURL: "http://test-last-applied-url",
expectError: "",
claims: []runtime.Object{
newClaim(clusterclaim.ClaimOpenshiftVersion, "4.6.8"),
newClaim(clusterclaim.ClaimOCMKubeVersion, "v1.20.0"),
Expand Down Expand Up @@ -292,6 +300,7 @@ func Test_distributionInfo_syncer(t *testing.T) {
assert.Equal(t, len(info.Desired.Channels), test.expectDesiredChannelLen)
assert.Equal(t, info.UpgradeFailed, test.expectUpgradeFail)
assert.Equal(t, len(info.VersionAvailableUpdates), test.expectAvailableUpdatesLen)
assert.Equal(t, info.LastAppliedAPIServerURL, test.expectLastAppliedAPIServerURL)

//get the latest succeed version
assert.Equal(t, test.expectVersion, info.Version)
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.

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

2 changes: 1 addition & 1 deletion vendor/modules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ github.com/spf13/pflag
# github.com/stoewer/go-strcase v1.2.0
## explicit; go 1.11
github.com/stoewer/go-strcase
# github.com/stolostron/cluster-lifecycle-api v0.0.0-20230222063645-5b18b26381ff
# github.com/stolostron/cluster-lifecycle-api v0.0.0-20230510064049-824d580bc143
## explicit; go 1.18
github.com/stolostron/cluster-lifecycle-api/action/v1beta1
github.com/stolostron/cluster-lifecycle-api/clusterinfo/v1beta1
Expand Down

0 comments on commit 3bcc084

Please sign in to comment.