func initConfig() {
	if rootFlags.cfgFile != "" {
		viper.SetConfigFile(rootFlags.cfgFile)
	} else {
		home, err := homedir.Dir()
		if err != nil {
			log.Print(err)
			os.Exit(1)
		}
		viper.AddConfigPath(filepath.Join(home, ".config"))
		viper.SetConfigName("eqc")
	}
	if !strings.Contains(rootFlags.svcAddr, ":") {
		rootFlags.svcAddr += ":37706"
	}
	viper.AutomaticEnv()  
	if err := viper.ReadInConfig(); err == nil {
		log.Print("Using config file:", viper.ConfigFileUsed())
	}
}
initConfig reads in config file and ENV variables if set.
package cmd
import (
	"context"
	"crypto/x509"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"path/filepath"
	"strings"
	homedir "github.com/mitchellh/go-homedir"
	"github.com/shiblon/entroq"
	"github.com/shiblon/entroq/backend/eqgrpc"
	"github.com/spf13/cobra"
	"github.com/spf13/pflag"
	"github.com/spf13/viper"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
)
var rootFlags struct {
	cfgFile      string
	svcAddr      string
	jsonValue    bool
	secure       bool
	authzToken   string
	maxMsgSizeMB int
}
var eq *entroq.EntroQ
var rootCmd = &cobra.Command{
	Use:   "eqc [options] <command>",
	Short: "EntroQ Client CLI for poking at an EntroQ gRPC service",
	Long: `The eqc CLI allows you to query an EntroQ service, getting
queue listings, individual task information, etc.`,
	PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
		if cmd.Name() == "help" || cmd.IsAdditionalHelpTopicCommand() {
			return nil
		}
		var opts []eqgrpc.Option
		if rootFlags.secure {
			pool, err := x509.SystemCertPool()
			if err != nil {
				return fmt.Errorf("cert pool: %w", err)
			}
			creds := credentials.NewClientTLSFromCert(pool, "")
			opts = append(opts, eqgrpc.WithDialOpts(grpc.WithTransportCredentials(creds)))
		} else {
			opts = append(opts, eqgrpc.WithInsecure())
		}
		if rootFlags.authzToken != "" {
			opts = append(opts, eqgrpc.WithBearerToken(rootFlags.authzToken))
		}
		if size := rootFlags.maxMsgSizeMB; size != 0 {
			opts = append(opts, eqgrpc.WithMaxSize(size))
		}
		var err error
		eq, err = entroq.New(context.Background(), eqgrpc.Opener(rootFlags.svcAddr, opts...))
		if err != nil {
			return fmt.Errorf("entroq client open: %w", err)
		}
		return nil
	},
	PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
		if eq != nil {
			return eq.Close()
		}
		return nil
	},
	SilenceUsage:  true,
	SilenceErrors: true,
}
func Execute() {
	if err := rootCmd.Execute(); err != nil {
		log.Print(err)
		os.Exit(1)
	}
}
func init() {
	cobra.OnInitialize(initConfig)
	rootCmd.PersistentFlags().StringVar(&rootFlags.cfgFile, "config", "", "config file (default is $HOME/.config/eqc.yaml)")
	rootCmd.PersistentFlags().StringVarP(&rootFlags.svcAddr, "svcaddr", "s", ":37706", "address of service, uses port 37706 if none is specified")
	rootCmd.PersistentFlags().BoolVarP(&rootFlags.jsonValue, "json", "j", false, "Display task values as JSON.")
	rootCmd.PersistentFlags().BoolVarP(&rootFlags.secure, "secure", "S", false, "Use secure connection.")
	rootCmd.PersistentFlags().StringVar(&rootFlags.authzToken, "authz_token", "", "Pass an Authorization token.")
	rootCmd.PersistentFlags().IntVar(&rootFlags.maxMsgSizeMB, "max_msg_size_mb", 10, "Maximum gRPC message size in megabytes.")
	viper.BindPFlag("authz_token", pflag.Lookup("authz_token"))
}
func mustTaskString(t *entroq.Task) string {
	b, err := json.Marshal(t)
	if err != nil {
		log.Fatalf("Failed to marshal to JSON: %v", err)
	}
	if !rootFlags.jsonValue {
		return string(b)
	}
	var tm map[string]interface{}
	var vm interface{}
	if err := json.Unmarshal(b, &tm); err != nil {
		log.Fatalf("Error creating map from JSON: %v", err)
	}
	if val, ok := tm["value"]; !ok || val == nil {
		return string(b)
	}
	v, err := base64.StdEncoding.DecodeString(tm["value"].(string))
	if err != nil {
		log.Fatalf("Failed to b64 deserialize byte value: %v", err)
	}
	if err := json.Unmarshal(v, &vm); err != nil {
		log.Fatalf("Failed to unmarshal JSON value: %v", err)
	}
	tm["value"] = vm
	b, err = json.Marshal(tm)
	if err != nil {
		log.Fatalf("Error marshaling unnested task: %v", err)
	}
	return string(b)
}