diff --git a/ast/capabilities.go b/ast/capabilities.go index 7850901fa0..8666e1f2d9 100644 --- a/ast/capabilities.go +++ b/ast/capabilities.go @@ -6,6 +6,8 @@ package ast import ( "bytes" + _ "embed" + "encoding/json" "fmt" "io" "os" @@ -13,10 +15,37 @@ import ( "strings" caps "github.com/open-policy-agent/opa/capabilities" + "github.com/open-policy-agent/opa/internal/semver" "github.com/open-policy-agent/opa/internal/wasm/sdk/opa/capabilities" "github.com/open-policy-agent/opa/util" ) +// VersonIndex contains an index from built-in function name, language feature, +// and future rego keyword to version number. During the build, this is used to +// create an index of the minimum version required for the built-in/feature/kw. +type VersionIndex struct { + Builtins map[string]semver.Version `json:"builtins"` + Features map[string]semver.Version `json:"features"` + Keywords map[string]semver.Version `json:"keywords"` +} + +// NOTE(tsandall): this file is generated by internal/cmd/genversionindex/main.go +// and run as part of go:generate. We generate the version index as part of the +// build process because it's relatively expensive to build (it takes ~500ms on +// my machine) and never changes. +// +//go:embed version_index.json +var versionIndexBs []byte + +var minVersionIndex = func() VersionIndex { + var vi VersionIndex + err := json.Unmarshal(versionIndexBs, &vi) + if err != nil { + panic(err) + } + return vi +}() + // In the compiler, we used this to check that we're OK working with ref heads. // If this isn't present, we'll fail. This is to ensure that older versions of // OPA can work with policies that we're compiling -- if they don't know ref @@ -130,6 +159,50 @@ func LoadCapabilitiesVersions() ([]string, error) { return capabilitiesVersions, nil } +// MinimumCompatibleVersion returns the minimum compatible OPA version based on +// the built-ins, features, and keywords in c. +func (c *Capabilities) MinimumCompatibleVersion() (string, bool) { + + var maxVersion semver.Version + + // this is the oldest OPA release that includes capabilities + if err := maxVersion.Set("0.17.0"); err != nil { + panic("unreachable") + } + + for _, bi := range c.Builtins { + v, ok := minVersionIndex.Builtins[bi.Name] + if !ok { + return "", false + } + if v.Compare(maxVersion) > 0 { + maxVersion = v + } + } + + for _, kw := range c.FutureKeywords { + v, ok := minVersionIndex.Keywords[kw] + if !ok { + return "", false + } + if v.Compare(maxVersion) > 0 { + maxVersion = v + } + } + + for _, feat := range c.Features { + v, ok := minVersionIndex.Features[feat] + if !ok { + return "", false + } + if v.Compare(maxVersion) > 0 { + maxVersion = v + } + } + + return maxVersion.String(), true +} + // addBuiltinSorted inserts a built-in into c in sorted order. An existing built-in with the same name // will be overwritten. func (c *Capabilities) addBuiltinSorted(bi *Builtin) { diff --git a/ast/capabilities_test.go b/ast/capabilities_test.go index 9ccaa48deb..73e3b94d67 100644 --- a/ast/capabilities_test.go +++ b/ast/capabilities_test.go @@ -157,6 +157,51 @@ func TestCapabilitiesAddBuiltinSorted(t *testing.T) { } } +func TestCapabilitiesMinimumCompatibleVersion(t *testing.T) { + + tests := []struct { + note string + module string + version string + }{ + { + note: "builtins", + module: ` + package x + p { array.reverse([1,2,3]) } + `, + version: "0.36.0", + }, + { + note: "keywords", + module: ` + package x + import future.keywords.every + `, + version: "0.38.0", + }, + { + note: "features", + module: ` + package x + import future.keywords.if + p.a.b.c.d if { true } + `, + version: "0.46.0", + }, + } + + for _, tc := range tests { + t.Run(tc.note, func(t *testing.T) { + c := MustCompileModules(map[string]string{"test.rego": tc.module}) + minVersion, found := c.Required.MinimumCompatibleVersion() + if !found || minVersion != tc.version { + t.Fatal("expected", tc.version, "but got", minVersion) + } + }) + } +} + func findBuiltinIndex(c *Capabilities, name string) int { for i, bi := range c.Builtins { if bi.Name == name { diff --git a/ast/version_index.json b/ast/version_index.json new file mode 100644 index 0000000000..085064862b --- /dev/null +++ b/ast/version_index.json @@ -0,0 +1,1408 @@ +{ + "builtins": { + "abs": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "all": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "and": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "any": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "array.concat": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "array.reverse": { + "Major": 0, + "Minor": 36, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "array.slice": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "assign": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "base64.decode": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "base64.encode": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "base64.is_valid": { + "Major": 0, + "Minor": 24, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "base64url.decode": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "base64url.encode": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "base64url.encode_no_pad": { + "Major": 0, + "Minor": 25, + "Patch": 0, + "PreRelease": "rc2", + "Metadata": "" + }, + "bits.and": { + "Major": 0, + "Minor": 18, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "bits.lsh": { + "Major": 0, + "Minor": 18, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "bits.negate": { + "Major": 0, + "Minor": 18, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "bits.or": { + "Major": 0, + "Minor": 18, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "bits.rsh": { + "Major": 0, + "Minor": 18, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "bits.xor": { + "Major": 0, + "Minor": 18, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "cast_array": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "cast_boolean": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "cast_null": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "cast_object": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "cast_set": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "cast_string": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "ceil": { + "Major": 0, + "Minor": 26, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "concat": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "contains": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "count": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "crypto.hmac.equal": { + "Major": 0, + "Minor": 52, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "crypto.hmac.md5": { + "Major": 0, + "Minor": 36, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "crypto.hmac.sha1": { + "Major": 0, + "Minor": 36, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "crypto.hmac.sha256": { + "Major": 0, + "Minor": 36, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "crypto.hmac.sha512": { + "Major": 0, + "Minor": 36, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "crypto.md5": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "crypto.parse_private_keys": { + "Major": 0, + "Minor": 55, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "crypto.sha1": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "crypto.sha256": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "crypto.x509.parse_and_verify_certificates": { + "Major": 0, + "Minor": 31, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "crypto.x509.parse_certificate_request": { + "Major": 0, + "Minor": 21, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "crypto.x509.parse_certificates": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "crypto.x509.parse_keypair": { + "Major": 0, + "Minor": 53, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "crypto.x509.parse_rsa_private_key": { + "Major": 0, + "Minor": 33, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "div": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "endswith": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "eq": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "equal": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "floor": { + "Major": 0, + "Minor": 26, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "format_int": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "glob.match": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "glob.quote_meta": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "graph.reachable": { + "Major": 0, + "Minor": 20, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "graph.reachable_paths": { + "Major": 0, + "Minor": 37, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "graphql.is_valid": { + "Major": 0, + "Minor": 41, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "graphql.parse": { + "Major": 0, + "Minor": 41, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "graphql.parse_and_verify": { + "Major": 0, + "Minor": 41, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "graphql.parse_query": { + "Major": 0, + "Minor": 41, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "graphql.parse_schema": { + "Major": 0, + "Minor": 41, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "graphql.schema_is_valid": { + "Major": 0, + "Minor": 46, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "gt": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "gte": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "hex.decode": { + "Major": 0, + "Minor": 25, + "Patch": 0, + "PreRelease": "rc2", + "Metadata": "" + }, + "hex.encode": { + "Major": 0, + "Minor": 25, + "Patch": 0, + "PreRelease": "rc2", + "Metadata": "" + }, + "http.send": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "indexof": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "indexof_n": { + "Major": 0, + "Minor": 37, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "internal.member_2": { + "Major": 0, + "Minor": 34, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "internal.member_3": { + "Major": 0, + "Minor": 34, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "internal.print": { + "Major": 0, + "Minor": 34, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "intersection": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "io.jwt.decode": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "io.jwt.decode_verify": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "io.jwt.encode_sign": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "io.jwt.encode_sign_raw": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "io.jwt.verify_es256": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "io.jwt.verify_es384": { + "Major": 0, + "Minor": 20, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "io.jwt.verify_es512": { + "Major": 0, + "Minor": 20, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "io.jwt.verify_hs256": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "io.jwt.verify_hs384": { + "Major": 0, + "Minor": 20, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "io.jwt.verify_hs512": { + "Major": 0, + "Minor": 20, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "io.jwt.verify_ps256": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "io.jwt.verify_ps384": { + "Major": 0, + "Minor": 20, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "io.jwt.verify_ps512": { + "Major": 0, + "Minor": 20, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "io.jwt.verify_rs256": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "io.jwt.verify_rs384": { + "Major": 0, + "Minor": 20, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "io.jwt.verify_rs512": { + "Major": 0, + "Minor": 20, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "is_array": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "is_boolean": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "is_null": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "is_number": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "is_object": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "is_set": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "is_string": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "json.filter": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "json.is_valid": { + "Major": 0, + "Minor": 25, + "Patch": 0, + "PreRelease": "rc1", + "Metadata": "" + }, + "json.marshal": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "json.match_schema": { + "Major": 0, + "Minor": 50, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "json.patch": { + "Major": 0, + "Minor": 25, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "json.remove": { + "Major": 0, + "Minor": 18, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "json.unmarshal": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "json.verify_schema": { + "Major": 0, + "Minor": 50, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "lower": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "lt": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "lte": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "max": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "min": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "minus": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "mul": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "neq": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "net.cidr_contains": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "net.cidr_contains_matches": { + "Major": 0, + "Minor": 19, + "Patch": 0, + "PreRelease": "rc1", + "Metadata": "" + }, + "net.cidr_expand": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "net.cidr_intersects": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "net.cidr_is_valid": { + "Major": 0, + "Minor": 46, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "net.cidr_merge": { + "Major": 0, + "Minor": 24, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "net.cidr_overlap": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "net.lookup_ip_addr": { + "Major": 0, + "Minor": 35, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "numbers.range": { + "Major": 0, + "Minor": 22, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "numbers.range_step": { + "Major": 0, + "Minor": 56, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "object.filter": { + "Major": 0, + "Minor": 17, + "Patch": 2, + "PreRelease": "", + "Metadata": "" + }, + "object.get": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "object.keys": { + "Major": 0, + "Minor": 47, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "object.remove": { + "Major": 0, + "Minor": 17, + "Patch": 2, + "PreRelease": "", + "Metadata": "" + }, + "object.subset": { + "Major": 0, + "Minor": 42, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "object.union": { + "Major": 0, + "Minor": 17, + "Patch": 2, + "PreRelease": "", + "Metadata": "" + }, + "object.union_n": { + "Major": 0, + "Minor": 37, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "opa.runtime": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "or": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "plus": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "print": { + "Major": 0, + "Minor": 34, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "product": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "providers.aws.sign_req": { + "Major": 0, + "Minor": 47, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "rand.intn": { + "Major": 0, + "Minor": 31, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "re_match": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "regex.find_all_string_submatch_n": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "regex.find_n": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "regex.globs_match": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "regex.is_valid": { + "Major": 0, + "Minor": 23, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "regex.match": { + "Major": 0, + "Minor": 23, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "regex.replace": { + "Major": 0, + "Minor": 45, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "regex.split": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "regex.template_match": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "rego.metadata.chain": { + "Major": 0, + "Minor": 40, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "rego.metadata.rule": { + "Major": 0, + "Minor": 40, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "rego.parse_module": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "rem": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "replace": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "round": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "semver.compare": { + "Major": 0, + "Minor": 22, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "semver.is_valid": { + "Major": 0, + "Minor": 22, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "set_diff": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "sort": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "split": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "sprintf": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "startswith": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "strings.any_prefix_match": { + "Major": 0, + "Minor": 44, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "strings.any_suffix_match": { + "Major": 0, + "Minor": 44, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "strings.replace_n": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "strings.reverse": { + "Major": 0, + "Minor": 36, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "substring": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "sum": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "time.add_date": { + "Major": 0, + "Minor": 19, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "time.clock": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "time.date": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "time.diff": { + "Major": 0, + "Minor": 28, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "time.format": { + "Major": 0, + "Minor": 48, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "time.now_ns": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "time.parse_duration_ns": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "time.parse_ns": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "time.parse_rfc3339_ns": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "time.weekday": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "to_number": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "trace": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "trim": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "trim_left": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "trim_prefix": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "trim_right": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "trim_space": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "trim_suffix": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "type_name": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "union": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "units.parse": { + "Major": 0, + "Minor": 41, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "units.parse_bytes": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "upper": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "urlquery.decode": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "urlquery.decode_object": { + "Major": 0, + "Minor": 24, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "urlquery.encode": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "urlquery.encode_object": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "uuid.parse": { + "Major": 0, + "Minor": 57, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "uuid.rfc4122": { + "Major": 0, + "Minor": 20, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "walk": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "yaml.is_valid": { + "Major": 0, + "Minor": 25, + "Patch": 0, + "PreRelease": "rc1", + "Metadata": "" + }, + "yaml.marshal": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "yaml.unmarshal": { + "Major": 0, + "Minor": 17, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + } + }, + "features": { + "rule_head_ref_string_prefixes": { + "Major": 0, + "Minor": 46, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + } + }, + "keywords": { + "contains": { + "Major": 0, + "Minor": 42, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "every": { + "Major": 0, + "Minor": 38, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "if": { + "Major": 0, + "Minor": 42, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + }, + "in": { + "Major": 0, + "Minor": 34, + "Patch": 0, + "PreRelease": "", + "Metadata": "" + } + } +} diff --git a/compile/compile.go b/compile/compile.go index 83413498d2..798f0e8fcf 100644 --- a/compile/compile.go +++ b/compile/compile.go @@ -1173,6 +1173,13 @@ func compile(c *ast.Capabilities, b *bundle.Bundle, dbg debug.Debug, enablePrint return nil, compiler.Errors } + minVersion, ok := compiler.Required.MinimumCompatibleVersion() + if !ok { + dbg.Printf("could not determine minimum compatible version!") + } else { + dbg.Printf("minimum compatible version: %v", minVersion) + } + return compiler, nil } diff --git a/internal/cmd/genversionindex/main.go b/internal/cmd/genversionindex/main.go new file mode 100644 index 0000000000..ee560c89c9 --- /dev/null +++ b/internal/cmd/genversionindex/main.go @@ -0,0 +1,78 @@ +package main + +import ( + "encoding/json" + "os" + + "github.com/open-policy-agent/opa/ast" + "github.com/open-policy-agent/opa/internal/semver" +) + +func minVersionIndex() ast.VersionIndex { + + index := ast.VersionIndex{ + Builtins: map[string]semver.Version{}, + Features: map[string]semver.Version{}, + Keywords: map[string]semver.Version{}, + } + + versions, err := ast.LoadCapabilitiesVersions() + if err != nil { + panic(err) + } + + for _, v := range versions { + var sv semver.Version + if err := sv.Set(v[1:]); err != nil { + panic(err) + } + + c, err := ast.LoadCapabilitiesVersion(v) + if err != nil { + panic(err) + } + + for _, bi := range c.Builtins { + exist, ok := index.Builtins[bi.Name] + if !ok || exist.Compare(sv) > 0 { + index.Builtins[bi.Name] = sv + } + } + + for _, kw := range c.FutureKeywords { + exist, ok := index.Keywords[kw] + if !ok || exist.Compare(sv) > 0 { + index.Keywords[kw] = sv + } + } + + for _, feat := range c.Features { + exist, ok := index.Features[feat] + if !ok || exist.Compare(sv) > 0 { + index.Features[feat] = sv + } + } + } + + return index +} + +func main() { + fd, err := os.Create(os.Args[1]) + if err != nil { + panic(err) + } + + enc := json.NewEncoder(fd) + enc.SetIndent("", " ") + + vi := minVersionIndex() + + if err := enc.Encode(vi); err != nil { + panic(err) + } + + if err := fd.Close(); err != nil { + panic(err) + } +} diff --git a/main.go b/main.go index 5aba68b3e8..d03e7b957b 100644 --- a/main.go +++ b/main.go @@ -16,6 +16,6 @@ func main() { } } -// Capabilities + built-in metadata file generation: //go:generate build/gen-run-go.sh internal/cmd/genopacapabilities/main.go capabilities.json //go:generate build/gen-run-go.sh internal/cmd/genbuiltinmetadata/main.go builtin_metadata.json +//go:generate build/gen-run-go.sh internal/cmd/genversionindex/main.go ast/version_index.json