diff --git a/jfrog-oauth/README.md b/jfrog-oauth/README.md index d6785b39..663c8ff8 100644 --- a/jfrog-oauth/README.md +++ b/jfrog-oauth/README.md @@ -21,7 +21,6 @@ module "jfrog" { source = "https://registry.coder.com/modules/jfrog-oauth" agent_id = coder_agent.example.id jfrog_url = "https://jfrog.example.com" - auth_method = "oauth" username_field = "username" # If you are using GitHub to login to both Coder and Artifactory, use username_field = "username" package_managers = { "npm": "npm", @@ -106,6 +105,25 @@ jf pip install requests pip install requests ``` +### 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. + +```hcl +module "jfrog" { + source = "https://registry.coder.com/modules/jfrog-oauth" + agent_id = coder_agent.example.id + jfrog_url = "https://jfrog.example.com" + 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" + } +} +``` + ### Using the access token in other terraform resources JFrog Access token is also available as a terraform output. You can use it in other terraform resources. For example, you can use it to configure an [Artifactory docker registry](https://jfrog.com/help/r/jfrog-artifactory-documentation/docker-registry) with the [docker terraform provider](https://registry.terraform.io/providers/kreuzwerker/docker/latest/docs). diff --git a/jfrog-oauth/main.tf b/jfrog-oauth/main.tf index 8a81594c..9f05e56a 100644 --- a/jfrog-oauth/main.tf +++ b/jfrog-oauth/main.tf @@ -4,14 +4,19 @@ terraform { required_providers { coder = { source = "coder/coder" - version = ">= 0.12" + version = ">= 0.12.4" } } } variable "jfrog_url" { type = string - description = "JFrog instance URL. e.g. https://jfrog.example.com" + description = "JFrog instance URL. e.g. https://myartifactory.jfrog.io" + # ensue the URL is HTTPS or HTTP + validation { + condition = can(regex("^(https|http)://", var.jfrog_url)) + error_message = "jfrog_url must be a valid URL starting with either 'https://' or 'http://'" + } } variable "username_field" { @@ -35,22 +40,30 @@ variable "agent_id" { description = "The ID of a Coder agent." } +variable "configure_code_server" { + type = bool + description = "Set to true to configure code-server to use JFrog." + default = false +} + variable "package_managers" { type = map(string) description = < /dev/null 2>&1; then echo "✅ JFrog CLI is already installed, skipping installation." else echo "📦 Installing JFrog CLI..." - # Install the JFrog CLI. curl -fL https://install-cli.jfrog.io | sudo sh sudo chmod 755 /usr/local/bin/jf fi @@ -15,30 +14,31 @@ fi # The jf CLI checks $CI when determining whether to use interactive # flows. export CI=true -# Authenticate with the JFrog CLI. -jf c rm 0 || true -echo "${ARTIFACTORY_ACCESS_TOKEN}" | jf c add --access-token-stdin --url "${JFROG_URL}" 0 +# Authenticate JFrog CLI with Artifactory. +echo "${ARTIFACTORY_ACCESS_TOKEN}" | jf c add --access-token-stdin --url "${JFROG_URL}" --overwrite 0 +# Set the configured server as the default. +jf c use 0 +# Configure npm to use the Artifactory "npm" repository. if [ -z "${REPOSITORY_NPM}" ]; then - echo "🤔 REPOSITORY_NPM is not set, skipping npm configuration." + 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." else - # check if npm is installed and configure it to use the Artifactory "npm" repository. - if command -v npm > /dev/null 2>&1; then - echo "📦 Configuring npm..." - jf npmc --global --repo-resolve "${REPOSITORY_NPM}" - fi + echo "📦 Configuring npm..." + jf npmc --global --repo-resolve "${REPOSITORY_NPM}" cat << EOF > ~/.npmrc -email = ${ARTIFACTORY_EMAIL} -registry = ${JFROG_URL}/artifactory/api/npm/${REPOSITORY_NPM} +email=${ARTIFACTORY_EMAIL} +registry=${JFROG_URL}/artifactory/api/npm/${REPOSITORY_NPM} EOF - jf rt curl /api/npm/auth >> ~/.npmrc + echo "//${JFROG_HOST}/artifactory/api/npm/${REPOSITORY_NPM}/:_authToken=${ARTIFACTORY_ACCESS_TOKEN}" >> ~/.npmrc fi # Configure the `pip` to use the Artifactory "python" repository. if [ -z "${REPOSITORY_PYPI}" ]; then - echo "🤔 REPOSITORY_PYPI is not set, skipping pip configuration." + 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." else - echo "🐍 Configuring pip..." + echo "📦 Configuring pip..." jf pipc --global --repo-resolve "${REPOSITORY_PYPI}" mkdir -p ~/.pip cat << EOF > ~/.pip/pip.conf @@ -47,12 +47,76 @@ index-url = https://${ARTIFACTORY_USERNAME}:${ARTIFACTORY_ACCESS_TOKEN}@${JFROG_ EOF fi -# Set GOPROXY to use the Artifactory "go" repository. +# Configure Artifactory "go" repository. if [ -z "${REPOSITORY_GO}" ]; then - echo "🤔 REPOSITORY_GO is not set, skipping go configuration." + 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." else echo "🐹 Configuring go..." - jf go-config --global --repo-resolve "${REPOSITORY_GO}" - export GOPROXY="https://${ARTIFACTORY_USERNAME}:${ARTIFACTORY_ACCESS_TOKEN}@${JFROG_HOST}/artifactory/api/go/${REPOSITORY_GO}" + jf goc --global --repo-resolve "${REPOSITORY_GO}" 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." +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 + else + echo "🤔 no docker is installed, skipping docker configuration." + fi +fi + +# Install the JFrog vscode extension for code-server. +if [ "${CONFIGURE_CODE_SERVER}" == "true" ]; then + while ! [ -x /tmp/code-server/bin/code-server ]; do + counter=0 + if [ $counter -eq 60 ]; then + echo "Timed out waiting for /tmp/code-server/bin/code-server to be installed." + exit 1 + fi + echo "Waiting for /tmp/code-server/bin/code-server to be installed..." + sleep 1 + ((counter++)) + done + echo "📦 Installing JFrog extension..." + /tmp/code-server/bin/code-server --install-extension jfrog.jfrog-vscode-extension + echo "🥳 JFrog extension installed!" +else + echo "🤔 Skipping JFrog extension installation. Set configure_code_server to true to install the JFrog extension." +fi + +# Configure the JFrog CLI completion +echo "📦 Configuring JFrog CLI completion..." +# Get the user's shell +SHELLNAME=$(grep "^$USER" /etc/passwd | awk -F':' '{print $7}' | awk -F'/' '{print $NF}') +# Generate the completion script +jf completion $SHELLNAME --install +# Add the completion script to the user's shell profile +if [ "$SHELLNAME" == "bash" ] && [ -f ~/.bashrc ]; then + if ! grep -q "# jf CLI shell completion" ~/.bashrc; then + echo "" >> ~/.bashrc + echo "# BEGIN: jf CLI shell completion (added by coder module jfrog-oauth)" >> ~/.bashrc + echo 'source "$HOME/.jfrog/jfrog_bash_completion"' >> ~/.bashrc + echo "# END: jf CLI shell completion" >> ~/.bashrc + else + echo "🥳 ~/.bashrc already contains jf CLI shell completion configuration, skipping." + fi +elif [ "$SHELLNAME" == "zsh" ] && [ -f ~/.zshrc ]; then + if ! grep -q "# jf CLI shell completion" ~/.zshrc; then + echo "" >> ~/.zshrc + echo "# BEGIN: jf CLI shell completion (added by coder module jfrog-oauth)" >> ~/.zshrc + echo "autoload -Uz compinit" >> ~/.zshrc + echo "compinit" >> ~/.zshrc + echo 'source "$HOME/.jfrog/jfrog_zsh_completion"' >> ~/.zshrc + echo "# END: jf CLI shell completion" >> ~/.zshrc + else + echo "🥳 ~/.zshrc already contains jf CLI shell completion configuration, skipping." + fi +else + echo "🤔 ~/.bashrc or ~/.zshrc does not exist, skipping jf CLI shell completion configuration." +fi diff --git a/jfrog-token/README.md b/jfrog-token/README.md index 97e229d8..94a7ff9c 100644 --- a/jfrog-token/README.md +++ b/jfrog-token/README.md @@ -14,15 +14,15 @@ Install the JF CLI and authenticate package managers with Artifactory using Arti ```hcl module "jfrog" { - source = "https://registry.coder.com/modules/jfrog-token" - agent_id = coder_agent.example.id - jfrog_url = "https://XXXX.jfrog.io" - artifactory_access_token = var.artifactory_access_token - package_managers = { - "npm": "npm", - "go": "go", - "pypi": "pypi" - } + source = "https://registry.coder.com/modules/jfrog-token" + agent_id = coder_agent.example.id + jfrog_url = "https://XXXX.jfrog.io" + artifactory_access_token = var.artifactory_access_token + package_managers = { + "npm": "npm", + "go": "go", + "pypi": "pypi" + } } ``` @@ -30,8 +30,8 @@ Get a JFrog access token from your Artifactory instance. The token must be an [a ```hcl variable "artifactory_access_token" { - type = string - sensitive = true + type = string + sensitive = true } ``` @@ -46,15 +46,15 @@ variable "artifactory_access_token" { ```hcl module "jfrog" { - source = "https://registry.coder.com/modules/jfrog-token" - agent_id = coder_agent.example.id - 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" - } + source = "https://registry.coder.com/modules/jfrog-token" + agent_id = coder_agent.example.id + 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" + } } ``` @@ -72,6 +72,25 @@ go get github.com/golang/example/hello pip install requests ``` +### 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. + +```hcl +module "jfrog" { + source = "https://registry.coder.com/modules/jfrog-token" + agent_id = coder_agent.example.id + jfrog_url = "https://XXXX.jfrog.io" + 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" + } +} +``` + ### Using the access token in other terraform resources JFrog Access token is also available as a terraform output. You can use it in other terraform resources. For example, you can use it to configure an [Artifactory docker registry](https://jfrog.com/help/r/jfrog-artifactory-documentation/docker-registry) with the [docker terraform provider](https://registry.terraform.io/providers/kreuzwerker/docker/latest/docs). diff --git a/jfrog-token/main.tf b/jfrog-token/main.tf index d9aa55ff..7e63649d 100644 --- a/jfrog-token/main.tf +++ b/jfrog-token/main.tf @@ -4,18 +4,23 @@ terraform { required_providers { coder = { source = "coder/coder" - version = ">= 0.12" + version = ">= 0.12.4" } artifactory = { source = "registry.terraform.io/jfrog/artifactory" - version = "~> 9.8.0" + version = "~> 10.0.2" } } } variable "jfrog_url" { type = string - description = "JFrog instance URL. e.g. https://YYY.jfrog.io" + description = "JFrog instance URL. e.g. https://myartifactory.jfrog.io" + # ensue the URL is HTTPS or HTTP + validation { + condition = can(regex("^(https|http)://", var.jfrog_url)) + error_message = "jfrog_url must be a valid URL starting with either 'https://' or 'http://'" + } } variable "artifactory_access_token" { @@ -56,22 +61,30 @@ variable "agent_id" { description = "The ID of a Coder agent." } +variable "configure_code_server" { + type = bool + description = "Set to true to configure code-server to use JFrog." + default = false +} + variable "package_managers" { type = map(string) description = < /dev/null 2>&1; then echo "✅ JFrog CLI is already installed, skipping installation." else echo "📦 Installing JFrog CLI..." - # Install the JFrog CLI. curl -fL https://install-cli.jfrog.io | sudo sh sudo chmod 755 /usr/local/bin/jf fi @@ -15,28 +14,29 @@ fi # The jf CLI checks $CI when determining whether to use interactive # flows. export CI=true -# Authenticate with the JFrog CLI. -jf c rm 0 || true -echo "${ARTIFACTORY_ACCESS_TOKEN}" | jf c add --access-token-stdin --url "${JFROG_URL}" 0 +# Authenticate JFrog CLI with Artifactory. +echo "${ARTIFACTORY_ACCESS_TOKEN}" | jf c add --access-token-stdin --url "${JFROG_URL}" --overwrite 0 +# Set the configured server as the default. +jf c use 0 +# Configure npm to use the Artifactory "npm" repository. if [ -z "${REPOSITORY_NPM}" ]; then - echo "🤔 REPOSITORY_NPM is not set, skipping npm configuration." + 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." else - # check if npm is installed and configure it to use the Artifactory "npm" repository. - if command -v npm > /dev/null 2>&1; then - echo "📦 Configuring npm..." - jf npmc --global --repo-resolve "${REPOSITORY_NPM}" - fi + echo "📦 Configuring npm..." + jf npmc --global --repo-resolve "${REPOSITORY_NPM}" cat << EOF > ~/.npmrc -email = ${ARTIFACTORY_EMAIL} -registry = ${JFROG_URL}/artifactory/api/npm/${REPOSITORY_NPM} +email=${ARTIFACTORY_EMAIL} +registry=${JFROG_URL}/artifactory/api/npm/${REPOSITORY_NPM} EOF - jf rt curl /api/npm/auth >> ~/.npmrc + echo "//${JFROG_HOST}/artifactory/api/npm/${REPOSITORY_NPM}/:_authToken=${ARTIFACTORY_ACCESS_TOKEN}" >> ~/.npmrc fi # Configure the `pip` to use the Artifactory "python" repository. if [ -z "${REPOSITORY_PYPI}" ]; then - echo "🤔 REPOSITORY_PYPI is not set, skipping pip configuration." + 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." else echo "🐍 Configuring pip..." jf pipc --global --repo-resolve "${REPOSITORY_PYPI}" @@ -47,12 +47,76 @@ index-url = https://${ARTIFACTORY_USERNAME}:${ARTIFACTORY_ACCESS_TOKEN}@${JFROG_ EOF fi -# Set GOPROXY to use the Artifactory "go" repository. +# Configure Artifactory "go" repository. if [ -z "${REPOSITORY_GO}" ]; then - echo "🤔 REPOSITORY_GO is not set, skipping go configuration." + 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." else echo "🐹 Configuring go..." - jf go-config --global --repo-resolve "${REPOSITORY_GO}" - export GOPROXY="https://${ARTIFACTORY_USERNAME}:${ARTIFACTORY_ACCESS_TOKEN}@${JFROG_HOST}/artifactory/api/go/${REPOSITORY_GO}" + jf goc --global --repo-resolve "${REPOSITORY_GO}" 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." +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 + else + echo "🤔 no docker is installed, skipping docker configuration." + fi +fi + +# Install the JFrog vscode extension for code-server. +if [ "${CONFIGURE_CODE_SERVER}" == "true" ]; then + while ! [ -x /tmp/code-server/bin/code-server ]; do + counter=0 + if [ $counter -eq 60 ]; then + echo "Timed out waiting for /tmp/code-server/bin/code-server to be installed." + exit 1 + fi + echo "Waiting for /tmp/code-server/bin/code-server to be installed..." + sleep 1 + ((counter++)) + done + echo "📦 Installing JFrog extension..." + /tmp/code-server/bin/code-server --install-extension jfrog.jfrog-vscode-extension + echo "🥳 JFrog extension installed!" +else + echo "🤔 Skipping JFrog extension installation. Set configure_code_server to true to install the JFrog extension." +fi + +# Configure the JFrog CLI completion +echo "📦 Configuring JFrog CLI completion..." +# Get the user's shell +SHELLNAME=$(grep "^$USER" /etc/passwd | awk -F':' '{print $7}' | awk -F'/' '{print $NF}') +# Generate the completion script +jf completion $SHELLNAME --install +# Add the completion script to the user's shell profile +if [ "$SHELLNAME" == "bash" ] && [ -f ~/.bashrc ]; then + if ! grep -q "# jf CLI shell completion" ~/.bashrc; then + echo "" >> ~/.bashrc + echo "# BEGIN: jf CLI shell completion (added by coder module jfrog-token)" >> ~/.bashrc + echo 'source "$HOME/.jfrog/jfrog_bash_completion"' >> ~/.bashrc + echo "# END: jf CLI shell completion" >> ~/.bashrc + else + echo "🥳 ~/.bashrc already contains jf CLI shell completion configuration, skipping." + fi +elif [ "$SHELLNAME" == "zsh" ] && [ -f ~/.zshrc ]; then + if ! grep -q "# jf CLI shell completion" ~/.zshrc; then + echo "" >> ~/.zshrc + echo "# BEGIN: jf CLI shell completion (added by coder module jfrog-token)" >> ~/.zshrc + echo "autoload -Uz compinit" >> ~/.zshrc + echo "compinit" >> ~/.zshrc + echo 'source "$HOME/.jfrog/jfrog_zsh_completion"' >> ~/.zshrc + echo "# END: jf CLI shell completion" >> ~/.zshrc + else + echo "🥳 ~/.zshrc already contains jf CLI shell completion configuration, skipping." + fi +else + echo "🤔 ~/.bashrc or ~/.zshrc does not exist, skipping jf CLI shell completion configuration." +fi