config.go 9.0 KB
Newer Older
1 2 3 4 5
package config

import (
	"fmt"
	"github.com/spf13/viper"
6
	authoptions "kubesphere.io/kubesphere/pkg/apiserver/authentication/options"
H
hongming 已提交
7
	authorizationoptions "kubesphere.io/kubesphere/pkg/apiserver/authorization/options"
J
Jeff 已提交
8
	"kubesphere.io/kubesphere/pkg/simple/client/alerting"
Z
zryfish 已提交
9
	"kubesphere.io/kubesphere/pkg/simple/client/cache"
R
runzexia 已提交
10
	"kubesphere.io/kubesphere/pkg/simple/client/devops/jenkins"
J
junotx 已提交
11
	eventsclient "kubesphere.io/kubesphere/pkg/simple/client/events/elasticsearch"
12 13
	"kubesphere.io/kubesphere/pkg/simple/client/k8s"
	"kubesphere.io/kubesphere/pkg/simple/client/ldap"
G
Guangzhe Huang 已提交
14
	"kubesphere.io/kubesphere/pkg/simple/client/logging/elasticsearch"
G
Guangzhe Huang 已提交
15
	"kubesphere.io/kubesphere/pkg/simple/client/monitoring/prometheus"
H
hongming 已提交
16
	"kubesphere.io/kubesphere/pkg/simple/client/multicluster"
17
	"kubesphere.io/kubesphere/pkg/simple/client/network"
J
Jeff 已提交
18
	"kubesphere.io/kubesphere/pkg/simple/client/notification"
19
	"kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
Z
zryfish 已提交
20
	"kubesphere.io/kubesphere/pkg/simple/client/s3"
21 22
	"kubesphere.io/kubesphere/pkg/simple/client/servicemesh"
	"kubesphere.io/kubesphere/pkg/simple/client/sonarqube"
J
Jeff 已提交
23 24
	"reflect"
	"strings"
25 26
)

J
Jeff 已提交
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
// Package config saves configuration for running KubeSphere components
//
// Config can be configured from command line flags and configuration file.
// Command line flags hold higher priority than configuration file. But if
// component Endpoint/Host/APIServer was left empty, all of that component
// command line flags will be ignored, use configuration file instead.
// For example, we have configuration file
//
// mysql:
//   host: mysql.kubesphere-system.svc
//   username: root
//   password: password
//
// At the same time, have command line flags like following:
//
// --mysql-host mysql.openpitrix-system.svc --mysql-username king --mysql-password 1234
//
// We will use `king:1234@mysql.openpitrix-system.svc` from command line flags rather
// than `root:password@mysql.kubesphere-system.svc` from configuration file,
// cause command line has higher priority. But if command line flags like following:
//
// --mysql-username root --mysql-password password
//
50
// we will `root:password@mysql.kubesphere-system.svc` as input, cause
J
Jeff 已提交
51 52 53
// mysql-host is missing in command line flags, all other mysql command line flags
// will be ignored.

54
const (
J
Jeff 已提交
55
	// DefaultConfigurationName is the default name of configuration
56
	defaultConfigurationName = "kubesphere"
J
Jeff 已提交
57 58

	// DefaultConfigurationPath the default location of the configuration file
59
	defaultConfigurationPath = "/etc/kubesphere"
60 61
)

