From ac7df8be2de99f59bdc0b2dea243656711473a36 Mon Sep 17 00:00:00 2001 From: Matthieu 'JP' DERASSE Date: Thu, 29 Sep 2022 20:04:37 +0000 Subject: [PATCH] feat(template): Refactor template standard variable and implement dockerfile --- cmd/generateDocker.go | 35 +++++++++++--- cmd/init.go | 24 ++++++---- go.mod | 1 - go.sum | 1 - helpers/api_types/base/generate_dockerfile.go | 13 +++++ helpers/api_types/go_swagger/common.go | 47 +++++++++++++++++++ .../go_swagger/generate_dockerfile.go | 33 +++++++++++++ .../api_types/go_swagger/generate_launcher.go | 23 +-------- .../api_types/go_swagger/generate_makefile.go | 23 +-------- .../api_types/go_swagger/generate_readme.go | 14 ++---- helpers/api_types/go_swagger/go_swagger.go | 5 +- helpers/api_types/go_swagger/yaml.go | 24 ++-------- helpers/api_types/interface.go | 1 + templates/go-swagger/Dockerfile.tmpl | 25 ++++++++++ templates/go-swagger/Readme.md.tmpl | 4 +- templates/go-swagger/api.yaml.tmpl | 16 +++---- 16 files changed, 191 insertions(+), 98 deletions(-) create mode 100644 helpers/api_types/base/generate_dockerfile.go create mode 100644 helpers/api_types/go_swagger/common.go create mode 100644 helpers/api_types/go_swagger/generate_dockerfile.go create mode 100644 templates/go-swagger/Dockerfile.tmpl diff --git a/cmd/generateDocker.go b/cmd/generateDocker.go index a2852ca..ed0c980 100644 --- a/cmd/generateDocker.go +++ b/cmd/generateDocker.go @@ -5,20 +5,43 @@ Copyright © 2022 Matthieu Derasse package cmd import ( - "fmt" - + "git.home.m-and-m.ovh/mderasse/gouick/helpers/api_types" "github.com/spf13/cobra" + + log "github.com/sirupsen/logrus" ) // dockerCmd represents the docker command. var dockerCmd = &cobra.Command{ Use: "docker", - Short: "Generate Dockerfile for API & Workers", - Run: func(cmd *cobra.Command, args []string) { - fmt.Println("docker called") - }, + Short: "Generate Dockerfile & co for API, Crons and Workers", + Run: runGenerateDockerAction, } func init() { generateCmd.AddCommand(dockerCmd) } + +// runGenerateDockerAction will generate the Dockerfile & co for the current project. +func runGenerateDockerAction(cmd *cobra.Command, args []string) { + log.Debugf("Starting command GenerateDocker") + + currentPath, config, err := loadProjectAndConfig() + if err != nil { + return + } + + apiType, err := api_types.GetAPIType(config.ProjectType) + if err != nil { + log.Error("Impossible to load that API Type generator") + return + } + + // Generate Dockerfile + log.Info("Generating Dockerfile") + err = apiType.GenerateDockerfile(currentPath, config) + if err != nil { + log.Errorf("Fail to generate Dockerfile. The following error happen: %s", err.Error()) + return + } +} diff --git a/cmd/init.go b/cmd/init.go index 73773f7..1d97376 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -131,13 +131,13 @@ func runInitAction(cmd *cobra.Command, args []string) { // ask project contact config.ProjectContact = models.ProjectContactStruct{} - log.Info("Mail address of the developer team:") - config.ProjectContact.Email = input.Mail(true) - log.Info("Name of the team:") config.ProjectContact.Name = input.String(true) - log.Info("URL of the contact informatino of the team:") + log.Info("Mail address of the developer team:") + config.ProjectContact.Email = input.Mail(true) + + log.Info("URL of the contact information of the team:") config.ProjectContact.URL = input.String(false) // launch GetInitializeUserInput from selected api type @@ -193,6 +193,14 @@ func runInitAction(cmd *cobra.Command, args []string) { return } + // Create API Skeleton + log.Info("Creating API skeleton") + err = apiType.CreateProjectSkeleton(projectDirPath, config) + if err != nil { + log.Errorf("Fail to create the project skeleton. The following error happen: %s", err.Error()) + return + } + // Generate Makefile log.Info("Generating Makefile") err = apiType.GenerateMakefile(projectDirPath, config) @@ -209,11 +217,11 @@ func runInitAction(cmd *cobra.Command, args []string) { return } - // Create API Skeleton - log.Info("Creating API skeleton") - err = apiType.CreateProjectSkeleton(projectDirPath, config) + // Generate Launcher + log.Info("Generating Launcher") + err = apiType.GenerateLauncher(projectDirPath, config) if err != nil { - log.Errorf("Fail to create the project skeleton. The following error happen: %s", err.Error()) + log.Errorf("Fail to generate launcher.sh. The following error happen: %s", err.Error()) return } } diff --git a/go.mod b/go.mod index d2ba5a8..411f864 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,6 @@ go 1.17 require ( github.com/blang/semver v3.5.1+incompatible github.com/go-swagger/go-swagger v0.29.0 - github.com/iancoleman/strcase v0.2.0 github.com/jessevdk/go-flags v1.5.0 github.com/juju/errors v1.0.0 github.com/sirupsen/logrus v1.8.1 diff --git a/go.sum b/go.sum index 9f204f2..5d89759 100644 --- a/go.sum +++ b/go.sum @@ -400,7 +400,6 @@ github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOn github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE= github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk= github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= -github.com/iancoleman/strcase v0.2.0 h1:05I4QRnGpI0m37iZQRuskXh+w77mr6Z41lwQzuHLwW0= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= diff --git a/helpers/api_types/base/generate_dockerfile.go b/helpers/api_types/base/generate_dockerfile.go new file mode 100644 index 0000000..588dacb --- /dev/null +++ b/helpers/api_types/base/generate_dockerfile.go @@ -0,0 +1,13 @@ +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" +) + +// GenerateDockerfile will generate dockerfile based on the given config. +func (a APIType) GenerateDockerfile(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/common.go b/helpers/api_types/go_swagger/common.go new file mode 100644 index 0000000..fa4ef95 --- /dev/null +++ b/helpers/api_types/go_swagger/common.go @@ -0,0 +1,47 @@ +package go_swagger + +import ( + "github.com/juju/errors" + + "git.home.m-and-m.ovh/mderasse/gouick/models" + + log "github.com/sirupsen/logrus" +) + +type stdTemplateStruct struct { + categorizedProcess + Config *models.Config +} + +type categorizedProcess struct { + APIs []*models.Process + Crons []*models.Process + Workers []*models.Process +} + +// getStdTemplate will generate the "basic" struct we will provide to a template. +func (a APIType) getStdTemplate(path string, config *models.Config) (*stdTemplateStruct, error) { + + data := stdTemplateStruct{ + Config: config, + } + + processes, err := a.getProcesses(path) + if err != nil { + log.Error("Fail to list processes") + return nil, errors.Trace(err) + } + + for _, process := range processes { + switch process.Type { + case models.ProcessType_API: + data.APIs = append(data.APIs, process) + case models.ProcessType_CRON: + data.Crons = append(data.Crons, process) + case models.ProcessType_WORKER: + data.Workers = append(data.Workers, process) + } + } + + return &data, nil +} diff --git a/helpers/api_types/go_swagger/generate_dockerfile.go b/helpers/api_types/go_swagger/generate_dockerfile.go new file mode 100644 index 0000000..9965cc3 --- /dev/null +++ b/helpers/api_types/go_swagger/generate_dockerfile.go @@ -0,0 +1,33 @@ +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" +) + +// GenerateDockerfile will generate a Dockerfile based on the given config. +func (a APIType) GenerateDockerfile(path string, config *models.Config) error { + log.Debugf("Starting %s - %s", a.GetName(), helpers.GetCurrentFuncName()) + + templatePath := filepath.Join(templateDirectory, "Dockerfile.tmpl") + savePath := filepath.Join(path, "Dockerfile") + + data, err := a.getStdTemplate(path, config) + if err != nil { + log.Error("Fail to generate standard template variable") + return errors.Trace(err) + } + + err = helpers.WriteTemplate(templatePath, savePath, data) + if err != nil { + return errors.Trace(err) + } + + return nil +} diff --git a/helpers/api_types/go_swagger/generate_launcher.go b/helpers/api_types/go_swagger/generate_launcher.go index 432aba0..2d9ea58 100644 --- a/helpers/api_types/go_swagger/generate_launcher.go +++ b/helpers/api_types/go_swagger/generate_launcher.go @@ -11,12 +11,6 @@ import ( log "github.com/sirupsen/logrus" ) -type launcherTemplate struct { - APIs []*models.Process - Crons []*models.Process - Workers []*models.Process -} - // GenerateLauncher will generate a launcher.sh based on the files found in cmd directory. func (a APIType) GenerateLauncher(path string, config *models.Config) error { log.Debugf("Starting %s - %s", a.GetName(), helpers.GetCurrentFuncName()) @@ -24,25 +18,12 @@ func (a APIType) GenerateLauncher(path string, config *models.Config) error { templatePath := filepath.Join(templateDirectory, "launcher.sh.tmpl") savePath := filepath.Join(path, "launcher.sh") - data := launcherTemplate{} - - processes, err := a.getProcesses(path) + data, err := a.getStdTemplate(path, config) if err != nil { - log.Error("Fail to list processes") + log.Error("Fail to generate standard template variable") return errors.Trace(err) } - for _, process := range processes { - switch process.Type { - case models.ProcessType_API: - data.APIs = append(data.APIs, process) - case models.ProcessType_CRON: - data.Crons = append(data.Crons, process) - case models.ProcessType_WORKER: - data.Workers = append(data.Workers, process) - } - } - err = helpers.WriteTemplate(templatePath, savePath, data) if err != nil { return errors.Trace(err) diff --git a/helpers/api_types/go_swagger/generate_makefile.go b/helpers/api_types/go_swagger/generate_makefile.go index a21c622..24fd070 100644 --- a/helpers/api_types/go_swagger/generate_makefile.go +++ b/helpers/api_types/go_swagger/generate_makefile.go @@ -11,12 +11,6 @@ import ( log "github.com/sirupsen/logrus" ) -type makefileTemplate struct { - APIs []*models.Process - Crons []*models.Process - Workers []*models.Process -} - // 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 { @@ -25,25 +19,12 @@ func (a APIType) GenerateMakefile(path string, config *models.Config) error { templatePath := filepath.Join(templateDirectory, "Makefile.tmpl") savePath := filepath.Join(path, "Makefile") - data := makefileTemplate{} - - processes, err := a.getProcesses(path) + data, err := a.getStdTemplate(path, config) if err != nil { - log.Error("Fail to list processes") + log.Error("Fail to generate standard template variable") return errors.Trace(err) } - for _, process := range processes { - switch process.Type { - case models.ProcessType_API: - data.APIs = append(data.APIs, process) - case models.ProcessType_CRON: - data.Crons = append(data.Crons, process) - case models.ProcessType_WORKER: - data.Workers = append(data.Workers, process) - } - } - err = helpers.WriteTemplate(templatePath, savePath, data) if err != nil { return errors.Trace(err) diff --git a/helpers/api_types/go_swagger/generate_readme.go b/helpers/api_types/go_swagger/generate_readme.go index 97d92ad..59caeb9 100644 --- a/helpers/api_types/go_swagger/generate_readme.go +++ b/helpers/api_types/go_swagger/generate_readme.go @@ -11,11 +11,6 @@ import ( 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 { @@ -24,12 +19,13 @@ func (a APIType) GenerateReadme(path string, config *models.Config) error { templatePath := filepath.Join(templateDirectory, "Readme.md.tmpl") savePath := filepath.Join(path, "Readme.md") - data := readmeTemplate{ - ProjectDescription: config.ProjectDescription, - ProjectName: config.ProjectName, + data, err := a.getStdTemplate(path, config) + if err != nil { + log.Error("Fail to generate standard template variable") + return errors.Trace(err) } - err := helpers.WriteTemplate(templatePath, savePath, data) + err = helpers.WriteTemplate(templatePath, savePath, data) if err != nil { return errors.Trace(err) } diff --git a/helpers/api_types/go_swagger/go_swagger.go b/helpers/api_types/go_swagger/go_swagger.go index d87dc7b..cac6c09 100644 --- a/helpers/api_types/go_swagger/go_swagger.go +++ b/helpers/api_types/go_swagger/go_swagger.go @@ -90,7 +90,10 @@ func (a APIType) goSwaggerGenerate(path string) error { Server: &generate.Server{}, } generateCmd.Server.Shared.Spec = flags.Filename(filepath.Join(path, mergeYamlFileName)) - generateCmd.Server.Shared.Target = flags.Filename(path) + //generateCmd.Server.Shared.Target = flags.Filename(path) + generateCmd.Server.ServerPackage = "restapi" + generateCmd.Server.Models.ModelPackage = "models" + generateCmd.Server.Operations.APIPackage = "operations" generateCmd.Server.Shared.StrictResponders = true return generateCmd.Server.Execute(nil) diff --git a/helpers/api_types/go_swagger/yaml.go b/helpers/api_types/go_swagger/yaml.go index 915820c..467a2ed 100644 --- a/helpers/api_types/go_swagger/yaml.go +++ b/helpers/api_types/go_swagger/yaml.go @@ -12,18 +12,6 @@ import ( log "github.com/sirupsen/logrus" ) -type apiYamlTemplate struct { - ProjectDescription string - ProjectName string - ProjectContact apiYamlContact -} - -type apiYamlContact struct { - Email string - Name string - URL string -} - // createDefaultAPIYamls will generate the main api yaml file based on the given config. // Launched only at project init. func (a APIType) createDefaultAPIYamls(path string, config *models.Config) error { @@ -49,14 +37,10 @@ func (a APIType) createDefaultAPIYamls(path string, config *models.Config) error }, } - data := apiYamlTemplate{ - ProjectDescription: config.ProjectDescription, - ProjectName: config.ProjectName, - ProjectContact: apiYamlContact{ - Email: config.ProjectContact.Email, - Name: config.ProjectContact.Name, - URL: config.ProjectContact.URL, - }, + data, err := a.getStdTemplate(path, config) + if err != nil { + log.Error("Fail to generate standard template variable") + return errors.Trace(err) } for _, templateFile := range templateFileList { diff --git a/helpers/api_types/interface.go b/helpers/api_types/interface.go index 3eecac8..a58e4a8 100644 --- a/helpers/api_types/interface.go +++ b/helpers/api_types/interface.go @@ -6,6 +6,7 @@ import "git.home.m-and-m.ovh/mderasse/gouick/models" type APITypeInterface interface { CheckInitialize() error CreateProjectSkeleton(path string, config *models.Config) error + GenerateDockerfile(path string, config *models.Config) error GenerateLauncher(path string, config *models.Config) error GenerateMakefile(path string, config *models.Config) error GenerateReadme(path string, config *models.Config) error diff --git a/templates/go-swagger/Dockerfile.tmpl b/templates/go-swagger/Dockerfile.tmpl new file mode 100644 index 0000000..81f3b71 --- /dev/null +++ b/templates/go-swagger/Dockerfile.tmpl @@ -0,0 +1,25 @@ +# Code generated by gouick; DO NOT EDIT. +FROM alpine + +LABEL maintainer="{{.Config.ProjectContact.Name}} <{{.Config.ProjectContact.Email}}>" + +RUN apk add --no-cache ca-certificates + +USER nobody + +COPY launcher.sh \ +{{- range .APIs }} + {{.Binary}} \ +{{- end }} +{{- range .Crons }} + {{.Binary}} \ +{{- end }} +{{- range .Workers }} + {{.Binary}} \ +{{- end }} + /app/ + +# expose port 8080 +EXPOSE 8080 + +CMD [ "/app/launcher.sh" ] diff --git a/templates/go-swagger/Readme.md.tmpl b/templates/go-swagger/Readme.md.tmpl index a0c0d24..69120d0 100644 --- a/templates/go-swagger/Readme.md.tmpl +++ b/templates/go-swagger/Readme.md.tmpl @@ -1,3 +1,3 @@ -# {{ .ProjectName }} +# {{ .Config.ProjectName }} -{{ .ProjectDescription }} +{{ .Config.ProjectDescription }} diff --git a/templates/go-swagger/api.yaml.tmpl b/templates/go-swagger/api.yaml.tmpl index 98e44a7..5465932 100644 --- a/templates/go-swagger/api.yaml.tmpl +++ b/templates/go-swagger/api.yaml.tmpl @@ -2,16 +2,16 @@ swagger: "2.0" info: version: "1.0" - title: "{{ .ProjectName }}" - description: "{{ .ProjectDescription }}" + title: "{{ .Config.ProjectName }}" + description: "{{ .Config.ProjectDescription }}" contact: - name: "{{ .ProjectContact.Name }}" - email: "{{ .ProjectContact.Email }}" -{{if .ProjectContact.URL }} - url: "{{ .ProjectContact.URL }}" -{{end}} + name: "{{ .Config.ProjectContact.Name }}" + email: "{{ .Config.ProjectContact.Email }}" +{{- if .Config.ProjectContact.URL }} + url: "{{ .Config.ProjectContact.URL }}" +{{- end }} consumes: - "application/json" produces: - "application/json" -basePath: "/" \ No newline at end of file +basePath: "/"