-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from aztekas/test/cli
Restructure repository, add aux commands
- Loading branch information
Showing
18 changed files
with
984 additions
and
424 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,152 @@ | ||
package configcmd | ||
|
||
import ( | ||
"bytes" | ||
"errors" | ||
"fmt" | ||
"slices" | ||
|
||
"github.com/aztekas/cleura-client-go/cmd/cleura/utils" | ||
"github.com/spf13/viper" | ||
"github.com/urfave/cli/v2" | ||
"golang.org/x/exp/maps" | ||
"gopkg.in/yaml.v2" | ||
) | ||
|
||
type Config struct { | ||
ActiveConfig string `mapstructure:"active_configuration" yaml:"active_configuration"` | ||
Configurations map[string]Configuration `mapstructure:"configurations"` | ||
location string | ||
} | ||
type Configuration struct { | ||
Username string `mapstructure:"username" yaml:"username"` | ||
Token string `mapstructure:"token" yaml:"token"` | ||
DefaultDomainID string `mapstructure:"domain-id" yaml:"domain-id"` | ||
DefaultRegion string `mapstructure:"region" yaml:"region"` | ||
DefaultProjectID string `mapstructure:"project-id" yaml:"project-id"` | ||
//APIHost string `mapstructure:"api-host" yaml:"api-host"` | ||
} | ||
|
||
func (c *Config) SetActive(name string) error { | ||
viper.SetConfigFile(c.location) | ||
viper.SetConfigType("yaml") | ||
|
||
_, ok := c.Configurations[name] | ||
if !ok { | ||
return errors.New("error: specified configuration name is not present in configuration file") | ||
} | ||
c.ActiveConfig = name | ||
configByte, err := yaml.Marshal(c) | ||
if err != nil { | ||
return err | ||
} | ||
err = viper.ReadConfig(bytes.NewBuffer(configByte)) | ||
if err != nil { | ||
return err | ||
} | ||
err = viper.WriteConfig() | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func (c *Config) UpdateConfiguration(key string, value string) error { | ||
|
||
_, ok := c.Configurations[c.ActiveConfig] | ||
if !ok { | ||
return errors.New("error: no active configuration in configuration file") | ||
} | ||
viper.SetConfigFile(c.location) | ||
viper.SetConfigType("yaml") | ||
err := viper.ReadInConfig() | ||
if err != nil { | ||
return err | ||
} | ||
viper.Set("configurations."+c.ActiveConfig+"."+key, value) | ||
err = viper.WriteConfig() | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func (c *Config) PrintConfigurations() { | ||
if len(c.Configurations) > 0 { | ||
fmt.Printf("Available configurations: (in %s)\n", c.location) | ||
for i, conf := range maps.Keys(c.Configurations) { | ||
if conf == c.ActiveConfig { | ||
conf = conf + " (active)" | ||
} | ||
fmt.Printf("%d. %s\n", i, conf) | ||
} | ||
} else { | ||
fmt.Printf("no configurations found in configuration file: %s\n", c.location) | ||
} | ||
} | ||
|
||
func LoadConfiguration(path string) (*Config, error) { | ||
var config Config | ||
path, err := utils.ChoosePath(path) | ||
if err != nil { | ||
return nil, err | ||
} | ||
viper.SetConfigFile(path) | ||
viper.SetConfigType("yaml") | ||
err = viper.ReadInConfig() // Find and read the config file | ||
if err != nil { // Handle errors reading the config file | ||
return nil, fmt.Errorf("loadConfiguration: error reading config file: %w", err) | ||
} | ||
err = viper.Unmarshal(&config) | ||
if err != nil { | ||
return nil, err | ||
} | ||
config.location = path | ||
return &config, nil | ||
} | ||
|
||
// Get available configuration settings from supplied or default configuration file | ||
func TrySetConfigFromFile(c *cli.Context) error { | ||
var config *Config | ||
//ignore api-host as it always has default value | ||
//ignore path as it always has default value (%HOME/.config/cleura/config) | ||
var ignoreFlags = []string{"help", "api-host", "path"} | ||
config, err := LoadConfiguration(c.String("path")) | ||
if err != nil { | ||
fmt.Printf("Failed to read configuration file: %s, proceed with explicit configuration via flags and environment variables\n", err) | ||
return nil | ||
} | ||
activeConfig := config.ActiveConfig | ||
if activeConfig == "" { | ||
fmt.Printf("No active configuration found in %s, proceed with explicit configuration via flags and environment variables\n", config.location) | ||
return nil | ||
} | ||
// Get a map put of struct fields with yaml tag | ||
configFromFile, err := utils.ToMap(config.Configurations[activeConfig], "yaml") | ||
if err != nil { | ||
return err | ||
} | ||
|
||
//Iterate over all defined flags (set and unset) | ||
for _, flag := range c.Command.Flags { | ||
ok := c.IsSet(flag.Names()[0]) | ||
// Only set flags that are not already set directly of via environment variables | ||
if !ok && !slices.Contains(ignoreFlags, flag.Names()[0]) { | ||
c.Set(flag.Names()[0], configFromFile[flag.Names()[0]].(string)) | ||
} | ||
} | ||
//return fmt.Errorf("error: expected error") | ||
return nil | ||
} | ||
|
||
func Command() *cli.Command { | ||
return &cli.Command{ | ||
Name: "config", | ||
Description: "Command used for preparing cleura cli credentials and setting default parameter values", | ||
Subcommands: []*cli.Command{ | ||
setCommand(), | ||
listCommand(), | ||
showActiveCommand(), | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package configcmd | ||
|
||
import "github.com/urfave/cli/v2" | ||
|
||
func listCommand() *cli.Command { | ||
return &cli.Command{ | ||
Name: "list", | ||
Description: "List available configurations", | ||
Usage: "List available configurations defined in configuration file", | ||
Flags: []cli.Flag{ | ||
&cli.StringFlag{ | ||
Name: "path", | ||
Aliases: []string{"p"}, | ||
Usage: "Path to configuration file. $HOME/.config/cleura/config if not set", | ||
}, | ||
}, | ||
Action: func(ctx *cli.Context) error { | ||
var config *Config | ||
config, err := LoadConfiguration(ctx.String("path")) | ||
if err != nil { | ||
return err | ||
} | ||
config.PrintConfigurations() | ||
return nil | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package configcmd | ||
|
||
import "github.com/urfave/cli/v2" | ||
|
||
func setCommand() *cli.Command { | ||
return &cli.Command{ | ||
Name: "set", | ||
Description: "Set active configuration from the list of configurations defined in the configuration file", | ||
Usage: "Set active configuration from the list of configurations defined in the configuration file", | ||
Flags: []cli.Flag{ | ||
&cli.StringFlag{ | ||
Name: "name", | ||
Required: true, | ||
Aliases: []string{"n"}, | ||
Usage: "Configuration name", | ||
}, | ||
&cli.StringFlag{ | ||
Name: "path", | ||
Aliases: []string{"p"}, | ||
Usage: "Path to configuration file. $HOME/.config/cleura/config if not set", | ||
}, | ||
}, | ||
Action: func(ctx *cli.Context) error { | ||
var config *Config | ||
config, err := LoadConfiguration(ctx.String("path")) | ||
if err != nil { | ||
return err | ||
} | ||
err = config.SetActive(ctx.String("name")) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
|
||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package configcmd | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/urfave/cli/v2" | ||
) | ||
|
||
func showActiveCommand() *cli.Command { | ||
return &cli.Command{ | ||
Name: "show-active", | ||
Description: "Show currently active configuration", | ||
Usage: "Show currently active configuration", | ||
Flags: []cli.Flag{ | ||
&cli.StringFlag{ | ||
Name: "path", | ||
Aliases: []string{"p"}, | ||
Usage: "Path to configuration file. $HOME/.config/cleura/config if not set", | ||
}, | ||
}, | ||
Action: func(ctx *cli.Context) error { | ||
var config *Config | ||
config, err := LoadConfiguration(ctx.String("path")) | ||
if err != nil { | ||
return err | ||
} | ||
activeConf := config.ActiveConfig | ||
if activeConf == "" { | ||
fmt.Println("Active configuration is not set, try setting with `cleura config set --name <configuration_name>`") | ||
} else { | ||
fmt.Printf("Active configuration: `%s` (in %s)\n", activeConf, config.location) | ||
} | ||
return nil | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package domaincmd | ||
|
||
import "github.com/urfave/cli/v2" | ||
|
||
func Command() *cli.Command { | ||
return &cli.Command{ | ||
Name: "domain", | ||
Description: "Command used to list available domains", | ||
Subcommands: []*cli.Command{ | ||
listCommand(), | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
package domaincmd | ||
|
||
import ( | ||
"fmt" | ||
"strconv" | ||
|
||
"github.com/aztekas/cleura-client-go/cmd/cleura/configcmd" | ||
"github.com/aztekas/cleura-client-go/pkg/api/cleura" | ||
"github.com/jedib0t/go-pretty/v6/table" | ||
"github.com/jedib0t/go-pretty/v6/text" | ||
"github.com/urfave/cli/v2" | ||
) | ||
|
||
func listCommand() *cli.Command { | ||
return &cli.Command{ | ||
Name: "list", | ||
Description: "List available domains", | ||
Usage: "List domains available to current user", | ||
Before: configcmd.TrySetConfigFromFile, | ||
Flags: []cli.Flag{ | ||
&cli.StringFlag{ | ||
Name: "token", | ||
Aliases: []string{"t"}, | ||
Usage: "Token to validate", | ||
EnvVars: []string{"CLEURA_API_TOKEN"}, | ||
}, | ||
&cli.StringFlag{ | ||
Name: "username", | ||
Aliases: []string{"u"}, | ||
Usage: "Username token belongs to", | ||
EnvVars: []string{"CLEURA_API_USERNAME"}, | ||
}, | ||
&cli.StringFlag{ | ||
Name: "api-host", | ||
Aliases: []string{"host"}, | ||
Usage: "Cleura API host", | ||
Value: "https://rest.cleura.cloud", | ||
EnvVars: []string{"CLEURA_API_HOST"}, | ||
}, | ||
&cli.StringFlag{ | ||
Name: "path", | ||
Aliases: []string{"p"}, | ||
Usage: "Path to configuration file. $HOME/.config/cleura/config if not set", | ||
}, | ||
}, | ||
Action: func(ctx *cli.Context) error { | ||
token := ctx.String("token") | ||
username := ctx.String("username") | ||
host := ctx.String("api-host") | ||
client, err := cleura.NewClientNoPassword(&host, &username, &token) | ||
if err != nil { | ||
return err | ||
} | ||
domains, err := client.ListDomains() | ||
if err != nil { | ||
re, ok := err.(*cleura.RequestAPIError) | ||
if ok { | ||
if re.StatusCode == 403 { | ||
return fmt.Errorf("error: invalid token") | ||
} | ||
} | ||
return err | ||
} | ||
t := table.NewWriter() | ||
t.SetAutoIndex(true) | ||
t.Style().Format.Header = text.FormatTitle | ||
t.AppendHeader(table.Row{"Name", "Domain Id", "Regions"}) | ||
for _, domain := range *domains { | ||
var regs string | ||
for _, region := range domain.Area.Regions { | ||
regs += fmt.Sprintf("%s:%s\n", region.Region, region.Status) | ||
} | ||
t.AppendRow(table.Row{fmt.Sprintf("%s(enabled:%s,status:%s)", domain.Name, strconv.FormatBool(domain.Enabled), domain.Status), domain.Id, regs}) | ||
} | ||
fmt.Println(t.Render()) | ||
return nil | ||
}, | ||
} | ||
} |
Oops, something went wrong.