Skip to content

Commit

Permalink
CONSOLE-2425: Support localization of dynamic plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
jhadvig committed Jul 1, 2021
1 parent 598109b commit 60fbab5
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 22 deletions.
1 change: 1 addition & 0 deletions Dockerfile.plugins.demo
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ RUN yarn install && \
FROM node:10

COPY --from=build /src/console/frontend/dynamic-demo-plugin/dist /opt/console-demo-plugin/static
COPY --from=build /src/console/frontend/dynamic-demo-plugin/locales /opt/console-demo-plugin/static/locales
COPY --from=build /src/console/frontend/dynamic-demo-plugin/node_modules /opt/console-demo-plugin/node_modules
COPY --from=build /src/console/frontend/dynamic-demo-plugin/http-server.sh /opt/console-demo-plugin/http-server.sh

Expand Down
1 change: 1 addition & 0 deletions Dockerfile.plugins.demo2
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
FROM node:10

COPY ./frontend/dynamic-demo-plugin/dist /opt/console-demo-plugin/static
COPY ./frontend/dynamic-demo-plugin/locales /opt/console-demo-plugin/static/locales
COPY ./frontend/dynamic-demo-plugin/node_modules /opt/console-demo-plugin/node_modules
COPY ./frontend/dynamic-demo-plugin/http-server.sh /opt/console-demo-plugin/http-server.sh

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"Subject": "Subject"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"Subject": "サブジェクト"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"Subject": "제목"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"Subject": "主题"
}
2 changes: 1 addition & 1 deletion frontend/public/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ i18n
// for all options read: https://www.i18next.com/overview/configuration-options
.init({
backend: {
loadPath: 'static/locales/{{lng}}/{{ns}}.json',
loadPath: '/locales/resource.json?lng={{lng}}&ns={{ns}}',
},
lng: localStorage.getItem('bridge/language'),
fallbackLng: 'en',
Expand Down
49 changes: 45 additions & 4 deletions pkg/plugins/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,73 @@ import (
type PluginsHandler struct {
Client *http.Client
PluginsEndpointMap map[string]string
PublicDir string
}

func NewPluginsHandler(client *http.Client, token string, pluginsEndpointMap map[string]string) *PluginsHandler {
func NewPluginsHandler(client *http.Client, pluginsEndpointMap map[string]string, publicDir string) *PluginsHandler {
return &PluginsHandler{
Client: client,
PluginsEndpointMap: pluginsEndpointMap,
PublicDir: publicDir,
}
}

func (p *PluginsHandler) HandlePluginLocales(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
w.Header().Set("Allow", "GET")
serverutils.SendResponse(w, http.StatusMethodNotAllowed, serverutils.ApiError{Err: "Method unsupported, the only supported methods is GET"})
return
}

query := r.URL.Query()
lang := query.Get("lng")
// In case of static plugin the localization namespace should contain name of the json file that contains the localization strings,
// since various static plugins have different names for the localization file.
// eg. namespace query for the local-storage-operator-plugin locales - '&ns=lso-plugin.json'
// In case of the dynamic plugin the localization namespace should contain name of the plugin prefixed with 'plugin__' prefix.
// No file extension is needed since for the dynamic plugins we will fetch file from the plugin pod, based on the namespace.
// eg. 'plugin__helm-plugin' will fetch `helm-plugin.json`
namespace := query.Get("ns")
if !strings.HasPrefix(namespace, "plugin__") {
http.ServeFile(w, r, path.Join(p.PublicDir, "locales", lang, namespace))
return
}
// in case of dynamic-plugin we need to trim the "plugin__" prefix.
pluginName := strings.TrimPrefix(namespace, "plugin__")

pluginServiceRequestURL, err := p.getServiceRequestURL(pluginName)
if err != nil {
errMsg := err.Error()
klog.Error(errMsg)
serverutils.SendResponse(w, http.StatusBadGateway, serverutils.ApiError{Err: errMsg})
return
}
pluginServiceRequestURL.Path = path.Join(pluginServiceRequestURL.Path, "locales", lang, fmt.Sprintf("%s.json", namespace))

p.proxyPluginRequest(pluginServiceRequestURL, pluginName, w, r)
}

func (p *PluginsHandler) HandlePlugins(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
w.Header().Set("Allow", "GET")
serverutils.SendResponse(w, http.StatusMethodNotAllowed, serverutils.ApiError{Err: "Method unsupported, the only supported methods is GET"})
return
}
pluginName, pluginAssetPath := parsePluginNameAndAssetPath(r.URL.Path)
serviceRequestURL, err := p.getServiceRequestURL(pluginName)
pluginServiceRequestURL, err := p.getServiceRequestURL(pluginName)
if err != nil {
errMsg := err.Error()
klog.Error(errMsg)
serverutils.SendResponse(w, http.StatusBadGateway, serverutils.ApiError{Err: errMsg})
return
}
serviceRequestURL.Path = path.Join(serviceRequestURL.Path, pluginAssetPath)
pluginServiceRequestURL.Path = path.Join(pluginServiceRequestURL.Path, pluginAssetPath)

p.proxyPluginRequest(pluginServiceRequestURL, pluginName, w, r)
}

resp, err := p.Client.Get(serviceRequestURL.String())
func (p *PluginsHandler) proxyPluginRequest(requestURL *url.URL, pluginName string, w http.ResponseWriter, r *http.Request) {
resp, err := p.Client.Get(requestURL.String())
if err != nil {
errMsg := fmt.Sprintf("GET request for %q plugin failed: %v", pluginName, err)
klog.Error(errMsg)
Expand Down
36 changes: 19 additions & 17 deletions pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ const (
devfileEndpoint = "/api/devfile/"
devfileSamplesEndpoint = "/api/devfile/samples/"
pluginsEndpoint = "/api/plugins/"
localesEndpoint = "/locales/resource.json"

sha256Prefix = "sha256~"
)
Expand Down Expand Up @@ -422,24 +423,25 @@ func (s *Server) HTTPHandler() http.Handler {

helmHandlers := helmhandlerspkg.New(s.K8sProxyConfig.Endpoint.String(), s.K8sClient.Transport, s)

// No need to create plugins handler if no plugin is enabled.
if len(s.EnabledConsolePlugins) > 0 {
pluginsHandler := plugins.NewPluginsHandler(
&http.Client{
Timeout: 10 * time.Second,
Transport: &http.Transport{TLSClientConfig: s.PluginsProxyTLSConfig},
},
s.ServiceAccountToken,
s.EnabledConsolePlugins,
)
pluginsHandler := plugins.NewPluginsHandler(
&http.Client{
Timeout: 10 * time.Second,
Transport: &http.Transport{TLSClientConfig: s.PluginsProxyTLSConfig},
},
s.EnabledConsolePlugins,
s.PublicDir,
)

handle(pluginsEndpoint, http.StripPrefix(
proxy.SingleJoiningSlash(s.BaseURL.Path, pluginsEndpoint),
authHandler(func(w http.ResponseWriter, r *http.Request) {
pluginsHandler.HandlePlugins(w, r)
}),
))
}
handle(pluginsEndpoint, http.StripPrefix(
proxy.SingleJoiningSlash(s.BaseURL.Path, pluginsEndpoint),
authHandler(func(w http.ResponseWriter, r *http.Request) {
pluginsHandler.HandlePlugins(w, r)
}),
))

handleFunc(localesEndpoint, func(w http.ResponseWriter, r *http.Request) {
pluginsHandler.HandlePluginLocales(w, r)
})

// Helm Endpoints
handle("/api/helm/template", authHandlerWithUser(helmHandlers.HandleHelmRenderManifests))
Expand Down

0 comments on commit 60fbab5

Please sign in to comment.