Skip to content
Closed
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
4 changes: 4 additions & 0 deletions docker/sandbox/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ COPY nix/nix.conf nix/registry.json /etc/nix/
# Nix looks for its state here, and without it falls back to a store in the
# user's home that needs namespaces the agents' user can't make.
RUN mkdir -p /nix/store /nix/var/nix && chown -R 1000:1000 /nix
# The pod's software, on the PATH of login shells, as agents' commands run,
# and of interactive ones, as in the dock's terminal.
COPY nix/software-path.sh /etc/profile.d/sugabots-software.sh
RUN echo '. /etc/profile.d/sugabots-software.sh' >> /etc/bash.bashrc

COPY sugabots-desktop /usr/local/bin/sugabots-desktop

Expand Down
6 changes: 6 additions & 0 deletions docker/sandbox/nix/software-path.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# The pod's software, which Sugabots installs into this Nix profile and keeps
# on every sandbox the pod has, ahead of the image's own.
case ":$PATH:" in
*:/nix/var/nix/profiles/sugabots/bin:*) ;;
*) PATH="/nix/var/nix/profiles/sugabots/bin:$PATH" ;;
esac
16 changes: 15 additions & 1 deletion packages/contracts/src/http/groups/pod-sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import {
newSandboxHostSchema,
podSandboxNetworkSchema,
podSandboxSchema,
podSandboxSoftwareSchema,
sandboxHostSchema,
sandboxPackageNameSchema,
sandboxSoftwareChannelSchema,
} from "../../sandbox-providers.ts";
import { uuidSchema } from "../../uuid.ts";
import { BadRequest, Conflict, refused } from "../errors.ts";
Expand All @@ -14,7 +17,8 @@ const params = { podId: uuidSchema };

/**
* A pod's sandbox: how it stands, starting it afresh or moving its work to the
* current image, and the hosts it may reach beyond what the workspace allows.
* current image, the hosts it may reach beyond what the workspace allows, and
* the software it has beyond its image.
*/
export class PodSandboxApi extends HttpApiGroup.make("podSandbox")
.add(
Expand Down Expand Up @@ -45,5 +49,15 @@ export class PodSandboxApi extends HttpApiGroup.make("podSandbox")
success: podSandboxNetworkSchema,
error: refused,
}),
HttpApiEndpoint.get("software", `${root}/software`, {
params,
success: podSandboxSoftwareSchema,
error: refused,
}),
HttpApiEndpoint.delete("removePackage", `${root}/software/:channel/:name`, {
params: { ...params, channel: sandboxSoftwareChannelSchema, name: sandboxPackageNameSchema },
success: podSandboxSoftwareSchema,
error: refused,
}),
)
.middleware(Session) {}
33 changes: 33 additions & 0 deletions packages/contracts/src/sandbox-providers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,3 +244,36 @@ export const podSandboxNetworkSchema = Schema.Struct({
export type PodSandboxNetwork = typeof podSandboxNetworkSchema.Type;

export const newSandboxHostSchema = Schema.Struct({ host: sandboxHostSchema });

/** Which nixpkgs a package comes from: a NixOS release, or unstable for newer versions. */
export const sandboxSoftwareChannelSchema = Schema.Literals(["stable", "unstable"]);

export type SandboxSoftwareChannel = typeof sandboxSoftwareChannelSchema.Type;

/**
* A package's attribute in nixpkgs, such as `ffmpeg` or
* `python3Packages.pandas`: names joined by dots, of letters, digits, `_`,
* `-` and `+`.
*/
export const sandboxPackageNameSchema = Schema.String.check(
Schema.isMaxLength(200),
Schema.isPattern(/^[A-Za-z_][A-Za-z0-9_+-]*(?:\.[A-Za-z_][A-Za-z0-9_+-]*)*$/, {
message: "Enter a nixpkgs package name, such as ffmpeg or python3Packages.pandas",
}),
);

/** Software a pod's sandbox has, each package at the nixpkgs commit it was installed from. */
export const podSandboxSoftwareSchema = Schema.Struct({
packages: Schema.Array(
Schema.Struct({
name: sandboxPackageNameSchema,
channel: sandboxSoftwareChannelSchema,
nixpkgsRev: Schema.String,
/** Who allowed the agent's request for it; null once they've left. */
addedByName: Schema.NullOr(Schema.String),
addedAt: isoTimestampSchema,
}),
),
});

export type PodSandboxSoftware = typeof podSandboxSoftwareSchema.Type;
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CREATE TABLE "sandbox_pod_package" (
"workspace_id" uuid NOT NULL,
"pod_id" uuid,
"name" text,
"channel" text,
"nixpkgs_rev" text NOT NULL,
"added_by_id" uuid,
"created_at" timestamp with time zone DEFAULT now() NOT NULL,
CONSTRAINT "sandbox_pod_package_pkey" PRIMARY KEY("pod_id","channel","name"),
CONSTRAINT "sandbox_pod_package_channel_check" CHECK ("channel" in ('stable', 'unstable'))
);
--> statement-breakpoint
ALTER TABLE "sandbox_pod_package" ADD CONSTRAINT "sandbox_pod_package_added_by_id_user_id_fkey" FOREIGN KEY ("added_by_id") REFERENCES "user"("id") ON DELETE SET NULL;--> statement-breakpoint
ALTER TABLE "sandbox_pod_package" ADD CONSTRAINT "sandbox_pod_package_pod_workspace_fkey" FOREIGN KEY ("pod_id","workspace_id") REFERENCES "pod"("id","workspace_id") ON DELETE CASCADE;
Loading
Loading