Using harbor lib config

using config manager to get env configs

Signed-off-by: Qian Deng <dengq@vmware.com>
This commit is contained in:
Qian Deng 2021-09-16 22:47:01 +00:00
parent 543d044f7a
commit 31707dbf25
11 changed files with 243 additions and 41 deletions

View File

@ -169,4 +169,21 @@ const (
MetricEnable = "metric_enable"
MetricPort = "metric_port"
MetricPath = "metric_path"
// Trace setting items
TraceEnabled = "trace_enabled"
TraceServiceName = "trace_service_name"
TraceSampleRate = "trace_sample_rate"
TraceNamespace = "trace_namespace"
TraceAttributes = "trace_attribute"
TraceJaegerEndpoint = "trace_jaeger_endpoint"
TraceJaegerUsername = "trace_jaeger_username"
TraceJaegerPassword = "trace_jaeger_password"
TraceJaegerAgentHost = "trace_jaeger_agent_host"
TraceJaegerAgentPort = "trace_jaeger_agent_port"
TraceOtelEndpoint = "trace_otel_endpoint"
TraceOtelURLPath = "trace_otel_url_path"
TraceOtelCompression = "trace_otel_compression"
TraceOtelInsecure = "trace_otel_insecure"
TraceOtelTimeout = "trace_otel_timeout"
)

View File

@ -20,7 +20,6 @@ import (
"net/http"
"time"
tracelib "github.com/goharbor/harbor/src/lib/trace"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
)
@ -43,10 +42,11 @@ func init() {
} else {
secureHTTPTransport = NewTransport()
}
if tracelib.Enabled() {
insecureHTTPTransport = otelhttp.NewTransport(insecureHTTPTransport)
secureHTTPTransport = otelhttp.NewTransport(secureHTTPTransport)
}
}
func AddTracingWithGlobalTransport() {
insecureHTTPTransport = otelhttp.NewTransport(insecureHTTPTransport)
secureHTTPTransport = otelhttp.NewTransport(secureHTTPTransport)
}
// Use this instead of Default Transport in library because it sets ForceAttemptHTTP2 to true

View File

