Merge pull request #227 from negz/intermediary
Allow XRs and XRCs to record when they last published connection details
This commit is contained in:
commit
31eef9b01e
|
|
@ -41,6 +41,7 @@ const AnnotationKeyExternalName = "crossplane.io/external-name"
|
||||||
const (
|
const (
|
||||||
AnnotationKeyPropagateToPrefix = "to.propagate.crossplane.io/"
|
AnnotationKeyPropagateToPrefix = "to.propagate.crossplane.io/"
|
||||||
|
|
||||||
|
// Deprecated: This functionality will be removed soon.
|
||||||
AnnotationKeyPropagateFromNamespace = "from.propagate.crossplane.io/namespace"
|
AnnotationKeyPropagateFromNamespace = "from.propagate.crossplane.io/namespace"
|
||||||
AnnotationKeyPropagateFromName = "from.propagate.crossplane.io/name"
|
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
|
// AllowPropagation from one object to another by adding consenting annotations
|
||||||
// to both.
|
// to both.
|
||||||
|
// Deprecated: This functionality will be removed soon.
|
||||||
func AllowPropagation(from, to metav1.Object) {
|
func AllowPropagation(from, to metav1.Object) {
|
||||||
AddAnnotations(to, map[string]string{
|
AddAnnotations(to, map[string]string{
|
||||||
AnnotationKeyPropagateFromNamespace: from.GetNamespace(),
|
AnnotationKeyPropagateFromNamespace: from.GetNamespace(),
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ const (
|
||||||
|
|
||||||
// An APIManagedConnectionPropagator propagates connection details by reading
|
// An APIManagedConnectionPropagator propagates connection details by reading
|
||||||
// them from and writing them to a Kubernetes API server.
|
// them from and writing them to a Kubernetes API server.
|
||||||
|
// Deprecated: This functionality will be removed soon.
|
||||||
type APIManagedConnectionPropagator struct {
|
type APIManagedConnectionPropagator struct {
|
||||||
Propagator ConnectionPropagator
|
Propagator ConnectionPropagator
|
||||||
}
|
}
|
||||||
|
|
@ -54,12 +55,14 @@ func (a *APIManagedConnectionPropagator) PropagateConnection(ctx context.Context
|
||||||
|
|
||||||
// An APIConnectionPropagator propagates connection details by reading
|
// An APIConnectionPropagator propagates connection details by reading
|
||||||
// them from and writing them to a Kubernetes API server.
|
// them from and writing them to a Kubernetes API server.
|
||||||
|
// Deprecated: This functionality will be removed soon.
|
||||||
type APIConnectionPropagator struct {
|
type APIConnectionPropagator struct {
|
||||||
client ClientApplicator
|
client ClientApplicator
|
||||||
typer runtime.ObjectTyper
|
typer runtime.ObjectTyper
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAPIConnectionPropagator returns a new APIConnectionPropagator.
|
// NewAPIConnectionPropagator returns a new APIConnectionPropagator.
|
||||||
|
// Deprecated: This functionality will be removed soon.
|
||||||
func NewAPIConnectionPropagator(c client.Client, t runtime.ObjectTyper) *APIConnectionPropagator {
|
func NewAPIConnectionPropagator(c client.Client, t runtime.ObjectTyper) *APIConnectionPropagator {
|
||||||
return &APIConnectionPropagator{
|
return &APIConnectionPropagator{
|
||||||
client: ClientApplicator{Client: c, Applicator: NewAPIUpdatingApplicator(c)},
|
client: ClientApplicator{Client: c, Applicator: NewAPIUpdatingApplicator(c)},
|
||||||
|
|
|
||||||
|
|
@ -181,6 +181,20 @@ func (m *ComposedResourcesReferencer) SetResourceReferences(r []corev1.ObjectRef
|
||||||
// GetResourceReferences gets the composed references.
|
// GetResourceReferences gets the composed references.
|
||||||
func (m *ComposedResourcesReferencer) GetResourceReferences() []corev1.ObjectReference { return m.Refs }
|
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
|
// UserCounter is a mock that satisfies UserCounter
|
||||||
// interface.
|
// interface.
|
||||||
type UserCounter struct{ Users int64 }
|
type UserCounter struct{ Users int64 }
|
||||||
|
|
@ -251,7 +265,9 @@ type Composite struct {
|
||||||
ComposedResourcesReferencer
|
ComposedResourcesReferencer
|
||||||
ClaimReferencer
|
ClaimReferencer
|
||||||
ConnectionSecretWriterTo
|
ConnectionSecretWriterTo
|
||||||
|
|
||||||
v1alpha1.ConditionedStatus
|
v1alpha1.ConditionedStatus
|
||||||
|
ConnectionDetailsLastPublishedTimer
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetObjectKind returns schema.ObjectKind.
|
// GetObjectKind returns schema.ObjectKind.
|
||||||
|
|
@ -300,7 +316,9 @@ type CompositeClaim struct {
|
||||||
CompositionReferencer
|
CompositionReferencer
|
||||||
CompositeResourceReferencer
|
CompositeResourceReferencer
|
||||||
LocalConnectionSecretWriterTo
|
LocalConnectionSecretWriterTo
|
||||||
|
|
||||||
v1alpha1.ConditionedStatus
|
v1alpha1.ConditionedStatus
|
||||||
|
ConnectionDetailsLastPublishedTimer
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetObjectKind returns schema.ObjectKind.
|
// GetObjectKind returns schema.ObjectKind.
|
||||||
|
|
|
||||||
|
|
@ -126,6 +126,13 @@ type UserCounter interface {
|
||||||
GetUsers() int64
|
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.
|
// An Object is a Kubernetes object.
|
||||||
type Object interface {
|
type Object interface {
|
||||||
metav1.Object
|
metav1.Object
|
||||||
|
|
@ -188,6 +195,7 @@ type Composite interface {
|
||||||
ConnectionSecretWriterTo
|
ConnectionSecretWriterTo
|
||||||
|
|
||||||
Conditioned
|
Conditioned
|
||||||
|
ConnectionDetailsPublishedTimer
|
||||||
}
|
}
|
||||||
|
|
||||||
// Composed resources can be a composed into a Composite resource.
|
// Composed resources can be a composed into a Composite resource.
|
||||||
|
|
@ -208,4 +216,5 @@ type CompositeClaim interface {
|
||||||
LocalConnectionSecretWriterTo
|
LocalConnectionSecretWriterTo
|
||||||
|
|
||||||
Conditioned
|
Conditioned
|
||||||
|
ConnectionDetailsPublishedTimer
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -72,6 +72,7 @@ type LocalConnectionSecretOwner interface {
|
||||||
|
|
||||||
// A ConnectionPropagator is responsible for propagating information required to
|
// A ConnectionPropagator is responsible for propagating information required to
|
||||||
// connect to a resource.
|
// connect to a resource.
|
||||||
|
// Deprecated: This functionality will be removed soon.
|
||||||
type ConnectionPropagator interface {
|
type ConnectionPropagator interface {
|
||||||
PropagateConnection(ctx context.Context, to LocalConnectionSecretOwner, from ConnectionSecretOwner) error
|
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
|
// A ManagedConnectionPropagator is responsible for propagating information
|
||||||
// required to connect to a managed resource (for example the connection secret)
|
// required to connect to a managed resource (for example the connection secret)
|
||||||
// from the managed resource to a target.
|
// from the managed resource to a target.
|
||||||
|
// Deprecated: This functionality will be removed soon.
|
||||||
type ManagedConnectionPropagator interface {
|
type ManagedConnectionPropagator interface {
|
||||||
PropagateConnection(ctx context.Context, o LocalConnectionSecretOwner, mg Managed) error
|
PropagateConnection(ctx context.Context, o LocalConnectionSecretOwner, mg Managed) error
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -139,3 +139,17 @@ func (c *Unstructured) SetConditions(conditions ...v1alpha1.Condition) {
|
||||||
conditioned.SetConditions(conditions...)
|
conditioned.SetConditions(conditions...)
|
||||||
_ = fieldpath.Pave(c.Object).SetValue("status.conditions", conditioned.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
|
package claim
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
corev1 "k8s.io/api/core/v1"
|
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...)
|
conditioned.SetConditions(conditions...)
|
||||||
_ = fieldpath.Pave(c.Object).SetValue("status.conditions", conditioned.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
|
package composite
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
corev1 "k8s.io/api/core/v1"
|
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