func CheckCommandExists(command string) (string, error) {
	cmdPath, err := exec.LookPath(command)
	if err != nil {
		return "", err
	}
	return cmdPath, nil
}
CheckCommandExists tries to find the location of a given binary.
package appconfig
import (
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"sync"
	"github.com/spf13/viper"
	archutil "github.com/rigup/ephemeral-iam/internal/appconfig/arch_util"
	util "github.com/rigup/ephemeral-iam/internal/eiamutil"
	errorsutil "github.com/rigup/ephemeral-iam/internal/errors"
)
const (
	AuthProxyAddress       = "authproxy.proxyaddress"
	AuthProxyPort          = "authproxy.proxyport"
	AuthProxyVerbose       = "authproxy.verbose"
	AuthProxyLogDir        = "authproxy.logdir"
	AuthProxyCertFile      = "authproxy.certfile"
	AuthProxyKeyFile       = "authproxy.keyfile"
	DefaultServiceAccounts = "serviceaccounts"
	CloudSQLProxyPath      = "binarypaths.cloudsqlproxy"
	GcloudPath             = "binarypaths.gcloud"
	KubectlPath            = "binarypaths.kubectl"
	GithubAuth             = "github.auth"
	GithubTokens           = "github.tokens"  
	LoggingFormat          = "logging.format"
	LoggingLevel           = "logging.level"
	LoggingLevelTruncation = "logging.disableleveltruncation"
	LoggingPadLevelText    = "logging.padleveltext"
)
var (
	configDir string
	once      sync.Once
	binPaths = map[string]string{
		CloudSQLProxyPath: "cloud_sql_proxy",
		GcloudPath:        "gcloud",
		KubectlPath:       "kubectl",
	}
)
func InitConfig() error {
	viper.SetConfigName("config")
	viper.AddConfigPath(GetConfigDir())
	viper.AutomaticEnv()
	viper.SetConfigType("yml")
	if err := viper.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
			return errorsutil.New("Failed to initialize configuration", err)
		}
		initConfig()
	}
	util.Logger = util.NewLogger()
	if err := getBinPaths(); err != nil {
		return err
	}
	return nil
}
func initConfig() {
	viper.SetDefault(AuthProxyAddress, "127.0.0.1")
	viper.SetDefault(AuthProxyPort, "8084")
	viper.SetDefault(AuthProxyVerbose, false)
	viper.SetDefault(AuthProxyLogDir, filepath.Join(GetConfigDir(), "log"))
	viper.SetDefault(AuthProxyCertFile, filepath.Join(GetConfigDir(), "server.pem"))
	viper.SetDefault(AuthProxyKeyFile, filepath.Join(GetConfigDir(), "server.key"))
	viper.SetDefault(GithubAuth, false)
	viper.SetDefault(LoggingFormat, "text")
	viper.SetDefault(LoggingLevel, "info")
	viper.SetDefault(LoggingLevelTruncation, true)
	viper.SetDefault(LoggingPadLevelText, true)
	if err := viper.SafeWriteConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileAlreadyExistsError); !ok {
			log.Fatalf("failed to write config file %s/config.yml: %v", GetConfigDir(), err)
		}
	}
}
func getBinPaths() error {
	updated := false
	for configKey, binName := range binPaths {
		if viper.GetString(configKey) == "" {
			updated = true
			binPath, err := CheckCommandExists(binName)
			if err != nil {
				if configKey != CloudSQLProxyPath {
					return err
				}
				util.Logger.Debug("Could not find path to cloud_sql_proxy binary")
			}
			viper.Set(configKey, binPath)
		}
	}
	if updated {
		if err := viper.WriteConfig(); err != nil {
			return errorsutil.New("Failed to write binary paths to configuration file", err)
		}
	}
	return nil
}