Skip to content

Commit

Permalink
steps to get this thing working
Browse files Browse the repository at this point in the history
  • Loading branch information
Integralist committed Jan 26, 2021
1 parent 2222721 commit d073156
Show file tree
Hide file tree
Showing 11 changed files with 258 additions and 19 deletions.
5 changes: 4 additions & 1 deletion GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,13 @@ test-compile:
fi
go test -c $(TEST) $(TESTARGS)

precompile-docs:
go run scripts/docs-precompile.go

validate-docs:
tfplugindocs validate

gen-docs:
gen-docs: precompile-docs
tfplugindocs generate

.PHONY: build test testacc vet fmt fmtcheck errcheck test-compile validate-docs gen-docs
236 changes: 236 additions & 0 deletions scripts/docs-precompile.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
// This script is designed to precompile all our documentation template files
// so they are ready to then be passed onto the official terraform
// documentation generation tool:
// https://github.com/hashicorp/terraform-plugin-docs
//
// The reason why we need to precompile the templates is because they use the
// {{ define "..." }} syntax to allow us to reuse Markdown content across
// multiple files, and so we need this script to expose those separate files as
// if they were defined within a single template file.
//
// The reason we need the official terraform documentation generator tool is
// because it helps to pick up missing content that we've not defined by
// reflecting over the schemas of our resources and data sources.
//
// THE COMPLETE DOCUMENTATION STEPS ARE:
//
// 1. acquire all the templates
// 2. render the templates into Markdown
// 3. write the file output to a temp directory and still use .tmpl extension
// 4. append to each rendered .tmpl file the template code needed by tfplugindocs (e.g. {{ .SchemaMarkdown | trimspace }})
// 5. rename repo /templates/{data-sources/resources} directories to avoid being overwritten by next step
// 6. move contents of temp directory (i.e. data-sources/resources) into repo /templates directory
// 7. run tfplugindocs generate function to output final documentation to /docs directory
// 8. replace /templates/{data-sources/resources} directories with their backed up equivalents
//
package main

import (
"fmt"
"html/template"
"io/ioutil"
"log"
"os"
"path/filepath"
"runtime"
"strings"
)

// PageData represents a type of service and enables a template to render
// different content depending on the service type.
type PageData struct {
ServiceType string
}

// Page represents a template page to be rendered.
//
// name: the {{ define "..." }} in each template.
// path: the path to write rendered output to.
// Data: context specific information (e.g. vcl vs wasm).
//
// Data is public as it's called via the template processing logic.
type Page struct {
name string
path string
Data PageData
}

func main() {
baseDir := getBaseDir()
tmplDir := baseDir + "/templates/"
// docsDir := baseDir + "/docs/"

tempDir, err := ioutil.TempDir("", "precompile")
fmt.Println(tempDir)
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(tempDir)

var dataPages = []Page{
{
name: "ip_ranges",
path: tempDir + "/data-sources/ip_ranges.md.tmpl",
},
{
name: "waf_rules",
path: tempDir + "/data-sources/waf_rules.md.tmpl",
},
}

var resourcePages = []Page{
{
name: "service_v1",
path: tempDir + "/resources/service_v1.md.tmpl",
Data: PageData{
"vcl",
},
},
{
name: "service_compute",
path: tempDir + "/resources/service_compute.md.tmpl",
Data: PageData{
"wasm",
},
},
{
name: "service_dictionary_items_v1",
path: tempDir + "/resources/service_dictionary_items_v1.md.tmpl",
},
{
name: "service_acl_entries_v1",
path: tempDir + "/resources/service_acl_entries_v1.md.tmpl",
},
{
name: "service_dynamic_snippet_content_v1",
path: tempDir + "/resources/service_dynamic_snippet_content_v1.md.tmpl",
},
{
name: "service_waf_configuration",
path: tempDir + "/resources/service_waf_configuration.md.tmpl",
},
{
name: "user_v1",
path: tempDir + "/resources/user_v1.md.tmpl",
},
}

pages := append(resourcePages, dataPages...)

renderPages(getTemplate(tmplDir), pages)

appendSyntaxToFiles(tempDir)

backupTemplatesDir(tmplDir)
}

// getBaseDir returns the terraform repo directory.
//
// TODO: simplify this logic with something like:
// git rev-parse --show-toplevel
func getBaseDir() string {
_, scriptPath, _, ok := runtime.Caller(0)
if !ok {
log.Fatal("Could not get current working directory")
}
for !strings.HasPrefix(filepath.Base(scriptPath), "terraform-provider-") && scriptPath != "/" {
scriptPath = filepath.Clean(scriptPath + "/..")
}
if scriptPath == "/" {
log.Fatal("Script was run outside of fastly provider directory")
}
return scriptPath
}

// getTemplate walks the templates directory filtering non-tmpl extension
// files, and parsing all the templates found (ensuring they must parse).
func getTemplate(tmplDir string) *template.Template {
var templateFiles []string
filepath.Walk(tmplDir, func(path string, info os.FileInfo, err error) error {
if filepath.Ext(path) == ".tmpl" {
templateFiles = append(templateFiles, path)
}
return nil
})
return template.Must(template.ParseFiles(templateFiles...))
}

// renderPages iterates over the given pages and renders each element.
func renderPages(t *template.Template, pages []Page) {
for _, p := range pages {
renderPage(t, p)
}
}

// renderPage creates a new file based on the page information given, and
// renders the associated template for that page.
func renderPage(t *template.Template, p Page) {
basePath := filepath.Dir(p.path)
err := makeDirectoryIfNotExists(basePath)
if err != nil {
log.Fatal()
}

f, err := os.Create(p.path)
if err != nil {
panic(err)
}
defer f.Close()
err = t.ExecuteTemplate(f, p.name, p)
if err != nil {
panic(err)
}
}

