Skip to content
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
2 changes: 1 addition & 1 deletion api/crds/manifests/openmcp.cloud_clusterproviders.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ spec:
- image
type: object
status:
description: DeploymentStatus defines the observed state of a provider.
description: ClusterProviderStatus defines the observed state of ClusterProvider.
properties:
conditions:
items:
Expand Down
2 changes: 1 addition & 1 deletion api/crds/manifests/openmcp.cloud_platformservices.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ spec:
- image
type: object
status:
description: DeploymentStatus defines the observed state of a provider.
description: PlatformServiceStatus defines the observed state of PlatformService.
properties:
conditions:
items:
Expand Down
2 changes: 1 addition & 1 deletion api/crds/manifests/openmcp.cloud_serviceproviders.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ spec:
- image
type: object
status:
description: DeploymentStatus defines the observed state of a provider.
description: ServiceProviderStatus defines the observed state of ServiceProvider.
properties:
conditions:
items:
Expand Down
7 changes: 3 additions & 4 deletions api/provider/v1alpha1/clusterprovider_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ type ClusterProviderSpec struct {

// ClusterProviderStatus defines the observed state of ClusterProvider.
type ClusterProviderStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
DeploymentStatus `json:",inline"`
}

// +kubebuilder:object:root=true
Expand All @@ -44,8 +43,8 @@ type ClusterProviderStatus struct {
type ClusterProvider struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ClusterProviderSpec `json:"spec,omitempty"`
Status DeploymentStatus `json:"status,omitempty"`
Spec ClusterProviderSpec `json:"spec,omitempty"`
Status ClusterProviderStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true
Expand Down
7 changes: 3 additions & 4 deletions api/provider/v1alpha1/platformservice_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ type PlatformServiceSpec struct {

// PlatformServiceStatus defines the observed state of PlatformService.
type PlatformServiceStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
DeploymentStatus `json:",inline"`
}

// +kubebuilder:object:root=true
Expand All @@ -44,8 +43,8 @@ type PlatformServiceStatus struct {
type PlatformService struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec PlatformServiceSpec `json:"spec,omitempty"`
Status DeploymentStatus `json:"status,omitempty"`
Spec PlatformServiceSpec `json:"spec,omitempty"`
Status PlatformServiceStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true
Expand Down
7 changes: 3 additions & 4 deletions api/provider/v1alpha1/serviceprovider_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ type ServiceProviderSpec struct {

// ServiceProviderStatus defines the observed state of ServiceProvider.
type ServiceProviderStatus struct {
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
// Important: Run "make" to regenerate code after modifying this file
DeploymentStatus `json:",inline"`
}

// +kubebuilder:object:root=true
Expand All @@ -44,8 +43,8 @@ type ServiceProviderStatus struct {
type ServiceProvider struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec ServiceProviderSpec `json:"spec,omitempty"`
Status DeploymentStatus `json:"status,omitempty"`
Spec ServiceProviderSpec `json:"spec,omitempty"`
Status ServiceProviderStatus `json:"status,omitempty"`
}

// +kubebuilder:object:root=true
Expand Down
3 changes: 3 additions & 0 deletions api/provider/v1alpha1/zz_generated.deepcopy.go

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

11 changes: 6 additions & 5 deletions cmd/openmcp-operator/app/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ import (
)

var setupLog logging.Logger
var allControllers = []string{strings.ToLower(scheduler.ControllerName)}
var allControllers = []string{
strings.ToLower(scheduler.ControllerName),
strings.ToLower(provider.ControllerName),
}

func NewRunCommand(so *SharedOptions) *cobra.Command {
opts := &RunOptions{
Expand Down Expand Up @@ -297,13 +300,11 @@ func (o *RunOptions) Run(ctx context.Context) error {
}

// setup deployment controller
// TODO: Can we use a variable/constant/function instead of a hardcoded string for the controller name here?
// TODO: This value has to be added to the allControllers variable too, because I guess we want it to be enabled by default.
if slices.Contains(o.Controllers, strings.ToLower("deploymentcontroller")) {
if slices.Contains(o.Controllers, strings.ToLower(provider.ControllerName)) {
utilruntime.Must(clientgoscheme.AddToScheme(mgr.GetScheme()))
utilruntime.Must(api.AddToScheme(mgr.GetScheme()))

if err = provider.NewDeploymentController().SetupWithManager(mgr, o.ProviderGVKList); err != nil {
if err = provider.NewDeploymentController().SetupWithManager(mgr, o.ProviderGVKList, o.Environment); err != nil {
return fmt.Errorf("unable to setup provider controllers: %w", err)
}
}
Expand Down
6 changes: 5 additions & 1 deletion internal/controllers/provider/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"errors"
"fmt"
"strings"
"time"

"github.com/openmcp-project/controller-utils/pkg/controller"
Expand Down Expand Up @@ -35,10 +36,11 @@ const (
type ProviderReconciler struct {
schema.GroupVersionKind
PlatformClient client.Client
Environment string
}

func (r *ProviderReconciler) ControllerName() string {
return r.GroupVersionKind.String()
return strings.ToLower(r.GroupVersionKind.Kind)
}

func (r *ProviderReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res ctrl.Result, err error) {
Expand Down Expand Up @@ -144,6 +146,7 @@ func (r *ProviderReconciler) install(
PlatformClient: r.PlatformClient,
Provider: provider,
DeploymentSpec: deploymentSpec,
Environment: r.Environment,
}

if !isInitialized(deploymentStatus) {
Expand Down Expand Up @@ -198,6 +201,7 @@ func (r *ProviderReconciler) handleDeleteOperation(ctx context.Context, provider
PlatformClient: r.PlatformClient,
Provider: provider,
DeploymentSpec: nil,
Environment: r.Environment,
}

deploymentStatus.Phase = phaseTerminating
Expand Down
31 changes: 31 additions & 0 deletions internal/controllers/provider/controller_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package provider

import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"

"github.com/openmcp-project/openmcp-operator/api/provider/v1alpha1"
)

var _ = Describe("Deployment Controller", func() {

Context("Converter", func() {

It("should convert a deploymentStatus into an unstructured and back", func() {
originalStatus := &v1alpha1.DeploymentStatus{
Conditions: nil,
ObservedGeneration: 6,
Phase: phaseProgressing,
}
r := &ProviderReconciler{}
provider := &unstructured.Unstructured{}
provider.Object = map[string]interface{}{}
err := r.deploymentStatusIntoUnstructured(originalStatus, provider)
Expect(err).NotTo(HaveOccurred())
status, err := r.deploymentStatusFromUnstructured(provider)
Expect(err).NotTo(HaveOccurred())
Expect(status).To(Equal(originalStatus))
})
})
})
24 changes: 10 additions & 14 deletions internal/controllers/provider/deployment_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,17 @@ limitations under the License.
package provider

import (
"github.com/openmcp-project/controller-utils/pkg/controller"
v1 "k8s.io/api/batch/v1"
apps "k8s.io/api/apps/v1"
batch "k8s.io/api/batch/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/validation/field"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/handler"

"github.com/openmcp-project/openmcp-operator/internal/controllers/provider/install"
)

// DeploymentController is not a controller, but a collection of controllers reconciling
// ClusterProviders, ServiceProviders, and PlatformServices.
const ControllerName = "DeploymentController"

// DeploymentController is a collection of controllers reconciling ClusterProviders, ServiceProviders, and PlatformServices.
type DeploymentController struct {
Reconcilers []*ProviderReconciler
}
Expand All @@ -40,7 +37,7 @@ func NewDeploymentController() *DeploymentController {
}

// SetupWithManager sets up the controllers with the Manager.
func (r *DeploymentController) SetupWithManager(mgr ctrl.Manager, providerGKVList []schema.GroupVersionKind) error {
func (r *DeploymentController) SetupWithManager(mgr ctrl.Manager, providerGKVList []schema.GroupVersionKind, environment string) error {
allErrs := field.ErrorList{}

r.Reconcilers = make([]*ProviderReconciler, len(providerGKVList))
Expand All @@ -49,18 +46,17 @@ func (r *DeploymentController) SetupWithManager(mgr ctrl.Manager, providerGKVLis
r.Reconcilers[i] = &ProviderReconciler{
GroupVersionKind: gvk,
PlatformClient: mgr.GetClient(),
Environment: environment,
}

obj := &unstructured.Unstructured{}
obj.SetGroupVersionKind(gvk)

err := ctrl.NewControllerManagedBy(mgr).
For(obj).
Named(r.Reconcilers[i].ControllerName()).
Watches(&v1.Job{},
handler.EnqueueRequestsFromMapFunc(r.Reconcilers[i].HandleJob),
builder.WithPredicates(controller.HasAnnotationPredicate(install.ProviderKindLabel, "")),
builder.WithPredicates(controller.HasAnnotationPredicate(install.ProviderNameLabel, ""))).
For(obj).
Owns(&batch.Job{}).
Owns(&apps.Deployment{}).
Complete(r.Reconcilers[i])
if err != nil {
allErrs = append(allErrs, field.InternalError(field.NewPath(gvk.String()), err))
Expand Down
24 changes: 14 additions & 10 deletions internal/controllers/provider/install/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@ import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/utils/ptr"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"

"github.com/openmcp-project/controller-utils/pkg/resources"
)

const (
deploymentSelectorLabelKey = "app"
deploymentSelectorLabelValue = "openmcp.cloud/deployment"
"github.com/openmcp-project/openmcp-operator/api/install"
)

type deploymentMutator struct {
Expand Down Expand Up @@ -44,13 +43,11 @@ func (m *deploymentMutator) Empty() *appsv1.Deployment {
}
}

func (m *deploymentMutator) Mutate(r *appsv1.Deployment) error {
r.Spec = appsv1.DeploymentSpec{
func (m *deploymentMutator) Mutate(d *appsv1.Deployment) error {
d.Spec = appsv1.DeploymentSpec{
Replicas: ptr.To[int32](1),
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
deploymentSelectorLabelKey: deploymentSelectorLabelValue,
},
MatchLabels: m.values.LabelsController(),
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Expand All @@ -64,6 +61,7 @@ func (m *deploymentMutator) Mutate(r *appsv1.Deployment) error {
ImagePullPolicy: corev1.PullIfNotPresent,
Args: []string{
"run",
"--environment=" + m.values.Environment(),
},
},
},
Expand All @@ -72,5 +70,11 @@ func (m *deploymentMutator) Mutate(r *appsv1.Deployment) error {
},
},
}
return m.meta.Mutate(r)

// Set the provider as owner of the deployment, so that the provider controller gets an event if the deployment changes.
if err := controllerutil.SetControllerReference(m.values.provider, d, install.InstallOperatorAPIs(runtime.NewScheme())); err != nil {
return fmt.Errorf("failed to set deployment controller as owner of deployment: %w", err)
}

return m.meta.Mutate(d)
}
Loading