1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
package cmd
import (
"fmt"
"net/url"
"os"
"strings"
"sync"
"github.com/fatih/color"
"github.com/kong/deck/utils"
homedir "github.com/mitchellh/go-homedir"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var (
cfgFile string
rootConfig utils.KongClientConfig
)
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "deck",
Short: "Administer your Kong declaratively",
Long: `decK helps you manage Kong clusters with a declarative
configuration file.
It can be used to export, import or sync entities to Kong.`,
SilenceUsage: true,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
if _, err := url.ParseRequestURI(rootConfig.Address); err != nil {
return errors.WithStack(errors.Wrap(err, "invalid URL"))
}
return nil
},
}
// Execute adds all child commands to the root command and sets
// sflags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
var wg sync.WaitGroup
var err error
const threads = 1
wg.Add(threads)
go func() {
defer wg.Done()
err = rootCmd.Execute()
}()
wg.Wait()
if err != nil {
os.Exit(1)
}
}
//nolint:errcheck
func init() {
cobra.OnInitialize(initConfig)
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "",
"config file (default is $HOME/.deck.yaml)")
rootCmd.PersistentFlags().String("kong-addr", "http://localhost:8001",
"HTTP Address of Kong's Admin API.\n"+
"This value can also be set using DECK_KONG_ADDR\n"+
" environment variable.")
viper.BindPFlag("kong-addr",
rootCmd.PersistentFlags().Lookup("kong-addr"))
rootCmd.PersistentFlags().StringSlice("headers", []string{},
"HTTP Headers(key:value) to inject in all requests to Kong's Admin API.\n"+
"This flag can be specified multiple times to inject multiple headers.")
viper.BindPFlag("headers",
rootCmd.PersistentFlags().Lookup("headers"))
rootCmd.PersistentFlags().Bool("tls-skip-verify", false,
"Disable verification of Kong's Admin TLS certificate.\n"+
"This value can also be set using DECK_TLS_SKIP_VERIFY "+
"environment variable.")
viper.BindPFlag("tls-skip-verify",
rootCmd.PersistentFlags().Lookup("tls-skip-verify"))
rootCmd.PersistentFlags().String("tls-server-name", "",
"Name to use to verify the hostname in "+
"Kong's Admin TLS certificate.\n"+
"This value can also be set using DECK_TLS_SERVER_NAME"+
" environment variable.")
viper.BindPFlag("tls-server-name",
rootCmd.PersistentFlags().Lookup("tls-server-name"))
rootCmd.PersistentFlags().String("ca-cert", "",
"Custom CA certificate to use to verify "+
"Kong's Admin TLS certificate.\n"+
"This value can also be set using DECK_CA_CERT"+
" environment variable.")
viper.BindPFlag("ca-cert",
rootCmd.PersistentFlags().Lookup("ca-cert"))
rootCmd.PersistentFlags().Int("verbose", 0,
"Enable verbose verbose logging levels\n"+
"Setting this value to 2 outputs all HTTP requests/responses\n"+
"between decK and Kong.")
viper.BindPFlag("verbose",
rootCmd.PersistentFlags().Lookup("verbose"))
rootCmd.PersistentFlags().Bool("no-color", false,
"disable colorized output")
viper.BindPFlag("no-color",
rootCmd.PersistentFlags().Lookup("no-color"))
rootCmd.PersistentFlags().Bool("skip-workspace-crud", false,
"Skip API calls related to Workspaces (Kong Enterprise only)")
viper.BindPFlag("skip-workspace-crud",
rootCmd.PersistentFlags().Lookup("skip-workspace-crud"))
}
// initConfig reads in config file and ENV variables if set.
func initConfig() {
if cfgFile != "" {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
} else {
// Find home directory.
home, err := homedir.Dir()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// Search config in home directory with name ".deck"(without extension).
viper.AddConfigPath(home)
viper.SetConfigName(".deck")
}
viper.SetEnvPrefix("deck")
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_", "-", "_"))
viper.AutomaticEnv() // read in environment variables that match
// If a config file is found, read it in.
if err := viper.ReadInConfig(); err != nil {
if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
fmt.Println(err)
}
}
rootConfig.Address = viper.GetString("kong-addr")
rootConfig.TLSServerName = viper.GetString("tls-server-name")
rootConfig.TLSSkipVerify = viper.GetBool("tls-skip-verify")
rootConfig.TLSCACert = viper.GetString("ca-cert")
rootConfig.Headers = viper.GetStringSlice("headers")
rootConfig.SkipWorkspaceCrud = viper.GetBool("skip-workspace-crud")
rootConfig.Debug = (viper.GetInt("verbose") >= 1)
color.NoColor = (color.NoColor || viper.GetBool("no-color"))
}
|