Skip to content

Commit 7cc5141

Browse files
authored
Make function to dump PackageRevisionResources a utility function (#966)
* Move function to dump PackageRevisionResources to disk to a utility function and make visible Signed-off-by: liamfallon <liam.fallon@est.tech> * Added documentation for hack Signed-off-by: liamfallon <liam.fallon@est.tech> * Generate unit tests and fix copilot comments Signed-off-by: liamfallon <liam.fallon@est.tech> * Address copilot comments Signed-off-by: liamfallon <liam.fallon@est.tech> --------- Signed-off-by: liamfallon <liam.fallon@est.tech>
1 parent 74d82d5 commit 7cc5141

4 files changed

Lines changed: 151 additions & 25 deletions

File tree

controllers/packagerevisions/pkg/controllers/packagerevision/render.go

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"context"
1919
"fmt"
2020
iofs "io/fs"
21-
"path"
2221
"strings"
2322

2423
fnresult "github.com/kptdev/kpt/pkg/api/fnresult/v1"
@@ -66,7 +65,7 @@ func newKptRenderer(runtime fn.FunctionRuntime, opts runneroptions.RunnerOptions
6665

6766
func (r *kptRenderer) Render(ctx context.Context, resources map[string]string) (*renderResult, error) {
6867
fs := filesys.MakeFsInMemory()
69-
pkgPath, err := writeResourcesToFS(fs, resources)
68+
pkgPath, err := repository.WriteResourcesToFS(fs, "", resources)
7069
if err != nil {
7170
return nil, fmt.Errorf("failed to write resources for render: %w", err)
7271
}
@@ -95,28 +94,6 @@ func (r *kptRenderer) Render(ctx context.Context, resources map[string]string) (
9594
}, nil
9695
}
9796

98-
func writeResourcesToFS(fs filesys.FileSystem, resources map[string]string) (string, error) {
99-
var packageDir string
100-
for k, v := range resources {
101-
dir := path.Dir(k)
102-
if dir == "." {
103-
dir = "/"
104-
}
105-
if err := fs.MkdirAll(dir); err != nil {
106-
return "", err
107-
}
108-
if err := fs.WriteFile(path.Join(dir, path.Base(k)), []byte(v)); err != nil {
109-
return "", err
110-
}
111-
if path.Base(k) == "Kptfile" {
112-
if packageDir == "" || dir == "/" || strings.HasPrefix(packageDir, dir+"/") {
113-
packageDir = dir
114-
}
115-
}
116-
}
117-
return packageDir, nil
118-
}
119-
12097
func readResourcesFromFS(fs filesys.FileSystem) (map[string]string, error) {
12198
contents := map[string]string{}
12299
if err := fs.Walk("/", func(p string, info iofs.FileInfo, err error) error {
@@ -150,7 +127,6 @@ func renderTrigger(pr *porchv1alpha2.PackageRevision) (requested string, annotat
150127
return
151128
}
152129

153-
154130
// isRenderStale returns true if the annotation changed during render.
155131
func isRenderStale(currentAnnotation, rendered string) bool {
156132
return currentAnnotation != rendered

docs/content/en/docs/9_troubleshooting_and_faq/lazy-dog/_index.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,41 @@ into your Starlark script, which will cause an error and trigger the output:
5252

5353
i = 10/0 # Deliberate division by zero error
5454
```
55+
56+
## Dumping resources to disk while debugging rendering in Porch
57+
58+
It can be difficult to see what is happening with `PackageRevisionResources` during rendering,
59+
especially if a mutation pipeline is buggy. During debugging of rendering in Porch it can be
60+
convenient to dump the resources to disk so that regular comparison tools can be used to
61+
spot inconsistencies.
62+
63+
For example, the code fragment below calls a render:
64+
65+
```go
66+
resources, _, err = th.renderMutation(draftMeta.GetNamespace()).apply(ctx, resources)
67+
if err != nil {
68+
klog.Error(err)
69+
return renderError(err)
70+
}
71+
```
72+
73+
You can temporarily add a call to the `WriteResourcesToFS()` function to dump the "before" and "after" resources to disk for comparison.
74+
75+
```go
76+
_, err = repository.WriteResourcesToFS(filesys.MakeFsOnDisk(), "/tmp/before", resources.Contents)
77+
if err != nil {
78+
klog.Error(err)
79+
return renderError(err)
80+
}
81+
82+
resources, _, err = th.renderMutation(draftMeta.GetNamespace()).apply(ctx, resources)
83+
if err != nil {
84+
klog.Error(err)
85+
return renderError(err)
86+
}
87+
_, err = repository.WriteResourcesToFS(filesys.MakeFsOnDisk(), "/tmp/after", resources.Contents)
88+
if err != nil {
89+
klog.Error(err)
90+
return renderError(err)
91+
}
92+
```

pkg/repository/util.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package repository
1717
import (
1818
"context"
1919
"fmt"
20+
"path"
2021
"strconv"
2122
"strings"
2223

@@ -26,6 +27,7 @@ import (
2627
"github.com/nephio-project/porch/pkg/util"
2728
pkgerrors "github.com/pkg/errors"
2829
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
30+
"sigs.k8s.io/kustomize/kyaml/filesys"
2931
)
3032

3133
func ToAPIReadinessGates(kf kptfilev1.KptFile) []porchapi.ReadinessGate {
@@ -209,3 +211,33 @@ func PackageRevisionIsPlaceholder(ctx context.Context, namespace string, referen
209211

210212
return false, nil
211213
}
214+
215+
func WriteResourcesToFS(fs filesys.FileSystem, rootDir string, resources map[string]string) (string, error) {
216+
if rootDir != "" {
217+
if err := fs.MkdirAll(rootDir); err != nil {
218+
return "", err
219+
}
220+
}
221+
222+
var packageDir string
223+
for k, v := range resources {
224+
dir := path.Dir(k)
225+
if dir == "." {
226+
dir = "/"
227+
}
228+
229+
fullDir := path.Join(rootDir, dir)
230+
if err := fs.MkdirAll(fullDir); err != nil {
231+
return "", err
232+
}
233+
if err := fs.WriteFile(path.Join(fullDir, path.Base(k)), []byte(v)); err != nil {
234+
return "", err
235+
}
236+
if path.Base(k) == "Kptfile" {
237+
if packageDir == "" || dir == "/" || strings.HasPrefix(packageDir, dir+"/") {
238+
packageDir = dir
239+
}
240+
}
241+
}
242+
return packageDir, nil
243+
}

pkg/repository/util_test.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
configapi "github.com/nephio-project/porch/api/porchconfig/v1alpha1"
2525
"github.com/stretchr/testify/assert"
2626
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27+
"sigs.k8s.io/kustomize/kyaml/filesys"
2728
)
2829

2930
func TestRevision2Int(t *testing.T) {
@@ -250,6 +251,85 @@ func TestValidatePackagePathOverlap(t *testing.T) {
250251
assert.NoError(t, ValidatePackagePathOverlap(newPr, []PackageRevision{differentRepoRev}))
251252
}
252253

254+
func TestWriteResourcesToFS(t *testing.T) {
255+
tests := []struct {
256+
name string
257+
rootDir string
258+
resources map[string]string
259+
wantPkgDir string
260+
wantFiles map[string]string
261+
}{
262+
{
263+
name: "empty resources",
264+
resources: map[string]string{},
265+
wantPkgDir: "",
266+
},
267+
{
268+
name: "single file at root",
269+
resources: map[string]string{"foo.yaml": "content"},
270+
wantPkgDir: "",
271+
wantFiles: map[string]string{"/foo.yaml": "content"},
272+
},
273+
{
274+
name: "Kptfile at root",
275+
resources: map[string]string{"Kptfile": "kpt-content"},
276+
wantPkgDir: "/",
277+
wantFiles: map[string]string{"/Kptfile": "kpt-content"},
278+
},
279+
{
280+
name: "nested file",
281+
resources: map[string]string{"sub/dir/file.yaml": "nested"},
282+
wantPkgDir: "",
283+
wantFiles: map[string]string{"/sub/dir/file.yaml": "nested"},
284+
},
285+
{
286+
name: "Kptfile in subdir",
287+
resources: map[string]string{"pkg/Kptfile": "kpt"},
288+
wantPkgDir: "pkg",
289+
wantFiles: map[string]string{"/pkg/Kptfile": "kpt"},
290+
},
291+
{
292+
name: "Kptfile at root takes precedence over nested",
293+
resources: map[string]string{
294+
"Kptfile": "root-kpt",
295+
"sub/Kptfile": "sub-kpt",
296+
"sub/file.yaml": "data",
297+
},
298+
wantPkgDir: "/",
299+
wantFiles: map[string]string{
300+
"/Kptfile": "root-kpt",
301+
"/sub/Kptfile": "sub-kpt",
302+
"/sub/file.yaml": "data",
303+
},
304+
},
305+
{
306+
name: "with rootDir",
307+
rootDir: "root",
308+
resources: map[string]string{"Kptfile": "kpt", "file.yaml": "data"},
309+
wantPkgDir: "/",
310+
wantFiles: map[string]string{
311+
"/root/Kptfile": "kpt",
312+
"/root/file.yaml": "data",
313+
},
314+
},
315+
}
316+
317+
for _, tt := range tests {
318+
t.Run(tt.name, func(t *testing.T) {
319+
fs := filesys.MakeFsInMemory()
320+
gotPkgDir, err := WriteResourcesToFS(fs, tt.rootDir, tt.resources)
321+
assert.NoError(t, err)
322+
assert.Equal(t, tt.wantPkgDir, gotPkgDir)
323+
324+
for path, wantContent := range tt.wantFiles {
325+
data, err := fs.ReadFile(path)
326+
assert.NoError(t, err, "reading %s", path)
327+
assert.Equal(t, wantContent, string(data))
328+
}
329+
})
330+
}
331+
}
332+
253333
type fakeReferenceResolver struct {
254334
repo *configapi.Repository
255335
err error

0 commit comments

Comments
 (0)