From dde10209e36e8e989ab5a8b8e5aa616e95562827 Mon Sep 17 00:00:00 2001 From: Martin Marosi Date: Mon, 4 Nov 2024 13:16:20 +0100 Subject: [PATCH] Enable consuming generating fed-modules.json from FEO env variables --- .env.example | 6 ++ .gitignore | 1 + Dockerfile | 3 + Makefile | 2 +- README.md | 2 +- deploy/clowdapp.yml | 33 +++++++- main.go | 1 + rest/util/createChromeConfiguration.go | 105 +++++++++++++++++++++++++ 8 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 rest/util/createChromeConfiguration.go diff --git a/.env.example b/.env.example index adbabe34..cc466e6c 100644 --- a/.env.example +++ b/.env.example @@ -13,3 +13,9 @@ KAFKA_JMX_PORT=9999 KAFKA_CLIENT_LISTEN_PORT=9092 KAFKA_CLIENT_LISTEN_PORT_2=29092 +# Values to generate chrome UI configuration +FEO_SEARCH_INDEX=[{"id":"landing-env-boot-landing","href":"/","title":"Landing","description":"Landing page description","alt_title":["HCC Home page","Home"]},{"id":"landing-env-boot-landing-widgets","href":"/widgets","title":"Widget fantastic","description":"Widget"}] +FEO_FED_MODULES={"landing":{"manifestLocation":"/apps/landing/fed-mods.json","modules":[{"id":"landing","module":"./RootApp","routes":[{"pathname":"/","exact":true}]}],"fullProfile":false}} +FEO_SERVICE_TILES=[{"id":"automation","title":"Automation","groups":[{"id":"ansible","title":"Ansible","tiles":[{"section":"automation","group":"ansible","id":"ansible-link","href":"/ansible/foo","title":"Ansible FOO","description":"Ansible FOO description thing","icon":"AnsibleIcon"}]},{"id":"rhel","title":"Red Hat Enterprise Linux","tiles":[]}]},{"id":"iam","title":"Identity and Access Management","groups":[{"id":"iam","title":"IAM","tiles":[{"section":"iam","group":"iam","id":"iam-link","href":"/iam","title":"IAM FOO","description":"Some Iam thing","icon":"IAMIcon"}]}]}] +FEO_WIDGET_REGISTRY=[{"scope":"landing","module":"./RandomWidget","config":{"icon":"CogIcon","title":"Random Widget","headerLink":{"title":"","href":""}},"defaults":{"sm":{"w":1,"h":1,"maxH":1,"minH":1},"md":{"w":1,"h":1,"maxH":1,"minH":1},"lg":{"w":1,"h":1,"maxH":1,"minH":1},"xl":{"w":1,"h":1,"maxH":1,"minH":1}}}] + diff --git a/.gitignore b/.gitignore index 121a36c0..36e9cd7b 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ static/**/links-storage.json static/**/services-generated.json *-services.db static/**/search-index.json +static/*-generated.json .tekton/chrome-service-pull-request.bak.yaml .tekton/chrome-service-push.bak.yaml diff --git a/Dockerfile b/Dockerfile index a4a95225..21fb7c17 100644 --- a/Dockerfile +++ b/Dockerfile @@ -31,6 +31,9 @@ FROM registry.access.redhat.com/ubi9-minimal:latest RUN mkdir -p /app RUN chgrp -R 0 /app && \ chmod -R g=u /app +RUN mkdir -p /static +RUN chgrp -R 0 /static && \ + chmod -R g=u /static COPY --from=builder /go/bin/chrome-service-backend /app/chrome-service-backend COPY --from=builder /go/bin/chrome-migrate /usr/bin COPY --from=builder /go/bin/chrome-search-index /usr/bin diff --git a/Makefile b/Makefile index bbfe6cd2..542ddd4c 100644 --- a/Makefile +++ b/Makefile @@ -31,7 +31,7 @@ env: cp .env.example .env migrate: - go run cmd/migrate/migrate.go + go run cmd/migrate/migrate.go database: podman-compose up diff --git a/README.md b/README.md index 52c5eb7b..a1d75c4e 100644 --- a/README.md +++ b/README.md @@ -51,4 +51,4 @@ eyJpZGVudGl0eSI6eyJ1c2VyIjp7InVzZXJfaWQiOiIxMiJ9fX0= `make generate-search-index` will generate search index file -`make parse-services` will generate the `services-generated.json` file +`make parse-services` will generate the `services-generated.json` file diff --git a/deploy/clowdapp.yml b/deploy/clowdapp.yml index 936422bc..5c715956 100644 --- a/deploy/clowdapp.yml +++ b/deploy/clowdapp.yml @@ -41,7 +41,6 @@ objects: - bash - -c - chrome-search-index - inheritEnv: true livenessProbe: failureThreshold: 3 httpGet: @@ -63,6 +62,31 @@ objects: successThreshold: 1 timeoutSeconds: 120 env: + - name: FEO_SEARCH_INDEX + valueFrom: + configMapKeyRef: + key: search-index.json + name: ${CHROME_CONFIG_MAP} + # because keys in configmap can be empty + optional: true + - name: FEO_FED_MODULES + valueFrom: + configMapKeyRef: + key: fed-modules.json + name: ${CHROME_CONFIG_MAP} + optional: true + - name: FEO_SERVICE_TILES + valueFrom: + configMapKeyRef: + key: service-tiles.json + name: ${CHROME_CONFIG_MAP} + optional: true + - name: FEO_WIDGET_REGISTRY + valueFrom: + configMapKeyRef: + key: widget-registry.json + name: ${CHROME_CONFIG_MAP} + optional: true - name: CLOWDER_ENABLED value: ${CLOWDER_ENABLED} - name: LOG_LEVEL @@ -188,5 +212,12 @@ parameters: - description: ClowdEnv Name name: ENV_NAME required: true +- description: Chrome config map name + name: CHROME_CONFIG_MAP + value: feo-context-cfg - name: LINT_ANNOTATION value: 'ignore-check.kube-linter.io/minimum-three-replicas' +- description: Frontend environment + name: FRONTEND_ENVIRONMENT + # fallback to stage environment if not set + value: stage diff --git a/main.go b/main.go index da487d02..f033a610 100644 --- a/main.go +++ b/main.go @@ -30,6 +30,7 @@ func init() { flag.Parse() database.Init() util.InitUserIdentitiesCache() + util.CreateChromeConfiguration() } func main() { diff --git a/rest/util/createChromeConfiguration.go b/rest/util/createChromeConfiguration.go new file mode 100644 index 00000000..c45aeadd --- /dev/null +++ b/rest/util/createChromeConfiguration.go @@ -0,0 +1,105 @@ +package util + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + + "github.com/joho/godotenv" + "github.com/sirupsen/logrus" +) + +const ( + fedModulesPath = "static/fed-modules-generated.json" + staticFedModulesPath = "static/stable/%s/modules/fed-modules.json" +) + +func getLegacyConfigFile(path string, env string) ([]byte, error) { + // read the file + file, err := os.ReadFile(fmt.Sprintf(path, env)) + if err != nil { + return nil, err + } + return file, nil +} + +func parseFedModules(fedModulesConfig string, env string) ([]byte, error) { + + fm := make(map[string]interface{}) + lfm := make(map[string]interface{}) + if fedModulesConfig == "" { + logrus.Warn("FEO_FED_MODULES is not set, using empty configuration") + } else { + err := json.Unmarshal([]byte(fedModulesConfig), &fm) + // do the thing + if err != nil { + return nil, err + } + } + + // read legacy configFile + legacyFedModulesFile, err := getLegacyConfigFile(staticFedModulesPath, env) + if err != nil { + return nil, err + } + + err = json.Unmarshal(legacyFedModulesFile, &lfm) + if err != nil { + return nil, err + } + + for key, value := range fm { + // We will have to wrap this assignment to some kind of if statement to make sure we don't overwrite the values if the frontend resource is not ready to be used + // merge legacy and generated values + lfm[key] = value + } + + // parse back to string so it can be written to a file + res, err := json.MarshalIndent(lfm, "", " ") + return res, err +} + +func writeConfigFile(config []byte, path string) error { + cwd, err := filepath.Abs(".") + if err != nil { + return err + } + file := fmt.Sprintf("%s/%s", cwd, path) + logrus.Infof("Writing configuration to %s", file) + err = os.WriteFile(file, config, 0644) + return err +} + +func CreateChromeConfiguration() { + err := LoadEnv() + if err != nil { + godotenv.Load() + } + + // environment type + // Can be one if prod, stage, itless, anything else will cause exception + env := os.Getenv("FRONTEND_ENVIRONMENT") + if env == "" { + logrus.Warn("FRONTEND_ENVIRONMENT is not set, using 'stage'") + env = "stage" + } else if env != "prod" && env != "stage" && env != "itless" { + panic(fmt.Sprintf("Invalid FRONTEND_ENVIRONMENT value: %s", env)) + } + + fedModulesVar := os.Getenv("FEO_FED_MODULES") + // searchVar := os.Getenv("FEO_SEARCH_INDEX") + // serviceTilesVar := os.Getenv("FEO_SERVICE_TILES") + // widgetRegistryVar := os.Getenv("FEO_WIDGET_REGISTRY") + + fedModules, err := parseFedModules(fedModulesVar, env) + if err != nil { + panic(fmt.Sprintf("Error parsing FEO_FED_MODULES: %v", err)) + } + + fmt.Println("Writing fed-modules.json") + err = writeConfigFile(fedModules, fedModulesPath) + if err != nil { + panic(err) + } +}