github.com/awslabs/clencli@v0.0.0-20210514234156-7ecf17182a20/cobra/aid/configure.go (about)

     1  /*
     2  Copyright © 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
     3  Licensed under the Apache License, Version 2.0 (the "License");
     4  you may not use this file except in compliance with the License.
     5  You may obtain a copy of the License at
     6  
     7      http://www.apache.org/licenses/LICENSE-2.0
     8  
     9  Unless required by applicable law or agreed to in writing, software
    10  distributed under the License is distributed on an "AS IS" BASIS,
    11  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  See the License for the specific language governing permissions and
    13  limitations under the License.
    14  */
    15  
    16  package aid
    17  
    18  import (
    19  	"bufio"
    20  	"encoding/json"
    21  	"fmt"
    22  	"io/ioutil"
    23  	"os"
    24  	"runtime"
    25  	"strconv"
    26  	"strings"
    27  
    28  	"github.com/awslabs/clencli/helper"
    29  	"github.com/sirupsen/logrus"
    30  	"github.com/spf13/cobra"
    31  	"github.com/spf13/viper"
    32  	"gopkg.in/yaml.v2"
    33  )
    34  
    35  // ConfigurationsDirectoryExist returns `true` if the configuration directory exist, `false` otherwise
    36  func ConfigurationsDirectoryExist() bool {
    37  	return helper.DirOrFileExists(GetAppInfo().ConfigurationsDir)
    38  }
    39  
    40  // ConfigurationsFileExist returns `true` if the configuration file exist, `false` otherwise
    41  func ConfigurationsFileExist() bool {
    42  	return helper.DirOrFileExists(GetAppInfo().ConfigurationsPath)
    43  }
    44  
    45  // CreateConfigurationsDirectory creates the configuration directory, returns `true` if the configuration directory exist, `false` otherwise
    46  func CreateConfigurationsDirectory() (bool, string) {
    47  	dir := GetAppInfo().ConfigurationsDir
    48  	return helper.MkDirsIfNotExist(dir), dir
    49  }
    50  
    51  // CredentialsFileExist returns `true` if the credentials file exist, `false` otherwise
    52  func CredentialsFileExist() bool {
    53  	return helper.DirOrFileExists(GetAppInfo().CredentialsPath)
    54  }
    55  
    56  // ReadConfig returns the viper instance of the given configuration `name`
    57  func ReadConfig(name string) (*viper.Viper, error) {
    58  	v := viper.New()
    59  	app := GetAppInfo()
    60  
    61  	v.SetConfigName(name)
    62  	v.SetConfigType("yaml")
    63  	v.AddConfigPath(app.ConfigurationsDir)
    64  
    65  	err := v.ReadInConfig()
    66  	if err != nil {
    67  		return v, fmt.Errorf("unable to read configuration:%s\n%v", name, err)
    68  	}
    69  	return v, err
    70  }
    71  
    72  // ReadConfigAsViper returns...
    73  func ReadConfigAsViper(configPath string, configName string, configType string) (*viper.Viper, error) {
    74  	v := viper.New()
    75  
    76  	v.AddConfigPath(configPath)
    77  	v.SetConfigName(configName)
    78  	v.SetConfigType(configType)
    79  
    80  	err := v.ReadInConfig()
    81  	if err != nil {
    82  		return v, fmt.Errorf("unable to read configuration as viper\n%v", err)
    83  	}
    84  	return v, err
    85  }
    86  
    87  // ReadTemplate read the given template under clencli/*.yaml
    88  func ReadTemplate(fileName string) (*viper.Viper, error) {
    89  	c := viper.New()
    90  	c.AddConfigPath("clencli")
    91  	c.SetConfigName(fileName)
    92  	c.SetConfigType("yaml")
    93  	c.SetConfigPermissions(os.ModePerm)
    94  
    95  	err := c.ReadInConfig() // Find and read the c file
    96  	if err != nil {         // Handle errors reading the c file
    97  		return c, fmt.Errorf("Unable to read "+fileName+" via Viper"+"\n%v", err)
    98  	}
    99  
   100  	return c, nil
   101  }
   102  
   103  // WriteInterfaceToFile write the given interface into a file
   104  func WriteInterfaceToFile(in interface{}, path string) error {
   105  	b, err := yaml.Marshal(&in)
   106  	if err != nil {
   107  		_, ok := err.(*json.UnsupportedTypeError)
   108  		if ok {
   109  			return fmt.Errorf("json unsupported type error")
   110  		}
   111  	}
   112  
   113  	err = ioutil.WriteFile(path, b, os.ModePerm)
   114  	if err != nil {
   115  		return fmt.Errorf("unable to update:%s\n%v", path, err)
   116  	}
   117  
   118  	return err
   119  }
   120  
   121  // DeleteCredentialFile delete the credentials file
   122  func DeleteCredentialFile() error {
   123  	return helper.DeleteFile(GetAppInfo().CredentialsPath)
   124  }
   125  
   126  // DeleteConfigurationFile delete the credentials file
   127  func DeleteConfigurationFile() error {
   128  	return helper.DeleteFile(GetAppInfo().ConfigurationsPath)
   129  }
   130  
   131  // DeleteConfigurationsDirectory delete the configurations directory
   132  func DeleteConfigurationsDirectory() error {
   133  	return os.RemoveAll(GetAppInfo().ConfigurationsDir)
   134  }
   135  
   136  // GetSensitiveUserInput get sensitive input as string
   137  func GetSensitiveUserInput(cmd *cobra.Command, text string, info string) (string, error) {
   138  	return getUserInput(cmd, text+" ["+maskString(info, 3)+"]", "")
   139  }
   140  
   141  func maskString(s string, showLastChars int) string {
   142  	maskSize := len(s) - showLastChars
   143  	if maskSize <= 0 {
   144  		return s
   145  	}
   146  
   147  	return strings.Repeat("*", maskSize) + s[maskSize:]
   148  }
   149  
   150  // GetSensitiveUserInputAsString get sensitive input as string
   151  func GetSensitiveUserInputAsString(cmd *cobra.Command, text string, info string) string {
   152  	answer, err := GetSensitiveUserInput(cmd, text, info)
   153  	if err != nil {
   154  		logrus.Fatalf("unable to get user input about profile's name\n%v", err)
   155  	}
   156  
   157  	// if user typed ENTER, keep the current value
   158  	if answer != "" {
   159  		return answer
   160  	}
   161  
   162  	return info
   163  }
   164  
   165  func getInput() (string, error) {
   166  
   167  	reader := bufio.NewReader(os.Stdin)
   168  
   169  	text, err := reader.ReadString('\n')
   170  	if err != nil {
   171  		return "", err
   172  	}
   173  
   174  	if runtime.GOOS == "windows" {
   175  		// convert LF to CRLF
   176  		text = strings.Replace(text, "\r\n", "", -1)
   177  	} else {
   178  		// convert CRLF to LF
   179  		text = strings.Replace(text, "\n", "", -1)
   180  	}
   181  
   182  	return text, nil
   183  }
   184  
   185  func getUserInput(cmd *cobra.Command, text string, info string) (string, error) {
   186  	if info == "" {
   187  		cmd.Print(text + ": ")
   188  	} else {
   189  		cmd.Print(text + " [" + info + "]: ")
   190  	}
   191  
   192  	input, err := getInput()
   193  
   194  	return input, err
   195  }
   196  
   197  // GetUserInputAsBool prints `text` on console and return answer as `boolean`
   198  func GetUserInputAsBool(cmd *cobra.Command, text string, info bool) bool {
   199  	answer, err := getUserInput(cmd, text, strconv.FormatBool(info))
   200  	if err != nil {
   201  		logrus.Fatalf("unable to get user input as boolean\n%s", err)
   202  	}
   203  
   204  	if answer == "true" {
   205  		return true
   206  	} else if answer == "false" {
   207  		return false
   208  	}
   209  
   210  	return info
   211  }
   212  
   213  // GetUserInputAsString prints `text` on console and return answer as `string`
   214  func GetUserInputAsString(cmd *cobra.Command, text string, info string) string {
   215  	answer, err := getUserInput(cmd, text, info)
   216  	if err != nil {
   217  		logrus.Fatalf("unable to get user input about profile's name\n%v", err)
   218  	}
   219  
   220  	// if user typed ENTER, keep the current value
   221  	if answer != "" {
   222  		return answer
   223  	}
   224  
   225  	return info
   226  }