Merge pull request #227 from negz/intermediary

Allow XRs and XRCs to record when they last published connection details
This commit is contained in:
Nic Cope 2020-11-05 00:51:05 -08:00 committed by GitHub
commit 31eef9b01e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 136 additions and 0 deletions

View File

@ -41,6 +41,7 @@ const AnnotationKeyExternalName = "crossplane.io/external-name"
const (
AnnotationKeyPropagateToPrefix = "to.propagate.crossplane.io/"
// Deprecated: This functionality will be removed soon.
AnnotationKeyPropagateFromNamespace = "from.propagate.crossplane.io/namespace"
AnnotationKeyPropagateFromName = "from.propagate.crossplane.io/name"
)
@ -246,6 +247,7 @@ func SetExternalName(o metav1.Object, name string) {
// AllowPropagation from one object to another by adding consenting annotations
// to both.
// Deprecated: This functionality will be removed soon.
func AllowPropagation(from, to metav1.Object) {
AddAnnotations(to, map[string]string{
AnnotationKeyPropagateFromNamespace: from.GetNamespace(),

View File

@ -43,6 +43,7 @@ const (
// An APIManagedConnectionPropagator propagates connection details by reading
// them from and writing them to a Kubernetes API server.
// Deprecated: This functionality will be removed soon.
type APIManagedConnectionPropagator struct {
Propagator ConnectionPropagator
}
@ -54,12 +55,14 @@ func (a *APIManagedConnectionPropagator) PropagateConnection(ctx context.Context
// An APIConnectionPropagator propagates connection details by reading
// them from and writing them to a Kubernetes API server.
// Deprecated: This functionality will be removed soon.
type APIConnectionPropagator struct {
client ClientApplicator
typer runtime.ObjectTyper
}
// NewAPIConnectionPropagator returns a new APIConnectionPropagator.
// Deprecated: This functionality will be removed soon.
func NewAPIConnectionPropagator(c client.Client, t runtime.ObjectTyper) *APIConnectionPropagator {
return &APIConnectionPropagator{
client: ClientApplicator{Client: c, Applicator: NewAPIUpdatingApplicator(c)},

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

@ -72,6 +72,7 @@ type LocalConnectionSecretOwner interface {
// A ConnectionPropagator is responsible for propagating information required to
// connect to a resource.
// Deprecated: This functionality will be removed soon.
type ConnectionPropagator interface {
PropagateConnection(ctx context.Context, to LocalConnectionSecretOwner, from ConnectionSecretOwner) error
}
@ -83,6 +84,7 @@ type ConnectionPropagatorFn func(ctx context.Context, to LocalConnectionSecretOw
// A ManagedConnectionPropagator is responsible for propagating information
// required to connect to a managed resource (for example the connection secret)
// from the managed resource to a target.
// Deprecated: This functionality will be removed soon.
type ManagedConnectionPropagator interface {
PropagateConnection(ctx context.Context, o LocalConnectionSecretOwner, mg Managed) error
}

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