62
// Config defines everything needed for apiserver to deal with external services
63
type Config struct {
H
hongming 已提交
64 65 66 67 68 69 70 71 72 73 74 75
	DevopsOptions         *jenkins.Options                           `json:"devops,omitempty" yaml:"devops,omitempty" mapstructure:"devops"`
	SonarQubeOptions      *sonarqube.Options                         `json:"sonarqube,omitempty" yaml:"sonarQube,omitempty" mapstructure:"sonarqube"`
	KubernetesOptions     *k8s.KubernetesOptions                     `json:"kubernetes,omitempty" yaml:"kubernetes,omitempty" mapstructure:"kubernetes"`
	ServiceMeshOptions    *servicemesh.Options                       `json:"servicemesh,omitempty" yaml:"servicemesh,omitempty" mapstructure:"servicemesh"`
	NetworkOptions        *network.Options                           `json:"network,omitempty" yaml:"network,omitempty" mapstructure:"network"`
	LdapOptions           *ldap.Options                              `json:"-,omitempty" yaml:"ldap,omitempty" mapstructure:"ldap"`
	RedisOptions          *cache.Options                             `json:"redis,omitempty" yaml:"redis,omitempty" mapstructure:"redis"`
	S3Options             *s3.Options                                `json:"s3,omitempty" yaml:"s3,omitempty" mapstructure:"s3"`
	OpenPitrixOptions     *openpitrix.Options                        `json:"openpitrix,omitempty" yaml:"openpitrix,omitempty" mapstructure:"openpitrix"`
	MonitoringOptions     *prometheus.Options                        `json:"monitoring,omitempty" yaml:"monitoring,omitempty" mapstructure:"monitoring"`
	LoggingOptions        *elasticsearch.Options                     `json:"logging,omitempty" yaml:"logging,omitempty" mapstructure:"logging"`
	AuthenticationOptions *authoptions.AuthenticationOptions         `json:"authentication,omitempty" yaml:"authentication,omitempty" mapstructure:"authentication"`
H
hongming 已提交
76
	AuthorizationOptions  *authorizationoptions.AuthorizationOptions `json:"authorization,omitempty" yaml:"authorization,omitempty" mapstructure:"authorization"`
H
hongming 已提交
77
	MultiClusterOptions   *multicluster.Options                      `json:"multicluster,omitempty" yaml:"multicluster,omitempty" mapstructure:"multicluster"`
J
junotx 已提交
78
	EventsOptions         *eventsclient.Options                      `json:"events,omitempty" yaml:"events,omitempty" mapstructure:"events"`
J
Jeff 已提交
79 80
	// Options used for enabling components, not actually used now. Once we switch Alerting/Notification API to kubesphere,
	// we can add these options to kubesphere command lines
Z
zryfish 已提交
81 82
	AlertingOptions     *alerting.Options     `json:"alerting,omitempty" yaml:"alerting,omitempty" mapstructure:"alerting"`
	NotificationOptions *notification.Options `json:"notification,omitempty" yaml:"notification,omitempty" mapstructure:"notification"`
83 84
}

85 86
// newConfig creates a default non-empty Config
func New() *Config {
87
	return &Config{
88 89 90 91
		DevopsOptions:         jenkins.NewDevopsOptions(),
		SonarQubeOptions:      sonarqube.NewSonarQubeOptions(),
		KubernetesOptions:     k8s.NewKubernetesOptions(),
		ServiceMeshOptions:    servicemesh.NewServiceMeshOptions(),
92
		NetworkOptions:        network.NewNetworkOptions(),
93 94 95 96 97 98 99 100 101
		LdapOptions:           ldap.NewOptions(),
		RedisOptions:          cache.NewRedisOptions(),
		S3Options:             s3.NewS3Options(),
		OpenPitrixOptions:     openpitrix.NewOptions(),
		MonitoringOptions:     prometheus.NewPrometheusOptions(),
		AlertingOptions:       alerting.NewAlertingOptions(),
		NotificationOptions:   notification.NewNotificationOptions(),
		LoggingOptions:        elasticsearch.NewElasticSearchOptions(),
		AuthenticationOptions: authoptions.NewAuthenticateOptions(),
H
hongming 已提交
102
		AuthorizationOptions:  authorizationoptions.NewAuthorizationOptions(),
H
hongming 已提交
103
		MultiClusterOptions:   multicluster.NewOptions(),
J
junotx 已提交
104
		EventsOptions:         eventsclient.NewElasticSearchOptions(),
105 106 107
	}
}

108 109 110 111 112
// TryLoadFromDisk loads configuration from default location after server startup
// return nil error if configuration file not exists
func TryLoadFromDisk() (*Config, error) {
	viper.SetConfigName(defaultConfigurationName)
	viper.AddConfigPath(defaultConfigurationPath)
113

114 115
	// Load from current working directory, only used for debugging
	viper.AddConfigPath(".")
116

117 118 119 120 121 122
	if err := viper.ReadInConfig(); err != nil {
		if _, ok := err.(viper.ConfigFileNotFoundError); ok {
			return nil, err
		} else {
			return nil, fmt.Errorf("error parsing configuration file %s", err)
		}
J
Jeff 已提交
123 124
	}

125
	conf := New()
126

127 128
	if err := viper.Unmarshal(conf); err != nil {
		return nil, err
J
Jeff 已提交
129 130
	}

131 132
	return conf, nil
}
133