// makeDirectoryIfNotExists asserts whether a directory exists and makes it
// if not. Returns nil if exists or successfully made.
func makeDirectoryIfNotExists(path string) error {
fi, err := os.Stat(path)
switch {
case err == nil && fi.IsDir():
return nil
case err == nil && !fi.IsDir():
return fmt.Errorf("%s already exists as a regular file", path)
case os.IsNotExist(err):
return os.MkdirAll(path, 0750)
case err != nil:
return err
}

return nil
}

// appendSyntaxToFiles walks the temporary directory finding all the rendered
// Markdown files we generated and proceeds to append the required template
// syntax that the tfplugindocs tool needs.
func appendSyntaxToFiles(tempDir string) {
filepath.Walk(tempDir, func(path string, info os.FileInfo, err error) error {
if filepath.Ext(path) == ".tmpl" {
// open file for appending and in write-only mode
f, err := os.OpenFile(path, os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
if _, err := f.Write([]byte("{{ .SchemaMarkdown | trimspace }}\n")); err != nil {
f.Close() // ignore error; Write error takes precedence
log.Fatal(err)
}
if err := f.Close(); err != nil {
log.Fatal(err)
}
}
return nil
})
}

// backupTemplatesDir renames the /templates directory.
//
// We do this so that we can create a new /templates directory and move the
// contents of the temporary directory into the new location. Thus allowing
// tfplugindocs to be run within the root of the terraform provider repo.
func backupTemplatesDir(tmplDir string) {
err := os.Rename(tmplDir, tmplDir+"-backup")
if err != nil {
log.Fatal(err)
}
}
4 changes: 2 additions & 2 deletions templates/data-sources/ip_ranges.md.tmpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
---
{{define "ip_ranges"}}---
page_title: "Fastly: fastly_ip_ranges"
---

Expand Down Expand Up @@ -30,4 +30,4 @@ resource "aws_security_group" "from_fastly" {
* `ipv6_cidr_blocks` - The lexically ordered list of ipv6 CIDR blocks.

[1]: https://docs.fastly.com/guides/securing-communications/accessing-fastlys-ip-ranges
{{ .SchemaMarkdown | trimspace }}
{{end}}
4 changes: 2 additions & 2 deletions templates/data-sources/waf_rules.md.tmpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
---
{{define "waf_rules"}}---
page_title: "Fastly: fastly_waf_rules"
---

Expand Down Expand Up @@ -143,4 +143,4 @@ The `rules` block supports:

[1]: https://developer.fastly.com/reference/api/waf/rules/

{{ .SchemaMarkdown | trimspace }}
{{end}}
4 changes: 2 additions & 2 deletions templates/resources/service_acl_entries_v1.md.tmpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
---
{{define "service_acl_entries_v1"}}---
page_title: "Fastly: service_acl_entries_v1"
---

Expand Down Expand Up @@ -234,4 +234,4 @@ The following is an example of the Terraform state command to remove the resourc
$ terraform state rm fastly_service_acl_entries_v1.entries
```

{{ .SchemaMarkdown | trimspace }}
{{end}}
4 changes: 2 additions & 2 deletions templates/resources/service_compute.md.tmpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
---
{{define "service_compute"}}---
page_title: "Fastly: service_compute"
---

Expand Down Expand Up @@ -112,4 +112,4 @@ The following arguments are supported:
{{ template "export_intro" .}}
{{ template "footer" .}}

{{ .SchemaMarkdown | trimspace }}
{{end}}
4 changes: 2 additions & 2 deletions templates/resources/service_dictionary_items_v1.md.tmpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
---
{{define "service_dictionary_items_v1"}}---
page_title: "Fastly: service_dictionary_items_v1"
---

Expand Down Expand Up @@ -247,4 +247,4 @@ The following is an example of the Terraform state command to remove the resourc
```
$ terraform state rm fastly_service_dictionary_items_v1.items
```
{{ .SchemaMarkdown | trimspace }}
{{end}}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
---
{{define "service_dynamic_snippet_content_v1"}}---
page_title: "Fastly: service_dynamic_snippet_content_v1"
---

Expand Down Expand Up @@ -202,4 +202,4 @@ The following is an example of the Terraform state command to remove the resourc
```
$ terraform state rm fastly_service_dynamic_snippet_content_v1.content
```
{{ .SchemaMarkdown | trimspace }}
{{end}}
4 changes: 2 additions & 2 deletions templates/resources/service_v1.md.tmpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
---
{{define "service_v1"}}---
page_title: "Fastly: service_v1"
---

Expand Down Expand Up @@ -308,4 +308,4 @@ The following arguments are supported:

{{ template "footer" .}}

{{ .SchemaMarkdown | trimspace }}
{{end}}
4 changes: 2 additions & 2 deletions templates/resources/service_waf_configuration.md.tmpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
---
{{define "service_waf_configuration"}}---
page_title: "Fastly: service_waf_configuration"
---

Expand Down Expand Up @@ -623,4 +623,4 @@ The following is an example of the Terraform state command to remove the resourc
```
$ terraform state rm fastly_service_waf_configuration.waf
```
{{ .SchemaMarkdown | trimspace }}
{{end}}
4 changes: 2 additions & 2 deletions templates/resources/user_v1.md.tmpl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
---
{{define "user_v1"}}---
page_title: "Fastly: user_v1"
---

Expand Down Expand Up @@ -40,4 +40,4 @@ A Fastly User can be imported using their user ID, e.g.
```
$ terraform import fastly_user_v1.demo xxxxxxxxxxxxxxxxxxxx
```
{{ .SchemaMarkdown | trimspace }}
{{end}}

0 comments on commit d073156

Please sign in to comment.