@ -54,6 +54,7 @@ import (
"github.com/goharbor/harbor/src/lib/orm"
tracelib "github.com/goharbor/harbor/src/lib/trace"
"github.com/goharbor/harbor/src/migration"
_ "github.com/goharbor/harbor/src/pkg/config/inmemory"
"github.com/goharbor/harbor/src/pkg/notification"
_ "github.com/goharbor/harbor/src/pkg/notifier/topic"
"github.com/goharbor/harbor/src/pkg/oidc"
@ -187,6 +188,7 @@ func main() {
go metric.ServeProm(metricCfg.Path, metricCfg.Port)
}
ctx := context.Background()
config.InitTraceConfig(ctx)
shutdownTracerProvider := tracelib.InitGlobalTracer(ctx)
token.InitCreators()
database, err := config.Database()

View File

@ -29,6 +29,7 @@ import (
"github.com/goharbor/harbor/src/jobservice/runtime"
cfgLib "github.com/goharbor/harbor/src/lib/config"
tracelib "github.com/goharbor/harbor/src/lib/trace"
_ "github.com/goharbor/harbor/src/pkg/config/inmemory"
_ "github.com/goharbor/harbor/src/pkg/config/rest"
)
@ -59,6 +60,7 @@ func main() {
panic(err)
}
cfgLib.InitTraceConfig(ctx)
defer tracelib.InitGlobalTracer(context.Background()).Shutdown()
// Set job context initializer

View File

@ -156,11 +156,28 @@ var (
{Name: common.RobotTokenDuration, Scope: UserScope, Group: BasicGroup, EnvKey: "ROBOT_TOKEN_DURATION", DefaultValue: "30", ItemType: &IntType{}, Editable: true, Description: `The robot account token duration in days`},
{Name: common.RobotNamePrefix, Scope: UserScope, Group: BasicGroup, EnvKey: "ROBOT_NAME_PREFIX", DefaultValue: "robot$", ItemType: &StringType{}, Editable: true, Description: `The rebot account name prefix`},
{Name: common.NotificationEnable, Scope: UserScope, Group: BasicGroup, EnvKey: "NOTIFICATION_ENABLE", DefaultValue: "true", ItemType: &BoolType{}, Editable: true, Description: `Enable notification`},
{Name: common.MetricEnable, Scope: SystemScope, Group: BasicGroup, EnvKey: "METRIC_ENABLE", DefaultValue: "false", ItemType: &BoolType{}, Editable: true},
{Name: common.MetricPort, Scope: SystemScope, Group: BasicGroup, EnvKey: "METRIC_PORT", DefaultValue: "9090", ItemType: &IntType{}, Editable: true},
{Name: common.MetricPort, Scope: SystemScope, Group: BasicGroup, EnvKey: "METRIC_PORT", DefaultValue: "9090", ItemType: &PortType{}, Editable: true},
{Name: common.MetricPath, Scope: SystemScope, Group: BasicGroup, EnvKey: "METRIC_PATH", DefaultValue: "/metrics", ItemType: &StringType{}, Editable: true},
{Name: common.QuotaPerProjectEnable, Scope: UserScope, Group: QuotaGroup, EnvKey: "QUOTA_PER_PROJECT_ENABLE", DefaultValue: "true", ItemType: &BoolType{}, Editable: true, Description: `Enable quota per project`},
{Name: common.StoragePerProject, Scope: UserScope, Group: QuotaGroup, EnvKey: "STORAGE_PER_PROJECT", DefaultValue: "-1", ItemType: &QuotaType{}, Editable: true, Description: `The storage quota per project`},
{Name: common.TraceEnabled, Scope: SystemScope, Group: BasicGroup, EnvKey: "TRACE_ENABLED", DefaultValue: "false", ItemType: &BoolType{}, Editable: false, Description: `Enable trace`},
{Name: common.TraceServiceName, Scope: SystemScope, Group: BasicGroup, EnvKey: "TRACE_SERVICE_NAME", DefaultValue: "", ItemType: &StringType{}, Editable: false, Description: `The service name of the trace`},
{Name: common.TraceNamespace, Scope: SystemScope, Group: BasicGroup, EnvKey: "TRACE_NAMESPACE", DefaultValue: "", ItemType: &StringType{}, Editable: false, Description: `The namespace of the trace`},
{Name: common.TraceSampleRate, Scope: SystemScope, Group: BasicGroup, EnvKey: "TRACE_SAMPLE_RATE", DefaultValue: "1", ItemType: &Float64Type{}, Editable: false, Description: `The sample rate of the trace`},
{Name: common.TraceAttributes, Scope: SystemScope, Group: BasicGroup, EnvKey: "TRACE_ATTRIBUTES", DefaultValue: "", ItemType: &StringToStringMapType{}, Editable: false, Description: `The attribute of the trace`},
{Name: common.TraceJaegerEndpoint, Scope: SystemScope, Group: BasicGroup, EnvKey: "TRACE_JAEGER_ENDPOINT", DefaultValue: "", ItemType: &StringType{}, Editable: false, Description: `The endpoint of the Jaeger`},
{Name: common.TraceJaegerUsername, Scope: SystemScope, Group: BasicGroup, EnvKey: "TRACE_JAEGER_USERNAME", DefaultValue: "", ItemType: &StringType{}, Editable: false, Description: `The username of the Jaeger`},
{Name: common.TraceJaegerPassword, Scope: SystemScope, Group: BasicGroup, EnvKey: "TRACE_JAEGER_PASSWORD", DefaultValue: "", ItemType: &PasswordType{}, Editable: false, Description: `The password of the Jaeger`},
{Name: common.TraceJaegerAgentHost, Scope: SystemScope, Group: BasicGroup, EnvKey: "TRACE_JAEGER_AGENT_HOSTNAME", DefaultValue: "", ItemType: &StringType{}, Editable: false, Description: `The agent host of the Jaeger`},
{Name: common.TraceJaegerAgentPort, Scope: SystemScope, Group: BasicGroup, EnvKey: "TRACE_JAEGER_AGENT_PORT", DefaultValue: "6831", ItemType: &StringType{}, Editable: false, Description: `The agent port of the Jaeger`},
{Name: common.TraceOtelEndpoint, Scope: SystemScope, Group: BasicGroup, EnvKey: "TRACE_OTEL_ENDPOINT", DefaultValue: "", ItemType: &StringType{}, Editable: false, Description: `The endpoint of the Otel`},
{Name: common.TraceOtelURLPath, Scope: SystemScope, Group: BasicGroup, EnvKey: "TRACE_OTEL_URL_PATH", DefaultValue: "", ItemType: &StringType{}, Editable: false, Description: `The URL path of the Otel`},
{Name: common.TraceOtelCompression, Scope: SystemScope, Group: BasicGroup, EnvKey: "TRACE_OTEL_COMPRESSION", DefaultValue: "", ItemType: &BoolType{}, Editable: false, Description: `The compression of the Otel`},
{Name: common.TraceOtelInsecure, Scope: SystemScope, Group: BasicGroup, EnvKey: "TRACE_OTEL_INSECURE", DefaultValue: "", ItemType: &BoolType{}, Editable: false, Description: `The insecure of the Otel`},
{Name: common.TraceOtelTimeout, Scope: SystemScope, Group: BasicGroup, EnvKey: "TRACE_OTEL_TIMEOUT", DefaultValue: "", ItemType: &IntType{}, Editable: false, Description: `The timeout of the Otel`},
}
)

