Merge pull request 'Create Golang version devtool' (#7) from oscar-next into master
Reviewed-on: #7
This commit is contained in:
		
						commit
						927d6e92b0
					
				
							
								
								
									
										1
									
								
								go/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								go/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					/test
 | 
				
			||||||
							
								
								
									
										18
									
								
								go/commands/git.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								go/commands/git.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					package commands
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"ocl/portainer-devtool/utils"
 | 
				
			||||||
 | 
						"os/exec"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ListBranches(workdir string) error {
 | 
				
			||||||
 | 
						cmd := exec.Command("git", "branch")
 | 
				
			||||||
 | 
						cmd.Dir = workdir
 | 
				
			||||||
 | 
						out, err := cmd.Output()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						utils.PrintOutput("Your current checkout branch", out)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										15
									
								
								go/commands/yarn.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								go/commands/yarn.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					package commands
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"ocl/portainer-devtool/utils"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RunClient starts the portainer client
 | 
				
			||||||
 | 
					func RunPortainerClient(workdir string) error {
 | 
				
			||||||
 | 
						err := utils.RunCommandWithStdoutPipe(workdir, "yarn")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return utils.RunCommandWithStdoutPipe(workdir, "yarn", "start:client")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										153
									
								
								go/configs/config.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								go/configs/config.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,153 @@
 | 
				
			|||||||
 | 
					package configs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"ocl/portainer-devtool/utils"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						ConfigFileName string = ".devtool"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						ErrConfigNotInitialized error = errors.New("Config file is not initialized")
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Config struct {
 | 
				
			||||||
 | 
						// ProjectPath is the location on your host where all dev relevant folders will be stored to
 | 
				
			||||||
 | 
						ProjectPath string
 | 
				
			||||||
 | 
						// VolumePath is where all the persisitant data will be stored
 | 
				
			||||||
 | 
						VolumePath string
 | 
				
			||||||
 | 
						// Credentials for UI login
 | 
				
			||||||
 | 
						LoginCredential LoginCredential
 | 
				
			||||||
 | 
						// key is repository name, for example, "repository-ee"
 | 
				
			||||||
 | 
						RepositoryConfig map[string]RepositoryConfig
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// LoginCredential stores the user credential for API request
 | 
				
			||||||
 | 
					type LoginCredential struct {
 | 
				
			||||||
 | 
						Username string
 | 
				
			||||||
 | 
						Password string
 | 
				
			||||||
 | 
						Address  string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type RepositoryConfig struct {
 | 
				
			||||||
 | 
						Name        string
 | 
				
			||||||
 | 
						URL         string
 | 
				
			||||||
 | 
						Directory   string
 | 
				
			||||||
 | 
						Private     bool
 | 
				
			||||||
 | 
						GitUsername string
 | 
				
			||||||
 | 
						GitPassword string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetConfig() (*Config, error) {
 | 
				
			||||||
 | 
						file, err := getConfigFile(ConfigFileName)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if err == ErrConfigNotInitialized {
 | 
				
			||||||
 | 
								return initializeConfig(file)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defer file.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return getConfig(file)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (config *Config) Summarize() {
 | 
				
			||||||
 | 
						fmt.Printf("The project path is %s\nThe volume path is %s\n", config.ProjectPath, config.VolumePath)
 | 
				
			||||||
 | 
						if config.LoginCredential.Username != "" && config.LoginCredential.Password != "" {
 | 
				
			||||||
 | 
							fmt.Printf("Login credential [%s] is configured\n", config.LoginCredential.Username)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if len(config.RepositoryConfig) > 0 {
 | 
				
			||||||
 | 
							for name := range config.RepositoryConfig {
 | 
				
			||||||
 | 
								fmt.Printf("Repository [%s] is added\n", name)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							fmt.Println("No repository is added")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// initializeConfig will set up the mandatory dev information for the first time.
 | 
				
			||||||
 | 
					// such as devtool path, login credential
 | 
				
			||||||
 | 
					// The configuration also can be updated later
 | 
				
			||||||
 | 
					func initializeConfig(w io.WriteCloser) (*Config, error) {
 | 
				
			||||||
 | 
						config := &Config{}
 | 
				
			||||||
 | 
						config.ProjectPath = utils.Prompt("Specify Git Project Root Path")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// analyze all the repositories in the project root path
 | 
				
			||||||
 | 
						// add the parsed information to RepositoryConfig
 | 
				
			||||||
 | 
						config.configureRepositories()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// generate volume path automatically
 | 
				
			||||||
 | 
						config.VolumePath = utils.Prompt("Specify Volume Path")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						config.configureLoginCredential()
 | 
				
			||||||
 | 
						// able to configure multiple project
 | 
				
			||||||
 | 
						// if utils.PromptConfirm("Do you want to configure the repository now?") {
 | 
				
			||||||
 | 
						// 	// configure repository
 | 
				
			||||||
 | 
						// }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bytes, err := json.Marshal(config)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err = w.Write(bytes)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return config, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getConfig(f *os.File) (*Config, error) {
 | 
				
			||||||
 | 
						config := &Config{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						info, err := f.Stat()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						bytes := make([]byte, info.Size())
 | 
				
			||||||
 | 
						n, err := f.Read(bytes)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if n == 0 {
 | 
				
			||||||
 | 
							// The file exists, but it's empty file, so we need to initalize
 | 
				
			||||||
 | 
							return initializeConfig(f)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = json.Unmarshal(bytes, &config)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return config, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// getConfigFile get the config file handler
 | 
				
			||||||
 | 
					func getConfigFile(name string) (*os.File, error) {
 | 
				
			||||||
 | 
						_, err := os.Stat(name)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if errors.Is(err, os.ErrNotExist) {
 | 
				
			||||||
 | 
								//create file
 | 
				
			||||||
 | 
								file, err := os.Create(name)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return nil, fmt.Errorf("fail to create config file: %w", err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// first set up the git project path and volume path
 | 
				
			||||||
 | 
								// git credential
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return file, err
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return os.OpenFile(name, os.O_RDWR, 0644)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										32
									
								
								go/configs/credential.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								go/configs/credential.go
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										54
									
								
								go/configs/repository.go
									
									
									
									
									
										Normal 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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								go/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								go/main.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"log"
 | 
				
			||||||
 | 
						"ocl/portainer-devtool/configs"
 | 
				
			||||||
 | 
						"ocl/portainer-devtool/tasks"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func main() {
 | 
				
			||||||
 | 
						config, err := configs.GetConfig()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatalln(err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						config.Summarize()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Init tasks
 | 
				
			||||||
 | 
						taskItems := []tasks.Tasker{
 | 
				
			||||||
 | 
							tasks.NewGenerateJwtTokenTask(config),
 | 
				
			||||||
 | 
							tasks.NewCurlLookupTask(),
 | 
				
			||||||
 | 
							tasks.NewCodeSecurityScanTask(),
 | 
				
			||||||
 | 
							tasks.NewListDevToolCommandTask(config),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						tasks.ListCommandMenu(taskItems, "Which repository of action do you want operate:")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										5
									
								
								go/repositories/actioner.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								go/repositories/actioner.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					package repositories
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Actioner interface {
 | 
				
			||||||
 | 
						Execute() error
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										71
									
								
								go/repositories/ee.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								go/repositories/ee.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,71 @@
 | 
				
			|||||||
 | 
					package repositories
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"ocl/portainer-devtool/commands"
 | 
				
			||||||
 | 
						"ocl/portainer-devtool/utils"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						ACTION_EE_BUILD_ALL int = iota + 1
 | 
				
			||||||
 | 
						ACTION_EE_RUN_FRONTEND
 | 
				
			||||||
 | 
						ACTION_EE_RUN_BACKEND
 | 
				
			||||||
 | 
						ACTION_EE_VALIDATE_ALL
 | 
				
			||||||
 | 
						ACTION_EE_VALIDATE_FRONTEND
 | 
				
			||||||
 | 
						ACTION_EE_VALIDATE_BACKEND
 | 
				
			||||||
 | 
						ACTION_EE_RUN_UNIT_TEST_ALL
 | 
				
			||||||
 | 
						ACTION_EE_RUN_UNIT_TEST_FRONTEND
 | 
				
			||||||
 | 
						ACTION_EE_RUN_UNIT_TEST_BACKEND
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type PortainerEE struct {
 | 
				
			||||||
 | 
						WorkDir     string
 | 
				
			||||||
 | 
						FrontendDir string
 | 
				
			||||||
 | 
						BackendDir  string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewPortainerEERepository() *PortainerEE {
 | 
				
			||||||
 | 
						repo := &PortainerEE{
 | 
				
			||||||
 | 
							WorkDir: "/home/oscarzhou/source/github.com/portainer/portainer-ee",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						utils.HighlightPrint("Your portainer EE repository work directory is ")
 | 
				
			||||||
 | 
						fmt.Println(repo.WorkDir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return repo
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (repo *PortainerEE) Execute() error {
 | 
				
			||||||
 | 
						err := commands.ListBranches(repo.WorkDir)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if !utils.PromptContinue() {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						option := utils.PromptMenu(repo.listSubMenu)
 | 
				
			||||||
 | 
						switch option {
 | 
				
			||||||
 | 
						case ACTION_EE_BUILD_ALL:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case ACTION_EE_RUN_FRONTEND:
 | 
				
			||||||
 | 
							commands.RunPortainerClient(repo.WorkDir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (repo *PortainerEE) listSubMenu() {
 | 
				
			||||||
 | 
						utils.MenuPrint("Do you want?", `
 | 
				
			||||||
 | 
					 1. Build both front-end and backend
 | 
				
			||||||
 | 
					 2. Run front-end only
 | 
				
			||||||
 | 
					 3. Run backend only
 | 
				
			||||||
 | 
					 4. Validate both fornt-end and backend before commit 
 | 
				
			||||||
 | 
					 5. Validate front-end only before commit
 | 
				
			||||||
 | 
					 6. Validate backend only before commit
 | 
				
			||||||
 | 
					 7. Run unit tests for both front-end and backend
 | 
				
			||||||
 | 
					 8. Run unit tests for front-end only
 | 
				
			||||||
 | 
					 9. Run unit tests for backend only`)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										16
									
								
								go/tasks/build_all.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								go/tasks/build_all.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					package tasks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "ocl/portainer-devtool/configs"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type BuildAllTask struct {
 | 
				
			||||||
 | 
						Config *configs.Config
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (task *BuildAllTask) Execute() error {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (task *BuildAllTask) String() string {
 | 
				
			||||||
 | 
						return "Build all"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										15
									
								
								go/tasks/build_backend.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								go/tasks/build_backend.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					package tasks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "ocl/portainer-devtool/configs"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type BuildBackendOnlyTask struct {
 | 
				
			||||||
 | 
						Config *configs.Config
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (task *BuildBackendOnlyTask) Execute() error {
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (task *BuildBackendOnlyTask) String() string {
 | 
				
			||||||
 | 
						return "Build backend only"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										35
									
								
								go/tasks/code_security_scan.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								go/tasks/code_security_scan.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					package tasks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"ocl/portainer-devtool/utils"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CodeSecurityScanTask struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewCodeSecurityScanTask() *CodeSecurityScanTask {
 | 
				
			||||||
 | 
						return &CodeSecurityScanTask{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (task *CodeSecurityScanTask) Execute() error {
 | 
				
			||||||
 | 
						utils.SuccessPrint(`
 | 
				
			||||||
 | 
					        1. Scan client with snyk: "snyk test"
 | 
				
			||||||
 | 
					        2. Scan server with snyk: "cd api && snyk test"
 | 
				
			||||||
 | 
					        3. If snyk is not authenticated: "snyk auth"
 | 
				
			||||||
 | 
					        4. Specify the severity threshold: "snyk test --severity-threshold=<low|medium|high|critical>"
 | 
				
			||||||
 | 
					        5. Other commands with snyk: "snyk --help"
 | 
				
			||||||
 | 
						`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						utils.SuccessPrint(`
 | 
				
			||||||
 | 
					        Steps to scan portainer image with Trivy:
 | 
				
			||||||
 | 
					        1. Build the local image: "docker build -t oscarzhou/portainer:dev-ee -f build/linux/Dockfile ."
 | 
				
			||||||
 | 
					        2. Scan with trivy: 'docker run --rm -v "/var/run/docker.sock":"/var/run/docker.sock" aquasec/trivy:latest image oscarzhou/portainer:dev-ee'
 | 
				
			||||||
 | 
					        3. Other commands with trivy: 'docker run --rm -v "/var/run/docker.sock":"/var/run/docker.sock" aquasec/trivy:latest --help'	
 | 
				
			||||||
 | 
						`)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (task *CodeSecurityScanTask) String() string {
 | 
				
			||||||
 | 
						return "Code Security Scan"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										48
									
								
								go/tasks/curl_lookup.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								go/tasks/curl_lookup.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					package tasks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"ocl/portainer-devtool/utils"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CurlLookupTask struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewCurlLookupTask() *CurlLookupTask {
 | 
				
			||||||
 | 
						return &CurlLookupTask{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (task *CurlLookupTask) Execute() error {
 | 
				
			||||||
 | 
						var option string
 | 
				
			||||||
 | 
						utils.InputPrint("1.POST 2.GET 3.PUT 4.DELETE: ")
 | 
				
			||||||
 | 
						fmt.Scanf("%s", &option)
 | 
				
			||||||
 | 
						switch option {
 | 
				
			||||||
 | 
						case "1", "POST", "post":
 | 
				
			||||||
 | 
							utils.HighlightPrint("POST Command:")
 | 
				
			||||||
 | 
							utils.SuccessPrint("curl -d '{\"repository\":\"https://github.com/portainer/portainer-ee\",\"username\":\"oscarzhou\", \"password\":\"your PAT\"}' -H 'Content-Type: application/json' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsInNjb3BlIjoiZGVmYXVsdCIsImZvcmNlQ2hhbmdlUGFzc3dvcmQiOmZhbHNlLCJleHAiOjE2NjAwMzQ2MjUsImlhdCI6MTY2MDAwNTgyNX0.S0UbPO4POD9kbuWOmvO9WR6LY6v424bpGw46rlEkNs0' http://127.0.0.1:9000/api/gitops/repo/refs")
 | 
				
			||||||
 | 
							break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case "2", "GET", "get":
 | 
				
			||||||
 | 
							utils.HighlightPrint("GET Command:")
 | 
				
			||||||
 | 
							utils.SuccessPrint("curl -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsInNjb3BlIjoiZGVmYXVsdCIsImZvcmNlQ2hhbmdlUGFzc3dvcmQiOmZhbHNlLCJleHAiOjE2NTUxMTg2ODUsImlhdCI6MTY1NTA4OTg4NX0.mJSZomeiEpRlz36MxSsLFWpUbA0BHRXWYijsZAo1NWc' http://127.0.0.1:9000/api/users/1/gitcredentials")
 | 
				
			||||||
 | 
							break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case "3", "PUT", "put":
 | 
				
			||||||
 | 
							utils.HighlightPrint("PUT Command:")
 | 
				
			||||||
 | 
							utils.SuccessPrint(`curl -X PUT http://127.0.0.1:9000/api/users/1/gitcredentials/11 -d '{"name":"test-credential-11","username":"cred11", "password":"cred11"}' -H 'Content-Type: application/json' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsInNjb3BlIjoiZGVmYXVsdCIsImZvcmNlQ2hhbmdlUGFzc3dvcmQiOmZhbHNlLCJleHAiOjE2NTcwODQ5MzUsImlhdCI6MTY1NzA1NjEzNX0.kUhkhhSt4WH33Q3hYzLwsYDv1a9a2ygCi6p8MkKMbwc'`)
 | 
				
			||||||
 | 
							break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						case "4", "DELETE", "delete":
 | 
				
			||||||
 | 
							utils.HighlightPrint("DELETE Command:")
 | 
				
			||||||
 | 
							utils.SuccessPrint(`curl -X DELETE http://192.168.1.109:9000/api/users/1/gitcredentials/1 -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsInNjb3BlIjoiZGVmYXVsdCIsImZvcmNlQ2hhbmdlUGFzc3dvcmQiOmZhbHNlLCJleHAiOjE2NTQ3NTc1NzYsImlhdCI6MTY1NDcyODc3Nn0.GlxGmL6XTTH29Ns8aRnX5qp1qBfDVF2zaPzuSmG7qUs'`)
 | 
				
			||||||
 | 
							break
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return fmt.Errorf("No option %v\n", option)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (task *CurlLookupTask) String() string {
 | 
				
			||||||
 | 
						return "Lookup Curl Commands"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								go/tasks/exit.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								go/tasks/exit.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					package tasks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "errors"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ExitTask struct {
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewExitTask() *ExitTask {
 | 
				
			||||||
 | 
						return &ExitTask{}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (task *ExitTask) Execute() error {
 | 
				
			||||||
 | 
						return errors.New("exit")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (task *ExitTask) String() string {
 | 
				
			||||||
 | 
						return "Exit"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										57
									
								
								go/tasks/jwt_token_gen.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								go/tasks/jwt_token_gen.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,57 @@
 | 
				
			|||||||
 | 
					package tasks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bytes"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"ocl/portainer-devtool/configs"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type GenerateJwtTokenTask struct {
 | 
				
			||||||
 | 
						Config *configs.Config
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type GenerateJwtTokenResponse struct {
 | 
				
			||||||
 | 
						JWT string `json:"jwt"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewGenerateJwtTokenTask(cfg *configs.Config) *GenerateJwtTokenTask {
 | 
				
			||||||
 | 
						return &GenerateJwtTokenTask{
 | 
				
			||||||
 | 
							Config: cfg,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (task *GenerateJwtTokenTask) Execute() error {
 | 
				
			||||||
 | 
						postBody, _ := json.Marshal(map[string]string{
 | 
				
			||||||
 | 
							"username": task.Config.LoginCredential.Username,
 | 
				
			||||||
 | 
							"password": task.Config.LoginCredential.Password,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						responseBody := bytes.NewBuffer(postBody)
 | 
				
			||||||
 | 
						resp, err := http.Post(task.Config.LoginCredential.Address, "application/json", responseBody)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("http requset error: %s", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer resp.Body.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						//Read the response body
 | 
				
			||||||
 | 
						body, err := ioutil.ReadAll(resp.Body)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return fmt.Errorf("failed to parse the response body: %s", err.Error())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var ret GenerateJwtTokenResponse
 | 
				
			||||||
 | 
						err = json.Unmarshal(body, &ret)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Printf("jwt token is:\n%s\n", ret.JWT)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (task *GenerateJwtTokenTask) String() string {
 | 
				
			||||||
 | 
						return "Generate JWT Token"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										31
									
								
								go/tasks/list_dev_tool_cmd.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								go/tasks/list_dev_tool_cmd.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					package tasks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"ocl/portainer-devtool/configs"
 | 
				
			||||||
 | 
						"ocl/portainer-devtool/tasks/subtasks"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ListDevToolCommandTask struct {
 | 
				
			||||||
 | 
						Config *configs.Config
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewListDevToolCommandTask(cfg *configs.Config) *ListDevToolCommandTask {
 | 
				
			||||||
 | 
						return &ListDevToolCommandTask{
 | 
				
			||||||
 | 
							Config: cfg,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (task *ListDevToolCommandTask) Execute() error {
 | 
				
			||||||
 | 
						subTaskItems := []Tasker{
 | 
				
			||||||
 | 
							subtasks.NewListVolumeSubTask(task.Config),
 | 
				
			||||||
 | 
							subtasks.NewListRepositorySubTask(task.Config),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ListCommandMenu(subTaskItems, "Which management commands do you want to choose:")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (task *ListDevToolCommandTask) String() string {
 | 
				
			||||||
 | 
						return "List Dev Tool Commands"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										34
									
								
								go/tasks/subtasks/list_repository.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								go/tasks/subtasks/list_repository.go
									
									
									
									
									
										Normal 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"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										51
									
								
								go/tasks/subtasks/list_volume.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								go/tasks/subtasks/list_volume.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					package subtasks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io/fs"
 | 
				
			||||||
 | 
						"ocl/portainer-devtool/configs"
 | 
				
			||||||
 | 
						"ocl/portainer-devtool/utils"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ListVolumeSubTask struct {
 | 
				
			||||||
 | 
						Config *configs.Config
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewListVolumeSubTask(cfg *configs.Config) *ListVolumeSubTask {
 | 
				
			||||||
 | 
						return &ListVolumeSubTask{
 | 
				
			||||||
 | 
							Config: cfg,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (task *ListVolumeSubTask) Execute() error {
 | 
				
			||||||
 | 
						utils.HighlightPrint(fmt.Sprintf("Volume path: %s", task.Config.VolumePath))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						volumeList := []string{" "}
 | 
				
			||||||
 | 
						filepath.WalkDir(task.Config.VolumePath, func(path string, d fs.DirEntry, err error) error {
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if path == task.Config.VolumePath {
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if d.IsDir() {
 | 
				
			||||||
 | 
								if utils.MatchPathLength(task.Config.VolumePath, path, 1) {
 | 
				
			||||||
 | 
									volumeList = append(volumeList, d.Name())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						utils.SuccessPrint(strings.Join(volumeList, "\n"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (task *ListVolumeSubTask) String() string {
 | 
				
			||||||
 | 
						return "List Volumes"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										54
									
								
								go/tasks/tasker.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								go/tasks/tasker.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
				
			|||||||
 | 
					package tasks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"ocl/portainer-devtool/utils"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Tasker interface {
 | 
				
			||||||
 | 
						Execute() error
 | 
				
			||||||
 | 
						String() string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// ListCommandMenu iterates task items to display them // on the screen as the menu options
 | 
				
			||||||
 | 
					func ListCommandMenu(taskItems []Tasker, menuDesp string) error {
 | 
				
			||||||
 | 
						taskItems = append(taskItems, NewExitTask())
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							printMainMenu := func() {
 | 
				
			||||||
 | 
								taskNames := []string{}
 | 
				
			||||||
 | 
								for _, task := range taskItems {
 | 
				
			||||||
 | 
									taskNames = append(taskNames, task.String())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								utils.PrintMenu(menuDesp, taskNames)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								// utils.MenuPrint("Which repository or action do you want to operate:", `
 | 
				
			||||||
 | 
								//  1. Portainer EE Repository
 | 
				
			||||||
 | 
								//  2. Portainer CE Repository
 | 
				
			||||||
 | 
								//  3. Portainer Agent Repository
 | 
				
			||||||
 | 
								//  4. Others
 | 
				
			||||||
 | 
								//  5. Quit`)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							option := utils.SelectMenuItem(printMainMenu)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							index, err := strconv.Atoi(option)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								utils.ErrorPrint("please type the option number\n")
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if index < 1 || index > len(taskItems) {
 | 
				
			||||||
 | 
								utils.ErrorPrint(fmt.Sprintf("no such option %s, please select again\n", option))
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err = taskItems[index-1].Execute()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								utils.ErrorPrint(err.Error())
 | 
				
			||||||
 | 
								os.Exit(1)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										45
									
								
								go/utils/command.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								go/utils/command.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
				
			|||||||
 | 
					package utils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"bufio"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"os/exec"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func RunCommandWithStdoutPipe(workdir, progName string, args ...string) error {
 | 
				
			||||||
 | 
						cmd := exec.Command(progName, args...)
 | 
				
			||||||
 | 
						cmd.Dir = workdir
 | 
				
			||||||
 | 
						out, err := cmd.StdoutPipe()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						scanner := bufio.NewScanner(out)
 | 
				
			||||||
 | 
						go func() {
 | 
				
			||||||
 | 
							counter := 0
 | 
				
			||||||
 | 
							for scanner.Scan() {
 | 
				
			||||||
 | 
								if counter > 10 {
 | 
				
			||||||
 | 
									// Swallow the output
 | 
				
			||||||
 | 
									if counter%50 == 0 {
 | 
				
			||||||
 | 
										fmt.Printf("output %d lines in total.\n", counter)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									counter++
 | 
				
			||||||
 | 
									continue
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								PrintOutput("", scanner.Bytes())
 | 
				
			||||||
 | 
								counter++
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = cmd.Start()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = cmd.Wait()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								go/utils/path.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								go/utils/path.go
									
									
									
									
									
										Normal 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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										87
									
								
								go/utils/print.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								go/utils/print.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,87 @@
 | 
				
			|||||||
 | 
					package utils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						colorReset string = "\033[0m"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						colorRed    string = "\033[31m"
 | 
				
			||||||
 | 
						colorGreen  string = "\033[32m"
 | 
				
			||||||
 | 
						colorYellow string = "\033[33m"
 | 
				
			||||||
 | 
						colorBlue   string = "\033[34m"
 | 
				
			||||||
 | 
						colorPurple string = "\033[35m"
 | 
				
			||||||
 | 
						colorCyan   string = "\033[36m"
 | 
				
			||||||
 | 
						colorWhite  string = "\033[37m"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func PrintOutput(message string, output []byte) {
 | 
				
			||||||
 | 
						if message != "" {
 | 
				
			||||||
 | 
							HighlightPrint(message)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						fmt.Println(string(output))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func HighlightPrint(message string) {
 | 
				
			||||||
 | 
						fmt.Println()
 | 
				
			||||||
 | 
						fmt.Println(colorBlue, message, colorReset)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func SuccessPrint(message string) {
 | 
				
			||||||
 | 
						fmt.Println()
 | 
				
			||||||
 | 
						fmt.Println(colorGreen, message, colorReset)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ErrorPrint(message string) {
 | 
				
			||||||
 | 
						fmt.Println()
 | 
				
			||||||
 | 
						fmt.Println(colorRed, message, colorReset)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func WarnPrint(message string) {
 | 
				
			||||||
 | 
						fmt.Println()
 | 
				
			||||||
 | 
						fmt.Println(colorPurple, message, colorReset)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func InputPrint(message string) {
 | 
				
			||||||
 | 
						// adding \n before setting colorful output can
 | 
				
			||||||
 | 
						// remove the first space in the colorful output
 | 
				
			||||||
 | 
						fmt.Println()
 | 
				
			||||||
 | 
						fmt.Println(colorYellow, message, colorReset)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func PrintMenu(question string, taskNames []string) {
 | 
				
			||||||
 | 
						if question != "" {
 | 
				
			||||||
 | 
							InputPrint(fmt.Sprintf("[%s]", question))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// adding \n before setting colorful output can
 | 
				
			||||||
 | 
						// remove the first space in the colorful output
 | 
				
			||||||
 | 
						menuContent := "\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for i, name := range taskNames {
 | 
				
			||||||
 | 
							menuContent += fmt.Sprintf("%d. %s\n", i+1, name)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Println(colorCyan, menuContent, colorReset)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func MenuPrint(question, menu string) {
 | 
				
			||||||
 | 
						if question != "" {
 | 
				
			||||||
 | 
							InputPrint(fmt.Sprintf("[%s]", question))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// 	menu := `
 | 
				
			||||||
 | 
						// 1. Build Portainer EE/CE All
 | 
				
			||||||
 | 
						// 2. Build Portainer EE/CE Frontend
 | 
				
			||||||
 | 
						// 3. Build Portainer EE/CE Backend
 | 
				
			||||||
 | 
						// 4. Generate Portainer EE/CE JWT
 | 
				
			||||||
 | 
						// 5. Run Before Commit [Portainer EE/CE]
 | 
				
			||||||
 | 
						// 6. Get Portainer CE API Reference
 | 
				
			||||||
 | 
						// 7. Run Before Commit [k8s]
 | 
				
			||||||
 | 
						// 8. Build Portainer Agent
 | 
				
			||||||
 | 
						// 9. Cleanup Temporary Volume
 | 
				
			||||||
 | 
						// 	`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fmt.Println(colorCyan, menu, colorReset)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										39
									
								
								go/utils/prompt.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								go/utils/prompt.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					package utils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func PromptContinue() bool {
 | 
				
			||||||
 | 
						ret := strings.ToLower(Prompt("Continue (y/n)"))
 | 
				
			||||||
 | 
						if ret == "y" || ret == "yes" {
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func PromptConfirm(question string) bool {
 | 
				
			||||||
 | 
						ret := Prompt(fmt.Sprintf("%s (y/n)?", question))
 | 
				
			||||||
 | 
						if ret == "y" || ret == "yes" {
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return false
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func SelectMenuItem(listMenu func()) string {
 | 
				
			||||||
 | 
						listMenu()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var option string
 | 
				
			||||||
 | 
						fmt.Scanf("%s", &option)
 | 
				
			||||||
 | 
						return option
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func Prompt(question string) string {
 | 
				
			||||||
 | 
						fmt.Printf("%s %s :%s", colorYellow, question, colorReset)
 | 
				
			||||||
 | 
						var ret string
 | 
				
			||||||
 | 
						fmt.Scanf("%s", &ret)
 | 
				
			||||||
 | 
						return ret
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										183
									
								
								run.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										183
									
								
								run.sh
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,183 @@
 | 
				
			|||||||
 | 
					#!/bin/bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set -eu
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					source ./utils/common.sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					WORKDIR=/home/oscarzhou/source/github.com/portainer
 | 
				
			||||||
 | 
					GLOBAL_VOLUME=/home/oscarzhou/volumes
 | 
				
			||||||
 | 
					TRUE=0;
 | 
				
			||||||
 | 
					FALSE=1;
 | 
				
			||||||
 | 
					REPO_DIR=
 | 
				
			||||||
 | 
					REPO_VOLUME=
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function debug_portainer_client() {
 | 
				
			||||||
 | 
					    print_highlight "[debug portainer client]"
 | 
				
			||||||
 | 
					    yarn
 | 
				
			||||||
 | 
					    yarn start:client
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function generate_portainer_jwt_token() {
 | 
				
			||||||
 | 
					    print_highlight "[generate portainer jwt token]"
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					    read -p "Username(admin):" username
 | 
				
			||||||
 | 
					    if [ -z "$username" ]; then 
 | 
				
			||||||
 | 
					        username="admin";
 | 
				
			||||||
 | 
					    fi 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    read -p "Password(****):" password
 | 
				
			||||||
 | 
					    read -p "Address(http://127.0.0.1:9000):" address
 | 
				
			||||||
 | 
					    if [ -z "$address" ]; then 
 | 
				
			||||||
 | 
					        address="http://127.0.0.1:9000";
 | 
				
			||||||
 | 
					    fi 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    payload="{\"username\":\"${username}\",\"password\":\"${password}\"}"
 | 
				
			||||||
 | 
					    curl -d ${payload} -H 'Content-Type: application/json' "${address}/api/auth"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function list_portainer_ee_menu() {
 | 
				
			||||||
 | 
					    print_highlight "Your current working directory is ${WORKDIR}/portainer-ee"
 | 
				
			||||||
 | 
					    if ! prompt_continue; then 
 | 
				
			||||||
 | 
					        exit;
 | 
				
			||||||
 | 
					    fi 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    REPO_DIR=${WORKDIR}/portainer-ee
 | 
				
			||||||
 | 
					    print_highlight "Your current volume is ${VOLUME}/portainer-ee-data"
 | 
				
			||||||
 | 
					    if ! prompt_continue; then
 | 
				
			||||||
 | 
					        exit;
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    REPO_VOLUME=${VOLUME}/portainer-ee-data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    PS3='Please select the action: '
 | 
				
			||||||
 | 
					    OPTIONS=(
 | 
				
			||||||
 | 
					        'Debug Client'
 | 
				
			||||||
 | 
					        'Lint Client'
 | 
				
			||||||
 | 
					        'Run Unit Test for Client'
 | 
				
			||||||
 | 
					        'Before Commit'
 | 
				
			||||||
 | 
					        'Build Client'
 | 
				
			||||||
 | 
					        'Build Server'
 | 
				
			||||||
 | 
					        'Run Unit Test for Server'
 | 
				
			||||||
 | 
					        'Get Portainer CE API Reference'
 | 
				
			||||||
 | 
					        'Quit'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    select opt in "${OPTIONS[@]}"
 | 
				
			||||||
 | 
					    do
 | 
				
			||||||
 | 
					        case $opt in 
 | 
				
			||||||
 | 
					            'Debug Client')
 | 
				
			||||||
 | 
					                debug_portainer_client
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					            'PortainerCE')
 | 
				
			||||||
 | 
					                build_portainer_frontend
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					            'Build Portainer EE/CE Backend')
 | 
				
			||||||
 | 
					                build_portainer_backend
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					            'Generate Portainer EE/CE JWT')
 | 
				
			||||||
 | 
					                generate_portainer_jwt
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					            'Run Before Commit [Portainer EE/CE]')
 | 
				
			||||||
 | 
					                run_before_commit
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					            'Get Portainer CE API Reference')
 | 
				
			||||||
 | 
					                get_portainer_ce_api_reference
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					            'Quit')
 | 
				
			||||||
 | 
					                break
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					        esac
 | 
				
			||||||
 | 
					    done
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function code_security_scan_summary() {
 | 
				
			||||||
 | 
					    echo "
 | 
				
			||||||
 | 
					        1. Scan client with snyk: $(print_highlight "snyk test")
 | 
				
			||||||
 | 
					        2. Scan server with snyk: $(print_highlight "cd api && snyk test")
 | 
				
			||||||
 | 
					        3. If snyk is not authenticated: $(print_highlight "snyk auth")
 | 
				
			||||||
 | 
					        4. Specify the severity threshold: $(print_highlight "snyk test --severity-threshold=<low|medium|high|critical>")
 | 
				
			||||||
 | 
					        5. Other commands with snyk: $(print_highlight "snyk --help")
 | 
				
			||||||
 | 
					    "
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    echo "
 | 
				
			||||||
 | 
					        Steps to scan portainer image with Trivy:
 | 
				
			||||||
 | 
					        1. Build the local image: $(print_highlight "docker build -t oscarzhou/portainer:dev-ee -f build/linux/Dockfile .")
 | 
				
			||||||
 | 
					        2. Scan with trivy: $(print_highlight 'docker run --rm -v "/var/run/docker.sock":"/var/run/docker.sock" aquasec/trivy:latest image oscarzhou/portainer:dev-ee')
 | 
				
			||||||
 | 
					        3. Other commands with trivy: $(print_highlight 'docker run --rm -v "/var/run/docker.sock":"/var/run/docker.sock" aquasec/trivy:latest --help')
 | 
				
			||||||
 | 
					    "
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function look_up_curl_commands() {
 | 
				
			||||||
 | 
					    input "1.POST 2.GET 3.PUT 4.DELETE :" option
 | 
				
			||||||
 | 
					    if [[ "${option}" == "1" ]]; then 
 | 
				
			||||||
 | 
					        echo "$(print_highlight "curl -d '{\"repository\":\"https://github.com/portainer/portainer-ee\",\"username\":\"oscarzhou\", \"password\":\"your PAT\"}' -H 'Content-Type: application/json' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsInNjb3BlIjoiZGVmYXVsdCIsImZvcmNlQ2hhbmdlUGFzc3dvcmQiOmZhbHNlLCJleHAiOjE2NjAwMzQ2MjUsImlhdCI6MTY2MDAwNTgyNX0.S0UbPO4POD9kbuWOmvO9WR6LY6v424bpGw46rlEkNs0' http://127.0.0.1:9000/api/gitops/repo/refs")"
 | 
				
			||||||
 | 
					    elif [[ "${option}" == "2" ]]; then 
 | 
				
			||||||
 | 
					        echo "$(print_highlight "curl -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsInNjb3BlIjoiZGVmYXVsdCIsImZvcmNlQ2hhbmdlUGFzc3dvcmQiOmZhbHNlLCJleHAiOjE2NTUxMTg2ODUsImlhdCI6MTY1NTA4OTg4NX0.mJSZomeiEpRlz36MxSsLFWpUbA0BHRXWYijsZAo1NWc' http://127.0.0.1:9000/api/users/1/gitcredentials")"
 | 
				
			||||||
 | 
					    elif [[ "${option}" == "3" ]]; then 
 | 
				
			||||||
 | 
					        echo "$(print_highlight "curl -X PUT http://127.0.0.1:9000/api/users/1/gitcredentials/11 -d '{"name":"test-credential-11","username":"cred11", "password":"cred11"}' -H 'Content-Type: application/json' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsInNjb3BlIjoiZGVmYXVsdCIsImZvcmNlQ2hhbmdlUGFzc3dvcmQiOmZhbHNlLCJleHAiOjE2NTcwODQ5MzUsImlhdCI6MTY1NzA1NjEzNX0.kUhkhhSt4WH33Q3hYzLwsYDv1a9a2ygCi6p8MkKMbwc'")"
 | 
				
			||||||
 | 
					    elif [[ "${option}" == "4" ]]; then 
 | 
				
			||||||
 | 
					        echo "$(print_highlight "curl -X DELETE http://192.168.1.109:9000/api/users/1/gitcredentials/1 -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsInNjb3BlIjoiZGVmYXVsdCIsImZvcmNlQ2hhbmdlUGFzc3dvcmQiOmZhbHNlLCJleHAiOjE2NTQ3NTc1NzYsImlhdCI6MTY1NDcyODc3Nn0.GlxGmL6XTTH29Ns8aRnX5qp1qBfDVF2zaPzuSmG7qUs'")"
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        print_error "Invalid option"
 | 
				
			||||||
 | 
					    fi
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function menu() {
 | 
				
			||||||
 | 
					    PS3='Please select the action/repository: '
 | 
				
			||||||
 | 
					    OPTIONS=(
 | 
				
			||||||
 | 
					        'PortainerEE'
 | 
				
			||||||
 | 
					        'PortainerCE'
 | 
				
			||||||
 | 
					        'Build Portainer EE/CE Backend'
 | 
				
			||||||
 | 
					        'Generate Portainer JWT Token'
 | 
				
			||||||
 | 
					        'Run Before Commit [Portainer EE/CE]'
 | 
				
			||||||
 | 
					        'Get Portainer CE API Reference'
 | 
				
			||||||
 | 
					        'Look Up Curl Commands'
 | 
				
			||||||
 | 
					        'Code Security Scan'
 | 
				
			||||||
 | 
					        'Cleanup Temporary Volume'
 | 
				
			||||||
 | 
					        'Quit'
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    select opt in "${OPTIONS[@]}"
 | 
				
			||||||
 | 
					    do
 | 
				
			||||||
 | 
					        case $opt in 
 | 
				
			||||||
 | 
					            'PortainerEE')
 | 
				
			||||||
 | 
					                list_portainer_ee_menu
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					            'PortainerCE')
 | 
				
			||||||
 | 
					                build_portainer_frontend
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					            'Build Portainer EE/CE Backend')
 | 
				
			||||||
 | 
					                build_portainer_backend
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					            'Generate Portainer JWT Token')
 | 
				
			||||||
 | 
					                generate_portainer_jwt
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					            'Run Before Commit [Portainer EE/CE]')
 | 
				
			||||||
 | 
					                run_before_commit
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					            'Get Portainer CE API Reference')
 | 
				
			||||||
 | 
					                get_portainer_ce_api_reference
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					            'Look Up Curl Commands')
 | 
				
			||||||
 | 
					                look_up_curl_commands
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					            'Code Security Scan')
 | 
				
			||||||
 | 
					                code_security_scan_summary
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					            'Cleanup Temporary Volume')
 | 
				
			||||||
 | 
					                cleanup_temporary_volume 
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					            'Quit')
 | 
				
			||||||
 | 
					                break
 | 
				
			||||||
 | 
					                ;;
 | 
				
			||||||
 | 
					        esac
 | 
				
			||||||
 | 
					    done
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# check if the function exists (bash specific)
 | 
				
			||||||
 | 
					if [ "$#" -eq 0 ]; then
 | 
				
			||||||
 | 
					  menu
 | 
				
			||||||
 | 
					else 
 | 
				
			||||||
 | 
					  "$@"
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
@ -1,5 +1,7 @@
 | 
				
			|||||||
#!/bin/bash
 | 
					#!/bin/bash
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					TRUE=0;
 | 
				
			||||||
 | 
					FALSE=1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ERROR_COLOR='\033[0;31m';
 | 
					ERROR_COLOR='\033[0;31m';
 | 
				
			||||||
HIGHLIGHT_COLOR='\033[0;32m';
 | 
					HIGHLIGHT_COLOR='\033[0;32m';
 | 
				
			||||||
@ -18,3 +20,12 @@ function print_error() {
 | 
				
			|||||||
function input() {
 | 
					function input() {
 | 
				
			||||||
  read -p "$(echo -e ${INPUT_COLOR}$1 ${NO_COLOR})" $2
 | 
					  read -p "$(echo -e ${INPUT_COLOR}$1 ${NO_COLOR})" $2
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function prompt_continue() {
 | 
				
			||||||
 | 
					  read -p "Continue N/(Y)?" is_continue
 | 
				
			||||||
 | 
					  if [[ "${is_continue}" == "N" || "${is_continue}" == "n" ]]; then 
 | 
				
			||||||
 | 
					    return $FALSE; 
 | 
				
			||||||
 | 
					  fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return $TRUE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user