2022-09-21 15:00:10 +10:00
|
|
|
package configs
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
2022-12-28 12:39:18 +11:00
|
|
|
"ocl/portainer-devtool/utils"
|
2022-09-21 15:00:10 +10:00
|
|
|
"os"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
ConfigFileName string = ".devtool"
|
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
ErrConfigNotInitialized error = errors.New("Config file is not initialized")
|
|
|
|
)
|
|
|
|
|
|
|
|
type Config struct {
|
2022-12-25 23:10:59 +11:00
|
|
|
// ProjectPath is the location on your host where all dev relevant folders will be stored to
|
2022-09-21 15:00:10 +10:00
|
|
|
ProjectPath string
|
2022-12-25 23:10:59 +11:00
|
|
|
// VolumePath is where all the persisitant data will be stored
|
2022-09-21 15:00:10 +10:00
|
|
|
VolumePath string
|
2022-12-25 23:10:59 +11:00
|
|
|
// Credentials for UI login
|
2022-09-21 15:00:10 +10:00
|
|
|
LoginCredential LoginCredential
|
2022-12-25 23:10:59 +11:00
|
|
|
// key is repository name, for example, "repository-ee"
|
2022-09-21 15:00:10 +10:00
|
|
|
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 {
|
2022-09-22 07:24:10 +10:00
|
|
|
return initializeConfig(file)
|
2022-09-21 15:00:10 +10:00
|
|
|
}
|
2022-09-22 07:24:10 +10:00
|
|
|
return nil, err
|
2022-09-21 15:00:10 +10:00
|
|
|
}
|
|
|
|
|
2022-09-22 07:24:10 +10:00
|
|
|
defer file.Close()
|
|
|
|
|
2022-09-21 15:00:10 +10:00
|
|
|
return getConfig(file)
|
|
|
|
}
|
|
|
|
|
2022-09-22 07:24:10 +10:00
|
|
|
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")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-25 23:10:59 +11:00
|
|
|
// 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
|
2022-09-21 15:00:10 +10:00
|
|
|
func initializeConfig(w io.WriteCloser) (*Config, error) {
|
|
|
|
config := &Config{}
|
2022-12-28 12:39:18 +11:00
|
|
|
config.ProjectPath = utils.Prompt("Specify Git Project Root Path")
|
2022-09-21 15:00:10 +10:00
|
|
|
|
2022-12-28 12:39:18 +11:00
|
|
|
// analyze all the repositories in the project root path
|
|
|
|
// add the parsed information to RepositoryConfig
|
|
|
|
config.configureRepositories()
|
2022-09-21 15:00:10 +10:00
|
|
|
|
2022-12-28 12:39:18 +11:00
|
|
|
// generate volume path automatically
|
|
|
|
config.VolumePath = utils.Prompt("Specify Volume Path")
|
2022-09-21 15:00:10 +10:00
|
|
|
|
2022-12-28 12:39:18 +11:00
|
|
|
config.configureLoginCredential()
|
2022-09-21 15:00:10 +10:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2022-09-22 07:24:10 +10:00
|
|
|
func getConfig(f *os.File) (*Config, error) {
|
2022-09-21 15:00:10 +10:00
|
|
|
config := &Config{}
|
2022-09-22 07:24:10 +10:00
|
|
|
|
|
|
|
info, err := f.Stat()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
bytes := make([]byte, info.Size())
|
|
|
|
n, err := f.Read(bytes)
|
2022-09-21 15:00:10 +10:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
2022-09-22 07:24:10 +10:00
|
|
|
if n == 0 {
|
|
|
|
// The file exists, but it's empty file, so we need to initalize
|
|
|
|
return initializeConfig(f)
|
|
|
|
}
|
|
|
|
|
2022-09-21 15:00:10 +10:00
|
|
|
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)
|
|
|
|
}
|