summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorbaude <bbaude@redhat.com>2018-05-07 17:09:11 -0500
committerAtomic Bot <atomic-devel@projectatomic.io>2018-05-08 21:01:28 +0000
commit25263558f10b5e2e246b2349b49b1585852d57b6 (patch)
tree9cf12d770c3b3a376ffa85bdd327a3cb4e11ad99 /docs
parent21ebdb558cb939176d862e12bec99f34a1e5d4ba (diff)
downloadpodman-25263558f10b5e2e246b2349b49b1585852d57b6.tar.gz
podman-25263558f10b5e2e246b2349b49b1585852d57b6.tar.bz2
podman-25263558f10b5e2e246b2349b49b1585852d57b6.zip
Generate varlink API documentation automatically
Using varlink's idl parser, we generate API documentation for the podman API relying on the .varlink file as the source. Signed-off-by: baude <bbaude@redhat.com> Closes: #734 Approved by: baude
Diffstat (limited to 'docs')
-rw-r--r--docs/generate.go3
-rw-r--r--docs/varlink/apidoc.go248
2 files changed, 251 insertions, 0 deletions
diff --git a/docs/generate.go b/docs/generate.go
new file mode 100644
index 000000000..405d8c83f
--- /dev/null
+++ b/docs/generate.go
@@ -0,0 +1,3 @@
+package docs
+
+//go:generate go run varlink/apidoc.go ../cmd/podman/varlink/io.projectatomic.podman.varlink ../API.md
diff --git a/docs/varlink/apidoc.go b/docs/varlink/apidoc.go
new file mode 100644
index 000000000..fe9e0e044
--- /dev/null
+++ b/docs/varlink/apidoc.go
@@ -0,0 +1,248 @@
+package main
+
+import (
+ "bytes"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "strings"
+
+ "github.com/varlink/go/varlink/idl"
+)
+
+func readFileToString(path string) (string, error) {
+ content, err := ioutil.ReadFile(path)
+ if err != nil {
+ return "", err
+ }
+ return string(content), nil
+}
+
+func exit(err error) {
+ fmt.Println(err.Error())
+ os.Exit(1)
+}
+
+func typeToString(input *idl.Type) string {
+ switch input.Kind {
+ case idl.TypeString:
+ return "string"
+ case idl.TypeBool:
+ return "bool"
+ case idl.TypeFloat:
+ return "float"
+ case idl.TypeArray:
+ result := input.ElementType.Alias
+ if result == "" {
+ return fmt.Sprintf("[]%s", typeToString(input.ElementType))
+ }
+ return result
+ case idl.TypeAlias:
+ return input.Alias
+ case idl.TypeMap:
+ return "map[string]"
+ case idl.TypeInt:
+ return "int"
+ }
+ return ""
+}
+
+func typeToLink(input string) string {
+ switch input {
+ case "string":
+ return "https://godoc.org/builtin#string"
+ case "int":
+ return "https://godoc.org/builtin#int"
+ case "bool":
+ return "https://godoc.org/builtin#bool"
+ case "float":
+ return "https://golang.org/src/builtin/builtin.go#L58"
+ default:
+ return fmt.Sprintf("#%s", input)
+ }
+}
+
+type funcArgs struct {
+ paramName string
+ paramKind string
+}
+type funcDescriber struct {
+ Name string
+ inputParams []funcArgs
+ returnParams []funcArgs
+ doc string
+}
+
+type typeAttrs struct {
+ Name string
+ AttrType string
+}
+type typeDescriber struct {
+ Name string
+ doc string
+ Attrs []typeAttrs
+}
+
+type err struct {
+ Name string
+ doc string
+}
+
+// collects defined types in the idl
+func getTypes(tidl *idl.IDL) []typeDescriber {
+ var types []typeDescriber
+ for _, x := range tidl.Aliases {
+ i := typeDescriber{
+ Name: x.Name,
+ doc: x.Doc,
+ }
+ ta := []typeAttrs{}
+ for _, y := range x.Type.Fields {
+ result := typeToString(y.Type)
+ ta = append(ta, typeAttrs{Name: y.Name, AttrType: result})
+ }
+ i.Attrs = ta
+ types = append(types, i)
+ }
+ return types
+}
+
+// collects defined methods in the idl
+func getMethods(midl *idl.IDL) []funcDescriber {
+ var methods []funcDescriber
+ for _, t := range midl.Methods {
+ m := funcDescriber{
+ Name: t.Name,
+ doc: t.Doc,
+ }
+ fa := []funcArgs{}
+ fo := []funcArgs{}
+
+ for _, i := range t.In.Fields {
+ fa = append(fa, funcArgs{paramName: i.Name, paramKind: typeToString(i.Type)})
+
+ }
+ for _, f := range t.Out.Fields {
+ fo = append(fo, funcArgs{paramName: f.Name, paramKind: typeToString(f.Type)})
+ }
+ m.inputParams = fa
+ m.returnParams = fo
+ methods = append(methods, m)
+ }
+ return methods
+}
+
+// collects defined errors in the idl
+func getErrors(midl *idl.IDL) []err {
+ var errors []err
+ for _, e := range midl.Errors {
+ myError := err{
+ Name: e.Name,
+ doc: e.Doc,
+ }
+ errors = append(errors, myError)
+ }
+ return errors
+}
+
+// generates the index for the top of the markdown page
+func generateIndex(methods []funcDescriber, types []typeDescriber, errors []err, b bytes.Buffer) bytes.Buffer {
+ for _, method := range methods {
+ var inArgs []string
+ var outArgs []string
+ for _, inArg := range method.inputParams {
+ inArgs = append(inArgs, fmt.Sprintf("%s: %s", inArg.paramName, inArg.paramKind))
+
+ }
+ for _, outArg := range method.returnParams {
+ outArgs = append(outArgs, fmt.Sprintf("%s", outArg.paramKind))
+
+ }
+ b.WriteString(fmt.Sprintf("\n[func %s(%s) %s](#%s)\n", method.Name, strings.Join(inArgs, ", "), strings.Join(outArgs, ", "), method.Name))
+ }
+ for _, t := range types {
+ b.WriteString(fmt.Sprintf("[type %s](#%s)\n\n", t.Name, t.Name))
+ }
+ for _, e := range errors {
+ b.WriteString(fmt.Sprintf("[error %s](#%s)\n\n", e.Name, e.Name))
+ }
+ return b
+}
+
+// performs the output for defined methods
+func generateFuncDescriptions(methods []funcDescriber, b bytes.Buffer) bytes.Buffer {
+ for _, method := range methods {
+ b.WriteString(fmt.Sprintf("### <a name=\"%s\"></a>func %s\n", method.Name, method.Name))
+ var inArgs []string
+ var outArgs []string
+ for _, inArg := range method.inputParams {
+ inArgs = append(inArgs, fmt.Sprintf("%s: [%s](%s)", inArg.paramName, inArg.paramKind, typeToLink(inArg.paramKind)))
+ }
+ for _, outArg := range method.returnParams {
+ outArgs = append(outArgs, fmt.Sprintf("[%s](%s)", outArg.paramKind, typeToLink(outArg.paramKind)))
+ }
+ b.WriteString(fmt.Sprintf("<div style=\"background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;\">\n\nmethod %s(%s) %s</div>", method.Name, strings.Join(inArgs, ", "), strings.Join(outArgs, ", ")))
+ b.WriteString("\n")
+ b.WriteString(method.doc)
+ b.WriteString("\n")
+ }
+ return b
+}
+
+// performs the output for defined types/structs
+func generateTypeDescriptions(types []typeDescriber, b bytes.Buffer) bytes.Buffer {
+ for _, t := range types {
+ b.WriteString(fmt.Sprintf("### <a name=\"%s\"></a>type %s\n", t.Name, t.Name))
+ b.WriteString(fmt.Sprintf("\n%s\n", t.doc))
+ for _, i := range t.Attrs {
+ b.WriteString(fmt.Sprintf("\n%s [%s](%s)\n", i.Name, i.AttrType, typeToLink(i.AttrType)))
+ }
+ }
+ return b
+}
+
+// performs the output for defined errors
+func generateErrorDescriptions(errors []err, b bytes.Buffer) bytes.Buffer {
+ for _, e := range errors {
+ b.WriteString(fmt.Sprintf("### <a name=\"%s\"></a>type %s\n", e.Name, e.Name))
+ b.WriteString(fmt.Sprintf("\n%s\n", e.doc))
+ }
+ return b
+}
+
+func main() {
+ args := os.Args
+ if len(args) < 2 {
+ exit(fmt.Errorf("you must provide an input and output path"))
+ }
+ varlinkFile := args[1]
+ mdFile := args[2]
+
+ varlinkInput, err := readFileToString(varlinkFile)
+ if err != nil {
+ exit(err)
+ }
+ varlinkInput = strings.TrimRight(varlinkInput, "\n")
+
+ // Run the idl parser
+ midl, err := idl.New(varlinkInput)
+ if err != nil {
+ exit(err)
+ }
+
+ // Collect up the info from the idl
+ methods := getMethods(midl)
+ types := getTypes(midl)
+ errors := getErrors(midl)
+
+ out := bytes.Buffer{}
+ out.WriteString("## Index\n")
+ out = generateIndex(methods, types, errors, out)
+ out.WriteString("## Methods\n")
+ out = generateFuncDescriptions(methods, out)
+ out.WriteString("## Types\n")
+ out = generateTypeDescriptions(types, out)
+ out.WriteString("## Errors\n")
+ out = generateErrorDescriptions(errors, out)
+ ioutil.WriteFile(mdFile, out.Bytes(), 0755)
+}