From f9343a2585e05ebb10fa0c34f52fe06b2e118445 Mon Sep 17 00:00:00 2001 From: Lee Warrick Date: Mon, 8 Apr 2024 13:59:12 -0400 Subject: [PATCH 01/20] implement local nginx cache strategy in docker compose with system roles purge example --- docker-compose.yml | 15 +++++- nginx/Dockerfile | 79 ++++++++++++++++++++++++++++++++ nginx/cachepurge/source | 1 + nginx/nginx.conf | 56 ++++++++++++++++++++++ pkg/cedar/core/client.go | 5 +- pkg/cedar/core/role.go | 22 +++++++++ pkg/cedar/core/system_summary.go | 44 +++++++++++++----- pkg/server/routes.go | 3 +- 8 files changed, 209 insertions(+), 16 deletions(-) create mode 100644 nginx/Dockerfile create mode 100644 nginx/cachepurge/source create mode 100644 nginx/nginx.conf diff --git a/docker-compose.yml b/docker-compose.yml index 23af23d547..c33cf5d3a3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -20,7 +20,7 @@ services: - CEDAR_CORE_MOCK - CEDAR_INTAKE_ENABLED - CEDAR_API_KEY - - CEDAR_API_URL + - CEDAR_API_URL=cedarproxy:8001 - CEDAR_CORE_API_VERSION - CEDAR_CACHE_INTERVAL - CEDAR_EMAIL_ADDRESS @@ -73,6 +73,19 @@ services: depends_on: db_migrate: condition: service_completed_successfully # Only start if migrations completed successfully + cedarproxy: + # image: nginx:1.22 + image: nginx-with-cachepurge:v1 + environment: + - CEDAR_API_URL + # - NGINX_ENVSUBST_OUTPUT_DIR=/etc/nginx/conf.d + - NGINX_ENVSUBST_OUTPUT_DIR=/etc/nginx + volumes: + - ./nginx/nginx.conf:/etc/nginx/templates/nginx.conf.template + build: + context: ./nginx/ + args: + ENABLED_MODULES: cachepurge easi_client: image: easi_client:latest minio: diff --git a/nginx/Dockerfile b/nginx/Dockerfile new file mode 100644 index 0000000000..e9dea75b1c --- /dev/null +++ b/nginx/Dockerfile @@ -0,0 +1,79 @@ +ARG NGINX_FROM_IMAGE=nginx:mainline +FROM ${NGINX_FROM_IMAGE} as builder + +ARG ENABLED_MODULES + +SHELL ["/bin/bash", "-exo", "pipefail", "-c"] + +RUN if [ "$ENABLED_MODULES" = "" ]; then \ + echo "No additional modules enabled, exiting"; \ + exit 1; \ + fi + +COPY ./ /modules/ + +RUN apt-get update \ + && apt-get install -y --no-install-suggests --no-install-recommends \ + patch make wget mercurial devscripts debhelper dpkg-dev \ + quilt lsb-release build-essential libxml2-utils xsltproc \ + equivs git g++ libparse-recdescent-perl \ + && XSLSCRIPT_SHA512="f7194c5198daeab9b3b0c3aebf006922c7df1d345d454bd8474489ff2eb6b4bf8e2ffe442489a45d1aab80da6ecebe0097759a1e12cc26b5f0613d05b7c09ffa *stdin" \ + && wget -O /tmp/xslscript.pl https://hg.nginx.org/xslscript/raw-file/01dc9ba12e1b/xslscript.pl \ + && if [ "$(cat /tmp/xslscript.pl | openssl sha512 -r)" = "$XSLSCRIPT_SHA512" ]; then \ + echo "XSLScript checksum verification succeeded!"; \ + chmod +x /tmp/xslscript.pl; \ + mv /tmp/xslscript.pl /usr/local/bin/; \ + else \ + echo "XSLScript checksum verification failed!"; \ + exit 1; \ + fi \ + && hg clone -r ${NGINX_VERSION}-${PKG_RELEASE%%~*} https://hg.nginx.org/pkg-oss/ \ + && cd pkg-oss \ + && mkdir /tmp/packages \ + && for module in $ENABLED_MODULES; do \ + echo "Building $module for nginx-$NGINX_VERSION"; \ + if [ -d /modules/$module ]; then \ + echo "Building $module from user-supplied sources"; \ + # check if module sources file is there and not empty + if [ ! -s /modules/$module/source ]; then \ + echo "No source file for $module in modules/$module/source, exiting"; \ + exit 1; \ + fi; \ + # some modules require build dependencies + if [ -f /modules/$module/build-deps ]; then \ + echo "Installing $module build dependencies"; \ + apt-get update && apt-get install -y --no-install-suggests --no-install-recommends $(cat /modules/$module/build-deps | xargs); \ + fi; \ + # if a module has a build dependency that is not in a distro, provide a + # shell script to fetch/build/install those + # note that shared libraries produced as a result of this script will + # not be copied from the builder image to the main one so build static + if [ -x /modules/$module/prebuild ]; then \ + echo "Running prebuild script for $module"; \ + /modules/$module/prebuild; \ + fi; \ + /pkg-oss/build_module.sh -v $NGINX_VERSION -f -y -o /tmp/packages -n $module $(cat /modules/$module/source); \ + BUILT_MODULES="$BUILT_MODULES $(echo $module | tr '[A-Z]' '[a-z]' | tr -d '[/_\-\.\t ]')"; \ + elif make -C /pkg-oss/debian list | grep -P "^$module\s+\d" > /dev/null; then \ + echo "Building $module from pkg-oss sources"; \ + cd /pkg-oss/debian; \ + make rules-module-$module BASE_VERSION=$NGINX_VERSION NGINX_VERSION=$NGINX_VERSION; \ + mk-build-deps --install --tool="apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends --yes" debuild-module-$module/nginx-$NGINX_VERSION/debian/control; \ + make module-$module BASE_VERSION=$NGINX_VERSION NGINX_VERSION=$NGINX_VERSION; \ + find ../../ -maxdepth 1 -mindepth 1 -type f -name "*.deb" -exec mv -v {} /tmp/packages/ \;; \ + BUILT_MODULES="$BUILT_MODULES $module"; \ + else \ + echo "Don't know how to build $module module, exiting"; \ + exit 1; \ + fi; \ + done \ + && echo "BUILT_MODULES=\"$BUILT_MODULES\"" > /tmp/packages/modules.env + +FROM ${NGINX_FROM_IMAGE} +RUN --mount=type=bind,target=/tmp/packages/,source=/tmp/packages/,from=builder \ + apt-get update \ + && . /tmp/packages/modules.env \ + && for module in $BUILT_MODULES; do \ + apt-get install --no-install-suggests --no-install-recommends -y /tmp/packages/nginx-module-${module}_${NGINX_VERSION}*.deb; \ + done \ + && rm -rf /var/lib/apt/lists/ diff --git a/nginx/cachepurge/source b/nginx/cachepurge/source new file mode 100644 index 0000000000..c3e38fed22 --- /dev/null +++ b/nginx/cachepurge/source @@ -0,0 +1 @@ +https://github.com/FRiCKLE/ngx_cache_purge/archive/2.3.tar.gz diff --git a/nginx/nginx.conf b/nginx/nginx.conf new file mode 100644 index 0000000000..479a9281d1 --- /dev/null +++ b/nginx/nginx.conf @@ -0,0 +1,56 @@ +# load_module modules/ngx_cache_purge_module.so; +load_module modules/ngx_http_cache_purge_module.so; + +user nginx; +worker_processes auto; + +error_log /var/log/nginx/error.log notice; +pid /var/run/nginx.pid; + + +events { + worker_connections 1024; +} + + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + + sendfile on; + #tcp_nopush on; + + keepalive_timeout 65; + + #gzip on; + + # include /etc/nginx/conf.d/*.conf; + + proxy_cache_path /nginxcache keys_zone=cedarcorecache:10m; + proxy_cache_valid 200 302 10m; + + server { + listen 8001; + + server_name cedarproxy; + + location / { + proxy_pass https://${CEDAR_API_URL}/; + proxy_pass_request_headers on; + proxy_set_header Host $proxy_host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + + proxy_cache cedarcorecache; + proxy_cache_key $uri$is_args$args; + proxy_cache_purge PURGE from all; + } + } +} diff --git a/pkg/cedar/core/client.go b/pkg/cedar/core/client.go index 02a69340dc..8e4d5d37fd 100644 --- a/pkg/cedar/core/client.go +++ b/pkg/cedar/core/client.go @@ -37,7 +37,8 @@ func NewClient(ctx context.Context, cedarHost string, cedarAPIKey string, cedarA httptransport.New( cedarHost, basePath, - apiclient.DefaultSchemes, + []string{"http"}, + // apiclient.DefaultSchemes, ), strfmt.Default, ), @@ -53,7 +54,7 @@ func NewClient(ctx context.Context, cedarHost string, cedarAPIKey string, cedarA ) cacheRefreshTime = cedarCoreCacheDurationDefault } - client.startCacheRefresh(ctx, cacheRefreshTime, client.populateSystemSummaryCache) + // client.startCacheRefresh(ctx, cacheRefreshTime, client.populateSystemSummaryCache) return client } diff --git a/pkg/cedar/core/role.go b/pkg/cedar/core/role.go index 638174db3d..d3f79c02c5 100644 --- a/pkg/cedar/core/role.go +++ b/pkg/cedar/core/role.go @@ -4,6 +4,8 @@ import ( "context" "errors" "fmt" + "net/http" + "net/url" "strings" "github.com/guregu/null/zero" @@ -173,6 +175,24 @@ func (c *Client) GetRolesBySystem(ctx context.Context, cedarSystemID string, rol return retVal, nil } +func PurgeRoleCache(cedarSystemID string) error { + req, err := http.NewRequest("PURGE", "http://cedarproxy:8001/gateway/CEDAR%20Core%20API/2.0.0/role?application=alfabet&objectId="+url.QueryEscape(cedarSystemID), nil) + if err != nil { + panic(err) + } + res, err := http.DefaultClient.Do(req) + if err != nil { + panic(err) + } + if res.StatusCode == 404 { + fmt.Println("Cache NOT cleared for Roles") + } + if res.StatusCode == 200 { + fmt.Println("Cache SUCCESSFULLY cleared for Roles") + } + return nil +} + // GetRoleTypes queries CEDAR for the list of supported role types func (c *Client) GetRoleTypes(ctx context.Context) ([]*models.CedarRoleType, error) { if c.mockEnabled { @@ -354,6 +374,7 @@ func (c *Client) SetRolesForUser(ctx context.Context, cedarSystemID string, euaU return roleType.Name.String }) + PurgeRoleCache(cedarSystemID) // fetch the system name (likely from cache) and add it to the response system, getSystemErr := c.GetSystem(ctx, cedarSystemID) if getSystemErr != nil { @@ -418,6 +439,7 @@ func (c *Client) addRoles(ctx context.Context, cedarSystemID string, newRoles [] } return fmt.Errorf("unknown error") } + PurgeRoleCache(cedarSystemID) return nil } diff --git a/pkg/cedar/core/system_summary.go b/pkg/cedar/core/system_summary.go index e3742afd55..8c9420cd12 100644 --- a/pkg/cedar/core/system_summary.go +++ b/pkg/cedar/core/system_summary.go @@ -43,7 +43,7 @@ func (c *Client) GetSystemSummary(ctx context.Context, tryCache bool, euaUserID } // Check and use cache before making API call if `tryCache` is true and there is no `euaUserID` filter - if tryCache && euaUserID == nil { + if false && euaUserID == nil { cachedSystemMap := c.getCachedSystemMap(ctx) if cachedSystemMap != nil { cachedSystems := make([]*models.CedarSystem, len(cachedSystemMap)) @@ -72,7 +72,11 @@ func (c *Client) GetSystemSummary(ctx context.Context, tryCache bool, euaUserID // Make the API call resp, err := c.sdk.System.SystemSummaryFindList(params, c.auth) + // req, err := http.NewRequest("PURGE", "http://cedarproxy:8001/gateway/CEDAR%20Core%20API/2.0.0/system/summary?includeInSurvey=true&state=active", nil) + // res, err := http.DefaultClient.Do(req) + // fmt.Println(res) if err != nil { + fmt.Println(err) return []*models.CedarSystem{}, err } @@ -161,22 +165,38 @@ func (c *Client) GetSystem(ctx context.Context, systemID string) (*models.CedarS return cedarcoremock.GetSystem(systemID), nil } - // Try the cache first - cachedSystem := c.getSystemFromCache(ctx, systemID) - if cachedSystem != nil { - return cachedSystem, nil - } + // // Try the cache first + // cachedSystem := c.getSystemFromCache(ctx, systemID) + // if cachedSystem != nil { + // return cachedSystem, nil + // } + // + // // If it's not cached, populate the cache, and try the cache again + // err := c.populateSystemSummaryCache(ctx) + // if err != nil { + // return nil, err + // } + // + // // Try the cache again now that we know it is fresh + // cachedSystem = c.getSystemFromCache(ctx, systemID) + // if cachedSystem != nil { + // return cachedSystem, nil + // } - // If it's not cached, populate the cache, and try the cache again - err := c.populateSystemSummaryCache(ctx) + // Get data from API - don't use cache to populate cache! + systemSummary, err := c.GetSystemSummary(ctx, false, nil) if err != nil { return nil, err } - // Try the cache again now that we know it is fresh - cachedSystem = c.getSystemFromCache(ctx, systemID) - if cachedSystem != nil { - return cachedSystem, nil + systemSummaryMap := make(map[string]*models.CedarSystem) + for _, sys := range systemSummary { + if sys != nil { + systemSummaryMap[sys.ID.String] = sys + } + } + if sys, found := systemSummaryMap[systemID]; found && sys != nil { + return sys, nil } // If we still haven't found it after repopulating the cache, then it doesn't exist in CEDAR diff --git a/pkg/server/routes.go b/pkg/server/routes.go index 097c46af67..b56016a97b 100644 --- a/pkg/server/routes.go +++ b/pkg/server/routes.go @@ -108,7 +108,8 @@ func (s *Server) routes( //TODO: update this to have OKTA API live in it's own package? var userSearchClient usersearch.Client - if s.environment.Local() || s.environment.Test() { + if false { + // if s.environment.Local() || s.environment.Test() { userSearchClient = local.NewOktaAPIClient() } else { // Create Okta API Client From f26bcce67c347d7cd6e6edc9b59ebc0b005a6059 Mon Sep 17 00:00:00 2001 From: Justin Woodson Date: Wed, 24 Apr 2024 14:20:57 -0400 Subject: [PATCH 02/20] EASI-4129: dockerfile improvements --- .pre-commit-config.yaml | 1 + .../Dockerfile.cedarproxy | 29 +++++++------------ .../modules}/cachepurge/source | 0 {nginx => cedarproxy}/nginx.conf | 0 docker-compose.yml | 12 ++------ 5 files changed, 14 insertions(+), 28 deletions(-) rename nginx/Dockerfile => cedarproxy/Dockerfile.cedarproxy (78%) rename {nginx => cedarproxy/modules}/cachepurge/source (100%) rename {nginx => cedarproxy}/nginx.conf (100%) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 797ab9e6f0..3ede38e083 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -59,6 +59,7 @@ repos: language: node additional_dependencies: [dockerfilelint] files: Dockerfile.* + exclude: Dockerfile.cedarproxy - repo: local hooks: diff --git a/nginx/Dockerfile b/cedarproxy/Dockerfile.cedarproxy similarity index 78% rename from nginx/Dockerfile rename to cedarproxy/Dockerfile.cedarproxy index e9dea75b1c..7752d79cbc 100644 --- a/nginx/Dockerfile +++ b/cedarproxy/Dockerfile.cedarproxy @@ -1,7 +1,6 @@ -ARG NGINX_FROM_IMAGE=nginx:mainline -FROM ${NGINX_FROM_IMAGE} as builder +FROM nginx:mainline as builder -ARG ENABLED_MODULES +ARG ENABLED_MODULES=cachepurge SHELL ["/bin/bash", "-exo", "pipefail", "-c"] @@ -10,23 +9,12 @@ RUN if [ "$ENABLED_MODULES" = "" ]; then \ exit 1; \ fi -COPY ./ /modules/ +COPY ./modules/ /modules/ RUN apt-get update \ && apt-get install -y --no-install-suggests --no-install-recommends \ patch make wget mercurial devscripts debhelper dpkg-dev \ - quilt lsb-release build-essential libxml2-utils xsltproc \ - equivs git g++ libparse-recdescent-perl \ - && XSLSCRIPT_SHA512="f7194c5198daeab9b3b0c3aebf006922c7df1d345d454bd8474489ff2eb6b4bf8e2ffe442489a45d1aab80da6ecebe0097759a1e12cc26b5f0613d05b7c09ffa *stdin" \ - && wget -O /tmp/xslscript.pl https://hg.nginx.org/xslscript/raw-file/01dc9ba12e1b/xslscript.pl \ - && if [ "$(cat /tmp/xslscript.pl | openssl sha512 -r)" = "$XSLSCRIPT_SHA512" ]; then \ - echo "XSLScript checksum verification succeeded!"; \ - chmod +x /tmp/xslscript.pl; \ - mv /tmp/xslscript.pl /usr/local/bin/; \ - else \ - echo "XSLScript checksum verification failed!"; \ - exit 1; \ - fi \ + quilt lsb-release build-essential \ && hg clone -r ${NGINX_VERSION}-${PKG_RELEASE%%~*} https://hg.nginx.org/pkg-oss/ \ && cd pkg-oss \ && mkdir /tmp/packages \ @@ -67,13 +55,16 @@ RUN apt-get update \ exit 1; \ fi; \ done \ - && echo "BUILT_MODULES=\"$BUILT_MODULES\"" > /tmp/packages/modules.env + && echo "BUILT_MODULES=\"$BUILT_MODULES\"" > /tmp/packages/modules.env \ + && rm -rf /var/lib/apt/lists/* -FROM ${NGINX_FROM_IMAGE} +FROM nginx:mainline +ENV NGINX_ENVSUBST_OUTPUT_DIR=/etc/nginx +COPY ./nginx.conf /etc/nginx/templates/nginx.conf.template RUN --mount=type=bind,target=/tmp/packages/,source=/tmp/packages/,from=builder \ apt-get update \ && . /tmp/packages/modules.env \ && for module in $BUILT_MODULES; do \ apt-get install --no-install-suggests --no-install-recommends -y /tmp/packages/nginx-module-${module}_${NGINX_VERSION}*.deb; \ done \ - && rm -rf /var/lib/apt/lists/ + && rm -rf /var/lib/apt/lists/* diff --git a/nginx/cachepurge/source b/cedarproxy/modules/cachepurge/source similarity index 100% rename from nginx/cachepurge/source rename to cedarproxy/modules/cachepurge/source diff --git a/nginx/nginx.conf b/cedarproxy/nginx.conf similarity index 100% rename from nginx/nginx.conf rename to cedarproxy/nginx.conf diff --git a/docker-compose.yml b/docker-compose.yml index c33cf5d3a3..a08f7844cf 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -74,18 +74,12 @@ services: db_migrate: condition: service_completed_successfully # Only start if migrations completed successfully cedarproxy: - # image: nginx:1.22 - image: nginx-with-cachepurge:v1 + image: cedarproxy:latest environment: - CEDAR_API_URL - # - NGINX_ENVSUBST_OUTPUT_DIR=/etc/nginx/conf.d - - NGINX_ENVSUBST_OUTPUT_DIR=/etc/nginx - volumes: - - ./nginx/nginx.conf:/etc/nginx/templates/nginx.conf.template build: - context: ./nginx/ - args: - ENABLED_MODULES: cachepurge + dockerfile: Dockerfile.cedarproxy + context: ./cedarproxy/ easi_client: image: easi_client:latest minio: From e722245b14c9a504b6b1722645b1f332d0a89b6b Mon Sep 17 00:00:00 2001 From: Lee Warrick Date: Wed, 24 Apr 2024 14:45:21 -0400 Subject: [PATCH 03/20] nil deref and merge main --- pkg/cedar/core/client.go | 2 ++ pkg/cedar/core/system_summary.go | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pkg/cedar/core/client.go b/pkg/cedar/core/client.go index 2f573bee42..52339dd129 100644 --- a/pkg/cedar/core/client.go +++ b/pkg/cedar/core/client.go @@ -9,7 +9,9 @@ import ( httptransport "github.com/go-openapi/runtime/client" "github.com/go-openapi/strfmt" cache "github.com/patrickmn/go-cache" + "go.uber.org/zap" + "github.com/cmsgov/easi-app/pkg/appcontext" apiclient "github.com/cmsgov/easi-app/pkg/cedar/core/gen/client" ) diff --git a/pkg/cedar/core/system_summary.go b/pkg/cedar/core/system_summary.go index 0532e9603d..9f51514698 100644 --- a/pkg/cedar/core/system_summary.go +++ b/pkg/cedar/core/system_summary.go @@ -70,7 +70,9 @@ func (c *Client) GetSystemSummary(ctx context.Context, tryCache bool, opts ...sy // set additinoal param filters for _, opt := range opts { - opt(params) + if opt != nil { + opt(params) + } } params.HTTPClient = c.hc From f23661fd96cad1cf7618405447066235bbca75de Mon Sep 17 00:00:00 2001 From: Justin Woodson Date: Wed, 24 Apr 2024 15:09:03 -0400 Subject: [PATCH 04/20] EASI-4129: init cedarproxy k8s manifests --- deploy/base/cedarproxy.yaml | 48 ++++++++++++++++++++++++++++++++++ deploy/base/kustomization.yaml | 1 + scripts/k8s_dev.sh | 4 +++ 3 files changed, 53 insertions(+) create mode 100644 deploy/base/cedarproxy.yaml diff --git a/deploy/base/cedarproxy.yaml b/deploy/base/cedarproxy.yaml new file mode 100644 index 0000000000..f4c19600cf --- /dev/null +++ b/deploy/base/cedarproxy.yaml @@ -0,0 +1,48 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: cedarproxy-configmap + namespace: easi +data: + CEDAR_API_URL: webmethods-apigw.cedarimpl.cms.gov + +--- + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cedarproxy + namespace: easi +spec: + selector: + matchLabels: + app: cedarproxy + template: + metadata: + labels: + app: cedarproxy + spec: + containers: + - name: cedarproxy + image: cedarproxy:latest + imagePullPolicy: Never + envFrom: + - configMapRef: + name: cedarproxy-configmap + resources: {} + ports: + - containerPort: 8001 + +--- + +apiVersion: v1 +kind: Service +metadata: + name: cedarproxy + namespace: easi +spec: + selector: + app: cedarproxy + ports: + - port: 8001 + targetPort: 8001 \ No newline at end of file diff --git a/deploy/base/kustomization.yaml b/deploy/base/kustomization.yaml index 4ec652c532..b75bb77c70 100644 --- a/deploy/base/kustomization.yaml +++ b/deploy/base/kustomization.yaml @@ -7,3 +7,4 @@ resources: - minio.yaml - easi-client.yaml - easi.yaml + - cedarproxy.yaml diff --git a/scripts/k8s_dev.sh b/scripts/k8s_dev.sh index d7081dabc2..3dcf37cc7c 100755 --- a/scripts/k8s_dev.sh +++ b/scripts/k8s_dev.sh @@ -106,6 +106,9 @@ fi echo "🐋 Building db-migrate:${NAMESPACE} image 🐋" docker build -f ../Dockerfile.db_migrations --build-arg TAG=9.10-alpine -t db-migrate:"$NAMESPACE" ../. + + echo "🐋 Building cedarproxy:${NAMESPACE} image 🐋" + docker build -f ../cedarproxy/Dockerfile.cedarproxy -t cedarproxy:"$NAMESPACE" ../cedarproxy/. ) echo "❄️ Deploying EASi via Kustomize ❄️" @@ -122,6 +125,7 @@ delete_temp_dir() { kustomize build > manifest.yaml sed -i'' -E "s/easi-client:latest/easi-client:${NAMESPACE}/" manifest.yaml sed -i'' -E "s/easi-backend:latest/easi-backend:${NAMESPACE}/" manifest.yaml + sed -i'' -E "s/cedarproxy:latest/cedarproxy:${NAMESPACE}/" manifest.yaml sed -i'' -E "s/db-migrate:latest/db-migrate:${NAMESPACE}/" manifest.yaml sed -i'' -E "s/easi-backend.localdev.me/${NAMESPACE}-backend.localdev.me/" manifest.yaml sed -i'' -E "s/easi.localdev.me/${NAMESPACE}.localdev.me/" manifest.yaml From 63e523c99f3015a191ab798d3b1e04aff856ee0e Mon Sep 17 00:00:00 2001 From: Justin Woodson Date: Wed, 24 Apr 2024 15:20:50 -0400 Subject: [PATCH 05/20] EASI-4129: lint oops --- deploy/base/cedarproxy.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deploy/base/cedarproxy.yaml b/deploy/base/cedarproxy.yaml index f4c19600cf..d38c57c56b 100644 --- a/deploy/base/cedarproxy.yaml +++ b/deploy/base/cedarproxy.yaml @@ -45,4 +45,4 @@ spec: app: cedarproxy ports: - port: 8001 - targetPort: 8001 \ No newline at end of file + targetPort: 8001 From dbf00ccb1c4adffaada3381fdf3f8f65d044d0ef Mon Sep 17 00:00:00 2001 From: Lee Warrick Date: Fri, 26 Apr 2024 14:53:31 -0400 Subject: [PATCH 06/20] clean up caching helpers, remove old cache code, purge my systems cache --- pkg/cedar/core/client.go | 42 ++++++---- pkg/cedar/core/role.go | 32 +++----- pkg/cedar/core/system_summary.go | 112 +++----------------------- pkg/cedar/core/system_summary_test.go | 6 +- pkg/graph/schema.resolvers.go | 6 +- pkg/server/routes.go | 3 +- 6 files changed, 59 insertions(+), 142 deletions(-) diff --git a/pkg/cedar/core/client.go b/pkg/cedar/core/client.go index 52339dd129..ba01245749 100644 --- a/pkg/cedar/core/client.go +++ b/pkg/cedar/core/client.go @@ -15,10 +15,6 @@ import ( apiclient "github.com/cmsgov/easi-app/pkg/cedar/core/gen/client" ) -// const ( -// cedarCoreCacheDurationDefault = time.Hour * 6 -// ) - type loggingTransport struct { logger *zap.Logger } @@ -48,6 +44,33 @@ func (t *loggingTransport) RoundTrip(r *http.Request) (*http.Response, error) { return resp, err } +var cedarPath string + +func PurgeCacheByPath(ctx context.Context, path string) error { + req, err := http.NewRequest("PURGE", cedarPath+path, nil) + logger := appcontext.ZLogger(ctx) + if err != nil { + return err + } + res, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + var cacheIsPurged bool + if res.StatusCode == 200 { + cacheIsPurged = true + } + logger.Info( + "Cache Purge", + zap.String("pathArg", path), + zap.String("path", req.URL.Path), + zap.String("queryParams", req.URL.RawQuery), + zap.Int("status", res.StatusCode), + zap.Bool("success", cacheIsPurged), + ) + return nil +} + // NewClient builds the type that holds a connection to the CEDAR Core API func NewClient(ctx context.Context, cedarHost string, cedarAPIKey string, cedarAPIVersion string, cacheRefreshTime time.Duration, mockEnabled bool) *Client { c := cache.New(cache.NoExpiration, cache.NoExpiration) // Don't expire data _or_ clean it up @@ -59,6 +82,7 @@ func NewClient(ctx context.Context, cedarHost string, cedarAPIKey string, cedarA } basePath := "/gateway/CEDAR Core API/" + cedarAPIVersion + cedarPath = "http://" + cedarHost + basePath client := &Client{ mockEnabled: mockEnabled, auth: httptransport.APIKeyAuth( @@ -79,16 +103,6 @@ func NewClient(ctx context.Context, cedarHost string, cedarAPIKey string, cedarA cache: c, } - // if cacheRefreshTime <= 0 { - // appcontext.ZLogger(ctx).Error( - // "CEDAR cacheRefreshTime is not a valid value, falling back to default", - // zap.Duration("cacheRefreshTime", cacheRefreshTime), - // zap.Duration("defaultDuration", cedarCoreCacheDurationDefault), - // ) - // cacheRefreshTime = cedarCoreCacheDurationDefault - // } - // client.startCacheRefresh(ctx, cacheRefreshTime, client.populateSystemSummaryCache) - return client } diff --git a/pkg/cedar/core/role.go b/pkg/cedar/core/role.go index 91de8a5c80..2b523c8802 100644 --- a/pkg/cedar/core/role.go +++ b/pkg/cedar/core/role.go @@ -4,7 +4,6 @@ import ( "context" "errors" "fmt" - "net/http" "net/url" "strings" @@ -175,22 +174,8 @@ func (c *Client) GetRolesBySystem(ctx context.Context, cedarSystemID string, rol return retVal, nil } -func PurgeRoleCache(cedarSystemID string) error { - req, err := http.NewRequest("PURGE", "http://cedarproxy:8001/gateway/CEDAR%20Core%20API/2.0.0/role?application=alfabet&objectId="+url.QueryEscape(cedarSystemID), nil) - if err != nil { - panic(err) - } - res, err := http.DefaultClient.Do(req) - if err != nil { - panic(err) - } - if res.StatusCode == 404 { - fmt.Println("Cache NOT cleared for Roles") - } - if res.StatusCode == 200 { - fmt.Println("Cache SUCCESSFULLY cleared for Roles") - } - return nil +func PurgeRoleCache(ctx context.Context, cedarSystemID string) error { + return PurgeCacheByPath(ctx, "/role?application="+cedarRoleApplication+"&objectId="+url.QueryEscape(cedarSystemID)) } // GetRoleTypes queries CEDAR for the list of supported role types @@ -374,10 +359,19 @@ func (c *Client) SetRolesForUser(ctx context.Context, cedarSystemID string, euaU return roleType.Name.String }) - err = PurgeRoleCache(cedarSystemID) + err = PurgeRoleCache(ctx, cedarSystemID) + if err != nil { + return nil, err + } + err = PurgeSystemCacheByEUA(ctx, euaUserID) if err != nil { return nil, err } + // re-populate the cache for "My Systems" + _, err = c.GetSystemSummary(ctx, WithEuaIDFilter(euaUserID)) + if err != nil { + appcontext.ZLogger(ctx).Warn("error refreshing my systems for user") + } // fetch the system name (likely from cache) and add it to the response system, getSystemErr := c.GetSystem(ctx, cedarSystemID) if getSystemErr != nil { @@ -442,7 +436,7 @@ func (c *Client) addRoles(ctx context.Context, cedarSystemID string, newRoles [] } return fmt.Errorf("unknown error") } - err = PurgeRoleCache(cedarSystemID) + err = PurgeRoleCache(ctx, cedarSystemID) if err != nil { return err } diff --git a/pkg/cedar/core/system_summary.go b/pkg/cedar/core/system_summary.go index 9f51514698..3fb095a518 100644 --- a/pkg/cedar/core/system_summary.go +++ b/pkg/cedar/core/system_summary.go @@ -14,22 +14,9 @@ import ( "github.com/cmsgov/easi-app/pkg/models" ) -const ( - systemSummaryCacheKey = "system-summary-all" -) - -func (c *Client) getCachedSystemMap(ctx context.Context) map[string]*models.CedarSystem { - cachedStruct, found := c.cache.Get(systemSummaryCacheKey) - if found { - cachedSystemMap := cachedStruct.(map[string]*models.CedarSystem) - return cachedSystemMap - } - return nil -} - // GetSystemSummary makes a GET call to the /system/summary endpoint // If `tryCache` is true and `euaUserID` is nil, we will try to hit the cache. Otherwise, we will make an API call as we cannot filter on EUA on our end -func (c *Client) GetSystemSummary(ctx context.Context, tryCache bool, opts ...systemSummaryParamFilterOpt) ([]*models.CedarSystem, error) { +func (c *Client) GetSystemSummary(ctx context.Context, opts ...systemSummaryParamFilterOpt) ([]*models.CedarSystem, error) { if c.mockEnabled { appcontext.ZLogger(ctx).Info("CEDAR Core is disabled") @@ -42,25 +29,6 @@ func (c *Client) GetSystemSummary(ctx context.Context, tryCache bool, opts ...sy return cedarcoremock.GetSystems(), nil } - // Check and use cache before making API call if `tryCache` is true and there are no filters - // if tryCache && len(opts) < 1 { - if false { - cachedSystemMap := c.getCachedSystemMap(ctx) - if cachedSystemMap != nil { - cachedSystems := make([]*models.CedarSystem, len(cachedSystemMap)) - - i := 0 - for _, sys := range cachedSystemMap { - cachedSystems[i] = sys - i++ - } - - return cachedSystems, nil - } - } - - // No item in the cache - make the API call as usual - // Construct the parameters params := apisystems.NewSystemSummaryFindListParams() @@ -79,9 +47,6 @@ func (c *Client) GetSystemSummary(ctx context.Context, tryCache bool, opts ...sy // Make the API call resp, err := c.sdk.System.SystemSummaryFindList(params, c.auth) - // req, err := http.NewRequest("PURGE", "http://cedarproxy:8001/gateway/CEDAR%20Core%20API/2.0.0/system/summary?includeInSurvey=true&state=active", nil) - // res, err := http.DefaultClient.Do(req) - // fmt.Println(res) if err != nil { fmt.Println(err) return []*models.CedarSystem{}, err @@ -122,76 +87,22 @@ func (c *Client) GetSystemSummary(ctx context.Context, tryCache bool, opts ...sy return retVal, nil } -// populateSystemSummaryCache is a method used internally by the CEDAR Core client -// to populate the in-memory cache with the results of a call to the /system/summary endpoint -// -// It does not return anything from the cache, nor does it return anything at all (unless an error occurs) -// func (c *Client) populateSystemSummaryCache(ctx context.Context) error { -// if c.mockEnabled { -// appcontext.ZLogger(ctx).Info("CEDAR Core is disabled") -// return nil -// } -// -// appcontext.ZLogger(ctx).Info("Refreshing System Summary cache") -// -// // Get data from API - don't use cache to populate cache! -// systemSummary, err := c.GetSystemSummary(ctx, false) -// if err != nil { -// return err -// } -// -// systemSummaryMap := make(map[string]*models.CedarSystem) -// for _, sys := range systemSummary { -// if sys != nil { -// systemSummaryMap[sys.ID.String] = sys -// } -// } -// -// // Set in cache -// c.cache.SetDefault(systemSummaryCacheKey, systemSummaryMap) -// -// appcontext.ZLogger(ctx).Info("Refreshed System Summary cache") -// -// return nil -// } - -// func (c *Client) getSystemFromCache(ctx context.Context, systemID string) *models.CedarSystem { -// // Check if the system ID is cached in the map -// cachedSystemMap := c.getCachedSystemMap(ctx) -// if sys, found := cachedSystemMap[systemID]; found && sys != nil { -// return sys -// } -// return nil -// } - -// GetSystem retrieves a CEDAR system by ID (IctObjectID), by first checking the cache, then -// if it is not found, repopulating the cache and checking one more time. +func PurgeSystemCacheByEUA(ctx context.Context, euaID string) error { + err := PurgeCacheByPath(ctx, "/system/summary?includeInSurvey=true&state=active&userName="+euaID) + if err != nil { + return err + } + return nil +} + +// GetSystem retrieves a CEDAR system by ID (IctObjectID) func (c *Client) GetSystem(ctx context.Context, systemID string) (*models.CedarSystem, error) { if c.mockEnabled { appcontext.ZLogger(ctx).Info("CEDAR Core is disabled") return cedarcoremock.GetSystem(systemID), nil } - // // Try the cache first - // cachedSystem := c.getSystemFromCache(ctx, systemID) - // if cachedSystem != nil { - // return cachedSystem, nil - // } - // - // // If it's not cached, populate the cache, and try the cache again - // err := c.populateSystemSummaryCache(ctx) - // if err != nil { - // return nil, err - // } - // - // // Try the cache again now that we know it is fresh - // cachedSystem = c.getSystemFromCache(ctx, systemID) - // if cachedSystem != nil { - // return cachedSystem, nil - // } - - // Get data from API - don't use cache to populate cache! - systemSummary, err := c.GetSystemSummary(ctx, false, nil) + systemSummary, err := c.GetSystemSummary(ctx, nil) if err != nil { return nil, err } @@ -206,7 +117,6 @@ func (c *Client) GetSystem(ctx context.Context, systemID string) (*models.CedarS return sys, nil } - // If we still haven't found it after repopulating the cache, then it doesn't exist in CEDAR return nil, &apperrors.ResourceNotFoundError{Err: fmt.Errorf("no system found"), Resource: models.CedarSystem{}} } diff --git a/pkg/cedar/core/system_summary_test.go b/pkg/cedar/core/system_summary_test.go index f39cdeb281..cbb23516b4 100644 --- a/pkg/cedar/core/system_summary_test.go +++ b/pkg/cedar/core/system_summary_test.go @@ -30,7 +30,7 @@ func (s *SystemSummaryTestSuite) TestGetSystemSummary() { s.Run("LD defaults protects invocation of GetSystemSummary", func() { c := NewClient(ctx, "fake", "fake", "1.0.0", time.Minute, true) - resp, err := c.GetSystemSummary(ctx, false) + resp, err := c.GetSystemSummary(ctx) s.NoError(err) // ensure mock data is returned @@ -42,7 +42,7 @@ func (s *SystemSummaryTestSuite) TestGetSystemSummary() { s.Run("Retrieves filtered list when EUA filter is present", func() { c := NewClient(ctx, "fake", "fake", "1.0.0", time.Minute, true) - resp, err := c.GetSystemSummary(ctx, false, WithEuaIDFilter("USR1")) + resp, err := c.GetSystemSummary(ctx, WithEuaIDFilter("USR1")) s.NoError(err) // ensure filtered mock data is returned @@ -54,7 +54,7 @@ func (s *SystemSummaryTestSuite) TestGetSystemSummary() { s.Run("Retrieves filtered list when Sub-System filter is present", func() { c := NewClient(ctx, "fake", "fake", "1.0.0", time.Minute, true) - resp, err := c.GetSystemSummary(ctx, false, WithSubSystems("1")) + resp, err := c.GetSystemSummary(ctx, WithSubSystems("1")) s.NoError(err) // ensure filtered mock data is returned diff --git a/pkg/graph/schema.resolvers.go b/pkg/graph/schema.resolvers.go index 1b023d8445..a6e4058e2d 100644 --- a/pkg/graph/schema.resolvers.go +++ b/pkg/graph/schema.resolvers.go @@ -1236,12 +1236,12 @@ func (r *queryResolver) CedarSystem(ctx context.Context, cedarSystemID string) ( // CedarSystems is the resolver for the cedarSystems field. func (r *queryResolver) CedarSystems(ctx context.Context) ([]*models.CedarSystem, error) { - return r.cedarCoreClient.GetSystemSummary(ctx, true) + return r.cedarCoreClient.GetSystemSummary(ctx) } // CedarSubSystems is the resolver for the cedarSubSystems field. func (r *queryResolver) CedarSubSystems(ctx context.Context, cedarSystemID string) ([]*models.CedarSubSystem, error) { - systems, err := r.cedarCoreClient.GetSystemSummary(ctx, false, cedarcore.WithSubSystems(cedarSystemID)) + systems, err := r.cedarCoreClient.GetSystemSummary(ctx, cedarcore.WithSubSystems(cedarSystemID)) if err != nil { return nil, err } @@ -1267,7 +1267,7 @@ func (r *queryResolver) CedarContractsBySystem(ctx context.Context, cedarSystemI // MyCedarSystems is the resolver for the myCedarSystems field. func (r *queryResolver) MyCedarSystems(ctx context.Context) ([]*models.CedarSystem, error) { requesterEUAID := appcontext.Principal(ctx).ID() - return r.cedarCoreClient.GetSystemSummary(ctx, false, cedarcore.WithEuaIDFilter(requesterEUAID)) + return r.cedarCoreClient.GetSystemSummary(ctx, cedarcore.WithEuaIDFilter(requesterEUAID)) } // CedarSystemBookmarks is the resolver for the cedarSystemBookmarks field. diff --git a/pkg/server/routes.go b/pkg/server/routes.go index b56016a97b..097c46af67 100644 --- a/pkg/server/routes.go +++ b/pkg/server/routes.go @@ -108,8 +108,7 @@ func (s *Server) routes( //TODO: update this to have OKTA API live in it's own package? var userSearchClient usersearch.Client - if false { - // if s.environment.Local() || s.environment.Test() { + if s.environment.Local() || s.environment.Test() { userSearchClient = local.NewOktaAPIClient() } else { // Create Okta API Client From ffc60fa4c18606d4b0d17c01c074b48cba6fee46 Mon Sep 17 00:00:00 2001 From: Lee Warrick Date: Fri, 26 Apr 2024 15:50:48 -0400 Subject: [PATCH 07/20] add config var to allow using okta API locally --- .envrc | 6 +++--- docker-compose.yml | 1 + pkg/appconfig/config.go | 3 +++ pkg/server/routes.go | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.envrc b/.envrc index 48536e485f..11d235ec76 100644 --- a/.envrc +++ b/.envrc @@ -66,6 +66,9 @@ export OKTA_API_TOKEN= export OKTA_TEST_USERNAME= export OKTA_TEST_PASSWORD= export OKTA_TEST_SECRET= +# Use OKTA when doing local dev +export USE_OKTA_LOCAL=false + # Launch Darkly configuration export FLAG_SOURCE=LOCAL # LAUNCH_DARKLY, LOCAL, or FILE @@ -123,9 +126,6 @@ export AIR_CONFIG_DEBUG_WAIT="-c .airDebugWait.conf" # Fix job codes when sending email locally export ALT_JOB_CODES=true - - - # Load a local overrides file. Any changes you want to make for your local # environment should live in that file. diff --git a/docker-compose.yml b/docker-compose.yml index 589f832ccb..f190ef51a4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -70,6 +70,7 @@ services: - ALT_JOB_CODES - OKTA_API_URL - OKTA_API_TOKEN + - USE_OKTA_LOCAL depends_on: db_migrate: condition: service_completed_successfully # Only start if migrations completed successfully diff --git a/pkg/appconfig/config.go b/pkg/appconfig/config.go index b62435b382..2ddbde9bb9 100644 --- a/pkg/appconfig/config.go +++ b/pkg/appconfig/config.go @@ -231,3 +231,6 @@ const OKTAAPIURL = "OKTA_API_URL" // OKTAAPIToken is the key for the Okta API token // #nosec G101 false positive - not the actual API key itself const OKTAAPIToken = "OKTA_API_TOKEN" + +// OktaLocalEnabled is the key for enabling OKTA on local dev +const OktaLocalEnabled = "USE_OKTA_LOCAL" diff --git a/pkg/server/routes.go b/pkg/server/routes.go index 097c46af67..c5dff3285b 100644 --- a/pkg/server/routes.go +++ b/pkg/server/routes.go @@ -108,7 +108,7 @@ func (s *Server) routes( //TODO: update this to have OKTA API live in it's own package? var userSearchClient usersearch.Client - if s.environment.Local() || s.environment.Test() { + if (!s.Config.GetBool(appconfig.OktaLocalEnabled) && s.environment.Local()) || s.environment.Test() { userSearchClient = local.NewOktaAPIClient() } else { // Create Okta API Client From 0dd4c401ca61ed179dbf1257de63e56716002377 Mon Sep 17 00:00:00 2001 From: Lee Warrick Date: Tue, 30 Apr 2024 16:37:40 -0400 Subject: [PATCH 08/20] add build action for cedarproxy --- .../workflows/build_application_images.yml | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/.github/workflows/build_application_images.yml b/.github/workflows/build_application_images.yml index b7a276ef61..3dfb0abdac 100644 --- a/.github/workflows/build_application_images.yml +++ b/.github/workflows/build_application_images.yml @@ -142,3 +142,47 @@ jobs: if: ${{ failure() }} run: | ./scripts/github-action-announce-broken-branch + + build_cedarproxy_image: + runs-on: ubuntu-latest + steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Check for changes to cedarproxy folder + uses: dorny/paths-filter@v3 + id: changes + with: + filters: | + src: + - 'cedarproxy/**' + - name: Login to Docker Hub + uses: docker/login-action@v3 + if: steps.changes.outputs.cedarproxy == 'true' + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Configure AWS credentials + if: steps.changes.outputs.cedarproxy == 'true' + uses: aws-actions/configure-aws-credentials@v4.0.2 + with: + role-to-assume: ${{ secrets.AWS_INFRA_OIDC_ROLE_TO_ASSUME }} + aws-region: us-west-2 + - name: Login to Amazon ECR + if: steps.changes.outputs.cedarproxy == 'true' + id: login-ecr + uses: aws-actions/amazon-ecr-login@v2 + - name: Setup Docker Buildx + if: steps.changes.outputs.cedarproxy == 'true' + uses: docker/setup-buildx-action@v3 + - name: Build, tag, and push image to Amazon ECR + if: steps.changes.outputs.cedarproxy == 'true' + uses: docker/build-push-action@v5 + with: + context: ./cedarproxy + file: Dockerfile.cedarproxy + push: true + tags: ${{ steps.login-ecr.outputs.registry }}/easi-cedarproxy:${{ env.GIT_HASH }} + - name: Announce failure + if: ${{ failure() }} + run: | + ./scripts/github-action-announce-broken-branch From 301eb81139782e780ac63e45e4ebba9c1c0b5f1a Mon Sep 17 00:00:00 2001 From: Lee Warrick Date: Tue, 30 Apr 2024 16:49:04 -0400 Subject: [PATCH 09/20] fix build image workflow filter --- .github/workflows/build_application_images.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build_application_images.yml b/.github/workflows/build_application_images.yml index 3dfb0abdac..834e74aced 100644 --- a/.github/workflows/build_application_images.yml +++ b/.github/workflows/build_application_images.yml @@ -153,7 +153,7 @@ jobs: id: changes with: filters: | - src: + cedarproxy: - 'cedarproxy/**' - name: Login to Docker Hub uses: docker/login-action@v3 From 8692f3714d4498190f5c362f0454e51a30b53876 Mon Sep 17 00:00:00 2001 From: Lee Warrick Date: Tue, 30 Apr 2024 17:03:13 -0400 Subject: [PATCH 10/20] fix build image workflow context --- .github/workflows/build_application_images.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build_application_images.yml b/.github/workflows/build_application_images.yml index 834e74aced..0e08486cf6 100644 --- a/.github/workflows/build_application_images.yml +++ b/.github/workflows/build_application_images.yml @@ -178,8 +178,8 @@ jobs: if: steps.changes.outputs.cedarproxy == 'true' uses: docker/build-push-action@v5 with: - context: ./cedarproxy - file: Dockerfile.cedarproxy + context: ./cedarproxy/ + file: ./cedarproxy/Dockerfile.cedarproxy push: true tags: ${{ steps.login-ecr.outputs.registry }}/easi-cedarproxy:${{ env.GIT_HASH }} - name: Announce failure From 4e71e71c812ccfc5ed40b238081e569d21d83114 Mon Sep 17 00:00:00 2001 From: Lee Warrick Date: Thu, 2 May 2024 15:07:39 -0400 Subject: [PATCH 11/20] increase cache valid time to 24h --- cedarproxy/nginx.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cedarproxy/nginx.conf b/cedarproxy/nginx.conf index 479a9281d1..785c73771f 100644 --- a/cedarproxy/nginx.conf +++ b/cedarproxy/nginx.conf @@ -32,8 +32,8 @@ http { # include /etc/nginx/conf.d/*.conf; - proxy_cache_path /nginxcache keys_zone=cedarcorecache:10m; - proxy_cache_valid 200 302 10m; + proxy_cache_path /nginxcache keys_zone=cedarcorecache:24h; + proxy_cache_valid 200 302 24h; server { listen 8001; From e43e85970baf92128267c43ee67772cedeff7c17 Mon Sep 17 00:00:00 2001 From: Lee Warrick Date: Thu, 2 May 2024 15:43:23 -0400 Subject: [PATCH 12/20] add deploy pipeline for cedarproxy dev --- .github/workflows/deploy_to_environment.yml | 42 ++++++++++++++++++++- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy_to_environment.yml b/.github/workflows/deploy_to_environment.yml index 3994cf9fc9..7968efc8c1 100644 --- a/.github/workflows/deploy_to_environment.yml +++ b/.github/workflows/deploy_to_environment.yml @@ -29,6 +29,44 @@ jobs: run: | echo "Deploy confirmed! 🚀" + deploy_cedar_proxy: + runs-on: ubuntu-latest + needs: confirm_deploy + environment: ${{ inputs.env }} + steps: + - name: Check out code + uses: actions/checkout@v4 + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@v4.0.2 + with: + role-to-assume: ${{ secrets.AWS_OIDC_ROLE_TO_ASSUME }} + aws-region: us-west-2 + - name: Check for changes to cedarproxy folder + uses: dorny/paths-filter@v3 + id: changes + with: + filters: | + cedarproxy: + - 'pkg/cedar/core/gen/**' + - 'cedarproxy/**' + - name: Clean the database + if: ${{ contains(inputs.env, 'dev') && steps.changes.outputs.cedarproxy == 'true' }} + env: + ECR_REGISTRY: ${{ secrets.ECR_REGISTRY }} + ECR_REPOSITORY: easi-cedarproxy + NEW_IMAGE_TAG: ${{ env.GIT_HASH }} + TASK_FAMILY: "easi-cedarproxy-${{ inputs.env }}" + ECS_CLUSTER: "${{ inputs.env }}-easi-app" + SERVICE_NAME: easi-cedarproxy + SECURITY_GROUP_NAME: "ecs-easi-cedarproxy-${{ inputs.env }}" + run: | + export TASK_REVISION=$(./scripts/update_ecs_task_definition.sh) + ./scripts/run_ecs_task.sh + - name: Announce failure + if: ${{ failure() }} + run: | + ./scripts/github-action-announce-broken-branch + database_actions: runs-on: ubuntu-latest needs: confirm_deploy @@ -42,7 +80,7 @@ jobs: uses: aws-actions/configure-aws-credentials@v4.0.2 with: role-to-assume: ${{ secrets.AWS_OIDC_ROLE_TO_ASSUME }} - aws-region: us-west-2 + aws-region: us-west-2 - name: Clean the database if: ${{ contains(inputs.env, 'dev') && vars.ENABLE_DEV_DB_CLEAN == '1' }} env: @@ -110,7 +148,7 @@ jobs: if: ${{ failure() }} run: | ./scripts/github-action-announce-broken-branch - + deploy_frontend: needs: [database_actions] runs-on: ubuntu-latest From af5b21de40248557a315588a297b59acca7926e8 Mon Sep 17 00:00:00 2001 From: Lee Warrick Date: Thu, 2 May 2024 16:39:01 -0400 Subject: [PATCH 13/20] update step name --- .github/workflows/deploy_to_environment.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy_to_environment.yml b/.github/workflows/deploy_to_environment.yml index 7968efc8c1..8e541ab5c8 100644 --- a/.github/workflows/deploy_to_environment.yml +++ b/.github/workflows/deploy_to_environment.yml @@ -49,7 +49,7 @@ jobs: cedarproxy: - 'pkg/cedar/core/gen/**' - 'cedarproxy/**' - - name: Clean the database + - name: Update ECS task definition if: ${{ contains(inputs.env, 'dev') && steps.changes.outputs.cedarproxy == 'true' }} env: ECR_REGISTRY: ${{ secrets.ECR_REGISTRY }} From 8e920c30c2a7464d3844aea550278b9ddaa88237 Mon Sep 17 00:00:00 2001 From: Justin Woodson Date: Thu, 2 May 2024 16:46:16 -0400 Subject: [PATCH 14/20] EASI-4129: call correct script --- .github/workflows/deploy_to_environment.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy_to_environment.yml b/.github/workflows/deploy_to_environment.yml index 8e541ab5c8..ec39ed8c57 100644 --- a/.github/workflows/deploy_to_environment.yml +++ b/.github/workflows/deploy_to_environment.yml @@ -49,7 +49,7 @@ jobs: cedarproxy: - 'pkg/cedar/core/gen/**' - 'cedarproxy/**' - - name: Update ECS task definition + - name: Update ECS task definition and deploy Cedarproxy if: ${{ contains(inputs.env, 'dev') && steps.changes.outputs.cedarproxy == 'true' }} env: ECR_REGISTRY: ${{ secrets.ECR_REGISTRY }} @@ -61,7 +61,7 @@ jobs: SECURITY_GROUP_NAME: "ecs-easi-cedarproxy-${{ inputs.env }}" run: | export TASK_REVISION=$(./scripts/update_ecs_task_definition.sh) - ./scripts/run_ecs_task.sh + ./scripts/deploy_ecs_service.sh - name: Announce failure if: ${{ failure() }} run: | From e3ea6113ceb6da9890cb866c355fc4f341996928 Mon Sep 17 00:00:00 2001 From: Lee Warrick Date: Thu, 2 May 2024 17:30:42 -0400 Subject: [PATCH 15/20] cache size is not cache time --- cedarproxy/nginx.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cedarproxy/nginx.conf b/cedarproxy/nginx.conf index 785c73771f..d081e15e5b 100644 --- a/cedarproxy/nginx.conf +++ b/cedarproxy/nginx.conf @@ -32,7 +32,7 @@ http { # include /etc/nginx/conf.d/*.conf; - proxy_cache_path /nginxcache keys_zone=cedarcorecache:24h; + proxy_cache_path /nginxcache keys_zone=cedarcorecache:10m; proxy_cache_valid 200 302 24h; server { From 75d8d64979e78121db07cd18bb850442b8830a8d Mon Sep 17 00:00:00 2001 From: Lee Warrick Date: Mon, 6 May 2024 14:31:53 -0400 Subject: [PATCH 16/20] mention proxy within CEDAR docs --- docs/cedar.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/docs/cedar.md b/docs/cedar.md index 4871a121d6..0279fc177d 100644 --- a/docs/cedar.md +++ b/docs/cedar.md @@ -6,6 +6,13 @@ The CMS Enterprise Data and Analytics Repository (CEDAR) is a collection of APIs [CEDAR's Confluence Space](https://confluence.cms.gov/pages/viewpage.action?pageId=319959581) +## CEDAR UI + +The CEDAR web UI (where you can view documentation, try out APIs, and browse data in Alfabet). It can be accessed from the following URLs for each environment + +- IMPL: https://www.cedarimpl.cms.gov/ +- PROD: https://www.cedar.cms.gov/ + ## Local Prerequisites In order to browse the CEDAR UI you'll need to meet a few prerequisites: @@ -15,17 +22,10 @@ In order to browse the CEDAR UI you'll need to meet a few prerequisites: 1. The following edits to your [hosts file](https://en.wikipedia.org/wiki/Hosts_(file)) ``` -10.138.78.45 cedarimpl.cms.gov aris.cedarimpl.cms.gov alfabet.cedarimpl.cms.gov webmethods-apigw.cedarimpl.cms.gov webmethods-apiportal.cedarimpl.cms.gov www.cedarimpl.cms.gov aris.cedarimpl.cms.gov alfabet.cedarimpl.cms.gov webmethods-apigw.cedarimpl.cms.gov +10.138.78.45 cedarimpl.cms.gov aris.cedarimpl.cms.gov alfabet.cedarimpl.cms.gov webmethods-apigw.cedarimpl.cms.gov webmethods-apiportal.cedarimpl.cms.gov www.cedarimpl.cms.gov aris.cedarimpl.cms.gov alfabet.cedarimpl.cms.gov webmethods-apigw.cedarimpl.cms.gov 10.245.38.21 www.cedar.cms.gov cedar.cms.gov aris.cedar.cms.gov alfabet.cedar.cms.gov webmethods-apigw.cedar.cms.gov webmethods-apiportal.cedar.cms.gov ``` -## CEDAR UI - -The CEDAR web UI (where you can view documentation, try out APIs, and browse data in Alfabet). It can be accessed from the following URLs for each environment - -- IMPL: https://www.cedarimpl.cms.gov/ -- PROD: https://www.cedar.cms.gov/ - ### webMethods API Portal The [webMethods API Portal](https://webmethods-apiportal.cedar.cms.gov/portal/) is where you can view CEDARs API documentation, and is probably the most useful tool for developers. You will need to be on the VPN to access the portal. Once you're there, you can click "API Gallery" at the top of the page to view the details of each CEDAR API. @@ -42,7 +42,9 @@ However, you can click Alfabet on the main CEDAR UI page to see the Alfabet UI, ## How is CEDAR accessed within EASi? -The calls that are made to the CEDAR APIs are defined by code generated by `go-swagger`. However, in order to not have changes to the CEDAR API documentation break EASi, a "translated client" is usually created for each CEDAR API that wraps the generated code with our own, tested client. An example of this is the [pkg/cedar/intake/client.go](../pkg/cedar/intake/client.go) file. +The CEDAR API can be slow when responding to http requests, so a cache-enabled proxy is used to expedite data-retrieval. The proxy is an nginx server with rules applied for caching requests and purging cached responses. This proxy is managed by the EASi team and all of the EASi API calls are made to the proxy which then communicates with the CEDAR API as necessary. + +Within the EASi API, the calls that are made to the CEDAR APIs are defined by code generated by `go-swagger`. However, in order to not have changes to the CEDAR API documentation break EASi, a "translated client" is usually created for each CEDAR API that wraps the generated code with our own, tested client. An example of this is the [pkg/cedar/intake/client.go](../pkg/cedar/intake/client.go) file. ### Code Generation From 66bb5fe544abce366e70873a463d3c217e0eae47 Mon Sep 17 00:00:00 2001 From: Lee Warrick Date: Wed, 8 May 2024 13:54:41 -0400 Subject: [PATCH 17/20] remove memcache code, add proxy URL env var --- .envrc | 3 ++- deploy/base/easi.yaml | 3 ++- docker-compose.yml | 3 ++- pkg/appconfig/config.go | 3 +++ pkg/cedar/core/client.go | 27 ++------------------------- pkg/cedar/core/client_test.go | 3 +-- pkg/cedar/core/system_summary_test.go | 9 ++++----- pkg/graph/schema.resolvers_test.go | 3 +-- pkg/server/routes.go | 3 +-- 9 files changed, 18 insertions(+), 39 deletions(-) diff --git a/.envrc b/.envrc index 11d235ec76..9b4e215466 100644 --- a/.envrc +++ b/.envrc @@ -109,9 +109,10 @@ PATH_add ./bin # CEDAR export CEDAR_CORE_MOCK=true export CEDAR_INTAKE_ENABLED=false +# for CEDAR core caching +export CEDAR_PROXY_URL="" export CEDAR_API_URL="webmethods-apigw.cedarimpl.cms.gov" export CEDAR_API_KEY="" -export CEDAR_CACHE_INTERVAL="30m" export CEDAR_CORE_API_VERSION="2.0.0" export CEDAR_EMAIL_ADDRESS="EnterpriseArchitecture@notCMS.gov" diff --git a/deploy/base/easi.yaml b/deploy/base/easi.yaml index 123c6c340c..5287270fa1 100644 --- a/deploy/base/easi.yaml +++ b/deploy/base/easi.yaml @@ -7,7 +7,8 @@ data: CEDAR_CORE_MOCK: 'true' CEDAR_INTAKE_ENABLED: 'false' CEDAR_API_KEY: '' - CEDAR_API_URL: "webmethods-apigw.cedardev.cms.gov" + CEDAR_PROXY_URL: "" + CEDAR_API_URL: "webmethods-apigw.cedarimpl.cms.gov" CEDAR_CORE_API_VERSION: "2.0.0" CEDAR_CACHE_INTERVAL: "30m" CEDAR_EMAIL_ADDRESS: "EnterpriseArchitecture@notCMS.gov" diff --git a/docker-compose.yml b/docker-compose.yml index f190ef51a4..124eea6da2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -20,7 +20,8 @@ services: - CEDAR_CORE_MOCK - CEDAR_INTAKE_ENABLED - CEDAR_API_KEY - - CEDAR_API_URL=cedarproxy:8001 + - CEDAR_API_URL + - CEDAR_PROXY_URL=cedarproxy:8001 - CEDAR_CORE_API_VERSION - CEDAR_CACHE_INTERVAL - CEDAR_EMAIL_ADDRESS diff --git a/pkg/appconfig/config.go b/pkg/appconfig/config.go index 2ddbde9bb9..2bdd6f17dc 100644 --- a/pkg/appconfig/config.go +++ b/pkg/appconfig/config.go @@ -161,6 +161,9 @@ const LocalMinioS3SecretKey = "MINIO_SECRET_KEY" // AWSRegion is the key for the region we establish a session to for AWS services const AWSRegion = "AWS_REGION" +// CEDARPROXYURL is the key for the CEDAR proxy url +const CEDARPROXYURL = "CEDAR_PROXY_URL" + // CEDARAPIURL is the key for the CEDAR base url const CEDARAPIURL = "CEDAR_API_URL" diff --git a/pkg/cedar/core/client.go b/pkg/cedar/core/client.go index ba01245749..0c32bfdd9b 100644 --- a/pkg/cedar/core/client.go +++ b/pkg/cedar/core/client.go @@ -8,7 +8,6 @@ import ( "github.com/go-openapi/runtime" httptransport "github.com/go-openapi/runtime/client" "github.com/go-openapi/strfmt" - cache "github.com/patrickmn/go-cache" "go.uber.org/zap" "github.com/cmsgov/easi-app/pkg/appcontext" @@ -72,9 +71,7 @@ func PurgeCacheByPath(ctx context.Context, path string) error { } // NewClient builds the type that holds a connection to the CEDAR Core API -func NewClient(ctx context.Context, cedarHost string, cedarAPIKey string, cedarAPIVersion string, cacheRefreshTime time.Duration, mockEnabled bool) *Client { - c := cache.New(cache.NoExpiration, cache.NoExpiration) // Don't expire data _or_ clean it up - +func NewClient(ctx context.Context, cedarHost string, cedarAPIKey string, cedarAPIVersion string, mockEnabled bool) *Client { hc := http.Client{ Transport: &loggingTransport{ logger: appcontext.ZLogger(ctx), @@ -99,8 +96,7 @@ func NewClient(ctx context.Context, cedarHost string, cedarAPIKey string, cedarA ), strfmt.Default, ), - hc: &hc, - cache: c, + hc: &hc, } return client @@ -112,23 +108,4 @@ type Client struct { auth runtime.ClientAuthInfoWriter sdk *apiclient.CEDARCoreAPI hc *http.Client - cache *cache.Cache } - -// startCacheRefresh starts a goroutine that will run `populateCache` based on cacheRefreshTime. -// startCacheRefresh returns no errors, and only logs when something goes wrong. -// Upon being called, startCacheRefresh will populate the cache once immediately, then again at an interval specificed by cacheRefreshTime. -// func (c *Client) startCacheRefresh(ctx context.Context, cacheRefreshTime time.Duration, populateCache func(context.Context) error) { -// ticker := time.NewTicker(cacheRefreshTime) -// go func(ctx context.Context) { -// for { -// err := populateCache(ctx) -// if err != nil { -// // This is a Warn() instead of Error() as it happens somewhat frequently, and doesn't necessarily warrant immediate attention -// appcontext.ZLogger(ctx).Warn("Failed to refresh cache", zap.Error(err)) -// } -// // Wait for the ticker. This will block the current goroutine until the ticker sends a message over the channel -// <-ticker.C -// } -// }(ctx) -// } diff --git a/pkg/cedar/core/client_test.go b/pkg/cedar/core/client_test.go index e288d3411e..cf848d42f5 100644 --- a/pkg/cedar/core/client_test.go +++ b/pkg/cedar/core/client_test.go @@ -3,7 +3,6 @@ package cedarcore import ( "context" "testing" - "time" "github.com/stretchr/testify/suite" "go.uber.org/zap" @@ -28,7 +27,7 @@ func (s *ClientTestSuite) TestClient() { ctx := appcontext.WithLogger(context.Background(), s.logger) s.Run("Instantiation successful", func() { - c := NewClient(ctx, "fake", "fake", "1.0.0", time.Minute, true) + c := NewClient(ctx, "fake", "fake", "1.0.0", true) s.NotNil(c) }) } diff --git a/pkg/cedar/core/system_summary_test.go b/pkg/cedar/core/system_summary_test.go index cbb23516b4..775b7a2ea7 100644 --- a/pkg/cedar/core/system_summary_test.go +++ b/pkg/cedar/core/system_summary_test.go @@ -3,7 +3,6 @@ package cedarcore import ( "context" "testing" - "time" "github.com/stretchr/testify/suite" "go.uber.org/zap" @@ -29,7 +28,7 @@ func (s *SystemSummaryTestSuite) TestGetSystemSummary() { ctx := appcontext.WithLogger(context.Background(), s.logger) s.Run("LD defaults protects invocation of GetSystemSummary", func() { - c := NewClient(ctx, "fake", "fake", "1.0.0", time.Minute, true) + c := NewClient(ctx, "fake", "fake", "1.0.0", true) resp, err := c.GetSystemSummary(ctx) s.NoError(err) @@ -41,7 +40,7 @@ func (s *SystemSummaryTestSuite) TestGetSystemSummary() { }) s.Run("Retrieves filtered list when EUA filter is present", func() { - c := NewClient(ctx, "fake", "fake", "1.0.0", time.Minute, true) + c := NewClient(ctx, "fake", "fake", "1.0.0", true) resp, err := c.GetSystemSummary(ctx, WithEuaIDFilter("USR1")) s.NoError(err) @@ -53,7 +52,7 @@ func (s *SystemSummaryTestSuite) TestGetSystemSummary() { }) s.Run("Retrieves filtered list when Sub-System filter is present", func() { - c := NewClient(ctx, "fake", "fake", "1.0.0", time.Minute, true) + c := NewClient(ctx, "fake", "fake", "1.0.0", true) resp, err := c.GetSystemSummary(ctx, WithSubSystems("1")) s.NoError(err) @@ -69,7 +68,7 @@ func (s *SystemSummaryTestSuite) TestGetSystem() { ctx := appcontext.WithLogger(context.Background(), s.logger) s.Run("LD defaults protects invocation of GetSystem", func() { - c := NewClient(ctx, "fake", "fake", "1.0.0", time.Minute, true) + c := NewClient(ctx, "fake", "fake", "1.0.0", true) _, err := c.GetSystem(ctx, "fake") s.NoError(err) diff --git a/pkg/graph/schema.resolvers_test.go b/pkg/graph/schema.resolvers_test.go index 3c07c4afa4..be8508c029 100644 --- a/pkg/graph/schema.resolvers_test.go +++ b/pkg/graph/schema.resolvers_test.go @@ -5,7 +5,6 @@ import ( "fmt" "net/url" "testing" - "time" "github.com/99designs/gqlgen/client" "github.com/99designs/gqlgen/graphql" @@ -148,7 +147,7 @@ func TestGraphQLTestSuite(t *testing.T) { } oktaAPIClient := local.NewOktaAPIClient() - cedarCoreClient := cedarcore.NewClient(appcontext.WithLogger(context.Background(), logger), "fake", "fake", "1.0.0", time.Minute, true) + cedarCoreClient := cedarcore.NewClient(appcontext.WithLogger(context.Background(), logger), "fake", "fake", "1.0.0", true) directives := generated.DirectiveRoot{HasRole: func(ctx context.Context, obj interface{}, next graphql.Resolver, role model.Role) (res interface{}, err error) { return next(ctx) diff --git a/pkg/server/routes.go b/pkg/server/routes.go index c5dff3285b..dd15f0db65 100644 --- a/pkg/server/routes.go +++ b/pkg/server/routes.go @@ -124,10 +124,9 @@ func (s *Server) routes( // set up CEDAR core API client coreClient := cedarcore.NewClient( appcontext.WithLogger(context.Background(), s.logger), - s.Config.GetString(appconfig.CEDARAPIURL), + s.Config.GetString(appconfig.CEDARPROXYURL), s.Config.GetString(appconfig.CEDARAPIKey), s.Config.GetString(appconfig.CEDARCoreAPIVersion), - s.Config.GetDuration(appconfig.CEDARCacheIntervalKey), s.Config.GetBool(appconfig.CEDARCoreMock), ) From 3955dde9544f02525db8c4126d437a72027f8831 Mon Sep 17 00:00:00 2001 From: Lee Warrick Date: Wed, 8 May 2024 14:51:43 -0400 Subject: [PATCH 18/20] go.mod change for go-cache --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 70712f48e5..0db198f7b0 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,6 @@ require ( github.com/lib/pq v1.10.9 github.com/mitchellh/mapstructure v1.5.0 github.com/okta/okta-jwt-verifier-golang v1.3.1 - github.com/patrickmn/go-cache v2.1.0+incompatible github.com/pquerna/otp v1.4.0 github.com/samber/lo v1.39.0 github.com/spf13/cobra v1.8.0 @@ -46,6 +45,7 @@ require ( github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/termenv v0.15.2 // indirect + github.com/patrickmn/go-cache v2.1.0+incompatible // indirect github.com/rivo/uniseg v0.4.6 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect From 32f011ab43d228e4df364ccc7185873eff1a5363 Mon Sep 17 00:00:00 2001 From: Lee Warrick Date: Thu, 9 May 2024 12:33:52 -0400 Subject: [PATCH 19/20] add once protection for client --- pkg/cedar/core/client.go | 60 ++++++++++++++++++-------------- pkg/cedar/core/system_summary.go | 1 - 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/pkg/cedar/core/client.go b/pkg/cedar/core/client.go index 0c32bfdd9b..7807e3325a 100644 --- a/pkg/cedar/core/client.go +++ b/pkg/cedar/core/client.go @@ -3,6 +3,7 @@ package cedarcore import ( "context" "net/http" + "sync" "time" "github.com/go-openapi/runtime" @@ -43,7 +44,11 @@ func (t *loggingTransport) RoundTrip(r *http.Request) (*http.Response, error) { return resp, err } -var cedarPath string +var ( + cedarPath string + client *Client + clientOnce sync.Once +) func PurgeCacheByPath(ctx context.Context, path string) error { req, err := http.NewRequest("PURGE", cedarPath+path, nil) @@ -70,35 +75,36 @@ func PurgeCacheByPath(ctx context.Context, path string) error { return nil } -// NewClient builds the type that holds a connection to the CEDAR Core API +// NewClient builds the type that holds a connection to the CEDAR Core func NewClient(ctx context.Context, cedarHost string, cedarAPIKey string, cedarAPIVersion string, mockEnabled bool) *Client { - hc := http.Client{ - Transport: &loggingTransport{ - logger: appcontext.ZLogger(ctx), - }, - } + clientOnce.Do(func() { + hc := http.Client{ + Transport: &loggingTransport{ + logger: appcontext.ZLogger(ctx), + }, + } - basePath := "/gateway/CEDAR Core API/" + cedarAPIVersion - cedarPath = "http://" + cedarHost + basePath - client := &Client{ - mockEnabled: mockEnabled, - auth: httptransport.APIKeyAuth( - "x-Gateway-APIKey", - "header", - cedarAPIKey, - ), - sdk: apiclient.New( - httptransport.New( - cedarHost, - basePath, - []string{"http"}, - // apiclient.DefaultSchemes, + basePath := "/gateway/CEDAR Core API/" + cedarAPIVersion + cedarPath = "http://" + cedarHost + basePath + client = &Client{ + mockEnabled: mockEnabled, + auth: httptransport.APIKeyAuth( + "x-Gateway-APIKey", + "header", + cedarAPIKey, ), - strfmt.Default, - ), - hc: &hc, - } - + sdk: apiclient.New( + httptransport.New( + cedarHost, + basePath, + []string{"http"}, + // apiclient.DefaultSchemes, + ), + strfmt.Default, + ), + hc: &hc, + } + }) return client } diff --git a/pkg/cedar/core/system_summary.go b/pkg/cedar/core/system_summary.go index 3fb095a518..e6e3abada2 100644 --- a/pkg/cedar/core/system_summary.go +++ b/pkg/cedar/core/system_summary.go @@ -48,7 +48,6 @@ func (c *Client) GetSystemSummary(ctx context.Context, opts ...systemSummaryPara // Make the API call resp, err := c.sdk.System.SystemSummaryFindList(params, c.auth) if err != nil { - fmt.Println(err) return []*models.CedarSystem{}, err } From b3cd2347ffa571500dc0e5bb9950ef0a13912ed0 Mon Sep 17 00:00:00 2001 From: Lee Warrick Date: Thu, 9 May 2024 12:39:20 -0400 Subject: [PATCH 20/20] add comments --- pkg/cedar/core/client.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pkg/cedar/core/client.go b/pkg/cedar/core/client.go index 7807e3325a..fce9f4de3e 100644 --- a/pkg/cedar/core/client.go +++ b/pkg/cedar/core/client.go @@ -50,6 +50,7 @@ var ( clientOnce sync.Once ) +// Purges Proxy Cache by URL using a given path func PurgeCacheByPath(ctx context.Context, path string) error { req, err := http.NewRequest("PURGE", cedarPath+path, nil) logger := appcontext.ZLogger(ctx) @@ -75,7 +76,7 @@ func PurgeCacheByPath(ctx context.Context, path string) error { return nil } -// NewClient builds the type that holds a connection to the CEDAR Core +// NewClient builds the type that holds a connection to the CEDAR Core API func NewClient(ctx context.Context, cedarHost string, cedarAPIKey string, cedarAPIVersion string, mockEnabled bool) *Client { clientOnce.Do(func() { hc := http.Client{