Skip to content

Commit

Permalink
[features test cmd] Write tests with a non-root remoteUser (#286)
Browse files Browse the repository at this point in the history
* [features test cmd] Play nice with setting 'remoteUser' in a test

Previously, if you set 'remoteUser' in a test, the accompanying test
scripts placed into the shared 'workspaceFolder' would not have the
appropriate permission bits set to be executed by the exec user.

This patch ensure that all files in the workspaceFolder can be
read/written/executed by the exec user.

A test is added to validate creating a user and setting 'remoteUser' in
a scenario, and then running a test within that context to validate.

* add new test project

* let -> const
  • Loading branch information
joshspicer authored Nov 16, 2022
1 parent eb8752e commit 37ee770
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 11 deletions.
23 changes: 12 additions & 11 deletions src/spec-node/featuresCLI/testCommandImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { DockerResolverParameters } from '../utils';
import { DevContainerConfig } from '../../spec-configuration/configuration';
import { FeaturesTestCommandInput } from './test';
import { cpDirectoryLocal } from '../../spec-utils/pfs';
import { nullLog } from '../../spec-utils/log';

const TEST_LIBRARY_SCRIPT_NAME = 'dev-container-features-test-lib';

Expand Down Expand Up @@ -170,7 +171,7 @@ async function doRunAutoTest(feature: string, workspaceFolder: string, params: D
await cliHost.writeFile(path.join(workspaceFolder, TEST_LIBRARY_SCRIPT_NAME), Buffer.from(testLibraryScript));

// Execute Test
const result = await execTest(params, 'test.sh', workspaceFolder);
const result = await execTest(params, 'test.sh', workspaceFolder, cliHost);
testResults.push({
testName: feature,
result,
Expand Down Expand Up @@ -231,7 +232,7 @@ async function doScenario(pathToTestDir: string, targetFeatureOrGlobal: string,
// Execute Test
testResults.push({
testName: scenarioName,
result: await execTest(params, `${scenarioName}.sh`, workspaceFolder)
result: await execTest(params, `${scenarioName}.sh`, workspaceFolder, cliHost)
});
}
return testResults;
Expand Down Expand Up @@ -267,7 +268,7 @@ const devcontainerTemplate = `
}`;

async function createContainerFromWorkingDirectory(params: DockerResolverParameters, workspaceFolder: string, args: FeaturesTestCommandInput): Promise<LaunchResult | undefined> {
const { quiet, remoteUser, disposables } = args;
const { quiet, disposables } = args;
log(`workspaceFolder: ${workspaceFolder}`);

// 2. Use 'devcontainer-cli up' to build and start a container
Expand All @@ -282,7 +283,6 @@ async function createContainerFromWorkingDirectory(params: DockerResolverParamet

log(`Launched container.`, { prefix: '\n🚀', info: true });
log(`containerId: ${containerId}`);
log(`remoteUser: ${remoteUser}`);

return launchResult;
}
Expand Down Expand Up @@ -367,6 +367,9 @@ async function generateProjectFromScenario(
await cpDirectoryLocal(localPathToAdditionalConfigFolder, `${tmpFolder}/.devcontainer`);
}

// Update permissions on the copied files to make them readable/writable/executable by everyone
await cliHost.exec({ cmd: 'chmod', args: ['-R', '777', tmpFolder], output: nullLog });

// tmpFolder will serve as our auto-generated 'workingFolder'
return tmpFolder;
}
Expand Down Expand Up @@ -420,15 +423,13 @@ async function launchProject(params: DockerResolverParameters, workspaceFolder:
}
}

async function execTest(params: DockerResolverParameters, testFileName: string, workspaceFolder: string) {
async function execTest(params: DockerResolverParameters, testFileName: string, workspaceFolder: string, cliHost: CLIHost) {
// Ensure all the tests scripts in the workspace folder are executable
let cmd = 'chmod';
let args = ['-R', '777', '.'];
await exec(params, cmd, args, workspaceFolder);

// Update permissions on the copied files to make them readable/writable/executable by everyone
await cliHost.exec({ cmd: 'chmod', args: ['-R', '777', workspaceFolder], output: nullLog });

cmd = `./${testFileName}`;
args = [];
const cmd = `./${testFileName}`;
const args: string[] = [];
return await exec(params, cmd, args, workspaceFolder);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"id": "whoisremoteuser",
"version": "0.0.0",
"name": "Stores and echoes original value of _REMOTE_USER",
"options": {},
"installsAfter": [
"ghcr.io/devcontainers/features/common-utils"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/sh
set -e

echo "Activating feature 'whoisremoteuser'"

cat > /usr/local/bin/whoisremoteuser \
<< EOF
#!/bin/sh
echo -n "$_REMOTE_USER"
EOF

chmod +x /usr/local/bin/whoisremoteuser
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# Definition specific tests
check "ensure i am user codespace" bash -c "whoami | grep 'codespace'"

check "_REMOTE_USER was equal to codespace" bash -c "whoisremoteuser | grep 'codespace'"


# Report result
reportResults
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"different_remote_user": {
"image": "mcr.microsoft.com/devcontainers/base:ubuntu",
"remoteUser": "codespace",
"features": {
"ghcr.io/devcontainers/features/common-utils:1": {
"installZsh": false,
"installOhMyZsh": false,
"upgradePackages": false,
"username": "codespace"
},
"whoisremoteuser": {}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash

set -e

# Optional: Import test library
source dev-container-features-test-lib

# Definition specific tests
check "ensure i am root" bash -c "whoami | grep 'root'"

check "_REMOTE_USER was equal to root" bash -c "whoisremoteuser | grep 'root'"

# Report result
reportResults

0 comments on commit 37ee770

Please sign in to comment.