Skip to content

Commit

Permalink
add --odf-operator-namespace flag to managedcluster addons
Browse files Browse the repository at this point in the history
Signed-off-by: Umanga Chapagain <[email protected]>
  • Loading branch information
umangachapagain committed Aug 1, 2024
1 parent 4dc2459 commit e68c54f
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 123 deletions.
14 changes: 7 additions & 7 deletions addons/agent_mirrorpeer_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,12 @@ import (

// MirrorPeerReconciler reconciles a MirrorPeer object
type MirrorPeerReconciler struct {
HubClient client.Client
Scheme *runtime.Scheme
SpokeClient client.Client
SpokeClusterName string
Logger *slog.Logger
HubClient client.Client
Scheme *runtime.Scheme
SpokeClient client.Client
SpokeClusterName string
OdfOperatorNamespace string
Logger *slog.Logger
}

// Reconcile is part of the main kubernetes reconciliation loop which aims to
Expand Down Expand Up @@ -174,7 +175,6 @@ func (r *MirrorPeerReconciler) Reconcile(ctx context.Context, req ctrl.Request)
return ctrl.Result{}, err
}
if err == nil {
// TODO: Replace it with exported type from ocs-operator
type OnboardingTicket struct {
ID string `json:"id"`
ExpirationDate int64 `json:"expirationDate,string"`
Expand All @@ -196,7 +196,7 @@ func (r *MirrorPeerReconciler) Reconcile(ctx context.Context, req ctrl.Request)
}
}
logger.Info("Creating a new onboarding token", "Token", token.Name)
err = createStorageClusterPeerTokenSecret(ctx, r.HubClient, r.Scheme, r.SpokeClusterName, "openshift-storage", mirrorPeer, scr) //TODO: get odfOperatorNamespace from addon flags
err = createStorageClusterPeerTokenSecret(ctx, r.HubClient, r.Scheme, r.SpokeClusterName, r.OdfOperatorNamespace, mirrorPeer, scr)
if err != nil {
logger.Error("Failed to create StorageCluster peer token on the hub.", "error", err)
return ctrl.Result{}, err
Expand Down
13 changes: 8 additions & 5 deletions addons/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ type AddonAgentOptions struct {
ProbeAddr string
HubKubeconfigFile string
SpokeClusterName string
OdfOperatorNamespace string
DRMode string
DevMode bool
}
Expand All @@ -99,6 +100,7 @@ func (o *AddonAgentOptions) AddFlags(cmd *cobra.Command) {
"Enabling this will ensure there is only one active controller manager.")
flags.StringVar(&o.HubKubeconfigFile, "hub-kubeconfig", o.HubKubeconfigFile, "Location of kubeconfig file to connect to hub cluster.")
flags.StringVar(&o.SpokeClusterName, "cluster-name", o.SpokeClusterName, "Name of spoke cluster.")
flags.StringVar(&o.OdfOperatorNamespace, "odf-operator-namespace", o.OdfOperatorNamespace, "Namespace of ODF operator on the spoke cluster.")
flags.StringVar(&o.DRMode, "mode", o.DRMode, "The DR mode of token exchange addon. Valid values are: 'sync', 'async'")
flags.BoolVar(&o.DevMode, "dev", false, "Set to true for dev environment (Text logging)")
}
Expand Down Expand Up @@ -184,11 +186,12 @@ func runHubManager(ctx context.Context, options AddonAgentOptions, logger *slog.
}

