Skip to content
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
43 changes: 35 additions & 8 deletions basefiles/app-compose.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,39 @@
#!/bin/sh
tdxctl notify-host -e "boot.progress" -d "starting containers" || true
#!/bin/bash

docker compose up --remove-orphans -d || true
chmod +x /usr/bin/containerd-shim-runc-v2
systemctl restart docker
if [ $(jq 'has("pre_launch_script")' app-compose.json) == true ]; then
echo "Running pre-launch script"
tdxctl notify-host -e "boot.progress" -d "pre-launch" || true
source <(jq -r '.pre_launch_script' app-compose.json)
fi

RUNNER=$(jq -r '.runner' app-compose.json)
case "$RUNNER" in
"docker-compose")
echo "Starting containers"
tdxctl notify-host -e "boot.progress" -d "starting containers" || true
if ! [ -f docker-compose.yaml ]; then
jq -r '.docker_compose_file' app-compose.json >docker-compose.yaml
fi
docker compose up --remove-orphans -d || true
chmod +x /usr/bin/containerd-shim-runc-v2
systemctl restart docker

if ! docker compose up --remove-orphans -d; then
tdxctl notify-host -e "boot.error" -d "failed to start containers"
if ! docker compose up --remove-orphans -d; then
tdxctl notify-host -e "boot.error" -d "failed to start containers"
exit 1
fi
;;
"bash")
chmod +x /usr/bin/containerd-shim-runc-v2
echo "Running main script"
tdxctl notify-host -e "boot.progress" -d "running main script" || true
jq -r '.bash_script' app-compose.json | bash
;;
*)
echo "ERROR: unsupported runner: $RUNNER" >&2
tdxctl notify-host -e "boot.error" -d "unsupported runner: $RUNNER"
exit 1
fi
;;
esac

tdxctl notify-host -e "boot.progress" -d "done" || true
16 changes: 0 additions & 16 deletions tdxctl/src/tboot.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ impl<'a> Setup<'a> {
nc.notify_q("boot.progress", "setting up docker").await;
self.setup_docker_registry()?;
self.setup_docker_account()?;
self.prepare_docker_compose()?;
Ok(())
}

Expand Down Expand Up @@ -263,21 +262,6 @@ impl<'a> Setup<'a> {
cmd!(docker login -u $username -p $token)?;
Ok(())
}

fn prepare_docker_compose(&self) -> Result<()> {
info!("Preparing docker compose");
if self.app_compose.runner == "docker-compose" {
let docker_compose = self
.app_compose
.docker_compose_file
.as_ref()
.context("Missing docker_compose_file")?;
fs::write(self.resolve("/tapp/docker-compose.yaml"), docker_compose)?;
} else {
bail!("Unsupported runner: {}", self.app_compose.runner);
}
Ok(())
}
}

