Skip to content

Commit 0781cc8

Browse files
committed
Exclude fn-config from owning function's input in fn render
Signed-off-by: Aravindhan Ayyanathan <aravindhan.a@est.tech>
1 parent 4b88f62 commit 0781cc8

9 files changed

Lines changed: 405 additions & 62 deletions

File tree

api/kptfile/v1/types.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,9 @@ type Function struct {
338338
Exec string `yaml:"exec,omitempty" json:"exec,omitempty"`
339339

340340
// `ConfigPath` specifies a slash-delimited relative path to a file in the current directory
341-
// containing a KRM resource used as the function config. This resource is
342-
// excluded when resolving 'sources', and as a result cannot be operated on
343-
// by the pipeline.
341+
// containing a KRM resource used as the function config. The function will
342+
// not see this resource in its input items — it is passed as configuration
343+
// only. Other functions in the pipeline can still see and modify the file.
344344
ConfigPath string `yaml:"configPath,omitempty" json:"configPath,omitempty"`
345345

346346
// `ConfigMap` is a convenient way to specify a function config of kind ConfigMap.

documentation/content/en/book/04-using-functions/_index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,8 @@ The `functionConfig` field is an optional meta resource containing the arguments
281281

282282
The general way to provide a `functionConfig` of the arbitrary kind (core or custom resources) is to declare the resource in a separate file, in the same directory as the `Kptfile`, and refer to it using the `configPath` field.
283283

284+
A function will not modify its own `configPath` resource. The resource is passed to the function as configuration only — it will not appear as one of the input resources that the function acts upon. Other functions in the pipeline can still see and modify the file.
285+
284286
For example:
285287

286288
```yaml

e2e/testdata/fn-render/fnconfig-ancestorfn-not-mutate-subpkg-config/.expected/diff.patch

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
diff --git a/Kptfile b/Kptfile
2-
index 8d8916e..67d2002 100644
2+
index 8d8916e..af76fa0 100644
33
--- a/Kptfile
44
+++ b/Kptfile
55
@@ -7,3 +7,22 @@ pipeline:
@@ -16,7 +16,7 @@ index 8d8916e..67d2002 100644
1616
+ - image: ghcr.io/kptdev/krm-functions-catalog/set-labels:latest
1717
+ exitCode: 0
1818
+ results:
19-
+ - message: set 4 labels in total
19+
+ - message: set 3 labels in total
2020
+ severity: info
2121
+ - image: ghcr.io/kptdev/krm-functions-catalog/set-namespace:latest
2222
+ exitCode: 0
@@ -39,15 +39,13 @@ index f4f3c67..456cee5 100644
3939
mutators:
4040
- image: ghcr.io/kptdev/krm-functions-catalog/set-labels:latest
4141
diff --git a/db/labelconfig.yaml b/db/labelconfig.yaml
42-
index 22d2de2..f4d597f 100644
42+
index 22d2de2..3c63796 100644
4343
--- a/db/labelconfig.yaml
4444
+++ b/db/labelconfig.yaml
45-
@@ -15,5 +15,8 @@ apiVersion: v1
45+
@@ -15,5 +15,6 @@ apiVersion: v1
4646
kind: ConfigMap
4747
metadata:
4848
name: label-config
49-
+ labels:
50-
+ tier: db
5149
+ namespace: staging
5250
data:
5351
tier: db

e2e/testdata/fn-render/fnconfig-in-subdir/.expected/diff.patch

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
diff --git a/Kptfile b/Kptfile
2-
index f244e01..9f79949 100644
2+
index f244e01..7de4df7 100644
33
--- a/Kptfile
44
+++ b/Kptfile
55
@@ -2,7 +2,21 @@ apiVersion: kpt.dev/v1
@@ -22,20 +22,8 @@ index f244e01..9f79949 100644
2222
+ - image: ghcr.io/kptdev/krm-functions-catalog/set-labels:latest
2323
+ exitCode: 0
2424
+ results:
25-
+ - message: set 5 labels in total
25+
+ - message: set 4 labels in total
2626
+ severity: info
27-
diff --git a/db/labelconfig.yaml b/db/labelconfig.yaml
28-
index 22d2de2..19e0746 100644
29-
--- a/db/labelconfig.yaml
30-
+++ b/db/labelconfig.yaml
31-
@@ -15,5 +15,7 @@ apiVersion: v1
32-
kind: ConfigMap
33-
metadata:
34-
name: label-config
35-
+ labels:
36-
+ tier: db
37-
data:
38-
tier: db
3927
diff --git a/resources.yaml b/resources.yaml
4028
index f2eec52..8ea86f0 100644
4129
--- a/resources.yaml

e2e/testdata/fn-render/fnconfig-pkgfn-refers-subdir/.expected/diff.patch

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
diff --git a/Kptfile b/Kptfile
2-
index 34f24da..f5bcf7c 100644
2+
index 34f24da..ba374a1 100644
33
--- a/Kptfile
44
+++ b/Kptfile
55
@@ -2,7 +2,21 @@ apiVersion: kpt.dev/v1
@@ -22,20 +22,8 @@ index 34f24da..f5bcf7c 100644
2222
+ - image: ghcr.io/kptdev/krm-functions-catalog/set-labels:latest
2323
+ exitCode: 0
2424
+ results:
25-
+ - message: set 5 labels in total
25+
+ - message: set 4 labels in total
2626
+ severity: info
27-
diff --git a/confs/labelconfig.yaml b/confs/labelconfig.yaml
28-
index 22d2de2..19e0746 100644
29-
--- a/confs/labelconfig.yaml
30-
+++ b/confs/labelconfig.yaml
31-
@@ -15,5 +15,7 @@ apiVersion: v1
32-
kind: ConfigMap
33-
metadata:
34-
name: label-config
35-
+ labels:
36-
+ tier: db
37-
data:
38-
tier: db
3927
diff --git a/resources.yaml b/resources.yaml
4028
index f2eec52..8ea86f0 100644
4129
--- a/resources.yaml

e2e/testdata/fn-render/fnconfig/.expected/diff.patch

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
diff --git a/Kptfile b/Kptfile
2-
index cd1b1e5..a14e2ce 100644
2+
index cd1b1e5..fa0fdfa 100644
33
--- a/Kptfile
44
+++ b/Kptfile
55
@@ -2,6 +2,8 @@ apiVersion: kpt.dev/v1
@@ -44,7 +44,7 @@ index cd1b1e5..a14e2ce 100644
4444
+ - image: ghcr.io/kptdev/krm-functions-catalog/set-labels:latest
4545
+ exitCode: 0
4646
+ results:
47-
+ - message: set 8 labels in total
47+
+ - message: set 7 labels in total
4848
+ severity: info
4949
diff --git a/db/Kptfile b/db/Kptfile
5050
index a0e6f2d..5e0e30a 100644
@@ -79,16 +79,14 @@ index dabe43c..25f77c1 100644
7979
+ app: backend
8080
+ tier: db
8181
diff --git a/labelconfig.yaml b/labelconfig.yaml
82-
index 22d2de2..8712cbf 100644
82+
index 22d2de2..3c63796 100644
8383
--- a/labelconfig.yaml
8484
+++ b/labelconfig.yaml
85-
@@ -15,5 +15,8 @@ apiVersion: v1
85+
@@ -15,5 +15,6 @@ apiVersion: v1
8686
kind: ConfigMap
8787
metadata:
8888
name: label-config
8989
+ namespace: staging
90-
+ labels:
91-
+ tier: db
9290
data:
9391
tier: db
9492
diff --git a/resources.yaml b/resources.yaml

e2e/testdata/fn-render/modify-path-annotation/.expected/diff.patch

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,3 @@ diff --git a/deployment.yaml b/newfilename.yaml
2323
similarity index 100%
2424
rename from deployment.yaml
2525
rename to newfilename.yaml
26-
diff --git a/starlark-fn.yaml b/starlark-fn.yaml
27-
index 247c2ae..0ef906e 100644
28-
--- a/starlark-fn.yaml
29-
+++ b/starlark-fn.yaml
30-
@@ -11,7 +11,6 @@
31-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
32-
# See the License for the specific language governing permissions and
33-
# limitations under the License.
34-
-
35-
apiVersion: fn.kpt.dev/v1alpha1
36-
kind: StarlarkRun
37-
metadata:

pkg/lib/kptops/render_executor.go

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -765,11 +765,13 @@ func (pn *pkgNode) runMutators(ctx context.Context, hctx *hydrationContext, inpu
765765
for i, mutator := range mutators {
766766
resultCountBeforeExec := len(hctx.fnResults.Items)
767767

768+
// Identify the fn-config resource for the current mutator.
769+
// If found, refresh the FunctionRunner's config reference (it may
770+
// have been mutated by a preceding function) and exclude it from
771+
// the function's input items. A function should only receive its
772+
// config via resourceList.functionConfig, not in resourceList.items.
773+
var fnConfigNode *yaml.RNode
768774
if pl.Mutators[i].ConfigPath != "" {
769-
// functionConfigs are included in the function inputs during `render`
770-
// and as a result, they can be mutated during the `render`.
771-
// So functionConfigs needs be updated in the FunctionRunner instance
772-
// before every run.
773775
for _, r := range input {
774776
pkgPath, err := pkg.GetPkgPathAnnotation(r)
775777
if err != nil {
@@ -779,14 +781,23 @@ func (pn *pkgNode) runMutators(ctx context.Context, hctx *hydrationContext, inpu
779781
if err != nil {
780782
return nil, err
781783
}
782-
if pkgPath == pn.pkg.UniquePath.String() && // resource belong to current package
784+
if pkgPath == pn.pkg.UniquePath.String() && // resource belongs to current package
783785
currPath == pl.Mutators[i].ConfigPath { // configPath matches
784786
mutator.SetFnConfig(r)
785-
continue
787+
fnConfigNode = r
788+
break
786789
}
787790
}
788791
}
789792

793+
// Remove fn-config from input before passing to the function.
794+
// We'll add it back unmodified after execution.
795+
if fnConfigNode != nil {
796+
input = slices.DeleteFunc(input, func(node *yaml.RNode) bool {
797+
return node == fnConfigNode
798+
})
799+
}
800+
790801
selectors := pl.Mutators[i].Selectors
791802
exclusions := pl.Mutators[i].Exclusions
792803

@@ -813,6 +824,9 @@ func (pn *pkgNode) runMutators(ctx context.Context, hctx *hydrationContext, inpu
813824
}
814825
err = mutation.Execute()
815826
if err != nil {
827+
if fnConfigNode != nil {
828+
input = append(input, fnConfigNode)
829+
}
816830
clearAnnotationsOnMutFailure(input)
817831
hctx.mutationSteps = append(hctx.mutationSteps, captureStepResult(pl.Mutators[i], hctx.fnResults, resultCountBeforeExec, err))
818832
return input, err
@@ -831,6 +845,12 @@ func (pn *pkgNode) runMutators(ctx context.Context, hctx *hydrationContext, inpu
831845
} else {
832846
input = output.Nodes
833847
}
848+
849+
// Add fn-config back unmodified so it remains in the resource list
850+
// for subsequent functions and is not pruned from disk.
851+
if fnConfigNode != nil {
852+
input = append(input, fnConfigNode)
853+
}
834854
}
835855
return input, nil
836856
}
@@ -852,9 +872,33 @@ func (pn *pkgNode) runValidators(ctx context.Context, hctx *hydrationContext, in
852872
for i := range pl.Validators {
853873
function := pl.Validators[i]
854874
resultCountBeforeExec := len(hctx.fnResults.Items)
875+
876+
// Exclude the validator's own fn-config from its input items.
877+
validatorInput := input
878+
if function.ConfigPath != "" {
879+
for _, r := range input {
880+
pkgPath, err := pkg.GetPkgPathAnnotation(r)
881+
if err != nil {
882+
return err
883+
}
884+
currPath, _, err := kioutil.GetFileAnnotations(r)
885+
if err != nil {
886+
return err
887+
}
888+
if pkgPath == pn.pkg.UniquePath.String() &&
889+
currPath == function.ConfigPath {
890+
// Create a filtered copy without the fn-config
891+
validatorInput = slices.DeleteFunc(slices.Clone(input), func(node *yaml.RNode) bool {
892+
return node == r
893+
})
894+
break
895+
}
896+
}
897+
}
898+
855899
// validators are run on a copy of mutated resources to ensure
856900
// resources are not mutated.
857-
selectedResources, err := fnruntime.SelectInput(input, function.Selectors, function.Exclusions, &fnruntime.SelectionContext{RootPackagePath: hctx.root.pkg.UniquePath})
901+
selectedResources, err := fnruntime.SelectInput(validatorInput, function.Selectors, function.Exclusions, &fnruntime.SelectionContext{RootPackagePath: hctx.root.pkg.UniquePath})
858902
if err != nil {
859903
return err
860904
}

0 commit comments

Comments
 (0)