134 135
// convertToMap simply converts config to map[string]bool
// to hide sensitive information
136 137
func (conf *Config) ToMap() map[string]bool {
	conf.stripEmptyOptions()
138
	result := make(map[string]bool, 0)
139

140 141
	if conf == nil {
		return result
142 143
	}

144
	c := reflect.Indirect(reflect.ValueOf(conf))
145

146 147 148 149 150
	for i := 0; i < c.NumField(); i++ {
		name := strings.Split(c.Type().Field(i).Tag.Get("json"), ",")[0]
		if strings.HasPrefix(name, "-") {
			continue
		}
151

152 153 154 155 156
		if c.Field(i).IsNil() {
			result[name] = false
		} else {
			result[name] = true
		}
157
	}
158 159

	return result
160
}
J
Jeff 已提交
161

Z
zryfish 已提交
162
// Remove invalid options before serializing to json or yaml
163
func (conf *Config) stripEmptyOptions() {
J
Jeff 已提交
164

Z
zryfish 已提交
165
	if conf.RedisOptions != nil && conf.RedisOptions.Host == "" {
166
		conf.RedisOptions = nil
J
Jeff 已提交
167 168
	}

169 170
	if conf.DevopsOptions != nil && conf.DevopsOptions.Host == "" {
		conf.DevopsOptions = nil
J
Jeff 已提交
171 172
	}

173 174 175
	if conf.MonitoringOptions != nil && conf.MonitoringOptions.Endpoint == "" &&
		conf.MonitoringOptions.SecondaryEndpoint == "" {
		conf.MonitoringOptions = nil
J
Jeff 已提交
176 177
	}

178 179
	if conf.SonarQubeOptions != nil && conf.SonarQubeOptions.Host == "" {
		conf.SonarQubeOptions = nil
J
Jeff 已提交
180 181
	}

182 183
	if conf.LdapOptions != nil && conf.LdapOptions.Host == "" {
		conf.LdapOptions = nil
J
Jeff 已提交
184 185
	}

186 187
	if conf.OpenPitrixOptions != nil && conf.OpenPitrixOptions.IsEmpty() {
		conf.OpenPitrixOptions = nil
J
Jeff 已提交
188 189
	}

190 191 192 193
	if conf.NetworkOptions != nil && conf.NetworkOptions.WeaveScopeHost == "" {
		conf.NetworkOptions = nil
	}

194 195 196 197
	if conf.ServiceMeshOptions != nil && conf.ServiceMeshOptions.IstioPilotHost == "" &&
		conf.ServiceMeshOptions.ServicemeshPrometheusHost == "" &&
		conf.ServiceMeshOptions.JaegerQueryHost == "" {
		conf.ServiceMeshOptions = nil
J
Jeff 已提交
198 199
	}

200 201
	if conf.S3Options != nil && conf.S3Options.Endpoint == "" {
		conf.S3Options = nil
J
Jeff 已提交
202 203
	}

204 205
	if conf.AlertingOptions != nil && conf.AlertingOptions.Endpoint == "" {
		conf.AlertingOptions = nil
J
Jeff 已提交
206 207
	}

208 209
	if conf.LoggingOptions != nil && conf.LoggingOptions.Host == "" {
		conf.LoggingOptions = nil
J
Jeff 已提交
210 211
	}

212 213
	if conf.NotificationOptions != nil && conf.NotificationOptions.Endpoint == "" {
		conf.NotificationOptions = nil
J
Jeff 已提交
214 215
	}

Z
zryfish 已提交
216 217 218
	if conf.MultiClusterOptions != nil && !conf.MultiClusterOptions.Enable {
		conf.MultiClusterOptions = nil
	}
J
junotx 已提交
219 220 221 222

	if conf.EventsOptions != nil && conf.EventsOptions.Host == "" {
		conf.EventsOptions = nil
	}
J
Jeff 已提交
223
}