diff --git a/fn.go b/fn.go index 6400124..1575ab6 100644 --- a/fn.go +++ b/fn.go @@ -5,6 +5,8 @@ import ( "context" "encoding/base64" "io" + "io/fs" + "os" "dario.cat/mergo" "google.golang.org/protobuf/encoding/protojson" @@ -25,11 +27,20 @@ import ( "github.com/crossplane-contrib/function-go-templating/input/v1beta1" ) +// osFS is a dead-simple implementation of [io/fs.FS] that just wraps around +// [os.Open]. +type osFS struct{} + +func (*osFS) Open(name string) (fs.File, error) { + return os.Open(name) +} + // Function uses Go templates to compose resources. type Function struct { fnv1beta1.UnimplementedFunctionRunnerServiceServer - log logging.Logger + log logging.Logger + fsys fs.FS } const ( @@ -51,7 +62,7 @@ func (f *Function) RunFunction(_ context.Context, req *fnv1beta1.RunFunctionRequ return rsp, nil } - tg, err := NewTemplateSourceGetter(in) + tg, err := NewTemplateSourceGetter(f.fsys, in) if err != nil { response.Fatal(rsp, errors.Wrap(err, "invalid function input")) return rsp, nil diff --git a/fn_test.go b/fn_test.go index de13b12..6d69d0d 100644 --- a/fn_test.go +++ b/fn_test.go @@ -2,6 +2,7 @@ package main import ( "context" + "embed" "fmt" "testing" @@ -38,6 +39,9 @@ var ( path = "testdata/templates" wrongPath = "testdata/wrong" + + //go:embed testdata + testdataFS embed.FS ) func TestRunFunction(t *testing.T) { @@ -425,7 +429,7 @@ func TestRunFunction(t *testing.T) { Results: []*fnv1beta1.Result{ { Severity: fnv1beta1.Severity_SEVERITY_FATAL, - Message: "invalid function input: cannot read tmpl from the folder {testdata/wrong}: lstat testdata/wrong: no such file or directory", + Message: "invalid function input: cannot read tmpl from the folder {testdata/wrong}: open testdata/wrong: file does not exist", }, }, }, @@ -587,7 +591,10 @@ func TestRunFunction(t *testing.T) { for name, tc := range cases { t.Run(name, func(t *testing.T) { - f := &Function{log: logging.NewNopLogger()} + f := &Function{ + log: logging.NewNopLogger(), + fsys: testdataFS, + } rsp, err := f.RunFunction(tc.args.ctx, tc.args.req) if diff := cmp.Diff(tc.want.rsp, rsp, protocmp.Transform()); diff != "" { diff --git a/go.mod b/go.mod index c7fba8e..5e0607e 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,6 @@ require ( github.com/google/go-cmp v0.6.0 google.golang.org/protobuf v1.31.0 gopkg.in/yaml.v3 v3.0.1 - k8s.io/api v0.28.4 k8s.io/apimachinery v0.28.4 sigs.k8s.io/controller-tools v0.13.0 ) @@ -73,6 +72,7 @@ require ( google.golang.org/grpc v1.59.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + k8s.io/api v0.28.4 // indirect k8s.io/apiextensions-apiserver v0.28.3 // indirect k8s.io/client-go v0.28.3 // indirect k8s.io/klog/v2 v2.100.1 // indirect diff --git a/go.sum b/go.sum index f59cca2..0965f5f 100644 --- a/go.sum +++ b/go.sum @@ -75,8 +75,6 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/crossplane/crossplane-runtime v1.14.2 h1:pV5JMzyzi/kcbeVBVPCat5MHH8zS94MBUapAyGx/Ry0= -github.com/crossplane/crossplane-runtime v1.14.2/go.mod h1:aOP+5W2wKpvthVs3pFNbVOe1jwrKYbJho0ThGNCVz9o= github.com/crossplane/crossplane-runtime v1.14.3 h1:YNGALph/UJTtQO+cJ9KGQ5NfALI5453PeE93Aqy9SWg= github.com/crossplane/crossplane-runtime v1.14.3/go.mod h1:aOP+5W2wKpvthVs3pFNbVOe1jwrKYbJho0ThGNCVz9o= github.com/crossplane/function-sdk-go v0.1.0 h1:WN3CUSaj6wgDqQPZZP1whMVIkTAZtN3HVCS67pTMzd8= @@ -724,14 +722,10 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.28.3 h1:Gj1HtbSdB4P08C8rs9AR94MfSGpRhJgsS+GF9V26xMM= -k8s.io/api v0.28.3/go.mod h1:MRCV/jr1dW87/qJnZ57U5Pak65LGmQVkKTzf3AtKFHc= k8s.io/api v0.28.4 h1:8ZBrLjwosLl/NYgv1P7EQLqoO8MGQApnbgH8tu3BMzY= k8s.io/api v0.28.4/go.mod h1:axWTGrY88s/5YE+JSt4uUi6NMM+gur1en2REMR7IRj0= k8s.io/apiextensions-apiserver v0.28.3 h1:Od7DEnhXHnHPZG+W9I97/fSQkVpVPQx2diy+2EtmY08= k8s.io/apiextensions-apiserver v0.28.3/go.mod h1:NE1XJZ4On0hS11aWWJUTNkmVB03j9LM7gJSisbRt8Lc= -k8s.io/apimachinery v0.28.3 h1:B1wYx8txOaCQG0HmYF6nbpU8dg6HvA06x5tEffvOe7A= -k8s.io/apimachinery v0.28.3/go.mod h1:uQTKmIqs+rAYaq+DFaoD2X7pcjLOqbQX2AOiO0nIpb8= k8s.io/apimachinery v0.28.4 h1:zOSJe1mc+GxuMnFzD4Z/U1wst50X28ZNsn5bhgIIao8= k8s.io/apimachinery v0.28.4/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg= k8s.io/client-go v0.28.3 h1:2OqNb72ZuTZPKCl+4gTKvqao0AMOl9f3o2ijbAj3LI4= diff --git a/main.go b/main.go index 88f0def..8939db0 100644 --- a/main.go +++ b/main.go @@ -24,7 +24,11 @@ func (c *CLI) Run() error { return err } - return function.Serve(&Function{log: log}, + return function.Serve( + &Function{ + log: log, + fsys: &osFS{}, + }, function.Listen(c.Network, c.Address), function.MTLSCertificates(c.TLSCertsDir), function.Insecure(c.Insecure)) diff --git a/template.go b/template.go index ccfa4c1..706e51b 100644 --- a/template.go +++ b/template.go @@ -1,7 +1,7 @@ package main import ( - "os" + "io/fs" "path/filepath" "github.com/crossplane/function-sdk-go/errors" @@ -18,12 +18,12 @@ type TemplateGetter interface { } // NewTemplateSourceGetter returns a TemplateGetter based on the cd source -func NewTemplateSourceGetter(in *v1beta1.GoTemplate) (TemplateGetter, error) { +func NewTemplateSourceGetter(fsys fs.FS, in *v1beta1.GoTemplate) (TemplateGetter, error) { switch in.Source { case v1beta1.InlineSource: return newInlineSource(in) case v1beta1.FileSystemSource: - return newFileSource(in) + return newFileSource(fsys, in) case "": return nil, errors.Errorf("source is required") default: @@ -62,14 +62,14 @@ func (fs *FileSource) GetTemplates() string { return fs.Template } -func newFileSource(in *v1beta1.GoTemplate) (*FileSource, error) { +func newFileSource(fsys fs.FS, in *v1beta1.GoTemplate) (*FileSource, error) { if in.FileSystem == nil || in.FileSystem.DirPath == "" { return nil, errors.New("fileSystem.dirPath should be provided") } d := in.FileSystem.DirPath - tmpl, err := readTemplates(d) + tmpl, err := readTemplates(fsys, d) if err != nil { return nil, errors.Errorf("cannot read tmpl from the folder %s: %s", *in.FileSystem, err) } @@ -80,10 +80,10 @@ func newFileSource(in *v1beta1.GoTemplate) (*FileSource, error) { }, nil } -func readTemplates(dir string) (string, error) { +func readTemplates(fsys fs.FS, dir string) (string, error) { tmpl := "" - if err := filepath.WalkDir(dir, func(path string, dirEntry os.DirEntry, e error) error { + if err := fs.WalkDir(fsys, dir, func(path string, dirEntry fs.DirEntry, e error) error { if e != nil { return e } @@ -103,7 +103,7 @@ func readTemplates(dir string) (string, error) { return nil } - data, err := os.ReadFile(path) + data, err := fs.ReadFile(fsys, path) if err != nil { return err }