diff --git a/cmd/bridge/config.go b/cmd/bridge/config.go index 424a631784d5..6ac9ef801be0 100644 --- a/cmd/bridge/config.go +++ b/cmd/bridge/config.go @@ -55,6 +55,8 @@ type Auth struct { type Customization struct { Branding string `yaml:"branding"` DocumentationBaseURL string `yaml:"documentationBaseURL"` + CustomProductName string `yaml:"customProductName"` + CustomLogoFile string `yaml:"customLogoFile"` } // SetFlagsFromConfig sets flag values based on a YAML config file. @@ -175,4 +177,12 @@ func addCustomization(fs *flag.FlagSet, customization *Customization) { if customization.DocumentationBaseURL != "" { fs.Set("documentation-base-url", customization.DocumentationBaseURL) } + + if customization.CustomProductName != "" { + fs.Set("custom-product-name", customization.CustomProductName) + } + + if customization.CustomLogoFile != "" { + fs.Set("custom-logo-file", customization.CustomLogoFile) + } } diff --git a/cmd/bridge/main.go b/cmd/bridge/main.go index a9e0f3c6c6c4..3dbe41f0d734 100644 --- a/cmd/bridge/main.go +++ b/cmd/bridge/main.go @@ -84,6 +84,8 @@ func main() { fDexAPIHost := fs.String("dex-api-host", "", "Target host and port of the Dex API service.") fBranding := fs.String("branding", "okd", "Console branding for the masthead logo and title. One of okd, openshift, ocp, online, dedicated, or azure. Defaults to okd.") + fCustomProductName := fs.String("custom-product-name", "", "Custom product name for console branding.") + fCustomLogoFile := fs.String("custom-logo-file", "", "Custom product image for console branding.") fDocumentationBaseURL := fs.String("documentation-base-url", "", "The base URL for documentation links.") fGoogleTagManagerID := fs.String("google-tag-manager-id", "", "Google Tag Manager ID. External analytics are disabled if this is not set.") @@ -152,6 +154,12 @@ func main() { flagFatalf("branding", "value must be one of okd, openshift, ocp, online, dedicated, or azure") } + if *fCustomLogoFile != "" { + if _, err := os.Stat(*fCustomLogoFile); err != nil { + log.Fatalf("could not read logo file: %v", err) + } + } + srv := &server.Server{ PublicDir: *fPublicDir, TectonicVersion: *fTectonicVersion, @@ -159,6 +167,8 @@ func main() { LogoutRedirect: logoutRedirect, TectonicCACertFile: caCertFilePath, Branding: branding, + CustomProductName: *fCustomProductName, + CustomLogoFile: *fCustomLogoFile, DocumentationBaseURL: documentationBaseURL, GoogleTagManagerID: *fGoogleTagManagerID, LoadTestFactor: *fLoadTestFactor, diff --git a/frontend/public/components/about-modal.tsx b/frontend/public/components/about-modal.tsx index c6147dd971d8..0c0e8fe22965 100644 --- a/frontend/public/components/about-modal.tsx +++ b/frontend/public/components/about-modal.tsx @@ -16,6 +16,7 @@ const AboutModal_: React.FC = ({isOpen, closeAboutModal, cluste }, []); const details = getBrandingDetails(); + const customBranding = (window as any).SERVER_FLAGS.customLogoURL || (window as any).SERVER_FLAGS.customProductName; return ( = ({isOpen, closeAboutModal, cluste brandImageSrc={details.logoImg} brandImageAlt={details.productName} > -

OpenShift is Red Hat's container application platform that allows developers to quickly develop, host, - and scale applications in a cloud environment.

+ {!customBranding &&

OpenShift is Red Hat's container application platform that allows developers to quickly develop, host, + and scale applications in a cloud environment.

}
diff --git a/frontend/public/components/masthead.jsx b/frontend/public/components/masthead.jsx index b729af601476..65282c4f4c2c 100644 --- a/frontend/public/components/masthead.jsx +++ b/frontend/public/components/masthead.jsx @@ -39,6 +39,12 @@ export const getBrandingDetails = () => { logoImg = okdLogoImg; productName = 'OKD'; } + if (window.SERVER_FLAGS.customLogoURL) { + logoImg = window.SERVER_FLAGS.customLogoURL; + } + if (window.SERVER_FLAGS.customProductName) { + productName = window.SERVER_FLAGS.customProductName; + } return { logoImg, productName }; }; diff --git a/frontend/public/index.html b/frontend/public/index.html index 758d93580cba..abd2b6d21fa5 100644 --- a/frontend/public/index.html +++ b/frontend/public/index.html @@ -5,43 +5,48 @@ - [[ if eq .Branding "okd" ]] - OKD - - [[ end ]] - [[ if eq .Branding "openshift" ]] - Red Hat OpenShift - - [[ end ]] - [[ if eq .Branding "ocp" ]] - Red Hat OpenShift Container Platform - - [[ end ]] - [[ if eq .Branding "online" ]] - Red Hat OpenShift Online - - [[ end ]] - [[ if eq .Branding "dedicated" ]] - Red Hat OpenShift Dedicated - - [[ end ]] - [[ if eq .Branding "azure" ]] - Azure Red Hat OpenShift - - [[ end ]] - - [[ if eq .Branding "okd" ]] - - - - - + [[ if .CustomProductName ]] + [[ .CustomProductName ]] + [[ else ]] - - - - - + [[ if eq .Branding "okd" ]] + OKD + + [[ end ]] + [[ if eq .Branding "openshift" ]] + Red Hat OpenShift + + [[ end ]] + [[ if eq .Branding "ocp" ]] + Red Hat OpenShift Container Platform + + [[ end ]] + [[ if eq .Branding "online" ]] + Red Hat OpenShift Online + + [[ end ]] + [[ if eq .Branding "dedicated" ]] + Red Hat OpenShift Dedicated + + [[ end ]] + [[ if eq .Branding "azure" ]] + Azure Red Hat OpenShift + + [[ end ]] + + [[ if eq .Branding "okd" ]] + + + + + + [[ else ]] + + + + + + [[ end ]] [[ end ]] diff --git a/frontend/public/style/_overrides.scss b/frontend/public/style/_overrides.scss index 55db94db7e9b..da48389cc58f 100644 --- a/frontend/public/style/_overrides.scss +++ b/frontend/public/style/_overrides.scss @@ -264,11 +264,12 @@ tags-input .autocomplete .suggestion-item em { .pf-c-about-modal-box { &__brand { + align-items: flex-start; // so logos don't stretch vertically min-width: 220px; } &__brand-image { - height: auto !important; + height: auto !important; // allow logo to be taller } } diff --git a/server/server.go b/server/server.go index 9163d3bbd390..c0102d817101 100644 --- a/server/server.go +++ b/server/server.go @@ -32,6 +32,7 @@ const ( prometheusProxyEndpoint = "/api/prometheus" prometheusTenancyProxyEndpoint = "/api/prometheus-tenancy" alertManagerProxyEndpoint = "/api/alertmanager" + customLogoEndpoint = "/custom-logo" ) var ( @@ -54,6 +55,8 @@ type jsGlobals struct { PrometheusTenancyBaseURL string `json:"prometheusTenancyBaseURL"` AlertManagerBaseURL string `json:"alertManagerBaseURL"` Branding string `json:"branding"` + CustomProductName string `json:"customProductName"` + CustomLogoURL string `json:"customLogoURL"` DocumentationBaseURL string `json:"documentationBaseURL"` GoogleTagManagerID string `json:"googleTagManagerID"` LoadTestFactor int `json:"loadTestFactor"` @@ -72,6 +75,8 @@ type Server struct { KubeAPIServerURL string DocumentationBaseURL *url.URL Branding string + CustomProductName string + CustomLogoFile string GoogleTagManagerID string LoadTestFactor int DexClient api.DexClient @@ -108,13 +113,15 @@ func (s *Server) HTTPHandler() http.Handler { fn := func(loginInfo auth.LoginJSON, successURL string, w http.ResponseWriter) { jsg := struct { - auth.LoginJSON `json:",inline"` - LoginSuccessURL string `json:"loginSuccessURL"` - Branding string `json:"branding"` + auth.LoginJSON `json:",inline"` + LoginSuccessURL string `json:"loginSuccessURL"` + Branding string `json:"branding"` + CustomProductName string `json:"customProductName"` }{ - LoginJSON: loginInfo, - LoginSuccessURL: successURL, - Branding: s.Branding, + LoginJSON: loginInfo, + LoginSuccessURL: successURL, + Branding: s.Branding, + CustomProductName: s.CustomProductName, } tpl := template.New(tokenizerPageTemplateName) @@ -162,6 +169,12 @@ func (s *Server) HTTPHandler() http.Handler { staticHandler := http.StripPrefix(proxy.SingleJoiningSlash(s.BaseURL.Path, "/static/"), http.FileServer(http.Dir(s.PublicDir))) handle("/static/", gzipHandler(securityHeadersMiddleware(staticHandler))) + if s.CustomLogoFile != "" { + handleFunc(customLogoEndpoint, func(w http.ResponseWriter, r *http.Request) { + http.ServeFile(w, r, s.CustomLogoFile) + }) + } + // Scope of Service Worker needs to be higher than the requests it is intercepting (https://stackoverflow.com/a/35780776/6909941) handleFunc("/load-test.sw.js", func(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, path.Join(s.PublicDir, "load-test.sw.js")) @@ -254,6 +267,7 @@ func (s *Server) indexHandler(w http.ResponseWriter, r *http.Request) { LogoutRedirect: s.LogoutRedirect.String(), KubeAPIServerURL: s.KubeAPIServerURL, Branding: s.Branding, + CustomProductName: s.CustomProductName, DocumentationBaseURL: s.DocumentationBaseURL.String(), GoogleTagManagerID: s.GoogleTagManagerID, LoadTestFactor: s.LoadTestFactor, @@ -276,6 +290,10 @@ func (s *Server) indexHandler(w http.ResponseWriter, r *http.Request) { s.Auther.SetCSRFCookie(s.BaseURL.Path, &w) } + if s.CustomLogoFile != "" { + jsg.CustomLogoURL = proxy.SingleJoiningSlash(s.BaseURL.Path, customLogoEndpoint) + } + tpl := template.New(indexPageTemplateName) tpl.Delims("[[", "]]") tpls, err := tpl.ParseFiles(path.Join(s.PublicDir, indexPageTemplateName))