github.com/unionj-cloud/go-doudou@v1.3.8-0.20221011095552-0088008e5b31/framework/internal/config/config.go (about)

     1  package config
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/apolloconfig/agollo/v4"
     6  	"github.com/apolloconfig/agollo/v4/env/config"
     7  	"github.com/pkg/errors"
     8  	"github.com/sirupsen/logrus"
     9  	"github.com/unionj-cloud/go-doudou/framework/configmgr"
    10  	"github.com/unionj-cloud/go-doudou/toolkit/cast"
    11  	"github.com/unionj-cloud/go-doudou/toolkit/dotenv"
    12  	"github.com/unionj-cloud/go-doudou/toolkit/stringutils"
    13  	"github.com/unionj-cloud/go-doudou/toolkit/yaml"
    14  	"github.com/unionj-cloud/go-doudou/toolkit/zlogger"
    15  	"github.com/wubin1989/nacos-sdk-go/common/constant"
    16  	"github.com/wubin1989/nacos-sdk-go/vo"
    17  	_ "go.uber.org/automaxprocs"
    18  	"net"
    19  	"net/url"
    20  	"os"
    21  	"strconv"
    22  	"strings"
    23  )
    24  
    25  func LoadConfigFromLocal() {
    26  	env := os.Getenv("GDD_ENV")
    27  	if "" == env {
    28  		env = "dev"
    29  	}
    30  	yaml.Load(env)
    31  	dotenv.Load(env)
    32  }
    33  
    34  func LoadConfigFromRemote() {
    35  	configType := GddConfigRemoteType.LoadOrDefault(DefaultGddConfigRemoteType)
    36  	switch configType {
    37  	case "":
    38  		return
    39  	case NacosConfigType:
    40  		nacosConfigFormat := GddNacosConfigFormat.LoadOrDefault(string(DefaultGddNacosConfigFormat))
    41  		nacosConfigGroup := GddNacosConfigGroup.LoadOrDefault(DefaultGddNacosConfigGroup)
    42  		nacosConfigDataid := GddNacosConfigDataid.LoadOrDefault(DefaultGddNacosConfigDataid)
    43  		if stringutils.IsEmpty(nacosConfigDataid) {
    44  			panic(errors.New("[go-doudou] nacos config dataId is required"))
    45  		}
    46  		err := configmgr.LoadFromNacos(GetNacosClientParam(), nacosConfigDataid, nacosConfigFormat, nacosConfigGroup)
    47  		if err != nil {
    48  			panic(errors.Wrap(err, "[go-doudou] fail to load config from Nacos"))
    49  		}
    50  	case ApolloConfigType:
    51  		if stringutils.IsEmpty(GddServiceName.Load()) {
    52  			panic(errors.New("[go-doudou] service name is required"))
    53  		}
    54  		apolloCluster := GddApolloCluster.LoadOrDefault(DefaultGddApolloCluster)
    55  		apolloAddr := GddApolloAddr.LoadOrDefault(DefaultGddApolloAddr)
    56  		if stringutils.IsEmpty(apolloAddr) {
    57  			panic(errors.New("[go-doudou] apollo config service address is required"))
    58  		}
    59  		apolloNamespace := GddApolloNamespace.LoadOrDefault(DefaultGddApolloNamespace)
    60  		apolloBackup := cast.ToBoolOrDefault(GddApolloBackupEnable.Load(), DefaultGddApolloBackupEnable)
    61  		apolloBackupPath := GddApolloBackupPath.LoadOrDefault(DefaultGddApolloBackupPath)
    62  		apolloSecret := GddApolloSecret.LoadOrDefault(DefaultGddApolloSecret)
    63  		apolloMustStart := cast.ToBoolOrDefault(GddApolloMuststart.Load(), DefaultGddApolloMuststart)
    64  		apolloLogEnable := cast.ToBoolOrDefault(GddApolloLogEnable.Load(), DefaultGddApolloLogEnable)
    65  		if apolloLogEnable {
    66  			agollo.SetLogger(logrus.StandardLogger())
    67  		}
    68  		c := &config.AppConfig{
    69  			AppID:            GddServiceName.Load(),
    70  			Cluster:          apolloCluster,
    71  			IP:               apolloAddr,
    72  			NamespaceName:    apolloNamespace,
    73  			IsBackupConfig:   apolloBackup,
    74  			Secret:           apolloSecret,
    75  			BackupConfigPath: apolloBackupPath,
    76  			MustStart:        apolloMustStart,
    77  		}
    78  		configmgr.LoadFromApollo(c)
    79  	default:
    80  		panic(fmt.Errorf("[go-doudou] unknown config type: %s\n", configType))
    81  	}
    82  }
    83  
    84  func CheckDev() bool {
    85  	return stringutils.IsEmpty(os.Getenv("GDD_ENV")) || os.Getenv("GDD_ENV") == "dev"
    86  }
    87  
    88  func init() {
    89  	LoadConfigFromLocal()
    90  	LoadConfigFromRemote()
    91  	opts := []zlogger.LoggerConfigOption{
    92  		zlogger.WithDev(CheckDev()),
    93  		zlogger.WithCaller(cast.ToBoolOrDefault(GddLogCaller.Load(), DefaultGddLogCaller)),
    94  	}
    95  	zlogger.InitEntry(GddLogLevel.LoadOrDefault(DefaultGddLogLevel), zlogger.NewLoggerConfig(opts...))
    96  }
    97  
    98  type envVariable string
    99  
   100  func (receiver envVariable) MarshalJSON() ([]byte, error) {
   101  	return []byte(strconv.Quote(receiver.Load())), nil
   102  }
   103  
   104  const (
   105  	NacosConfigType  = "nacos"
   106  	ApolloConfigType = "apollo"
   107  )
   108  
   109  const (
   110  	// GddBanner indicates banner enabled or not
   111  	GddBanner envVariable = "GDD_BANNER"
   112  	// GddBannerText sets text content of banner
   113  	GddBannerText envVariable = "GDD_BANNER_TEXT"
   114  	// GddLogLevel accepts panic, fatal, error, warn, warning, info, debug, trace, disabled. please reference zerolog.ParseLevel
   115  	GddLogLevel envVariable = "GDD_LOG_LEVEL"
   116  	// GddLogFormat text or json
   117  	// Deprecated: move to zerolog
   118  	GddLogFormat envVariable = "GDD_LOG_FORMAT"
   119  	// GddLogReqEnable enables request and response logging
   120  	GddLogReqEnable envVariable = "GDD_LOG_REQ_ENABLE"
   121  	GddLogCaller    envVariable = "GDD_LOG_CALLER"
   122  	// GddGraceTimeout sets graceful shutdown timeout
   123  	GddGraceTimeout envVariable = "GDD_GRACE_TIMEOUT"
   124  	// GddWriteTimeout sets http connection write timeout
   125  	GddWriteTimeout envVariable = "GDD_WRITE_TIMEOUT"
   126  	// GddReadTimeout sets http connection read timeout
   127  	GddReadTimeout envVariable = "GDD_READ_TIMEOUT"
   128  	// GddIdleTimeout sets http connection idle timeout
   129  	GddIdleTimeout envVariable = "GDD_IDLE_TIMEOUT"
   130  	// GddRouteRootPath sets root path for all routes
   131  	GddRouteRootPath envVariable = "GDD_ROUTE_ROOT_PATH"
   132  	// GddServiceName sets service name
   133  	GddServiceName envVariable = "GDD_SERVICE_NAME"
   134  	// GddHost sets bind host for http server
   135  	GddHost envVariable = "GDD_HOST"
   136  	// GddPort sets bind port for http server
   137  	GddPort envVariable = "GDD_PORT"
   138  	// GddGrpcPort sets bind port for grpc server
   139  	GddGrpcPort envVariable = "GDD_GRPC_PORT"
   140  	// GddManage if true, it will add built-in apis with /go-doudou path prefix for online api document and service status monitor etc.
   141  	GddManage envVariable = "GDD_MANAGE_ENABLE"
   142  	// GddManageUser manage api endpoint http basic auth user
   143  	GddManageUser envVariable = "GDD_MANAGE_USER"
   144  	// GddManagePass manage api endpoint http basic auth password
   145  	GddManagePass envVariable = "GDD_MANAGE_PASS"
   146  
   147  	GddEnableResponseGzip envVariable = "GDD_ENABLE_RESPONSE_GZIP"
   148  	// Deprecated: move to GddFallbackContentType
   149  	GddAppType envVariable = "GDD_APP_TYPE"
   150  	// GddFallbackContentType fallback response content-type header value
   151  	GddFallbackContentType        envVariable = "GDD_FALLBACK_CONTENTTYPE"
   152  	GddRouterSaveMatchedRoutePath envVariable = "GDD_ROUTER_SAVEMATCHEDROUTEPATH"
   153  
   154  	// GddConfigRemoteType has two options available: nacos, apollo
   155  	GddConfigRemoteType envVariable = "GDD_CONFIG_REMOTE_TYPE"
   156  
   157  	// GddMemSeed sets cluster seeds for joining
   158  	GddMemSeed envVariable = "GDD_MEM_SEED"
   159  	// GddMemName unique name of this node in cluster. if empty or not set, hostname will be used instead
   160  	GddMemName envVariable = "GDD_MEM_NAME"
   161  	// GddMemHost specify AdvertiseAddr attribute of memberlist config struct.
   162  	// if GddMemHost starts with dot such as .seed-svc-headless.default.svc.cluster.local,
   163  	// it will be prefixed by hostname such as seed-2.seed-svc-headless.default.svc.cluster.local
   164  	// for supporting k8s stateful service
   165  	// if empty or not set, private ip will be used instead.
   166  	GddMemHost envVariable = "GDD_MEM_HOST"
   167  	// GddMemPort if empty or not set, an available port will be chosen randomly. recommend specifying a port
   168  	GddMemPort envVariable = "GDD_MEM_PORT"
   169  	// GddMemDeadTimeout dead node will be removed from node map if not received refute messages from it in GddMemDeadTimeout second
   170  	// expose GossipToTheDeadTime property of memberlist.Config
   171  	GddMemDeadTimeout envVariable = "GDD_MEM_DEAD_TIMEOUT"
   172  	// GddMemSyncInterval local node will synchronize states from other random node every GddMemSyncInterval second
   173  	// expose PushPullInterval property of memberlist.Config
   174  	GddMemSyncInterval envVariable = "GDD_MEM_SYNC_INTERVAL"
   175  	// GddMemReclaimTimeout dead node will be replaced with new node with the same name but different full address in GddMemReclaimTimeout second
   176  	// expose DeadNodeReclaimTime property of memberlist.Config
   177  	GddMemReclaimTimeout envVariable = "GDD_MEM_RECLAIM_TIMEOUT"
   178  	// GddMemProbeInterval probe interval
   179  	// expose ProbeInterval property of memberlist.Config
   180  	GddMemProbeInterval envVariable = "GDD_MEM_PROBE_INTERVAL"
   181  	// GddMemProbeTimeout probe timeout
   182  	// expose ProbeTimeout property of memberlist.Config
   183  	GddMemProbeTimeout envVariable = "GDD_MEM_PROBE_TIMEOUT"
   184  	// GddMemSuspicionMult is the multiplier for determining the time an inaccessible node is considered suspect before declaring it dead.
   185  	// expose SuspicionMult property of memberlist.Config
   186  	GddMemSuspicionMult  envVariable = "GDD_MEM_SUSPICION_MULT"
   187  	GddMemRetransmitMult envVariable = "GDD_MEM_RETRANSMIT_MULT"
   188  	// GddMemGossipNodes how many remote nodes you want to gossip messages
   189  	// expose GossipNodes property of memberlist.Config
   190  	GddMemGossipNodes envVariable = "GDD_MEM_GOSSIP_NODES"
   191  	// GddMemGossipInterval gossip interval
   192  	// expose GossipInterval property of memberlist.Config
   193  	GddMemGossipInterval envVariable = "GDD_MEM_GOSSIP_INTERVAL"
   194  	// GddMemTCPTimeout tcp timeout
   195  	// expose TCPTimeout property of memberlist.Config
   196  	GddMemTCPTimeout envVariable = "GDD_MEM_TCP_TIMEOUT"
   197  	// GddMemWeight node weight
   198  	GddMemWeight envVariable = "GDD_MEM_WEIGHT"
   199  	// GddMemWeightInterval node weight will be calculated every GddMemWeightInterval
   200  	GddMemWeightInterval envVariable = "GDD_MEM_WEIGHT_INTERVAL"
   201  	GddMemIndirectChecks envVariable = "GDD_MEM_INDIRECT_CHECKS"
   202  	GddMemLogDisable     envVariable = "GDD_MEM_LOG_DISABLE"
   203  	// GddMemCIDRsAllowed If not set, allow any connection (default), otherwise specify all networks
   204  	// allowed connecting (you must specify IPv6/IPv4 separately)
   205  	GddMemCIDRsAllowed envVariable = "GDD_MEM_CIDRS_ALLOWED"
   206  
   207  	GddRetryCount         envVariable = "GDD_RETRY_COUNT"
   208  	GddTracingMetricsRoot envVariable = "GDD_TRACING_METRICS_ROOT"
   209  
   210  	GddServiceDiscoveryMode envVariable = "GDD_SERVICE_DISCOVERY_MODE"
   211  
   212  	GddNacosNamespaceId         envVariable = "GDD_NACOS_NAMESPACE_ID"
   213  	GddNacosTimeoutMs           envVariable = "GDD_NACOS_TIMEOUT_MS"
   214  	GddNacosNotLoadCacheAtStart envVariable = "GDD_NACOS_NOT_LOAD_CACHE_AT_START"
   215  	GddNacosNotloadcacheatstart envVariable = "GDD_NACOS_NOTLOADCACHEATSTART"
   216  	GddNacosLogDir              envVariable = "GDD_NACOS_LOG_DIR"
   217  	GddNacosCacheDir            envVariable = "GDD_NACOS_CACHE_DIR"
   218  	GddNacosLogLevel            envVariable = "GDD_NACOS_LOG_LEVEL"
   219  	GddNacosLogDiscard          envVariable = "GDD_NACOS_LOG_DISCARD"
   220  	GddNacosServerAddr          envVariable = "GDD_NACOS_SERVER_ADDR"
   221  	GddNacosRegisterHost        envVariable = "GDD_NACOS_REGISTER_HOST"
   222  	GddNacosClusterName         envVariable = "GDD_NACOS_CLUSTER_NAME"
   223  	GddNacosGroupName           envVariable = "GDD_NACOS_GROUP_NAME"
   224  	// GddNacosConfigFormat has two options available: dotenv, yaml
   225  	GddNacosConfigFormat envVariable = "GDD_NACOS_CONFIG_FORMAT"
   226  	GddNacosConfigGroup  envVariable = "GDD_NACOS_CONFIG_GROUP"
   227  	GddNacosConfigDataid envVariable = "GDD_NACOS_CONFIG_DATAID"
   228  
   229  	// GddWeight node weight
   230  	GddWeight envVariable = "GDD_WEIGHT"
   231  
   232  	GddApolloCluster      envVariable = "GDD_APOLLO_CLUSTER"
   233  	GddApolloAddr         envVariable = "GDD_APOLLO_ADDR"
   234  	GddApolloNamespace    envVariable = "GDD_APOLLO_NAMESPACE"
   235  	GddApolloBackupEnable envVariable = "GDD_APOLLO_BACKUP_ENABLE"
   236  	GddApolloBackupPath   envVariable = "GDD_APOLLO_BACKUP_PATH"
   237  	GddApolloMuststart    envVariable = "GDD_APOLLO_MUSTSTART"
   238  	GddApolloSecret       envVariable = "GDD_APOLLO_SECRET"
   239  	GddApolloLogEnable    envVariable = "GDD_APOLLO_LOG_ENABLE"
   240  
   241  	// GddSqlLogEnable only for doc purpose
   242  	GddSqlLogEnable envVariable = "GDD_SQL_LOG_ENABLE"
   243  
   244  	GddStatsFreq envVariable = "GDD_STATS_FREQ"
   245  )
   246  
   247  // Load loads value from environment variable
   248  func (receiver envVariable) Load() string {
   249  	return os.Getenv(string(receiver))
   250  }
   251  
   252  func (receiver envVariable) LoadOrDefault(d string) string {
   253  	val := d
   254  	if stringutils.IsNotEmpty(receiver.Load()) {
   255  		val = receiver.Load()
   256  	}
   257  	return val
   258  }
   259  
   260  // String return string representation for receiver
   261  func (receiver envVariable) String() string {
   262  	return receiver.Load()
   263  }
   264  
   265  // Write sets the environment variable to value
   266  func (receiver envVariable) Write(value string) error {
   267  	return os.Setenv(string(receiver), value)
   268  }
   269  
   270  func GetNacosClientParam() vo.NacosClientParam {
   271  	namespaceId := DefaultGddNacosNamespaceId
   272  	if stringutils.IsNotEmpty(GddNacosNamespaceId.Load()) {
   273  		namespaceId = GddNacosNamespaceId.Load()
   274  	}
   275  	timeoutMs := DefaultGddNacosTimeoutMs
   276  	if stringutils.IsNotEmpty(GddNacosTimeoutMs.Load()) {
   277  		if t, err := cast.ToIntE(GddNacosTimeoutMs.Load()); err == nil {
   278  			timeoutMs = t
   279  		}
   280  	}
   281  	notLoadCacheAtStart := DefaultGddNacosNotLoadCacheAtStart
   282  	if stringutils.IsNotEmpty(GddNacosNotLoadCacheAtStart.Load()) {
   283  		notLoadCacheAtStart, _ = cast.ToBoolE(GddNacosNotLoadCacheAtStart.Load())
   284  	}
   285  	logDir := DefaultGddNacosLogDir
   286  	if stringutils.IsNotEmpty(GddNacosLogDir.Load()) {
   287  		logDir = GddNacosLogDir.Load()
   288  	}
   289  	cacheDir := DefaultGddNacosCacheDir
   290  	if stringutils.IsNotEmpty(GddNacosCacheDir.Load()) {
   291  		cacheDir = GddNacosCacheDir.Load()
   292  	}
   293  	logLevel := DefaultGddNacosLogLevel
   294  	if stringutils.IsNotEmpty(GddNacosLogLevel.Load()) {
   295  		logLevel = GddNacosLogLevel.Load()
   296  	}
   297  	logDiscard := DefaultGddNacosLogDiscard
   298  	if stringutils.IsNotEmpty(GddNacosLogDiscard.Load()) {
   299  		logDiscard, _ = cast.ToBoolE(GddNacosLogDiscard.Load())
   300  	}
   301  	clientConfig := *constant.NewClientConfig(
   302  		constant.WithNamespaceId(namespaceId),
   303  		constant.WithTimeoutMs(uint64(timeoutMs)),
   304  		constant.WithNotLoadCacheAtStart(notLoadCacheAtStart),
   305  		constant.WithLogDir(logDir),
   306  		constant.WithCacheDir(cacheDir),
   307  		constant.WithLogLevel(logLevel),
   308  		constant.WithLogDiscard(logDiscard),
   309  	)
   310  	serverAddrStr := DefaultGddNacosServerAddr
   311  	if stringutils.IsNotEmpty(GddNacosServerAddr.Load()) {
   312  		serverAddrStr = GddNacosServerAddr.Load()
   313  	}
   314  	var serverConfigs []constant.ServerConfig
   315  	addrs := strings.Split(serverAddrStr, ",")
   316  	for _, addr := range addrs {
   317  		u, err := url.Parse(addr)
   318  		if err != nil {
   319  			panic(fmt.Errorf("[go-doudou] failed to create nacos discovery client: %v", err))
   320  		}
   321  		host, port, err := net.SplitHostPort(u.Host)
   322  		if err != nil {
   323  			panic(fmt.Errorf("[go-doudou] failed to create nacos discovery client: %v", err))
   324  		}
   325  		serverConfigs = append(serverConfigs, *constant.NewServerConfig(
   326  			host,
   327  			uint64(cast.ToInt(port)),
   328  			constant.WithScheme(u.Scheme),
   329  			constant.WithContextPath(u.Path),
   330  		))
   331  	}
   332  
   333  	return vo.NacosClientParam{
   334  		ClientConfig:  &clientConfig,
   335  		ServerConfigs: serverConfigs,
   336  	}
   337  }