Skip to content

Commit

Permalink
feat: adding display of multiple CRDs on a single webpage (#111)
Browse files Browse the repository at this point in the history
  • Loading branch information
Skarlso authored Oct 3, 2024
1 parent 4259e16 commit f50a662
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 106 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ cty generate -c delivery.krok.app_krokcommands --comments --format html
![parsed1_cli](./imgs/parsed1_cli.png)
![parsed2_cli](./imgs/parsed2_cli.png)

In case of multiple CRD files being parsed using a `folder` target, the CRDs will be listed
in collapsed drop-down menus where their KIND is the title.

![parsed3_cli](./imgs/parsed3_cli.png)

### Minimal required CRD sample

It's possible to generate a sample YAML for a CRD that will make the CRD validation pass. Meaning, it will only contain
Expand Down
21 changes: 15 additions & 6 deletions cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,21 @@ func runGenerate(_ *cobra.Command, _ []string) error {

var w io.WriteCloser

if args.format == FormatHTML {
if args.stdOut {
w = os.Stdout
} else {
w, err = os.Create(args.output)
if err != nil {
return fmt.Errorf("failed to create output file: %w", err)
}

defer w.Close()
}

return pkg.RenderContent(w, crds, args.comments, args.minimal)
}

var errs []error //nolint:prealloc // nope
for _, crd := range crds {
if args.stdOut {
Expand All @@ -112,12 +127,6 @@ func runGenerate(_ *cobra.Command, _ []string) error {
w = outputFile
}

if args.format == FormatHTML {
errs = append(errs, pkg.RenderContent(w, crd, args.comments, args.minimal))

continue
}

errs = append(errs, pkg.Generate(crd, w, args.comments, args.minimal, args.skipRandom))
}

Expand Down
11 changes: 0 additions & 11 deletions gotemplates.gotemplating.fn.crossplane.io_sample.yaml

This file was deleted.

Binary file added imgs/parsed3_cli.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
69 changes: 46 additions & 23 deletions pkg/create_html_output.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import (
v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
)

type Index struct {
Page []ViewPage
}

// Version wraps a top level version resource which contains the underlying openAPIV3Schema.
type Version struct {
Version string
Expand All @@ -26,6 +30,7 @@ type Version struct {

// ViewPage is the template for view.html.
type ViewPage struct {
Title string
Versions []Version
}

Expand Down Expand Up @@ -61,40 +66,58 @@ func LoadTemplates() error {
}

// RenderContent creates an HTML website from the CRD content.
func RenderContent(w io.WriteCloser, crd *v1.CustomResourceDefinition, comments, minimal bool) (err error) {
func RenderContent(w io.WriteCloser, crds []*v1.CustomResourceDefinition, comments, minimal bool) (err error) {
defer func() {
if cerr := w.Close(); cerr != nil {
err = errors.Join(err, cerr)
}
}()

versions := make([]Version, 0)
parser := NewParser(crd.Spec.Group, crd.Spec.Names.Kind, comments, minimal, false)
allViews := make([]ViewPage, 0, len(crds))

for _, version := range crd.Spec.Versions {
out, err := parseCRD(version.Schema.OpenAPIV3Schema.Properties, version.Name, minimal, RootRequiredFields)
if err != nil {
return fmt.Errorf("failed to parse properties: %w", err)
for _, crd := range crds {
versions := make([]Version, 0)
parser := NewParser(crd.Spec.Group, crd.Spec.Names.Kind, comments, minimal, false)

for _, version := range crd.Spec.Versions {
out, err := parseCRD(version.Schema.OpenAPIV3Schema.Properties, version.Name, minimal, RootRequiredFields)
if err != nil {
return fmt.Errorf("failed to parse properties: %w", err)
}
var buffer []byte
buf := bytes.NewBuffer(buffer)
if err := parser.ParseProperties(version.Name, buf, version.Schema.OpenAPIV3Schema.Properties); err != nil {
return fmt.Errorf("failed to generate yaml sample: %w", err)
}
versions = append(versions, Version{
Version: version.Name,
Properties: out,
Kind: crd.Spec.Names.Kind,
Group: crd.Spec.Group,
Description: version.Schema.OpenAPIV3Schema.Description,
YAML: buf.String(),
})
}
var buffer []byte
buf := bytes.NewBuffer(buffer)
if err := parser.ParseProperties(version.Name, buf, version.Schema.OpenAPIV3Schema.Properties); err != nil {
return fmt.Errorf("failed to generate yaml sample: %w", err)

if len(versions) == 0 {
continue
}
versions = append(versions, Version{
Version: version.Name,
Properties: out,
Kind: crd.Spec.Names.Kind,
Group: crd.Spec.Group,
Description: version.Schema.OpenAPIV3Schema.Description,
YAML: buf.String(),
})
}
view := ViewPage{
Versions: versions,

view := ViewPage{
Title: crd.Spec.Names.Kind,
Versions: versions,
}

allViews = append(allViews, view)
}

t := templates["view.html"]
if err := t.Execute(w, view); err != nil {

index := Index{
Page: allViews,
}

if err := t.Execute(w, index); err != nil {
return fmt.Errorf("failed to execute template: %w", err)
}

Expand Down
128 changes: 62 additions & 66 deletions pkg/templates/view.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,82 +31,78 @@
padding-bottom: 2rem;
}
</style>
<style>

<!-- User Provided CSS is put here. -->
<style>
</style>
</head>

<body class="dark-mode" data-dm-shortcut-enabled="true" data-sidebar-shortcut-enabled="true">
<div class="content-wrapper">
<div class="container">
<div class="versions">
{{range .Versions}}
<h1>
Version: {{.Group}}/{{.Version}}<br>
Kind: {{.Kind}}
</h1>
<p class="font-size-18">
<div>
<p>{{.Description}}</p>
</div>
<label>Generated YAML sample:</label>
<div class="collapse-group">
<details class="collapse-panel">
<div id="yaml-{{.Version}}" class="collapse-content">
<pre class="language-yaml"><code class="language-yaml">{{.YAML}}</code></pre>
</div>
</details>
</div>
</p>
<div class="d-flex flex-row-reverse mb-10 mt-10">
<button class="btn ml-10" type="button" onclick="expandAll()">
+ expand all
</button>
<button class="btn" type="button" onclick="collapseAll()">
- collapse all
</button>
</div>
<div class="collapse-group">
{{range $i, $v := .Properties}}
<details class="collapse-panel">
<summary class="collapse-header position-relative">
{{$v.Name}} <kbd class="text-muted">{{$v.Type}}</kbd>
{{if $v.Format}}
<kbd class="text-muted">{{.Format}}</kbd>
{{end}}
{{if $v.Patterns}}
<kbd class="text-muted">{{.Patterns}}</kbd>
{{end}}
{{if $v.Default}}
<kbd class="text-primary">{{$v.Default}}</kbd>
{{end}}
{{if $v.Required}}
<span class="badge badge-primary">required</span>
<h2 style="text-align: center">The following CRDs have been rendered</h2>

{{range .Page}}
<details class="collapse-panel mw-full mt-10 mr-20 ml-20 px-md-20"> <!-- w-400 = width: 40rem (400px), mw-full = max-width: 100% -->
<summary class="collapse-header">
{{.Title}}
</summary>
<div class="collapse-content">
<div class="versions">
{{range .Versions}}
<h1>
Version: {{.Group}}/{{.Version}}<br>
Kind: {{.Kind}}
</h1>
<p class="font-size-18">
<div>
<p>{{.Description}}</p>
</div>
<label>Generated YAML sample:</label>
<div class="collapse-group">
<details class="collapse-panel">
<div id="yaml-{{.Version}}" class="collapse-content">
<pre class="language-yaml"><code class="language-yaml">{{.YAML}}</code></pre>
</div>
</details>
</div>
</p>
<div class="collapse-group">
{{range $i, $v := .Properties}}
<details class="collapse-panel">
<summary class="collapse-header position-relative">
{{$v.Name}} <kbd class="text-muted">{{$v.Type}}</kbd>
{{if $v.Format}}
<kbd class="text-muted">{{.Format}}</kbd>
{{end}}
{{if $v.Patterns}}
<kbd class="text-muted">{{.Patterns}}</kbd>
{{end}}
{{if $v.Default}}
<kbd class="text-primary">{{$v.Default}}</kbd>
{{end}}
{{if $v.Required}}
<span class="badge badge-primary">required</span>
{{end}}
</summary>
<div id="{{$v.Name}}" class="collapse-content">
<div class="property-description">
<p>{{$v.Description}}</p>
</div>
{{template "properties" .Properties}}
</div>
<br>
</details>
{{end}}
</summary>
<div id="{{$v.Name}}" class="collapse-content">
<div class="property-description">
<p>{{$v.Description}}</p>
</div>
{{template "properties" .Properties}}
</div>
<br>
</details>
{{end}}
{{end}}
</div>
</div>
{{end}}
</div>
</div>
</details>
{{end}}
<!-- <div class="container">-->
<!-- -->
<!-- </div>-->
</div>
<script>
function expandAll() {
console.log("todo: loop through all elements and expand them")
}

function collapseAll() {
console.log("todo: loop through all elements and collapse them")
}
</script>
</body>
</html>

Expand Down

0 comments on commit f50a662

Please sign in to comment.