Compare commits
No commits in common. "927d6e92b0ff77e836092ec22cbbd18a11950142" and "7b66f95832fdaf1d6341930d18cebc5691a43718" have entirely different histories.
927d6e92b0
...
7b66f95832
1
go/.gitignore
vendored
1
go/.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
/test
|
|
@ -1,18 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
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")
|
|
||||||
}
|
|
@ -1,153 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
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
26
go/main.go
@ -1,26 +0,0 @@
|
|||||||
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:")
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
package repositories
|
|
||||||
|
|
||||||
type Actioner interface {
|
|
||||||
Execute() error
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
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`)
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
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"
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
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"
|
|
||||||
}
|
|
@ -1,35 +0,0 @@
|
|||||||
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"
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
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"
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
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"
|
|
||||||
}
|
|
@ -1,57 +0,0 @@
|
|||||||
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"
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
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"
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
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"
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
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"
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,18 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,87 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
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
183
run.sh
@ -1,183 +0,0 @@
|
|||||||
#!/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,7 +1,5 @@
|
|||||||
#!/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';
|
||||||
@ -20,12 +18,3 @@ 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…
Reference in New Issue
Block a user