Commit a352e76f authored by 赵嘉慧's avatar 赵嘉慧 Committed by zhujf1989
Browse files

make language config file to configmap

parent ad116c22
Showing with 195 additions and 113 deletions
+195 -113
...@@ -26,7 +26,6 @@ COPY pkg/ pkg/ ...@@ -26,7 +26,6 @@ COPY pkg/ pkg/
COPY docs/ docs/ COPY docs/ docs/
COPY vendor/ vendor/ COPY vendor/ vendor/
COPY Makefile Makefile COPY Makefile Makefile
COPY i18n/ i18n/
# Build # Build
RUN make build-cube RUN make build-cube
...@@ -36,6 +35,5 @@ RUN make build-cube ...@@ -36,6 +35,5 @@ RUN make build-cube
FROM alpine:3.13.4 FROM alpine:3.13.4
WORKDIR / WORKDIR /
COPY --from=builder /workspace/cube . COPY --from=builder /workspace/cube .
COPY --from=builder /workspace/i18n i18n
ENTRYPOINT ["/cube"] ENTRYPOINT ["/cube"]
...@@ -24,6 +24,7 @@ import ( ...@@ -24,6 +24,7 @@ import (
"github.com/kubecube-io/kubecube/pkg/clog" "github.com/kubecube-io/kubecube/pkg/clog"
"github.com/kubecube-io/kubecube/pkg/ctrlmgr" "github.com/kubecube-io/kubecube/pkg/ctrlmgr"
"github.com/kubecube-io/kubecube/pkg/cube" "github.com/kubecube-io/kubecube/pkg/cube"
"github.com/kubecube-io/kubecube/pkg/utils/international"
"github.com/urfave/cli/v2" "github.com/urfave/cli/v2"
utilerrors "k8s.io/apimachinery/pkg/util/errors" utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/sample-controller/pkg/signals" "k8s.io/sample-controller/pkg/signals"
...@@ -62,12 +63,18 @@ func run(s *options.CubeOptions, stop <-chan struct{}) { ...@@ -62,12 +63,18 @@ func run(s *options.CubeOptions, stop <-chan struct{}) {
// initialize cube client set // initialize cube client set
clients.InitCubeClientSetWithOpts(s.ClientMgrOpts) clients.InitCubeClientSetWithOpts(s.ClientMgrOpts)
c := cube.New(s.GenericCubeOpts) // initialize language managers
m, err := international.InitGi18nManagers()
if err != nil {
clog.Fatal("cube initialized gi18n managers failed: %v", err)
}
s.APIServerOpts.Gi18nManagers = m
c := cube.New(s.GenericCubeOpts)
c.IntegrateWith("cube-controller-manager", ctrlmgr.NewCtrlMgrWithOpts(s.CtrlMgrOpts)) c.IntegrateWith("cube-controller-manager", ctrlmgr.NewCtrlMgrWithOpts(s.CtrlMgrOpts))
c.IntegrateWith("cube-apiserver", apiserver.NewAPIServerWithOpts(s.APIServerOpts)) c.IntegrateWith("cube-apiserver", apiserver.NewAPIServerWithOpts(s.APIServerOpts))
err := c.Initialize() err = c.Initialize()
if err != nil { if err != nil {
clog.Fatal("cube initialized failed: %v", err) clog.Fatal("cube initialized failed: %v", err)
} }
......
apiVersion: v1
kind: ConfigMap
metadata:
name: kubecube-language-config
namespace: kubecube-system
data:
languages: "zh,en"
en.toml: |
# method
POST = "create"
PUT = "update"
DELETE = "delete"
# resourceType
deployments = "Deployment"
namespaces = "Namespace"
jobs = "Job"
cronjobs = "Cronjob"
persistentvolumeclaims = "Persistentvolumeclaim"
customresourcedefinitions = "Customresourcedefinition"
horizontalpodautoscalers = "Horizontalpodautoscaler"
networkpolicies = "Networkpolicie"
statefulsets = "Statefulset"
replicasets = "Replicaset"
pods = "Pod"
secrets = "Secret"
ingresses = "Ingress"
services = "Service"
configmaps = "Configmap"
user = "User"
key = "Key"
# description
createUser = "createUser"
updateUser = "updateUser"
deleteKey = "deleteKey"
zh.toml: |
# method
POST = "创建"
PUT = "更新"
DELETE = "删除"
# resourceType
deployments = "无状态负载"
namespaces = "namespace"
jobs = "任务"
cronjobs = "定时任务"
persistentvolumeclaims = "存储声明"
customresourcedefinitions = "自定义资源"
horizontalpodautoscalers = "自动伸缩(HPA)"
networkpolicies = "网络策略"
statefulsets = "有状态负载"
replicasets = "副本集"
pods = "副本"
secret = "secret"
ingresses = "ingress"
services = "service"
configmaps = "configmap"
user = "user"
key = "key"
# description
createUser = "创建用户"
updateUser = "更新用户"
deleteKey = "删除密钥"
\ No newline at end of file
...@@ -62,7 +62,7 @@ func registerCubeAPI(cfg *Config) http.Handler { ...@@ -62,7 +62,7 @@ func registerCubeAPI(cfg *Config) http.Handler {
apisOutsideMiddlewares(router) apisOutsideMiddlewares(router)
// set middlewares for apis below // set middlewares for apis below
middlewares.SetUpMiddlewares(router) middlewares.SetUpMiddlewares(router, cfg.Gi18nManagers)
// clusters apis handler // clusters apis handler
cluster.NewHandler().AddApisTo(router) cluster.NewHandler().AddApisTo(router)
......
...@@ -18,6 +18,7 @@ package apiserver ...@@ -18,6 +18,7 @@ package apiserver
import ( import (
"github.com/kubecube-io/kubecube/pkg/authentication" "github.com/kubecube-io/kubecube/pkg/authentication"
"github.com/kubecube-io/kubecube/pkg/utils/international"
) )
type Config struct { type Config struct {
...@@ -25,6 +26,7 @@ type Config struct { ...@@ -25,6 +26,7 @@ type Config struct {
authentication.LdapConfig authentication.LdapConfig
authentication.JwtConfig authentication.JwtConfig
authentication.GenericConfig authentication.GenericConfig
Gi18nManagers *international.Gi18nManagers
} }
type HttpConfig struct { type HttpConfig struct {
......
...@@ -118,6 +118,7 @@ func CreateKey(c *gin.Context) { ...@@ -118,6 +118,7 @@ func CreateKey(c *gin.Context) {
// @Router /api/v1/cube/key [delete] // @Router /api/v1/cube/key [delete]
func DeleteKey(c *gin.Context) { func DeleteKey(c *gin.Context) {
accessKey := c.Query("accessKey") accessKey := c.Query("accessKey")
c = audit.SetAuditInfo(c, audit.DeleteKey, accessKey)
// get user info // get user info
userInfo, err := token.GetUserFromReq(c.Request) userInfo, err := token.GetUserFromReq(c.Request)
if err != nil { if err != nil {
...@@ -147,7 +148,6 @@ func DeleteKey(c *gin.Context) { ...@@ -147,7 +148,6 @@ func DeleteKey(c *gin.Context) {
return return
} }
c = audit.SetAuditInfo(c, audit.DeleteKey, accessKey)
response.SuccessReturn(c, nil) response.SuccessReturn(c, nil)
} }
......
...@@ -29,7 +29,6 @@ import ( ...@@ -29,7 +29,6 @@ import (
"time" "time"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/gogf/gf/v2/i18n/gi18n"
"github.com/google/uuid" "github.com/google/uuid"
jsoniter "github.com/json-iterator/go" jsoniter "github.com/json-iterator/go"
...@@ -39,21 +38,23 @@ import ( ...@@ -39,21 +38,23 @@ import (
"github.com/kubecube-io/kubecube/pkg/utils/audit" "github.com/kubecube-io/kubecube/pkg/utils/audit"
"github.com/kubecube-io/kubecube/pkg/utils/constants" "github.com/kubecube-io/kubecube/pkg/utils/constants"
"github.com/kubecube-io/kubecube/pkg/utils/env" "github.com/kubecube-io/kubecube/pkg/utils/env"
"github.com/kubecube-io/kubecube/pkg/utils/international/en" "github.com/kubecube-io/kubecube/pkg/utils/international"
"github.com/kubecube-io/kubecube/pkg/utils/international/zh"
) )
var json = jsoniter.ConfigCompatibleWithStandardLibrary
const eventRespBody = "responseBody"
var ( var (
json = jsoniter.ConfigCompatibleWithStandardLibrary
auditWhiteList = map[string]string{ auditWhiteList = map[string]string{
constants.ApiPathRoot + "/audit": "POST", constants.ApiPathRoot + "/audit": "POST",
} }
auditSvc env.AuditSvcApi auditSvc env.AuditSvcApi
) )
const eventRespBody = "responseBody"
type Handler struct {
Managers *international.Gi18nManagers
}
func init() { func init() {
auditSvc = env.AuditSVC() auditSvc = env.AuditSVC()
} }
...@@ -69,7 +70,7 @@ func withinWhiteList(url *url.URL, method string, whiteList map[string]string) b ...@@ -69,7 +70,7 @@ func withinWhiteList(url *url.URL, method string, whiteList map[string]string) b
return false return false
} }
func Audit() gin.HandlerFunc { func (h *Handler) Audit() gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
w := &responseBodyWriter{body: &bytes.Buffer{}, ResponseWriter: c.Writer} w := &responseBodyWriter{body: &bytes.Buffer{}, ResponseWriter: c.Writer}
...@@ -107,11 +108,9 @@ func Audit() gin.HandlerFunc { ...@@ -107,11 +108,9 @@ func Audit() gin.HandlerFunc {
} }
// get event name and description // get event name and description
t := &gi18n.Manager{} t := h.Managers.GetInstants(env.AuditLanguage())
if env.AuditLanguage() == "zh" { if t == nil {
t = zh.GetZhManager() t = h.Managers.GetInstants("en")
} else {
t = en.GetEnManager()
} }
ctx := context.Background() ctx := context.Background()
eventName, isExist := c.Get(constants.EventName) eventName, isExist := c.Get(constants.EventName)
...@@ -123,7 +122,7 @@ func Audit() gin.HandlerFunc { ...@@ -123,7 +122,7 @@ func Audit() gin.HandlerFunc {
ResourceName: c.GetString(audit.EventResourceName), ResourceName: c.GetString(audit.EventResourceName),
}} }}
} else { } else {
e = handleProxyApi(ctx, c, *e, t) e = h.handleProxyApi(ctx, c, *e)
} }
go sendEvent(e) go sendEvent(e)
...@@ -171,7 +170,7 @@ func sendEvent(e *Event) { ...@@ -171,7 +170,7 @@ func sendEvent(e *Event) {
} }
// get event name and description // get event name and description
func handleProxyApi(ctx context.Context, c *gin.Context, e Event, t *gi18n.Manager) *Event { func (h *Handler) handleProxyApi(ctx context.Context, c *gin.Context, e Event) *Event {
var ( var (
objectType string objectType string
objectName string objectName string
...@@ -214,8 +213,12 @@ func handleProxyApi(ctx context.Context, c *gin.Context, e Event, t *gi18n.Manag ...@@ -214,8 +213,12 @@ func handleProxyApi(ctx context.Context, c *gin.Context, e Event, t *gi18n.Manag
} }
method := c.Request.Method method := c.Request.Method
enT := en.GetEnManager() enT := h.Managers.GetInstants("en")
e.EventName = enT.Translate(ctx, method) + strings.Title(objectType[:len(objectType)-1]) e.EventName = enT.Translate(ctx, method) + strings.Title(objectType[:len(objectType)-1])
t := h.Managers.GetInstants(env.AuditLanguage())
if t == nil {
t = h.Managers.GetInstants("en")
}
e.Description = t.Translate(ctx, method) + t.Translate(ctx, objectType) e.Description = t.Translate(ctx, method) + t.Translate(ctx, objectType)
e.ResourceReports = []Resource{{ e.ResourceReports = []Resource{{
ResourceType: objectType[:len(objectType)-1], ResourceType: objectType[:len(objectType)-1],
......
...@@ -18,6 +18,7 @@ package audit ...@@ -18,6 +18,7 @@ package audit
import ( import (
"bytes" "bytes"
"context"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
...@@ -26,10 +27,13 @@ import ( ...@@ -26,10 +27,13 @@ import (
"time" "time"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/gogf/gf/v2/i18n/gi18n"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/kubecube-io/kubecube/pkg/utils/constants" "github.com/kubecube-io/kubecube/pkg/utils/international"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/kubecube-io/kubecube/pkg/utils/constants"
) )
type header struct { type header struct {
...@@ -69,35 +73,37 @@ func TestSendEvent(t *testing.T) { ...@@ -69,35 +73,37 @@ func TestSendEvent(t *testing.T) {
func TestGetEventName(t *testing.T) { func TestGetEventName(t *testing.T) {
e := &Event{} e := &Event{}
router := gin.New() ctx := context.Background()
enInstance := gi18n.Instance()
// check get method enInstance.SetPath("/Users/zhaojiahui/code/go/kubecube/KubeCube/i18n")
router.GET("/api/v1/cube/proxy/clusters/:cluster/apis/apps/v1/namespaces/:namespace/statefulsets/:name", func(c *gin.Context) { enInstance.SetLanguage("en")
e = handleProxyApi(c, *e) h := Handler{
return Managers: &international.Gi18nManagers{
}) Managers: map[string]*gi18n.Manager{
_ = performRequest(router, http.MethodGet, "/api/v1/cube/proxy/clusters/pivot-cluster/apis/apps/v1/namespaces/dev/statefulsets/stsA", []byte("")) "en": enInstance,
if e.EventName != "[KubeCube] query statefulsets" { },
t.Fail() },
} }
// check post method // check post method
router.POST("/api/v1/cube/proxy/clusters/:cluster/api/v1/namespaces/:namespace/services", func(c *gin.Context) { router1 := gin.New()
e = handleProxyApi(c, *e) router1.POST("/api/v1/cube/proxy/clusters/:cluster/api/v1/namespaces/:namespace/services", func(c *gin.Context) {
e = h.handleProxyApi(ctx, c, *e)
return return
}) })
_ = performRequest(router, http.MethodPost, "/api/v1/cube/proxy/clusters/pivot-cluster/api/v1/namespaces/dev/services", []byte("")) _ = performRequest(router1, http.MethodPost, "/api/v1/cube/proxy/clusters/pivot-cluster/api/v1/namespaces/dev/services", []byte(""))
if e.EventName != "[KubeCube] create services" { if e.EventName != "createService" {
t.Fail() t.Fail()
} }
// check put method // check put method
router.PUT("/api/v1/cube/proxy/clusters/:cluster/api/v1/namespaces/:namespace/secrets/:name", func(c *gin.Context) { router2 := gin.New()
e = handleProxyApi(c, *e) router2.PUT("/api/v1/cube/proxy/clusters/:cluster/api/v1/namespaces/:namespace/secrets/:name", func(c *gin.Context) {
e = h.handleProxyApi(ctx, c, *e)
return return
}) })
_ = performRequest(router, http.MethodPut, "/api/v1/cube/proxy/clusters/pivot-cluster/api/v1/namespaces/dev/secrets/secretA", []byte("")) _ = performRequest(router2, http.MethodPut, "/api/v1/cube/proxy/clusters/pivot-cluster/api/v1/namespaces/dev/secrets/secretA", []byte(""))
if e.EventName != "[KubeCube] update secrets" { if e.EventName != "updateSecret" {
t.Fail() t.Fail()
} }
} }
......
...@@ -23,16 +23,20 @@ import ( ...@@ -23,16 +23,20 @@ import (
"github.com/kubecube-io/kubecube/pkg/apiserver/middlewares/precheck" "github.com/kubecube-io/kubecube/pkg/apiserver/middlewares/precheck"
"github.com/kubecube-io/kubecube/pkg/apiserver/middlewares/recovery" "github.com/kubecube-io/kubecube/pkg/apiserver/middlewares/recovery"
"github.com/kubecube-io/kubecube/pkg/utils/env" "github.com/kubecube-io/kubecube/pkg/utils/env"
"github.com/kubecube-io/kubecube/pkg/utils/international"
) )
func SetUpMiddlewares(router *gin.Engine) { func SetUpMiddlewares(router *gin.Engine, managers *international.Gi18nManagers) {
if router == nil { if router == nil {
return return
} }
router.Use(precheck.PreCheck()) router.Use(precheck.PreCheck())
router.Use(auth.Auth()) router.Use(auth.Auth())
if env.AuditIsEnable() { if env.AuditIsEnable() {
router.Use(audit.Audit()) h := audit.Handler{
Managers: managers,
}
router.Use(h.Audit())
} }
router.Use(recovery.Recovery()) router.Use(recovery.Recovery())
} }
/*
Copyright 2021 KubeCube 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 en
import (
"github.com/gogf/gf/v2/i18n/gi18n"
)
var enManager *gi18n.Manager
func GetEnManager() *gi18n.Manager {
return enManager
}
func InitEnManager() {
t := gi18n.New()
t.SetLanguage("en")
enManager = t
}
...@@ -16,11 +16,72 @@ limitations under the License. ...@@ -16,11 +16,72 @@ limitations under the License.
package international package international
import ( import (
"github.com/kubecube-io/kubecube/pkg/utils/international/en" "context"
"github.com/kubecube-io/kubecube/pkg/utils/international/zh" "errors"
"strings"
"sync"
"github.com/gogf/gf/v2/i18n/gi18n"
"github.com/kubecube-io/kubecube/pkg/clients"
"github.com/kubecube-io/kubecube/pkg/clog"
"github.com/kubecube-io/kubecube/pkg/utils/constants"
v1 "k8s.io/api/core/v1"
ioerrors "k8s.io/apimachinery/pkg/api/errors"
"sigs.k8s.io/controller-runtime/pkg/client"
) )
func init() { var defaultOptions = []string{"zh,en"}
en.InitEnManager()
zh.InitEnManager() type Gi18nManagers struct {
Managers map[string]*gi18n.Manager
lock sync.RWMutex
}
type Config struct {
Languages map[string]string
}
func InitGi18nManagers() (*Gi18nManagers, error) {
// read kubecube-language-config
kClient := clients.Interface().Kubernetes(constants.PivotCluster).Direct()
if kClient == nil {
return nil, errors.New("get pivot cluster client is nil")
}
cm := &v1.ConfigMap{}
err := kClient.Get(context.Background(), client.ObjectKey{Name: "kubecube-language-config", Namespace: constants.CubeNamespace}, cm)
if err != nil && !ioerrors.IsNotFound(err) {
clog.Error("get configmap kubecube-language-config from K8s err: %v", err)
return nil, err
}
var languages []string
if ioerrors.IsNotFound(err) {
languages = defaultOptions
} else {
languages = strings.Split(cm.Data["languages"], ",")
}
m := &Gi18nManagers{
Managers: make(map[string]*gi18n.Manager),
}
m.lock.Lock()
defer m.lock.Unlock()
for _, l := range languages {
inst := gi18n.Instance(l)
inst.SetLanguage(l)
m.Managers[l] = inst
}
return m, nil
}
func (g *Gi18nManagers) GetInstants(language string) *gi18n.Manager {
g.lock.RLock()
defer g.lock.RUnlock()
return g.Managers[language]
}
func (g *Gi18nManagers) Translate(ctx context.Context, language string, content string) string {
m := g.Managers[language]
g.lock.RLock()
defer g.lock.RUnlock()
return m.Translate(ctx, content)
} }
/*
Copyright 2021 KubeCube 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 zh
import (
"github.com/gogf/gf/v2/i18n/gi18n"
)
var zhManager *gi18n.Manager
func GetZhManager() *gi18n.Manager {
return zhManager
}
func InitEnManager() {
t := gi18n.New()
t.SetLanguage("zh")
zhManager = t
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment