code reformat, init fixes
This commit is contained in:
@ -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:])
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
42
app/modules/compose/create_compose.go
Normal file
42
app/modules/compose/create_compose.go
Normal file
@ -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
|
||||
}
|
@ -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 {
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
57
app/modules/docker_hub/docker_hub_images.go
Normal file
57
app/modules/docker_hub/docker_hub_images.go
Normal file
@ -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
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
33
app/modules/dockerfile/dockerfile.go
Normal file
33
app/modules/dockerfile/dockerfile.go
Normal file
@ -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
|
||||
}
|
64
app/modules/interact/docker_hub.go
Normal file
64
app/modules/interact/docker_hub.go
Normal file
@ -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
|
||||
}
|
@ -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
|
||||
}
|
24
app/modules/interact/docker_init.go
Normal file
24
app/modules/interact/docker_init.go
Normal file
@ -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
|
||||
}
|
51
app/modules/interact/docker_service.go
Normal file
51
app/modules/interact/docker_service.go
Normal file
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user