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
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package lifecycle
package conditions

import (
"fmt"
Expand All @@ -7,6 +7,8 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
ctrl "sigs.k8s.io/controller-runtime"

"github.com/platform-mesh/golang-commons/controller/lifecycle/runtimeobject"
"github.com/platform-mesh/golang-commons/controller/lifecycle/subroutine"
"github.com/platform-mesh/golang-commons/logger"
"github.com/platform-mesh/golang-commons/sentry"
)
Expand All @@ -30,9 +32,10 @@ const (
subroutineMessageErrorFormatString = "The %s has an error: %s"
)

func (l *LifecycleManager) WithConditionManagement() *LifecycleManager {
l.manageConditions = true
return l
type ConditionManager struct{}

func NewConditionManager() *ConditionManager {
return &ConditionManager{}
}

type RuntimeObjectConditions interface {
Expand All @@ -41,7 +44,7 @@ type RuntimeObjectConditions interface {
}

// Set the Condition of the instance to be ready
func setInstanceConditionReady(conditions *[]metav1.Condition, status metav1.ConditionStatus) bool {
func (c *ConditionManager) SetInstanceConditionReady(conditions *[]metav1.Condition, status metav1.ConditionStatus) bool {
var msg string
switch status {
case metav1.ConditionTrue:
Expand All @@ -60,15 +63,15 @@ func setInstanceConditionReady(conditions *[]metav1.Condition, status metav1.Con
}

// Set the Condition to be Unknown in case it is not set yet
func setInstanceConditionUnknownIfNotSet(conditions *[]metav1.Condition) bool {
func (c *ConditionManager) SetInstanceConditionUnknownIfNotSet(conditions *[]metav1.Condition) bool {
existingCondition := meta.FindStatusCondition(*conditions, ConditionReady)
if existingCondition == nil {
return setInstanceConditionReady(conditions, metav1.ConditionUnknown)
return c.SetInstanceConditionReady(conditions, metav1.ConditionUnknown)
}
return false
}

func setSubroutineConditionToUnknownIfNotSet(conditions *[]metav1.Condition, subroutine Subroutine, isFinalize bool, log *logger.Logger) bool {
func (c *ConditionManager) SetSubroutineConditionToUnknownIfNotSet(conditions *[]metav1.Condition, subroutine subroutine.Subroutine, isFinalize bool, log *logger.Logger) bool {
conditionName, conditionMessage := getConditionNameAndMessage(subroutine, isFinalize)

existingCondition := meta.FindStatusCondition(*conditions, conditionName)
Expand All @@ -83,7 +86,7 @@ func setSubroutineConditionToUnknownIfNotSet(conditions *[]metav1.Condition, sub
return false
}

func getConditionNameAndMessage(subroutine Subroutine, isFinalize bool) (string, string) {
func getConditionNameAndMessage(subroutine subroutine.Subroutine, isFinalize bool) (string, string) {
conditionName := fmt.Sprintf(subroutineReadyConditionFormatString, subroutine.GetName())
conditionMessage := "subroutine"
if isFinalize {
Expand All @@ -94,7 +97,7 @@ func getConditionNameAndMessage(subroutine Subroutine, isFinalize bool) (string,
}

// Set Subroutines Conditions
func setSubroutineCondition(conditions *[]metav1.Condition, subroutine Subroutine, subroutineResult ctrl.Result, subroutineErr error, isFinalize bool, log *logger.Logger) bool {
func (c *ConditionManager) SetSubroutineCondition(conditions *[]metav1.Condition, subroutine subroutine.Subroutine, subroutineResult ctrl.Result, subroutineErr error, isFinalize bool, log *logger.Logger) bool {
conditionName, conditionMessage := getConditionNameAndMessage(subroutine, isFinalize)

// processing complete
Expand All @@ -120,18 +123,18 @@ func setSubroutineCondition(conditions *[]metav1.Condition, subroutine Subroutin
return changed
}

func toRuntimeObjectConditionsInterface(instance RuntimeObject, log *logger.Logger) (RuntimeObjectConditions, error) {
func (c *ConditionManager) ToRuntimeObjectConditionsInterface(instance runtimeobject.RuntimeObject, log *logger.Logger) (RuntimeObjectConditions, error) {
if obj, ok := instance.(RuntimeObjectConditions); ok {
return obj, nil
}
err := fmt.Errorf("manageConditions is enabled, but instance does not implement RuntimeObjectConditions interface. This is a programming error")
err := fmt.Errorf("ManageConditions is enabled, but instance does not implement RuntimeObjectConditions interface. This is a programming error")
log.Error().Err(err).Msg("instance does not implement RuntimeObjectConditions interface")
sentry.CaptureError(err, nil)
return nil, err
}

func MustToRuntimeObjectConditionsInterface(instance RuntimeObject, log *logger.Logger) RuntimeObjectConditions {
obj, err := toRuntimeObjectConditionsInterface(instance, log)
func (c *ConditionManager) MustToRuntimeObjectConditionsInterface(instance runtimeobject.RuntimeObject, log *logger.Logger) RuntimeObjectConditions {
obj, err := c.ToRuntimeObjectConditionsInterface(instance, log)
if err == nil {
return obj
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package lifecycle
package conditions

import (
"errors"
Expand All @@ -11,32 +11,19 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
controllerruntime "sigs.k8s.io/controller-runtime"

"github.com/platform-mesh/golang-commons/controller/testSupport"
pmtesting "github.com/platform-mesh/golang-commons/controller/lifecycle/testing"
"github.com/platform-mesh/golang-commons/logger"
)

// Test LifecycleManager.WithConditionManagement
func TestLifecycleManager_WithConditionManagement(t *testing.T) {
// Given
fakeClient := testSupport.CreateFakeClient(t, &testSupport.TestApiObject{})
_, log := createLifecycleManager([]Subroutine{}, fakeClient)

// When
l := NewLifecycleManager(log.Logger, "test-operator", "test-controller", fakeClient, []Subroutine{}).WithConditionManagement()

// Then
assert.True(t, true, l.manageConditions)
}

// Test the setReady function with an empty array
func TestSetReady(t *testing.T) {

t.Run("TestSetReady with empty array", func(t *testing.T) {
// Given
condition := []metav1.Condition{}

cm := NewConditionManager()
// When
setInstanceConditionReady(&condition, metav1.ConditionTrue)
cm.SetInstanceConditionReady(&condition, metav1.ConditionTrue)

// Then
assert.Equal(t, 1, len(condition))
Expand All @@ -45,12 +32,13 @@ func TestSetReady(t *testing.T) {

t.Run("TestSetReady with existing condition", func(t *testing.T) {
// Given
cm := NewConditionManager()
condition := []metav1.Condition{
{Type: "test", Status: metav1.ConditionFalse},
}

// When
setInstanceConditionReady(&condition, metav1.ConditionTrue)
cm.SetInstanceConditionReady(&condition, metav1.ConditionTrue)

// Then
assert.Equal(t, 2, len(condition))
Expand All @@ -62,10 +50,11 @@ func TestSetUnknown(t *testing.T) {

t.Run("TestSetUnknown with empty array", func(t *testing.T) {
// Given
cm := NewConditionManager()
condition := []metav1.Condition{}

// When
setInstanceConditionUnknownIfNotSet(&condition)
cm.SetInstanceConditionUnknownIfNotSet(&condition)

// Then
assert.Equal(t, 1, len(condition))
Expand All @@ -74,12 +63,13 @@ func TestSetUnknown(t *testing.T) {

t.Run("TestSetUnknown with existing ready condition", func(t *testing.T) {
// Given
cm := NewConditionManager()
condition := []metav1.Condition{
{Type: ConditionReady, Status: metav1.ConditionTrue},
}

// When
setInstanceConditionUnknownIfNotSet(&condition)
cm.SetInstanceConditionUnknownIfNotSet(&condition)

// Then
assert.Equal(t, 1, len(condition))
Expand Down Expand Up @@ -111,9 +101,10 @@ func TestSetSubroutineConditionToUnknownIfNotSet(t *testing.T) {
t.Run(tt.Name, func(t *testing.T) {
// Given
condition := []metav1.Condition{}
cm := NewConditionManager()

// When
setSubroutineConditionToUnknownIfNotSet(&condition, changeStatusSubroutine{}, tt.IsFinalize, log)
cm.SetSubroutineConditionToUnknownIfNotSet(&condition, pmtesting.ChangeStatusSubroutine{}, tt.IsFinalize, log)

// Then
assert.Equal(t, 1, len(condition))
Expand All @@ -124,12 +115,13 @@ func TestSetSubroutineConditionToUnknownIfNotSet(t *testing.T) {

t.Run("TestSetSubroutineConditionToUnknownIfNotSet with existing condition", func(t *testing.T) {
// Given
cm := NewConditionManager()
condition := []metav1.Condition{
{Type: "test", Status: metav1.ConditionFalse},
}

// When
setSubroutineConditionToUnknownIfNotSet(&condition, changeStatusSubroutine{}, false, log)
cm.SetSubroutineConditionToUnknownIfNotSet(&condition, pmtesting.ChangeStatusSubroutine{}, false, log)

// Then
assert.Equal(t, 2, len(condition))
Expand All @@ -138,14 +130,15 @@ func TestSetSubroutineConditionToUnknownIfNotSet(t *testing.T) {

t.Run("TestSetSubroutineConditionToUnknownIfNotSet with existing ready", func(t *testing.T) {
// Given
subroutine := changeStatusSubroutine{}
cm := NewConditionManager()
subroutine := pmtesting.ChangeStatusSubroutine{}
condition := []metav1.Condition{
{Type: "test", Status: metav1.ConditionFalse},
{Type: fmt.Sprintf("%s_Ready", subroutine.GetName()), Status: metav1.ConditionTrue},
}

// When
setSubroutineConditionToUnknownIfNotSet(&condition, subroutine, false, log)
cm.SetSubroutineConditionToUnknownIfNotSet(&condition, subroutine, false, log)

// Then
assert.Equal(t, 2, len(condition))
Expand All @@ -160,11 +153,12 @@ func TestSubroutineCondition(t *testing.T) {
// Add a test case to set a subroutine condition to ready if it was successfull
t.Run("TestSetSubroutineConditionReady", func(t *testing.T) {
// Given
cm := NewConditionManager()
condition := []metav1.Condition{}
subroutine := changeStatusSubroutine{}
subroutine := pmtesting.ChangeStatusSubroutine{}

// When
setSubroutineCondition(&condition, subroutine, controllerruntime.Result{}, nil, false, log)
cm.SetSubroutineCondition(&condition, subroutine, controllerruntime.Result{}, nil, false, log)

// Then
assert.Equal(t, 1, len(condition))
Expand All @@ -174,11 +168,12 @@ func TestSubroutineCondition(t *testing.T) {
// Add a test case to set a subroutine condition to unknown if it is still processing
t.Run("TestSetSubroutineConditionProcessing", func(t *testing.T) {
// Given
cm := NewConditionManager()
condition := []metav1.Condition{}
subroutine := changeStatusSubroutine{}
subroutine := pmtesting.ChangeStatusSubroutine{}

// When
setSubroutineCondition(&condition, subroutine, controllerruntime.Result{RequeueAfter: 1 * time.Second}, nil, false, log)
cm.SetSubroutineCondition(&condition, subroutine, controllerruntime.Result{RequeueAfter: 1 * time.Second}, nil, false, log)

// Then
assert.Equal(t, 1, len(condition))
Expand All @@ -189,10 +184,11 @@ func TestSubroutineCondition(t *testing.T) {
t.Run("TestSetSubroutineConditionError", func(t *testing.T) {
// Given
condition := []metav1.Condition{}
subroutine := changeStatusSubroutine{}
cm := NewConditionManager()
subroutine := pmtesting.ChangeStatusSubroutine{}

// When
setSubroutineCondition(&condition, subroutine, controllerruntime.Result{}, errors.New("failed"), false, log)
cm.SetSubroutineCondition(&condition, subroutine, controllerruntime.Result{}, errors.New("failed"), false, log)

// Then
assert.Equal(t, 1, len(condition))
Expand All @@ -202,11 +198,12 @@ func TestSubroutineCondition(t *testing.T) {
// Add a test case to set a subroutine condition for isFinalize true
t.Run("TestSetSubroutineFinalizeConditionReady", func(t *testing.T) {
// Given
cm := NewConditionManager()
condition := []metav1.Condition{}
subroutine := changeStatusSubroutine{}
subroutine := pmtesting.ChangeStatusSubroutine{}

// When
setSubroutineCondition(&condition, subroutine, controllerruntime.Result{}, nil, true, log)
cm.SetSubroutineCondition(&condition, subroutine, controllerruntime.Result{}, nil, true, log)

// Then
assert.Equal(t, 1, len(condition))
Expand All @@ -217,10 +214,11 @@ func TestSubroutineCondition(t *testing.T) {
t.Run("TestSetSubroutineFinalizeConditionProcessing", func(t *testing.T) {
// Given
condition := []metav1.Condition{}
subroutine := changeStatusSubroutine{}
cm := NewConditionManager()
subroutine := pmtesting.ChangeStatusSubroutine{}

// When
setSubroutineCondition(&condition, subroutine, controllerruntime.Result{RequeueAfter: 1 * time.Second}, nil, true, log)
cm.SetSubroutineCondition(&condition, subroutine, controllerruntime.Result{RequeueAfter: 1 * time.Second}, nil, true, log)

// Then
assert.Equal(t, 1, len(condition))
Expand All @@ -231,10 +229,11 @@ func TestSubroutineCondition(t *testing.T) {
t.Run("TestSetSubroutineFinalizeConditionError", func(t *testing.T) {
// Given
condition := []metav1.Condition{}
subroutine := changeStatusSubroutine{}
cm := NewConditionManager()
subroutine := pmtesting.ChangeStatusSubroutine{}

// When
setSubroutineCondition(&condition, subroutine, controllerruntime.Result{}, errors.New("failed"), true, log)
cm.SetSubroutineCondition(&condition, subroutine, controllerruntime.Result{}, errors.New("failed"), true, log)

// Then
assert.Equal(t, 1, len(condition))
Expand Down
Loading