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

feat: introduces conditional control plane installation #10

Merged
Merged
Show file tree
Hide file tree
Changes from 14 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
20 changes: 17 additions & 3 deletions apis/ossm.plugins.kubeflow.org/v1alpha1/ossm_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,25 @@ type OssmPluginSpec struct {
Auth AuthSpec `json:"auth,omitempty"`
}

// InstallationMode defines how plugin should handle OpenShift Service Mesh.
type InstallationMode string

var (
// Existing indicates that KfDef plugin for Openshift Service Mesh will use existing
// installation and patch Service Mesh Control Plane.
Existing InstallationMode = "Existing"
// Managed results in installing Openshift Service Mesh Control Plane
// in defined namespace.
Managed InstallationMode = "Managed"
)

// MeshSpec holds information on how Service Mesh should be configured.
type MeshSpec struct {
Name string `json:"name,omitempty"`
Namespace string `json:"namespace,omitempty"`
Certificate CertSpec `json:"certificate,omitempty"`
Name string `json:"name,omitempty"`
Namespace string `json:"namespace,omitempty"`
// +kubebuilder:validation:Enum=Managed;Existing
Mode InstallationMode `json:"mode,omitempty"`
Certificate CertSpec `json:"certificate,omitempty"`
}

type CertSpec struct {
Expand Down
7 changes: 7 additions & 0 deletions config/crd/bases/ossm.plugins.kubeflow.org_ossmplugins.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ spec:
name:
type: string
type: object
mode:
description: InstallationMode defines how plugin should handle
OpenShift Service Mesh.
enum:
- Managed
- Existing
type: string
name:
type: string
namespace:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ spec:
name:
type: string
type: object
mode:
description: InstallationMode defines how plugin should handle
OpenShift Service Mesh.
type: string
name:
type: string
namespace:
Expand Down
7 changes: 3 additions & 4 deletions controllers/kfdef.apps.kubeflow.org/kfdef_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,12 +247,11 @@ func (r *KfDefReconciler) Reconcile(ctx context.Context, request ctrl.Request) (
}

// set status of the KfDef resource
if err := r.reconcileStatus(instance); err != nil {
return ctrl.Result{}, err
if reconcileError := r.reconcileStatus(instance); reconcileError != nil {
return ctrl.Result{}, reconcileError
}

// If deployment created successfully - don't requeue
return ctrl.Result{}, nil
return ctrl.Result{}, err
}

// SetupWithManager sets up the controller with the Manager.
Expand Down
6 changes: 5 additions & 1 deletion controllers/kfdef.apps.kubeflow.org/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ func (r *KfDefReconciler) reconcileStatus(cr *kfdefv1.KfDef) error {
func getReconcileStatus(cr *kfdefv1.KfDef, err error) error {
conditions := []kfdefv1.KfDefCondition{}

availabilityStatus := corev1.ConditionTrue

if err != nil {
availabilityStatus = corev1.ConditionFalse

conditions = append(conditions, kfdefv1.KfDefCondition{
LastUpdateTime: cr.CreationTimestamp,
Status: corev1.ConditionTrue,
Expand All @@ -51,7 +55,7 @@ func getReconcileStatus(cr *kfdefv1.KfDef, err error) error {

conditions = append(conditions, kfdefv1.KfDefCondition{
LastUpdateTime: cr.CreationTimestamp,
Status: corev1.ConditionTrue,
Status: availabilityStatus,
Reason: DeploymentCompleted,
Type: kfdefv1.KfAvailable,
})
Expand Down
25 changes: 22 additions & 3 deletions pkg/kfapp/coordinator/coordinator.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,22 @@ func (kfapp *coordinator) Apply(resources kftypesv3.ResourceEnum) error {
}
}

serviceMeshConfig := func() error {
if kfapp.KfDef.Spec.Platform != kftypesv3.OSSM {
return nil
}

if p, ok := kfapp.Platforms[kfapp.KfDef.Spec.Platform]; !ok {
return &kfapis.KfError{
Code: int(kfapis.INTERNAL_ERROR),
Message: "Platform OSSM specified but not loaded.",
}
} else {
ossmInstaller := p.(*ossm.OssmInstaller)
return ossmInstaller.Apply(kftypesv3.K8S)
}
}

if err := kfapp.KfDef.SyncCache(); err != nil {
return &kfapis.KfError{
Code: int(kfapis.INTERNAL_ERROR),
Expand All @@ -423,6 +439,9 @@ func (kfapp *coordinator) Apply(resources kftypesv3.ResourceEnum) error {
case kftypesv3.PLATFORM:
return platform()
case kftypesv3.K8S:
if err := serviceMeshConfig(); err != nil {
return err
}
if err := k8s(); err != nil {
return err
}
Expand Down Expand Up @@ -471,7 +490,7 @@ func (kfapp *coordinator) Delete(resources kftypesv3.ResourceEnum) error {
return nil
}

ossmCleanup := func() error {
serviceMeshCleanup := func() error {
if kfapp.KfDef.Spec.Platform != kftypesv3.OSSM {
return nil
}
Expand All @@ -483,7 +502,7 @@ func (kfapp *coordinator) Delete(resources kftypesv3.ResourceEnum) error {
}
} else {
ossmInstaller := p.(*ossm.OssmInstaller)
return ossmInstaller.CleanupResources()
return ossmInstaller.Delete(kftypesv3.K8S)
}
}

Expand Down Expand Up @@ -515,7 +534,7 @@ func (kfapp *coordinator) Delete(resources kftypesv3.ResourceEnum) error {
if err := k8s(); err != nil {
return err
}
return ossmCleanup()
return serviceMeshCleanup()
}
return nil
}
Expand Down
34 changes: 31 additions & 3 deletions pkg/kfapp/ossm/feature/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package feature
import (
"github.com/opendatahub-io/opendatahub-operator/pkg/kfconfig/ossmplugin"
"github.com/pkg/errors"
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
Expand Down Expand Up @@ -53,6 +54,10 @@ func (fb *featureBuilder) UsingConfig(config *rest.Config) *featureBuilder {
return errors.WithStack(err)
}

if err := apiextv1.AddToScheme(f.client.Scheme()); err != nil {
cam-garrison marked this conversation as resolved.
Show resolved Hide resolved
return err
}

return nil
})

Expand Down Expand Up @@ -99,6 +104,16 @@ func (fb *featureBuilder) Preconditions(preconditions ...action) *featureBuilder
return fb
}

func (fb *featureBuilder) Postconditions(postconditions ...action) *featureBuilder {
fb.builders = append(fb.builders, func(f *Feature) error {
f.postconditions = append(f.postconditions, postconditions...)

return nil
})

return fb
}

func (fb *featureBuilder) OnDelete(cleanups ...action) *featureBuilder {
fb.builders = append(fb.builders, func(f *Feature) error {
f.addCleanup(cleanups...)
Expand All @@ -119,9 +134,20 @@ func (fb *featureBuilder) WithResources(resources ...action) *featureBuilder {
return fb
}

func (fb *featureBuilder) EnabledIf(enabled func(f *Feature) bool) *featureBuilder {
fb.builders = append(fb.builders, func(f *Feature) error {
f.Enabled = enabled(f)

return nil

})
return fb
}

func (fb *featureBuilder) Load() (*Feature, error) {
feature := &Feature{
Name: fb.name,
Name: fb.name,
Enabled: true,
}

for i := range fb.builders {
Expand All @@ -130,8 +156,10 @@ func (fb *featureBuilder) Load() (*Feature, error) {
}
}

if err := feature.createResourceTracker(); err != nil {
return nil, err
if feature.Enabled {
if err := feature.createResourceTracker(); err != nil {
return feature, err
}
}

return feature, nil
Expand Down
36 changes: 14 additions & 22 deletions pkg/kfapp/ossm/feature/cleanup.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
)

var smcpGVR = schema.GroupVersionResource{
Group: "maistra.io",
Version: "v2",
Resource: "servicemeshcontrolplanes",
}

func RemoveTokenVolumes(feature *Feature) error {
tokenVolume := fmt.Sprintf("%s-oauth2-tokens", feature.Spec.AppNamespace)

gvr := schema.GroupVersionResource{
Group: "maistra.io",
Version: "v2",
Resource: "servicemeshcontrolplanes",
}

meshNs := feature.Spec.Mesh.Namespace
meshName := feature.Spec.Mesh.Name

smcp, err := feature.dynamicClient.Resource(gvr).Namespace(meshNs).Get(context.Background(), meshName, metav1.GetOptions{})
smcp, err := feature.dynamicClient.Resource(smcpGVR).Namespace(meshNs).Get(context.Background(), meshName, metav1.GetOptions{})
if err != nil {
return err
}
Expand All @@ -37,7 +37,7 @@ func RemoveTokenVolumes(feature *Feature) error {
for i, v := range volumes {
volume, ok := v.(map[string]interface{})
if !ok {
fmt.Println("Unexpected type for volume")
log.Info("unexpected type for volume", "type", fmt.Sprintf("%T", volume))
continue
}

Expand All @@ -46,7 +46,7 @@ func RemoveTokenVolumes(feature *Feature) error {
return err
}
if !found {
fmt.Println("No volumeMount found in the volume")
log.Info("no volumeMount found in the volume")
continue
}

Expand All @@ -60,12 +60,9 @@ func RemoveTokenVolumes(feature *Feature) error {
}
}

_, err = feature.dynamicClient.Resource(gvr).Namespace(meshNs).Update(context.Background(), smcp, metav1.UpdateOptions{})
if err != nil {
return err
}
_, err = feature.dynamicClient.Resource(smcpGVR).Namespace(meshNs).Update(context.Background(), smcp, metav1.UpdateOptions{})

return nil
return err
}

func RemoveOAuthClient(feature *Feature) error {
Expand All @@ -86,6 +83,7 @@ func RemoveOAuthClient(feature *Feature) error {

if err := feature.dynamicClient.Resource(gvr).Delete(context.Background(), oauthClientName, metav1.DeleteOptions{}); err != nil {
log.Error(err, "failed deleting OAuthClient", "name", oauthClientName)

return err
}

Expand All @@ -95,15 +93,9 @@ func RemoveOAuthClient(feature *Feature) error {
func RemoveExtensionProvider(feature *Feature) error {
ossmAuthzProvider := fmt.Sprintf("%s-odh-auth-provider", feature.Spec.AppNamespace)

gvr := schema.GroupVersionResource{
Group: "maistra.io",
Version: "v2",
Resource: "servicemeshcontrolplanes",
}

mesh := feature.Spec.Mesh

smcp, err := feature.dynamicClient.Resource(gvr).
smcp, err := feature.dynamicClient.Resource(smcpGVR).
Namespace(mesh.Namespace).
Get(context.Background(), mesh.Name, metav1.GetOptions{})
if err != nil {
Expand Down Expand Up @@ -136,7 +128,7 @@ func RemoveExtensionProvider(feature *Feature) error {
}
}

_, err = feature.dynamicClient.Resource(gvr).
_, err = feature.dynamicClient.Resource(smcpGVR).
Namespace(mesh.Namespace).
Update(context.Background(), smcp, metav1.UpdateOptions{})

Expand Down
26 changes: 23 additions & 3 deletions pkg/kfapp/ossm/feature/feature.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ import (
var log = ctrlLog.Log.WithName("ossm-features")

type Feature struct {
Name string
Spec *Spec
Name string
Spec *Spec
Enabled bool

clientset *kubernetes.Clientset
dynamicClient dynamic.Interface
Expand All @@ -42,6 +43,13 @@ type Feature struct {
type action func(feature *Feature) error

func (f *Feature) Apply() error {

if !f.Enabled {
log.Info("feature is disabled, skipping.", "name", f.Name)

return nil
}

// Verify all precondition and collect errors
var multiErr *multierror.Error
for _, precondition := range f.preconditions {
Expand Down Expand Up @@ -80,12 +88,24 @@ func (f *Feature) Apply() error {
return err
}

// TODO postconditions
for _, postcondition := range f.postconditions {
multiErr = multierror.Append(multiErr, postcondition(f))
}

if multiErr.ErrorOrNil() != nil {
return multiErr.ErrorOrNil()
}

return nil
}

func (f *Feature) Cleanup() error {
if !f.Enabled {
log.Info("feature is disabled, skipping.", "name", f.Name)

return nil
}

var cleanupErrors *multierror.Error
for _, cleanupFunc := range f.cleanups {
cleanupErrors = multierror.Append(cleanupErrors, cleanupFunc(f))
Expand Down
7 changes: 4 additions & 3 deletions pkg/kfapp/ossm/feature/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,15 +113,16 @@ func ServiceMeshEnabledInDashboard(feature *Feature) error {
dashboardConfig := spec["dashboardConfig"].(map[string]interface{})
dashboardConfig["disableServiceMesh"] = false

_, err = feature.dynamicClient.Resource(gvr).
if _, err := feature.dynamicClient.Resource(gvr).
Namespace(feature.Spec.AppNamespace).
Update(context.Background(), &config, metav1.UpdateOptions{})
if err != nil {
Update(context.Background(), &config, metav1.UpdateOptions{}); err != nil {
log.Error(err, "Failed to update odhdashboardconfig")

return err
}

log.Info("Successfully patched odhdashboardconfig")

return nil
}

Expand Down
Loading