Skip to content

Commit

Permalink
Setup spin cli templates and plugins
Browse files Browse the repository at this point in the history
We only install templates and plugins when the there are non installed
before. If the user has already configured spin, then we don't want to
modify their setup, as we would overwrite them on each app start.

Signed-off-by: Jan Dubois <[email protected]>
  • Loading branch information
jandubois committed May 8, 2024
1 parent d30350c commit 7be2d84
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 12 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# All Linux scripts should have LF line endings
# But only text files should be changed (not any binaries / images / etc.)
resources/linux/** text=auto eol=lf
resources/setup-spin text=auto eol=lf
pkg/rancher-desktop/assets/scripts/** text=auto eol=lf
1 change: 1 addition & 0 deletions .github/actions/spelling/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,7 @@ userpreference
UTCTIME
vcenter
vcpus
vcruntime
vcs
vde
ventura
Expand Down
2 changes: 1 addition & 1 deletion .github/actions/spelling/patterns.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ sha\d+:[0-9]*[a-f]{3,}[0-9a-f]*

# hit-count: 6 file-count: 4
# tar arguments
\b(?:\\n|)g?tar(?:\.exe|)(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+
\b(?:\\n|)g?tar(?:\.exe|)"?(?:(?:\s+--[-a-zA-Z]+|\s+-[a-zA-Z]+|\s[ABGJMOPRSUWZacdfh-pr-xz]+\b)(?:=[^ ]*|))+

# hit-count: 4 file-count: 3
# base64 encoded content
Expand Down
8 changes: 7 additions & 1 deletion pkg/rancher-desktop/backend/lima.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1567,7 +1567,13 @@ export default class LimaBackend extends events.EventEmitter implements VMBacken
await this.writeFile('/etc/cni/net.d/10-flannel.conflist', FLANNEL_CONFLIST);
}

await BackendHelper.configureContainerEngine(this, configureWASM);
const promises: Promise<unknown>[] = [];

promises.push(BackendHelper.configureContainerEngine(this, configureWASM));
if (configureWASM) {
promises.push(this.spawnWithCapture(path.join(paths.resources, 'setup-spin'), {}));
}
await Promise.all(promises);
} catch (err) {
console.log(`Error trying to start/update containerd: ${ err }: `, err);
}
Expand Down
5 changes: 4 additions & 1 deletion pkg/rancher-desktop/backend/wsl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1510,8 +1510,11 @@ export default class WSLBackend extends events.EventEmitter implements VMBackend

await this.writeFile('/usr/local/bin/wsl-exec', WSL_EXEC, 0o755);
await this.runInit();
if (configureWASM) {
await this.execCommand(await this.wslify(path.join(paths.resources, 'setup-spin')));
}
if (rdNetworking) {
// Do not await on this, as we don't want to wait until the proxy exits.
// Do not await on this, as we don't want to wait until the proxy exits.
this.runWslProxy().catch(console.error);
}
}),
Expand Down
21 changes: 12 additions & 9 deletions pkg/rancher-desktop/integrations/windowsIntegrationManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ export default class WindowsIntegrationManager implements IntegrationManager {
this.syncDistroSocketProxy(distro, state),
this.syncDistroDockerPlugins(distro, state),
this.syncDistroKubeconfig(distro, kubeconfigPath, state),
this.syncDistroSpinCLI(distro, state),
]);
} catch (ex) {
console.error(`Failed to sync integration for ${ distro }: ${ ex }`);
Expand Down Expand Up @@ -307,15 +308,7 @@ export default class WindowsIntegrationManager implements IntegrationManager {
protected async getLinuxToolPath(distro: string, tool: string): Promise<string> {
// We need to get the Linux path to our helper executable; it is easier to
// just get WSL to do the transformation for us.

const logStream = Logging[`wsl-helper.${ distro }`];
const { stdout } = await spawnFile(
await this.wslExe,
['--distribution', distro, '--exec', '/bin/wslpath', '-a', '-u', tool],
{ stdio: ['ignore', 'pipe', logStream] },
);

return stdout.trim();
return (await this.captureCommand( { distro }, '/bin/wslpath', '-a', '-u', tool)).trim();
}

protected async syncHostSocketProxy(): Promise<void> {
Expand Down Expand Up @@ -497,6 +490,16 @@ export default class WindowsIntegrationManager implements IntegrationManager {
console.log(`kubeconfig integration for ${ distro } set to ${ state }`);
}

protected async syncDistroSpinCLI(distro: string, state: boolean) {
if (state) {
const setupSpin = (await this.captureCommand(
{ distro }, '/bin/wslpath', '-a', '-u', path.join(paths.resources, 'setup-spin'))
).trim();

await this.execCommand( { distro }, setupSpin);
}
}

protected get nonBlacklistedDistros(): Promise<WSLDistro[]> {
return (async() => {
let wslOutput: string;
Expand Down
1 change: 1 addition & 0 deletions pkg/rancher-desktop/utils/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const executableMap: Record<string, string[] | undefined> = {
kubectl: undefined,
nerdctl: undefined,
rdctl: undefined,
spin: undefined,
'wsl-helper': [paths.resources, process.platform, 'internal', platformBinary('wsl-helper')],
'wsl-helper-linux': [paths.resources, 'linux', 'internal', 'wsl-helper'],
};
Expand Down
128 changes: 128 additions & 0 deletions resources/setup-spin
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#!/bin/sh
# This script uses sh instead of bash to be compatible with as many distros as possible.

# The script is located in the Rancher Desktop resources/ directory.
resources_dir=$(dirname "$0")

# We run setup-spin in the rancher-desktop distro to setup spin on the Win32 host.
if [ "$WSL_DISTRO_NAME" = "rancher-desktop" ]; then
app_data_dir=$(/bin/wslpath "$(powershell.exe -Command "Write-Output \${Env:LOCALAPPDATA}")" | tr -d "\r")
system_root=$(/bin/wslpath "$(powershell.exe -Command "Write-Output \${Env:SystemRoot}")" | tr -d "\r")
spin="${resources_dir}/win32/bin/spin.exe"
elif [ "$(uname)" = "Linux" ]; then
app_data_dir="${XDG_DATA_HOME:-$HOME/.local/share}"
spin="${resources_dir}/linux/bin/spin"
else
app_data_dir="${HOME}/Library/Application Support"
spin="${resources_dir}/darwin/bin/spin"
fi

if [ ! -x "$spin" ]; then
echo "Cannot execute '${spin}' (or does not exist)"
exit 1
fi

spin_dir="${app_data_dir}/spin"

# shellcheck disable=SC2012 # Using `ls` is fine
if [ -d "${spin_dir}/templates" ] && [ "$(ls -1 "${spin_dir}/templates" | wc -l)" -gt 0 ]; then
echo "'${spin_dir}/templates' already exists and is not empty"
exit 0
fi

# shellcheck disable=SC2012 # Using `ls` is fine
if [ -d "${spin_dir}/plugins" ] && [ "$(ls -1 "${spin_dir}/plugins" | wc -l)" -gt 0 ]; then
echo "'${spin_dir}/plugins' already exists and is not empty"
exit 0
fi

if [ "$WSL_DISTRO_NAME" = "rancher-desktop" ]; then
echo "Waiting for github.com to become resolvable"
for _ in $(seq 30); do
curl --head --silent http://github.com >/dev/null
rc=$?; test $rc -ne 0 && echo "curl exit status is $rc"
if [ $rc -ne 6 ]; then
break
fi
sleep 2
done
fi

# The reason for this complexity is to be able to run on systems without git.
# We do need either curl or wget to be on the PATH though.
install_templates() {
repo=$1
branch=main
tmpdir="${spin_dir}/rancher-desktop.$$"
tarball="${tmpdir}/${repo}.tar.gz"

url="https://github.com/fermyon/${repo}/archive/refs/heads/${branch}.tar.gz"

if [ "$WSL_DISTRO_NAME" = "rancher-desktop" ]; then
# Download and extract tarball on Win32 host side to avoid 9p syncing issues
tmpdir=$(/bin/wslpath -w "$tmpdir")
tarball=$(/bin/wslpath -w "$tarball")

"${system_root}/system32/cmd.exe" /c mkdir "$tmpdir"

echo "Downloading '${url}' to '${tarball}' with curl.exe"
"${system_root}/system32/curl.exe" --silent --location "$url" --output "$tarball"
rc=$?; test $rc -ne 0 && echo "curl.exe exit status is $rc"

if [ $rc -eq 0 ]; then
echo "Unpacking '${tarball}'"
"${system_root}/system32/tar.exe" xfz "$tarball" -C "$tmpdir"
rc=$?; test $rc -ne 0 && echo "tar.exe exit status is $rc"

dir="${tmpdir}\\${repo}-${branch}"
echo "Installing templates from '${dir}'"
"$spin" templates install --update --dir "$dir"
rc=$?; test $rc -ne 0 && echo "Exit status is $rc"
else
echo "Could not download '${url}'"
fi
"${system_root}/system32/cmd.exe" /c rmdir /s /q "$tmpdir"
return
fi

mkdir -p "$tmpdir"
if command -v curl >/dev/null; then
echo "Downloading '${url}' to '${tarball}' with curl"
curl --silent --location "$url" --output "$tarball"
rc=$?; test $rc -ne 0 && echo "curl exit status is $rc"
elif command -v wget >/dev/null; then
echo "Downloading '${url}' to '${tarball}' with wget"
wget --no-verbose "$url" -O "$tarball"
rc=$?; test $rc -ne 0 && echo "wget exit status is $rc"
fi
if [ -f "$tarball" ]; then
echo "Unpacking '${tarball}'"
tar xfz "$tarball" -C "$tmpdir"
rc=$?; test $rc -ne 0 && echo "tar exit status is $rc"

dir="${tmpdir}/${repo}-${branch}"
echo "Installing templates from '${dir}'"
"$spin" templates install --update --dir "$dir"
rc=$?; test $rc -ne 0 && echo "Exit status is $rc"
else
echo "Could not download '${url}' (maybe no curl/wget)"
fi
rm -rf "$tmpdir"
}

install_plugin() {
plugin=$1
url="https://raw.githubusercontent.com/fermyon/spin-plugins/main/manifests/${plugin}/${plugin}.json"
echo "Installing plugin from '${url}'"
"$spin" plugins install --yes --url "$url"
rc=$?; test $rc -ne 0 && echo "Exit status is $rc"
}

install_templates spin
install_templates spin-python-sdk
install_templates spin-js-sdk

install_plugin js2wasm
install_plugin kube

echo "'${spin}' setup complete"

0 comments on commit 7be2d84

Please sign in to comment.