Skip to content

Commit

Permalink
Merge pull request #110 from negz/ref
Browse files Browse the repository at this point in the history
Move some referencer types back to pkg/resource
  • Loading branch information
negz authored Jan 15, 2020
2 parents e0d566e + 5e66b02 commit cd8c52b
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 151 deletions.
6 changes: 3 additions & 3 deletions pkg/reconciler/managed/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,15 @@ type ReferenceResolver interface {
// resources to update corresponding fields in CanReference, for example
// setting .spec.network to the name of the Network resource specified as
// .spec.networkRef.
ResolveReferences(ctx context.Context, res CanReference) error
ResolveReferences(ctx context.Context, res resource.CanReference) error
}

// A ReferenceResolverFn is a function that satisfies the
// ReferenceResolver interface.
type ReferenceResolverFn func(context.Context, CanReference) error
type ReferenceResolverFn func(context.Context, resource.CanReference) error

// ResolveReferences calls ReferenceResolverFn function
func (m ReferenceResolverFn) ResolveReferences(ctx context.Context, res CanReference) error {
func (m ReferenceResolverFn) ResolveReferences(ctx context.Context, res resource.CanReference) error {
return m(ctx, res)
}

Expand Down
34 changes: 17 additions & 17 deletions pkg/reconciler/managed/reconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func TestReconciler(t *testing.T) {
}

errBoom := errors.New("boom")
errNotReady := &referencesAccessErr{[]ReferenceStatus{{Name: "cool-res", Status: ReferenceNotReady}}}
errNotReady := &referencesAccessErr{[]resource.ReferenceStatus{{Name: "cool-res", Status: resource.ReferenceNotReady}}}
now := metav1.Now()

cases := map[string]struct {
Expand Down Expand Up @@ -160,7 +160,7 @@ func TestReconciler(t *testing.T) {
o: []ReconcilerOption{
WithInitializers(),
WithExternalConnecter(&NopConnecter{}),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, res CanReference) error {
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, res resource.CanReference) error {
return errNotReady
})),
},
Expand Down Expand Up @@ -189,7 +189,7 @@ func TestReconciler(t *testing.T) {
o: []ReconcilerOption{
WithInitializers(),
WithExternalConnecter(&NopConnecter{}),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, res CanReference) error {
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, res resource.CanReference) error {
return errBoom
})),
},
Expand Down Expand Up @@ -258,7 +258,7 @@ func TestReconciler(t *testing.T) {
mg: resource.ManagedKind(fake.GVK(&fake.Managed{})),
o: []ReconcilerOption{
WithInitializers(),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ CanReference) error { return nil })),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ resource.CanReference) error { return nil })),
WithExternalConnecter(ExternalConnectorFn(func(_ context.Context, mg resource.Managed) (ExternalClient, error) {
c := &ExternalClientFns{
ObserveFn: func(_ context.Context, _ resource.Managed) (ExternalObservation, error) {
Expand Down Expand Up @@ -302,7 +302,7 @@ func TestReconciler(t *testing.T) {
mg: resource.ManagedKind(fake.GVK(&fake.Managed{})),
o: []ReconcilerOption{
WithInitializers(),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ CanReference) error { return nil })),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ resource.CanReference) error { return nil })),
WithExternalConnecter(ExternalConnectorFn(func(_ context.Context, mg resource.Managed) (ExternalClient, error) {
c := &ExternalClientFns{
ObserveFn: func(_ context.Context, _ resource.Managed) (ExternalObservation, error) {
Expand Down Expand Up @@ -344,7 +344,7 @@ func TestReconciler(t *testing.T) {
mg: resource.ManagedKind(fake.GVK(&fake.Managed{})),
o: []ReconcilerOption{
WithInitializers(),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ CanReference) error { return nil })),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ resource.CanReference) error { return nil })),
WithExternalConnecter(ExternalConnectorFn(func(_ context.Context, mg resource.Managed) (ExternalClient, error) {
c := &ExternalClientFns{
ObserveFn: func(_ context.Context, _ resource.Managed) (ExternalObservation, error) {
Expand Down Expand Up @@ -386,7 +386,7 @@ func TestReconciler(t *testing.T) {
mg: resource.ManagedKind(fake.GVK(&fake.Managed{})),
o: []ReconcilerOption{
WithInitializers(),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ CanReference) error { return nil })),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ resource.CanReference) error { return nil })),
WithExternalConnecter(ExternalConnectorFn(func(_ context.Context, mg resource.Managed) (ExternalClient, error) {
c := &ExternalClientFns{
ObserveFn: func(_ context.Context, _ resource.Managed) (ExternalObservation, error) {
Expand Down Expand Up @@ -417,7 +417,7 @@ func TestReconciler(t *testing.T) {
mg: resource.ManagedKind(fake.GVK(&fake.Managed{})),
o: []ReconcilerOption{
WithInitializers(),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ CanReference) error { return nil })),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ resource.CanReference) error { return nil })),
WithExternalConnecter(ExternalConnectorFn(func(_ context.Context, mg resource.Managed) (ExternalClient, error) {
c := &ExternalClientFns{
ObserveFn: func(_ context.Context, _ resource.Managed) (ExternalObservation, error) {
Expand Down Expand Up @@ -454,7 +454,7 @@ func TestReconciler(t *testing.T) {
mg: resource.ManagedKind(fake.GVK(&fake.Managed{})),
o: []ReconcilerOption{
WithInitializers(),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ CanReference) error { return nil })),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ resource.CanReference) error { return nil })),
WithExternalConnecter(&NopConnecter{}),
WithConnectionPublishers(ConnectionPublisherFns{
PublishConnectionFn: func(_ context.Context, _ resource.Managed, _ ConnectionDetails) error { return errBoom },
Expand Down Expand Up @@ -485,7 +485,7 @@ func TestReconciler(t *testing.T) {
mg: resource.ManagedKind(fake.GVK(&fake.Managed{})),
o: []ReconcilerOption{
WithInitializers(),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ CanReference) error { return nil })),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ resource.CanReference) error { return nil })),
WithExternalConnecter(&NopConnecter{}),
WithConnectionPublishers(),
WithFinalizer(FinalizerFns{AddFinalizerFn: func(_ context.Context, _ resource.Managed) error { return errBoom }}),
Expand Down Expand Up @@ -515,7 +515,7 @@ func TestReconciler(t *testing.T) {
mg: resource.ManagedKind(fake.GVK(&fake.Managed{})),
o: []ReconcilerOption{
WithInitializers(),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ CanReference) error { return nil })),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ resource.CanReference) error { return nil })),
WithExternalConnecter(ExternalConnectorFn(func(_ context.Context, mg resource.Managed) (ExternalClient, error) {
c := &ExternalClientFns{
ObserveFn: func(_ context.Context, _ resource.Managed) (ExternalObservation, error) {
Expand Down Expand Up @@ -555,7 +555,7 @@ func TestReconciler(t *testing.T) {
mg: resource.ManagedKind(fake.GVK(&fake.Managed{})),
o: []ReconcilerOption{
WithInitializers(),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ CanReference) error { return nil })),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ resource.CanReference) error { return nil })),
WithExternalConnecter(ExternalConnectorFn(func(_ context.Context, mg resource.Managed) (ExternalClient, error) {
c := &ExternalClientFns{
ObserveFn: func(_ context.Context, _ resource.Managed) (ExternalObservation, error) {
Expand Down Expand Up @@ -606,7 +606,7 @@ func TestReconciler(t *testing.T) {
mg: resource.ManagedKind(fake.GVK(&fake.Managed{})),
o: []ReconcilerOption{
WithInitializers(),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ CanReference) error { return nil })),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ resource.CanReference) error { return nil })),
WithExternalConnecter(&NopConnecter{}),
WithConnectionPublishers(),
WithFinalizer(FinalizerFns{AddFinalizerFn: func(_ context.Context, _ resource.Managed) error { return nil }}),
Expand Down Expand Up @@ -636,7 +636,7 @@ func TestReconciler(t *testing.T) {
mg: resource.ManagedKind(fake.GVK(&fake.Managed{})),
o: []ReconcilerOption{
WithInitializers(),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ CanReference) error { return nil })),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ resource.CanReference) error { return nil })),
WithExternalConnecter(ExternalConnectorFn(func(_ context.Context, mg resource.Managed) (ExternalClient, error) {
c := &ExternalClientFns{
ObserveFn: func(_ context.Context, _ resource.Managed) (ExternalObservation, error) {
Expand Down Expand Up @@ -673,7 +673,7 @@ func TestReconciler(t *testing.T) {
mg: resource.ManagedKind(fake.GVK(&fake.Managed{})),
o: []ReconcilerOption{
WithInitializers(),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ CanReference) error { return nil })),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ resource.CanReference) error { return nil })),
WithExternalConnecter(ExternalConnectorFn(func(_ context.Context, mg resource.Managed) (ExternalClient, error) {
c := &ExternalClientFns{
ObserveFn: func(_ context.Context, _ resource.Managed) (ExternalObservation, error) {
Expand Down Expand Up @@ -713,7 +713,7 @@ func TestReconciler(t *testing.T) {
mg: resource.ManagedKind(fake.GVK(&fake.Managed{})),
o: []ReconcilerOption{
WithInitializers(),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ CanReference) error { return nil })),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ resource.CanReference) error { return nil })),
WithExternalConnecter(ExternalConnectorFn(func(_ context.Context, mg resource.Managed) (ExternalClient, error) {
c := &ExternalClientFns{
ObserveFn: func(_ context.Context, _ resource.Managed) (ExternalObservation, error) {
Expand Down Expand Up @@ -764,7 +764,7 @@ func TestReconciler(t *testing.T) {
mg: resource.ManagedKind(fake.GVK(&fake.Managed{})),
o: []ReconcilerOption{
WithInitializers(),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ CanReference) error { return nil })),
WithReferenceResolver(ReferenceResolverFn(func(_ context.Context, _ resource.CanReference) error { return nil })),
WithExternalConnecter(ExternalConnectorFn(func(_ context.Context, mg resource.Managed) (ExternalClient, error) {
c := &ExternalClientFns{
ObserveFn: func(_ context.Context, _ resource.Managed) (ExternalObservation, error) {
Expand Down
78 changes: 13 additions & 65 deletions pkg/reconciler/managed/reference_resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ import (

"github.com/google/go-cmp/cmp"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/runtime"

"sigs.k8s.io/controller-runtime/pkg/client"

"github.com/crossplaneio/crossplane-runtime/pkg/resource"
)

// Error strings
Expand All @@ -36,45 +36,17 @@ const (
errAssignAttribute = "could not assign the attribute"
)

// ReferenceStatusType is an enum type for the possible values for a Reference Status
type ReferenceStatusType int

const (
// ReferenceStatusUnknown is the default value
ReferenceStatusUnknown ReferenceStatusType = iota
// ReferenceNotFound shows that the reference is not found
ReferenceNotFound
// ReferenceNotReady shows that the reference is not ready
ReferenceNotReady
// ReferenceReady shows that the reference is ready
ReferenceReady
)

func (t ReferenceStatusType) String() string {
return []string{"Unknown", "NotFound", "NotReady", "Ready"}[t]
}

// ReferenceStatus has the name and status of a reference
type ReferenceStatus struct {
Name string
Status ReferenceStatusType
}

func (r ReferenceStatus) String() string {
return fmt.Sprintf("{reference:%s status:%s}", r.Name, r.Status)
}

// referencesAccessErr is used to indicate that one or more references can not
// be accessed
type referencesAccessErr struct {
statuses []ReferenceStatus
statuses []resource.ReferenceStatus
}

// newReferenceAccessErr returns a referencesAccessErr if any of the given
// references are not ready
func newReferenceAccessErr(statuses []ReferenceStatus) error {
func newReferenceAccessErr(statuses []resource.ReferenceStatus) error {
for _, st := range statuses {
if st.Status != ReferenceReady {
if st.Status != resource.ReferenceReady {
return &referencesAccessErr{statuses}
}
}
Expand All @@ -94,41 +66,17 @@ func IsReferencesAccessError(err error) bool {
return result
}

// A CanReference is a resource that can reference another resource in its
// spec in order to automatically resolve corresponding spec field values
// by inspecting the referenced resource.
type CanReference runtime.Object

// An AttributeReferencer resolves cross-resource attribute references. See
// https://github.com/crossplaneio/crossplane/blob/master/design/one-pager-cross-resource-referencing.md
// for more information
type AttributeReferencer interface {
// GetStatus retries the referenced resource, as well as other non-managed
// resources (like a `Provider`) and reports their readiness for use as a
// referenced resource.
GetStatus(ctx context.Context, res CanReference, r client.Reader) ([]ReferenceStatus, error)

// Build retrieves the referenced resource, as well as other non-managed
// resources (like a `Provider`), and builds the referenced attribute,
// returning it as a string value.
Build(ctx context.Context, res CanReference, r client.Reader) (value string, err error)

// Assign accepts a managed resource object, and assigns the given value to
// its corresponding property.
Assign(res CanReference, value string) error
}

// An AttributeReferencerFinder returns all types within the supplied object
// that satisfy AttributeReferencer.
type AttributeReferencerFinder interface {
FindReferencers(obj interface{}) []AttributeReferencer
FindReferencers(obj interface{}) []resource.AttributeReferencer
}

// An AttributeReferencerFinderFn satisfies AttributeReferencerFinder.
type AttributeReferencerFinderFn func(obj interface{}) []AttributeReferencer
type AttributeReferencerFinderFn func(obj interface{}) []resource.AttributeReferencer

// FindReferencers finds all AttributeReferencers.
func (fn AttributeReferencerFinderFn) FindReferencers(obj interface{}) []AttributeReferencer {
func (fn AttributeReferencerFinderFn) FindReferencers(obj interface{}) []resource.AttributeReferencer {
return fn(obj)
}

Expand Down Expand Up @@ -170,7 +118,7 @@ func NewAPIReferenceResolver(c client.Client, o ...APIReferenceResolverOption) *
}

// ResolveReferences resolves references made to other managed resources
func (r *APIReferenceResolver) ResolveReferences(ctx context.Context, res CanReference) error {
func (r *APIReferenceResolver) ResolveReferences(ctx context.Context, res resource.CanReference) error {
// Retrieve all the referencer fields from the managed resource.
referencers := r.finder.FindReferencers(res)

Expand All @@ -180,7 +128,7 @@ func (r *APIReferenceResolver) ResolveReferences(ctx context.Context, res CanRef
}

// Make sure that all the references are ready.
allStatuses := []ReferenceStatus{}
allStatuses := []resource.ReferenceStatus{}
for _, referencer := range referencers {
statuses, err := referencer.GetStatus(ctx, res, r.client)
if err != nil {
Expand Down Expand Up @@ -221,18 +169,18 @@ func (r *APIReferenceResolver) ResolveReferences(ctx context.Context, res CanRef
// AttributeReferencer. It assesses only pointers, structs, and slices because
// it is assumed that only struct fields or slice elements that are pointers to
// a struct will satisfy AttributeReferencer.
func findReferencers(obj interface{}) []AttributeReferencer { // nolint:gocyclo
func findReferencers(obj interface{}) []resource.AttributeReferencer { // nolint:gocyclo
// NOTE(negz): This function is slightly over our complexity goal, but is
// easier to follow as a single function.

referencers := []AttributeReferencer{}
referencers := []resource.AttributeReferencer{}

switch v := reflect.ValueOf(obj); v.Kind() {
case reflect.Ptr:
if v.IsNil() || !v.CanInterface() {
return nil
}
if ar, ok := v.Interface().(AttributeReferencer); ok {
if ar, ok := v.Interface().(resource.AttributeReferencer); ok {
referencers = append(referencers, ar)
}
if v.Elem().CanInterface() {
Expand Down
Loading

0 comments on commit cd8c52b

Please sign in to comment.