From 32e48319f1ad777b0a05e239d1faa5f1a4445064 Mon Sep 17 00:00:00 2001 From: Daniel Shebib Date: Tue, 4 Jun 2024 15:38:55 -0500 Subject: [PATCH] Refactor API generator to include non-resource endpoints --- gen-apidocs/generators/api/config.go | 4 +- gen-apidocs/generators/html.go | 107 +++++++++++++++++++++------ gen-apidocs/generators/util.go | 1 + gen-apidocs/generators/writer.go | 31 ++++++++ 4 files changed, 119 insertions(+), 24 deletions(-) diff --git a/gen-apidocs/generators/api/config.go b/gen-apidocs/generators/api/config.go index 163a51c2c5..9dcffa7c83 100644 --- a/gen-apidocs/generators/api/config.go +++ b/gen-apidocs/generators/api/config.go @@ -262,7 +262,9 @@ func (c *Config) initOperations(specs []*loads.Document) error { if op, ok := c.Operations[target.ID]; !ok || op.Definition == nil { if !c.opExcluded(op.ID) { fmt.Printf("\033[31mNo Definition found for %s [%s].\033[0m\n", op.ID, op.Path) - } + } else { + fmt.Printf("Op excluded: %s\n", op.ID) + } } }) diff --git a/gen-apidocs/generators/html.go b/gen-apidocs/generators/html.go index 8ff0cc88fa..6ea4f284d3 100644 --- a/gen-apidocs/generators/html.go +++ b/gen-apidocs/generators/html.go @@ -250,6 +250,23 @@ func (h *HTMLWriter) WriteDefinitionsOverview() error { return nil } +func (h *HTMLWriter) WriteOrphanedOperationsOverview() error { + if err := writeStaticFile("_operations.html", h.SectionHeading("Operations")); err != nil { + return err + } + + item := TOCItem{ + Level: 1, + Title: "OPERATIONS", + Link: "operations", + File: "_operations.html", + } + h.TOC.Sections = append(h.TOC.Sections, &item) + h.currentTOCItem = &item + + return nil +} + func (h *HTMLWriter) WriteDefinition(d *api.Definition) error { fn := "_" + definitionFileName(d) + ".html" path := filepath.Join(api.IncludesDir, fn) @@ -293,6 +310,44 @@ func (h *HTMLWriter) WriteDefinition(d *api.Definition) error { return nil } +func (h *HTMLWriter) WriteOperation(o *api.Operation) error { + fn := "_" + operationFileName(o) + ".html" + path := filepath.Join(api.IncludesDir, fn) + f, err := os.Create(path) + if err != nil { + return err + } + defer f.Close() + + nvg := fmt.Sprintf("%s", o.ID) + linkID := getLink(nvg) + + oGroup, oVersion, oKind, _ := o.GetGroupVersionKindSub() + oApiVersion := api.ApiVersion(oVersion) + + if len(oGroup) > 0 { + nvg = h.gvkMarkup(oGroup, oApiVersion, oKind) + } + + fmt.Fprintf(f, "
\n", linkID) + defer fmt.Fprint(f, "
\n") + + fmt.Fprintf(f, "

%s

\n", nvg) + + item := TOCItem{ + Level: 2, + Title: nvg, + Link: linkID, + File: fn, + } + h.currentTOCItem.SubSections = append(h.currentTOCItem.SubSections, &item) + + h.WriteOperationBody(f, o, o.ID) + + return nil +} + + func (h *HTMLWriter) writeSamples(w io.Writer, d *api.Definition) { if d.Sample.Sample == "" { return @@ -426,6 +481,28 @@ func (h *HTMLWriter) writeResponseParams(w io.Writer, o *api.Operation) { fmt.Fprintf(w, "\n\n") } +func (h *HTMLWriter) WriteOperationBody(w io.Writer, o *api.Operation, opID string) { + if o.Definition != nil { + // Example requests + requests := o.GetExampleRequests() + if len(requests) > 0 { + h.writeOperationSample(w, true, opID, requests) + } + // Example responses + responses := o.GetExampleResponses() + if len(responses) > 0 { + h.writeOperationSample(w, false, opID, responses) + } + } + + fmt.Fprintf(w, "

%s

\n", o.Description()) + fmt.Fprintf(w, "

HTTP Request

\n") + fmt.Fprintf(w, "

%s

\n", o.GetDisplayHttp()) + + h.writeRequestParams(w, o) + h.writeResponseParams(w, o) +} + func (h *HTMLWriter) WriteResource(r *api.Resource) error { fn := "_" + conceptFileName(r.Definition) + ".html" path := filepath.Join(api.IncludesDir, fn) @@ -488,23 +565,23 @@ func (h *HTMLWriter) WriteResource(r *api.Resource) error { return nil } - for _, c := range r.Definition.OperationCategories { - if len(c.Operations) == 0 { + for _, oc := range r.Definition.OperationCategories { + if len(oc.Operations) == 0 { continue } - catID := strings.ReplaceAll(strings.ToLower(c.Name), " ", "-") + "-" + r.Definition.LinkID() + catID := strings.ReplaceAll(strings.ToLower(oc.Name), " ", "-") + "-" + r.Definition.LinkID() fmt.Fprintf(w, "
\n", catID) - fmt.Fprintf(w, "

%s

\n", c.Name) + fmt.Fprintf(w, "

%s

\n", oc.Name) ocItem := TOCItem{ Level: 3, - Title: c.Name, + Title: oc.Name, Link: catID, } resourceItem.SubSections = append(resourceItem.SubSections, &ocItem) - for _, o := range c.Operations { + for _, o := range oc.Operations { opID := strings.ReplaceAll(strings.ToLower(o.Type.Name), " ", "-") + "-" + r.Definition.LinkID() fmt.Fprintf(w, "
\n", opID) fmt.Fprintf(w, "

%s

\n", o.Type.Name) @@ -516,23 +593,7 @@ func (h *HTMLWriter) WriteResource(r *api.Resource) error { } ocItem.SubSections = append(ocItem.SubSections, &OPItem) - // Example requests - requests := o.GetExampleRequests() - if len(requests) > 0 { - h.writeOperationSample(w, true, opID, requests) - } - // Example responses - responses := o.GetExampleResponses() - if len(responses) > 0 { - h.writeOperationSample(w, false, opID, responses) - } - - fmt.Fprintf(w, "

%s

\n", o.Description()) - fmt.Fprintf(w, "

HTTP Request

\n") - fmt.Fprintf(w, "

%s

\n", o.GetDisplayHttp()) - - h.writeRequestParams(w, o) - h.writeResponseParams(w, o) + h.WriteOperationBody(w, o, opID); fmt.Fprint(w, "
\n") } diff --git a/gen-apidocs/generators/util.go b/gen-apidocs/generators/util.go index a9a0d709bc..4ff30a970b 100644 --- a/gen-apidocs/generators/util.go +++ b/gen-apidocs/generators/util.go @@ -69,4 +69,5 @@ func PrintInfo(config *api.Config) { } } } + } diff --git a/gen-apidocs/generators/writer.go b/gen-apidocs/generators/writer.go index b307d141e8..445305492b 100644 --- a/gen-apidocs/generators/writer.go +++ b/gen-apidocs/generators/writer.go @@ -39,7 +39,9 @@ type DocWriter interface { WriteResourceCategory(name, file string) error WriteResource(r *api.Resource) error WriteDefinitionsOverview() error + WriteOrphanedOperationsOverview() error WriteDefinition(d *api.Definition) error + WriteOperation(o *api.Operation) error WriteOldVersionsOverview() error Finalize() error } @@ -94,6 +96,30 @@ func GenerateFiles() error { } } + // Write orphaned operation endpoints + orphanedIDs := make([]string, 0) + for id, o := range config.Operations { + if o.Definition == nil { + orphanedIDs = append(orphanedIDs, id) + } + } + + if len(orphanedIDs) > 0 { + if err := writer.WriteOrphanedOperationsOverview(); err != nil { + return err + } + + sort.Strings(orphanedIDs) + + for _, opKey := range orphanedIDs { + if err := writer.WriteOperation(config.Operations[opKey]); + err != nil { + return err + } + } + } + + if err := writer.WriteDefinitionsOverview(); err != nil { return err } @@ -160,6 +186,11 @@ func definitionFileName(d *api.Definition) string { return fmt.Sprintf("%s_%s_%s_definition", name, d.Version, d.Group) } +func operationFileName(o *api.Operation) string { + name := "generated_" + strings.ToLower(strings.ReplaceAll(o.ID, ".", "_")) + return fmt.Sprintf("%s_operation", name) +} + func conceptFileName(d *api.Definition) string { name := "generated_" + strings.ToLower(strings.ReplaceAll(d.Name, ".", "_")) return fmt.Sprintf("%s_%s_%s_concept", name, d.Version, d.Group)