Skip to content

Commit

Permalink
feat: adds ability to import apidoc for a siteid #345
Browse files Browse the repository at this point in the history
  • Loading branch information
srinandan committed Dec 6, 2023
1 parent 7725dde commit 4ae1307
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 123 deletions.
17 changes: 7 additions & 10 deletions cmd/apidocs/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package apidocs

import (
"fmt"
"internal/apiclient"

"internal/client/apidocs"
Expand All @@ -31,20 +32,16 @@ var ImpCmd = &cobra.Command{
return apiclient.SetApigeeOrg(org)
},
RunE: func(cmd *cobra.Command, args []string) error {
return apidocs.Import(conn, folder)
if siteid == "" {
return fmt.Errorf("siteid is a mandatory parameter")
}
return apidocs.Import(siteid, folder)
},
}

var (
conn int
filePath string
)

func init() {
ImpCmd.Flags().StringVarP(&filePath, "folder", "f",
"", "Folder containing apidocs.json and apidocs_<siteid>_<id>.json files")
ImpCmd.Flags().IntVarP(&conn, "conn", "c",
4, "Number of connections")
ImpCmd.Flags().StringVarP(&folder, "folder", "f",
"", "Folder containing site_<siteid>.json and apidocs_<siteid>_<id>.json files")

_ = ImpCmd.MarkFlagRequired("file")
}
164 changes: 51 additions & 113 deletions internal/client/apidocs/apidocs.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,11 @@ import (
"net/url"
"os"
"path"
"path/filepath"
"strconv"
"strings"
"sync"

"internal/apiclient"
"internal/client/sites"
"internal/clilog"
)

type Action uint8
Expand All @@ -51,14 +48,14 @@ type listapidocs struct {
NextPageToken string `json:"nextPageToken,omitempty"`
}

type documentation struct {
Status string `json:"status,omitempty"`
Message string `json:"message,omitempty"`
RequestID string `json:"requestId,omitempty"`
Data apidocsdata `json:"data,omitempty"`
type apidocsdata struct {
Status string `json:"status,omitempty"`
Message string `json:"message,omitempty"`
RequestID string `json:"requestId,omitempty"`
Data documentation `json:"data,omitempty"`
}

type apidocsdata struct {
type documentation struct {
OasDocumentation *oasDocumentation `json:"oasDocumentation,omitempty"`
GraphqlDocumentation *graphqlDocumentation `json:"graphqlDocumentation,omitempty"`
}
Expand Down Expand Up @@ -241,11 +238,10 @@ func Export(folder string) (err error) {
}

pageToken := ""
listdocs := listapidocs{}

for _, siteid := range siteids {
l := listapidocs{}
for {
l := listapidocs{}
listRespBytes, err := List(siteid, maxPageSize, pageToken)
if err != nil {
return fmt.Errorf("failed to fetch apidocs: %w", err)
Expand All @@ -254,7 +250,6 @@ func Export(folder string) (err error) {
if err != nil {
return fmt.Errorf("failed to unmarshall: %w", err)
}
listdocs.Data = append(listdocs.Data, l.Data...)
pageToken = l.NextPageToken
// write apidocs Documentation
for _, data := range l.Data {
Expand All @@ -271,152 +266,95 @@ func Export(folder string) (err error) {
break
}
}
respBody, err := json.Marshal(l.Data)
if err != nil {
return err
}
respBody, _ = apiclient.PrettifyJSON(respBody)
if err = apiclient.WriteByteArrayToFile(path.Join(folder, "site_"+siteid+".json"), false, respBody); err != nil {
return err
}
}

respBody, err := json.Marshal(listdocs.Data)
if err != nil {
return err
}
respBody, _ = apiclient.PrettifyJSON(respBody)
return apiclient.WriteByteArrayToFile(path.Join(folder, "apidocs.json"), false, respBody)
return nil
}

func Import(conn int, folder string) (err error) {
entities, err := readAPIDocsFile(path.Join(folder, "apidocs.json"))
func Import(siteid string, folder string) (err error) {
var errs []string

docsList, err := readAPIDocsDataFile(path.Join(folder, "site_"+siteid+".json"))
if err != nil {
clilog.Error.Println("Error reading file: ", err)
return err
}
for _, entity := range entities {
respBodyApiDocs, e := Create(entity.SiteID, entity.Title, entity.Description,
strconv.FormatBool(entity.Published),
strconv.FormatBool(entity.AnonAllowed), entity.ApiProductName,
strconv.FormatBool(entity.RequireCallbackUrl), entity.ImageUrl, entity.CategoryIDs)
if e != nil {
errs = append(errs, e.Error())
continue
}
d := documentation{}
if e = json.Unmarshal(respBodyApiDocs, &d); e != nil {
errs = append(errs, e.Error())
for _, doc := range docsList {
// 1. create the apidoc object
_, err = Create(siteid, doc.Title, doc.Description, strconv.FormatBool(doc.Published),
strconv.FormatBool(doc.AnonAllowed), doc.ApiProductName,
strconv.FormatBool(doc.RequireCallbackUrl), doc.ImageUrl, doc.CategoryIDs)
if err != nil {
errs = append(errs, err.Error())
continue

}
// get all the files that match this siteid
siteIDDocsList := []string{}
err = filepath.Walk(folder, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
return nil
}
if filepath.Ext(path) != ".json" {
return nil
}
matchCriteria := fmt.Sprintf("apidocs_%s_*.json", entity.SiteID)
if ok, _ := filepath.Match(matchCriteria, path); ok {
siteIDDocsList = append(siteIDDocsList, path)
}
return nil
})
// 2. find the documentation associated with this site
documentationFileName := fmt.Sprintf("apidocs_%s_%s", siteid, doc.ID)
apidocument, err := readAPIDocumentationFile(documentationFileName)
if err != nil {
return err
}
if len(siteIDDocsList) == 0 {
clilog.Warning.Printf("No API Docs files were found for siteid %s in the folder", entity.SiteID)
errs = append(errs, err.Error())
continue
}
clilog.Debug.Printf("Found %d API Docs for siteid %s in the folder\n", len(siteIDDocsList), entity.SiteID)
for _, siteIDDoc := range siteIDDocsList {
doc, err := readAPIDocumentationFile(siteIDDoc)
if apidocument.Data.GraphqlDocumentation != nil {
schema, err := base64.StdEncoding.DecodeString(apidocument.Data.GraphqlDocumentation.Schema.Contents)
if err != nil {
errs = append(errs, err.Error())
continue
}
if doc.Data.GraphqlDocumentation != nil {
schema, err := base64.StdEncoding.DecodeString(doc.Data.GraphqlDocumentation.Schema.Contents)
if err != nil {
errs = append(errs, err.Error())
continue
}
_, err = UpdateDocumentation(entity.SiteID, entity.ID, doc.Data.OasDocumentation.Spec.DisplayName, "",
string(schema), doc.Data.GraphqlDocumentation.EndpointUri)
} else {
oasdoc, err := base64.StdEncoding.DecodeString(doc.Data.OasDocumentation.Spec.Contents)
if err != nil {
errs = append(errs, err.Error())
continue
}
_, err = UpdateDocumentation(entity.SiteID, entity.ID, doc.Data.OasDocumentation.Spec.DisplayName, string(oasdoc),
"", "")
}
_, err = UpdateDocumentation(siteid, doc.ID, apidocument.Data.OasDocumentation.Spec.DisplayName, "",
string(schema), apidocument.Data.GraphqlDocumentation.EndpointUri)
} else {
oasdoc, err := base64.StdEncoding.DecodeString(apidocument.Data.OasDocumentation.Spec.Contents)
if err != nil {
errs = append(errs, err.Error())
continue
}
_, err = UpdateDocumentation(siteid, doc.ID, apidocument.Data.OasDocumentation.Spec.DisplayName, string(oasdoc),
"", "")
}
if err != nil {
errs = append(errs, err.Error())
continue
}
}

if len(errs) > 0 {
return errors.New(strings.Join(errs, "\n"))
}
return nil
}

func importDocs(wg *sync.WaitGroup, jobs <-chan string, errs chan<- error) {
defer wg.Done()
for {
job, ok := <-jobs
if !ok {
return
}
jsonFile, err := os.Open(job)
if err != nil {
errs <- err
}
byteValue, err := io.ReadAll(jsonFile)
if err != nil {
errs <- err
}
docsFile := documentation{}
err = json.Unmarshal(byteValue, &docsFile)
if err != nil {
errs <- err
}
jsonFile.Close()
}
}

func getArrayStr(str []string) string {
tmp := strings.Join(str, ",")
tmp = strings.ReplaceAll(tmp, ",", "\",\"")
return tmp
}

func readAPIDocsFile(filePath string) (d []data, err error) {
jsonFile, err := os.Open(filePath)
func readAPIDocumentationFile(fileName string) (a apidocsdata, err error) {
jsonFile, err := os.Open(fileName)
if err != nil {
return nil, err
return a, err
}

defer jsonFile.Close()

byteValue, err := io.ReadAll(jsonFile)
content, err := io.ReadAll(jsonFile)
if err != nil {
return nil, err
return a, err
}

err = json.Unmarshal(byteValue, &d)

err = json.Unmarshal(content, &a)
if err != nil {
return nil, err
return a, err
}
return d, nil
return a, nil
}

func readAPIDocumentationFile(fileName string) (d documentation, err error) {
func readAPIDocsDataFile(fileName string) (d []data, err error) {
jsonFile, err := os.Open(fileName)
if err != nil {
return d, err
Expand Down

0 comments on commit 4ae1307

Please sign in to comment.