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

kustomize renderer pipeline #14

Draft
wants to merge 1 commit into
base: initialize_api
Choose a base branch
from
Draft
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
166 changes: 70 additions & 96 deletions controllers/components/dashboard_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ package components

import (
"context"
"errors"
"fmt"
"path/filepath"

appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
Expand All @@ -45,7 +43,7 @@ import (
odhrec "github.com/opendatahub-io/opendatahub-operator/v2/pkg/controller/reconciler"
odhtypes "github.com/opendatahub-io/opendatahub-operator/v2/pkg/controller/types"
"github.com/opendatahub-io/opendatahub-operator/v2/pkg/deploy"
ctrlogger "github.com/opendatahub-io/opendatahub-operator/v2/pkg/logger"
"github.com/opendatahub-io/opendatahub-operator/v2/pkg/manifests/kustomize"
"github.com/opendatahub-io/opendatahub-operator/v2/pkg/metadata/labels"
)

Expand Down Expand Up @@ -73,17 +71,36 @@ func NewDashboardReconciler(ctx context.Context, mgr ctrl.Manager) error {
}

actionCtx := logf.IntoContext(ctx, r.Log)
d := Dashboard{}

// Add Dashboard-specific actions
r.AddAction(&InitializeAction{actions.BaseAction{Log: mgr.GetLogger().WithName("actions").WithName("initialize")}})
r.AddAction(&SupportDevFlagsAction{actions.BaseAction{Log: mgr.GetLogger().WithName("actions").WithName("devFlags")}})
r.AddAction(&CleanupOAuthClientAction{actions.BaseAction{Log: mgr.GetLogger().WithName("actions").WithName("cleanup")}})
r.AddAction(&DeployComponentAction{actions.BaseAction{Log: mgr.GetLogger().WithName("actions").WithName("deploy")}})
r.AddAction(actions.NewActionFn(actionCtx, d.initialize))
r.AddAction(actions.NewActionFn(actionCtx, d.devFlags))

r.AddAction(actions.NewRenderManifestsAction(
actionCtx,
actions.WithRenderManifestsOptions(
kustomize.WithEngineRenderOpts(
kustomize.WithLabel(labels.ComponentName, ComponentName),
),
),
))

r.AddAction(actions.NewActionFn(actionCtx, d.customizeResources))

r.AddAction(actions.NewDeployAction(
actionCtx,
actions.WithDeployedResourceFieldOwner(ComponentName),
))

r.AddAction(actions.NewUpdateStatusAction(
actionCtx,
actions.WithUpdateStatusLabel(labels.ComponentName, ComponentName),
))

// finalization
r.AddFinalizer(actions.NewActionFn(ctx, d.cleanupOAuthClient))

eh := handler.EnqueueRequestsFromMapFunc(watchDashboardResources)

err = ctrl.NewControllerManagedBy(mgr).
Expand All @@ -101,6 +118,7 @@ func NewDashboardReconciler(ctx context.Context, mgr ctrl.Manager) error {
Watches(&corev1.ServiceAccount{}, eh).
// shared filter
WithEventFilter(dashboardPredicates).
// done
Complete(r)

if err != nil {
Expand Down Expand Up @@ -166,11 +184,12 @@ func CreateDashboardInstance(dsc *dscv1.DataScienceCluster) *componentsv1.Dashbo
// +kubebuilder:rbac:groups="*",resources=replicasets,verbs=*

func watchDashboardResources(_ context.Context, a client.Object) []reconcile.Request {
if a.GetLabels()["app.opendatahub.io/dashboard"] == "true" {
if a.GetLabels()[labels.ODH.Component(ComponentNameUpstream)] == "true" || a.GetLabels()[labels.ODH.Component(ComponentNameDownstream)] == "true" {
return []reconcile.Request{{
NamespacedName: types.NamespacedName{Name: DashboardInstanceName},
}}
}

return nil
}

Expand Down Expand Up @@ -200,6 +219,7 @@ var dashboardPredicates = predicate.Funcs{
},
}

//nolint:unused
func updateKustomizeVariable(ctx context.Context, cli client.Client, platform cluster.Platform, dscispec *dsciv1.DSCInitializationSpec) (map[string]string, error) {
adminGroups := map[cluster.Platform]string{
cluster.SelfManagedRhods: "rhods-admins",
Expand Down Expand Up @@ -233,13 +253,11 @@ func updateKustomizeVariable(ctx context.Context, cli client.Client, platform cl
}, nil
}

// Action implementations
// TODO added only to avoid name collision

type InitializeAction struct {
actions.BaseAction
}
type Dashboard struct{}

func (a *InitializeAction) Execute(ctx context.Context, rr *odhtypes.ReconciliationRequest) error {
func (d Dashboard) initialize(ctx context.Context, rr *odhtypes.ReconciliationRequest) error {
// Implement initialization logic
log := logf.FromContext(ctx).WithName(ComponentNameUpstream)

Expand All @@ -254,7 +272,20 @@ func (a *InitializeAction) Execute(ctx context.Context, rr *odhtypes.Reconciliat
}
DefaultPath = manifestMap[rr.Platform]

rr.Manifests = manifestMap
componentName := ComponentNameDownstream
if rr.Platform == cluster.SelfManagedRhods || rr.Platform == cluster.ManagedRhods {
componentName = ComponentNameDownstream
}

rr.Manifests = []odhtypes.ManifestInfo{{
Path: DefaultPath,
ContextDir: "",
SourcePath: "",
RenderOpts: []kustomize.RenderOptsFn{
kustomize.WithLabel(labels.ODH.Component(componentName), "true"),
kustomize.WithLabel(labels.K8SCommon.PartOf, componentName),
},
}}

if err := deploy.ApplyParams(DefaultPath, imageParamMap); err != nil {
log.Error(err, "failed to update image", "path", DefaultPath)
Expand All @@ -263,11 +294,7 @@ func (a *InitializeAction) Execute(ctx context.Context, rr *odhtypes.Reconciliat
return nil
}

type SupportDevFlagsAction struct {
actions.BaseAction
}

func (a *SupportDevFlagsAction) Execute(ctx context.Context, rr *odhtypes.ReconciliationRequest) error {
func (d Dashboard) devFlags(ctx context.Context, rr *odhtypes.ReconciliationRequest) error {
dashboard, ok := rr.Instance.(*componentsv1.Dashboard)
if !ok {
return fmt.Errorf("resource instance %v is not a componentsv1.Dashboard)", rr.Instance)
Expand All @@ -284,84 +311,40 @@ func (a *SupportDevFlagsAction) Execute(ctx context.Context, rr *odhtypes.Reconc
return err
}
if manifestConfig.SourcePath != "" {
rr.Manifests[rr.Platform] = filepath.Join(deploy.DefaultManifestPath, ComponentNameUpstream, manifestConfig.SourcePath)
rr.Manifests[0].Path = deploy.DefaultManifestPath
rr.Manifests[0].ContextDir = ComponentNameUpstream
rr.Manifests[0].SourcePath = manifestConfig.SourcePath
}
}

if rr.DSCI.Spec.DevFlags != nil {
mode := rr.DSCI.Spec.DevFlags.LogMode
a.Log = ctrlogger.NewNamedLogger(logf.FromContext(ctx), ComponentName, mode)
}

return nil
}

type CleanupOAuthClientAction struct {
actions.BaseAction
}
func (d Dashboard) cleanupOAuthClient(ctx context.Context, rr *odhtypes.ReconciliationRequest) error {
oauthClientSecret := corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "dashboard-oauth-client",
Namespace: rr.DSCI.Spec.ApplicationsNamespace,
},
}

func (a *CleanupOAuthClientAction) Execute(ctx context.Context, rr *odhtypes.ReconciliationRequest) error {
// Remove previous oauth-client secrets
// Check if component is going from state of `Not Installed --> Installed`
// Assumption: Component is currently set to enabled
name := "dashboard-oauth-client"

// r.Log.Info("Cleanup any left secret")
// Delete client secrets from previous installation
oauthClientSecret := &corev1.Secret{}
err := rr.Client.Get(ctx, client.ObjectKey{
Namespace: rr.DSCI.Spec.ApplicationsNamespace,
Name: name,
}, oauthClientSecret)
if err != nil {
if !k8serr.IsNotFound(err) {
return fmt.Errorf("error getting secret %s: %w", name, err)
}
} else {
if err := rr.Client.Delete(ctx, oauthClientSecret); err != nil {
return fmt.Errorf("error deleting secret %s: %w", name, err)
}
// r.Log.Info("successfully deleted secret", "secret", name)
err := rr.Client.Delete(ctx, &oauthClientSecret)
if err != nil && !k8serr.IsNotFound(err) {
return fmt.Errorf("error deleting secret %s: %w", oauthClientSecret.Name, err)
}

return nil
}

type DeployComponentAction struct {
actions.BaseAction
}

func (a *DeployComponentAction) Execute(ctx context.Context, rr *odhtypes.ReconciliationRequest) error {
// Implement component deployment logic
// 1. platform specific RBAC
if rr.Platform == cluster.OpenDataHub || rr.Platform == "" {
if err := cluster.UpdatePodSecurityRolebinding(ctx, rr.Client, rr.DSCI.Spec.ApplicationsNamespace, "odh-dashboard"); err != nil {
return err
}
} else {
func (d Dashboard) customizeResources(ctx context.Context, rr *odhtypes.ReconciliationRequest) error {
switch rr.Platform {
case cluster.SelfManagedRhods, cluster.ManagedRhods:
if err := cluster.UpdatePodSecurityRolebinding(ctx, rr.Client, rr.DSCI.Spec.ApplicationsNamespace, "rhods-dashboard"); err != nil {
return err
}
}

// 2. Append or Update variable for component to consume
_, err := updateKustomizeVariable(ctx, rr.Client, rr.Platform, &rr.DSCI.Spec)
if err != nil {
return errors.New("failed to set variable for extraParamsMap")
}

// 3. update params.env regardless devFlags is provided of not
// if err := deploy.ApplyParams(r.entryPath, nil, extraParamsMap); err != nil {
// return fmt.Errorf("failed to update params.env from %s : %w", r.entryPath, err)
// }

path := rr.Manifests[rr.Platform]
name := ComponentNameUpstream

// common: Deploy odh-dashboard manifests
// TODO: check if we can have the same component name odh-dashboard for both, or still keep rhods-dashboard for RHOAI
switch rr.Platform {
case cluster.SelfManagedRhods, cluster.ManagedRhods:
// TODO this should be added to rr.Resources and let the final deploy action
// to apply the resource to the cluster
//
// anaconda
blckownerDel := true
ctrlr := true
Expand All @@ -381,28 +364,19 @@ func (a *DeployComponentAction) Execute(ctx context.Context, rr *odhtypes.Reconc
}),
cluster.WithLabels(
labels.ComponentName, ComponentName,
labels.ODH.Component(name), "true",
labels.K8SCommon.PartOf, name,
labels.ODH.Component(ComponentNameUpstream), "true",
labels.K8SCommon.PartOf, ComponentNameUpstream,
),
)

if err != nil {
return fmt.Errorf("failed to create access-secret for anaconda: %w", err)
}

name = ComponentNameDownstream
default:
if err := cluster.UpdatePodSecurityRolebinding(ctx, rr.Client, rr.DSCI.Spec.ApplicationsNamespace, "odh-dashboard"); err != nil {
return err
}
}

err = deploy.DeployManifestsFromPathWithLabels(ctx, rr.Client, rr.Instance, path, rr.DSCI.Spec.ApplicationsNamespace, name, true, map[string]string{
labels.ComponentName: ComponentName,
})

if err != nil {
return fmt.Errorf("failed to apply manifests from %s: %w", name, err)
}

a.Log.Info("apply manifests done")

return nil
}
Loading
Loading