Skip to content
This repository was archived by the owner on May 15, 2025. It is now read-only.

feat(jfrog): add JFrog vscode extension, CLI completion and docker support #115

Merged
merged 53 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
0421dfe
add JFrog extension configuration
matifali Dec 25, 2023
cb49f8d
add example to README
matifali Dec 25, 2023
85e9297
fmt
matifali Dec 25, 2023
902b382
update JFrog Token module
matifali Dec 25, 2023
cf60e20
fixup!
matifali Dec 25, 2023
68cbcd1
update artifactory terraform provider
matifali Dec 25, 2023
44f9a1e
fix tests
matifali Dec 26, 2023
5127897
Merge branch 'main' into jfrog-code-server-extension
matifali Dec 26, 2023
97a6613
Update README.md
matifali Dec 27, 2023
c6d8f39
Update run.sh
matifali Dec 27, 2023
eea0274
Update run.sh
matifali Dec 27, 2023
e36c284
Update main.tf
matifali Dec 27, 2023
d36b580
Update main.tf
matifali Dec 27, 2023
4a0fd4c
Update main.tf
matifali Dec 27, 2023
7f9a6bc
Update main.tf
matifali Dec 27, 2023
f621777
Update main.tf
matifali Dec 27, 2023
ee43370
Update JFrog extension installation message
matifali Dec 27, 2023
955eadb
Update code-server installation path
matifali Dec 27, 2023
9cc2a37
Update coder_env resource names for Go proxy
matifali Dec 27, 2023
c0c8ac5
add wait
matifali Dec 27, 2023
7b9302e
wait for code-server to be insatlled.
matifali Dec 27, 2023
cbd294d
fixup!
matifali Dec 27, 2023
5694858
Update npm config fix command to use global flag
matifali Dec 27, 2023
b1f2cc7
Update JFrog instance URL and package manager configurations
matifali Dec 28, 2023
489fcd1
fix formatting of .npmrc
matifali Dec 28, 2023
5b1337e
fixup!
matifali Dec 28, 2023
963d4d6
fixup!
matifali Dec 28, 2023
c289810
use token from `jf rt curl /api/npm/auth`
matifali Dec 28, 2023
7d85783
Update 'jf go-config' command to 'jf goc'
matifali Dec 28, 2023
168e20d
Update authentication in run.sh scripts
matifali Dec 28, 2023
6689114
Add Docker repository configuration
matifali Jan 1, 2024
04c2bcb
Add JFrog CLI completion to shell profile
matifali Jan 1, 2024
f5a7310
Refactor JFrog CLI completion configuration
matifali Jan 1, 2024
268bfe4
fixup!: JFrog CLI completion installation
matifali Jan 1, 2024
ac9afb2
Fix shell completion in run.sh
matifali Jan 1, 2024
cd27883
Update JFrog cli configuration to include --overwrite
matifali Jan 1, 2024
740b3fe
Update JFrog CLI authentication and npm configuration
matifali Jan 1, 2024
e85607f
Update JFrog CLI completion configuration to get the default shell
matifali Jan 1, 2024
d9a25fa
Remove unnecessary blank line in main.tf
matifali Jan 1, 2024
5d54492
Add email field to JFrog OAuth and JFrog Token run scripts
matifali Jan 2, 2024
a9baa1f
Add shell completion support for jf CLI
matifali Jan 2, 2024
3308bf1
refactor
matifali Jan 2, 2024
b1e182f
suggestions from review
matifali Jan 2, 2024
f2ebcf0
`fmt`
matifali Jan 2, 2024
b53e2d8
more suggestions
matifali Jan 2, 2024
171fb35
simplify npm authentication
matifali Jan 2, 2024
fee0d4e
fixup!
matifali Jan 2, 2024
236e4ac
Fix base64 encoding for `~/.docker/config.json`
matifali Jan 2, 2024
7362993
Update docker credentials configuration to use `docker login`
matifali Jan 2, 2024
1738ff1
simlified
matifali Jan 2, 2024
3b96d21
added check to see if docker binary is installed
matifali Jan 5, 2024
1cfefb8
Update timeout value in run.sh script
matifali Jan 5, 2024
22ecc79
skip if shellrc files do not exist.
matifali Jan 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion jfrog-oauth/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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).
Expand Down
57 changes: 50 additions & 7 deletions jfrog-oauth/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand All @@ -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 = <<EOF
A map of package manager names to their respective artifactory repositories.
For example:
{
"npm": "npm-local",
"go": "go-local",
"pypi": "pypi-local"
"npm": "YOUR_NPM_REPO_KEY",
"go": "YOUR_GO_REPO_KEY",
"pypi": "YOUR_PYPI_REPO_KEY",
"docker": "YOUR_DOCKER_REPO_KEY"
}
EOF
}

