Skip to content

Commit

Permalink
Merge of #128
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Mar 17, 2024
2 parents ca3a38e + d0d4b96 commit da66117
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 92 deletions.
4 changes: 2 additions & 2 deletions containers/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion containers/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@winglibs/containers",
"version": "0.0.22",
"version": "0.0.23",
"description": "Container support for Wing",
"repository": {
"type": "git",
Expand Down
185 changes: 96 additions & 89 deletions containers/workload.sim.w
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ bring "./utils.w" as utils;
pub class Workload_sim {
publicUrlKey: str?;
internalUrlKey: str?;
containerIdKey: str;

pub publicUrl: str?;
pub internalUrl: str?;
Expand All @@ -18,12 +17,12 @@ pub class Workload_sim {
imageTag: str;
public: bool;
state: sim.State;

new(props: api.WorkloadProps) {
this.appDir = utils.entrypointDir(this);
this.props = props;
this.state = new sim.State();
this.containerIdKey = "container_id";
let containerName = util.uuidv4();

let hash = utils.resolveContentHash(this, props);
if let hash = hash {
Expand All @@ -50,109 +49,117 @@ pub class Workload_sim {
this.internalUrlKey = key;
}

let s = new cloud.Service(inflight () => {
this.start();
return () => { this.stop(); };
});

std.Node.of(s).hidden = true;
std.Node.of(this.state).hidden = true;
}

inflight start(): void {
log("starting workload...");
let containerService = new cloud.Service(inflight () => {
log("starting workload...");

let opts = this.props;
let opts = this.props;

// if this a reference to a local directory, build the image from a docker file
if utils.isPathInflight(opts.image) {
// check if the image is already built
try {
utils.shell("docker", ["inspect", this.imageTag]);
log("image {this.imageTag} already exists");
} catch {
log("building locally from {opts.image} and tagging {this.imageTag}...");
utils.shell("docker", ["build", "-t", this.imageTag, opts.image], this.appDir);
}
} else {
try {
utils.shell("docker", ["inspect", this.imageTag]);
log("image {this.imageTag} already exists");
} catch {
log("pulling {this.imageTag}");
utils.shell("docker", ["pull", this.imageTag]);
// if this a reference to a local directory, build the image from a docker file
if utils.isPathInflight(opts.image) {
// check if the image is already built
try {
utils.shell("docker", ["inspect", this.imageTag]);
log("image {this.imageTag} already exists");
} catch {
log("building locally from {opts.image} and tagging {this.imageTag}...");
utils.shell("docker", ["build", "-t", this.imageTag, opts.image], this.appDir);
}
} else {
try {
utils.shell("docker", ["inspect", this.imageTag]);
log("image {this.imageTag} already exists");
} catch {
log("pulling {this.imageTag}");
utils.shell("docker", ["pull", this.imageTag]);
}
}
}

// start the new container
let dockerRun = MutArray<str>[];
dockerRun.push("run");
dockerRun.push("--detach");
// start the new container
let dockerRun = MutArray<str>[];
dockerRun.push("run");
dockerRun.push("--detach");
dockerRun.push("--rm");

if let port = opts.port {
dockerRun.push("-p");
dockerRun.push("{port}");
}
dockerRun.push("--name", containerName);

if let env = opts.env {
if env.size() > 0 {
dockerRun.push("-e");
for k in env.keys() {
dockerRun.push("{k}={env.get(k)!}");
}
if let port = opts.port {
dockerRun.push("-p");
dockerRun.push("{port}");
}
}

dockerRun.push(this.imageTag);

if let runArgs = this.props.args {
for a in runArgs {
dockerRun.push(a);
if let env = opts.env {
if env.size() > 0 {
dockerRun.push("-e");
for k in env.keys() {
dockerRun.push("{k}={env.get(k)!}");
}
}
}
}

log("starting container from image {this.imageTag}");
log("docker {dockerRun.join(" ")}");
let containerId = utils.shell("docker", dockerRun.copy()).trim();
this.state.set(this.containerIdKey, containerId);
dockerRun.push(this.imageTag);

log("containerId={containerId}");
if let runArgs = this.props.args {
for a in runArgs {
dockerRun.push(a);
}
}

let out = Json.parse(utils.shell("docker", ["inspect", containerId]));
log("starting container from image {this.imageTag}");
log("docker {dockerRun.join(" ")}");
utils.shell("docker", dockerRun.copy());

log("containerName={containerName}");

return () => {
utils.shell("docker", ["rm", "-f", containerName]);
};
}) as "ContainerService";
std.Node.of(containerService).hidden = true;

let readinessService = new cloud.Service(inflight () => {
let opts = this.props;
let var out: Json? = nil;
util.waitUntil(inflight () => {
try {
out = Json.parse(utils.shell("docker", ["inspect", containerName]));
return true;
} catch {
log("something went wrong");
return false;
}
}, interval: 0.1s);

if let port = opts.port {
let hostPort = out.tryGetAt(0)?.tryGet("NetworkSettings")?.tryGet("Ports")?.tryGet("{port}/tcp")?.tryGetAt(0)?.tryGet("HostPort")?.tryAsStr();
if !hostPort? {
throw "Container does not listen to port {port}";
}
if let port = opts.port {
let hostPort = out?.tryGetAt(0)?.tryGet("NetworkSettings")?.tryGet("Ports")?.tryGet("{port}/tcp")?.tryGetAt(0)?.tryGet("HostPort")?.tryAsStr();
if !hostPort? {
throw "Container does not listen to port {port}";
}

let publicUrl = "http://localhost:{hostPort!}";
let publicUrl = "http://localhost:{hostPort!}";

if let k = this.publicUrlKey {
this.state.set(k, publicUrl);
}
if let k = this.publicUrlKey {
this.state.set(k, publicUrl);
}

if let k = this.internalUrlKey {
this.state.set(k, "http://host.docker.internal:{hostPort!}");
}
if let k = this.internalUrlKey {
this.state.set(k, "http://host.docker.internal:{hostPort!}");
}

if let readiness = opts.readiness {
let readinessUrl = "{publicUrl}{readiness}";
log("waiting for container to be ready: {readinessUrl}...");
util.waitUntil(inflight () => {
try {
return http.get(readinessUrl).ok;
} catch {
return false;
}
}, interval: 0.1s);
if let readiness = opts.readiness {
let readinessUrl = "{publicUrl}{readiness}";
log("waiting for container to be ready: {readinessUrl}...");
util.waitUntil(inflight () => {
try {
return http.get(readinessUrl).ok;
} catch {
return false;
}
}, interval: 0.1s);
}
}
}
}
}) as "ReadinessService";
std.Node.of(readinessService).hidden = true;

inflight stop() {
let containerId = this.state.get(this.containerIdKey).asStr();
log("stopping container {containerId}");
utils.shell("docker", ["rm", "-f", containerId]);
std.Node.of(this.state).hidden = true;
}
}
}

0 comments on commit da66117

Please sign in to comment.