if err = (&MirrorPeerReconciler{
Scheme: mgr.GetScheme(),
HubClient: mgr.GetClient(),
SpokeClient: spokeClient,
SpokeClusterName: options.SpokeClusterName,
Logger: logger.With("controller", "MirrorPeerReconciler"),
Scheme: mgr.GetScheme(),
HubClient: mgr.GetClient(),
SpokeClient: spokeClient,
SpokeClusterName: options.SpokeClusterName,
OdfOperatorNamespace: options.OdfOperatorNamespace,
Logger: logger.With("controller", "MirrorPeerReconciler"),
}).SetupWithManager(mgr); err != nil {
logger.Error("Failed to create MirrorPeer controller", "controller", "MirrorPeer", "error", err)
os.Exit(1)
Expand Down
13 changes: 13 additions & 0 deletions addons/setup/addon_setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,17 +84,30 @@ func (a *Addons) Manifests(cluster *clusterv1.ManagedCluster, addon *addonapiv1a
groups := agent.DefaultGroups(cluster.Name, a.AddonName)
user := agent.DefaultUser(cluster.Name, a.AddonName, a.AddonName)

var odfOperatorNamespace string
if utils.HasRequiredODFKey(cluster) {
odfOperatorNamespacedName, err := utils.GetNamespacedNameForClusterInfo(*cluster)
if err != nil {
return objects, fmt.Errorf("error while getting ODF operator namespace on the spoke cluster %q. %w", cluster.Name, err)
}
odfOperatorNamespace = odfOperatorNamespacedName.Namespace
} else {
return objects, fmt.Errorf("error while getting ODF operator namespace on the spoke cluster %q. Expected ClusterClaim does not exist", cluster.Name)
}

manifestConfig := struct {
KubeConfigSecret string
ClusterName string
AddonInstallNamespace string
OdfOperatorNamespace string
Image string
DRMode string
Group string
User string
}{
KubeConfigSecret: fmt.Sprintf("%s-hub-kubeconfig", a.AddonName),
AddonInstallNamespace: installNamespace,
OdfOperatorNamespace: odfOperatorNamespace,
ClusterName: cluster.Name,
Image: a.AgentImage,
DRMode: addon.Annotations[utils.DRModeAnnotationKey],
Expand Down
1 change: 1 addition & 0 deletions addons/setup/tokenexchange-manifests/spoke_deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ spec:
- "addons"
- "--hub-kubeconfig=/var/run/hub/kubeconfig"
- "--cluster-name={{ .ClusterName }}"
- "--odf-operator-namespace={{ .OdfOperatorNamespace }}"
- "--mode={{ .DRMode }}"
volumeMounts:
- name: hub-config
Expand Down
37 changes: 3 additions & 34 deletions controllers/managedcluster_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ import (
"context"
"fmt"
"log/slog"
"strings"

"github.com/red-hat-storage/odf-multicluster-orchestrator/controllers/utils"
viewv1beta1 "github.com/stolostron/multicloud-operators-foundation/pkg/apis/view/v1beta1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
clusterv1 "open-cluster-management.io/api/cluster/v1"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
Expand All @@ -25,10 +23,6 @@ type ManagedClusterReconciler struct {
Logger *slog.Logger
}

const (
OdfInfoClusterClaimNamespacedName = "odfinfo.odf.openshift.io"
)

func (r *ManagedClusterReconciler) Reconcile(ctx context.Context, req reconcile.Request) (reconcile.Result, error) {
logger := r.Logger.With("ManagedCluster", req.NamespacedName)
logger.Info("Reconciling ManagedCluster")
Expand All @@ -51,16 +45,6 @@ func (r *ManagedClusterReconciler) Reconcile(ctx context.Context, req reconcile.
return ctrl.Result{}, nil
}

func hasRequiredODFKey(mc *clusterv1.ManagedCluster) bool {
claims := mc.Status.ClusterClaims
for _, claim := range claims {
if claim.Name == OdfInfoClusterClaimNamespacedName {
return true
}
}
return false

}
func (r *ManagedClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
r.Logger.Info("Setting up ManagedClusterReconciler with manager")
managedClusterPredicate := predicate.Funcs{
Expand All @@ -69,14 +53,14 @@ func (r *ManagedClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {
if !ok {
return false
}
return hasRequiredODFKey(obj)
return utils.HasRequiredODFKey(obj)
},
CreateFunc: func(e event.CreateEvent) bool {
obj, ok := e.Object.(*clusterv1.ManagedCluster)
if !ok {
return false
}
return hasRequiredODFKey(obj)
return utils.HasRequiredODFKey(obj)
},
}

Expand All @@ -89,7 +73,7 @@ func (r *ManagedClusterReconciler) SetupWithManager(mgr ctrl.Manager) error {

func (r *ManagedClusterReconciler) processManagedClusterViews(ctx context.Context, managedCluster clusterv1.ManagedCluster) error {
resourceType := "ConfigMap"
odfInfoConfigMapNamespacedName, err := getNamespacedNameForClusterInfo(managedCluster)
odfInfoConfigMapNamespacedName, err := utils.GetNamespacedNameForClusterInfo(managedCluster)
if err != nil {
return fmt.Errorf("error while getting NamespacedName of the %s. %w", resourceType, err)
}
Expand All @@ -114,18 +98,3 @@ func (r *ManagedClusterReconciler) processManagedClusterViews(ctx context.Contex

return nil
}

func getNamespacedNameForClusterInfo(managedCluster clusterv1.ManagedCluster) (types.NamespacedName, error) {
clusterClaims := managedCluster.Status.ClusterClaims
for _, claim := range clusterClaims {
if claim.Name == OdfInfoClusterClaimNamespacedName {
namespacedName := strings.Split(claim.Value, "/")
if len(namespacedName) != 2 {
return types.NamespacedName{}, fmt.Errorf("invalid format for namespaced name claim: expected 'namespace/name', got '%s'", claim.Value)
}
return types.NamespacedName{Namespace: namespacedName[0], Name: namespacedName[1]}, nil
}
}

return types.NamespacedName{}, fmt.Errorf("cannot find ClusterClaim %q in ManagedCluster status", OdfInfoClusterClaimNamespacedName)
}
80 changes: 4 additions & 76 deletions controllers/managedcluster_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ package controllers

import (
"context"
"reflect"
"testing"

"github.com/red-hat-storage/odf-multicluster-orchestrator/controllers/utils"
Expand Down Expand Up @@ -50,7 +49,7 @@ func TestManagedClusterReconcile(t *testing.T) {
Status: clusterv1.ManagedClusterStatus{
ClusterClaims: []clusterv1.ManagedClusterClaim{
{
Name: OdfInfoClusterClaimNamespacedName,
Name: utils.OdfInfoClusterClaimNamespacedName,
Value: "openshift-storage/odf-info",
},
},
Expand Down Expand Up @@ -86,7 +85,7 @@ func TestProcessManagedClusterViews(t *testing.T) {
Status: clusterv1.ManagedClusterStatus{
ClusterClaims: []clusterv1.ManagedClusterClaim{
{
Name: OdfInfoClusterClaimNamespacedName,
Name: utils.OdfInfoClusterClaimNamespacedName,
Value: "openshift-storage/odf-info",
},
},
Expand Down Expand Up @@ -127,7 +126,7 @@ func TestProcessManagedClusterViews(t *testing.T) {
Status: clusterv1.ManagedClusterStatus{
ClusterClaims: []clusterv1.ManagedClusterClaim{
{
Name: OdfInfoClusterClaimNamespacedName,
Name: utils.OdfInfoClusterClaimNamespacedName,
Value: "openshift-storage/odf-info",
},
},
Expand Down Expand Up @@ -166,7 +165,7 @@ func TestProcessManagedClusterViews(t *testing.T) {
Status: clusterv1.ManagedClusterStatus{
ClusterClaims: []clusterv1.ManagedClusterClaim{
{
Name: OdfInfoClusterClaimNamespacedName,
Name: utils.OdfInfoClusterClaimNamespacedName,
Value: "openshift-storage/odf-info",
},
},
Expand All @@ -176,74 +175,3 @@ func TestProcessManagedClusterViews(t *testing.T) {
assert.NoError(t, err)
})
}

func Test_getNamespacedNameForClusterInfo(t *testing.T) {
type args struct {
managedCluster clusterv1.ManagedCluster
}
tests := []struct {
name string
args args
want types.NamespacedName
wantErr bool
}{
{
name: "Valid Namespaced Name Claim",
args: args{
managedCluster: clusterv1.ManagedCluster{
Status: clusterv1.ManagedClusterStatus{
ClusterClaims: []clusterv1.ManagedClusterClaim{
{
Name: OdfInfoClusterClaimNamespacedName,
Value: "namespace/name",
},
},
},
},
},
want: types.NamespacedName{Namespace: "namespace", Name: "name"},
wantErr: false,
},
{
name: "Missing Namespaced Name Claim",
args: args{
managedCluster: clusterv1.ManagedCluster{
Status: clusterv1.ManagedClusterStatus{
ClusterClaims: []clusterv1.ManagedClusterClaim{},
},
},
},
want: types.NamespacedName{},
wantErr: true,
},
{
name: "Invalid Format for Namespaced Name Claim",
args: args{
managedCluster: clusterv1.ManagedCluster{
Status: clusterv1.ManagedClusterStatus{
ClusterClaims: []clusterv1.ManagedClusterClaim{
{
Name: OdfInfoClusterClaimNamespacedName,
Value: "invalidformat",
},
},
},
},
},
want: types.NamespacedName{},
wantErr: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := getNamespacedNameForClusterInfo(tt.args.managedCluster)
if (err != nil) != tt.wantErr {
t.Errorf("getNamespacedNameForClusterInfo() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("getNamespacedNameForClusterInfo() = %v, want %v", got, tt.want)
}
})
}
}
33 changes: 32 additions & 1 deletion controllers/utils/managedcluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@ package utils
import (
"context"
"fmt"
"strings"

"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/types"
clusterv1 "open-cluster-management.io/api/cluster/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

const clusterIDLabelKey = "clusterID"
const (
clusterIDLabelKey = "clusterID"
OdfInfoClusterClaimNamespacedName = "odfinfo.odf.openshift.io"
)

// GetManagedClusterById fetches a ManagedCluster by its cluster ID label
func GetManagedClusterById(ctx context.Context, c client.Client, clusterId string) (*clusterv1.ManagedCluster, error) {
Expand All @@ -34,3 +39,29 @@ func GetManagedClusterById(ctx context.Context, c client.Client, clusterId strin
// Return the first matching ManagedCluster (there should only be one)
return &managedClusterList.Items[0], nil
}

func GetNamespacedNameForClusterInfo(managedCluster clusterv1.ManagedCluster) (types.NamespacedName, error) {
clusterClaims := managedCluster.Status.ClusterClaims
for _, claim := range clusterClaims {
if claim.Name == OdfInfoClusterClaimNamespacedName {
namespacedName := strings.Split(claim.Value, "/")
if len(namespacedName) != 2 {
return types.NamespacedName{}, fmt.Errorf("invalid format for namespaced name claim: expected 'namespace/name', got '%s'", claim.Value)
}
return types.NamespacedName{Namespace: namespacedName[0], Name: namespacedName[1]}, nil
}
}

return types.NamespacedName{}, fmt.Errorf("cannot find ClusterClaim %q in ManagedCluster status", OdfInfoClusterClaimNamespacedName)
}

func HasRequiredODFKey(mc *clusterv1.ManagedCluster) bool {
claims := mc.Status.ClusterClaims
for _, claim := range claims {
if claim.Name == OdfInfoClusterClaimNamespacedName {
return true
}
}
return false

}
Loading

0 comments on commit e68c54f

Please sign in to comment.