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

feat: Render entry.go (second stage) #34

Merged
merged 23 commits into from
Mar 15, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
6ea5f9d
add EntryXml struct, render all missing functions for entry.go, exten…
sebastianczech Mar 11, 2024
4d70add
start work on service.go
sebastianczech Mar 11, 2024
401a470
refactor names in template for entry.go
sebastianczech Mar 11, 2024
53084e3
add not_present and from_version to SpecParamProfile
sebastianczech Mar 11, 2024
c5ff1b4
current service is only prepared for entry
sebastianczech Mar 11, 2024
5da312c
clear service template
sebastianczech Mar 11, 2024
2e011a7
render entry.go only for specs with entry
sebastianczech Mar 11, 2024
8e301c0
Merge branch 'main' into render-entry
sebastianczech Mar 11, 2024
48db70c
create structs for nested specs
sebastianczech Mar 11, 2024
07ccc14
generate content of function SpecifyEntry for specification with nest…
sebastianczech Mar 12, 2024
60af14e
generate content of function Normalize for specification with nested …
sebastianczech Mar 12, 2024
917a301
add function comments
sebastianczech Mar 12, 2024
2939d86
replace all string concatenation using "+" by function fmt.Sprintf()
sebastianczech Mar 13, 2024
b51801b
for item with type object, render []string, which will contain all me…
sebastianczech Mar 13, 2024
6461db6
refactor NormalizeAssignment(), SpecifyEntryAssignment(), fix some of…
sebastianczech Mar 13, 2024
30bcb0d
extend template functions after tests for service.yaml
sebastianczech Mar 13, 2024
743ac40
apply changes after review (#1)
sebastianczech Mar 14, 2024
f0e47db
remove comments
sebastianczech Mar 14, 2024
a0edfa2
use fmt.Errorf to return errors
sebastianczech Mar 14, 2024
e55a5be
apply changes after review (#2)
sebastianczech Mar 14, 2024
f6e4f92
refactor SpecMatchesFunction()
sebastianczech Mar 14, 2024
4df52fa
refactor funcs.go
sebastianczech Mar 15, 2024
0ff2d59
refactor structs.go
sebastianczech Mar 15, 2024
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
1 change: 1 addition & 0 deletions cmd/codegen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func parseFlags() Config {
return cfg
}

// runCommand executed command to generate code for SDK or Terraform
func runCommand(ctx context.Context, cmdType codegen.CommandType, cfg string) {
cmd, err := codegen.NewCommand(ctx, cmdType, cfg)
if err != nil {
Expand Down
4 changes: 3 additions & 1 deletion pkg/generate/assets.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"path/filepath"
)

// CopyAssets copy assets (static files) according to configuration
func CopyAssets(config *properties.Config) error {
for _, asset := range config.Assets {
files, err := listAssets(asset)
Expand All @@ -32,10 +33,10 @@ func CopyAssets(config *properties.Config) error {
return nil
}

// listAssets walk through directory and get list of all assets (static files)
func listAssets(asset *properties.Asset) ([]string, error) {
var files []string

// Walk through directory and get list of all files
err := filepath.WalkDir(asset.Source, func(path string, entry fs.DirEntry, err error) error {
if err != nil {
return err
Expand All @@ -52,6 +53,7 @@ func listAssets(asset *properties.Asset) ([]string, error) {
return files, nil
}

// copyAsset copy single asset, which may contain multiple files
func copyAsset(target string, asset *properties.Asset, files []string) error {
// Prepare destination path
destinationDir := target + "/" + asset.Destination
Expand Down
48 changes: 35 additions & 13 deletions pkg/generate/generator.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package generate

import (
"bytes"
"fmt"
"io"
"log"
"os"
"path/filepath"
Expand All @@ -18,6 +20,7 @@ type Creator struct {
Spec *properties.Normalization
}

// NewCreator initialize Creator instance
func NewCreator(goOutputDir, templatesDir string, spec *properties.Normalization) *Creator {
return &Creator{
GoOutputDir: goOutputDir,
Expand All @@ -26,6 +29,7 @@ func NewCreator(goOutputDir, templatesDir string, spec *properties.Normalization
}
}

// RenderTemplate loop through all templates, parse them and render content, which is saved to output file
func (c *Creator) RenderTemplate() error {
log.Println("Start rendering templates")

Expand All @@ -42,30 +46,40 @@ func (c *Creator) RenderTemplate() error {
return fmt.Errorf("error creating directories for %s: %w", filePath, err)
}

outputFile, err := os.Create(filePath)
if err != nil {
return fmt.Errorf("error creating file %s: %w", filePath, err)
}
defer outputFile.Close()

tmpl, err := c.parseTemplate(templateName)
if err != nil {
return fmt.Errorf("error parsing template %s: %w", templateName, err)
}

if err := tmpl.Execute(outputFile, c.Spec); err != nil {
var data bytes.Buffer
if err := tmpl.Execute(&data, c.Spec); err != nil {
return fmt.Errorf("error executing template %s: %w", templateName, err)
}
// If from template no data was rendered (e.g. for DNS spec entry should not be created),
// then we don't need to create empty file (e.g. `entry.go`) with no content
if data.Len() > 0 {
pimielowski marked this conversation as resolved.
Show resolved Hide resolved
outputFile, err := os.Create(filePath)
if err != nil {
return fmt.Errorf("error creating file %s: %w", filePath, err)
}
defer outputFile.Close()

_, err = io.Copy(outputFile, &data)
if err != nil {
return err
}
}
}
return nil
}


// createFullFilePath returns a full path for output file generated from template passed as argument to function
func (c *Creator) createFullFilePath(templateName string) string {
fileBaseName := strings.TrimSuffix(templateName, filepath.Ext(templateName))
return filepath.Join(c.GoOutputDir, filepath.Join(c.Spec.GoSdkPath...), fileBaseName+".go")
}

// listOfTemplates return list of templates defined in TemplatesDir
func (c *Creator) listOfTemplates() ([]string, error) {
var files []string
err := filepath.WalkDir(c.TemplatesDir, func(path string, entry os.DirEntry, err error) error {
Expand All @@ -86,11 +100,13 @@ func (c *Creator) listOfTemplates() ([]string, error) {
return files, nil
}

// makeAllDirs creates all required directories, which are in the file path
func (c *Creator) makeAllDirs(filePath string) error {
dirPath := filepath.Dir(filePath)
return os.MkdirAll(dirPath, os.ModePerm)
}

// createFile just create a file and return it
func (c *Creator) createFile(filePath string) (*os.File, error) {
outputFile, err := os.Create(filePath)
if err != nil {
Expand All @@ -99,21 +115,27 @@ func (c *Creator) createFile(filePath string) (*os.File, error) {
return outputFile, nil
}


// parseTemplate parse template passed as argument and with function map defined below
func (c *Creator) parseTemplate(templateName string) (*template.Template, error) {
templatePath := filepath.Join(c.TemplatesDir, templateName)
funcMap := template.FuncMap{
"packageName": translate.PackageName,
"locationType": translate.LocationType,
"specParamType": translate.SpecParamType,
"omitEmpty": translate.OmitEmpty,
"packageName": translate.PackageName,
"locationType": translate.LocationType,
"specParamType": translate.SpecParamType,
"xmlParamType": translate.XmlParamType,
"xmlTag": translate.XmlTag,
"specifyEntryAssignment": translate.SpecifyEntryAssignment,
"normalizeAssignment": translate.NormalizeAssignment,
"specMatchesFunction": translate.SpecMatchesFunction,
"omitEmpty": translate.OmitEmpty,
"contains": func(full, part string) bool {
return strings.Contains(full, part)
},
"subtract": func(a, b int) int {
return a - b
},
"asEntryXpath": translate.AsEntryXpath,
"nestedSpecs": translate.NestedSpecs,
}
return template.New(templateName).Funcs(funcMap).ParseFiles(templatePath)
}
1 change: 1 addition & 0 deletions pkg/properties/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ type Target struct {
TerraformProvider bool `json:"terraform_provider" yaml:"terraform_provider"`
}

// ParseConfig initialize Config instance using input data from YAML file
func ParseConfig(input []byte) (*Config, error) {
var ans Config
err := content.Unmarshal(input, &ans)
Expand Down
74 changes: 59 additions & 15 deletions pkg/properties/normalized.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,13 @@ type SpecParamItemsLength struct {
}

type SpecParamProfile struct {
Xpath []string `json:"xpath" yaml:"xpath"`
Type string `json:"type" yaml:"type,omitempty"`
Xpath []string `json:"xpath" yaml:"xpath"`
Type string `json:"type" yaml:"type,omitempty"`
NotPresent bool `json:"not_present" yaml:"not_present"`
FromVersion string `json:"from_version" yaml:"from_version"`
}

// GetNormalizations get list of all specs (normalizations)
func GetNormalizations() ([]string, error) {
_, loc, _, ok := runtime.Caller(0)
if !ok {
Expand Down Expand Up @@ -137,18 +140,34 @@ func GetNormalizations() ([]string, error) {
return files, nil
}

// ParseSpec parse single spec (unmarshal file), add name variants for locations and params, add default types for params
func ParseSpec(input []byte) (*Normalization, error) {
var spec Normalization

err := content.Unmarshal(input, &spec)
if err != nil {
sebastianczech marked this conversation as resolved.
Show resolved Hide resolved
return nil, err
}

err = spec.AddNameVariantsForLocation()
if err != nil {
return nil, err
}

err = spec.AddNameVariantsForParams()
if err != nil {
return nil, err
}

err = spec.AddDefaultTypesForParams()
if err != nil {
return nil, err
}

return &spec, err
}

// AddNameVariantsForLocation add name variants for location (under_score and CamelCase)
func (spec *Normalization) AddNameVariantsForLocation() error {
for key, location := range spec.Locations {
location.Name = &NameVariant{
Expand All @@ -167,6 +186,7 @@ func (spec *Normalization) AddNameVariantsForLocation() error {
return nil
}

// AddNameVariantsForParams recursively add name variants for params for nested specs
func AddNameVariantsForParams(name string, param *SpecParam) error {
param.Name = &NameVariant{
Underscore: name,
Expand All @@ -187,6 +207,7 @@ func AddNameVariantsForParams(name string, param *SpecParam) error {
return nil
}

// AddNameVariantsForParams add name variants for params (under_score and CamelCase)
func (spec *Normalization) AddNameVariantsForParams() error {
if spec.Spec != nil {
for key, param := range spec.Spec.Params {
Expand All @@ -203,27 +224,49 @@ func (spec *Normalization) AddNameVariantsForParams() error {
return nil
}

// AddDefaultTypesForParams ensures all SpecParams within Spec have a default type if not specified.
func (spec *Normalization) AddDefaultTypesForParams() error {
if spec.Spec == nil {
return nil
// AddDefaultTypesForParams recursively add default types for params for nested specs
func AddDefaultTypesForParams(param *SpecParam) error {
sebastianczech marked this conversation as resolved.
Show resolved Hide resolved
sebastianczech marked this conversation as resolved.
Show resolved Hide resolved
if param.Type == "" {
param.Type = "string"
}

setDefaultParamTypeForMap(spec.Spec.Params)
setDefaultParamTypeForMap(spec.Spec.OneOf)

return nil
if param.Spec != nil {
for _, childParam := range param.Spec.Params {
if err := AddDefaultTypesForParams(childParam); err != nil {
return err
}
}
for _, childParam := range param.Spec.OneOf {
if err := AddDefaultTypesForParams(childParam); err != nil {
return err
}
}
return nil
} else {
return nil
}
}

// setDefaultParamTypeForMap iterates over a map of SpecParam pointers, setting their Type to "string" if not specified.
func setDefaultParamTypeForMap(params map[string]*SpecParam) {
for _, param := range params {
if param.Type == "" {
param.Type = "string"
// AddDefaultTypesForParams ensures all params within Spec have a default type if not specified.
func (spec *Normalization) AddDefaultTypesForParams() error {
sebastianczech marked this conversation as resolved.
Show resolved Hide resolved
if spec.Spec != nil {
for _, childParam := range spec.Spec.Params {
if err := AddDefaultTypesForParams(childParam); err != nil {
return err
}
}
for _, childParam := range spec.Spec.OneOf {
if err := AddDefaultTypesForParams(childParam); err != nil {
return err
}
}
return nil
} else {
return nil
}
}

// Sanity basic checks for specification (normalization) e.g. check if at least 1 location is defined
func (spec *Normalization) Sanity() error {
if spec.Name == "" {
return errors.New("name is required")
Expand All @@ -238,6 +281,7 @@ func (spec *Normalization) Sanity() error {
return nil
}

// Validate validations for specification (normalization) e.g. check if XPath contain /
func (spec *Normalization) Validate() []error {
var checks []error

Expand Down
12 changes: 12 additions & 0 deletions pkg/properties/normalized_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ spec:
profiles:
- xpath:
- description
not_present: false
from_version: ""
spec: null
tags:
name:
Expand All @@ -285,6 +287,8 @@ spec:
- xpath:
- tag
type: member
not_present: false
from_version: ""
spec: null
one_of:
fqdn:
Expand All @@ -301,6 +305,8 @@ spec:
profiles:
- xpath:
- fqdn
not_present: false
from_version: ""
spec: null
ip_netmask:
name:
Expand All @@ -312,6 +318,8 @@ spec:
profiles:
- xpath:
- ip-netmask
not_present: false
from_version: ""
spec: null
ip_range:
name:
Expand All @@ -323,6 +331,8 @@ spec:
profiles:
- xpath:
- ip-range
not_present: false
from_version: ""
spec: null
ip_wildcard:
name:
Expand All @@ -334,6 +344,8 @@ spec:
profiles:
- xpath:
- ip-wildcard
not_present: false
from_version: ""
spec: null
`

Expand Down
Loading
Loading