diff --git a/app/cmd/docker.go b/app/cmd/docker.go index 3954c8d..1810498 100644 --- a/app/cmd/docker.go +++ b/app/cmd/docker.go @@ -34,4 +34,3 @@ var CmdDocker = cli.Command{ func runDockerDefault(ctx *cli.Context) error { return docker.RunComposePs(ctx) } - diff --git a/app/cmd/docker/build.go b/app/cmd/docker/build.go index 418231f..0378106 100644 --- a/app/cmd/docker/build.go +++ b/app/cmd/docker/build.go @@ -19,5 +19,3 @@ func RunComposeBuild(cmd *cli.Context) error { compose.ExecComposerBuild(ctx) return nil } - - diff --git a/app/cmd/docker/debug.go b/app/cmd/docker/debug.go index 9ecf7d9..93a5f33 100644 --- a/app/cmd/docker/debug.go +++ b/app/cmd/docker/debug.go @@ -18,4 +18,3 @@ func RunComposeDebug(cmd *cli.Context) error { compose.ExecComposerDebug(ctx) return nil } - diff --git a/app/cmd/docker/down.go b/app/cmd/docker/down.go index e05f0f4..905ae46 100644 --- a/app/cmd/docker/down.go +++ b/app/cmd/docker/down.go @@ -18,4 +18,3 @@ func RunComposeDown(cmd *cli.Context) error { compose.ExecComposerDown(ctx) return nil } - diff --git a/app/cmd/docker/logs.go b/app/cmd/docker/logs.go index ae3835a..f5ea87e 100644 --- a/app/cmd/docker/logs.go +++ b/app/cmd/docker/logs.go @@ -8,7 +8,7 @@ import ( var CmdComposeLogs = cli.Command{ Name: "logs", - Aliases: []string{"l"}, + Aliases: []string{"l"}, Usage: "logs from containers", Description: `Get fqn docker image defined as main service in config file`, Action: RunComposeLogs, @@ -19,4 +19,3 @@ func RunComposeLogs(cmd *cli.Context) error { compose.ExecComposerLogs(ctx, cmd.Args()) return nil } - diff --git a/app/cmd/docker/pull.go b/app/cmd/docker/pull.go index 3d1a076..f1e1ac5 100644 --- a/app/cmd/docker/pull.go +++ b/app/cmd/docker/pull.go @@ -18,4 +18,3 @@ func RunComposePull(cmd *cli.Context) error { compose.ExecComposerPull(ctx) return nil } - diff --git a/app/cmd/docker/restart.go b/app/cmd/docker/restart.go index 08b5ae1..72ab283 100644 --- a/app/cmd/docker/restart.go +++ b/app/cmd/docker/restart.go @@ -18,4 +18,3 @@ func RunComposeRestart(cmd *cli.Context) error { compose.ExecComposerRestart(ctx) return nil } - diff --git a/app/cmd/docker/run.go b/app/cmd/docker/run.go index 097520e..fab808a 100644 --- a/app/cmd/docker/run.go +++ b/app/cmd/docker/run.go @@ -23,4 +23,3 @@ func RunComposeRun(cmd *cli.Context) error { } return nil } - diff --git a/app/cmd/docker/shell.go b/app/cmd/docker/shell.go index f27ca21..d10afa7 100644 --- a/app/cmd/docker/shell.go +++ b/app/cmd/docker/shell.go @@ -19,4 +19,3 @@ func RunComposeShell(cmd *cli.Context) error { compose.ExecComposerShell(ctx) return nil } - diff --git a/app/cmd/docker/stop.go b/app/cmd/docker/stop.go index 1624261..d1dfe20 100644 --- a/app/cmd/docker/stop.go +++ b/app/cmd/docker/stop.go @@ -18,5 +18,3 @@ func RunComposeStop(cmd *cli.Context) error { compose.ExecComposerStop(ctx) return nil } - - diff --git a/app/cmd/docker/up.go b/app/cmd/docker/up.go index 4196b78..f5b0392 100644 --- a/app/cmd/docker/up.go +++ b/app/cmd/docker/up.go @@ -20,4 +20,3 @@ func RunComposeUp(cmd *cli.Context) error { compose.ExecComposerLogs(ctx, cmd.Args()) return nil } - diff --git a/app/cmd/docker/uponce.go b/app/cmd/docker/uponce.go index 70c57c1..abe9ed1 100644 --- a/app/cmd/docker/uponce.go +++ b/app/cmd/docker/uponce.go @@ -18,4 +18,3 @@ func RunComposeUpOnce(cmd *cli.Context) error { compose.ExecComposerUpOnce(ctx) return nil } - diff --git a/app/cmd/init.go b/app/cmd/init.go index add9f5e..c034e35 100644 --- a/app/cmd/init.go +++ b/app/cmd/init.go @@ -1,10 +1,12 @@ package cmd import ( - "fmt" "github.com/urfave/cli/v2" "html/template" + "ledo/app/helper" + "ledo/app/modules/compose" "ledo/app/modules/context" + "ledo/app/modules/dockerfile" "ledo/app/modules/interact" "ledo/app/templates" "log" @@ -21,20 +23,88 @@ var CmdInit = cli.Command{ } func runInitLedo(cmd *cli.Context) error { - config, _ := context.LoadConfigFile() + var advRun bool + config, err := context.LoadConfigFile() + if err != nil { + return err + } + data, err := interact.InitLedoProject(config.Docker) + if err != nil { + return err + } + tpl, err := template.New("tpl").Parse(templates.LedoConfigurationFileTemplate) + if err != nil { + return err + } + if err != nil { log.Fatalln(err) } - err = tpl.Execute(os.Stdout, data) + f, err := os.Create("./.ledo.yml") if err != nil { - panic(err) + return err } - advRun := interact.InitAdvancedConfigurationAsk() - fmt.Printf("%v", advRun) + err = tpl.Execute(f, data) + if err != nil { + return err + } + advRun = false + // advRun := interact.InitAdvancedConfigurationAsk("Run advanced docker mode configuration?") + if advRun == true { + ctx := context.InitCommand(cmd) + dConf, _ := interact.InitDocker() + err = dockerfile.CreateDockerFile(dConf) + if err != nil { + return err + } + + projectComposeConfig := helper.DockerProjectCfg{} + projectComposeConfig.DockerBaseImage = dConf.DockerBaseImage + + var dockerComposeServices []helper.DockerProjectAdditionalServiceCfg + var dockerComposeModeConfig []helper.DockerComposeModeCfg + + + for _, composeMode := range interact.PredefinedDockerComposeModes { + var configMode bool + + if composeMode == "base" { + configMode = true + } else { + configMode = interact.InitAdvancedConfigurationAsk("Configure "+composeMode+" stack?") + } + + if configMode == true { + for { + serviceCfg, _ := interact.CreateDockerService() + serviceCfg.DockerServiceMode = composeMode + dockerComposeServices = append(dockerComposeServices, serviceCfg) + addAnother := interact.InitAdvancedConfigurationAsk("Add another service do " + composeMode + " stack?") + if addAnother == false { + break + } + } + composeFilename := "./docker/docker-compose.yml" + if composeMode != "base" { + composeFilename = "./docker/docker-compose."+composeMode+".yml" + } + mdCfg := helper.DockerComposeModeCfg{ + DockerComposeName: composeFilename, + DockerComposeServices: dockerComposeServices, + } + dockerComposeModeConfig = append(dockerComposeModeConfig, mdCfg) + } + } + projectComposeConfig.DockerComposeModes = dockerComposeModeConfig + + err = compose.CreateComposeFile(ctx, projectComposeConfig, "base") + if err != nil { + return err + } + } + return err } - - diff --git a/app/cmd/mode.go b/app/cmd/mode.go index 0501b55..57e664d 100644 --- a/app/cmd/mode.go +++ b/app/cmd/mode.go @@ -21,4 +21,3 @@ var CmdMode = cli.Command{ func runModeDefault(cmd *cli.Context) error { return mode.RunSelectMode(cmd) } - diff --git a/app/cmd/mode/list.go b/app/cmd/mode/list.go index e430fb7..fc4b1af 100644 --- a/app/cmd/mode/list.go +++ b/app/cmd/mode/list.go @@ -17,6 +17,3 @@ func RunModeList(cmd *cli.Context) error { ctx.Mode.PrintListModes() return nil } - - - diff --git a/app/cmd/mode/select.go b/app/cmd/mode/select.go index 867340d..faa106d 100644 --- a/app/cmd/mode/select.go +++ b/app/cmd/mode/select.go @@ -24,5 +24,3 @@ func RunSelectMode(cmd *cli.Context) error { interact.SelectMode(ctx, "") return nil } - - diff --git a/app/helper/docker_configuration.go b/app/helper/docker_configuration.go new file mode 100644 index 0000000..c90768e --- /dev/null +++ b/app/helper/docker_configuration.go @@ -0,0 +1,77 @@ +package helper + +type DockerServiceEnvironment struct { + EnvironmentName string `yaml:"environment_name,omitempty" json:"environmentName"` + EnvironmentValue string `yaml:"environment_value,omitempty" json:"environmentValue"` +} + +type DockerProjectAdditionalServiceCfg struct { + DockerServiceMode string `yaml:"docker_service_mode,omitempty" json:"dockerServiceMode"` + DockerServiceType string `yaml:"docker_service_type,omitempty" json:"dockerServiceType"` + DockerServiceImage string `yaml:"docker_service_image,omitempty" json:"dockerServiceImage"` + DockerServiceTag string `yaml:"docker_service_tag,omitempty" json:"dockerServiceTag"` + DockerServiceEnvironment []DockerServiceEnvironment `yaml:"docker_service_environment,omitempty" json:"dockerServiceEnvironment"` +} + +type DockerComposeModeCfg struct { + DockerComposeName string `yaml:"docker_compose_name,omitempty" json:"dockerComposeName"` + DockerComposeServices []DockerProjectAdditionalServiceCfg `yaml:"docker_compose_services,omitempty" json:"dockerComposeServices"` +} + +type DockerProjectCfg struct { + HasDockerRegistry bool `yaml:"has_docker_registry,omitempty" json:"hasDockerRegistry"` + DockerBaseImage string `yaml:"docker_base_image,omitempty" json:"dockerBaseImage"` + DockerBaseTag string `yaml:"docker_base_tag,omitempty" json:"dockerBaseTag"` + DockerComposeModes []DockerComposeModeCfg `yaml:"docker_compose_modes,omitempty" json:"dockerComposeModes"` +} + +//var PredefinedAdditionalService = []DockerProjectAdditionalServiceCfg{ +// { +// DockerServiceMode: "base", +// DockerServiceType: "database", +// DockerServiceImage: "mariadb", +// DockerServiceTag: "", +// DockerServiceEnvironment: []DockerServiceEnvironment{ +// { +// EnvironmentName: "DB_NAME", +// EnvironmentValue: "dev", +// }, +// }, +// }, +// { +// DockerServiceMode: "dev", +// DockerServiceType: "tools", +// DockerServiceImage: "dbgate/dbgate", +// DockerServiceTag: "", +// }, +// { +// DockerServiceMode: "dev", +// DockerServiceType: "tools", +// DockerServiceImage: "mailhog/mailhog", +// DockerServiceTag: "", +// }, +// { +// DockerServiceMode: "dev", +// DockerServiceType: "tools", +// DockerServiceImage: "minio/minio", +// DockerServiceTag: "", +// }, +// { +// DockerServiceMode: "base", +// DockerServiceType: "security", +// DockerServiceImage: "authelia/authelia", +// DockerServiceTag: "", +// }, +// { +// DockerServiceMode: "base", +// DockerServiceType: "infrastructure", +// DockerServiceImage: "traefik", +// DockerServiceTag: "", +// }, +// { +// DockerServiceMode: "base", +// DockerServiceType: "infrastructure", +// DockerServiceImage: "portainer", +// DockerServiceTag: "", +// }, +//} diff --git a/app/helper/popupar_images.go b/app/helper/popupar_images.go deleted file mode 100644 index a980640..0000000 --- a/app/helper/popupar_images.go +++ /dev/null @@ -1,2 +0,0 @@ -package helper - diff --git a/app/modules/compose/compose.go b/app/modules/compose/compose.go index 47fa29b..53b8d5f 100644 --- a/app/modules/compose/compose.go +++ b/app/modules/compose/compose.go @@ -41,41 +41,41 @@ func CheckDockerComposeVersion() { } func MergeComposerFiles(filenames ...string) (string, error) { - var resultValues map[string]interface{} + var resultValues map[string]interface{} if len(filenames) <= 0 { - return "", errors.New("You must provide at least one filename for reading Values") - } + return "", errors.New("You must provide at least one filename for reading Values") + } - for _, filename := range filenames { + for _, filename := range filenames { - var override map[string]interface{} - bs, err := ioutil.ReadFile(filename) - if err != nil { - log.Print(err) - continue - } - if err := yaml.Unmarshal(bs, &override); err != nil { - log.Print(err) - continue - } + var override map[string]interface{} + bs, err := ioutil.ReadFile(filename) + if err != nil { + log.Print(err) + continue + } + if err := yaml.Unmarshal(bs, &override); err != nil { + log.Print(err) + continue + } - if resultValues == nil { - resultValues = override - } else { - for k, v := range override { - resultValues[k] = v - } - } - } + if resultValues == nil { + resultValues = override + } else { + for k, v := range override { + resultValues[k] = v + } + } + } - bs, err := yaml.Marshal(resultValues) - if err != nil { - log.Fatal(err) - return "", err - } + bs, err := yaml.Marshal(resultValues) + if err != nil { + log.Fatal(err) + return "", err + } - return string(bs), nil + return string(bs), nil } func ShowDockerImageFQN(ctx *context.LedoContext) string { @@ -107,7 +107,6 @@ func ExecComposerBuild(ctx *context.LedoContext) { ctx.ExecCmd("docker-compose", args[0:]) } - func ExecComposerDown(ctx *context.LedoContext) { args := ctx.ComposeArgs args = append(args, "down") @@ -166,7 +165,3 @@ func ExecComposerUpOnce(ctx *context.LedoContext) { args = append(args, "up", "--force-recreate", "--renew-anon-volumes", "--abort-on-container-exit", "--exit-code-from", ctx.Config.Docker.MainService) ctx.ExecCmd("docker-compose", args[0:]) } - - - - diff --git a/app/modules/compose/create_compose.go b/app/modules/compose/create_compose.go new file mode 100644 index 0000000..6f528b8 --- /dev/null +++ b/app/modules/compose/create_compose.go @@ -0,0 +1,42 @@ +package compose + +import ( + "html/template" + "ledo/app/helper" + "ledo/app/modules/context" + "ledo/app/templates" + "log" + "os" +) + +func CreateComposeFile(ctx *context.LedoContext, dockerProject helper.DockerProjectCfg, composeMode string) error { + if _, err := os.Stat("./docker"); os.IsNotExist(err) { + err := os.Mkdir("./docker", 0755) + if err != nil { + log.Fatal(err) + } + } + + log.Printf("%v", dockerProject) + + templateName := templates.LedoDockerComposeBaseFileTemplate_base + + tpl, err := template.New("dockercompose").Parse(templateName) + if err != nil { + log.Fatalln(err) + } + + composeFilename := "./docker/docker-compose.yml" + + if composeMode != "base" { + composeFilename = "./docker/docker-compose."+composeMode+".yml" + } + + f, err := os.Create(composeFilename) + if err != nil { + log.Println("create file: ", err) + } + err = tpl.Execute(f, ctx) + + return err +} \ No newline at end of file diff --git a/app/modules/config/ledofile.go b/app/modules/config/ledofile.go index 0ac461e..4a14c4a 100644 --- a/app/modules/config/ledofile.go +++ b/app/modules/config/ledofile.go @@ -6,9 +6,9 @@ import ( ) type LedoFile struct { - Docker DockerMap `yaml:"docker,omitempty"` - Modes map[string]string `yaml:"modes,omitempty"` - Project string `yaml:"project,omitempty"` + Docker DockerMap `yaml:"docker,omitempty"` + Modes map[string]string `yaml:"modes,omitempty"` + Project string `yaml:"project,omitempty"` } type DockerMap struct { diff --git a/app/modules/context/context.go b/app/modules/context/context.go index 9a561da..a2dd426 100644 --- a/app/modules/context/context.go +++ b/app/modules/context/context.go @@ -12,16 +12,16 @@ import ( type LedoContext struct { *cli.Context - Config *config.LedoFile + Config *config.LedoFile ComposeArgs []string - Mode mode.Mode - Output string + Mode mode.Mode + Output string } func InitCommand(ctx *cli.Context) *LedoContext { var ( - c LedoContext + c LedoContext cfg *config.LedoFile ) @@ -39,8 +39,8 @@ func InitCommand(ctx *cli.Context) *LedoContext { os.Exit(1) } - mode := mode.InitMode(modeYml, configYml) - c.Mode = mode + ledoMode := mode.InitMode(modeYml, configYml) + c.Mode = ledoMode c.Output = ctx.String("output") @@ -50,10 +50,10 @@ func InitCommand(ctx *cli.Context) *LedoContext { args := []string{"--env-file", ".env"} args = append(args, "--project-name", strings.ToLower(strings.Replace(c.Config.Docker.Name, "/", "-", -1))) - composes, _ := mode.GetModeConfig() + composes, _ := ledoMode.GetModeConfig() for _, element := range composes { args = append(args, "-f") - args = append(args, element) + args = append(args, element) } c.ComposeArgs = args @@ -66,7 +66,7 @@ func LoadConfigFile() (*config.LedoFile, error) { if _, err := os.Stat(configYml); err != nil { nilCfg := &config.LedoFile{} - return nilCfg, err + return nilCfg, err } cfg, _ := config.NewLedoFile(configYml) @@ -80,4 +80,4 @@ func (lx *LedoContext) ExecCmd(cmd string, cmdArgs []string) error { command.Stdout = os.Stdout command.Stderr = os.Stderr return command.Run() -} \ No newline at end of file +} diff --git a/app/modules/docker_hub/docker_hub_images.go b/app/modules/docker_hub/docker_hub_images.go new file mode 100644 index 0000000..b5eaf64 --- /dev/null +++ b/app/modules/docker_hub/docker_hub_images.go @@ -0,0 +1,57 @@ +package docker_hub + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "net/url" +) + +type DockerSearchResponse struct { + NumPages int `json:"num_pages"` + NumResults int `json:"num_results"` + PageSize int `json:"page_size"` + Page int `json:"page"` + Query string `json:"query"` + Results []DockerImage `json:"results"` +} + +type DockerImage struct { + Name string `json:"name"` + Description string `json:"description"` + StarCount int `json:"star_count"` + IsTrusted bool `json:"is_trusted"` + IsAutomated bool `json:"is_automated"` + IsOfficial bool `json:"is_official"` +} + +var urlSearch = "https://registry.hub.docker.com/v1/search" + +func GetImage(image string) []DockerImage { + var resp DockerSearchResponse + searchString := url.QueryEscape(image) + urlSearch = urlSearch + "/?q=" + searchString + fmt.Printf("%v", urlSearch) + res, _ := http.Get(urlSearch) + defer res.Body.Close() + + bytes, err := ioutil.ReadAll(res.Body) + if err != nil { + panic(err.Error()) + } + + json.Unmarshal(bytes, &resp) + + return resp.Results +} + +func DockerImageToArray(images []DockerImage) []string { + n := len(images) + arrTags := make([]string, n) + for idx, image := range images { + arrTags[idx] = image.Name + } + + return arrTags +} diff --git a/app/modules/docker_hub/docker_hub.go b/app/modules/docker_hub/docker_hub_tags.go similarity index 62% rename from app/modules/docker_hub/docker_hub.go rename to app/modules/docker_hub/docker_hub_tags.go index ec54872..80640ab 100644 --- a/app/modules/docker_hub/docker_hub.go +++ b/app/modules/docker_hub/docker_hub_tags.go @@ -8,23 +8,23 @@ import ( type DockerImageTag struct { Layer string `json:"layer"` - Name string `json:"name"` + Name string `json:"name"` } -var url = "https://registry.hub.docker.com/v1/repositories" +var urlTags = "https://registry.hub.docker.com/v1/repositories" func GetImageTags(image string) []DockerImageTag { - url = url + "/" + image + "/tags" - res, _ := http.Get(url) + urlTags = urlTags + "/" + image + "/tags" + res, _ := http.Get(urlTags) defer res.Body.Close() bytes, err := ioutil.ReadAll(res.Body) - if err != nil { - panic(err.Error()) - } + if err != nil { + panic(err.Error()) + } - var tags []DockerImageTag - json.Unmarshal(bytes, &tags) + var tags []DockerImageTag + json.Unmarshal(bytes, &tags) return tags } @@ -37,4 +37,4 @@ func ImageTagsToArray(tags []DockerImageTag) []string { } return arrTags -} \ No newline at end of file +} diff --git a/app/modules/dockerfile/dockerfile.go b/app/modules/dockerfile/dockerfile.go new file mode 100644 index 0000000..0374c9e --- /dev/null +++ b/app/modules/dockerfile/dockerfile.go @@ -0,0 +1,33 @@ +package dockerfile + +import ( + "html/template" + "ledo/app/helper" + "ledo/app/templates" + "log" + "os" +) + +func CreateDockerFile(cfg helper.DockerProjectCfg) error { + if _, err := os.Stat("./Dockerfile"); err == nil { + log.Printf("Dockerfile exists!") + os.Exit(1) + } + + templateName := templates.DockerFileTemplate_default + if cfg.DockerBaseImage == "paramah/php" { + templateName = templates.DockerFileTemplate_php + } + tpl, err := template.New("dockerfile").Parse(templateName) + if err != nil { + log.Fatalln(err) + } + + f, err := os.Create("./Dockerfile") + if err != nil { + log.Println("create file: ", err) + } + err = tpl.Execute(f, cfg) + + return err +} \ No newline at end of file diff --git a/app/modules/interact/docker_hub.go b/app/modules/interact/docker_hub.go new file mode 100644 index 0000000..65eaa19 --- /dev/null +++ b/app/modules/interact/docker_hub.go @@ -0,0 +1,64 @@ +package interact + +import ( + "github.com/AlecAivazis/survey/v2" + "ledo/app/modules/docker_hub" +) + +func SelectDockerHubTag(dockerImage string) (string, error) { + dockerImageTags := docker_hub.GetImageTags(dockerImage) + selectedTag := "latest" + + var qs = []*survey.Question{ + { + Name: "tags", + Prompt: &survey.Select{ + Message: "Select available docker image tag", + PageSize: 10, + Options: docker_hub.ImageTagsToArray(dockerImageTags), + }, + }, + } + + err := survey.Ask(qs, &selectedTag) + + if err != nil { + return "", err + } + + return selectedTag, err +} + +func EnterDockerImage() (string, error) { + dockerImage := "" + prompt := &survey.Input{ + Message: "Enter docker base image: ", + Help: "This is base Dockerfile image (FROM image)", + } + survey.AskOne(prompt, &dockerImage) + return dockerImage, nil +} + +func SearchDockerImage(image string) (string, error) { + dockerImages := docker_hub.GetImage(image) + selectedImage := "" + + var qs = []*survey.Question{ + { + Name: "image", + Prompt: &survey.Select{ + Message: "Select available docker image", + PageSize: 100, + Options: docker_hub.DockerImageToArray(dockerImages), + }, + }, + } + + err := survey.Ask(qs, &selectedImage) + + if err != nil { + return "", err + } + + return selectedImage, err +} diff --git a/app/modules/interact/docker_hub_tags.go b/app/modules/interact/docker_hub_tags.go deleted file mode 100644 index 3468aad..0000000 --- a/app/modules/interact/docker_hub_tags.go +++ /dev/null @@ -1,30 +0,0 @@ -package interact - -import ( - survey "github.com/AlecAivazis/survey/v2" - "ledo/app/modules/docker_hub" -) - -func SelectDockerHubTag(dockerImage string) (string, error) { - dockerImageTags := docker_hub.GetImageTags(dockerImage) - selectedTag := "latest" - - var qs = []*survey.Question{ - { - Name: "tags", - Prompt: &survey.Select{ - Message: "Select available docker image tag", - PageSize: 10, - Options: docker_hub.ImageTagsToArray(dockerImageTags), - }, - }, - } - - err := survey.Ask(qs, &selectedTag) - - if err != nil { - return "", err - } - - return selectedTag, err -} \ No newline at end of file diff --git a/app/modules/interact/docker_init.go b/app/modules/interact/docker_init.go new file mode 100644 index 0000000..0321781 --- /dev/null +++ b/app/modules/interact/docker_init.go @@ -0,0 +1,24 @@ +package interact + +import ( + "ledo/app/helper" +) + +func InitDocker() (helper.DockerProjectCfg, error) { + dockerConfig := helper.DockerProjectCfg{} + + image, err := EnterDockerImage() + if err != nil { + return dockerConfig, err + } + + tag, err := SelectDockerHubTag(image) + if err != nil { + return dockerConfig, err + } + + dockerConfig.DockerBaseImage = image + dockerConfig.DockerBaseTag = tag + + return dockerConfig, err +} diff --git a/app/modules/interact/docker_service.go b/app/modules/interact/docker_service.go new file mode 100644 index 0000000..14775e7 --- /dev/null +++ b/app/modules/interact/docker_service.go @@ -0,0 +1,51 @@ +package interact + +import ( + "github.com/AlecAivazis/survey/v2" + "ledo/app/helper" +) + +var PredefinedDockerComposeModes = []string{ + "base", + "dev", + "test", +} + +func CreateDockerService() (helper.DockerProjectAdditionalServiceCfg, error) { + dockerServiceConfig := helper.DockerProjectAdditionalServiceCfg{} + + var qs = []*survey.Question{ + //{ + // Name: "DockerServiceType", + // Prompt: &survey.Select{ + // Message: "Select type of service", + // PageSize: 10, + // Options: []string{"database", "development", "tools"}, + // }, + //}, + //{ + // Name: "DockerServiceMode", + // Prompt: &survey.Select{ + // Message: "Select docker-compose mode (file)", + // PageSize: 10, + // Options: PredefinedDockerComposeModes, + // }, + //}, + { + Name: "DockerServiceImage", + Prompt: &survey.Input{Message: "Enter image name: "}, + Validate: survey.Required, + Transform: survey.ToLower, + }, + + } + + err := survey.Ask(qs, &dockerServiceConfig) + + if err != nil { + return dockerServiceConfig, err + } + + return dockerServiceConfig, err +} + diff --git a/app/modules/interact/init.go b/app/modules/interact/init.go index bcbea34..0ececd4 100644 --- a/app/modules/interact/init.go +++ b/app/modules/interact/init.go @@ -1,14 +1,13 @@ - package interact import ( - survey "github.com/AlecAivazis/survey/v2" + "github.com/AlecAivazis/survey/v2" "ledo/app/modules/config" ) func InitLedoProject(dockerConfig config.DockerMap) (config.DockerMap, error) { if dockerConfig.Registry == "" { - dockerConfig.Registry = "hub.docker.com" + dockerConfig.Registry = "" } if dockerConfig.Shell == "" { @@ -21,42 +20,41 @@ func InitLedoProject(dockerConfig config.DockerMap) (config.DockerMap, error) { var qs = []*survey.Question{ { - Name: "Registry", - Prompt: &survey.Input{Message: "Enter docker registry address: ", Default: dockerConfig.Registry, Help: "Docker registry for main service image"}, - Validate: survey.Required, + Name: "Registry", + Prompt: &survey.Input{Message: "Enter docker registry address: ", Default: dockerConfig.Registry, Help: "Docker registry for main service image"}, + Validate: survey.Required, Transform: survey.ToLower, }, { - Name: "Namespace", - Prompt: &survey.Input{Message: "Enter project namespace: ",Default: dockerConfig.Namespace, Help: "Project namespace (eq. GitLab project group)"}, - Validate: survey.Required, + Name: "Namespace", + Prompt: &survey.Input{Message: "Enter project namespace: ", Default: dockerConfig.Namespace, Help: "Project namespace (eq. GitLab project group)"}, + Validate: survey.Required, Transform: survey.ToLower, }, { - Name: "Name", - Prompt: &survey.Input{Message: "Enter project name: ", Default: dockerConfig.Name}, - Validate: survey.Required, + Name: "Name", + Prompt: &survey.Input{Message: "Enter project name: ", Default: dockerConfig.Name}, + Validate: survey.Required, Transform: survey.ToLower, }, { - Name: "MainService", - Prompt: &survey.Input{Message: "Enter docker-compose main service name: ",Default: dockerConfig.MainService, Help: "Main service, important if you want use ledo shell command or ledo run command"}, - Validate: survey.Required, + Name: "MainService", + Prompt: &survey.Input{Message: "Enter docker-compose main service name: ", Default: dockerConfig.MainService, Help: "Main service, important if you want use ledo shell command or ledo run command"}, + Validate: survey.Required, Transform: survey.ToLower, }, { - Name: "Shell", - Prompt: &survey.Input{Message: "Enter default shell: ", Default: dockerConfig.Shell}, - Validate: survey.Required, + Name: "Shell", + Prompt: &survey.Input{Message: "Enter default shell: ", Default: dockerConfig.Shell}, + Validate: survey.Required, Transform: survey.ToLower, }, { - Name: "Username", - Prompt: &survey.Input{Message: "Enter docker main service username: ", Default: dockerConfig.Username, Help: "Default user, if set ledo run command was execute with sudo user"}, - Validate: survey.Required, + Name: "Username", + Prompt: &survey.Input{Message: "Enter docker main service username: ", Default: dockerConfig.Username, Help: "Default user, if set ledo run command was execute with sudo user"}, + Validate: survey.Required, Transform: survey.ToLower, }, - } err := survey.Ask(qs, &dockerConfig) @@ -68,9 +66,9 @@ func InitLedoProject(dockerConfig config.DockerMap) (config.DockerMap, error) { return dockerConfig, err } -func InitAdvancedConfigurationAsk() (bool) { +func InitAdvancedConfigurationAsk(question string) bool { runAdv := false - prompt := &survey.Confirm{Message: "Run advanced docker mode configuration?"} + prompt := &survey.Confirm{Message: question} survey.AskOne(prompt, &runAdv) return runAdv -} \ No newline at end of file +} diff --git a/app/modules/interact/mode.go b/app/modules/interact/mode.go index 2cad34f..a693a09 100644 --- a/app/modules/interact/mode.go +++ b/app/modules/interact/mode.go @@ -1,7 +1,7 @@ package interact import ( - survey "github.com/AlecAivazis/survey/v2" + "github.com/AlecAivazis/survey/v2" "github.com/thoas/go-funk" "ledo/app/modules/context" ) @@ -29,4 +29,4 @@ func SelectMode(context *context.LedoContext, selectedMode string) (string, erro _, err := mode.SetMode(selectedMode) return selectedMode, err -} \ No newline at end of file +} diff --git a/app/modules/mode/mode.go b/app/modules/mode/mode.go index 33bfeaa..a933af9 100644 --- a/app/modules/mode/mode.go +++ b/app/modules/mode/mode.go @@ -58,7 +58,7 @@ func (c *Mode) GetMode() string { func (c *Mode) PrintListModes() { fmt.Printf("Available modes:\n") - for m, _ := range c.availableModes { + for m := range c.availableModes { fmt.Printf("- %v\n", m) } } @@ -96,14 +96,12 @@ func (c *Mode) SetMode(modeName string) (bool, error) { } func (c *Mode) GetModeConfig() ([]string, error) { - _, err := c.CheckMode(c.CurrentMode); + _, err := c.CheckMode(c.CurrentMode) - if err == nil { + if err == nil { composes := strings.Fields(c.availableModes[c.CurrentMode]) return composes, nil } return nil, errors.New("Selected mode not exists in config file") } - - diff --git a/app/templates/compose_template.go b/app/templates/compose_template.go index 54fdc28..4eb65b8 100644 --- a/app/templates/compose_template.go +++ b/app/templates/compose_template.go @@ -1,5 +1,15 @@ package templates -var LedoDockerComposeBaseFileTemplate = ` +var LedoDockerComposeBaseFileTemplate_base = ` +version: '3.7' +services: -` \ No newline at end of file + {{.Config.Docker.MainService}}: + image: {{.Config.Docker.Registry}} + networks: + - network-{{.Config.Docker.Namespace}} + env_file: ${PWD}/.env + +networks: + nestork-{{.Config.Docker.Namespace}}: {} +` diff --git a/app/templates/dockerfile_template.go b/app/templates/dockerfile_template.go index b4ef6b5..b63ecff 100644 --- a/app/templates/dockerfile_template.go +++ b/app/templates/dockerfile_template.go @@ -1,7 +1,7 @@ package templates -var default_DockerFileTemplate = ` -FROM {{.Image}}/{{.Tag}} +var DockerFileTemplate_default = ` +FROM {{.DockerBaseImage}}:{{.DockerBaseTag}} ENV DIR /usr/local WORKDIR ${DIR} @@ -10,13 +10,13 @@ WORKDIR ${DIR} COPY docker/docker-entrypoint.sh /bin/docker-entrypoint.sh # Copy project content -COPY {{.ContainerContent}} $DIR +COPY ./app $DIR ENTRYPOINT ["docker-entrypoint.sh"] CMD [""] ` -var php_DockerFileTemplate = ` -FROM paramah/{{.Tag}} +var DockerFileTemplate_php = ` +FROM {{.DockerBaseImage}}:{{.DockerBaseTag}} ARG ENVIRONMENT=production RUN ngxconfig sf.conf @@ -49,4 +49,4 @@ EXPOSE 80 USER root CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/supervisord.conf"] -` \ No newline at end of file +` diff --git a/app/templates/entrypoint_template.go b/app/templates/entrypoint_template.go new file mode 100644 index 0000000..8b83f7b --- /dev/null +++ b/app/templates/entrypoint_template.go @@ -0,0 +1,31 @@ +package templates + +var DockerEntrypointTemplate_bash = ` +#!/bin/bash +set -eo pipefail +shopt -s nullglob + +h1() { + declare border padding text + border='\e[1;34m'"$(printf '=%.0s' $(seq 1 "$term_width"))"'\e[0m' + padding="$(printf ' %.0s' $(seq 1 $(((term_width - $(wc -m <<<"$*")) / 2))))" + text="\\e[1m$*\\e[0m" + echo -e "$border" + echo -e "${padding}${text}${padding}" + echo -e "$border" +} + +h2() { + printf '\e[1;33m==>\e[37;1m %s\e[0m\n' "$*" +} + +h1 "Project init" + +### +### Your code here +### + +h1 "End of init" + +exec "$@" +` diff --git a/app/templates/ledofile_template.go b/app/templates/ledofile_template.go index 14c473b..c2266ac 100644 --- a/app/templates/ledofile_template.go +++ b/app/templates/ledofile_template.go @@ -11,8 +11,7 @@ docker: username: {{.Username}} {{end}} modes: - normal: docker/docker-compose.yml + base: docker/docker-compose.yml dev: docker/docker-compose.yml docker/docker-compose.dev.yml - traefik: docker/docker-compose.yml docker/docker-compose.traefik.yml + test: docker/docker-compose.yml docker/docker-compose.test.yml ` - diff --git a/main.go b/main.go index 9b18af5..3db51b7 100644 --- a/main.go +++ b/main.go @@ -25,13 +25,13 @@ func main() { app.Usage = "LeadDocker helper for docker-compose work" app.Description = appDescription app.CustomAppHelpTemplate = helpTemplate - app.Version = version + app.Version = GetCurrentVersion() app.Commands = []*cli.Command{ &cmd.CmdInit, &cmd.CmdDocker, &cmd.CmdMode, &cmd.CmdAutocomplete, - &CmdSelfupdate, + // &CmdSelfupdate, } app.EnableBashCompletion = true err := app.Run(os.Args)