Skip to content

Commit 0bc7f21

Browse files
authored
Merge pull request #96 from MisterMX/fix/env-patch-policy-fromfieldpath
fix(environment): Skip optional patches
2 parents 9112dd8 + 2758aa4 commit 0bc7f21

File tree

2 files changed

+142
-0
lines changed

2 files changed

+142
-0
lines changed

fn.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,12 @@ func (f *Function) RunFunction(ctx context.Context, req *fnv1beta1.RunFunctionRe
121121
for i := range input.Environment.Patches {
122122
p := &input.Environment.Patches[i]
123123
if err := ApplyEnvironmentPatch(p, env, oxr.Resource, dxr.Resource); err != nil {
124+
125+
// Ignore not found errors if patch policy is set to Optional
126+
if fieldpath.IsNotFound(err) && p.GetPolicy().GetFromFieldPathPolicy() == v1beta1.FromFieldPathPolicyOptional {
127+
continue
128+
}
129+
124130
response.Fatal(rsp, errors.Wrapf(err, "cannot apply the %q environment patch at index %d", p.GetType(), i))
125131
return rsp, nil
126132
}

fn_test.go

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -897,6 +897,142 @@ func TestRunFunction(t *testing.T) {
897897
Context: contextWithEnvironment(map[string]interface{}{
898898
"widgets": "30",
899899
})}}},
900+
"EnvironmentPatchOptionalNotFoundSkipped": {
901+
reason: "A basic ToEnvironment patch with optional or not field path policy should be skipped",
902+
args: args{
903+
req: &fnv1beta1.RunFunctionRequest{
904+
Input: resource.MustStructObject(&v1beta1.Resources{
905+
Resources: []v1beta1.ComposedTemplate{
906+
{
907+
Name: "cool-resource",
908+
Base: &runtime.RawExtension{Raw: []byte(`{"apiVersion":"example.org/v1","kind":"CD"}`)},
909+
}},
910+
Environment: &v1beta1.Environment{
911+
Patches: []v1beta1.EnvironmentPatch{
912+
{
913+
Type: v1beta1.PatchTypeFromCompositeFieldPath,
914+
Patch: v1beta1.Patch{
915+
FromFieldPath: ptr.To[string]("spec.watchers"),
916+
ToFieldPath: ptr.To[string]("widgets"),
917+
Transforms: []v1beta1.Transform{
918+
{
919+
Type: v1beta1.TransformTypeMath,
920+
Math: &v1beta1.MathTransform{
921+
Type: v1beta1.MathTransformTypeMultiply,
922+
Multiply: ptr.To[int64](3),
923+
},
924+
},
925+
{
926+
Type: v1beta1.TransformTypeConvert,
927+
Convert: &v1beta1.ConvertTransform{
928+
ToType: v1beta1.TransformIOTypeString,
929+
},
930+
}}},
931+
},
932+
{
933+
// This patch should be skipped, because
934+
// the path is not found
935+
Type: v1beta1.PatchTypeFromCompositeFieldPath,
936+
Patch: v1beta1.Patch{
937+
FromFieldPath: ptr.To[string]("spec.doesNotExist"),
938+
},
939+
},
940+
{
941+
// This patch should be skipped, because
942+
// the path is not found
943+
Type: v1beta1.PatchTypeFromCompositeFieldPath,
944+
Patch: v1beta1.Patch{
945+
FromFieldPath: ptr.To[string]("spec.doesNotExist"),
946+
Policy: &v1beta1.PatchPolicy{
947+
FromFieldPath: ptr.To(v1beta1.FromFieldPathPolicyOptional),
948+
},
949+
},
950+
}}}}),
951+
Observed: &fnv1beta1.State{
952+
Composite: &fnv1beta1.Resource{
953+
Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD","spec":{"watchers":10}}`),
954+
},
955+
Resources: map[string]*fnv1beta1.Resource{},
956+
},
957+
Context: contextWithEnvironment(nil),
958+
}},
959+
want: want{
960+
rsp: &fnv1beta1.RunFunctionResponse{
961+
Meta: &fnv1beta1.ResponseMeta{Ttl: durationpb.New(response.DefaultTTL)},
962+
Desired: &fnv1beta1.State{
963+
Composite: &fnv1beta1.Resource{
964+
Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD"}`),
965+
},
966+
Resources: map[string]*fnv1beta1.Resource{
967+
"cool-resource": {
968+
Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD"}`),
969+
}}},
970+
Context: contextWithEnvironment(map[string]interface{}{
971+
"widgets": "30",
972+
},
973+
)}}},
974+
"EnvironmentPatchRequiredNotFoundError": {
975+
reason: "A basic ToEnvironment patch with required field path policy should return an error",
976+
args: args{
977+
req: &fnv1beta1.RunFunctionRequest{
978+
Input: resource.MustStructObject(&v1beta1.Resources{
979+
Resources: []v1beta1.ComposedTemplate{
980+
{
981+
Name: "cool-resource",
982+
Base: &runtime.RawExtension{Raw: []byte(`{"apiVersion":"example.org/v1","kind":"CD"}`)},
983+
}},
984+
Environment: &v1beta1.Environment{
985+
Patches: []v1beta1.EnvironmentPatch{
986+
{
987+
Type: v1beta1.PatchTypeFromCompositeFieldPath,
988+
Patch: v1beta1.Patch{
989+
FromFieldPath: ptr.To[string]("spec.watchers"),
990+
ToFieldPath: ptr.To[string]("widgets"),
991+
Transforms: []v1beta1.Transform{
992+
{
993+
Type: v1beta1.TransformTypeMath,
994+
Math: &v1beta1.MathTransform{
995+
Type: v1beta1.MathTransformTypeMultiply,
996+
Multiply: ptr.To[int64](3),
997+
},
998+
},
999+
{
1000+
Type: v1beta1.TransformTypeConvert,
1001+
Convert: &v1beta1.ConvertTransform{
1002+
ToType: v1beta1.TransformIOTypeString,
1003+
},
1004+
}}},
1005+
},
1006+
{
1007+
// This patch should be skipped, because
1008+
// the path is not found
1009+
Type: v1beta1.PatchTypeFromCompositeFieldPath,
1010+
Patch: v1beta1.Patch{
1011+
FromFieldPath: ptr.To[string]("spec.doesNotExist"),
1012+
Policy: &v1beta1.PatchPolicy{
1013+
FromFieldPath: ptr.To(v1beta1.FromFieldPathPolicyRequired),
1014+
},
1015+
},
1016+
}}}}),
1017+
Observed: &fnv1beta1.State{
1018+
Composite: &fnv1beta1.Resource{
1019+
Resource: resource.MustStructJSON(`{"apiVersion":"example.org/v1","kind":"CD","spec":{"watchers":10}}`),
1020+
},
1021+
Resources: map[string]*fnv1beta1.Resource{},
1022+
},
1023+
Context: contextWithEnvironment(nil),
1024+
}},
1025+
want: want{
1026+
rsp: &fnv1beta1.RunFunctionResponse{
1027+
Meta: &fnv1beta1.ResponseMeta{Ttl: durationpb.New(response.DefaultTTL)},
1028+
Context: contextWithEnvironment(map[string]interface{}{}),
1029+
Results: []*fnv1beta1.Result{
1030+
{
1031+
Severity: fnv1beta1.Severity_SEVERITY_FATAL,
1032+
Message: `cannot apply the "FromCompositeFieldPath" environment patch at index 1: spec.doesNotExist: no such field`,
1033+
},
1034+
},
1035+
}}},
9001036
"PatchComposedResourceFromEnvironment": {
9011037
reason: "A basic FromEnvironmentPatch should work if defined at spec.resources[*].patches.",
9021038
args: args{

0 commit comments

Comments
 (0)