pub async fn tboot(args: &TbootArgs) -> Result<()> {
Expand Down
67 changes: 49 additions & 18 deletions teepod/src/console.html
Original file line number Diff line number Diff line change
Expand Up @@ -521,10 +521,16 @@ <h2>Deploy a new instance</h2>

<div class="form-group">
<label for="composeFile">Docker Compose File</label>
<textarea id="composeFile" v-model="vmForm.compose_file"
<textarea id="composeFile" v-model="vmForm.dockerComposeFile"
placeholder="Paste your docker-compose.yml here" required></textarea>
</div>

<div class="form-group">
<label for="preLaunchScript">Pre-launch Script</label>
<textarea id="preLaunchScript" v-model="vmForm.preLaunchScript"
placeholder="Optional: Bash script to run before starting containers"></textarea>
</div>

<div class="form-group full-width" v-if="config.portMappingEnabled">
<label>Port Mappings</label>
<div v-for="(port, index) in vmForm.ports" :key="index"
Expand Down Expand Up @@ -779,6 +785,9 @@ <h4 style="margin: 0 0 12px 0;">App Information</h4>
<h4 style="margin: 0 0 12px 0;">Docker Compose File</h4>
<pre
style="background: #f1f1f1; padding: 12px; border-radius: 4px; overflow-x: auto;">{{ vm.appCompose?.docker_compose_file }}</pre>
<h4 style="margin: 0 0 12px 0;">Pre-launch Script</h4>
<pre
style="background: #f1f1f1; padding: 12px; border-radius: 4px; overflow-x: auto;">{{ vm.appCompose?.pre_launch_script }}</pre>
</div>
</div>
</td>
Expand Down Expand Up @@ -818,14 +827,25 @@ <h3>Update VM Config</h3>
</select>
</div>

<div class="form-group">
<label for="upgradeFile">Upload New Compose File</label>
<input id="upgradeFile" type="file" @change="loadUpgradeFile" accept=".yml,.yaml,.txt">
<div style="display: flex; align-items: center; margin-top: 16px;">
<input type="checkbox" v-model="upgradeDialog.updateCompose" style="width: 16px; height: 16px;">
<span style="margin-left: 8px;">Update App Compose</span>
</div>
<div class="form-group">
<label for="upgradeCompose">Docker Compose File</label>
<textarea id="upgradeCompose" v-model="upgradeDialog.compose_file"
placeholder="Paste your new docker-compose.yml here" required></textarea>
<div v-if="upgradeDialog.updateCompose">
<div class="form-group">
<label for="upgradeFile">Upload New Compose File</label>
<input id="upgradeFile" type="file" @change="loadUpgradeFile" accept=".yml,.yaml,.txt">
</div>
<div class="form-group">
<label for="upgradeCompose">Docker Compose File</label>
<textarea id="upgradeCompose" v-model="upgradeDialog.dockerComposeFile"
placeholder="Paste your new docker-compose.yml here" required></textarea>
</div>
<div class="form-group">
<label for="upgradePrelauncher">Pre-launch Script</label>
<textarea id="upgradePrelauncher" v-model="upgradeDialog.preLaunchScript"
placeholder="Optional: Bash script to run before starting containers"></textarea>
</div>
</div>
<div style="display: flex; align-items: center; margin-top: 16px;">
<input type="checkbox" v-model="upgradeDialog.resetSecrets" style="width: 16px; height: 16px;">
Expand Down Expand Up @@ -931,7 +951,8 @@ <h3>Derive VM</h3>
const vmForm = ref({
name: '',
image: '',
compose_file: '',
dockerComposeFile: '',
preLaunchScript: '',
vcpu: 1,
memory: 1024,
disk_size: 20,
Expand All @@ -951,7 +972,9 @@ <h3>Derive VM</h3>
const upgradeDialog = ref({
show: false,
vm: null,
compose_file: '',
updateCompose: false,
dockerComposeFile: '',
preLaunchScript: '',
encrypted_envs: [],
resetSecrets: false,
vcpu: 0,
Expand Down Expand Up @@ -1035,7 +1058,7 @@ <h3>Derive VM</h3>
"manifest_version": 2,
"name": vmForm.value.name,
"runner": "docker-compose",
"docker_compose_file": vmForm.value.compose_file,
"docker_compose_file": vmForm.value.dockerComposeFile,
"docker_config": vmForm.value.docker_config.enabled ? {
"username": vmForm.value.docker_config.username,
"token_key": vmForm.value.docker_config.token_key,
Expand All @@ -1045,6 +1068,11 @@ <h3>Derive VM</h3>
"public_logs": vmForm.value.public_logs,
"public_sysinfo": vmForm.value.public_sysinfo
};

if (vmForm.value.preLaunchScript?.trim()) {
app_compose.pre_launch_script = vmForm.value.preLaunchScript;
}

const imgFeatures = imageVersionFeatures(imageVersion(vmForm.value.image));
if (imgFeatures.compose_version < 2) {
// Compatibility with old images
Expand All @@ -1058,7 +1086,7 @@ <h3>Derive VM</h3>
return JSON.stringify(app_compose);
};

const appIdOf = async (composeFile) => {
const calcAppId = async () => {
const app_compose = makeAppComposeFile();
const sha256Hash = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(app_compose));
return Array.from(new Uint8Array(sha256Hash)).map(b => b.toString(16).padStart(2, '0')).join('').slice(0, 40);
Expand Down Expand Up @@ -1101,7 +1129,7 @@ <h3>Derive VM</h3>
const makeEncryptedEnv = async (envs, kmsEnabled, appId) => {
if (!kmsEnabled || envs.length === 0) return '';
if (!appId) {
appId = await appIdOf(vmForm.value.compose_file);
appId = await calcAppId();
}
const response = await rpcCall('GetAppEnvEncryptPubKey', {
app_id: appId
Expand Down Expand Up @@ -1233,7 +1261,7 @@ <h3>Derive VM</h3>
if (file) {
const reader = new FileReader();
reader.onload = (e) => {
vmForm.value.compose_file = e.target.result;
vmForm.value.dockerComposeFile = e.target.result;
};
reader.readAsText(file);
}
Expand All @@ -1253,7 +1281,9 @@ <h3>Derive VM</h3>
upgradeDialog.value = {
show: true,
vm: vm,
compose_file: '',
updateCompose: false,
dockerComposeFile: vm.appCompose.docker_compose_file,
preLaunchScript: vm.appCompose.pre_launch_script,
resetSecrets: false,
vcpu: vm.configuration?.vcpu,
memory: vm.configuration?.memory,
Expand All @@ -1268,7 +1298,7 @@ <h3>Derive VM</h3>
if (file) {
const reader = new FileReader();
reader.onload = (e) => {
upgradeDialog.value.compose_file = e.target.result;
upgradeDialog.value.dockerComposeFile = e.target.result;
};
reader.readAsText(file);
}
Expand All @@ -1294,12 +1324,13 @@ <h3>Derive VM</h3>
const body = {
id: upgradeDialog.value.vm.id,
};
if (upgradeDialog.value.compose_file) {
if (upgradeDialog.value.updateCompose) {
const currentAppCompose = upgradeDialog.value.vm.appCompose;
const app_compose = {
...currentAppCompose,
docker_compose_file: upgradeDialog.value.compose_file
docker_compose_file: upgradeDialog.value.dockerComposeFile || currentAppCompose.docker_compose_file
};
app_compose.pre_launch_script = upgradeDialog.value.preLaunchScript?.trim();
body.compose_file = JSON.stringify(app_compose);
}

Expand Down
5 changes: 1 addition & 4 deletions teepod/src/main_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,11 +186,8 @@ impl TeepodRpc for RpcHandler {
runner: String,
docker_compose_file: Option<String>,
}
let app_compose: AppCompose =
let _app_compose: AppCompose =
serde_json::from_str(&request.compose_file).context("Invalid compose file")?;
if app_compose.docker_compose_file.is_none() {
bail!("Docker compose file cannot be empty");
}
}
let compose_file_path = self.compose_file_path(&request.id);
if !compose_file_path.exists() {
Expand Down