Skip to content

docs: expand jfrog platform and example template #9073

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Aug 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
100 changes: 79 additions & 21 deletions docs/platforms/jfrog.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ The full example template can be found [here](https://github.com/coder/coder/tre

- A JFrog Artifactory instance
- An admin-level access token for Artifactory
- 1:1 mapping of users in Coder to users in Artifactory by email address
- An npm repository in Artifactory named "npm"
- 1:1 mapping of users in Coder to users in Artifactory by email address and username
- Repositories configured in Artifactory for each package manager you want to use

<blockquote class="info">
The admin-level access token is used to provision user tokens and is never exposed to
Expand Down Expand Up @@ -40,14 +40,14 @@ terraform {
}
artifactory = {
source = "registry.terraform.io/jfrog/artifactory"
version = "6.22.3"
version = "~> 8.4.0"
}
}
}

variable "jfrog_url" {
variable "jfrog_host" {
type = string
description = "The URL of the JFrog instance."
description = "JFrog instance hostname. e.g. YYY.jfrog.io"
}

variable "artifactory_access_token" {
Expand All @@ -57,15 +57,15 @@ variable "artifactory_access_token" {

# Configure the Artifactory provider
provider "artifactory" {
url = "${var.jfrog_url}/artifactory"
url = "https://${var.jfrog_host}/artifactory"
access_token = "${var.artifactory_access_token}"
}
```

When pushing the template, you can pass in the variables using the `-V` flag:
When pushing the template, you can pass in the variables using the `--var` flag:

```sh
coder templates push --var 'jfrog_url=https://YYY.jfrog.io' --var 'artifactory_access_token=XXX'
coder templates push --var 'jfrog_host=YYY.jfrog.io' --var 'artifactory_access_token=XXX'
```

## Installing JFrog CLI
Expand All @@ -88,7 +88,21 @@ In our Docker-based example, we install `jf` by adding these lines to our `Docke
RUN curl -fL https://install-cli.jfrog.io | sh && chmod 755 $(which jf)
```

and use this `coder_agent` block:
## Configuring Coder workspace to use JFrog Artifactory repositories

Create a `locals` block to store the Artifactory repository keys for each package manager you want to use in your workspace. For example, if you want to use artifactory repositories with keys `npm`, `pypi`, and `go`, you can create a `locals` block like this:

```hcl
locals {
artifactory_repository_keys = {
npm = "npm"
python = "pypi"
go = "go"
}
}
```

To automatically configure `jf` CLI and Artifactory repositories for each user, add the following lines to your `startup_script` in the `coder_agent` block:

```hcl
resource "coder_agent" "main" {
Expand All @@ -107,9 +121,28 @@ resource "coder_agent" "main" {
export CI=true

jf c rm 0 || true
echo ${artifactory_access_token.me.access_token} | \
jf c add --access-token-stdin --url ${var.jfrog_url} 0
echo ${artifactory_scoped_token.me.access_token} | \
jf c add --access-token-stdin --url https://${var.jfrog_host} 0

# Configure the `npm` CLI to use the Artifactory "npm" repository.
cat << EOF > ~/.npmrc
email = ${data.coder_workspace.me.owner_email}
registry = https://${var.jfrog_host}/artifactory/api/npm/${local.artifactory_repository_keys["npm"]}
EOF
jf rt curl /api/npm/auth >> .npmrc

# Configure the `pip` to use the Artifactory "python" repository.
mkdir -p ~/.pip
cat << EOF > ~/.pip/pip.conf
[global]
index-url = https://${local.artifactory_username}:${artifactory_scoped_token.me.access_token}@${var.jfrog_host}/artifactory/api/pypi/${local.artifactory_repository_keys["python"]}/simple
EOF

EOT
# Set GOPROXY to use the Artifactory "go" repository.
env = {
GOPROXY : "https://${local.artifactory_username}:${artifactory_scoped_token.me.access_token}@${var.jfrog_host}/artifactory/api/go/${local.artifactory_repository_keys["go"]}"
}
}
```

Expand All @@ -119,12 +152,12 @@ running `jf c show`. It should display output like:
```text
coder@jf:~$ jf c show
Server ID: 0
JFrog Platform URL: https://cdr.jfrog.io/
Artifactory URL: https://cdr.jfrog.io/artifactory/
Distribution URL: https://cdr.jfrog.io/distribution/
Xray URL: https://cdr.jfrog.io/xray/
Mission Control URL: https://cdr.jfrog.io/mc/
Pipelines URL: https://cdr.jfrog.io/pipelines/
JFrog Platform URL: https://YYY.jfrog.io/
Artifactory URL: https://YYY.jfrog.io/artifactory/
Distribution URL: https://YYY.jfrog.io/distribution/
Xray URL: https://YYY.jfrog.io/xray/
Mission Control URL: https://YYY.jfrog.io/mc/
Pipelines URL: https://YYY.jfrog.io/pipelines/
User: ammar@....com
Access token: ...
Default: true
Expand All @@ -151,11 +184,11 @@ Note that this method will only work if your developers use code-server.
Add the following line to your `startup_script` to configure `npm` to use
Artifactory:

```sh
```shell
# Configure the `npm` CLI to use the Artifactory "npm" registry.
cat << EOF > ~/.npmrc
email = ${data.coder_workspace.me.owner_email}
registry=${var.jfrog_url}/artifactory/api/npm/npm/
registry = https://${var.jfrog_host}/artifactory/api/npm/npm/
EOF
jf rt curl /api/npm/auth >> .npmrc
```
Expand All @@ -165,8 +198,33 @@ use Artifactory as the package registry. You can verify that `npm` is configured
correctly by running `npm install --loglevel=http react` and checking that
npm is only hitting your Artifactory URL.

You can apply the same concepts to Docker, Go, Maven, and other package managers
supported by Artifactory.
## Configuring pip

Add the following lines to your `startup_script` to configure `pip` to use
Artifactory:

```shell
mkdir -p ~/.pip
cat << EOF > ~/.pip/pip.conf
[global]
index-url = https://${data.coder_workspace.me.owner}:${artifactory_scoped_token.me.access_token}@${var.jfrog_host}/artifactory/api/pypi/pypi/simple
EOF
```

Now, your developers can run `pip install` and transparently use Artifactory as the package registry. You can verify that `pip` is configured correctly by running `pip install --verbose requests` and checking that pip is only hitting your Artifactory URL.

## Configuring Go

Add the following environment variable to your `coder_agent` block to configure `go` to use Artifactory:

```hcl
env = {
GOPROXY : "https://${data.coder_workspace.me.owner}:${artifactory_scoped_token.me.access_token}@${var.jfrog_host}/artifactory/api/go/go"
}
```

You can apply the same concepts to Docker, Maven, and other package managers
supported by Artifactory. See the [JFrog documentation](https://jfrog.com/help/r/jfrog-artifactory-documentation/package-management) for more information.

## More reading

Expand Down
9 changes: 8 additions & 1 deletion examples/templates/jfrog-docker/build/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,20 @@ RUN apt-get update \
&& apt-get install -y \
curl \
git \
golang \
python3-pip \
sudo \
vim \
wget \
npm \
&& rm -rf /var/lib/apt/lists/*

ARG GO_VERSION=1.20.7
RUN mkdir --parents /usr/local/go && curl --silent --show-error --location \
"https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz" -o /usr/local/go.tar.gz && \
tar --extract --gzip --directory=/usr/local/go --file=/usr/local/go.tar.gz --strip-components=1

ENV PATH=$PATH:/usr/local/go/bin

ARG USER=coder
RUN useradd --groups sudo --no-create-home --shell /bin/bash ${USER} \
&& echo "${USER} ALL=(ALL) NOPASSWD:ALL" >/etc/sudoers.d/${USER} \
Expand Down
53 changes: 36 additions & 17 deletions examples/templates/jfrog-docker/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,23 @@ terraform {
}
artifactory = {
source = "registry.terraform.io/jfrog/artifactory"
version = "6.22.3"
version = "~> 8.4.0"
}
}
}

locals {
username = data.coder_workspace.me.owner
# if the jfrog username is same as the coder username, you can use the following
# artifactory_username = data.coder_workspace.me.owner
# if the username is same as email, you can use the following
# artifactory_username = urlencode(data.coder_workspace.me.owner_email)
artifactory_username = data.coder_workspace.me.owner
artifactory_repository_keys = {
"npm" = "npm"
"python" = "python"
"go" = "go"
}
workspace_user = data.coder_workspace.me.owner
}

data "coder_provisioner" "me" {
Expand All @@ -28,27 +38,24 @@ provider "docker" {
data "coder_workspace" "me" {
}

variable "jfrog_url" {
variable "jfrog_host" {
type = string
description = "The URL of the JFrog instance."
description = "JFrog instance hostname. For example, 'YYY.jfrog.io'."
}

variable "artifactory_access_token" {
type = string
description = "The admin-level access token to use for JFrog."
}


# Configure the Artifactory provider
provider "artifactory" {
url = "${var.jfrog_url}/artifactory"
url = "https://${var.jfrog_host}/artifactory"
access_token = var.artifactory_access_token
}

resource "artifactory_access_token" "me" {
username = data.coder_workspace.me.owner_email
# The token should live for the duration of the workspace.
end_date_relative = "0s"
resource "artifactory_scoped_token" "me" {
username = local.artifactory_username
}

resource "coder_agent" "main" {
Expand All @@ -67,23 +74,35 @@ resource "coder_agent" "main" {
export CI=true

jf c rm 0 || true
echo ${artifactory_access_token.me.access_token} | \
jf c add --access-token-stdin --url ${var.jfrog_url} 0
echo ${artifactory_scoped_token.me.access_token} | \
jf c add --access-token-stdin --url https://${var.jfrog_host} 0

# Configure the `npm` CLI to use the Artifactory "npm" registry.
# Configure the `npm` CLI to use the Artifactory "npm" repository.
cat << EOF > ~/.npmrc
email = ${data.coder_workspace.me.owner_email}
registry=${var.jfrog_url}/artifactory/api/npm/npm/
registry = https://${var.jfrog_host}/artifactory/api/npm/${local.artifactory_repository_keys["npm"]}
EOF
jf rt curl /api/npm/auth >> .npmrc

# Configure the `pip` to use the Artifactory "python" repository.
mkdir -p ~/.pip
cat << EOF > ~/.pip/pip.conf
[global]
index-url = https://${local.artifactory_username}:${artifactory_scoped_token.me.access_token}@${var.jfrog_host}/artifactory/api/pypi/${local.artifactory_repository_keys["python"]}/simple
EOF

EOT
# Set GOPROXY to use the Artifactory "go" repository.
env = {
GOPROXY : "https://${local.artifactory_username}:${artifactory_scoped_token.me.access_token}@${var.jfrog_host}/artifactory/api/go/${local.artifactory_repository_keys["go"]}"
}
}

resource "coder_app" "code-server" {
agent_id = coder_agent.main.id
slug = "code-server"
display_name = "code-server"
url = "http://localhost:13337/?folder=/home/${local.username}"
url = "http://localhost:13337/?folder=/home/${local.workspace_user}"
icon = "/icon/code.svg"
subdomain = false
share = "owner"
Expand All @@ -108,7 +127,7 @@ resource "docker_image" "main" {
build {
context = "./build"
build_args = {
USER = local.username
USER = local.workspace_user
}
}
triggers = {
Expand All @@ -130,7 +149,7 @@ resource "docker_container" "workspace" {
ip = "host-gateway"
}
volumes {
container_path = "/home/${local.username}"
container_path = "/home/${local.workspace_user}"
volume_name = docker_volume.home_volume.name
read_only = false
}
Expand Down