Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
Co-authored-by: Danail Branekov <danailster@gmail.com>
  • Loading branch information
uzabanov and danail-branekov committed Dec 11, 2024
1 parent b7a0cb9 commit 97585e5
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 145 deletions.
16 changes: 7 additions & 9 deletions controllers/controllers/services/bindings/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

korifiv1alpha1 "code.cloudfoundry.org/korifi/controllers/api/v1alpha1"
"code.cloudfoundry.org/korifi/controllers/controllers/shared"
"code.cloudfoundry.org/korifi/tools"
"code.cloudfoundry.org/korifi/tools/k8s"

"github.com/go-logr/logr"
Expand All @@ -42,7 +43,7 @@ const (
)

type CredentialsReconciler interface {
ReconcileResource(ctx context.Context, cfServiceBinding *korifiv1alpha1.CFServiceBinding) (ctrl.Result, error)
ReconcileResource(ctx context.Context, cfServiceBinding *korifiv1alpha1.CFServiceBinding, cfServiceInstance *korifiv1alpha1.CFServiceInstance) (ctrl.Result, error)
}

type Reconciler struct {
Expand Down Expand Up @@ -122,7 +123,7 @@ func (r *Reconciler) ReconcileResource(ctx context.Context, cfServiceBinding *ko
return ctrl.Result{}, err
}

r.setInstanceAnnotation(cfServiceInstance, cfServiceBinding)
setInstanceTypeAnnotation(cfServiceBinding, string(cfServiceInstance.Spec.Type))

err = controllerutil.SetOwnerReference(cfServiceInstance, cfServiceBinding, r.scheme)
if err != nil {
Expand All @@ -143,10 +144,10 @@ func (r *Reconciler) ReconcileResource(ctx context.Context, cfServiceBinding *ko

func (r *Reconciler) reconcileByType(ctx context.Context, cfServiceInstance *korifiv1alpha1.CFServiceInstance, cfServiceBinding *korifiv1alpha1.CFServiceBinding) (ctrl.Result, error) {
if cfServiceInstance.Spec.Type == korifiv1alpha1.UserProvidedType {
return r.upsiReconciler.ReconcileResource(ctx, cfServiceBinding)
return r.upsiReconciler.ReconcileResource(ctx, cfServiceBinding, cfServiceInstance)
}

return r.managedReconciler.ReconcileResource(ctx, cfServiceBinding)
return r.managedReconciler.ReconcileResource(ctx, cfServiceBinding, cfServiceInstance)
}

func needsRequeue(res ctrl.Result, err error) bool {
Expand All @@ -157,9 +158,6 @@ func needsRequeue(res ctrl.Result, err error) bool {
return !res.IsZero()
}

func (r *Reconciler) setInstanceAnnotation(cfServiceInstance *korifiv1alpha1.CFServiceInstance, cfServiceBinding *korifiv1alpha1.CFServiceBinding) {
if cfServiceBinding.Annotations == nil {
cfServiceBinding.Annotations = map[string]string{}
}
cfServiceBinding.Annotations[korifiv1alpha1.ServiceInstanceTypeAnnotationKey] = string(cfServiceInstance.Spec.Type)
func setInstanceTypeAnnotation(cfServiceBinding *korifiv1alpha1.CFServiceBinding, instanceType string) {
cfServiceBinding.Annotations = tools.SetMapValue(cfServiceBinding.Annotations, korifiv1alpha1.ServiceInstanceTypeAnnotationKey, instanceType)
}
75 changes: 5 additions & 70 deletions controllers/controllers/services/bindings/managed/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package managed

import (
"context"
"fmt"
"time"

"code.cloudfoundry.org/korifi/controllers/controllers/services/bindings/sbio"
"code.cloudfoundry.org/korifi/controllers/controllers/services/osbapi"
"code.cloudfoundry.org/korifi/tools"
"code.cloudfoundry.org/korifi/tools/k8s"
Expand All @@ -18,7 +18,6 @@ import (
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"

korifiv1alpha1 "code.cloudfoundry.org/korifi/controllers/api/v1alpha1"
ctrl "sigs.k8s.io/controller-runtime"
Expand All @@ -40,24 +39,14 @@ func NewReconciler(k8sClient client.Client, brokerClientFactory osbapi.BrokerCli
}
}

func (r *ManagedBindingsReconciler) ReconcileResource(ctx context.Context, cfServiceBinding *korifiv1alpha1.CFServiceBinding) (ctrl.Result, error) {
func (r *ManagedBindingsReconciler) ReconcileResource(ctx context.Context, cfServiceBinding *korifiv1alpha1.CFServiceBinding, cfServiceInstance *korifiv1alpha1.CFServiceInstance) (ctrl.Result, error) {
log := logr.FromContextOrDiscard(ctx).WithName("reconcile-managed-service-binding")

if !cfServiceBinding.GetDeletionTimestamp().IsZero() {
return r.finalizeCFServiceBinding(ctx, cfServiceBinding)
}

cfServiceInstance := new(korifiv1alpha1.CFServiceInstance)
err := r.k8sClient.Get(ctx, types.NamespacedName{Name: cfServiceBinding.Spec.Service.Name, Namespace: cfServiceBinding.Namespace}, cfServiceInstance)
if err != nil {
log.Info("service instance not found", "service-instance", cfServiceBinding.Spec.Service.Name, "error", err)
return ctrl.Result{}, err
}

if cfServiceBinding.Labels == nil {
cfServiceBinding.Labels = map[string]string{}
}
cfServiceBinding.Labels[korifiv1alpha1.PlanGUIDLabelKey] = cfServiceInstance.Spec.PlanGUID
cfServiceBinding.Labels = tools.SetMapValue(cfServiceBinding.Labels, korifiv1alpha1.PlanGUIDLabelKey, cfServiceInstance.Spec.PlanGUID)

assets, err := r.assets.GetServiceBindingAssets(ctx, cfServiceBinding)
if err != nil {
Expand Down Expand Up @@ -95,7 +84,7 @@ func (r *ManagedBindingsReconciler) ReconcileResource(ctx context.Context, cfSer
return ctrl.Result{}, err
}

if !isSbServiceBindingReady(sbServiceBinding) {
if !sbio.IsSbServiceBindingReady(sbServiceBinding) {
return ctrl.Result{}, k8s.NewNotReadyError().WithReason("ServiceBindingNotReady")
}

Expand Down Expand Up @@ -280,11 +269,9 @@ func (r *ManagedBindingsReconciler) finalizeCFServiceBinding(
}

func (r *ManagedBindingsReconciler) reconcileSBServiceBinding(ctx context.Context, cfServiceBinding *korifiv1alpha1.CFServiceBinding) (*servicebindingv1beta1.ServiceBinding, error) {
sbServiceBinding := r.toSBServiceBinding(cfServiceBinding)
sbServiceBinding := sbio.ToSBServiceBinding(cfServiceBinding, korifiv1alpha1.ManagedType)

_, err := controllerutil.CreateOrPatch(ctx, r.k8sClient, sbServiceBinding, func() error {
sbServiceBinding.Spec.Name = getSBServiceBindingName(cfServiceBinding)

return controllerutil.SetControllerReference(cfServiceBinding, sbServiceBinding, r.scheme)
})
if err != nil {
Expand All @@ -294,58 +281,6 @@ func (r *ManagedBindingsReconciler) reconcileSBServiceBinding(ctx context.Contex
return sbServiceBinding, nil
}

func (r *ManagedBindingsReconciler) toSBServiceBinding(cfServiceBinding *korifiv1alpha1.CFServiceBinding) *servicebindingv1beta1.ServiceBinding {
return &servicebindingv1beta1.ServiceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("cf-binding-%s", cfServiceBinding.Name),
Namespace: cfServiceBinding.Namespace,
Labels: map[string]string{
korifiv1alpha1.ServiceBindingGUIDLabel: cfServiceBinding.Name,
korifiv1alpha1.CFAppGUIDLabelKey: cfServiceBinding.Spec.AppRef.Name,
korifiv1alpha1.ServiceCredentialBindingTypeLabel: "app",
},
},
Spec: servicebindingv1beta1.ServiceBindingSpec{
Type: korifiv1alpha1.ManagedType,
Workload: servicebindingv1beta1.ServiceBindingWorkloadReference{
APIVersion: "apps/v1",
Kind: "StatefulSet",
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
korifiv1alpha1.CFAppGUIDLabelKey: cfServiceBinding.Spec.AppRef.Name,
},
},
},
Service: servicebindingv1beta1.ServiceBindingServiceReference{
APIVersion: "korifi.cloudfoundry.org/v1alpha1",
Kind: "CFServiceBinding",
Name: cfServiceBinding.Name,
},
},
}
}

func getSBServiceBindingName(cfServiceBinding *korifiv1alpha1.CFServiceBinding) string {
if cfServiceBinding.Spec.DisplayName != nil {
return *cfServiceBinding.Spec.DisplayName
}

return cfServiceBinding.Status.Binding.Name
}

func isSbServiceBindingReady(sbServiceBinding *servicebindingv1beta1.ServiceBinding) bool {
readyCondition := meta.FindStatusCondition(sbServiceBinding.Status.Conditions, "Ready")
if readyCondition == nil {
return false
}

if readyCondition.Status != metav1.ConditionTrue {
return false
}

return sbServiceBinding.Generation == sbServiceBinding.Status.ObservedGeneration
}

func isBindRequested(binding *korifiv1alpha1.CFServiceBinding) bool {
return meta.IsStatusConditionTrue(binding.Status.Conditions, korifiv1alpha1.BindingRequestedCondition)
}
Expand Down
64 changes: 64 additions & 0 deletions controllers/controllers/services/bindings/sbio/servicebinding.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package sbio

import (
"fmt"

"k8s.io/apimachinery/pkg/api/meta"

korifiv1alpha1 "code.cloudfoundry.org/korifi/controllers/api/v1alpha1"
servicebindingv1beta1 "github.com/servicebinding/runtime/apis/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func ToSBServiceBinding(cfServiceBinding *korifiv1alpha1.CFServiceBinding, bindingType string) *servicebindingv1beta1.ServiceBinding {
return &servicebindingv1beta1.ServiceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("cf-binding-%s", cfServiceBinding.Name),
Namespace: cfServiceBinding.Namespace,
Labels: map[string]string{
korifiv1alpha1.ServiceBindingGUIDLabel: cfServiceBinding.Name,
korifiv1alpha1.CFAppGUIDLabelKey: cfServiceBinding.Spec.AppRef.Name,
korifiv1alpha1.ServiceCredentialBindingTypeLabel: "app",
},
},
Spec: servicebindingv1beta1.ServiceBindingSpec{
Name: getSBServiceBindingName(cfServiceBinding),
Type: bindingType,
Workload: servicebindingv1beta1.ServiceBindingWorkloadReference{
APIVersion: "apps/v1",
Kind: "StatefulSet",
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
korifiv1alpha1.CFAppGUIDLabelKey: cfServiceBinding.Spec.AppRef.Name,
},
},
},
Service: servicebindingv1beta1.ServiceBindingServiceReference{
APIVersion: "korifi.cloudfoundry.org/v1alpha1",
Kind: "CFServiceBinding",
Name: cfServiceBinding.Name,
},
},
}
}

func getSBServiceBindingName(cfServiceBinding *korifiv1alpha1.CFServiceBinding) string {
if cfServiceBinding.Spec.DisplayName != nil {
return *cfServiceBinding.Spec.DisplayName
}

return cfServiceBinding.Status.Binding.Name
}

func IsSbServiceBindingReady(sbServiceBinding *servicebindingv1beta1.ServiceBinding) bool {
readyCondition := meta.FindStatusCondition(sbServiceBinding.Status.Conditions, "Ready")
if readyCondition == nil {
return false
}

if readyCondition.Status != metav1.ConditionTrue {
return false
}

return sbServiceBinding.Generation == sbServiceBinding.Status.ObservedGeneration
}
70 changes: 4 additions & 66 deletions controllers/controllers/services/bindings/upsi/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,15 @@ import (
"github.com/go-logr/logr"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"

korifiv1alpha1 "code.cloudfoundry.org/korifi/controllers/api/v1alpha1"
"code.cloudfoundry.org/korifi/controllers/controllers/services/bindings/sbio"
"code.cloudfoundry.org/korifi/controllers/controllers/services/credentials"
servicebindingv1beta1 "github.com/servicebinding/runtime/apis/v1beta1"
corev1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
ctrl "sigs.k8s.io/controller-runtime"
)
Expand All @@ -35,7 +34,7 @@ func NewReconciler(k8sClient client.Client, scheme *runtime.Scheme) *UPSIBinding
}
}

func (r *UPSIBindingReconciler) ReconcileResource(ctx context.Context, cfServiceBinding *korifiv1alpha1.CFServiceBinding) (ctrl.Result, error) {
func (r *UPSIBindingReconciler) ReconcileResource(ctx context.Context, cfServiceBinding *korifiv1alpha1.CFServiceBinding, cfServiceInstance *korifiv1alpha1.CFServiceInstance) (ctrl.Result, error) {
log := logr.FromContextOrDiscard(ctx)

if !cfServiceBinding.GetDeletionTimestamp().IsZero() {
Expand All @@ -46,13 +45,6 @@ func (r *UPSIBindingReconciler) ReconcileResource(ctx context.Context, cfService
return ctrl.Result{}, nil
}

cfServiceInstance := new(korifiv1alpha1.CFServiceInstance)
err := r.k8sClient.Get(ctx, types.NamespacedName{Name: cfServiceBinding.Spec.Service.Name, Namespace: cfServiceBinding.Namespace}, cfServiceInstance)
if err != nil {
log.Info("service instance not found", "service-instance", cfServiceBinding.Spec.Service.Name, "error", err)
return ctrl.Result{}, err
}

if cfServiceInstance.Status.Credentials.Name == "" {
return ctrl.Result{}, k8s.NewNotReadyError().
WithReason("CredentialsSecretNotAvailable").
Expand Down Expand Up @@ -82,7 +74,7 @@ func (r *UPSIBindingReconciler) ReconcileResource(ctx context.Context, cfService
return ctrl.Result{}, err
}

if !isSbServiceBindingReady(sbServiceBinding) {
if !sbio.IsSbServiceBindingReady(sbServiceBinding) {
return ctrl.Result{}, k8s.NewNotReadyError().WithReason("ServiceBindingNotReady")
}

Expand Down Expand Up @@ -132,11 +124,9 @@ func (r *UPSIBindingReconciler) reconcileCredentials(ctx context.Context, cfServ
}

func (r *UPSIBindingReconciler) reconcileSBServiceBinding(ctx context.Context, cfServiceBinding *korifiv1alpha1.CFServiceBinding, bindingSecret *corev1.Secret) (*servicebindingv1beta1.ServiceBinding, error) {
sbServiceBinding := r.toSBServiceBinding(cfServiceBinding)
sbServiceBinding := sbio.ToSBServiceBinding(cfServiceBinding, korifiv1alpha1.UserProvidedType)

_, err := controllerutil.CreateOrPatch(ctx, r.k8sClient, sbServiceBinding, func() error {
sbServiceBinding.Spec.Name = getSBServiceBindingName(cfServiceBinding)

secretType, hasType := bindingSecret.Data["type"]
if hasType && len(secretType) > 0 {
sbServiceBinding.Spec.Type = string(secretType)
Expand All @@ -154,55 +144,3 @@ func (r *UPSIBindingReconciler) reconcileSBServiceBinding(ctx context.Context, c

return sbServiceBinding, nil
}

func (r *UPSIBindingReconciler) toSBServiceBinding(cfServiceBinding *korifiv1alpha1.CFServiceBinding) *servicebindingv1beta1.ServiceBinding {
return &servicebindingv1beta1.ServiceBinding{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("cf-binding-%s", cfServiceBinding.Name),
Namespace: cfServiceBinding.Namespace,
Labels: map[string]string{
korifiv1alpha1.ServiceBindingGUIDLabel: cfServiceBinding.Name,
korifiv1alpha1.CFAppGUIDLabelKey: cfServiceBinding.Spec.AppRef.Name,
korifiv1alpha1.ServiceCredentialBindingTypeLabel: "app",
},
},
Spec: servicebindingv1beta1.ServiceBindingSpec{
Type: korifiv1alpha1.UserProvidedType,
Workload: servicebindingv1beta1.ServiceBindingWorkloadReference{
APIVersion: "apps/v1",
Kind: "StatefulSet",
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
korifiv1alpha1.CFAppGUIDLabelKey: cfServiceBinding.Spec.AppRef.Name,
},
},
},
Service: servicebindingv1beta1.ServiceBindingServiceReference{
APIVersion: "korifi.cloudfoundry.org/v1alpha1",
Kind: "CFServiceBinding",
Name: cfServiceBinding.Name,
},
},
}
}

func getSBServiceBindingName(cfServiceBinding *korifiv1alpha1.CFServiceBinding) string {
if cfServiceBinding.Spec.DisplayName != nil {
return *cfServiceBinding.Spec.DisplayName
}

return cfServiceBinding.Status.Binding.Name
}

func isSbServiceBindingReady(sbServiceBinding *servicebindingv1beta1.ServiceBinding) bool {
readyCondition := meta.FindStatusCondition(sbServiceBinding.Status.Conditions, "Ready")
if readyCondition == nil {
return false
}

if readyCondition.Status != metav1.ConditionTrue {
return false
}

return sbServiceBinding.Generation == sbServiceBinding.Status.ObservedGeneration
}
9 changes: 9 additions & 0 deletions tools/collections.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,12 @@ func NilOrEquals[E comparable](value *E, expectedValue E) bool {

return expectedValue == *value
}

func SetMapValue[K comparable, V any](m map[K]V, key K, value V) map[K]V {
if m == nil {
m = map[K]V{}
}
m[key] = value

return m
}

0 comments on commit 97585e5

Please sign in to comment.