github.com/henvic/wedeploycli@v1.7.6-0.20200319005353-3630f582f284/command/env-var/internal/commands/commands.go (about)

     1  package commands
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"os"
     8  	"sort"
     9  	"strconv"
    10  	"strings"
    11  
    12  	"github.com/hashicorp/errwrap"
    13  	"github.com/henvic/wedeploycli/cmdflagsfromhost"
    14  	"github.com/henvic/wedeploycli/color"
    15  	"github.com/henvic/wedeploycli/command/internal/we"
    16  	"github.com/henvic/wedeploycli/fancy"
    17  	"github.com/henvic/wedeploycli/isterm"
    18  	"github.com/henvic/wedeploycli/list"
    19  	"github.com/henvic/wedeploycli/services"
    20  )
    21  
    22  // ErrNoEnvToAdd is used when there is no environment varaible to add
    23  var ErrNoEnvToAdd = errors.New("no environment variable to add")
    24  
    25  // Command for environment variables
    26  type Command struct {
    27  	SetupHost      cmdflagsfromhost.SetupHost
    28  	ServicesClient *services.Client
    29  
    30  	Envs []services.EnvironmentVariable
    31  
    32  	SkipPrompt bool
    33  }
    34  
    35  func has(filterEnvKeys []string, key string) bool {
    36  	if len(filterEnvKeys) == 0 {
    37  		return true
    38  	}
    39  
    40  	for _, f := range filterEnvKeys {
    41  		if f == key {
    42  			return true
    43  		}
    44  	}
    45  
    46  	return false
    47  }
    48  
    49  // Show environment variables
    50  func (c *Command) Show(ctx context.Context, filterEnvKeys ...string) error {
    51  	c.Envs = []services.EnvironmentVariable{}
    52  
    53  	var l = list.New(list.Filter{
    54  		Project:  c.SetupHost.Project(),
    55  		Services: []string{c.SetupHost.Service()},
    56  	})
    57  
    58  	if err := l.Once(ctx, we.Context()); err != nil {
    59  		return err
    60  	}
    61  
    62  	var envs, err = c.ServicesClient.GetEnvironmentVariables(ctx,
    63  		c.SetupHost.Project(),
    64  		c.SetupHost.Service())
    65  
    66  	if err != nil {
    67  		return err
    68  	}
    69  
    70  	for _, e := range envs {
    71  		if !has(filterEnvKeys, e.Name) {
    72  			continue
    73  		}
    74  
    75  		c.Envs = append(c.Envs, services.EnvironmentVariable{
    76  			Name:  e.Name,
    77  			Value: e.Value,
    78  		})
    79  	}
    80  
    81  	if len(c.Envs) == 0 {
    82  		_, _ = fmt.Fprintf(os.Stderr, "No environment variable found.\n")
    83  		return nil
    84  	}
    85  
    86  	sort.Slice(c.Envs, func(i, j int) bool {
    87  		return c.Envs[i].Name < c.Envs[j].Name
    88  	})
    89  
    90  	fmt.Printf("%s\t%s\t%s\n",
    91  		color.Format(color.FgHiBlack, "#"),
    92  		color.Format(color.FgHiBlack, "Key"),
    93  		color.Format(color.FgHiBlack, "Value"))
    94  
    95  	for c, v := range c.Envs {
    96  		fmt.Printf("%d\t%s\t%s\n", c+1, v.Name, v.Value)
    97  	}
    98  
    99  	return nil
   100  }
   101  
   102  // Add environment variables
   103  func (c *Command) Add(ctx context.Context, args []string) error {
   104  	var envs, err = c.getAddEnvs(args)
   105  
   106  	if err != nil {
   107  		return err
   108  	}
   109  
   110  	for _, env := range envs {
   111  		err = c.ServicesClient.SetEnvironmentVariable(ctx, c.SetupHost.Project(), c.SetupHost.Service(), env.Name, env.Value)
   112  
   113  		if err != nil {
   114  			return errwrap.Wrapf("can't add \""+env.Name+"\": {{err}}", err)
   115  		}
   116  
   117  		fmt.Printf("Environment variable \"%v\" added.\n", env.Name)
   118  	}
   119  
   120  	return nil
   121  }
   122  
   123  // Replace environment variables
   124  func (c *Command) Replace(ctx context.Context, args []string) error {
   125  	var envs, err = c.getAddEnvs(args)
   126  
   127  	if err != nil && err != ErrNoEnvToAdd {
   128  		return err
   129  	}
   130  
   131  	if err = c.ServicesClient.SetEnvironmentVariables(ctx, c.SetupHost.Project(), c.SetupHost.Service(), envs); err != nil {
   132  		return err
   133  	}
   134  
   135  	for _, env := range envs {
   136  		fmt.Printf("Environment variable \"%v\" added.\n", env.Name)
   137  	}
   138  
   139  	return nil
   140  }
   141  
   142  func (c *Command) getAddEnvs(args []string) (envs []services.EnvironmentVariable, err error) {
   143  	args = filterEmptyEnvValues(args)
   144  
   145  	if len(args) == 0 && !c.SkipPrompt && isterm.Check() {
   146  		fmt.Println(fancy.Question("Type environment variables for \"" + c.SetupHost.Host() + "\" (e.g., A=1 B=2 C=3)"))
   147  		var argss string
   148  		argss, err = fancy.Prompt()
   149  
   150  		if err != nil {
   151  			return nil, err
   152  		}
   153  
   154  		args = strings.Split(argss, " ")
   155  	}
   156  
   157  	if strings.Join(args, "") == "" {
   158  		return envs, ErrNoEnvToAdd
   159  	}
   160  
   161  	return splitEnvKeyValueParameters(args)
   162  }
   163  
   164  func splitEnvKeyValueParameters(args []string) (envs []services.EnvironmentVariable, err error) {
   165  	if len(args) == 2 && !strings.Contains(args[0], "=") && !strings.Contains(args[1], "=") {
   166  		envs = append(envs, services.EnvironmentVariable{
   167  			Name:  args[0],
   168  			Value: args[1],
   169  		})
   170  
   171  		return envs, nil
   172  	}
   173  
   174  	for _, v := range args {
   175  		var kv = strings.SplitN(v, "=", 2)
   176  
   177  		if len(kv) != 2 {
   178  			return nil, fmt.Errorf("invalid environment variable key/value pair: \"%s\"", v)
   179  		}
   180  
   181  		envs = append(envs, services.EnvironmentVariable{
   182  			Name:  kv[0],
   183  			Value: kv[1],
   184  		})
   185  	}
   186  
   187  	return envs, nil
   188  }
   189  
   190  // Delete environment variables
   191  func (c *Command) Delete(ctx context.Context, args []string) error {
   192  	var envs, err = c.getDeleteEnvKeys(args)
   193  
   194  	if err != nil {
   195  		return err
   196  	}
   197  
   198  	for _, env := range envs {
   199  		err := c.ServicesClient.UnsetEnvironmentVariable(ctx, c.SetupHost.Project(), c.SetupHost.Service(), env)
   200  
   201  		if err != nil {
   202  			return err
   203  		}
   204  
   205  		fmt.Printf("Environment variable \"%s\" deleted.\n", env)
   206  	}
   207  
   208  	return nil
   209  }
   210  
   211  func (c *Command) getDeleteEnvKeys(args []string) ([]string, error) {
   212  	if len(args) != 0 {
   213  		return args, nil
   214  	}
   215  
   216  	fmt.Println(fancy.Question("Select a environment variable # or name to delete from \"" + c.SetupHost.Host() + "\""))
   217  	var envss, err = fancy.Prompt()
   218  
   219  	if err != nil {
   220  		return []string{}, err
   221  	}
   222  
   223  	var envs = strings.Split(envss, " ")
   224  
   225  	for index, env := range envs {
   226  		e := c.getEnvKeyOrOption(env)
   227  
   228  		if e != env {
   229  			envs[index] = e
   230  		}
   231  	}
   232  
   233  	return filterEmptyEnvValues(envs), nil
   234  }
   235  
   236  func (c *Command) getEnvKeyOrOption(answer string) string {
   237  	for _, e := range c.Envs {
   238  		if answer == e.Name {
   239  			return e.Name
   240  		}
   241  	}
   242  
   243  	switch num, err := strconv.Atoi(answer); {
   244  	case err != nil || num < 1 || num > len(c.Envs):
   245  		return answer
   246  	default:
   247  		return c.Envs[num-1].Name
   248  	}
   249  }
   250  
   251  func filterEmptyEnvValues(envKeys []string) []string {
   252  	var filtered []string
   253  
   254  	for _, e := range envKeys {
   255  		if e != "" {
   256  			filtered = append(filtered, e)
   257  		}
   258  	}
   259  
   260  	return filtered
   261  }