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:
Nic Cope 2020-11-05 04:12:20 +00:00
parent dd9eadb05e
commit cf744159e5
6 changed files with 129 additions and 0 deletions

View File

@ -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.

View File

@ -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
}

View File

@ -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)
}

View File

@ -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)
}
})
}
}

View File

@ -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)
}

View File

@ -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)
}
})
}
}