diff --git a/registry/coder/modules/jfrog-oauth/README.md b/registry/coder/modules/jfrog-oauth/README.md index a1b9d295..4bb9e633 100644 --- a/registry/coder/modules/jfrog-oauth/README.md +++ b/registry/coder/modules/jfrog-oauth/README.md @@ -28,12 +28,13 @@ module "jfrog" { go = ["go", "another-go-repo"] pypi = ["pypi", "extra-index-pypi"] docker = ["example-docker-staging.jfrog.io", "example-docker-production.jfrog.io"] + maven = ["maven-local", "maven-central"] } } ``` > Note -> This module does not install `npm`, `go`, `pip`, etc but only configure them. You need to handle the installation of these tools yourself. +> This module does not install `npm`, `go`, `pip`, `maven`, etc but only configure them. You need to handle the installation of these tools yourself. ## Prerequisites @@ -68,6 +69,35 @@ jf pip install requests pip install requests ``` +### Configure Maven package manager + +Configure Maven to fetch packages from Artifactory repositories. + +```tf +module "jfrog" { + count = data.coder_workspace.me.start_count + source = "registry.coder.com/coder/jfrog-oauth/coder" + version = "1.0.19" + agent_id = coder_agent.example.id + jfrog_url = "https://example.jfrog.io" + username_field = "username" + + package_managers = { + maven = ["maven-local", "maven-central"] + } +} +``` + +You should now be able to install packages from Artifactory using both the `jf mvn` and `mvn` command. + +```shell +jf mvn install +``` + +```shell +mvn install +``` + ### Configure code-server with JFrog extension The [JFrog extension](https://open-vsx.org/extension/JFrog/jfrog-vscode-extension) for VS Code allows you to interact with Artifactory from within the IDE. @@ -82,9 +112,10 @@ module "jfrog" { username_field = "username" # If you are using GitHub to login to both Coder and Artifactory, use username_field = "username" configure_code_server = true # Add JFrog extension configuration for code-server package_managers = { - npm = ["npm"] - go = ["go"] - pypi = ["pypi"] + npm = ["npm"] + go = ["go"] + pypi = ["pypi"] + maven = ["maven-local"] } } ``` diff --git a/registry/coder/modules/jfrog-oauth/main.test.ts b/registry/coder/modules/jfrog-oauth/main.test.ts index 20ace697..48711dcd 100644 --- a/registry/coder/modules/jfrog-oauth/main.test.ts +++ b/registry/coder/modules/jfrog-oauth/main.test.ts @@ -126,4 +126,98 @@ EOF`; 'if [ -z "YES" ]; then\n not_configured go', ); }); + + it("generates maven settings with multiple repos", async () => { + const state = await runTerraformApply(import.meta.dir, { + agent_id: "some-agent-id", + jfrog_url: fakeFrogUrl, + package_managers: JSON.stringify({ + maven: ["maven-local", "maven-central"], + }), + }); + const coderScript = findResourceInstance(state, "coder_script"); + const mavenStanza = `cat << EOF > ~/.m2/settings.xml + + + + + maven-local + ${user} + + + + maven-central + ${user} + + + + + + artifactory + + + maven-local + maven-local + http://localhost:8081/artifactory/maven-local + + true + + + true + + + + maven-central + maven-central + http://localhost:8081/artifactory/maven-central + + true + + + true + + + + + + maven-local + maven-local + http://localhost:8081/artifactory/maven-local + + true + + + true + + + + maven-central + maven-central + http://localhost:8081/artifactory/maven-central + + true + + + true + + + + + + + artifactory + + +EOF`; + expect(coderScript.script).toContain(mavenStanza); + expect(coderScript.script).toContain( + 'jf mvnc --global --repo-resolve "maven-local" --repo-deploy "maven-local"', + ); + expect(coderScript.script).toContain( + 'if [ -z "YES" ]; then\n not_configured maven', + ); + }); }); diff --git a/registry/coder/modules/jfrog-oauth/main.tf b/registry/coder/modules/jfrog-oauth/main.tf index 0bc22568..e65029c8 100644 --- a/registry/coder/modules/jfrog-oauth/main.tf +++ b/registry/coder/modules/jfrog-oauth/main.tf @@ -58,6 +58,7 @@ variable "package_managers" { go = optional(list(string), []) pypi = optional(list(string), []) docker = optional(list(string), []) + maven = optional(list(string), []) }) description = <<-EOF A map of package manager names to their respective artifactory repositories. Unused package managers can be omitted. @@ -67,6 +68,7 @@ variable "package_managers" { go = ["YOUR_GO_REPO_KEY", "ANOTHER_GO_REPO_KEY"] pypi = ["YOUR_PYPI_REPO_KEY", "ANOTHER_PYPI_REPO_KEY"] docker = ["YOUR_DOCKER_REPO_KEY", "ANOTHER_DOCKER_REPO_KEY"] + maven = ["YOUR_MAVEN_REPO_KEY", "ANOTHER_MAVEN_REPO_KEY"] } EOF } @@ -90,7 +92,7 @@ locals { { REPOS = [ for r in var.package_managers.npm : - strcontains(r, ":") ? zipmap(["SCOPE", "NAME"], ["${split(":", r)[0]}:", split(":", r)[1]]) : { SCOPE = "", NAME = r } + length(split(":", r)) > 1 ? zipmap(["SCOPE", "NAME"], ["${split(":", r)[0]}:", split(":", r)[1]]) : { SCOPE = "", NAME = r } ] } ) @@ -98,6 +100,9 @@ locals { pip_conf = templatefile( "${path.module}/pip.conf.tftpl", merge(local.common_values, { REPOS = var.package_managers.pypi }) ) + maven_settings = templatefile( + "${path.module}/settings.xml.tftpl", merge(local.common_values, { REPOS = var.package_managers.maven }) + ) } data "coder_workspace" "me" {} @@ -125,6 +130,9 @@ resource "coder_script" "jfrog" { REPOSITORY_PYPI = try(element(var.package_managers.pypi, 0), "") HAS_DOCKER = length(var.package_managers.docker) == 0 ? "" : "YES" REGISTER_DOCKER = join("\n", formatlist("register_docker \"%s\"", var.package_managers.docker)) + HAS_MAVEN = length(var.package_managers.maven) == 0 ? "" : "YES" + MAVEN_SETTINGS = local.maven_settings + REPOSITORY_MAVEN = try(element(var.package_managers.maven, 0), "") } )) run_on_start = true diff --git a/registry/coder/modules/jfrog-oauth/run.sh b/registry/coder/modules/jfrog-oauth/run.sh index 7d36e47c..800a35de 100644 --- a/registry/coder/modules/jfrog-oauth/run.sh +++ b/registry/coder/modules/jfrog-oauth/run.sh @@ -81,6 +81,19 @@ else fi fi +# Configure Maven to use the Artifactory "maven" repository. +if [ -z "${HAS_MAVEN}" ]; then + not_configured maven +else + echo "☕ Configuring maven..." + jf mvnc --global --repo-resolve "${REPOSITORY_MAVEN}" --repo-deploy "${REPOSITORY_MAVEN}" + mkdir -p ~/.m2 + cat << EOF > ~/.m2/settings.xml +${MAVEN_SETTINGS} +EOF + config_complete +fi + # Install the JFrog vscode extension for code-server. if [ "${CONFIGURE_CODE_SERVER}" == "true" ]; then while ! [ -x /tmp/code-server/bin/code-server ]; do diff --git a/registry/coder/modules/jfrog-oauth/settings.xml.tftpl b/registry/coder/modules/jfrog-oauth/settings.xml.tftpl new file mode 100644 index 00000000..bb1bd13d --- /dev/null +++ b/registry/coder/modules/jfrog-oauth/settings.xml.tftpl @@ -0,0 +1,53 @@ + + + +%{ for REPO in REPOS ~} + + ${REPO} + ${ARTIFACTORY_USERNAME} + ${ARTIFACTORY_ACCESS_TOKEN} + +%{ endfor ~} + + + + artifactory + +%{ for REPO in REPOS ~} + + ${REPO} + ${REPO} + ${JFROG_URL}/artifactory/${REPO} + + true + + + true + + +%{ endfor ~} + + +%{ for REPO in REPOS ~} + + ${REPO} + ${REPO} + ${JFROG_URL}/artifactory/${REPO} + + true + + + true + + +%{ endfor ~} + + + + + artifactory + + \ No newline at end of file diff --git a/registry/coder/modules/jfrog-token/README.md b/registry/coder/modules/jfrog-token/README.md index 26d98e61..35c2194e 100644 --- a/registry/coder/modules/jfrog-token/README.md +++ b/registry/coder/modules/jfrog-token/README.md @@ -24,6 +24,7 @@ module "jfrog" { go = ["go", "another-go-repo"] pypi = ["pypi", "extra-index-pypi"] docker = ["example-docker-staging.jfrog.io", "example-docker-production.jfrog.io"] + maven = ["maven-local", "maven-central"] } } ``` @@ -31,13 +32,13 @@ module "jfrog" { For detailed instructions, please see this [guide](https://coder.com/docs/v2/latest/guides/artifactory-integration#jfrog-token) on the Coder documentation. > Note -> This module does not install `npm`, `go`, `pip`, etc but only configure them. You need to handle the installation of these tools yourself. +> This module does not install `npm`, `go`, `pip`, `maven`, etc but only configure them. You need to handle the installation of these tools yourself. ![JFrog](../../.images/jfrog.png) ## Examples -### Configure npm, go, and pypi to use Artifactory local repositories +### Configure npm, go, pypi, and maven to use Artifactory local repositories ```tf module "jfrog" { @@ -47,25 +48,28 @@ module "jfrog" { jfrog_url = "https://YYYY.jfrog.io" artifactory_access_token = var.artifactory_access_token # An admin access token package_managers = { - npm = ["npm-local"] - go = ["go-local"] - pypi = ["pypi-local"] + npm = ["npm-local"] + go = ["go-local"] + pypi = ["pypi-local"] + maven = ["maven-local"] } } ``` -You should now be able to install packages from Artifactory using both the `jf npm`, `jf go`, `jf pip` and `npm`, `go`, `pip` commands. +You should now be able to install packages from Artifactory using both the `jf npm`, `jf go`, `jf pip`, `jf mvn` and `npm`, `go`, `pip`, `mvn` commands. ```shell jf npm install prettier jf go get github.com/golang/example/hello jf pip install requests +jf mvn install ``` ```shell npm install prettier go get github.com/golang/example/hello pip install requests +mvn install ``` ### Configure code-server with JFrog extension @@ -81,9 +85,10 @@ module "jfrog" { artifactory_access_token = var.artifactory_access_token configure_code_server = true # Add JFrog extension configuration for code-server package_managers = { - npm = ["npm"] - go = ["go"] - pypi = ["pypi"] + npm = ["npm"] + go = ["go"] + pypi = ["pypi"] + maven = ["maven-local"] } } ``` diff --git a/registry/coder/modules/jfrog-token/main.tf b/registry/coder/modules/jfrog-token/main.tf index 720e2d8c..a9d249fe 100644 --- a/registry/coder/modules/jfrog-token/main.tf +++ b/registry/coder/modules/jfrog-token/main.tf @@ -91,6 +91,7 @@ variable "package_managers" { go = optional(list(string), []) pypi = optional(list(string), []) docker = optional(list(string), []) + maven = optional(list(string), []) }) description = <<-EOF A map of package manager names to their respective artifactory repositories. Unused package managers can be omitted. @@ -100,6 +101,7 @@ variable "package_managers" { go = ["YOUR_GO_REPO_KEY", "ANOTHER_GO_REPO_KEY"] pypi = ["YOUR_PYPI_REPO_KEY", "ANOTHER_PYPI_REPO_KEY"] docker = ["YOUR_DOCKER_REPO_KEY", "ANOTHER_DOCKER_REPO_KEY"] + maven = ["YOUR_MAVEN_REPO_KEY", "ANOTHER_MAVEN_REPO_KEY"] } EOF } @@ -123,7 +125,7 @@ locals { { REPOS = [ for r in var.package_managers.npm : - strcontains(r, ":") ? zipmap(["SCOPE", "NAME"], ["${split(":", r)[0]}:", split(":", r)[1]]) : { SCOPE = "", NAME = r } + length(split(":", r)) > 1 ? zipmap(["SCOPE", "NAME"], ["${split(":", r)[0]}:", split(":", r)[1]]) : { SCOPE = "", NAME = r } ] } ) @@ -131,6 +133,9 @@ locals { pip_conf = templatefile( "${path.module}/pip.conf.tftpl", merge(local.common_values, { REPOS = var.package_managers.pypi }) ) + maven_settings = templatefile( + "${path.module}/settings.xml.tftpl", merge(local.common_values, { REPOS = var.package_managers.maven }) + ) } # Configure the Artifactory provider @@ -171,6 +176,9 @@ resource "coder_script" "jfrog" { REPOSITORY_PYPI = try(element(var.package_managers.pypi, 0), "") HAS_DOCKER = length(var.package_managers.docker) == 0 ? "" : "YES" REGISTER_DOCKER = join("\n", formatlist("register_docker \"%s\"", var.package_managers.docker)) + HAS_MAVEN = length(var.package_managers.maven) == 0 ? "" : "YES" + MAVEN_SETTINGS = local.maven_settings + REPOSITORY_MAVEN = try(element(var.package_managers.maven, 0), "") } )) run_on_start = true diff --git a/registry/coder/modules/jfrog-token/run.sh b/registry/coder/modules/jfrog-token/run.sh index d3a1a74c..1387586e 100644 --- a/registry/coder/modules/jfrog-token/run.sh +++ b/registry/coder/modules/jfrog-token/run.sh @@ -80,6 +80,19 @@ else fi fi +# Configure Maven to use the Artifactory "maven" repository. +if [ -z "${HAS_MAVEN}" ]; then + not_configured maven +else + echo "☕ Configuring maven..." + jf mvnc --global --repo-resolve "${REPOSITORY_MAVEN}" --repo-deploy "${REPOSITORY_MAVEN}" + mkdir -p ~/.m2 + cat << EOF > ~/.m2/settings.xml +${MAVEN_SETTINGS} +EOF + config_complete +fi + # Install the JFrog vscode extension for code-server. if [ "${CONFIGURE_CODE_SERVER}" == "true" ]; then while ! [ -x /tmp/code-server/bin/code-server ]; do diff --git a/registry/coder/modules/jfrog-token/settings.xml.tftpl b/registry/coder/modules/jfrog-token/settings.xml.tftpl new file mode 100644 index 00000000..bb1bd13d --- /dev/null +++ b/registry/coder/modules/jfrog-token/settings.xml.tftpl @@ -0,0 +1,53 @@ + + + +%{ for REPO in REPOS ~} + + ${REPO} + ${ARTIFACTORY_USERNAME} + ${ARTIFACTORY_ACCESS_TOKEN} + +%{ endfor ~} + + + + artifactory + +%{ for REPO in REPOS ~} + + ${REPO} + ${REPO} + ${JFROG_URL}/artifactory/${REPO} + + true + + + true + + +%{ endfor ~} + + +%{ for REPO in REPOS ~} + + ${REPO} + ${REPO} + ${JFROG_URL}/artifactory/${REPO} + + true + + + true + + +%{ endfor ~} + + + + + artifactory + + \ No newline at end of file