View File

@ -148,6 +148,17 @@ func (t *Int64Type) get(str string) (interface{}, error) {
return parseInt64(str)
}
type Float64Type struct{}
func (f *Float64Type) validate(str string) error {
_, err := parseFloat64(str)
return err
}
func (f *Float64Type) get(str string) (interface{}, error) {
return parseFloat64(str)
}
// BoolType ...
type BoolType struct {
}
@ -251,3 +262,12 @@ func parseInt(str string) (int, error) {
return 0, fmt.Errorf("invalid int string: %s", str)
}
func parseFloat64(str string) (float64, error) {
val, err := strconv.ParseFloat(str, 64)
if err == nil {
return val, nil
}
return 0, fmt.Errorf("invalid float64 string: %s", str)
}

View File

@ -95,6 +95,21 @@ func (c *ConfigureValue) GetInt64() int64 {
return 0
}
func (c *ConfigureValue) GetFloat64() float64 {
if item, ok := Instance().GetByName(c.Name); ok {
val, err := item.ItemType.get(c.Value)
if err != nil {
log.Errorf("GetFloat64 failed, error: %+v", err)
return 0
}
if float64Value, suc := val.(float64); suc {
return float64Value
}
}
log.Errorf("GetFloat64 failed, the current value's metadata is not defined, %+v", c)
return 0
}
// GetBool - return the bool value of current setting
func (c *ConfigureValue) GetBool() bool {
if item, ok := Instance().GetByName(c.Name); ok {

37
src/lib/config/trace.go Normal file
View File

@ -0,0 +1,37 @@
package config
import (
"context"
"github.com/goharbor/harbor/src/common"
commonhttp "github.com/goharbor/harbor/src/common/http"
"github.com/goharbor/harbor/src/lib/log"
tracelib "github.com/goharbor/harbor/src/lib/trace"
)
func InitTraceConfig(ctx context.Context) {
cfgMgr, err := GetManager(common.InMemoryCfgManager)
if err != nil {
log.Fatalf("failed to get config manager: %v", err)
}
tracelib.InitGlobalConfig(
tracelib.WithEnabled(cfgMgr.Get(ctx, common.TraceEnabled).GetBool()),
tracelib.WithServiceName(cfgMgr.Get(ctx, common.TraceServiceName).GetString()),
tracelib.WithNamespace(cfgMgr.Get(ctx, common.TraceNamespace).GetString()),
tracelib.WithSampleRate(cfgMgr.Get(ctx, common.TraceSampleRate).GetFloat64()),
tracelib.WithAttributes(cfgMgr.Get(ctx, common.TraceAttributes).GetStringToStringMap()),
tracelib.WithJaegerEndpoint(cfgMgr.Get(ctx, common.TraceJaegerEndpoint).GetString()),
tracelib.WithJaegerUsername(cfgMgr.Get(ctx, common.TraceJaegerUsername).GetString()),
tracelib.WithJaegerPassword(cfgMgr.Get(ctx, common.TraceJaegerPassword).GetString()),
tracelib.WithJaegerAgentHost(cfgMgr.Get(ctx, common.TraceJaegerAgentHost).GetString()),
tracelib.WithJaegerAgentPort(cfgMgr.Get(ctx, common.TraceJaegerAgentPort).GetString()),
tracelib.WithOtelEndpoint(cfgMgr.Get(ctx, common.TraceOtelEndpoint).GetString()),
tracelib.WithOtelURLPath(cfgMgr.Get(ctx, common.TraceOtelURLPath).GetString()),
tracelib.WithOtelCompression(cfgMgr.Get(ctx, common.TraceOtelCompression).GetBool()),
tracelib.WithOtelInsecure(cfgMgr.Get(ctx, common.TraceOtelInsecure).GetBool()),
tracelib.WithOtelTimeout(cfgMgr.Get(ctx, common.TraceOtelTimeout).GetInt()),
)
if tracelib.Enabled() {
commonhttp.AddTracingWithGlobalTransport()
}
}

View File

@ -15,12 +15,7 @@
package trace
import (
"bytes"
"fmt"
"strings"
"github.com/goharbor/harbor/src/lib/log"
"github.com/spf13/viper"
)
const (
@ -30,31 +25,8 @@ const (
// C is the global configuration for trace
var C Config
func init() {
viper.SetConfigType("json")
viper.SetEnvPrefix(TraceEnvPrefix)
viper.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
viper.AutomaticEnv()
C = Config{Otel: OtelConfig{}, Jaeger: JaegerConfig{}}
C.Enabled = viper.GetBool("enabled")
C.SampleRate = viper.GetFloat64("sample_rate")
C.Namespace = viper.GetString("namespace")
C.ServiceName = viper.GetString("service_name")
C.Jaeger.Endpoint = viper.GetString("jaeger_endpoint")
C.Jaeger.Username = viper.GetString("jaeger_agent_username")
C.Jaeger.Password = viper.GetString("jaeger_agent_password")
C.Jaeger.AgentHost = viper.GetString("jaeger_agent_host")
C.Jaeger.AgentPort = viper.GetString("jaeger_agent_port")
C.Otel.Endpoint = viper.GetString("otel_endpoint")
C.Otel.URLPath = viper.GetString("otel_url_path")
C.Otel.Compression = viper.GetBool("otel_compression")
C.Otel.Insecure = viper.GetBool("otel_insecure")
C.Otel.Timeout = viper.GetInt("otel_timeout")
var jsonExample = []byte(viper.GetString("attributes"))
viper.ReadConfig(bytes.NewBuffer(jsonExample))
fmt.Println(viper.GetStringMapString("attributes"))
C.Attributes = viper.GetStringMapString("attributes")
log.Infof("ns: %s attr %+v", C.Namespace, C.Attributes)
func InitGlobalConfig(opts ...Option) {
C = NewConfig(opts...)
}
// OtelConfig is the configuration for otel
@ -66,6 +38,11 @@ type OtelConfig struct {
Timeout int `mapstructure:"otel_trace_timeout"`
}
func (c *OtelConfig) String() string {
return fmt.Sprintf("endpoint: %s, url_path: %s, compression: %t, insecure: %t, timeout: %d",
c.Endpoint, c.URLPath, c.Compression, c.Insecure, c.Timeout)
}
// JaegerConfig is the configuration for Jaeger
type JaegerConfig struct {
Endpoint string `mapstructure:"jaeger_endpoint"`
@ -75,6 +52,11 @@ type JaegerConfig struct {
AgentPort string `mapstructure:"jaeger_agent_port"`
}
func (c *JaegerConfig) String() string {
return fmt.Sprintf("endpoint: %s, username: %s, password: %s, agent_host: %s, agent_port: %s",
c.Endpoint, c.Username, c.Password, c.AgentHost, c.AgentPort)
}
// Config is the configuration for trace
type Config struct {
Enabled bool `mapstructure:"enabled"`
@ -86,8 +68,111 @@ type Config struct {
Attributes map[string]string
}
func (c *Config) String() string {
return fmt.Sprintf("{Enabled: %v, ServiceName: %v, SampleRate: %v, Namespace: %v, ServiceName: %v, Jaeger: %v, Otel: %v}", c.Enabled, c.ServiceName, c.SampleRate, c.Namespace, c.ServiceName, c.Jaeger, c.Otel)
}
type Option func(*Config)
func WithEnabled(enabled bool) Option {
return func(c *Config) {
c.Enabled = enabled
}
}
func WithSampleRate(sampleRate float64) Option {
return func(c *Config) {
c.SampleRate = sampleRate
}
}
func WithNamespace(namespace string) Option {
return func(c *Config) {
c.Namespace = namespace
}
}
func WithServiceName(serviceName string) Option {
return func(c *Config) {
c.ServiceName = serviceName
}
}
func WithAttributes(attributes map[string]string) Option {
return func(c *Config) {
c.Attributes = attributes
}
}
func WithJaegerEndpoint(endpoint string) Option {
return func(c *Config) {
c.Jaeger.Endpoint = endpoint
}
}
func WithJaegerUsername(username string) Option {
return func(c *Config) {
c.Jaeger.Username = username
}
}
func WithJaegerPassword(password string) Option {
return func(c *Config) {
c.Jaeger.Password = password
}
}
func WithJaegerAgentHost(host string) Option {
return func(c *Config) {
c.Jaeger.AgentHost = host
}
}
func WithJaegerAgentPort(port string) Option {
return func(c *Config) {
c.Jaeger.AgentPort = port
}
}
func WithOtelEndpoint(endpoint string) Option {
return func(c *Config) {
c.Otel.Endpoint = endpoint
}
}
func WithOtelURLPath(urlPath string) Option {
return func(c *Config) {
c.Otel.URLPath = urlPath
}
}
func WithOtelCompression(compression bool) Option {
return func(c *Config) {
c.Otel.Compression = compression
}
}
func WithOtelInsecure(insecure bool) Option {
return func(c *Config) {
c.Otel.Insecure = insecure
}
}
func WithOtelTimeout(timeout int) Option {
return func(c *Config) {
c.Otel.Timeout = timeout
}
}
func NewConfig(opts ...Option) Config {
c := Config{Otel: OtelConfig{}, Jaeger: JaegerConfig{}}
for _, opt := range opts {
opt(&c)
}
return c
}
// GetConfig returns the global configuration for trace
func GetConfig() Config {
func GetGlobalConfig() Config {
return C
}

View File

@ -35,7 +35,7 @@ import (
func initExporter(ctx context.Context) (tracesdk.SpanExporter, error) {
var err error
var exp tracesdk.SpanExporter
cfg := GetConfig()
cfg := GetGlobalConfig()
if len(cfg.Jaeger.Endpoint) != 0 {
// Jaeger collector exporter
log.Infof("init trace provider jaeger collector on %s with user %s", cfg.Jaeger.Endpoint, cfg.Jaeger.Username)
@ -73,12 +73,15 @@ func initExporter(ctx context.Context) (tracesdk.SpanExporter, error) {
}
func initProvider(exp tracesdk.SpanExporter) (*tracesdk.TracerProvider, error) {
cfg := GetConfig()
cfg := GetGlobalConfig()
// prepare attribute resources
attriSlice := []attribute.KeyValue{
semconv.ServiceNameKey.String(cfg.ServiceName),
semconv.ServiceVersionKey.String(version.ReleaseVersion)}
}
if len(version.ReleaseVersion) != 0 {
attriSlice = append(attriSlice, semconv.ServiceVersionKey.String(version.ReleaseVersion))
}
if cfg.Namespace != "" {
attriSlice = append(attriSlice, semconv.ServiceNamespaceKey.String(cfg.Namespace))
}

View File

@ -35,8 +35,10 @@ import (
_ "github.com/docker/distribution/registry/storage/driver/swift"
common_http "github.com/goharbor/harbor/src/common/http"
cfgLib "github.com/goharbor/harbor/src/lib/config"
"github.com/goharbor/harbor/src/lib/log"
tracelib "github.com/goharbor/harbor/src/lib/trace"
_ "github.com/goharbor/harbor/src/pkg/config/inmemory"
"github.com/goharbor/harbor/src/registryctl/config"
"github.com/goharbor/harbor/src/registryctl/handlers"
)
@ -83,7 +85,6 @@ func (s *RegistryCtl) Start() {
if err != nil {
log.Fatal(err)
}
return
}
func main() {
@ -97,6 +98,9 @@ func main() {
if err := config.DefaultConfig.Load(*configPath, true); err != nil {
log.Fatalf("Failed to load configurations with error: %s\n", err)
}
cfgLib.InitTraceConfig(context.Background())
regCtl := &RegistryCtl{
ServerConf: *config.DefaultConfig,
Handler: handlers.NewHandlerChain(*config.DefaultConfig),