Skip to content
This repository has been archived by the owner on Jun 8, 2022. It is now read-only.

Commit

Permalink
add an unsatisfied reason into dependency status and tests
Browse files Browse the repository at this point in the history
Signed-off-by: 天元 <jianbo.sjb@alibaba-inc.com>
  • Loading branch information
wonderflow committed Sep 28, 2020
1 parent 50605a9 commit 14f1c2a
Show file tree
Hide file tree
Showing 7 changed files with 326 additions and 50 deletions.
13 changes: 9 additions & 4 deletions apis/core/v1alpha2/core_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -416,8 +416,9 @@ type DependencyStatus struct {
// UnstaifiedDependency describes unsatisfied dependency flow between
// one pair of objects.
type UnstaifiedDependency struct {
From DependencyFromObject `json:"from"`
To DependencyToObject `json:"to"`
Reason string `json:"reason"`
From DependencyFromObject `json:"from"`
To DependencyToObject `json:"to"`
}

// DependencyFromObject represents the object that dependency data comes from.
Expand Down Expand Up @@ -490,16 +491,20 @@ type ConditionRequirement struct {
Operator ConditionOperator `json:"op"`

// +optional
// Value is mutually exclusive with ValueFrom
// Value specifies an expected value
// This is mutually exclusive with ValueFrom
Value string `json:"value,omitempty"`
// +optional
// ValueFrom specifies expected value from AppConfig
// This is mutually exclusive with Value
ValueFrom ValueFrom `json:"valueFrom,omitempty"`

// +optional
// FieldPath specifies got value from workload/trait object
FieldPath string `json:"fieldPath,omitempty"`
}

// ValueFrom get value from AppConfig object by specify a path
// ValueFrom gets value from AppConfig object by specifying a path
type ValueFrom struct {
FieldPath string `json:"fieldPath"`
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,16 +101,21 @@ spec:
to match a value.
properties:
fieldPath:
description: FieldPath specifies got value from
workload/trait object
type: string
op:
description: ConditionOperator specifies the operator
to match a value.
type: string
value:
description: Value is mutually exclusive with ValueFrom
description: Value specifies an expected value This
is mutually exclusive with ValueFrom
type: string
valueFrom:
description: This is mutually exclusive with Value
description: ValueFrom specifies expected value
from AppConfig This is mutually exclusive with
Value
properties:
fieldPath:
type: string
Expand Down Expand Up @@ -241,18 +246,21 @@ spec:
requirement to match a value.
properties:
fieldPath:
description: FieldPath specifies got value
from workload/trait object
type: string
op:
description: ConditionOperator specifies the
operator to match a value.
type: string
value:
description: Value is mutually exclusive with
ValueFrom
description: Value specifies an expected value
This is mutually exclusive with ValueFrom
type: string
valueFrom:
description: This is mutually exclusive with
Value
description: ValueFrom specifies expected
value from AppConfig This is mutually exclusive
with Value
properties:
fieldPath:
type: string
Expand Down Expand Up @@ -356,6 +364,8 @@ spec:
- kind
- name
type: object
reason:
type: string
to:
description: DependencyToObject represents the object that
dependency data goes to.
Expand Down Expand Up @@ -383,6 +393,7 @@ spec:
type: object
required:
- from
- reason
- to
type: object
type: array
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -924,6 +924,7 @@ func TestDependency(t *testing.T) {
},
depStatus: &v1alpha2.DependencyStatus{
Unsatisfied: []v1alpha2.UnstaifiedDependency{{
Reason: "status.key not found in object",
From: v1alpha2.DependencyFromObject{
TypedReference: runtimev1alpha1.TypedReference{
APIVersion: unreadyWorkload.GetAPIVersion(),
Expand Down Expand Up @@ -1006,6 +1007,7 @@ func TestDependency(t *testing.T) {
},
depStatus: &v1alpha2.DependencyStatus{
Unsatisfied: []v1alpha2.UnstaifiedDependency{{
Reason: "status.key not found in object",
From: v1alpha2.DependencyFromObject{
TypedReference: runtimev1alpha1.TypedReference{
APIVersion: unreadyTrait.GetAPIVersion(),
Expand Down Expand Up @@ -1091,6 +1093,7 @@ func TestDependency(t *testing.T) {
},
depStatus: &v1alpha2.DependencyStatus{
Unsatisfied: []v1alpha2.UnstaifiedDependency{{
Reason: "status.key not found in object",
From: v1alpha2.DependencyFromObject{
TypedReference: runtimev1alpha1.TypedReference{
APIVersion: unreadyWorkload.GetAPIVersion(),
Expand Down Expand Up @@ -1178,6 +1181,7 @@ func TestDependency(t *testing.T) {
},
depStatus: &v1alpha2.DependencyStatus{
Unsatisfied: []v1alpha2.UnstaifiedDependency{{
Reason: "status.key not found in object",
From: v1alpha2.DependencyFromObject{
TypedReference: runtimev1alpha1.TypedReference{
APIVersion: unreadyTrait.GetAPIVersion(),
Expand Down
52 changes: 28 additions & 24 deletions pkg/controller/v1alpha2/applicationconfiguration/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -410,8 +410,9 @@ func (r *components) handleDependency(ctx context.Context, w *Workload, acc v1al
return uds, nil
}

func makeUnsatisfiedDependency(obj *unstructured.Unstructured, s *dagSource, in v1alpha2.DataInput) v1alpha2.UnstaifiedDependency {
func makeUnsatisfiedDependency(obj *unstructured.Unstructured, s *dagSource, in v1alpha2.DataInput, reason string) v1alpha2.UnstaifiedDependency {
return v1alpha2.UnstaifiedDependency{
Reason: reason,
From: v1alpha2.DependencyFromObject{
TypedReference: runtimev1alpha1.TypedReference{
APIVersion: s.ObjectRef.APIVersion,
Expand All @@ -438,12 +439,12 @@ func (r *components) handleDataInput(ctx context.Context, ins []v1alpha2.DataInp
if !ok {
return nil, errors.Wrapf(ErrDataOutputNotExist, "DataOutputName (%s)", in.ValueFrom.DataOutputName)
}
val, ready, err := r.getDataInput(ctx, s, ac)
val, ready, reason, err := r.getDataInput(ctx, s, ac)
if err != nil {
return nil, errors.Wrap(err, "getDataInput failed")
}
if !ready {
uds = append(uds, makeUnsatisfiedDependency(obj, s, in))
uds = append(uds, makeUnsatisfiedDependency(obj, s, in, reason))
return uds, nil
}

Expand Down Expand Up @@ -483,7 +484,7 @@ func fillValue(obj *unstructured.Unstructured, fs []string, val interface{}) err
return nil
}

func (r *components) getDataInput(ctx context.Context, s *dagSource, ac *unstructured.Unstructured) (interface{}, bool, error) {
func (r *components) getDataInput(ctx context.Context, s *dagSource, ac *unstructured.Unstructured) (interface{}, bool, string, error) {
obj := s.ObjectRef
key := types.NamespacedName{
Namespace: obj.Namespace,
Expand All @@ -493,43 +494,46 @@ func (r *components) getDataInput(ctx context.Context, s *dagSource, ac *unstruc
u.SetGroupVersionKind(obj.GroupVersionKind())
err := r.client.Get(ctx, key, u)
if err != nil {
return nil, false, errors.Wrap(resource.IgnoreNotFound(err), fmt.Sprintf("failed to get object (%s)", key.String()))
reason := fmt.Sprintf("failed to get object (%s)", key.String())
return nil, false, reason, errors.Wrap(resource.IgnoreNotFound(err), reason)
}
paved := fieldpath.Pave(u.UnstructuredContent())
pavedAC := fieldpath.Pave(ac.UnstructuredContent())

rawval, err := paved.GetValue(obj.FieldPath)
if err != nil {
if fieldpath.IsNotFound(err) {
return "", false, nil
return "", false, fmt.Sprintf("%s not found in object", obj.FieldPath), nil
}
return nil, false, fmt.Errorf("failed to get field value (%s) in object (%s): %w", obj.FieldPath, key.String(), err)
err = fmt.Errorf("failed to get field value (%s) in object (%s): %w", obj.FieldPath, key.String(), err)
return nil, false, err.Error(), err
}

var ok bool
var reason string
switch val := rawval.(type) {
case string:
// For string input we will:
// - check its value not empty if no condition is given.
// - check its value against conditions if no field path is specified.
ok, err = matchValue(s.Conditions, val, paved, pavedAC)
ok, reason = matchValue(s.Conditions, val, paved, pavedAC)
default:
ok, err = checkConditions(s.Conditions, paved, nil, pavedAC)
}
if err != nil {
return nil, false, err
ok, reason = checkConditions(s.Conditions, paved, nil, pavedAC)
}
if !ok {
return nil, false, nil
return nil, false, reason, nil
}

return rawval, true, nil
return rawval, true, "", nil
}

func matchValue(conds []v1alpha2.ConditionRequirement, val string, paved, ac *fieldpath.Paved) (bool, error) {
func matchValue(conds []v1alpha2.ConditionRequirement, val string, paved, ac *fieldpath.Paved) (bool, string) {
// If no condition is specified, it is by default to check value not empty.
if len(conds) == 0 {
return val != "", nil
if val == "" {
return false, "value should not be empty"
}
return true, ""
}

return checkConditions(conds, paved, &val, ac)
Expand Down Expand Up @@ -558,38 +562,38 @@ func getExpectVal(m v1alpha2.ConditionRequirement, ac *fieldpath.Paved) (string,
var err error
value, err := ac.GetString(m.ValueFrom.FieldPath)
if err != nil {
return "", fmt.Errorf("get field path %s err %v", m.ValueFrom.FieldPath, err)
return "", fmt.Errorf("get valueFrom.fieldPath fail: %v", err)
}
return value, nil
}

func checkConditions(conds []v1alpha2.ConditionRequirement, paved *fieldpath.Paved, val *string, ac *fieldpath.Paved) (bool, error) {
func checkConditions(conds []v1alpha2.ConditionRequirement, paved *fieldpath.Paved, val *string, ac *fieldpath.Paved) (bool, string) {
for _, m := range conds {
checkVal, err := getCheckVal(m, paved, val)
if err != nil {
return false, err
return false, fmt.Sprintf("can't get value to check %v", err)
}
m.Value, err = getExpectVal(m, ac)
if err != nil {
return false, fmt.Errorf("get field path %s err %v", m.ValueFrom.FieldPath, err)
return false, err.Error()
}

switch m.Operator {
case v1alpha2.ConditionEqual:
if m.Value != checkVal {
return false, nil
return false, fmt.Sprintf("got(%v) expected to be %v", checkVal, m.Value)
}
case v1alpha2.ConditionNotEqual:
if m.Value == checkVal {
return false, nil
return false, fmt.Sprintf("got(%v) expected not to be %v", checkVal, m.Value)
}
case v1alpha2.ConditionNotEmpty:
if checkVal == "" {
return false, nil
return false, "value should not be empty"
}
}
}
return true, nil
return true, ""
}

// GetTraitName return trait name
Expand Down
Loading

0 comments on commit 14f1c2a

Please sign in to comment.