mirror of
https://github.com/open-policy-agent/opa.git
synced 2026-08-12 19:32:48 -06:00
e43ef0a979
Earlier this evening I tried to run the Go [modernize](https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/modernize) analyzer on OPA. That didn't go as planned: - https://github.com/golang/go/issues/73661 - https://github.com/golang/go/issues/73663 While we wait for that to be fixed, I figured an old-fashioned search-and-replace across the repo may work for at least the `interface{}` to `any` conversion. That should help make it easier to see the other fixes as applied by the modernize tool once it has had those issues resolved. Signed-off-by: Anders Eknert <anders@styra.com>
126 lines
3.3 KiB
Go
126 lines
3.3 KiB
Go
// Copyright 2021 The OPA Authors. All rights reserved.
|
|
// Use of this source code is governed by an Apache2
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Package refactor implements different refactoring operations over Rego modules.
|
|
package refactor
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/open-policy-agent/opa/v1/ast"
|
|
)
|
|
|
|
// Error defines the structure of errors returned by refactor.
|
|
type Error struct {
|
|
Message string `json:"message"`
|
|
Location *ast.Location `json:"location,omitempty"`
|
|
}
|
|
|
|
func (e Error) Error() string {
|
|
|
|
if e.Location != nil {
|
|
return e.Location.Format(e.Message)
|
|
}
|
|
|
|
return e.Message
|
|
}
|
|
|
|
// Refactor implements different refactoring operations over Rego modules eg. renaming packages.
|
|
type Refactor struct {
|
|
}
|
|
|
|
// New returns a new Refactor object.
|
|
func New() *Refactor {
|
|
return &Refactor{}
|
|
}
|
|
|
|
// MoveQuery holds the set of Rego modules whose package paths and other references are to be rewritten
|
|
// as per the mapping defined in SrcDstMapping.
|
|
// If validate is true, the moved modules will be compiled to ensure they are valid.
|
|
type MoveQuery struct {
|
|
Modules map[string]*ast.Module
|
|
SrcDstMapping map[string]string
|
|
validate bool
|
|
}
|
|
|
|
// WithValidation controls whether to compile moved modules to ensure they are valid.
|
|
func (mq MoveQuery) WithValidation(v bool) MoveQuery {
|
|
mq.validate = v
|
|
return mq
|
|
}
|
|
|
|
// MoveQueryResult defines the output of a move query and holds the rewritten modules with updated packages paths
|
|
// and references.
|
|
type MoveQueryResult struct {
|
|
Result map[string]*ast.Module `json:"result"`
|
|
}
|
|
|
|
// validate validates moved modules by compiling them.
|
|
func (mqr *MoveQueryResult) validate() error {
|
|
compiler := ast.NewCompiler()
|
|
compiler.Compile(mqr.Result)
|
|
|
|
if compiler.Failed() {
|
|
return compiler.Errors
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Move rewrites Rego code by updating package paths and other references in q's modules as per
|
|
// the mapping specified in q.
|
|
func (*Refactor) Move(q MoveQuery) (*MoveQueryResult, error) {
|
|
|
|
for _, module := range q.Modules {
|
|
t := ast.NewGenericTransformer(func(x any) (any, error) {
|
|
if s, ok := x.(ast.Ref); ok {
|
|
for k, v := range q.SrcDstMapping {
|
|
other, err := ast.ParseRef(k)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if s.HasPrefix(other) {
|
|
newRef, err := ast.ParseRef(v)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return newRef.Concat(s[len(other):]), nil
|
|
}
|
|
|
|
// check if a reference in the policy is a prefix of a source reference
|
|
// example: policy_reference = data.foo
|
|
// mapping: {"data.foo.bar": "data.baz"}
|
|
// In this scenario, we can relocate data.foo.bar but everything under data.foo
|
|
// (e.g., data.foo.baz, data.foo.qux, etc.) can't be relocated
|
|
r := s.ConstantPrefix()
|
|
if len(r) != 0 && other.HasPrefix(r) {
|
|
msg := fmt.Sprintf("cannot rewrite `%v`: constant prefix `%v` of `%v` is too short", s, r, s)
|
|
x := Error{Message: msg, Location: s[len(s)-1].Loc()}
|
|
return nil, x
|
|
}
|
|
}
|
|
}
|
|
return x, nil
|
|
})
|
|
_, err := ast.Transform(t, module)
|
|
if err != nil {
|
|
switch err.(type) {
|
|
case Error:
|
|
return nil, err
|
|
default:
|
|
return nil, Error{Message: err.Error()}
|
|
}
|
|
}
|
|
}
|
|
|
|
result := &MoveQueryResult{Result: q.Modules}
|
|
|
|
if q.validate {
|
|
if err := result.validate(); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return result, nil
|
|
}
|