From 646adbcc5134760a863e2615c9a7f7df5e17d3d2 Mon Sep 17 00:00:00 2001 From: bsouza Date: Sun, 15 Sep 2024 23:12:01 +0000 Subject: [PATCH] Support for multiple repos --- jfrog-token/.npmrc.tftpl | 5 ++ jfrog-token/main.test.ts | 102 ++++++++++++++++++++++++++++++++++--- jfrog-token/main.tf | 88 ++++++++++++++++++++++---------- jfrog-token/pip.conf.tftpl | 6 +++ jfrog-token/run.sh | 51 +++++++++++-------- 5 files changed, 198 insertions(+), 54 deletions(-) create mode 100644 jfrog-token/.npmrc.tftpl create mode 100644 jfrog-token/pip.conf.tftpl diff --git a/jfrog-token/.npmrc.tftpl b/jfrog-token/.npmrc.tftpl new file mode 100644 index 00000000..8bb9fb8f --- /dev/null +++ b/jfrog-token/.npmrc.tftpl @@ -0,0 +1,5 @@ +email=${ARTIFACTORY_EMAIL} +%{ for REPO in REPOS ~} +${REPO.SCOPE}registry=${JFROG_URL}/artifactory/api/npm/${REPO.NAME} +//${JFROG_HOST}/artifactory/api/npm/${REPO.NAME}/:_authToken=${ARTIFACTORY_ACCESS_TOKEN} +%{ endfor ~} diff --git a/jfrog-token/main.test.ts b/jfrog-token/main.test.ts index b3b8df98..d71a4862 100644 --- a/jfrog-token/main.test.ts +++ b/jfrog-token/main.test.ts @@ -1,8 +1,10 @@ import { serve } from "bun"; -import { describe } from "bun:test"; +import { describe, expect, it } from "bun:test"; import { createJSONResponse, + findResourceInstance, runTerraformInit, + runTerraformApply, testRequiredVariables, } from "../test"; @@ -32,10 +34,98 @@ describe("jfrog-token", async () => { port: 0, }); - testRequiredVariables(import.meta.dir, { - agent_id: "some-agent-id", - jfrog_url: "http://" + fakeFrogHost.hostname + ":" + fakeFrogHost.port, - artifactory_access_token: "XXXX", - package_managers: "{}", + const fakeFrogHostAndPort = `${fakeFrogHost.hostname}:${fakeFrogHost.port}`; + const fakeFrogUrl = `http://${fakeFrogHostAndPort}`; + + it("can run apply with required variables", async () => { + testRequiredVariables(import.meta.dir, { + agent_id: "some-agent-id", + jfrog_url: fakeFrogUrl, + artifactory_access_token: "XXXX", + package_managers: "{}", + }); + }); + + it("generates an npmrc with scoped repos", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "some-agent-id", + jfrog_url: fakeFrogUrl, + artifactory_access_token: "XXXX", + package_managers: JSON.stringify({ + npm: ["global", "@foo:foo", "@bar:bar"], + }), + }); + const coderScript = findResourceInstance(state, "coder_script"); + const npmrcStanza = `cat << EOF > ~/.npmrc +email=default@example.com +registry=${fakeFrogUrl}/artifactory/api/npm/global +//${fakeFrogHostAndPort}/artifactory/api/npm/global/:_authToken=xxx +@foo:registry=${fakeFrogUrl}/artifactory/api/npm/foo +//${fakeFrogHostAndPort}/artifactory/api/npm/foo/:_authToken=xxx +@bar:registry=${fakeFrogUrl}/artifactory/api/npm/bar +//${fakeFrogHostAndPort}/artifactory/api/npm/bar/:_authToken=xxx + +EOF`; + expect(coderScript.script).toContain(npmrcStanza); + expect(coderScript.script).toContain('jf npmc --global --repo-resolve "global"'); + expect(coderScript.script).toContain('if [ -z "YES" ]; then\n not_configured npm'); + }); + + it("generates a pip config with extra-indexes", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "some-agent-id", + jfrog_url: fakeFrogUrl, + artifactory_access_token: "XXXX", + package_managers: JSON.stringify({ + pypi: ["global", "foo", "bar"], + }), + }); + const coderScript = findResourceInstance(state, "coder_script"); + const pipStanza = `cat << EOF > ~/.pip/pip.conf +[global] +index-url = https://default:xxx@${fakeFrogHostAndPort}/artifactory/api/pypi/global/simple +extra-index-url = + https://default:xxx@${fakeFrogHostAndPort}/artifactory/api/pypi/foo/simple + https://default:xxx@${fakeFrogHostAndPort}/artifactory/api/pypi/bar/simple + +EOF`; + expect(coderScript.script).toContain(pipStanza); + expect(coderScript.script).toContain('jf pipc --global --repo-resolve "global"'); + expect(coderScript.script).toContain('if [ -z "YES" ]; then\n not_configured pypi'); + }); + + it("registers multiple docker repos", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "some-agent-id", + jfrog_url: fakeFrogUrl, + artifactory_access_token: "XXXX", + package_managers: JSON.stringify({ + docker: ["foo.jfrog.io", "bar.jfrog.io", "baz.jfrog.io"], + }), + }); + const coderScript = findResourceInstance(state, "coder_script"); + const dockerStanza = `register_docker "foo.jfrog.io" +register_docker "bar.jfrog.io" +register_docker "baz.jfrog.io"`; + expect(coderScript.script).toContain(dockerStanza); + expect(coderScript.script).toContain('if [ -z "YES" ]; then\n not_configured docker'); + }); + + it("sets goproxy with multiple repos", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "some-agent-id", + jfrog_url: fakeFrogUrl, + artifactory_access_token: "XXXX", + package_managers: JSON.stringify({ + go: ["foo", "bar", "baz"], + }), + }); + const proxyEnv = findResourceInstance(state, "coder_env", "goproxy"); + const proxies = `https://default:xxx@${fakeFrogHostAndPort}/artifactory/api/go/foo,https://default:xxx@${fakeFrogHostAndPort}/artifactory/api/go/bar,https://default:xxx@${fakeFrogHostAndPort}/artifactory/api/go/baz`; + expect(proxyEnv["value"]).toEqual(proxies); + + const coderScript = findResourceInstance(state, "coder_script"); + expect(coderScript.script).toContain('jf goc --global --repo-resolve "foo"'); + expect(coderScript.script).toContain('if [ -z "YES" ]; then\n not_configured go'); }); }); diff --git a/jfrog-token/main.tf b/jfrog-token/main.tf index 90dad613..f6f5f5b0 100644 --- a/jfrog-token/main.tf +++ b/jfrog-token/main.tf @@ -80,23 +80,51 @@ variable "configure_code_server" { } variable "package_managers" { - type = map(string) - description = < /dev/null 2>&1; then echo "✅ JFrog CLI is already installed, skipping installation." @@ -11,8 +26,7 @@ else sudo chmod 755 /usr/local/bin/jf fi -# The jf CLI checks $CI when determining whether to use interactive -# flows. +# The jf CLI checks $CI when determining whether to use interactive flows. export CI=true # Authenticate JFrog CLI with Artifactory. echo "${ARTIFACTORY_ACCESS_TOKEN}" | jf c add --access-token-stdin --url "${JFROG_URL}" --overwrite "${JFROG_SERVER_ID}" @@ -20,52 +34,47 @@ echo "${ARTIFACTORY_ACCESS_TOKEN}" | jf c add --access-token-stdin --url "${JFRO jf c use "${JFROG_SERVER_ID}" # Configure npm to use the Artifactory "npm" repository. -if [ -z "${REPOSITORY_NPM}" ]; then - echo "🤔 no npm repository is set, skipping npm configuration." - echo "You can configure an npm repository by providing the a key for 'npm' in the 'package_managers' input." +if [ -z "${HAS_NPM}" ]; then + not_configured npm else echo "📦 Configuring npm..." jf npmc --global --repo-resolve "${REPOSITORY_NPM}" cat << EOF > ~/.npmrc -email=${ARTIFACTORY_EMAIL} -registry=${JFROG_URL}/artifactory/api/npm/${REPOSITORY_NPM} +${NPMRC} EOF - echo "//${JFROG_HOST}/artifactory/api/npm/${REPOSITORY_NPM}/:_authToken=${ARTIFACTORY_ACCESS_TOKEN}" >> ~/.npmrc + echo "🥳 Configuration complete!" fi # Configure the `pip` to use the Artifactory "python" repository. -if [ -z "${REPOSITORY_PYPI}" ]; then - echo "🤔 no pypi repository is set, skipping pip configuration." - echo "You can configure a pypi repository by providing the a key for 'pypi' in the 'package_managers' input." +if [ -z "${HAS_PYPI}" ]; then + not_configured pypi else echo "🐍 Configuring pip..." jf pipc --global --repo-resolve "${REPOSITORY_PYPI}" mkdir -p ~/.pip cat << EOF > ~/.pip/pip.conf -[global] -index-url = https://${ARTIFACTORY_USERNAME}:${ARTIFACTORY_ACCESS_TOKEN}@${JFROG_HOST}/artifactory/api/pypi/${REPOSITORY_PYPI}/simple +${PIP_CONF} EOF + echo "🥳 Configuration complete!" fi # Configure Artifactory "go" repository. -if [ -z "${REPOSITORY_GO}" ]; then - echo "🤔 no go repository is set, skipping go configuration." - echo "You can configure a go repository by providing the a key for 'go' in the 'package_managers' input." +if [ -z "${HAS_GO}" ]; then + not_configured go else echo "🐹 Configuring go..." jf goc --global --repo-resolve "${REPOSITORY_GO}" + echo "🥳 Configuration complete!" fi -echo "🥳 Configuration complete!" # Configure the JFrog CLI to use the Artifactory "docker" repository. -if [ -z "${REPOSITORY_DOCKER}" ]; then - echo "🤔 no docker repository is set, skipping docker configuration." - echo "You can configure a docker repository by providing the a key for 'docker' in the 'package_managers' input." +if [ -z "${HAS_DOCKER}" ]; then + not_configured docker else if command -v docker > /dev/null 2>&1; then echo "🔑 Configuring 🐳 docker credentials..." mkdir -p ~/.docker - echo -n "${ARTIFACTORY_ACCESS_TOKEN}" | docker login ${JFROG_HOST} --username ${ARTIFACTORY_USERNAME} --password-stdin + ${REGISTER_DOCKER} else echo "🤔 no docker is installed, skipping docker configuration." fi