Address review items

- Fix versions in readme
- Make expected test values readable
- Support typed vars for testing
pull/289/head
bsouza 10 months ago
parent 4b0ac2a6fb
commit d06cd4a2e4

@ -17,7 +17,7 @@ Install the JF CLI and authenticate package managers with Artifactory using OAut
```tf ```tf
module "jfrog" { module "jfrog" {
source = "registry.coder.com/modules/jfrog-oauth/coder" source = "registry.coder.com/modules/jfrog-oauth/coder"
version = "2.0.0" version = "1.0.19"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
jfrog_url = "https://example.jfrog.io" jfrog_url = "https://example.jfrog.io"
username_field = "username" # If you are using GitHub to login to both Coder and Artifactory, use username_field = "username" username_field = "username" # If you are using GitHub to login to both Coder and Artifactory, use username_field = "username"
@ -45,7 +45,7 @@ Configure the Python pip package manager to fetch packages from Artifactory whil
```tf ```tf
module "jfrog" { module "jfrog" {
source = "registry.coder.com/modules/jfrog-oauth/coder" source = "registry.coder.com/modules/jfrog-oauth/coder"
version = "2.0.0" version = "1.0.19"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
jfrog_url = "https://example.jfrog.io" jfrog_url = "https://example.jfrog.io"
username_field = "email" username_field = "email"
@ -73,7 +73,7 @@ The [JFrog extension](https://open-vsx.org/extension/JFrog/jfrog-vscode-extensio
```tf ```tf
module "jfrog" { module "jfrog" {
source = "registry.coder.com/modules/jfrog-oauth/coder" source = "registry.coder.com/modules/jfrog-oauth/coder"
version = "2.0.0" version = "1.0.19"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
jfrog_url = "https://example.jfrog.io" jfrog_url = "https://example.jfrog.io"
username_field = "username" # If you are using GitHub to login to both Coder and Artifactory, use username_field = "username" username_field = "username" # If you are using GitHub to login to both Coder and Artifactory, use username_field = "username"

@ -7,13 +7,25 @@ import {
} from "../test"; } from "../test";
describe("jfrog-oauth", async () => { describe("jfrog-oauth", async () => {
type TestVariables = {
agent_id: string;
jfrog_url: string;
package_managers: string;
username_field?: string;
jfrog_server_id?: string;
external_auth_id?: string;
configure_code_server?: boolean;
};
await runTerraformInit(import.meta.dir); await runTerraformInit(import.meta.dir);
const fakeFrogHostAndPort = "localhost:8081"; const fakeFrogApi = "localhost:8081/artifactory/api";
const fakeFrogUrl = `http://${fakeFrogHostAndPort}`; const fakeFrogUrl = "http://localhost:8081";
const user = "default";
it("can run apply with required variables", async () => { it("can run apply with required variables", async () => {
testRequiredVariables(import.meta.dir, { testRequiredVariables<TestVariables>(import.meta.dir, {
agent_id: "some-agent-id", agent_id: "some-agent-id",
jfrog_url: fakeFrogUrl, jfrog_url: fakeFrogUrl,
package_managers: "{}", package_managers: "{}",
@ -21,7 +33,7 @@ describe("jfrog-oauth", async () => {
}); });
it("generates an npmrc with scoped repos", async () => { it("generates an npmrc with scoped repos", async () => {
const state = await runTerraformApply(import.meta.dir, { const state = await runTerraformApply<TestVariables>(import.meta.dir, {
agent_id: "some-agent-id", agent_id: "some-agent-id",
jfrog_url: fakeFrogUrl, jfrog_url: fakeFrogUrl,
package_managers: JSON.stringify({ package_managers: JSON.stringify({
@ -30,13 +42,13 @@ describe("jfrog-oauth", async () => {
}); });
const coderScript = findResourceInstance(state, "coder_script"); const coderScript = findResourceInstance(state, "coder_script");
const npmrcStanza = `cat << EOF > ~/.npmrc const npmrcStanza = `cat << EOF > ~/.npmrc
email=default@example.com email=${user}@example.com
registry=${fakeFrogUrl}/artifactory/api/npm/global registry=http://${fakeFrogApi}/npm/global
//${fakeFrogHostAndPort}/artifactory/api/npm/global/:_authToken= //${fakeFrogApi}/npm/global/:_authToken=
@foo:registry=${fakeFrogUrl}/artifactory/api/npm/foo @foo:registry=http://${fakeFrogApi}/npm/foo
//${fakeFrogHostAndPort}/artifactory/api/npm/foo/:_authToken= //${fakeFrogApi}/npm/foo/:_authToken=
@bar:registry=${fakeFrogUrl}/artifactory/api/npm/bar @bar:registry=http://${fakeFrogApi}/npm/bar
//${fakeFrogHostAndPort}/artifactory/api/npm/bar/:_authToken= //${fakeFrogApi}/npm/bar/:_authToken=
EOF`; EOF`;
expect(coderScript.script).toContain(npmrcStanza); expect(coderScript.script).toContain(npmrcStanza);
@ -49,7 +61,7 @@ EOF`;
}); });
it("generates a pip config with extra-indexes", async () => { it("generates a pip config with extra-indexes", async () => {
const state = await runTerraformApply(import.meta.dir, { const state = await runTerraformApply<TestVariables>(import.meta.dir, {
agent_id: "some-agent-id", agent_id: "some-agent-id",
jfrog_url: fakeFrogUrl, jfrog_url: fakeFrogUrl,
package_managers: JSON.stringify({ package_managers: JSON.stringify({
@ -59,10 +71,10 @@ EOF`;
const coderScript = findResourceInstance(state, "coder_script"); const coderScript = findResourceInstance(state, "coder_script");
const pipStanza = `cat << EOF > ~/.pip/pip.conf const pipStanza = `cat << EOF > ~/.pip/pip.conf
[global] [global]
index-url = https://default:@${fakeFrogHostAndPort}/artifactory/api/pypi/global/simple index-url = https://${user}:@${fakeFrogApi}/pypi/global/simple
extra-index-url = extra-index-url =
https://default:@${fakeFrogHostAndPort}/artifactory/api/pypi/foo/simple https://${user}:@${fakeFrogApi}/pypi/foo/simple
https://default:@${fakeFrogHostAndPort}/artifactory/api/pypi/bar/simple https://${user}:@${fakeFrogApi}/pypi/bar/simple
EOF`; EOF`;
expect(coderScript.script).toContain(pipStanza); expect(coderScript.script).toContain(pipStanza);
@ -75,7 +87,7 @@ EOF`;
}); });
it("registers multiple docker repos", async () => { it("registers multiple docker repos", async () => {
const state = await runTerraformApply(import.meta.dir, { const state = await runTerraformApply<TestVariables>(import.meta.dir, {
agent_id: "some-agent-id", agent_id: "some-agent-id",
jfrog_url: fakeFrogUrl, jfrog_url: fakeFrogUrl,
package_managers: JSON.stringify({ package_managers: JSON.stringify({
@ -83,9 +95,9 @@ EOF`;
}), }),
}); });
const coderScript = findResourceInstance(state, "coder_script"); const coderScript = findResourceInstance(state, "coder_script");
const dockerStanza = `register_docker "foo.jfrog.io" const dockerStanza = ["foo", "bar", "baz"]
register_docker "bar.jfrog.io" .map((r) => `register_docker "${r}.jfrog.io"`)
register_docker "baz.jfrog.io"`; .join("\n");
expect(coderScript.script).toContain(dockerStanza); expect(coderScript.script).toContain(dockerStanza);
expect(coderScript.script).toContain( expect(coderScript.script).toContain(
'if [ -z "YES" ]; then\n not_configured docker', 'if [ -z "YES" ]; then\n not_configured docker',
@ -93,7 +105,7 @@ register_docker "baz.jfrog.io"`;
}); });
it("sets goproxy with multiple repos", async () => { it("sets goproxy with multiple repos", async () => {
const state = await runTerraformApply(import.meta.dir, { const state = await runTerraformApply<TestVariables>(import.meta.dir, {
agent_id: "some-agent-id", agent_id: "some-agent-id",
jfrog_url: fakeFrogUrl, jfrog_url: fakeFrogUrl,
package_managers: JSON.stringify({ package_managers: JSON.stringify({
@ -101,7 +113,9 @@ register_docker "baz.jfrog.io"`;
}), }),
}); });
const proxyEnv = findResourceInstance(state, "coder_env", "goproxy"); const proxyEnv = findResourceInstance(state, "coder_env", "goproxy");
const proxies = `https://default:@${fakeFrogHostAndPort}/artifactory/api/go/foo,https://default:@${fakeFrogHostAndPort}/artifactory/api/go/bar,https://default:@${fakeFrogHostAndPort}/artifactory/api/go/baz`; const proxies = ["foo", "bar", "baz"]
.map((r) => `https://${user}:@${fakeFrogApi}/go/${r}`)
.join(",");
expect(proxyEnv["value"]).toEqual(proxies); expect(proxyEnv["value"]).toEqual(proxies);
const coderScript = findResourceInstance(state, "coder_script"); const coderScript = findResourceInstance(state, "coder_script");

@ -15,7 +15,7 @@ Install the JF CLI and authenticate package managers with Artifactory using Arti
```tf ```tf
module "jfrog" { module "jfrog" {
source = "registry.coder.com/modules/jfrog-token/coder" source = "registry.coder.com/modules/jfrog-token/coder"
version = "2.0.0" version = "1.0.19"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
jfrog_url = "https://XXXX.jfrog.io" jfrog_url = "https://XXXX.jfrog.io"
artifactory_access_token = var.artifactory_access_token artifactory_access_token = var.artifactory_access_token
@ -42,7 +42,7 @@ For detailed instructions, please see this [guide](https://coder.com/docs/v2/lat
```tf ```tf
module "jfrog" { module "jfrog" {
source = "registry.coder.com/modules/jfrog-token/coder" source = "registry.coder.com/modules/jfrog-token/coder"
version = "2.0.0" version = "1.0.19"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
jfrog_url = "https://YYYY.jfrog.io" jfrog_url = "https://YYYY.jfrog.io"
artifactory_access_token = var.artifactory_access_token # An admin access token artifactory_access_token = var.artifactory_access_token # An admin access token
@ -75,7 +75,7 @@ The [JFrog extension](https://open-vsx.org/extension/JFrog/jfrog-vscode-extensio
```tf ```tf
module "jfrog" { module "jfrog" {
source = "registry.coder.com/modules/jfrog-token/coder" source = "registry.coder.com/modules/jfrog-token/coder"
version = "2.0.0" version = "1.0.19"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
jfrog_url = "https://XXXX.jfrog.io" jfrog_url = "https://XXXX.jfrog.io"
artifactory_access_token = var.artifactory_access_token artifactory_access_token = var.artifactory_access_token
@ -95,7 +95,7 @@ data "coder_workspace" "me" {}
module "jfrog" { module "jfrog" {
source = "registry.coder.com/modules/jfrog-token/coder" source = "registry.coder.com/modules/jfrog-token/coder"
version = "2.0.0" version = "1.0.19"
agent_id = coder_agent.example.id agent_id = coder_agent.example.id
jfrog_url = "https://XXXX.jfrog.io" jfrog_url = "https://XXXX.jfrog.io"
artifactory_access_token = var.artifactory_access_token artifactory_access_token = var.artifactory_access_token

@ -7,8 +7,24 @@ import {
runTerraformApply, runTerraformApply,
testRequiredVariables, testRequiredVariables,
} from "../test"; } from "../test";
import { Test } from "test";
describe("jfrog-token", async () => { describe("jfrog-token", async () => {
type TestVariables = {
agent_id: string;
jfrog_url: string;
artifactory_access_token: string;
package_managers: string;
token_description?: string;
check_license?: boolean;
refreshable?: boolean;
expires_in?: number;
username_field?: string;
jfrog_server_id?: string;
configure_code_server?: boolean;
};
await runTerraformInit(import.meta.dir); await runTerraformInit(import.meta.dir);
// Run a fake JFrog server so the provider can initialize // Run a fake JFrog server so the provider can initialize
@ -34,11 +50,13 @@ describe("jfrog-token", async () => {
port: 0, port: 0,
}); });
const fakeFrogHostAndPort = `${fakeFrogHost.hostname}:${fakeFrogHost.port}`; const fakeFrogApi = `${fakeFrogHost.hostname}:${fakeFrogHost.port}/artifactory/api`;
const fakeFrogUrl = `http://${fakeFrogHostAndPort}`; const fakeFrogUrl = `http://${fakeFrogHost.hostname}:${fakeFrogHost.port}`;
const user = "default";
const token = "xxx";
it("can run apply with required variables", async () => { it("can run apply with required variables", async () => {
testRequiredVariables(import.meta.dir, { testRequiredVariables<TestVariables>(import.meta.dir, {
agent_id: "some-agent-id", agent_id: "some-agent-id",
jfrog_url: fakeFrogUrl, jfrog_url: fakeFrogUrl,
artifactory_access_token: "XXXX", artifactory_access_token: "XXXX",
@ -47,7 +65,7 @@ describe("jfrog-token", async () => {
}); });
it("generates an npmrc with scoped repos", async () => { it("generates an npmrc with scoped repos", async () => {
const state = await runTerraformApply(import.meta.dir, { const state = await runTerraformApply<TestVariables>(import.meta.dir, {
agent_id: "some-agent-id", agent_id: "some-agent-id",
jfrog_url: fakeFrogUrl, jfrog_url: fakeFrogUrl,
artifactory_access_token: "XXXX", artifactory_access_token: "XXXX",
@ -57,13 +75,13 @@ describe("jfrog-token", async () => {
}); });
const coderScript = findResourceInstance(state, "coder_script"); const coderScript = findResourceInstance(state, "coder_script");
const npmrcStanza = `cat << EOF > ~/.npmrc const npmrcStanza = `cat << EOF > ~/.npmrc
email=default@example.com email=${user}@example.com
registry=${fakeFrogUrl}/artifactory/api/npm/global registry=http://${fakeFrogApi}/npm/global
//${fakeFrogHostAndPort}/artifactory/api/npm/global/:_authToken=xxx //${fakeFrogApi}/npm/global/:_authToken=xxx
@foo:registry=${fakeFrogUrl}/artifactory/api/npm/foo @foo:registry=http://${fakeFrogApi}/npm/foo
//${fakeFrogHostAndPort}/artifactory/api/npm/foo/:_authToken=xxx //${fakeFrogApi}/npm/foo/:_authToken=xxx
@bar:registry=${fakeFrogUrl}/artifactory/api/npm/bar @bar:registry=http://${fakeFrogApi}/npm/bar
//${fakeFrogHostAndPort}/artifactory/api/npm/bar/:_authToken=xxx //${fakeFrogApi}/npm/bar/:_authToken=xxx
EOF`; EOF`;
expect(coderScript.script).toContain(npmrcStanza); expect(coderScript.script).toContain(npmrcStanza);
@ -76,7 +94,7 @@ EOF`;
}); });
it("generates a pip config with extra-indexes", async () => { it("generates a pip config with extra-indexes", async () => {
const state = await runTerraformApply(import.meta.dir, { const state = await runTerraformApply<TestVariables>(import.meta.dir, {
agent_id: "some-agent-id", agent_id: "some-agent-id",
jfrog_url: fakeFrogUrl, jfrog_url: fakeFrogUrl,
artifactory_access_token: "XXXX", artifactory_access_token: "XXXX",
@ -87,10 +105,10 @@ EOF`;
const coderScript = findResourceInstance(state, "coder_script"); const coderScript = findResourceInstance(state, "coder_script");
const pipStanza = `cat << EOF > ~/.pip/pip.conf const pipStanza = `cat << EOF > ~/.pip/pip.conf
[global] [global]
index-url = https://default:xxx@${fakeFrogHostAndPort}/artifactory/api/pypi/global/simple index-url = https://${user}:${token}@${fakeFrogApi}/pypi/global/simple
extra-index-url = extra-index-url =
https://default:xxx@${fakeFrogHostAndPort}/artifactory/api/pypi/foo/simple https://${user}:${token}@${fakeFrogApi}/pypi/foo/simple
https://default:xxx@${fakeFrogHostAndPort}/artifactory/api/pypi/bar/simple https://${user}:${token}@${fakeFrogApi}/pypi/bar/simple
EOF`; EOF`;
expect(coderScript.script).toContain(pipStanza); expect(coderScript.script).toContain(pipStanza);
@ -103,7 +121,7 @@ EOF`;
}); });
it("registers multiple docker repos", async () => { it("registers multiple docker repos", async () => {
const state = await runTerraformApply(import.meta.dir, { const state = await runTerraformApply<TestVariables>(import.meta.dir, {
agent_id: "some-agent-id", agent_id: "some-agent-id",
jfrog_url: fakeFrogUrl, jfrog_url: fakeFrogUrl,
artifactory_access_token: "XXXX", artifactory_access_token: "XXXX",
@ -112,9 +130,9 @@ EOF`;
}), }),
}); });
const coderScript = findResourceInstance(state, "coder_script"); const coderScript = findResourceInstance(state, "coder_script");
const dockerStanza = `register_docker "foo.jfrog.io" const dockerStanza = ["foo", "bar", "baz"]
register_docker "bar.jfrog.io" .map((r) => `register_docker "${r}.jfrog.io"`)
register_docker "baz.jfrog.io"`; .join("\n");
expect(coderScript.script).toContain(dockerStanza); expect(coderScript.script).toContain(dockerStanza);
expect(coderScript.script).toContain( expect(coderScript.script).toContain(
'if [ -z "YES" ]; then\n not_configured docker', 'if [ -z "YES" ]; then\n not_configured docker',
@ -122,7 +140,7 @@ register_docker "baz.jfrog.io"`;
}); });
it("sets goproxy with multiple repos", async () => { it("sets goproxy with multiple repos", async () => {
const state = await runTerraformApply(import.meta.dir, { const state = await runTerraformApply<TestVariables>(import.meta.dir, {
agent_id: "some-agent-id", agent_id: "some-agent-id",
jfrog_url: fakeFrogUrl, jfrog_url: fakeFrogUrl,
artifactory_access_token: "XXXX", artifactory_access_token: "XXXX",
@ -131,7 +149,9 @@ register_docker "baz.jfrog.io"`;
}), }),
}); });
const proxyEnv = findResourceInstance(state, "coder_env", "goproxy"); 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`; const proxies = ["foo", "bar", "baz"]
.map((r) => `https://${user}:${token}@${fakeFrogApi}/go/${r}`)
.join(",");
expect(proxyEnv["value"]).toEqual(proxies); expect(proxyEnv["value"]).toEqual(proxies);
const coderScript = findResourceInstance(state, "coder_script"); const coderScript = findResourceInstance(state, "coder_script");

@ -108,6 +108,8 @@ export interface TerraformState {
resources: [TerraformStateResource, ...TerraformStateResource[]]; resources: [TerraformStateResource, ...TerraformStateResource[]];
} }
type TerraformVariables = Record<string, JsonValue>;
export interface CoderScriptAttributes { export interface CoderScriptAttributes {
script: string; script: string;
agent_id: string; agent_id: string;
@ -145,9 +147,9 @@ export const findResourceInstance = <T extends string>(
* Creates a test-case for each variable provided and ensures that the apply * Creates a test-case for each variable provided and ensures that the apply
* fails without it. * fails without it.
*/ */
export const testRequiredVariables = <TVars extends Record<string, string>>( export const testRequiredVariables = <TVars extends TerraformVariables>(
dir: string, dir: string,
vars: TVars, vars: Readonly<TVars>,
) => { ) => {
// Ensures that all required variables are provided. // Ensures that all required variables are provided.
it("required variables", async () => { it("required variables", async () => {
@ -158,7 +160,7 @@ export const testRequiredVariables = <TVars extends Record<string, string>>(
varNames.forEach((varName) => { varNames.forEach((varName) => {
// Ensures that every variable provided is required! // Ensures that every variable provided is required!
it("missing variable " + varName, async () => { it("missing variable " + varName, async () => {
const localVars: Record<string, string> = {}; const localVars: TerraformVariables = {};
varNames.forEach((otherVarName) => { varNames.forEach((otherVarName) => {
if (otherVarName !== varName) { if (otherVarName !== varName) {
localVars[otherVarName] = vars[otherVarName]; localVars[otherVarName] = vars[otherVarName];
@ -187,11 +189,9 @@ export const testRequiredVariables = <TVars extends Record<string, string>>(
* fine to run in parallel with other instances of this function, as it uses a * fine to run in parallel with other instances of this function, as it uses a
* random state file. * random state file.
*/ */
export const runTerraformApply = async < export const runTerraformApply = async <TVars extends TerraformVariables>(
TVars extends Readonly<Record<string, string | boolean>>,
>(
dir: string, dir: string,
vars: TVars, vars: Readonly<TVars>,
env?: Record<string, string>, env?: Record<string, string>,
): Promise<TerraformState> => { ): Promise<TerraformState> => {
const stateFile = `${dir}/${crypto.randomUUID()}.tfstate`; const stateFile = `${dir}/${crypto.randomUUID()}.tfstate`;

Loading…
Cancel
Save