diff --git a/pkg/rules/rules.go b/pkg/rules/rules.go index aed1b960..c9923218 100644 --- a/pkg/rules/rules.go +++ b/pkg/rules/rules.go @@ -9,6 +9,7 @@ import ( "path/filepath" "sort" "sync" + "sync/atomic" "github.com/open-policy-agent/opa/ast" "github.com/open-policy-agent/opa/loader" @@ -51,11 +52,52 @@ func NewInput(fileContent map[string]string, modules map[string]*ast.Module) Inp filenames := util.Keys(modules) sort.Strings(filenames) - return Input{ + i := Input{ FileContent: fileContent, FileNames: filenames, Modules: modules, } + + if vi := virtualInput.Load(); vi != nil { + return i.Merge(*vi) + } + + return i +} + +func (i Input) Merge(o Input) Input { + for _, name := range o.FileNames { + i.FileContent[name] = o.FileContent[name] + i.Modules[name] = o.Modules[name] + i.FileNames = append(i.FileNames, name) + } + + return i +} + +var virtualInput atomic.Pointer[Input] //nolint:gochecknoglobals + +func SetVirtualInput(fsys fs.FS) error { + paths := []string{} + + if err := fs.WalkDir(fsys, ".", func(p string, _ fs.DirEntry, _ error) error { + if filepath.Ext(p) == ".rego" { + paths = append(paths, filepath.Join("/", p)) + } + + return nil + }); err != nil { + return fmt.Errorf("walking fs.FS: %w", err) + } + + in, err := inputFromPathsFS(fsys, paths) + if err != nil { + return fmt.Errorf("read input from fs.FS: %w", err) + } + + virtualInput.Store(&in) + + return nil } // InputFromPaths creates a new Input from a set of file or directory paths. Note that this function assumes that the