Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ support work driver config for cluster manager. #381

Merged
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
1 change: 1 addition & 0 deletions deploy/cluster-manager/config/rbac/cluster_role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ rules:
- "work-controller-sa-kubeconfig"
- "addon-manager-controller-sa-kubeconfig"
- "external-hub-kubeconfig"
- "work-driver-config"
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create"]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ metadata:
categories: Integration & Delivery,OpenShift Optional
certified: "false"
containerImage: quay.io/open-cluster-management/registration-operator:latest
createdAt: "2024-04-10T15:46:14Z"
createdAt: "2024-04-17T07:51:41Z"
description: Manages the installation and upgrade of the ClusterManager.
operators.operatorframework.io/builder: operator-sdk-v1.32.0
operators.operatorframework.io/project_layout: go.kubebuilder.io/v3
Expand Down Expand Up @@ -146,6 +146,7 @@ spec:
- work-controller-sa-kubeconfig
- addon-manager-controller-sa-kubeconfig
- external-hub-kubeconfig
- work-driver-config
resources:
- secrets
verbs:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,51 @@ spec:
description: RegistrationConfiguration contains the configuration
of registration
properties:
bootstrapKubeConfigs:
description: "BootstrapKubeConfigs defines the ordered list of
bootstrap kubeconfigs. The order decides which bootstrap kubeconfig
to use first when rebootstrap. \n When the agent loses the connection
to the current hub over HubConnectionTimeoutSeconds, or the
managedcluster CR is set `hubAcceptsClient=false` on the hub,
the controller marks the related bootstrap kubeconfig as \"failed\".
\n A failed bootstrapkubeconfig won't be used for the duration
specified by SkipFailedBootstrapKubeConfigSeconds. But if the
user updates the content of a failed bootstrapkubeconfig, the
\"failed\" mark will be cleared."
properties:
localSecretsConfig:
description: LocalSecretsConfig include a list of secrets
that contains the kubeconfigs for ordered bootstrap kubeconifigs.
The secrets must be in the same namespace where the agent
controller runs.
properties:
hubConnectionTimeoutSeconds:
default: 600
description: HubConnectionTimeoutSeconds is used to set
the timeout of connecting to the hub cluster. When agent
loses the connection to the hub over the timeout seconds,
the agent do a rebootstrap. By default is 10 mins.
format: int32
minimum: 180
type: integer
secretNames:
description: SecretNames is a list of secret names. The
secrets are in the same namespace where the agent controller
runs.
items:
type: string
type: array
type: object
type:
default: None
description: Type specifies the type of priority bootstrap
kubeconfigs. By default, it is set to None, representing
no priority bootstrap kubeconfigs are set.
enum:
- None
- LocalSecrets
type: string
type: object
clientCertExpirationSeconds:
description: clientCertExpirationSeconds represents the seconds
of a client certificate to expire. If it is not set or 0, the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,51 @@ spec:
description: RegistrationConfiguration contains the configuration
of registration
properties:
bootstrapKubeConfigs:
description: "BootstrapKubeConfigs defines the ordered list of
bootstrap kubeconfigs. The order decides which bootstrap kubeconfig
to use first when rebootstrap. \n When the agent loses the connection
to the current hub over HubConnectionTimeoutSeconds, or the
managedcluster CR is set `hubAcceptsClient=false` on the hub,
the controller marks the related bootstrap kubeconfig as \"failed\".
\n A failed bootstrapkubeconfig won't be used for the duration
specified by SkipFailedBootstrapKubeConfigSeconds. But if the
user updates the content of a failed bootstrapkubeconfig, the
\"failed\" mark will be cleared."
properties:
localSecretsConfig:
description: LocalSecretsConfig include a list of secrets
that contains the kubeconfigs for ordered bootstrap kubeconifigs.
The secrets must be in the same namespace where the agent
controller runs.
properties:
hubConnectionTimeoutSeconds:
default: 600
description: HubConnectionTimeoutSeconds is used to set
the timeout of connecting to the hub cluster. When agent
loses the connection to the hub over the timeout seconds,
the agent do a rebootstrap. By default is 10 mins.
format: int32
minimum: 180
type: integer
secretNames:
description: SecretNames is a list of secret names. The
secrets are in the same namespace where the agent controller
runs.
items:
type: string
type: array
type: object
type:
default: None
description: Type specifies the type of priority bootstrap
kubeconfigs. By default, it is set to None, representing
no priority bootstrap kubeconfigs are set.
enum:
- None
- LocalSecrets
type: string
type: object
clientCertExpirationSeconds:
description: clientCertExpirationSeconds represents the seconds
of a client certificate to expire. If it is not set or 0, the
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ require (
k8s.io/kube-aggregator v0.29.3
k8s.io/utils v0.0.0-20240310230437-4693a0247e57
open-cluster-management.io/addon-framework v0.9.1-0.20240419070222-e703fc5a2556
open-cluster-management.io/api v0.13.1-0.20240411131856-8f6aa25f111c
open-cluster-management.io/api v0.13.1-0.20240419062633-aacb530ea4ad
open-cluster-management.io/sdk-go v0.13.1-0.20240416062924-20307e6fe090
sigs.k8s.io/controller-runtime v0.17.3
sigs.k8s.io/kube-storage-version-migrator v0.0.6-0.20230721195810-5c8923c5ff96
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -425,8 +425,8 @@ k8s.io/utils v0.0.0-20240310230437-4693a0247e57 h1:gbqbevonBh57eILzModw6mrkbwM0g
k8s.io/utils v0.0.0-20240310230437-4693a0247e57/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
open-cluster-management.io/addon-framework v0.9.1-0.20240419070222-e703fc5a2556 h1:X3vJEx9agC94l7SitpWZFDshISdL1niqVH0+diyqfJo=
open-cluster-management.io/addon-framework v0.9.1-0.20240419070222-e703fc5a2556/go.mod h1:HayKCznnlyW+0dUJQGj5sNR6i3tvylSySD3YnvZkBtY=
open-cluster-management.io/api v0.13.1-0.20240411131856-8f6aa25f111c h1:/iUoY6/PqBmcBq3v0+UBFvIcI39k/QPRGqpOv9XtDIc=
open-cluster-management.io/api v0.13.1-0.20240411131856-8f6aa25f111c/go.mod h1:CuCPEzXDvOyxBB0H1d1eSeajbHqaeGEKq9c63vQc63w=
open-cluster-management.io/api v0.13.1-0.20240419062633-aacb530ea4ad h1:DB3GpK5vzbGu9ss13bfodi8pGTkPcpdcLvOPEPMptTk=
open-cluster-management.io/api v0.13.1-0.20240419062633-aacb530ea4ad/go.mod h1:yrNuMMpciXjXPnj2yznb6LTyrGliiTrFZAJDp/Ck3c4=
open-cluster-management.io/sdk-go v0.13.1-0.20240416062924-20307e6fe090 h1:zFmHuW+ztdfUUNslqNW+H1WEcfdEUQHoRDbmdajX340=
open-cluster-management.io/sdk-go v0.13.1-0.20240416062924-20307e6fe090/go.mod h1:w2OaxtCyegxeyFLU42UQ3oxUz01QdsBQkcHI17T/l48=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.28.0 h1:TgtAeesdhpm2SGwkQasmbeqDo8th5wOBA5h/AjTKA4I=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,13 @@ spec:
args:
- "/work"
- "manager"
- "--work-driver=kube"
{{ if .CloudEventsDriverEnabled }}
- "--work-driver={{ .WorkDriver }}"
{{ if ne .WorkDriver "kube" }}
- "--cloudevents-client-id=work-controller-$(POD_NAME)"
- "--work-driver-config=/var/run/secrets/work/config.yaml"
{{ end }}
{{ end }}
{{ if .HostedMode }}
- "--kubeconfig=/var/run/secrets/hub/kubeconfig"
{{ end }}
Expand Down Expand Up @@ -97,6 +103,11 @@ spec:
name: kubeconfig
readOnly: true
{{ end }}
{{ if and .CloudEventsDriverEnabled (ne .WorkDriver "kube") }}
- mountPath: /var/run/secrets/work
name: workdriverconfig
readOnly: true
{{ end }}
volumes:
- name: tmpdir
emptyDir: { }
Expand All @@ -105,3 +116,8 @@ spec:
secret:
secretName: work-controller-sa-kubeconfig
{{ end }}
{{ if and .CloudEventsDriverEnabled (ne .WorkDriver "kube") }}
- name: workdriverconfig
secret:
secretName: work-driver-config
{{ end }}
2 changes: 2 additions & 0 deletions manifests/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ type HubConfig struct {
AddOnManagerImage string
AddOnManagerEnabled bool
MWReplicaSetEnabled bool
CloudEventsDriverEnabled bool
WorkDriver string
AutoApproveUsers string
// ResourceRequirementResourceType is the resource requirement resource type for the cluster manager managed containers.
ResourceRequirementResourceType operatorapiv1.ResourceQosClass
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ type clusterManagerController struct {
mwctrEnabled, addonManagerEnabled bool) error
generateHubClusterClients func(hubConfig *rest.Config) (kubernetes.Interface, apiextensionsclient.Interface,
migrationclient.StorageVersionMigrationsGetter, error)
skipRemoveCRDs bool
skipRemoveCRDs bool
operatorNamespace string
}

type clusterManagerReconcile interface {
Expand All @@ -83,6 +84,7 @@ func NewClusterManagerController(
configMapInformer corev1informers.ConfigMapInformer,
recorder events.Recorder,
skipRemoveCRDs bool,
operatorNamespace string,
) factory.Controller {
controller := &clusterManagerController{
operatorKubeClient: operatorKubeClient,
Expand All @@ -97,6 +99,7 @@ func NewClusterManagerController(
ensureSAKubeconfigs: ensureSAKubeconfigs,
cache: resourceapply.NewResourceCache(),
skipRemoveCRDs: skipRemoveCRDs,
operatorNamespace: operatorNamespace,
}

return factory.New().WithSync(controller.sync).
Expand Down Expand Up @@ -132,6 +135,12 @@ func (n *clusterManagerController) sync(ctx context.Context, controllerContext f
return err
}

// default driver is kube
workDriver := operatorapiv1.WorkDriverTypeKube
if clusterManager.Spec.WorkConfiguration != nil && clusterManager.Spec.WorkConfiguration.WorkDriver != "" {
workDriver = clusterManager.Spec.WorkConfiguration.WorkDriver
}

// This config is used to render template of manifests.
config := manifests.HubConfig{
ClusterManagerName: clusterManager.Name,
Expand All @@ -150,6 +159,7 @@ func (n *clusterManagerController) sync(ctx context.Context, controllerContext f
},
ResourceRequirementResourceType: helpers.ResourceType(clusterManager),
ResourceRequirements: resourceRequirements,
WorkDriver: string(workDriver),
}

var registrationFeatureMsgs, workFeatureMsgs, addonFeatureMsgs string
Expand All @@ -169,6 +179,7 @@ func (n *clusterManagerController) sync(ctx context.Context, controllerContext f
}
config.WorkFeatureGates, workFeatureMsgs = helpers.ConvertToFeatureGateFlags("Work", workFeatureGates, ocmfeature.DefaultHubWorkFeatureGates)
config.MWReplicaSetEnabled = helpers.FeatureGateEnabled(workFeatureGates, ocmfeature.DefaultHubWorkFeatureGates, ocmfeature.ManifestWorkReplicaSet)
config.CloudEventsDriverEnabled = helpers.FeatureGateEnabled(workFeatureGates, ocmfeature.DefaultHubWorkFeatureGates, ocmfeature.CloudEventsDrivers)

var addonFeatureGates []operatorapiv1.FeatureGate
if clusterManager.Spec.AddOnManagerConfiguration != nil {
Expand Down Expand Up @@ -211,6 +222,8 @@ func (n *clusterManagerController) sync(ctx context.Context, controllerContext f
reconcilers := []clusterManagerReconcile{
&crdReconcile{cache: n.cache, recorder: n.recorder, hubAPIExtensionClient: hubApiExtensionClient,
hubMigrationClient: hubMigrationClient, skipRemoveCRDs: n.skipRemoveCRDs},
&secretReconcile{cache: n.cache, recorder: n.recorder, operatorKubeClient: n.operatorKubeClient,
hubKubeClient: hubClient, operatorNamespace: n.operatorNamespace},
&hubReoncile{cache: n.cache, recorder: n.recorder, hubKubeClient: hubClient},
&runtimeReconcile{cache: n.cache, recorder: n.recorder, hubKubeConfig: hubKubeConfig, hubKubeClient: hubClient,
kubeClient: managementClient, ensureSAKubeconfigs: n.ensureSAKubeconfigs},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (

fakeoperatorlient "open-cluster-management.io/api/client/operator/clientset/versioned/fake"
operatorinformers "open-cluster-management.io/api/client/operator/informers/externalversions"
ocmfeature "open-cluster-management.io/api/feature"
operatorapiv1 "open-cluster-management.io/api/operator/v1"
"open-cluster-management.io/sdk-go/pkg/patcher"

Expand Down Expand Up @@ -75,6 +76,7 @@ func newClusterManager(name string) *operatorapiv1.ClusterManager {
},
WorkConfiguration: &operatorapiv1.WorkConfiguration{
FeatureGates: []operatorapiv1.FeatureGate{featureGate},
WorkDriver: operatorapiv1.WorkDriverTypeKube,
Copy link
Member

Choose a reason for hiding this comment

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

ut on other type would be needed.

Copy link
Member Author

Choose a reason for hiding this comment

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

added UT for sync work driver config secret and condition check.

},
},
}
Expand Down Expand Up @@ -299,6 +301,56 @@ func ensureObject(t *testing.T, object runtime.Object, hubCore *operatorapiv1.Cl
}
}

func TestSyncSecret(t *testing.T) {
operatorNamespace := metav1.NamespaceDefault
clusterManager := newClusterManager("testhub")
clusterManager.Spec.WorkConfiguration.FeatureGates = append(clusterManager.Spec.WorkConfiguration.FeatureGates,
operatorapiv1.FeatureGate{
Feature: string(ocmfeature.CloudEventsDrivers),
Mode: operatorapiv1.FeatureGateModeTypeEnable,
})
clusterManager.Spec.WorkConfiguration.WorkDriver = operatorapiv1.WorkDriverTypeGrpc
tc := newTestController(t, clusterManager)
tc.clusterManagerController.operatorNamespace = operatorNamespace
clusterManagerNamespace := helpers.ClusterManagerNamespace(clusterManager.Name, clusterManager.Spec.DeployOption.Mode)
setup(t, tc, nil)

syncContext := testingcommon.NewFakeSyncContext(t, "testhub")

err := tc.clusterManagerController.sync(ctx, syncContext)
if err != nil {
t.Fatalf("Expected no error when sync, %v", err)
}

workDriverConfig := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "work-driver-config",
},
Data: map[string][]byte{
"config.yaml": []byte("url: grpc.example.com:8443"),
},
}

if _, err = tc.managementKubeClient.CoreV1().Secrets(operatorNamespace).Create(ctx, workDriverConfig, metav1.CreateOptions{}); err != nil {
t.Fatalf("Failed to create work driver config secret: %v", err)
}

err = tc.clusterManagerController.sync(ctx, syncContext)
if err != nil {
t.Fatalf("Expected no error when sync, %v", err)
}

// TODO: add test for secret sync condition
syncedSecret, err := tc.hubKubeClient.CoreV1().Secrets(clusterManagerNamespace).Get(ctx, "work-driver-config", metav1.GetOptions{})
if err != nil {
t.Fatalf("Failed to get synced work driver config secret: %v", err)
}

if string(syncedSecret.Data["config.yaml"]) != "url: grpc.example.com:8443" {
t.Fatalf("Expected secret data to be url: grpc.example.com:8443")
}
}

// TestSyncDeploy tests sync manifests of hub component
func TestSyncDeploy(t *testing.T) {
clusterManager := newClusterManager("testhub")
Expand Down
Loading
Loading