From 05ecb0513211ebeb4cacd36b9f85ce688efd019a Mon Sep 17 00:00:00 2001 From: Matthieu 'JP' DERASSE Date: Wed, 10 Aug 2022 15:40:37 +0000 Subject: [PATCH] feat(init): continue on template --- helpers/api_types/base/generate_makefile.go | 13 ---- .../go_swagger/create_directories.go | 4 ++ .../go_swagger/create_project_skeleton.go | 29 ++++++++- .../go_swagger/execute_go_swagger.go | 59 ++++++++++++++++++ .../go_swagger/generate_api_yamls.go | 60 +++++++++++++++++++ .../api_types/go_swagger/generate_makefile.go | 9 +-- .../api_types/go_swagger/generate_readme.go | 38 ++++++++++++ .../api_types/go_swagger/get_user_input.go | 4 +- .../go_swagger/initialize_go_module.go | 39 ++++++++++++ helpers/api_types/interface.go | 1 - models/config.go | 2 +- models/user_input_params.go | 2 +- templates/go-swagger/.empty | 0 templates/go-swagger/Readme.md.tmpl | 3 + templates/go-swagger/api.yaml.tmpl | 13 ++++ .../go-swagger/api/001-general.yaml.tmpl | 25 ++++++++ .../go-swagger/api/002-monitoring.yaml.tmpl | 48 +++++++++++++++ 17 files changed, 325 insertions(+), 24 deletions(-) delete mode 100644 helpers/api_types/base/generate_makefile.go create mode 100644 helpers/api_types/go_swagger/execute_go_swagger.go create mode 100644 helpers/api_types/go_swagger/generate_api_yamls.go create mode 100644 helpers/api_types/go_swagger/generate_readme.go create mode 100644 helpers/api_types/go_swagger/initialize_go_module.go delete mode 100644 templates/go-swagger/.empty create mode 100644 templates/go-swagger/Readme.md.tmpl create mode 100644 templates/go-swagger/api.yaml.tmpl create mode 100644 templates/go-swagger/api/001-general.yaml.tmpl create mode 100644 templates/go-swagger/api/002-monitoring.yaml.tmpl diff --git a/helpers/api_types/base/generate_makefile.go b/helpers/api_types/base/generate_makefile.go deleted file mode 100644 index 1e17c5e..0000000 --- a/helpers/api_types/base/generate_makefile.go +++ /dev/null @@ -1,13 +0,0 @@ -package base - -import ( - "github.com/juju/errors" - - "git.home.m-and-m.ovh/mderasse/gouick/helpers" - "git.home.m-and-m.ovh/mderasse/gouick/models" -) - -// GenerateMakefile will generate makefile based on the given config. -func (a APIType) GenerateMakefile(path string, config *models.Config) error { - return errors.NotImplementedf("%s not implemented for %s", helpers.GetCurrentFuncName(), a.GetName()) -} diff --git a/helpers/api_types/go_swagger/create_directories.go b/helpers/api_types/go_swagger/create_directories.go index 0221a11..be06b64 100644 --- a/helpers/api_types/go_swagger/create_directories.go +++ b/helpers/api_types/go_swagger/create_directories.go @@ -16,7 +16,11 @@ var standardDirectories = []string{ "cmd", "models", "pkg", + "pkg/api", + "pkg/helper", + "pkg/transform", "restapi", + "restapi/operations", "testdata", } diff --git a/helpers/api_types/go_swagger/create_project_skeleton.go b/helpers/api_types/go_swagger/create_project_skeleton.go index c84c8a1..bf41c4b 100644 --- a/helpers/api_types/go_swagger/create_project_skeleton.go +++ b/helpers/api_types/go_swagger/create_project_skeleton.go @@ -20,13 +20,38 @@ func (a APIType) CreateProjectSkeleton(path string, config *models.Config) error } // Generate Makefile - err = a.GenerateMakefile(path, config) + err = a.generateMakefile(path, config) if err != nil { log.Error("Fail to generate Makefile") return errors.Trace(err) } // Generate Readme - // Generate api.yaml + err = a.generateReadme(path, config) + if err != nil { + log.Error("Fail to generate Readme.md") + return errors.Trace(err) + } + + // Generate api yaml files + err = a.generateAPIYamls(path, config) + if err != nil { + log.Error("Fail to generate API Yaml files") + return errors.Trace(err) + } + + // init Go Module + err = a.initializeGoModule(path, config) + if err != nil { + log.Error("Fail to initialize Go Module") + return errors.Trace(err) + } + + // Launch Go Swagger + err = a.executeGoSwagger(path, config) + if err != nil { + log.Error("Fail to Execute Go Swagger") + return errors.Trace(err) + } return nil } diff --git a/helpers/api_types/go_swagger/execute_go_swagger.go b/helpers/api_types/go_swagger/execute_go_swagger.go new file mode 100644 index 0000000..b8961c1 --- /dev/null +++ b/helpers/api_types/go_swagger/execute_go_swagger.go @@ -0,0 +1,59 @@ +package go_swagger + +import ( + "os" + "os/exec" + "path/filepath" + + "github.com/juju/errors" + + "git.home.m-and-m.ovh/mderasse/gouick/helpers" + "git.home.m-and-m.ovh/mderasse/gouick/models" + + log "github.com/sirupsen/logrus" +) + +// executeGoSwagger will merge api yaml files and launch go-swagger generator. +func (a APIType) executeGoSwagger(path string, config *models.Config) error { + log.Debugf("Starting %s - %s", a.GetName(), helpers.GetCurrentFuncName()) + + // making sure that we are in the project directory + if err := os.Chdir(path); err != nil { + log.Error("Fail to move to the path") + return errors.Trace(err) + } + + // merge api files. + // TODO: use filepath.Glob and avoid an ugly bin sh. + cmd := exec.Command("/bin/sh", "-c", "swagger mixin --format=yaml --output=api-temp.yaml api.yaml api/*") + output, err := cmd.CombinedOutput() + if err != nil { + log.Error("fail to execute 'swagger mixin --format=yaml --output=api-temp.yaml api.yaml api/*'") + return errors.Trace(err) + } + + log.Debugf("'swagger mixin --format=yaml --output=api-temp.yaml api.yaml api/*' returned the following output: %s", string(output)) + + // cleanup some directory to avoid issues. + for _, directory := range []string{"models", "restapi/operations"} { + err := helpers.RemoveDirectoryContent(filepath.Join(path, directory)) + if err != nil { + log.Errorf("fail to delete content of directory '%s'", directory) + return errors.Trace(err) + } + } + + // generate server files + cmd = exec.Command("swagger", "generate", "server", "--spec=api-temp.yaml") + output, err = cmd.CombinedOutput() + if err != nil { + log.Error("fail to execute 'swagger generate server --spec=api-temp.yaml'") + return errors.Trace(err) + } + + log.Debugf("'swagger generate server --spec=api-temp.yaml' returned the following output: %s", string(output)) + + // TODO: execute 'go get ./...' + + return nil +} diff --git a/helpers/api_types/go_swagger/generate_api_yamls.go b/helpers/api_types/go_swagger/generate_api_yamls.go new file mode 100644 index 0000000..a7369a9 --- /dev/null +++ b/helpers/api_types/go_swagger/generate_api_yamls.go @@ -0,0 +1,60 @@ +package go_swagger + +import ( + "path/filepath" + + "github.com/juju/errors" + + "git.home.m-and-m.ovh/mderasse/gouick/helpers" + "git.home.m-and-m.ovh/mderasse/gouick/models" + + log "github.com/sirupsen/logrus" +) + +type apiYamlTemplate struct { + ProjectDescription string + ProjectName string + ProjectOwner string +} + +// generateAPIYamls will generate a readme based on the given config. +// Launched only at project init. +func (a APIType) generateAPIYamls(path string, config *models.Config) error { + log.Debugf("Starting %s - %s", a.GetName(), helpers.GetCurrentFuncName()) + + type templateFileStruct struct { + savePath string + templatePath string + } + + templateFileList := []templateFileStruct{ + { + savePath: filepath.Join(path, "api.yaml"), + templatePath: filepath.Join(templateDirectory, "api.yaml.tmpl"), + }, + { + savePath: filepath.Join(path, "api/001-general.yaml"), + templatePath: filepath.Join(templateDirectory, "api/001-general.yaml.tmpl"), + }, + { + savePath: filepath.Join(path, "api/001-monitoring.yaml"), + templatePath: filepath.Join(templateDirectory, "api/002-monitoring.yaml.tmpl"), + }, + } + + data := apiYamlTemplate{ + ProjectDescription: config.ProjectDescription, + ProjectName: config.ProjectName, + ProjectOwner: config.ProjectOwner, + } + + for _, templateFile := range templateFileList { + + err := helpers.WriteTemplate(templateFile.templatePath, templateFile.savePath, data) + if err != nil { + return errors.Trace(err) + } + } + + return nil +} diff --git a/helpers/api_types/go_swagger/generate_makefile.go b/helpers/api_types/go_swagger/generate_makefile.go index 7f30335..e0d58c2 100644 --- a/helpers/api_types/go_swagger/generate_makefile.go +++ b/helpers/api_types/go_swagger/generate_makefile.go @@ -12,18 +12,19 @@ import ( log "github.com/sirupsen/logrus" ) -type makefile struct { +type makefileTemplate struct { AppNameKebabCase string } -// GenerateMakefile will generate makefile based on the given config. -func (a APIType) GenerateMakefile(path string, config *models.Config) error { +// generateMakefile will generate makefile based on the given config. +// Launched only at project init or on force. +func (a APIType) generateMakefile(path string, config *models.Config) error { log.Debugf("Starting %s - %s", a.GetName(), helpers.GetCurrentFuncName()) templatePath := filepath.Join(templateDirectory, "Makefile.tmpl") savePath := filepath.Join(path, "Makefile") - data := makefile{ + data := makefileTemplate{ AppNameKebabCase: strcase.ToKebab(config.ProjectName), } diff --git a/helpers/api_types/go_swagger/generate_readme.go b/helpers/api_types/go_swagger/generate_readme.go new file mode 100644 index 0000000..c1f6e53 --- /dev/null +++ b/helpers/api_types/go_swagger/generate_readme.go @@ -0,0 +1,38 @@ +package go_swagger + +import ( + "path/filepath" + + "github.com/juju/errors" + + "git.home.m-and-m.ovh/mderasse/gouick/helpers" + "git.home.m-and-m.ovh/mderasse/gouick/models" + + log "github.com/sirupsen/logrus" +) + +type readmeTemplate struct { + ProjectDescription string + ProjectName string +} + +// generateReadme will generate a readme based on the given config. +// Launched only at project init. +func (a APIType) generateReadme(path string, config *models.Config) error { + log.Debugf("Starting %s - %s", a.GetName(), helpers.GetCurrentFuncName()) + + templatePath := filepath.Join(templateDirectory, "Readme.md.tmpl") + savePath := filepath.Join(path, "Readme.md") + + data := readmeTemplate{ + ProjectDescription: config.ProjectDescription, + ProjectName: config.ProjectName, + } + + err := helpers.WriteTemplate(templatePath, savePath, data) + if err != nil { + return errors.Trace(err) + } + + return nil +} diff --git a/helpers/api_types/go_swagger/get_user_input.go b/helpers/api_types/go_swagger/get_user_input.go index 7f5875c..586d13c 100644 --- a/helpers/api_types/go_swagger/get_user_input.go +++ b/helpers/api_types/go_swagger/get_user_input.go @@ -32,8 +32,8 @@ func (a APIType) GetInitializeUserInput(params *models.Config) (*models.Config, if !isInGoPath { log.Debug("We are not in GoPath, ask extra info") goModulePath := helpers.StringInput() - log.Info("Go Module name:") - params.ModuleName = &goModulePath + log.Info("Go Module path:") + params.ModulePath = &goModulePath } log.Info("Do you want to enable database models auto generation ?") diff --git a/helpers/api_types/go_swagger/initialize_go_module.go b/helpers/api_types/go_swagger/initialize_go_module.go new file mode 100644 index 0000000..e73488a --- /dev/null +++ b/helpers/api_types/go_swagger/initialize_go_module.go @@ -0,0 +1,39 @@ +package go_swagger + +import ( + "os" + "os/exec" + + "github.com/juju/errors" + + "git.home.m-and-m.ovh/mderasse/gouick/helpers" + "git.home.m-and-m.ovh/mderasse/gouick/models" + + log "github.com/sirupsen/logrus" +) + +// initializeGoModule will launch a go mod init. +func (a APIType) initializeGoModule(path string, config *models.Config) error { + log.Debugf("Starting %s - %s", a.GetName(), helpers.GetCurrentFuncName()) + + if err := os.Chdir(path); err != nil { + log.Error("Fail to move to the path") + return errors.Trace(err) + } + + modulePath := "" + if config.ModulePath != nil { + modulePath = *config.ModulePath + } + + cmd := exec.Command("go", "mod", "init", modulePath) + output, err := cmd.CombinedOutput() + if err != nil { + log.Errorf("fail to execute go mod init %s", modulePath) + return errors.Trace(err) + } + + log.Debugf("go mod init %s returned the following output: %s", modulePath, string(output)) + + return nil +} diff --git a/helpers/api_types/interface.go b/helpers/api_types/interface.go index 0244773..5573f71 100644 --- a/helpers/api_types/interface.go +++ b/helpers/api_types/interface.go @@ -6,7 +6,6 @@ import "git.home.m-and-m.ovh/mderasse/gouick/models" type APITypeInterface interface { CheckInitialize() error CreateProjectSkeleton(path string, config *models.Config) error - GenerateMakefile(path string, config *models.Config) error GetInitializeUserInput(params *models.Config) (*models.Config, error) GetName() models.APITypeName } diff --git a/models/config.go b/models/config.go index fd34ee7..6c2cb94 100644 --- a/models/config.go +++ b/models/config.go @@ -6,7 +6,7 @@ type Config struct { ProjectDescription string `yaml:"project_description"` ProjectOwner string `yaml:"project_owner"` ProjectType APITypeName `yaml:"project_type"` - ModuleName *string `yaml:"module_name"` + ModulePath *string `yaml:"module_name"` Features FeaturesConfig `yaml:"features"` } diff --git a/models/user_input_params.go b/models/user_input_params.go index a19f70c..8e89157 100644 --- a/models/user_input_params.go +++ b/models/user_input_params.go @@ -3,7 +3,7 @@ package models // UserInputParams is a struct containing all fields that can be useful for project generation. type UserInputParams struct { DatabaseModels bool - GoModuleName *string + GoModulePath *string ProjectDescription string ProjectDirectory string ProjectName string diff --git a/templates/go-swagger/.empty b/templates/go-swagger/.empty deleted file mode 100644 index e69de29..0000000 diff --git a/templates/go-swagger/Readme.md.tmpl b/templates/go-swagger/Readme.md.tmpl new file mode 100644 index 0000000..a0c0d24 --- /dev/null +++ b/templates/go-swagger/Readme.md.tmpl @@ -0,0 +1,3 @@ +# {{ .ProjectName }} + +{{ .ProjectDescription }} diff --git a/templates/go-swagger/api.yaml.tmpl b/templates/go-swagger/api.yaml.tmpl new file mode 100644 index 0000000..1112775 --- /dev/null +++ b/templates/go-swagger/api.yaml.tmpl @@ -0,0 +1,13 @@ +--- +swagger: "2.0" +info: + version: "1.0" + title: "{{ .ProjectName }}" + description: "{{ .ProjectDescription }}" + contact: + email: "{{ .ProjectOwner }}" +consumes: + - "application/json" +produces: + - "application/json" +basePath: "/" \ No newline at end of file diff --git a/templates/go-swagger/api/001-general.yaml.tmpl b/templates/go-swagger/api/001-general.yaml.tmpl new file mode 100644 index 0000000..eda771f --- /dev/null +++ b/templates/go-swagger/api/001-general.yaml.tmpl @@ -0,0 +1,25 @@ +--- +definitions: + # + # GENERAL TYPEs + # + Error: + type: object + properties: + code: + type: integer + format: int64 + message: + type: string + Metadata: + type: object + required: + - this + - total + properties: + total: + type: integer + format: int64 + this: + type: integer + format: int64 diff --git a/templates/go-swagger/api/002-monitoring.yaml.tmpl b/templates/go-swagger/api/002-monitoring.yaml.tmpl new file mode 100644 index 0000000..e2c615c --- /dev/null +++ b/templates/go-swagger/api/002-monitoring.yaml.tmpl @@ -0,0 +1,48 @@ +--- +tags: + - name: Monitoring + description: Monitoring routes +definitions: + MonPing: + type: object + properties: + status: + type: object + x-nullable: true + properties: + database: + type: boolean + description: State of the database + application: + type: boolean + description: State of the application + details: + type: object + x-nullable: true + properties: + app_version: + type: string + description: Application version + git_hash: + type: string + description: Git hash of the last commit +paths: + # + # SECTION : MONITORING + # + /mon/ping: + get: + tags: + - Monitoring + summary: Health check + description: Return Health status of the app with additionnal info such as the version + operationId: getMonPing + responses: + 200: + description: Health OK + schema: + $ref: "#/definitions/MonPing" + default: + description: Default error message + schema: + $ref: "#/definitions/Error"