168 lines
3.4 KiB
Go
168 lines
3.4 KiB
Go
package config
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"github.com/cirruslabs/orchard/internal/netconstants"
|
|
"github.com/cirruslabs/orchard/internal/orchardhome"
|
|
"gopkg.in/yaml.v3"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
const configName = "orchard.yml"
|
|
|
|
type Handle struct {
|
|
configPath string
|
|
}
|
|
|
|
func NewHandle() (*Handle, error) {
|
|
orchardHomeDir, err := orchardhome.Path()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &Handle{
|
|
configPath: filepath.Join(orchardHomeDir, configName),
|
|
}, nil
|
|
}
|
|
|
|
func (handle *Handle) Config() (*Config, error) {
|
|
config := Config{
|
|
Contexts: map[string]Context{},
|
|
}
|
|
|
|
configBytes, err := os.ReadFile(handle.configPath)
|
|
if err != nil {
|
|
// Handle a case where the config file is not created yet
|
|
if errors.Is(err, os.ErrNotExist) {
|
|
return &Config{
|
|
Contexts: map[string]Context{},
|
|
}, nil
|
|
}
|
|
|
|
return nil, fmt.Errorf("%w: %v", ErrConfigReadFailed, err)
|
|
}
|
|
|
|
if err := yaml.Unmarshal(configBytes, &config); err != nil {
|
|
return nil, fmt.Errorf("%w: invalid YAML: %v", ErrConfigReadFailed, err)
|
|
}
|
|
|
|
return &config, nil
|
|
}
|
|
|
|
func (handle *Handle) SetConfig(config *Config) error {
|
|
configBytes, err := yaml.Marshal(config)
|
|
if err != nil {
|
|
return fmt.Errorf("%w: failed to marshal YAML: %v", ErrConfigWriteFailed, err)
|
|
}
|
|
|
|
if err := os.WriteFile(handle.configPath, configBytes, 0600); err != nil {
|
|
return fmt.Errorf("%w: %v", ErrConfigWriteFailed, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (handle *Handle) CreateContext(name string, context Context, force bool) error {
|
|
unlock, err := handle.Lock()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer unlock()
|
|
|
|
config, err := handle.Config()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, exists := config.RetrieveContext(name)
|
|
if exists && !force {
|
|
return fmt.Errorf("%w: context %q already exists", ErrConfigConflict, name)
|
|
}
|
|
|
|
config.SetContext(name, context)
|
|
|
|
return handle.SetConfig(config)
|
|
}
|
|
|
|
func (handle *Handle) DefaultContext() (Context, error) {
|
|
unlock, err := handle.Lock()
|
|
if err != nil {
|
|
return Context{}, err
|
|
}
|
|
defer unlock()
|
|
|
|
config, err := handle.Config()
|
|
if err != nil {
|
|
return Context{}, err
|
|
}
|
|
|
|
defaultContext, ok := config.RetrieveDefaultContext()
|
|
if !ok {
|
|
defaultContext = Context{
|
|
URL: fmt.Sprintf("http://127.0.0.1:%d", netconstants.DefaultControllerPort),
|
|
}
|
|
|
|
config.SetContext("default", defaultContext)
|
|
|
|
if err := handle.SetConfig(config); err != nil {
|
|
return Context{}, err
|
|
}
|
|
}
|
|
|
|
// Environment variable overrides
|
|
if url, ok := os.LookupEnv(OrchardURL); ok {
|
|
defaultContext.URL = url
|
|
}
|
|
if serviceAccountName, ok := os.LookupEnv(OrchardServiceAccountName); ok {
|
|
defaultContext.ServiceAccountName = serviceAccountName
|
|
}
|
|
if serviceAccountToken, ok := os.LookupEnv(OrchardServiceAccountToken); ok {
|
|
defaultContext.ServiceAccountToken = serviceAccountToken
|
|
}
|
|
|
|
return defaultContext, nil
|
|
}
|
|
|
|
func (handle *Handle) SetDefaultContext(name string) error {
|
|
unlock, err := handle.Lock()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer unlock()
|
|
|
|
config, err := handle.Config()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, ok := config.RetrieveContext(name)
|
|
if !ok {
|
|
return fmt.Errorf("%w: no such context: %q", ErrConfigConflict, name)
|
|
}
|
|
|
|
config.DefaultContext = name
|
|
|
|
return handle.SetConfig(config)
|
|
}
|
|
|
|
func (handle *Handle) DeleteContext(name string) error {
|
|
unlock, err := handle.Lock()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer unlock()
|
|
|
|
config, err := handle.Config()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := config.DeleteContext(name); err != nil {
|
|
return err
|
|
}
|
|
|
|
return handle.SetConfig(config)
|
|
}
|