pkg/admin/config/config.go (180 lines of code) (raw):

/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package config import ( "net/url" "os" "path/filepath" "strings" "dubbo.apache.org/dubbo-go/v3/common" "dubbo.apache.org/dubbo-go/v3/common/extension" "dubbo.apache.org/dubbo-go/v3/config_center" "dubbo.apache.org/dubbo-go/v3/metadata/report" "dubbo.apache.org/dubbo-go/v3/registry" "github.com/glebarez/sqlite" "gorm.io/driver/mysql" "gorm.io/gorm" "github.com/apache/dubbo-admin/pkg/admin/constant" _ "github.com/apache/dubbo-admin/pkg/admin/imports" "github.com/apache/dubbo-admin/pkg/admin/model" "github.com/apache/dubbo-admin/pkg/logger" "gopkg.in/yaml.v2" ) const ( conf = "./conf/dubboadmin.yml" confPathKey = "ADMIN_CONFIG_PATH" ) const MockProviderConf = "./conf/mock_provider.yml" type Config struct { Admin Admin `yaml:"admin"` Prometheus Prometheus `yaml:"prometheus"` } type Prometheus struct { Ip string `json:"ip"` Port string `json:"port"` } type Admin struct { ConfigCenter string `yaml:"config-center"` MetadataReport AddressConfig `yaml:"metadata-report"` Registry AddressConfig `yaml:"registry"` MysqlDsn string `yaml:"mysql-dsn"` } var ( Governance GovernanceConfig RegistryCenter registry.Registry MetadataReportCenter report.MetadataReport DataBase *gorm.DB // for service mock ) var ( PrometheusIp string PrometheusPort string ) func LoadConfig() { configFilePath := conf if envPath := os.Getenv(confPathKey); envPath != "" { configFilePath = envPath } path, err := filepath.Abs(configFilePath) if err != nil { path = filepath.Clean(configFilePath) } content, err := os.ReadFile(path) if err != nil { panic(err) } var config Config err = yaml.Unmarshal(content, &config) if err != nil { logger.Errorf("Invalid configuration: \n %s", content) panic(err) } address := config.Admin.ConfigCenter registryAddress := config.Admin.Registry.Address metadataReportAddress := config.Admin.MetadataReport.Address loadDatabaseConfig(config.Admin.MysqlDsn) PrometheusIp = config.Prometheus.Ip PrometheusPort = config.Prometheus.Port if PrometheusIp == "" { PrometheusIp = "127.0.0.1" } if PrometheusPort == "" { PrometheusPort = "9090" } c, addrUrl := getValidAddressConfig(address, registryAddress) configCenter := newConfigCenter(c, addrUrl) Governance = newGovernanceConfig(configCenter, c.getProtocol()) properties, err := configCenter.GetProperties(constant.DubboPropertyKey) if err != nil { logger.Info("No configuration found in config center.") } if len(properties) > 0 { logger.Infof("Loaded remote configuration from config center:\n %s", properties) for _, property := range strings.Split(properties, "\n") { if strings.HasPrefix(property, constant.RegistryAddressKey) { registryAddress = strings.Split(property, "=")[1] } if strings.HasPrefix(property, constant.MetadataReportAddressKey) { metadataReportAddress = strings.Split(property, "=")[1] } } } if len(registryAddress) > 0 { logger.Infof("Valid registry address is %s", registryAddress) c := newAddressConfig(registryAddress) addrUrl, err := c.toURL() if err != nil { panic(err) } RegistryCenter, err = extension.GetRegistry(c.getProtocol(), addrUrl) if err != nil { panic(err) } } if len(metadataReportAddress) > 0 { logger.Infof("Valid meta center address is %s", metadataReportAddress) c := newAddressConfig(metadataReportAddress) addrUrl, err := c.toURL() if err != nil { panic(err) } factory := extension.GetMetadataReportFactory(c.getProtocol()) MetadataReportCenter = factory.CreateMetadataReport(addrUrl) } } func getValidAddressConfig(address string, registryAddress string) (AddressConfig, *common.URL) { if len(address) <= 0 && len(registryAddress) <= 0 { panic("Must at least specify `admin.config-center.address` or `admin.registry.address`!") } var c AddressConfig if len(address) > 0 { logger.Infof("Specified config center address is %s", address) c = newAddressConfig(address) } else { logger.Info("Using registry address as default config center address") c = newAddressConfig(registryAddress) } configUrl, err := c.toURL() if err != nil { panic(err) } return c, configUrl } func newConfigCenter(c AddressConfig, url *common.URL) config_center.DynamicConfiguration { factory, err := extension.GetConfigCenterFactory(c.getProtocol()) if err != nil { logger.Info(err.Error()) panic(err) } configCenter, err := factory.GetDynamicConfiguration(url) if err != nil { logger.Info("Failed to init config center, error msg is %s.", err.Error()) panic(err) } return configCenter } func newAddressConfig(address string) AddressConfig { config := AddressConfig{} config.Address = address var err error config.url, err = url.Parse(address) if err != nil { panic(err) } return config } // load database for mock rule storage, if dsn is empty, use sqlite in memory func loadDatabaseConfig(dsn string) { var db *gorm.DB var err error if dsn == "" { db, err = gorm.Open(sqlite.Open(":memory:"), &gorm.Config{}) } else { db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{}) } if err != nil { panic(err) } else { DataBase = db // init table initErr := DataBase.AutoMigrate(&model.MockRuleEntity{}) if initErr != nil { panic(initErr) } } }