Skip to content

Commit

Permalink
cmd/inspect: render "related resources" and small misc changes (#4399)
Browse files Browse the repository at this point in the history
Some small changes:

* cmd/inspect: inline ast.DropHead() as dropDataPrefix() -- to avoid the extra export in the ast package
* docs/annotations: update related_resources example
* cmd/inspect: unexport PageWidth
* cmd/inspect: make usage text markdown-friendly

   This looks better on the website docs, and doesn't matter much when
   viewed on the CLI.

* cmd/inspect: add test for pretty annotations output
* cmd/inspect: also render related_resources in pretty mode

Signed-off-by: Stephan Renatus <[email protected]>
  • Loading branch information
srenatus authored Mar 3, 2022
1 parent 64a03c1 commit 60e564f
Show file tree
Hide file tree
Showing 5 changed files with 187 additions and 31 deletions.
6 changes: 3 additions & 3 deletions ast/annotations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func TestAnnotationSetFlatten(t *testing.T) {
# description: pkg
# organizations:
# - pkg
# related_resources:
# related_resources:
# - https://pkg
# authors:
# - pkg
Expand All @@ -44,7 +44,7 @@ package test
# description: doc
# organizations:
# - doc
# related_resources:
# related_resources:
# - https://doc
# authors:
# - doc
Expand All @@ -58,7 +58,7 @@ package test
# description: rule
# organizations:
# - rule
# related_resources:
# related_resources:
# - https://rule
# authors:
# - rule
Expand Down
12 changes: 0 additions & 12 deletions ast/term.go
Original file line number Diff line number Diff line change
Expand Up @@ -1085,18 +1085,6 @@ func (ref Ref) OutputVars() VarSet {
return vis.Vars()
}

// DropHead drops the first component of this ref.
func (ref Ref) DropHead() Ref {
if len(ref) <= 1 {
return EmptyRef()
}
r := ref[1:].Copy()
if s, ok := r[0].Value.(String); ok {
r[0].Value = Var(s)
}
return r
}

// QueryIterator defines the interface for querying AST documents with references.
type QueryIterator func(map[Var]Value, Value) error

Expand Down
40 changes: 30 additions & 10 deletions cmd/inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
)

const maxTableFieldLen = 50
const PageWidth = 80
const pageWidth = 80

type inspectCommandParams struct {
outputFormat *util.EnumFlag
Expand Down Expand Up @@ -63,10 +63,9 @@ the following:
Example:
$ ls
bundle.tar.gz
$ opa inspect bundle.tar.gz
$ ls
bundle.tar.gz
$ opa inspect bundle.tar.gz
You can provide exactly one OPA bundle or path to the 'inspect' command on the command-line. If you provide a path
referring to a directory, the 'inspect' command will load that path as a bundle and summarize its structure and contents.
Expand Down Expand Up @@ -212,7 +211,7 @@ func populateAnnotations(out io.Writer, refs []*ast.AnnotationsRef) error {
}

if p := ref.GetPackage(); p != nil {
fmt.Fprintln(out, "Package: ", p.Path.DropHead()) // dropping data. prefix
fmt.Fprintln(out, "Package: ", dropDataPrefix(p.Path))
}
if r := ref.GetRule(); r != nil {
fmt.Fprintln(out, "Rule: ", r.Head.Name)
Expand Down Expand Up @@ -261,8 +260,17 @@ func populateAnnotations(out io.Writer, refs []*ast.AnnotationsRef) error {
fmt.Fprintln(out)
}

if len(a.RelatedResources) > 0 {
fmt.Fprintln(out, "Related Resources:")
l := make([]listEntry, 0, len(a.RelatedResources))
for _, res := range a.RelatedResources {
l = append(l, listEntry{removeNewLines(res.Ref.String()), res.Description})
}
printList(out, l, " ")
fmt.Fprintln(out)
}
if len(a.Custom) > 0 {
fmt.Fprintln(out, "Custom: ")
fmt.Fprintln(out, "Custom:")
l := make([]listEntry, 0, len(a.Custom))
for k, v := range a.Custom {
b, _ := json.Marshal(v)
Expand Down Expand Up @@ -297,7 +305,7 @@ func printList(out io.Writer, list []listEntry, separator string) {
separator,
strings.Repeat(" ", keyLength-len(e.key)),
e.value)
fmt.Fprintln(out, truncateStr(line, PageWidth))
fmt.Fprintln(out, truncateStr(line, pageWidth))
}
}

Expand All @@ -311,13 +319,13 @@ func printTitle(out io.Writer, ref *ast.AnnotationsRef) {
}

if len(title) == 0 {
title = ref.Path.DropHead().String() // dropping data. prefix
title = dropDataPrefix(ref.Path).String()
}

fmt.Fprintf(out, "%s\n", title)

var underline []byte
for i := 0; i < len(title) && i < PageWidth; i++ {
for i := 0; i < len(title) && i < pageWidth; i++ {
underline = append(underline, '=')
}
fmt.Fprintln(out, string(underline))
Expand Down Expand Up @@ -363,3 +371,15 @@ func truncateFileName(s string) string {
res, _ := iStrs.TruncateFilePaths(maxTableFieldLen, len(s), s)
return res[s]
}

// dropDataPrefix drops the first component of the passed Ref
func dropDataPrefix(ref ast.Ref) ast.Ref {
if len(ref) <= 1 {
return ast.EmptyRef()
}
r := ref[1:].Copy()
if s, ok := r[0].Value.(ast.String); ok {
r[0].Value = ast.Var(s)
}
return r
}
150 changes: 150 additions & 0 deletions cmd/inspect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,153 @@ func TestInspectMultiBundleError(t *testing.T) {
t.Fatalf("Expected error %v but got %v", exp, err.Error())
}
}

func TestDoInspectPrettyWithAnnotations(t *testing.T) {

files := map[string]string{
"x.rego": `# METADATA
# title: pkg-title
# description: pkg-descr
# organizations:
# - pkg-org
# related_resources:
# - https://pkg
# - ref: https://pkg
# description: rr-pkg-note
# authors:
# - pkg-author
# schemas:
# - input: {"type": "boolean"}
# custom:
# pkg: pkg-custom
package test
# METADATA
# scope: document
# title: doc-title
# description: doc-descr
# organizations:
# - doc-org
# related_resources:
# - https://doc
# - ref: https://doc
# description: rr-doc-note
# authors:
# - doc-author
# schemas:
# - input: {"type": "integer"}
# custom:
# doc: doc-custom
# METADATA
# title: rule-title
# description: rule-title
# organizations:
# - rule-org
# related_resources:
# - https://rule
# - ref: https://rule
# description: rr-rule-note
# authors:
# - rule-author
# schemas:
# - input: {"type": "string"}
# custom:
# rule: rule-custom
p = 1`,
}

test.WithTempFS(files, func(rootDir string) {
ps := newInspectCommandParams()
ps.listAnnotations = true
var out bytes.Buffer
err := doInspect(ps, rootDir, &out)
if err != nil {
t.Fatalf("Unexpected error %v", err)
}

bs := out.Bytes()
idx := bytes.Index(bs, []byte(`ANNOTATIONS`)) // skip NAMESPACE box
output := strings.TrimSpace(string(bs[idx:]))
expected := strings.TrimSpace(fmt.Sprintf(`
ANNOTATIONS:
pkg-title
=========
pkg-descr
Package: test
Location: %[1]s/x.rego:16
Organizations:
pkg-org
Authors:
pkg-author
Schemas:
input: {"type":"boolean"}
Related Resources:
https://pkg
https://pkg rr-pkg-note
Custom:
pkg: "pkg-custom"
doc-title
=========
doc-descr
Package: test
Rule: p
Location: %[1]s/x.rego:18
Organizations:
doc-org
Authors:
doc-author
Schemas:
input: {"type":"integer"}
Related Resources:
https://doc
https://doc rr-doc-note
Custom:
doc: "doc-custom"
rule-title
==========
rule-title
Package: test
Rule: p
Location: %[1]s/x.rego:50
Organizations:
rule-org
Authors:
rule-author
Schemas:
input: {"type":"string"}
Related Resources:
https://rule
https://rule rr-rule-note
Custom:
rule: "rule-custom"`, rootDir))

if output != expected {
t.Fatalf("Unexpected output. Expected:\n\n%q\n\nGot:\n\n%q", expected, output)
}

})
}
10 changes: 4 additions & 6 deletions docs/content/annotations.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,11 @@ When a *related-resource* entry is presented as a string, it needs to be a valid

```rego
# METADATA
# related-resources:
# -
# ref: https://example.com
# related_resources:
# - ref: https://example.com
# ...
# -
# ref: https://example.com/foo
# description: A text describing this resource
# - ref: https://example.com/foo
# description: A text describing this resource
allow {
...
}
Expand Down

0 comments on commit 60e564f

Please sign in to comment.