locals {
# The username field to use for artifactory
username = var.username_field == "email" ? data.coder_workspace.me.owner_email : data.coder_workspace.me.owner
username = var.username_field == "email" ? data.coder_workspace.me.owner_email : data.coder_workspace.me.owner
jfrog_host = replace(var.jfrog_url, "https://", "")
}

data "coder_workspace" "me" {}
Expand All @@ -65,17 +78,47 @@ resource "coder_script" "jfrog" {
icon = "/icon/jfrog.svg"
script = templatefile("${path.module}/run.sh", {
JFROG_URL : var.jfrog_url,
JFROG_HOST : replace(var.jfrog_url, "https://", ""),
JFROG_HOST : local.jfrog_host,
ARTIFACTORY_USERNAME : local.username,
ARTIFACTORY_EMAIL : data.coder_workspace.me.owner_email,
ARTIFACTORY_ACCESS_TOKEN : data.coder_external_auth.jfrog.access_token,
CONFIGURE_CODE_SERVER : var.configure_code_server,
REPOSITORY_NPM : lookup(var.package_managers, "npm", ""),
REPOSITORY_GO : lookup(var.package_managers, "go", ""),
REPOSITORY_PYPI : lookup(var.package_managers, "pypi", ""),
REPOSITORY_DOCKER : lookup(var.package_managers, "docker", ""),
})
run_on_start = true
}

resource "coder_env" "jfrog_ide_url" {
count = var.configure_code_server ? 1 : 0
agent_id = var.agent_id
name = "JFROG_IDE_URL"
value = var.jfrog_url
}

resource "coder_env" "jfrog_ide_access_token" {
count = var.configure_code_server ? 1 : 0
agent_id = var.agent_id
name = "JFROG_IDE_ACCESS_TOKEN"
value = data.coder_external_auth.jfrog.access_token
}

resource "coder_env" "jfrog_ide_store_connection" {
count = var.configure_code_server ? 1 : 0
agent_id = var.agent_id
name = "JFROG_IDE_STORE_CONNECTION"
value = true
}

resource "coder_env" "goproxy" {
count = lookup(var.package_managers, "go", "") == "" ? 0 : 1
agent_id = var.agent_id
name = "GOPROXY"
value = "https://${local.username}:${data.coder_external_auth.jfrog.access_token}@${local.jfrog_host}/artifactory/api/go/${lookup(var.package_managers, "go", "")}"
}

output "access_token" {
description = "value of the JFrog access token"
value = data.coder_external_auth.jfrog.access_token
Expand Down
102 changes: 83 additions & 19 deletions jfrog-oauth/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,38 +7,38 @@ if command -v jf > /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

# 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
Expand All @@ -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
59 changes: 39 additions & 20 deletions jfrog-token/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,24 @@ 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"
}
}
```

Get a JFrog access token from your Artifactory instance. The token must be an [admin token](https://registry.terraform.io/providers/jfrog/artifactory/latest/docs#access-token). It is recommended to store the token in a secret terraform variable.

```hcl
variable "artifactory_access_token" {
type = string
sensitive = true
type = string
sensitive = true
}
```

Expand All @@ -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"
}
}
```

Expand All @@ -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).
Expand Down
Loading