Allow XRs and XRCs to record when they last published connection details
This information is useful both for debugging XRs and XRCs, and for controllers to watch for updates to connection details (i.e. if those details were stored in an external system rather than in Secrets, which can themselves be watched). Signed-off-by: Nic Cope <negz@rk0n.org>
This commit is contained in:
parent
dd9eadb05e
commit
cf744159e5
|
|
@ -181,6 +181,20 @@ func (m *ComposedResourcesReferencer) SetResourceReferences(r []corev1.ObjectRef
|
|||
// GetResourceReferences gets the composed references.
|
||||
func (m *ComposedResourcesReferencer) GetResourceReferences() []corev1.ObjectReference { return m.Refs }
|
||||
|
||||
// ConnectionDetailsLastPublishedTimer is a mock that implements the
|
||||
// ConnectionDetailsLastPublishedTimer interface.
|
||||
type ConnectionDetailsLastPublishedTimer struct{ Time *metav1.Time }
|
||||
|
||||
// SetConnectionDetailsLastPublishedTime sets the published time.
|
||||
func (c *ConnectionDetailsLastPublishedTimer) SetConnectionDetailsLastPublishedTime(t *metav1.Time) {
|
||||
c.Time = t
|
||||
}
|
||||
|
||||
// GetConnectionDetailsLastPublishedTime gets the published time.
|
||||
func (c *ConnectionDetailsLastPublishedTimer) GetConnectionDetailsLastPublishedTime() *metav1.Time {
|
||||
return c.Time
|
||||
}
|
||||
|
||||
// UserCounter is a mock that satisfies UserCounter
|
||||
// interface.
|
||||
type UserCounter struct{ Users int64 }
|
||||
|
|
@ -251,7 +265,9 @@ type Composite struct {
|
|||
ComposedResourcesReferencer
|
||||
ClaimReferencer
|
||||
ConnectionSecretWriterTo
|
||||
|
||||
v1alpha1.ConditionedStatus
|
||||
ConnectionDetailsLastPublishedTimer
|
||||
}
|
||||
|
||||
// GetObjectKind returns schema.ObjectKind.
|
||||
|
|
@ -300,7 +316,9 @@ type CompositeClaim struct {
|
|||
CompositionReferencer
|
||||
CompositeResourceReferencer
|
||||
LocalConnectionSecretWriterTo
|
||||
|
||||
v1alpha1.ConditionedStatus
|
||||
ConnectionDetailsLastPublishedTimer
|
||||
}
|
||||
|
||||
// GetObjectKind returns schema.ObjectKind.
|
||||
|
|
|
|||
|
|
@ -126,6 +126,13 @@ type UserCounter interface {
|
|||
GetUsers() int64
|
||||
}
|
||||
|
||||
// A ConnectionDetailsPublishedTimer can record the last time its connection
|
||||
// details were published.
|
||||
type ConnectionDetailsPublishedTimer interface {
|
||||
SetConnectionDetailsLastPublishedTime(t *metav1.Time)
|
||||
GetConnectionDetailsLastPublishedTime() *metav1.Time
|
||||
}
|
||||
|
||||
// An Object is a Kubernetes object.
|
||||
type Object interface {
|
||||
metav1.Object
|
||||
|
|
@ -188,6 +195,7 @@ type Composite interface {
|
|||
ConnectionSecretWriterTo
|
||||
|
||||
Conditioned
|
||||
ConnectionDetailsPublishedTimer
|
||||
}
|
||||
|
||||
// Composed resources can be a composed into a Composite resource.
|
||||
|
|
@ -208,4 +216,5 @@ type CompositeClaim interface {
|
|||
LocalConnectionSecretWriterTo
|
||||
|
||||
Conditioned
|
||||
ConnectionDetailsPublishedTimer
|
||||
}
|
||||
|
|
|
|||
|
|
@ -139,3 +139,17 @@ func (c *Unstructured) SetConditions(conditions ...v1alpha1.Condition) {
|
|||
conditioned.SetConditions(conditions...)
|
||||
_ = fieldpath.Pave(c.Object).SetValue("status.conditions", conditioned.Conditions)
|
||||
}
|
||||
|
||||
// GetConnectionDetailsLastPublishedTime of this composite resource claim.
|
||||
func (c *Unstructured) GetConnectionDetailsLastPublishedTime() *metav1.Time {
|
||||
out := &metav1.Time{}
|
||||
if err := fieldpath.Pave(c.Object).GetValueInto("status.connectionDetails.lastPublishedTime", out); err != nil {
|
||||
return nil
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// SetConnectionDetailsLastPublishedTime of this composite resource claim.
|
||||
func (c *Unstructured) SetConnectionDetailsLastPublishedTime(t *metav1.Time) {
|
||||
_ = fieldpath.Pave(c.Object).SetValue("status.connectionDetails.lastPublishedTime", t)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@ limitations under the License.
|
|||
package claim
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
|
@ -213,3 +215,38 @@ func TestWriteConnectionSecretToReference(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnectionDetailsLastPublishedTime(t *testing.T) {
|
||||
now := &metav1.Time{Time: time.Now()}
|
||||
|
||||
// The timestamp loses a little resolution when round-tripped through JSON
|
||||
// encoding.
|
||||
lores := func(t *metav1.Time) *metav1.Time {
|
||||
out := &metav1.Time{}
|
||||
j, _ := json.Marshal(t)
|
||||
_ = json.Unmarshal(j, out)
|
||||
return out
|
||||
}
|
||||
|
||||
cases := map[string]struct {
|
||||
u *Unstructured
|
||||
set *metav1.Time
|
||||
want *metav1.Time
|
||||
}{
|
||||
"NewTime": {
|
||||
u: New(),
|
||||
set: now,
|
||||
want: lores(now),
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
tc.u.SetConnectionDetailsLastPublishedTime(tc.set)
|
||||
got := tc.u.GetConnectionDetailsLastPublishedTime()
|
||||
if diff := cmp.Diff(tc.want, got); diff != "" {
|
||||
t.Errorf("\nu.GetConnectionDetailsLastPublishedTime(): -want, +got:\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -161,3 +161,17 @@ func (c *Unstructured) SetConditions(conditions ...v1alpha1.Condition) {
|
|||
conditioned.SetConditions(conditions...)
|
||||
_ = fieldpath.Pave(c.Object).SetValue("status.conditions", conditioned.Conditions)
|
||||
}
|
||||
|
||||
// GetConnectionDetailsLastPublishedTime of this Composite resource.
|
||||
func (c *Unstructured) GetConnectionDetailsLastPublishedTime() *metav1.Time {
|
||||
out := &metav1.Time{}
|
||||
if err := fieldpath.Pave(c.Object).GetValueInto("status.connectionDetails.lastPublishedTime", out); err != nil {
|
||||
return nil
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// SetConnectionDetailsLastPublishedTime of this Composite resource.
|
||||
func (c *Unstructured) SetConnectionDetailsLastPublishedTime(t *metav1.Time) {
|
||||
_ = fieldpath.Pave(c.Object).SetValue("status.connectionDetails.lastPublishedTime", t)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@ limitations under the License.
|
|||
package composite
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
|
@ -238,3 +240,38 @@ func TestWriteConnectionSecretToReference(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConnectionDetailsLastPublishedTime(t *testing.T) {
|
||||
now := &metav1.Time{Time: time.Now()}
|
||||
|
||||
// The timestamp loses a little resolution when round-tripped through JSON
|
||||
// encoding.
|
||||
lores := func(t *metav1.Time) *metav1.Time {
|
||||
out := &metav1.Time{}
|
||||
j, _ := json.Marshal(t)
|
||||
_ = json.Unmarshal(j, out)
|
||||
return out
|
||||
}
|
||||
|
||||
cases := map[string]struct {
|
||||
u *Unstructured
|
||||
set *metav1.Time
|
||||
want *metav1.Time
|
||||
}{
|
||||
"NewTime": {
|
||||
u: New(),
|
||||
set: now,
|
||||
want: lores(now),
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
tc.u.SetConnectionDetailsLastPublishedTime(tc.set)
|
||||
got := tc.u.GetConnectionDetailsLastPublishedTime()
|
||||
if diff := cmp.Diff(tc.want, got); diff != "" {
|
||||
t.Errorf("\nu.GetConnectionDetailsLastPublishedTime(): -want, +got:\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue