Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add generator for openapi #27

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,5 +216,20 @@ EOF

### Make a new Kind

1. Add to openapi.yaml
2. Generate the new structs/clients (`make generate`)
Generator scripts can be used to auto generate a new Kind. Run the following command to generate a new kind:
```shell
go run ./scripts/generator.go --kind KindName
```

Following manual changes are required to run the application successfully:
- `pkg/api/presenters/kind.go` : Add case statement for the kind
- `pkg/api/presenters/path.go` : Add case statement for the kind
- `pkg/api/presenters/` : Add presenters file (if missing)
- `cmd/trex/environments/service_types.go` : Add new service locator for the kind
- `cmd/trex/environments/types.go` : Add service locator and use `cmd/trex/environments/framework.go` to instantiate
- `cmd/trex/server/routes.go` : Add service routes (if missing)
- Add validation methods in handler if required
- `pkg/db/migrations/migration_structs.go` : Add migration name
- `test/factories.go` : Add helper functions

Here's a reference MR for the same : https://github.com/openshift-online/rh-trex/pull/25
2 changes: 2 additions & 0 deletions openapi/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ paths:
$ref: '#/components/schemas/Error'
parameters:
- $ref: '#/components/parameters/id'
# AUTO-ADD NEW PATHS
components:
securitySchemes:
Bearer:
Expand Down Expand Up @@ -267,6 +268,7 @@ components:
properties:
species:
type: string
# AUTO-ADD NEW SCHEMAS
parameters:
id:
name: id
Expand Down
77 changes: 76 additions & 1 deletion scripts/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"bufio"
"bytes"
"flag"
"fmt"
"github.com/spf13/pflag"
Expand All @@ -24,7 +25,13 @@ TODO: all of it can be better
*/

var (
kind string = "Asteroid"
kind string = "Asteroid"
openapiEndpointStart string = "# NEW ENDPOINT START"
openapiEndpointEnd string = "# NEW ENDPOINT END"
openApiSchemaStart string = "# NEW SCHEMA START"
openApiSchemaEnd string = "# NEW SCHEMA END"
openApiEndpointMatchingLine string = " # AUTO-ADD NEW PATHS"
openApiSchemaMatchingLine string = " # AUTO-ADD NEW SCHEMAS"
)

func init() {
Expand All @@ -46,6 +53,8 @@ func main() {
"mock",
"migration",
"test",
"handlers",
"openapi-kind",
}

for _, nm := range templates {
Expand Down Expand Up @@ -78,6 +87,8 @@ func main() {
outPath = fmt.Sprintf("pkg/db/migrations/%s_add_%s.go", k.ID, k.KindLowerPlural)
} else if strings.Contains(nm, "test") {
outPath = fmt.Sprintf("test/integration/%s_test.go", k.KindLowerPlural)
} else if strings.Contains(nm, "openapi") {
outPath = fmt.Sprintf("openapi/openapi.%s.yaml", k.KindLowerPlural)
} else {
outPath = fmt.Sprintf("pkg/%s/%s.go", nm, k.KindLowerSingular)
}
Expand All @@ -92,6 +103,10 @@ func main() {
}
w.Flush()
f.Sync()

if strings.Contains(nm, "openapi") {
modifyOpenapi("openapi/openapi.yaml", fmt.Sprintf("openapi/openapi.%s.yaml", k.KindLowerPlural))
}
}
}

Expand All @@ -109,3 +124,63 @@ type myWriter struct {
KindLowerSingular string
ID string
}

func modifyOpenapi(mainPath string, kindPath string) {
endpointStrings := readBetweenLines(kindPath, openapiEndpointStart, openapiEndpointEnd)
kindFileName := strings.Split(kindPath, "/")[1]
for _, line := range endpointStrings {
endpointStr := strings.TrimSpace(line)
endpointStr = strings.Replace(endpointStr, "/", "~1", -1)
endpointStr = strings.Replace(endpointStr, ":", "", -1)
refPath := fmt.Sprintf(` $ref: '%s#/paths/%s'`, kindFileName, endpointStr)
pathsLine := fmt.Sprintf("%s%s", line, refPath)
writeAfterLine(mainPath, openApiEndpointMatchingLine, pathsLine)
}
schemaStrings := readBetweenLines(kindPath, openApiSchemaStart, openApiSchemaEnd)
for _, line := range schemaStrings {
schemaStr := strings.TrimSpace(line)
schemaStr = strings.Replace(schemaStr, ":", "", -1)
refPath := fmt.Sprintf(` $ref: '%s#/components/schemas/%s'`, kindFileName, schemaStr)
pathsLine := fmt.Sprintf("%s%s", line, refPath)
writeAfterLine(mainPath, openApiSchemaMatchingLine, pathsLine)
}
}

func readBetweenLines(path string, startLine string, endLine string) []string {
readFile, err := os.Open(path)
if err != nil {
fmt.Println(err)
}
fileScanner := bufio.NewScanner(readFile)
fileScanner.Split(bufio.ScanLines)
readFlag := false
var totalMatches []string
var matchedString strings.Builder
for fileScanner.Scan() {
trimmed := strings.TrimSpace(fileScanner.Text())
if trimmed == startLine {
readFlag = true
} else if trimmed == endLine {
readFlag = false
totalMatches = append(totalMatches, matchedString.String())
matchedString.Reset()
} else if readFlag {
matchedString.WriteString(fileScanner.Text() + "\n")
}
}
readFile.Close()
return totalMatches
}

func writeAfterLine(path string, matchingLine string, lineToWrite string) {
input, err := os.ReadFile(path)
if err != nil {
panic(err)
}
_ = strings.Replace(string(input), matchingLine, lineToWrite+"\n"+matchingLine, -1)
output := bytes.Replace(input, []byte(matchingLine), []byte(lineToWrite+"\n"+matchingLine), -1)
if err = os.WriteFile(path, output, 0666); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
Loading