Support for having circular dependencies while using referencers
Signed-off-by: Sergen Yalçın <yalcinsergen97@gmail.com>
This commit is contained in:
parent
988c9ba9c2
commit
ac7cf2045e
|
@ -77,10 +77,27 @@ type SecretKeySelector struct {
|
|||
Key string `json:"key"`
|
||||
}
|
||||
|
||||
// A ReferenceResolutionPolicy is a value for resolution policy for reference.
|
||||
type ReferenceResolutionPolicy string
|
||||
|
||||
const (
|
||||
// ReferencePolicyOptional is a resolution option.
|
||||
// When the ReferenceResolutionPolicy is set to ReferencePolicyOptional the
|
||||
// execution could continue even if the reference cannot be resolved.
|
||||
ReferencePolicyOptional ReferenceResolutionPolicy = "Optional"
|
||||
)
|
||||
|
||||
// A Reference to a named object.
|
||||
type Reference struct {
|
||||
// Name of the referenced object.
|
||||
Name string `json:"name"`
|
||||
// Policy of the referenced object.
|
||||
Policy ReferenceResolutionPolicy `json:"policy,omitempty"`
|
||||
}
|
||||
|
||||
// IsReferenceResolutionPolicyOptional checks whether the resolution policy of relevant reference is Optional.
|
||||
func (in *Reference) IsReferenceResolutionPolicyOptional() bool {
|
||||
return in.Policy == ReferencePolicyOptional
|
||||
}
|
||||
|
||||
// A TypedReference refers to an object by Name, Kind, and APIVersion. It is
|
||||
|
|
|
@ -182,9 +182,9 @@ func (rr MultiResolutionResponse) Validate() error {
|
|||
return errors.New(errNoMatches)
|
||||
}
|
||||
|
||||
for _, v := range rr.ResolvedValues {
|
||||
for i, v := range rr.ResolvedValues {
|
||||
if v == "" {
|
||||
return errors.New(errNoValue)
|
||||
return getReferenceError(&rr.ResolvedReferences[i], errors.New(errNoValue))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,11 +216,11 @@ func (r *APIResolver) Resolve(ctx context.Context, req ResolutionRequest) (Resol
|
|||
// The reference is already set - resolve it.
|
||||
if req.Reference != nil {
|
||||
if err := r.client.Get(ctx, types.NamespacedName{Name: req.Reference.Name}, req.To.Managed); err != nil {
|
||||
return ResolutionResponse{}, errors.Wrap(err, errGetManaged)
|
||||
return ResolutionResponse{}, getReferenceError(req.Reference, errors.Wrap(err, errGetManaged))
|
||||
}
|
||||
|
||||
rsp := ResolutionResponse{ResolvedValue: req.Extract(req.To.Managed), ResolvedReference: req.Reference}
|
||||
return rsp, rsp.Validate()
|
||||
return rsp, getReferenceError(req.Reference, rsp.Validate())
|
||||
}
|
||||
|
||||
// The reference was not set, but a selector was. Select a reference.
|
||||
|
@ -255,7 +255,7 @@ func (r *APIResolver) ResolveMultiple(ctx context.Context, req MultiResolutionRe
|
|||
vals := make([]string, len(req.References))
|
||||
for i := range req.References {
|
||||
if err := r.client.Get(ctx, types.NamespacedName{Name: req.References[i].Name}, req.To.Managed); err != nil {
|
||||
return MultiResolutionResponse{}, errors.Wrap(err, errGetManaged)
|
||||
return MultiResolutionResponse{}, getReferenceError(&req.References[i], errors.Wrap(err, errGetManaged))
|
||||
}
|
||||
vals[i] = req.Extract(req.To.Managed)
|
||||
}
|
||||
|
@ -285,6 +285,13 @@ func (r *APIResolver) ResolveMultiple(ctx context.Context, req MultiResolutionRe
|
|||
return rsp, rsp.Validate()
|
||||
}
|
||||
|
||||
func getReferenceError(ref *xpv1.Reference, err error) error {
|
||||
if !ref.IsReferenceResolutionPolicyOptional() {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ControllersMustMatch returns true if the supplied Selector requires that a
|
||||
// reference be to a managed resource whose controller reference matches the
|
||||
// referencing resource.
|
||||
|
|
|
@ -91,6 +91,7 @@ func TestResolve(t *testing.T) {
|
|||
now := metav1.Now()
|
||||
value := "coolv"
|
||||
ref := &xpv1.Reference{Name: "cool"}
|
||||
optionalRef := &xpv1.Reference{Name: "cool", Policy: xpv1.ReferencePolicyOptional}
|
||||
|
||||
controlled := &fake.Managed{}
|
||||
controlled.SetName(value)
|
||||
|
@ -204,6 +205,26 @@ func TestResolve(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
"OptionalPolicy": {
|
||||
reason: "No error should be returned when the resolution policy is Optional",
|
||||
c: &test.MockClient{
|
||||
MockGet: test.NewMockGetFn(nil),
|
||||
},
|
||||
from: &fake.Managed{},
|
||||
args: args{
|
||||
req: ResolutionRequest{
|
||||
Reference: optionalRef,
|
||||
To: To{Managed: &fake.Managed{}},
|
||||
Extract: func(resource.Managed) string { return "" },
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
rsp: ResolutionResponse{
|
||||
ResolvedReference: optionalRef,
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
},
|
||||
"ListError": {
|
||||
reason: "Should return errors encountered while listing potential referenced resources",
|
||||
c: &test.MockClient{
|
||||
|
@ -282,6 +303,7 @@ func TestResolveMultiple(t *testing.T) {
|
|||
now := metav1.Now()
|
||||
value := "coolv"
|
||||
ref := xpv1.Reference{Name: "cool"}
|
||||
optionalRef := xpv1.Reference{Name: "cool", Policy: xpv1.ReferencePolicyOptional}
|
||||
|
||||
controlled := &fake.Managed{}
|
||||
controlled.SetName(value)
|
||||
|
@ -396,6 +418,27 @@ func TestResolveMultiple(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
"OptionalPolicy": {
|
||||
reason: "No error should be returned when the resolution policy is Optional",
|
||||
c: &test.MockClient{
|
||||
MockGet: test.NewMockGetFn(nil),
|
||||
},
|
||||
from: &fake.Managed{},
|
||||
args: args{
|
||||
req: MultiResolutionRequest{
|
||||
References: []xpv1.Reference{optionalRef},
|
||||
To: To{Managed: &fake.Managed{}},
|
||||
Extract: func(resource.Managed) string { return "" },
|
||||
},
|
||||
},
|
||||
want: want{
|
||||
rsp: MultiResolutionResponse{
|
||||
ResolvedValues: []string{""},
|
||||
ResolvedReferences: []xpv1.Reference{optionalRef},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
},
|
||||
"ListError": {
|
||||
reason: "Should return errors encountered while listing potential referenced resources",
|
||||
c: &test.MockClient{
|
||||
|
|
Loading…
Reference in New Issue