Compare commits

...

4 Commits

12 changed files with 159 additions and 45 deletions

1
go/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/test

View File

@ -5,8 +5,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"io" "io"
"ocl/portainer-devtool/utils"
"os" "os"
"path"
) )
const ( const (
@ -78,39 +78,16 @@ func (config *Config) Summarize() {
// The configuration also can be updated later // The configuration also can be updated later
func initializeConfig(w io.WriteCloser) (*Config, error) { func initializeConfig(w io.WriteCloser) (*Config, error) {
config := &Config{} config := &Config{}
fmt.Printf("Initialize devtool path:\n (Project path will store volumes and repositories)") config.ProjectPath = utils.Prompt("Specify Git Project Root Path")
fmt.Scanf("%s", &(config.ProjectPath))
// analyze all the repositories in the project root path
// add the parsed information to RepositoryConfig
config.configureRepositories()
// generate volume path automatically // generate volume path automatically
config.VolumePath = path.Join(config.ProjectPath, "volumes") config.VolumePath = utils.Prompt("Specify Volume Path")
var loginCredential LoginCredential
fmt.Printf("Set login credential username(admin): ")
fmt.Scanf("%s", &(loginCredential.Username))
if loginCredential.Username == "" {
loginCredential.Username = "admin"
}
for {
fmt.Printf("Set login credential password(******): ")
fmt.Scanf("%s", &(loginCredential.Password))
if loginCredential.Password != "" {
break
}
fmt.Println("Login credential password must be provided")
}
fmt.Printf("Set login address(127.0.0.1): ")
fmt.Scanf("%s", &(loginCredential.Address))
if loginCredential.Address == "" {
loginCredential.Address = "http://127.0.0.1:9000/api/auth"
} else {
loginCredential.Address = fmt.Sprintf("http://%s:9000/api/auth", loginCredential.Address)
}
config.LoginCredential = loginCredential
config.configureLoginCredential()
// able to configure multiple project // able to configure multiple project
// if utils.PromptConfirm("Do you want to configure the repository now?") { // if utils.PromptConfirm("Do you want to configure the repository now?") {
// // configure repository // // configure repository

32
go/configs/credential.go Normal file
View File

@ -0,0 +1,32 @@
package configs
import (
"fmt"
"ocl/portainer-devtool/utils"
)
func (config *Config) configureLoginCredential() {
var loginCredential LoginCredential
loginCredential.Username = utils.Prompt("Set Login Credential Username(admin)")
if loginCredential.Username == "" {
loginCredential.Username = "admin"
}
for {
loginCredential.Password = utils.Prompt("Set Login Credential Password(*****)")
if loginCredential.Password != "" {
break
}
utils.WarnPrint("Login Credential Password must be provided")
}
loginCredential.Address = utils.Prompt("Set Login Address(127.0.0.1)")
if loginCredential.Address == "" {
loginCredential.Address = "http://127.0.0.1:9000/api/auth"
} else {
loginCredential.Address = fmt.Sprintf("http://%s:9000/api/auth", loginCredential.Address)
}
config.LoginCredential = loginCredential
}

54
go/configs/repository.go Normal file
View File

@ -0,0 +1,54 @@
package configs
import (
"fmt"
"io/fs"
"log"
"ocl/portainer-devtool/utils"
"path/filepath"
)
func (config *Config) configureRepositories() {
if config.RepositoryConfig == nil {
config.RepositoryConfig = make(map[string]RepositoryConfig)
}
for {
if !utils.PromptConfirm("Set up new repository") {
break
}
repoConfig := RepositoryConfig{}
repoConfig.Name = utils.Prompt("Name")
repoConfig.URL = utils.Prompt("URL")
repoConfig.Directory = utils.Prompt("Directory")
config.RepositoryConfig[repoConfig.Name] = repoConfig
}
utils.HighlightPrint("Configure repositories completed")
}
func (config *Config) generateRepositoriesBasedOnProjectPath(projectPath string) error {
filepath.WalkDir(projectPath, func(path string, d fs.DirEntry, err error) error {
if err != nil {
log.Printf("fail to walk in the project path %s, error: %v\n", projectPath, err)
return err
}
if utils.MatchPathLength(projectPath, path, 1) {
fmt.Println(path)
// posLastSeparator := strings.LastIndex(path, string(filepath.Separator))
// repoName := path[posLastSeparator+1:]
// repoConfig := RepositoryConfig{
// Name: repoName,
// // URL:
// }
// config.RepositoryConfig[repoName] =
}
return nil
})
return nil
}

View File

@ -20,8 +20,6 @@ func main() {
tasks.NewCurlLookupTask(), tasks.NewCurlLookupTask(),
tasks.NewCodeSecurityScanTask(), tasks.NewCodeSecurityScanTask(),
tasks.NewListDevToolCommandTask(config), tasks.NewListDevToolCommandTask(config),
tasks.NewExitTask(),
} }
tasks.ListCommandMenu(taskItems, "Which repository of action do you want operate:") tasks.ListCommandMenu(taskItems, "Which repository of action do you want operate:")

View File

@ -18,6 +18,7 @@ func NewListDevToolCommandTask(cfg *configs.Config) *ListDevToolCommandTask {
func (task *ListDevToolCommandTask) Execute() error { func (task *ListDevToolCommandTask) Execute() error {
subTaskItems := []Tasker{ subTaskItems := []Tasker{
subtasks.NewListVolumeSubTask(task.Config), subtasks.NewListVolumeSubTask(task.Config),
subtasks.NewListRepositorySubTask(task.Config),
} }
ListCommandMenu(subTaskItems, "Which management commands do you want to choose:") ListCommandMenu(subTaskItems, "Which management commands do you want to choose:")

View File

@ -0,0 +1,34 @@
package subtasks
import (
"ocl/portainer-devtool/configs"
"ocl/portainer-devtool/utils"
"strings"
)
type ListRepositorySubTask struct {
Config *configs.Config
}
func NewListRepositorySubTask(cfg *configs.Config) *ListRepositorySubTask {
return &ListRepositorySubTask{
Config: cfg,
}
}
func (task *ListRepositorySubTask) Execute() error {
utils.InputPrint("Which repository?")
repositoryList := []string{" "}
for _, repo := range task.Config.RepositoryConfig {
repositoryList = append(repositoryList, repo.Name)
}
utils.SuccessPrint(strings.Join(repositoryList, "\n"))
return nil
}
func (task *ListRepositorySubTask) String() string {
return "List Repositories"
}

View File

@ -22,8 +22,6 @@ func NewListVolumeSubTask(cfg *configs.Config) *ListVolumeSubTask {
func (task *ListVolumeSubTask) Execute() error { func (task *ListVolumeSubTask) Execute() error {
utils.HighlightPrint(fmt.Sprintf("Volume path: %s", task.Config.VolumePath)) utils.HighlightPrint(fmt.Sprintf("Volume path: %s", task.Config.VolumePath))
volumeLength := lenPath(task.Config.VolumePath)
volumeList := []string{" "} volumeList := []string{" "}
filepath.WalkDir(task.Config.VolumePath, func(path string, d fs.DirEntry, err error) error { filepath.WalkDir(task.Config.VolumePath, func(path string, d fs.DirEntry, err error) error {
if err != nil { if err != nil {
@ -35,8 +33,7 @@ func (task *ListVolumeSubTask) Execute() error {
} }
if d.IsDir() { if d.IsDir() {
dirLength := lenPath(path) if utils.MatchPathLength(task.Config.VolumePath, path, 1) {
if volumeLength+1 == dirLength {
volumeList = append(volumeList, d.Name()) volumeList = append(volumeList, d.Name())
} }
} }
@ -50,9 +47,5 @@ func (task *ListVolumeSubTask) Execute() error {
} }
func (task *ListVolumeSubTask) String() string { func (task *ListVolumeSubTask) String() string {
return "List Volume" return "List Volumes"
}
func lenPath(path string) int {
return len(strings.Split(path, string(filepath.Separator)))
} }

View File

@ -14,6 +14,7 @@ type Tasker interface {
// ListCommandMenu iterates task items to display them // on the screen as the menu options // ListCommandMenu iterates task items to display them // on the screen as the menu options
func ListCommandMenu(taskItems []Tasker, menuDesp string) error { func ListCommandMenu(taskItems []Tasker, menuDesp string) error {
taskItems = append(taskItems, NewExitTask())
for { for {
printMainMenu := func() { printMainMenu := func() {
taskNames := []string{} taskNames := []string{}

18
go/utils/path.go Normal file
View File

@ -0,0 +1,18 @@
package utils
import (
"path/filepath"
"strings"
)
// MatchPathLength matches the length of target path separated by path separator
// to the length of base path separated by path separator plus offset
func MatchPathLength(basePath, targetPath string, offset int) bool {
basePathLength := len(strings.Split(basePath, string(filepath.Separator)))
targetPathLength := len(strings.Split(targetPath, string(filepath.Separator)))
if basePathLength+offset == targetPathLength {
return true
}
return false
}

View File

@ -38,6 +38,11 @@ func ErrorPrint(message string) {
fmt.Println(colorRed, message, colorReset) fmt.Println(colorRed, message, colorReset)
} }
func WarnPrint(message string) {
fmt.Println()
fmt.Println(colorPurple, message, colorReset)
}
func InputPrint(message string) { func InputPrint(message string) {
// adding \n before setting colorful output can // adding \n before setting colorful output can
// remove the first space in the colorful output // remove the first space in the colorful output

View File

@ -6,7 +6,7 @@ import (
) )
func PromptContinue() bool { func PromptContinue() bool {
ret := strings.ToLower(prompt("Continue (y/n)")) ret := strings.ToLower(Prompt("Continue (y/n)"))
if ret == "y" || ret == "yes" { if ret == "y" || ret == "yes" {
return true return true
} }
@ -15,7 +15,7 @@ func PromptContinue() bool {
} }
func PromptConfirm(question string) bool { func PromptConfirm(question string) bool {
ret := fmt.Sprintf("%s (y/n)?", question) ret := Prompt(fmt.Sprintf("%s (y/n)?", question))
if ret == "y" || ret == "yes" { if ret == "y" || ret == "yes" {
return true return true
} }
@ -31,7 +31,7 @@ func SelectMenuItem(listMenu func()) string {
return option return option
} }
func prompt(question string) string { func Prompt(question string) string {
fmt.Printf("%s %s :%s", colorYellow, question, colorReset) fmt.Printf("%s %s :%s", colorYellow, question, colorReset)
var ret string var ret string
fmt.Scanf("%s", &ret) fmt.Scanf("%s", &ret)