mirror of
https://github.com/vmware-tanzu/pinniped.git
synced 2026-01-03 11:45:45 +00:00
Populate internal GitHub IDP Config from CRD
This commit is contained in:
@@ -12,29 +12,34 @@ import (
|
||||
"go.pinniped.dev/internal/plog"
|
||||
)
|
||||
|
||||
// MergeIDPConditions merges conditions into conditionsToUpdate. If returns true if it merged any error conditions.
|
||||
func MergeIDPConditions(conditions []*metav1.Condition, observedGeneration int64, conditionsToUpdate *[]metav1.Condition, log plog.MinLogger) bool {
|
||||
hadErrorCondition := false
|
||||
// MergeConditions merges conditions into conditionsToUpdate.
|
||||
// Note that LastTransitionTime refers to the time when the status changed,
|
||||
// but ObservedGeneration should be the current generation for all conditions, since Pinniped should always check every condition.
|
||||
// It returns true if any resulting condition has non-true status.
|
||||
func MergeConditions(
|
||||
conditions []*metav1.Condition,
|
||||
observedGeneration int64,
|
||||
conditionsToUpdate *[]metav1.Condition,
|
||||
log plog.MinLogger,
|
||||
lastTransitionTime metav1.Time,
|
||||
) bool {
|
||||
for i := range conditions {
|
||||
cond := conditions[i].DeepCopy()
|
||||
cond.LastTransitionTime = metav1.Now()
|
||||
cond.LastTransitionTime = lastTransitionTime
|
||||
cond.ObservedGeneration = observedGeneration
|
||||
if mergeIDPCondition(conditionsToUpdate, cond) {
|
||||
if mergeCondition(conditionsToUpdate, cond) {
|
||||
log.Info("updated condition", "type", cond.Type, "status", cond.Status, "reason", cond.Reason, "message", cond.Message)
|
||||
}
|
||||
if cond.Status == metav1.ConditionFalse {
|
||||
hadErrorCondition = true
|
||||
}
|
||||
}
|
||||
sort.SliceStable(*conditionsToUpdate, func(i, j int) bool {
|
||||
return (*conditionsToUpdate)[i].Type < (*conditionsToUpdate)[j].Type
|
||||
})
|
||||
return hadErrorCondition
|
||||
return HadErrorCondition(conditions)
|
||||
}
|
||||
|
||||
// mergeIDPCondition merges a new metav1.Condition into a slice of existing conditions. It returns true
|
||||
// mergeCondition merges a new metav1.Condition into a slice of existing conditions. It returns true
|
||||
// if the condition has meaningfully changed.
|
||||
func mergeIDPCondition(existing *[]metav1.Condition, new *metav1.Condition) bool {
|
||||
func mergeCondition(existing *[]metav1.Condition, new *metav1.Condition) bool {
|
||||
// Find any existing condition with a matching type.
|
||||
var old *metav1.Condition
|
||||
for i := range *existing {
|
||||
@@ -62,61 +67,7 @@ func mergeIDPCondition(existing *[]metav1.Condition, new *metav1.Condition) bool
|
||||
return true
|
||||
}
|
||||
|
||||
// Otherwise the entry is already up to date.
|
||||
return false
|
||||
}
|
||||
|
||||
// MergeConfigConditions merges conditions into conditionsToUpdate. It returns true if it merged any error conditions.
|
||||
func MergeConfigConditions(conditions []*metav1.Condition, observedGeneration int64, conditionsToUpdate *[]metav1.Condition, log plog.MinLogger, now metav1.Time) bool {
|
||||
hadErrorCondition := false
|
||||
for i := range conditions {
|
||||
cond := conditions[i].DeepCopy()
|
||||
cond.LastTransitionTime = now
|
||||
cond.ObservedGeneration = observedGeneration
|
||||
if mergeConfigCondition(conditionsToUpdate, cond) {
|
||||
log.Info("updated condition", "type", cond.Type, "status", cond.Status, "reason", cond.Reason, "message", cond.Message)
|
||||
}
|
||||
if cond.Status == metav1.ConditionFalse {
|
||||
hadErrorCondition = true
|
||||
}
|
||||
}
|
||||
sort.SliceStable(*conditionsToUpdate, func(i, j int) bool {
|
||||
return (*conditionsToUpdate)[i].Type < (*conditionsToUpdate)[j].Type
|
||||
})
|
||||
return hadErrorCondition
|
||||
}
|
||||
|
||||
// mergeConfigCondition merges a new metav1.Condition into a slice of existing conditions. It returns true
|
||||
// if the condition has meaningfully changed.
|
||||
func mergeConfigCondition(existing *[]metav1.Condition, new *metav1.Condition) bool {
|
||||
// Find any existing condition with a matching type.
|
||||
var old *metav1.Condition
|
||||
for i := range *existing {
|
||||
if (*existing)[i].Type == new.Type {
|
||||
old = &(*existing)[i]
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no existing condition of this type, append this one and we're done.
|
||||
if old == nil {
|
||||
*existing = append(*existing, *new)
|
||||
return true
|
||||
}
|
||||
|
||||
// Set the LastTransitionTime depending on whether the status has changed.
|
||||
new = new.DeepCopy()
|
||||
if old.Status == new.Status {
|
||||
new.LastTransitionTime = old.LastTransitionTime
|
||||
}
|
||||
|
||||
// If anything has actually changed, update the entry and return true.
|
||||
if !equality.Semantic.DeepEqual(old, new) {
|
||||
*old = *new
|
||||
return true
|
||||
}
|
||||
|
||||
// Otherwise the entry is already up to date.
|
||||
// Otherwise the entry is already up-to-date.
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
158
internal/controller/conditionsutil/conditions_util_test.go
Normal file
158
internal/controller/conditionsutil/conditions_util_test.go
Normal file
@@ -0,0 +1,158 @@
|
||||
// Copyright 2024 the Pinniped contributors. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package conditionsutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"go.pinniped.dev/internal/plog"
|
||||
)
|
||||
|
||||
func TestMergeIDPConditions(t *testing.T) {
|
||||
twoHoursAgo := metav1.Time{Time: time.Now().Add(-2 * time.Hour)}
|
||||
oneHourAgo := metav1.Time{Time: time.Now().Add(-1 * time.Hour)}
|
||||
testTime := metav1.Now()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
newConditions []*metav1.Condition
|
||||
conditionsToUpdate *[]metav1.Condition
|
||||
observedGeneration int64
|
||||
wantResult bool
|
||||
wantLogSnippets []string
|
||||
wantConditions []metav1.Condition
|
||||
}{
|
||||
{
|
||||
name: "True -> False returns true",
|
||||
newConditions: []*metav1.Condition{
|
||||
{
|
||||
Type: "UnchangedType",
|
||||
Status: metav1.ConditionTrue,
|
||||
Reason: "unchanged reason",
|
||||
Message: "unchanged message",
|
||||
},
|
||||
{
|
||||
Type: "FalseToTrueType",
|
||||
Status: metav1.ConditionFalse,
|
||||
Reason: "new reason",
|
||||
Message: "new message",
|
||||
},
|
||||
{
|
||||
Type: "NewType",
|
||||
Status: metav1.ConditionTrue,
|
||||
Reason: "new reason",
|
||||
Message: "new message",
|
||||
},
|
||||
},
|
||||
conditionsToUpdate: &[]metav1.Condition{
|
||||
{
|
||||
Type: "UnchangedType",
|
||||
Status: metav1.ConditionTrue,
|
||||
ObservedGeneration: int64(10),
|
||||
LastTransitionTime: twoHoursAgo,
|
||||
Reason: "unchanged reason",
|
||||
Message: "unchanged message",
|
||||
},
|
||||
{
|
||||
Type: "FalseToTrueType",
|
||||
Status: metav1.ConditionTrue,
|
||||
ObservedGeneration: int64(5),
|
||||
LastTransitionTime: oneHourAgo,
|
||||
Reason: "old reason",
|
||||
Message: "old message",
|
||||
},
|
||||
},
|
||||
observedGeneration: int64(100),
|
||||
wantLogSnippets: []string{
|
||||
`"message":"updated condition","type":"UnchangedType","status":"True"`,
|
||||
`"message":"updated condition","type":"NewType","status":"True"`,
|
||||
`"message":"updated condition","type":"FalseToTrueType","status":"False"`,
|
||||
},
|
||||
wantConditions: []metav1.Condition{
|
||||
{
|
||||
Type: "FalseToTrueType",
|
||||
Status: metav1.ConditionFalse,
|
||||
ObservedGeneration: int64(100),
|
||||
LastTransitionTime: testTime,
|
||||
Reason: "new reason",
|
||||
Message: "new message",
|
||||
},
|
||||
{
|
||||
Type: "NewType",
|
||||
Status: metav1.ConditionTrue,
|
||||
ObservedGeneration: int64(100),
|
||||
LastTransitionTime: testTime,
|
||||
Reason: "new reason",
|
||||
Message: "new message",
|
||||
},
|
||||
{
|
||||
Type: "UnchangedType",
|
||||
Status: metav1.ConditionTrue,
|
||||
ObservedGeneration: int64(100),
|
||||
LastTransitionTime: twoHoursAgo,
|
||||
Reason: "unchanged reason",
|
||||
Message: "unchanged message",
|
||||
},
|
||||
},
|
||||
wantResult: true,
|
||||
},
|
||||
{
|
||||
name: "No logs when ObservedGeneration is unchanged",
|
||||
newConditions: []*metav1.Condition{
|
||||
{
|
||||
Type: "UnchangedType",
|
||||
Status: metav1.ConditionFalse,
|
||||
Reason: "unchanged reason",
|
||||
Message: "unchanged message",
|
||||
},
|
||||
},
|
||||
conditionsToUpdate: &[]metav1.Condition{
|
||||
{
|
||||
Type: "UnchangedType",
|
||||
Status: metav1.ConditionFalse,
|
||||
ObservedGeneration: int64(10),
|
||||
LastTransitionTime: twoHoursAgo,
|
||||
Reason: "unchanged reason",
|
||||
Message: "unchanged message",
|
||||
},
|
||||
},
|
||||
observedGeneration: int64(10),
|
||||
wantConditions: []metav1.Condition{
|
||||
{
|
||||
Type: "UnchangedType",
|
||||
Status: metav1.ConditionFalse,
|
||||
ObservedGeneration: int64(10),
|
||||
LastTransitionTime: twoHoursAgo,
|
||||
Reason: "unchanged reason",
|
||||
Message: "unchanged message",
|
||||
},
|
||||
},
|
||||
wantResult: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
var log bytes.Buffer
|
||||
logger := plog.TestLogger(t, &log)
|
||||
|
||||
result := MergeConditions(tt.newConditions, tt.observedGeneration, tt.conditionsToUpdate, logger, testTime)
|
||||
|
||||
logString := log.String()
|
||||
require.Equal(t, len(tt.wantLogSnippets), strings.Count(logString, "\n"))
|
||||
for _, wantLog := range tt.wantLogSnippets {
|
||||
require.Contains(t, logString, wantLog)
|
||||
}
|
||||
require.Equal(t, tt.wantResult, result)
|
||||
require.Equal(t, tt.wantConditions, *tt.conditionsToUpdate)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user