1. change glog to klog
2. move types to api package to avoid cyclic import
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/apiserver/runtime"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/kubesphere"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/ldap"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
|
||||
@@ -56,7 +57,11 @@ func InstallAPI(c *restful.Container) {
|
||||
|
||||
ws.Route(ws.GET("/configz").
|
||||
To(func(request *restful.Request, response *restful.Response) {
|
||||
response.WriteAsJson(sharedConfig)
|
||||
var conf = *sharedConfig
|
||||
|
||||
conf.stripEmptyOptions()
|
||||
|
||||
response.WriteAsJson(conf)
|
||||
}).
|
||||
Doc("Get system components configuration").
|
||||
Produces(restful.MIME_JSON).
|
||||
@@ -84,10 +89,19 @@ func Load() error {
|
||||
}
|
||||
|
||||
conf := &Config{}
|
||||
if err := viper.Unmarshal(&conf); err != nil {
|
||||
if err := viper.Unmarshal(conf); err != nil {
|
||||
klog.Error(fmt.Errorf("error unmarshal configuration %v", err))
|
||||
return err
|
||||
} else {
|
||||
// make sure kubesphere options always exists
|
||||
if conf.KubeSphereOptions == nil {
|
||||
conf.KubeSphereOptions = kubesphere.NewKubeSphereOptions()
|
||||
} else {
|
||||
ksOptions := kubesphere.NewKubeSphereOptions()
|
||||
conf.KubeSphereOptions.ApplyTo(ksOptions)
|
||||
conf.KubeSphereOptions = ksOptions
|
||||
}
|
||||
|
||||
conf.Apply(shadowConfig)
|
||||
sharedConfig = conf
|
||||
}
|
||||
@@ -122,6 +136,7 @@ type Config struct {
|
||||
S3Options *s2is3.S3Options `json:"s3,omitempty" yaml:"s3,omitempty" mapstructure:"s3"`
|
||||
OpenPitrixOptions *openpitrix.OpenPitrixOptions `json:"openpitrix,omitempty" yaml:"openpitrix,omitempty" mapstructure:"openpitrix"`
|
||||
MonitoringOptions *prometheus.PrometheusOptions `json:"monitoring,omitempty" yaml:"monitoring,omitempty" mapstructure:"monitoring"`
|
||||
KubeSphereOptions *kubesphere.KubeSphereOptions `json:"-" yaml:"kubesphere,omitempty" mapstructure:"kubesphere"`
|
||||
}
|
||||
|
||||
func newConfig() *Config {
|
||||
@@ -136,6 +151,7 @@ func newConfig() *Config {
|
||||
S3Options: s2is3.NewS3Options(),
|
||||
OpenPitrixOptions: openpitrix.NewOpenPitrixOptions(),
|
||||
MonitoringOptions: prometheus.NewPrometheusOptions(),
|
||||
KubeSphereOptions: kubesphere.NewKubeSphereOptions(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,6 +162,10 @@ func Get() *Config {
|
||||
func (c *Config) Apply(conf *Config) {
|
||||
shadowConfig = conf
|
||||
|
||||
if conf.KubeSphereOptions != nil {
|
||||
conf.KubeSphereOptions.ApplyTo(c.KubeSphereOptions)
|
||||
}
|
||||
|
||||
if conf.MonitoringOptions != nil {
|
||||
conf.MonitoringOptions.ApplyTo(c.MonitoringOptions)
|
||||
}
|
||||
@@ -185,3 +205,45 @@ func (c *Config) Apply(conf *Config) {
|
||||
conf.MySQLOptions.ApplyTo(c.MySQLOptions)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Config) stripEmptyOptions() {
|
||||
if c.MySQLOptions != nil && c.MySQLOptions.Host == "" {
|
||||
c.MySQLOptions = nil
|
||||
}
|
||||
|
||||
if c.RedisOptions != nil && c.RedisOptions.Host == "" {
|
||||
c.RedisOptions = nil
|
||||
}
|
||||
|
||||
if c.DevopsOptions != nil && c.DevopsOptions.Host == "" {
|
||||
c.DevopsOptions = nil
|
||||
}
|
||||
|
||||
if c.MonitoringOptions != nil && c.MonitoringOptions.Endpoint == "" &&
|
||||
c.MonitoringOptions.SecondaryEndpoint == "" {
|
||||
c.MonitoringOptions = nil
|
||||
}
|
||||
|
||||
if c.SonarQubeOptions != nil && c.SonarQubeOptions.Host == "" {
|
||||
c.SonarQubeOptions = nil
|
||||
}
|
||||
|
||||
if c.LdapOptions != nil && c.LdapOptions.Host == "" {
|
||||
c.LdapOptions = nil
|
||||
}
|
||||
|
||||
if c.OpenPitrixOptions != nil && c.OpenPitrixOptions.APIServer == "" {
|
||||
c.OpenPitrixOptions = nil
|
||||
}
|
||||
|
||||
if c.ServiceMeshOptions != nil && c.ServiceMeshOptions.IstioPilotHost == "" &&
|
||||
c.ServiceMeshOptions.ServicemeshPrometheusHost == "" &&
|
||||
c.ServiceMeshOptions.JaegerQueryHost == "" {
|
||||
c.ServiceMeshOptions = nil
|
||||
}
|
||||
|
||||
if c.S3Options != nil && c.S3Options.Endpoint == "" {
|
||||
c.S3Options = nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"io/ioutil"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/devops"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/kubesphere"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/ldap"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/openpitrix"
|
||||
@@ -14,8 +15,8 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/s2is3"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/servicemesh"
|
||||
"kubesphere.io/kubesphere/pkg/simple/client/sonarqube"
|
||||
"kubesphere.io/kubesphere/pkg/utils/reflectutils"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
@@ -82,6 +83,10 @@ func newTestConfig() *Config {
|
||||
Endpoint: "http://prometheus.kubesphere-monitoring-system.svc",
|
||||
SecondaryEndpoint: "http://prometheus.kubesphere-monitoring-system.svc",
|
||||
},
|
||||
KubeSphereOptions: &kubesphere.KubeSphereOptions{
|
||||
APIServer: "http://ks-apiserver.kubesphere-system.svc",
|
||||
AccountServer: "http://ks-account.kubesphere-system.svc",
|
||||
},
|
||||
}
|
||||
return conf
|
||||
}
|
||||
@@ -115,6 +120,7 @@ func cleanTestConfig(t *testing.T) {
|
||||
func TestGet(t *testing.T) {
|
||||
conf := newTestConfig()
|
||||
saveTestConfig(t, conf)
|
||||
//defer cleanTestConfig(t)
|
||||
|
||||
err := Load()
|
||||
if err != nil {
|
||||
@@ -122,8 +128,49 @@ func TestGet(t *testing.T) {
|
||||
}
|
||||
conf2 := Get()
|
||||
|
||||
if !reflect.DeepEqual(conf2, conf) {
|
||||
t.Fatalf("Get %v\n expected %v\n", conf2, conf)
|
||||
if diff := reflectutils.Equal(conf, conf2); diff != nil {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
cleanTestConfig(t)
|
||||
}
|
||||
|
||||
func TestKubeSphereOptions(t *testing.T) {
|
||||
conf := newTestConfig()
|
||||
|
||||
t.Run("save nil kubesphere options", func(t *testing.T) {
|
||||
savedConf := *conf
|
||||
savedConf.KubeSphereOptions = nil
|
||||
saveTestConfig(t, &savedConf)
|
||||
defer cleanTestConfig(t)
|
||||
|
||||
err := Load()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
loadedConf := Get()
|
||||
|
||||
if diff := reflectutils.Equal(conf, loadedConf); diff != nil {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("save partially kubesphere options", func(t *testing.T) {
|
||||
savedConf := *conf
|
||||
savedConf.KubeSphereOptions.APIServer = "http://example.com"
|
||||
savedConf.KubeSphereOptions.AccountServer = ""
|
||||
|
||||
saveTestConfig(t, &savedConf)
|
||||
defer cleanTestConfig(t)
|
||||
|
||||
err := Load()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
loadedConf := Get()
|
||||
|
||||
savedConf.KubeSphereOptions.AccountServer = "http://ks-account.kubesphere-system.svc"
|
||||
|
||||
if diff := reflectutils.Equal(&savedConf, loadedConf); diff != nil {
|
||||
t.Fatal(diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
65
pkg/server/errors/errors.go
Normal file
65
pkg/server/errors/errors.go
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere Authors.
|
||||
|
||||
Licensed 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 errors
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"github.com/emicklei/go-restful"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type Error struct {
|
||||
Message string `json:"message" description:"error message"`
|
||||
}
|
||||
|
||||
var None = Error{Message: "success"}
|
||||
|
||||
func (e *Error) Error() string {
|
||||
return e.Message
|
||||
}
|
||||
|
||||
func Wrap(err error) Error {
|
||||
return Error{Message: err.Error()}
|
||||
}
|
||||
|
||||
func New(message string) Error {
|
||||
return Error{Message: message}
|
||||
}
|
||||
|
||||
func Parse(data []byte) error {
|
||||
var j map[string]string
|
||||
err := json.Unmarshal(data, &j)
|
||||
if err != nil {
|
||||
return errors.New(string(data))
|
||||
} else if message := j["message"]; message != "" {
|
||||
return errors.New(message)
|
||||
} else if message := j["Error"]; message != "" {
|
||||
return errors.New(message)
|
||||
} else {
|
||||
return errors.New(string(data))
|
||||
}
|
||||
}
|
||||
|
||||
func ParseSvcErr(err error, resp *restful.Response) {
|
||||
if svcErr, ok := err.(restful.ServiceError); ok {
|
||||
resp.WriteServiceError(svcErr.Code, svcErr)
|
||||
} else {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, Wrap(err))
|
||||
}
|
||||
}
|
||||
41
pkg/server/filter/logging.go
Normal file
41
pkg/server/filter/logging.go
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere Authors.
|
||||
|
||||
Licensed 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 filter
|
||||
|
||||
import (
|
||||
"k8s.io/klog"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
)
|
||||
|
||||
func Logging(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
|
||||
start := time.Now()
|
||||
chain.ProcessFilter(req, resp)
|
||||
klog.V(4).Infof("%s - \"%s %s %s\" %d %d %dms",
|
||||
strings.Split(req.Request.RemoteAddr, ":")[0],
|
||||
req.Request.Method,
|
||||
req.Request.RequestURI,
|
||||
req.Request.Proto,
|
||||
resp.StatusCode(),
|
||||
resp.ContentLength(),
|
||||
time.Since(start)/time.Millisecond,
|
||||
)
|
||||
}
|
||||
83
pkg/server/options/options.go
Normal file
83
pkg/server/options/options.go
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere Authors.
|
||||
|
||||
Licensed 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 options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/pflag"
|
||||
"kubesphere.io/kubesphere/pkg/utils/net"
|
||||
)
|
||||
|
||||
type ServerRunOptions struct {
|
||||
// server bind address
|
||||
BindAddress string
|
||||
|
||||
// insecure port number
|
||||
InsecurePort int
|
||||
|
||||
// secure port number
|
||||
SecurePort int
|
||||
|
||||
// tls cert file
|
||||
TlsCertFile string
|
||||
|
||||
// tls private key file
|
||||
TlsPrivateKey string
|
||||
}
|
||||
|
||||
func NewServerRunOptions() *ServerRunOptions {
|
||||
// create default server run options
|
||||
s := ServerRunOptions{
|
||||
BindAddress: "0.0.0.0",
|
||||
InsecurePort: 9090,
|
||||
SecurePort: 0,
|
||||
TlsCertFile: "",
|
||||
TlsPrivateKey: "",
|
||||
}
|
||||
|
||||
return &s
|
||||
}
|
||||
|
||||
func (s *ServerRunOptions) Validate() []error {
|
||||
errs := []error{}
|
||||
|
||||
if s.SecurePort == 0 && s.InsecurePort == 0 {
|
||||
errs = append(errs, fmt.Errorf("insecure and secure port can not be disabled at the same time"))
|
||||
}
|
||||
|
||||
if net.IsValidPort(s.SecurePort) {
|
||||
if s.TlsCertFile == "" {
|
||||
errs = append(errs, fmt.Errorf("tls cert file is empty while secure serving"))
|
||||
}
|
||||
|
||||
if s.TlsPrivateKey == "" {
|
||||
errs = append(errs, fmt.Errorf("tls private key file is empty while secure serving"))
|
||||
}
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
func (s *ServerRunOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
|
||||
fs.StringVar(&s.BindAddress, "bind-address", "0.0.0.0", "server bind address")
|
||||
fs.IntVar(&s.InsecurePort, "insecure-port", 9090, "insecure port number")
|
||||
fs.IntVar(&s.SecurePort, "secure-port", 0, "secure port number")
|
||||
fs.StringVar(&s.TlsCertFile, "tls-cert-file", "", "tls cert file")
|
||||
fs.StringVar(&s.TlsPrivateKey, "tls-private-key", "", "tls private key")
|
||||
}
|
||||
94
pkg/server/params/params.go
Normal file
94
pkg/server/params/params.go
Normal file
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
|
||||
Copyright 2019 The KubeSphere Authors.
|
||||
|
||||
Licensed 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 params
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/emicklei/go-restful"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
PagingParam = "paging"
|
||||
OrderByParam = "orderBy"
|
||||
ConditionsParam = "conditions"
|
||||
ReverseParam = "reverse"
|
||||
NameParam = "name"
|
||||
)
|
||||
|
||||
func ParsePaging(paging string) (limit, offset int) {
|
||||
|
||||
limit = 10
|
||||
offset = 0
|
||||
if groups := regexp.MustCompile(`^limit=(\d+),page=(\d+)$`).FindStringSubmatch(paging); len(groups) == 3 {
|
||||
limit, _ = strconv.Atoi(groups[1])
|
||||
page, _ := strconv.Atoi(groups[2])
|
||||
if page < 0 {
|
||||
page = 1
|
||||
}
|
||||
offset = (page - 1) * limit
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ParseConditions(conditionsStr string) (*Conditions, error) {
|
||||
|
||||
conditions := &Conditions{Match: make(map[string]string, 0), Fuzzy: make(map[string]string, 0)}
|
||||
|
||||
if conditionsStr == "" {
|
||||
return conditions, nil
|
||||
}
|
||||
|
||||
// ?conditions=key1=value1,key2~value2,key3=
|
||||
for _, item := range strings.Split(conditionsStr, ",") {
|
||||
// exact query: key=value, if value is empty means label value must be ""
|
||||
// fuzzy query: key~value, if value is empty means label value is "" or label key not exist
|
||||
if groups := regexp.MustCompile(`(\S+)([=~])(\S+)?`).FindStringSubmatch(item); len(groups) >= 3 {
|
||||
value := ""
|
||||
|
||||
if len(groups) > 3 {
|
||||
value = groups[3]
|
||||
}
|
||||
|
||||
if groups[2] == "=" {
|
||||
conditions.Match[groups[1]] = value
|
||||
} else {
|
||||
conditions.Fuzzy[groups[1]] = value
|
||||
}
|
||||
} else {
|
||||
return nil, fmt.Errorf("invalid conditions")
|
||||
}
|
||||
}
|
||||
return conditions, nil
|
||||
}
|
||||
|
||||
func ParseReverse(req *restful.Request) bool {
|
||||
reverse := req.QueryParameter(ReverseParam)
|
||||
b, err := strconv.ParseBool(reverse)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
type Conditions struct {
|
||||
Match map[string]string
|
||||
Fuzzy map[string]string
|
||||
}
|
||||
@@ -3,7 +3,7 @@ package server
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/klog"
|
||||
"net/http"
|
||||
"runtime"
|
||||
)
|
||||
@@ -18,7 +18,7 @@ func LogStackOnRecover(panicReason interface{}, httpWriter http.ResponseWriter)
|
||||
}
|
||||
buffer.WriteString(fmt.Sprintf(" %s:%d\r\n", file, line))
|
||||
}
|
||||
glog.Error(buffer.String())
|
||||
klog.Error(buffer.String())
|
||||
httpWriter.WriteHeader(http.StatusInternalServerError)
|
||||
httpWriter.Write([]byte("recover from panic situation"))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user