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
38 changes: 29 additions & 9 deletions src/workerd/api/container-test.c++
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class TracingRequestObserver final: public RequestObserver {
struct CapturedInstance {
bool isCustom = false;
kj::String named;
kj::String image;
double vcpu = 0;
uint64_t memoryMib = 0;
uint64_t diskMb = 0;
Expand All @@ -53,8 +54,13 @@ class MockContainerServer final: public rpc::Container::Server {
containerCalled(containerCalled) {}

kj::Promise<void> start(StartContext context) override {
auto instance = context.getParams().getInstance();
auto params = context.getParams();
auto instance = params.getInstance();
CapturedInstance captured;
auto source = params.getSource();
if (source.which() == rpc::Container::StartParams::Source::IMAGE) {
captured.image = kj::str(source.getImage());
}
switch (instance.which()) {
case rpc::Container::StartInstance::NAMED:
captured.named = kj::str(instance.getNamed());
Expand Down Expand Up @@ -633,10 +639,7 @@ KJ_TEST("Container::destroy updates running before restart and clears the old re
}

KJ_TEST("Container::start forwards a named instance type") {
capnp::MallocMessageBuilder message;
auto flags = message.initRoot<CompatibilityFlags>();
flags.setWorkerdExperimental(true);
auto fixture = TestFixture({.featureFlags = flags.asReader(), .useRealTimers = false});
auto fixture = makeFixture();
auto paf = kj::newPromiseAndFulfiller<CapturedInstance>();
auto promise = kj::mv(paf.promise);

Expand All @@ -657,10 +660,7 @@ KJ_TEST("Container::start forwards a named instance type") {
}

KJ_TEST("Container::start forwards custom instance resources") {
capnp::MallocMessageBuilder message;
auto flags = message.initRoot<CompatibilityFlags>();
flags.setWorkerdExperimental(true);
auto fixture = TestFixture({.featureFlags = flags.asReader(), .useRealTimers = false});
auto fixture = makeFixture();
auto paf = kj::newPromiseAndFulfiller<CapturedInstance>();
auto promise = kj::mv(paf.promise);

Expand All @@ -687,6 +687,26 @@ KJ_TEST("Container::start forwards custom instance resources") {
});
}

KJ_TEST("Container::start forwards an image") {
auto fixture = makeFixture();
auto paf = kj::newPromiseAndFulfiller<CapturedInstance>();
auto promise = kj::mv(paf.promise);

fixture.runInIoContext([promise = kj::mv(promise), fulfiller = kj::mv(paf.fulfiller)](
const TestFixture::Environment& env) mutable {
auto container = kj::rc<Container>(
rpc::Container::Client(kj::heap<MockContainerServer>(kj::mv(fulfiller))), false);
container->start(env.js,
Container::StartupOptions{
.image = kj::str("registry.example.com/image:tag"),
});
return kj::mv(promise)
.then([](CapturedInstance captured) {
KJ_EXPECT(captured.image == "registry.example.com/image:tag");
}).attach(kj::mv(container));
});
}

KJ_TEST("Container::snapshotDirectory propagates the current span context") {
bool directoryCalled = false;
bool containerCalled = false;
Expand Down
60 changes: 30 additions & 30 deletions src/workerd/api/container.c++
Original file line number Diff line number Diff line change
Expand Up @@ -365,42 +365,42 @@ void Container::start(jsg::Lock& js, jsg::Optional<StartupOptions> maybeOptions)
}
}

JSG_REQUIRE(options.image == kj::none || options.containerSnapshot == kj::none, TypeError,
"`image` and `containerSnapshot` are mutually exclusive.");
if (flags.getWorkerdExperimental()) {
JSG_REQUIRE(options.image == kj::none || options.containerSnapshot == kj::none, TypeError,
"`image` and `containerSnapshot` are mutually exclusive.");
KJ_IF_SOME(hardTimeoutMs, options.hardTimeout) {
JSG_REQUIRE(hardTimeoutMs > 0, RangeError, "Hard timeout must be greater than 0");
req.setHardTimeoutMs(hardTimeoutMs);
}
KJ_IF_SOME(image, options.image) {
JSG_REQUIRE(image.size() <= MAX_IMAGE_REFERENCE_SIZE, TypeError,
"Container image reference cannot exceed ", MAX_IMAGE_REFERENCE_SIZE, " bytes.");
for (auto c: image) {
auto byte = static_cast<kj::byte>(c);
JSG_REQUIRE(byte > 0x20 && byte < 0x7f, TypeError,
"Container image reference must contain only non-space printable ASCII characters.");
}
req.getSource().setImage(image);
}
KJ_IF_SOME(image, options.image) {
JSG_REQUIRE(image.size() <= MAX_IMAGE_REFERENCE_SIZE, TypeError,
"Container image reference cannot exceed ", MAX_IMAGE_REFERENCE_SIZE, " bytes.");
for (auto c: image) {
auto byte = static_cast<kj::byte>(c);
JSG_REQUIRE(byte > 0x20 && byte < 0x7f, TypeError,
"Container image reference must contain only non-space printable ASCII characters.");
}
KJ_IF_SOME(instance, options.instance) {
auto instanceBuilder = req.initInstance();
KJ_SWITCH_ONEOF(instance) {
KJ_CASE_ONEOF(named, kj::String) {
JSG_REQUIRE(
kj::arrayPtr(VALID_CONTAINER_INSTANCE_TYPES).findFirst(named.asPtr()) != kj::none,
TypeError, "Invalid container instance type.");
instanceBuilder.setNamed(named);
}
KJ_CASE_ONEOF(custom, StartResources) {
JSG_REQUIRE(std::isfinite(custom.vcpu) && custom.vcpu > 0, RangeError,
"Container resource vcpu must be a finite number greater than 0.");
auto memoryMib = requireResourceAmount(custom.memoryMib, "memoryMib"_kj);
auto diskMb = requireResourceAmount(custom.diskMb, "diskMb"_kj);
auto resources = instanceBuilder.initCustom();
resources.setVcpu(custom.vcpu);
resources.setMemoryMib(memoryMib);
resources.setDiskMb(diskMb);
}
req.getSource().setImage(image);
}
KJ_IF_SOME(instance, options.instance) {
auto instanceBuilder = req.initInstance();
KJ_SWITCH_ONEOF(instance) {
KJ_CASE_ONEOF(named, kj::String) {
JSG_REQUIRE(
kj::arrayPtr(VALID_CONTAINER_INSTANCE_TYPES).findFirst(named.asPtr()) != kj::none,
TypeError, "Invalid container instance type.");
instanceBuilder.setNamed(named);
}
KJ_CASE_ONEOF(custom, StartResources) {
JSG_REQUIRE(std::isfinite(custom.vcpu) && custom.vcpu > 0, RangeError,
"Container resource vcpu must be a finite number greater than 0.");
auto memoryMib = requireResourceAmount(custom.memoryMib, "memoryMib"_kj);
auto diskMb = requireResourceAmount(custom.diskMb, "diskMb"_kj);
auto resources = instanceBuilder.initCustom();
resources.setVcpu(custom.vcpu);
resources.setMemoryMib(memoryMib);
resources.setDiskMb(diskMb);
}
}
}
Expand Down
20 changes: 14 additions & 6 deletions src/workerd/api/container.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,17 +301,25 @@ class Container: public jsg::Object {
}
));
} else {
JSG_TS_OVERRIDE(ContainerStartupOptions {
JSG_TS_OVERRIDE(type ContainerStartupOptions = {
entrypoint?: string[];
enableInternet: boolean;
env?: Record<string, string>;
hardTimeout?: never;
image?: never;
instance?: never;
instance?: "lite" | "standard-1" | "standard-2" | "standard-3" | "standard-4" | ContainerStartResources;
labels?: Record<string, string>;
directorySnapshots?: ContainerDirectorySnapshotRestoreParams[];
containerSnapshot?: ContainerSnapshotRestoreParams;
});
} & (
| {
/** Cannot be used with `containerSnapshot`. */
image: string;
containerSnapshot?: never;
}
| {
image?: never;
/** Cannot be used with `image`. */
containerSnapshot?: ContainerSnapshotRestoreParams;
}
));
}
}
};
Expand Down
21 changes: 18 additions & 3 deletions types/generated-snapshot/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4003,14 +4003,29 @@ interface ContainerSnapshotRestoreParams {
interface ContainerSnapshotOptions {
name?: string;
}
interface ContainerStartupOptions {
type ContainerStartupOptions = {
entrypoint?: string[];
enableInternet: boolean;
env?: Record<string, string>;
instance?:
| "lite"
| "standard-1"
| "standard-2"
| "standard-3"
| "standard-4"
| ContainerStartResources;
labels?: Record<string, string>;
directorySnapshots?: ContainerDirectorySnapshotRestoreParams[];
containerSnapshot?: ContainerSnapshotRestoreParams;
}
} & (
| {
image: string;
containerSnapshot?: never;
}
| {
image?: never;
containerSnapshot?: ContainerSnapshotRestoreParams;
}
);
interface ContainerStartResources {
vcpu: number;
memoryMib: number;
Expand Down
21 changes: 18 additions & 3 deletions types/generated-snapshot/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4012,14 +4012,29 @@ export interface ContainerSnapshotRestoreParams {
export interface ContainerSnapshotOptions {
name?: string;
}
export interface ContainerStartupOptions {
export type ContainerStartupOptions = {
entrypoint?: string[];
enableInternet: boolean;
env?: Record<string, string>;
instance?:
| "lite"
| "standard-1"
| "standard-2"
| "standard-3"
| "standard-4"
| ContainerStartResources;
labels?: Record<string, string>;
directorySnapshots?: ContainerDirectorySnapshotRestoreParams[];
containerSnapshot?: ContainerSnapshotRestoreParams;
}
} & (
| {
image: string;
containerSnapshot?: never;
}
| {
image?: never;
containerSnapshot?: ContainerSnapshotRestoreParams;
}
);
export interface ContainerStartResources {
vcpu: number;
memoryMib: number;
Expand Down
Loading