portainer-devtool/go/configs/config.go

154 lines
3.4 KiB
Go

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)
}