diff --git a/Makefile b/Makefile index 3770cf1b..59e28c04 100644 --- a/Makefile +++ b/Makefile @@ -144,8 +144,13 @@ codegen-jp-docs: ## Generate JP docs @rm -rf docs/user/jp && mkdir -p docs/user/jp @go run ./hack/docs/jp/main.go > docs/user/jp/functions.md +.PHONY: codegen-catalog +codegen-catalog: ## Generate policy catalog + @echo Generate policy catalog... >&2 + @go run ./hack/docs/catalog/main.go + .PHONY: codegen-docs -codegen-docs: codegen-api-docs-md codegen-cli-docs codegen-jp-docs ## Generate docs +codegen-docs: codegen-api-docs-md codegen-cli-docs codegen-jp-docs codegen-catalog ## Generate docs .PHONY: codegen-mkdocs codegen-mkdocs: codegen-docs ## Generate mkdocs website diff --git a/catalog/aws/policy-1.yaml b/catalog/aws/policy-1.yaml new file mode 100644 index 00000000..33687d38 --- /dev/null +++ b/catalog/aws/policy-1.yaml @@ -0,0 +1,17 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: Policy +metadata: + name: test + labels: + s3.aws.tags.kyverno.io: '' + annotations: + title.catalog.kyverno.io: Policy 1 + description.catalog.kyverno.io: Policy 1 +spec: + rules: + - name: foo-bar + validate: + assert: + all: + - foo: + /(bar)/: 10 diff --git a/catalog/ecs/policy-1.yaml b/catalog/ecs/policy-1.yaml new file mode 100644 index 00000000..6884961d --- /dev/null +++ b/catalog/ecs/policy-1.yaml @@ -0,0 +1,12 @@ +apiVersion: json.kyverno.io/v1alpha1 +kind: Policy +metadata: + name: test +spec: + rules: + - name: foo-bar + validate: + assert: + all: + - foo: + /(bar)/: 10 diff --git a/hack/docs/catalog/main.go b/hack/docs/catalog/main.go new file mode 100644 index 00000000..4fe327e0 --- /dev/null +++ b/hack/docs/catalog/main.go @@ -0,0 +1,154 @@ +package main + +import ( + "io/fs" + "os" + "path/filepath" + "slices" + "strings" + "text/template" + + "github.com/kyverno/kyverno-json/pkg/apis/v1alpha1" + "github.com/kyverno/kyverno-json/pkg/catalog" + "github.com/kyverno/kyverno-json/pkg/policy" + fileinfo "github.com/kyverno/kyverno-json/pkg/utils/file-info" + "sigs.k8s.io/yaml" +) + +const ( + path = "./catalog" +) + +type pol struct { + Path string + Policy *v1alpha1.Policy +} + +func (p pol) TargetPath() string { + base, err := filepath.Rel(path, p.Path) + if err != nil { + panic(err) + } + target := filepath.Join("website/docs/catalog/policies/", base) + target = strings.TrimSuffix(target, filepath.Ext(target)) + ".md" + return target +} + +func (p pol) NavPath() string { + base, err := filepath.Rel("website/docs", p.TargetPath()) + if err != nil { + panic(err) + } + return base +} + +func (p pol) Generate() error { + if err := os.MkdirAll(filepath.Dir(p.TargetPath()), os.ModePerm); err != nil { + return err + } + template, err := template.ParseFiles("./website/policy.gotmpl") + if err != nil { + return err + } + policy, err := os.Create(p.TargetPath()) + if err != nil { + return err + } + defer policy.Close() + if err := template.Execute(policy, p); err != nil { + return err + } + return nil +} + +func (p pol) Title() string { + title := p.Policy.Annotations[catalog.AnnotationPolicyTitle] + if title != "" { + return title + } + base := filepath.Base(p.Path) + return strings.TrimSuffix(base, filepath.Ext(base)) +} + +func (p pol) Description() string { + description := p.Policy.Annotations[catalog.AnnotationPolicyDescription] + if description != "" { + return description + } + return "None" +} + +func (p pol) Manifest() string { + bytes, err := yaml.Marshal(p.Policy) + if err != nil { + return err.Error() + } + return strings.TrimSpace(string(bytes)) +} + +func (p pol) Tags() []string { + var tags []string + for k := range p.Policy.Labels { + if strings.HasSuffix(k, catalog.TagsLabelSuffix) { + tag := strings.TrimSuffix(k, catalog.TagsLabelSuffix) + parts := strings.Split(tag, ".") + slices.Reverse(parts) + for i := 1; i <= len(parts); i++ { + tags = append(tags, strings.Join(parts[:i], "/")) + } + } + } + return tags +} + +func main() { + var files []string + err := filepath.Walk(path, func(file string, info fs.FileInfo, err error) error { + if err != nil { + return err + } + if fileinfo.IsYaml(info) { + files = append(files, file) + } + return nil + }) + if err != nil { + panic(err) + } + var pols []pol + for _, file := range files { + policies, err := policy.Load(file) + if err != nil { + panic(err) + } + for _, policy := range policies { + pols = append(pols, pol{ + Path: file, + Policy: policy, + }) + } + if err := os.RemoveAll("website/docs/catalog/policies"); err != nil { + panic(err) + } + for _, pol := range pols { + err := pol.Generate() + if err != nil { + panic(err) + } + } + template, err := template.ParseFiles("./website/nav.gotmpl") + if err != nil { + panic(err) + } + mkdocs, err := os.Create("./website/mkdocs.yaml") + if err != nil { + panic(err) + } + defer mkdocs.Close() + if err := template.Execute(mkdocs, map[string]interface{}{ + "Policies": pols, + }); err != nil { + panic(err) + } + } +} diff --git a/pkg/catalog/metadata.go b/pkg/catalog/metadata.go new file mode 100644 index 00000000..a36706e5 --- /dev/null +++ b/pkg/catalog/metadata.go @@ -0,0 +1,7 @@ +package catalog + +const ( + TagsLabelSuffix = ".tags.kyverno.io" + AnnotationPolicyDescription = "description.policy.kyverno.io" + AnnotationPolicyTitle = "title.policy.kyverno.io" +) diff --git a/website/docs/catalog/policies/aws/policy-1.md b/website/docs/catalog/policies/aws/policy-1.md new file mode 100644 index 00000000..2a985895 --- /dev/null +++ b/website/docs/catalog/policies/aws/policy-1.md @@ -0,0 +1,35 @@ +--- +tags: +- aws +- aws/s3 +--- +# policy-1 + +## Description + +None + +## Manifest + +[Original policy](https://github.com/kyverno/kyverno-json/catalog/aws/policy-1.yaml) + +```yaml +apiVersion: json.kyverno.io/v1alpha1 +kind: Policy +metadata: + annotations: + description.catalog.kyverno.io: Policy 1 + title.catalog.kyverno.io: Policy 1 + creationTimestamp: null + labels: + s3.aws.tags.kyverno.io: "" + name: test +spec: + rules: + - name: foo-bar + validate: + assert: + all: + - foo: + /(bar)/: 10 +``` \ No newline at end of file diff --git a/website/docs/catalog/policies/ecs/policy-1.md b/website/docs/catalog/policies/ecs/policy-1.md new file mode 100644 index 00000000..32a19e0e --- /dev/null +++ b/website/docs/catalog/policies/ecs/policy-1.md @@ -0,0 +1,26 @@ + +# policy-1 + +## Description + +None + +## Manifest + +[Original policy](https://github.com/kyverno/kyverno-json/catalog/ecs/policy-1.yaml) + +```yaml +apiVersion: json.kyverno.io/v1alpha1 +kind: Policy +metadata: + creationTimestamp: null + name: test +spec: + rules: + - name: foo-bar + validate: + assert: + all: + - foo: + /(bar)/: 10 +``` \ No newline at end of file diff --git a/website/docs/overrides/home.html b/website/docs/overrides/home.html index 8ecf3f5f..121e9b18 100644 --- a/website/docs/overrides/home.html +++ b/website/docs/overrides/home.html @@ -3,7 +3,7 @@ {{ super() }}