Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Demuxing revamp and CLIs #11

Merged
merged 12 commits into from
Jan 31, 2024
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
1 change: 1 addition & 0 deletions .devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"cpushares",
"Datacenter",
"demux",
"demultiplexing",
"dind",
"Dnsrr",
"Domainname",
Expand Down
9 changes: 0 additions & 9 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,5 @@ module.exports = {
{ format: null, selector: "parameter", filter: { regex: "^_", match: false } },
],
},
overrides: [
{
files: ["./src/schemas.ts"],
rules: {
"max-lines": "off",
"unicorn/prevent-abbreviations": "off",
},
},
],
ignorePatterns: ["dist/", ".eslintrc.cjs"],
};
20 changes: 19 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# the-moby-effect

Moby API client built using [effect-ts](http://effect.website). If you want documentation, please consider reading [The Docker API documentation](https://docs.docker.com/engine/api/latest), it is very well written and there is nothing in this library that wouldn't be in there (plus I would just do a worse job if I tried to write my interpretation of their documentation here). If you are just looking for some examples to get your feet underneath you quickly with effect integration, then I do have some of those [here](./examples/).
Moby API client and CLI client built using [effect-ts](http://effect.website). If you want documentation, please consider reading [The Docker API documentation](https://docs.docker.com/engine/api/latest), it is very well written and there is nothing in this library that wouldn't be in there (plus I would just do a worse job if I tried to write my interpretation of their documentation here). If you are just looking for some examples to get your feet underneath you quickly with effect integration, then I do have some of those [here](./examples/).

## Goals :white_check_mark:

Expand All @@ -12,6 +12,23 @@ Moby API client built using [effect-ts](http://effect.website). If you want docu
- [x] - tests, examples, and in-line JSDoc comments based on the moby api documentation
- [x] - Strong focus on types and typescript support
- [x] - Support multiple "engines" (docker, podman, ect). If its built on top of [moby](https://github.com/moby/moby) then it _should_ just work, however, __currently only docker is tested against__
- [ ] - Implement all common docker commands except for login/logout because I don't want to interact with credential helpers

## Common docker commands implemented as CLIs
```
run Create and run a new container from an image
exec Execute a command in a running container
ps List containers
build Build an image from a Dockerfile
pull Download an image from a registry
push Upload an image to a registry
images List images
login Log in to a registry
logout Log out from a registry
search Search Docker Hub for images
version Show the Docker version information
info Display system-wide information
```

## Non-Goals :wastebasket:

Expand All @@ -21,6 +38,7 @@ Moby API client built using [effect-ts](http://effect.website). If you want docu

## Todo/Future :bulb:
- Add more examples
- Finish implementing all common docker commands
- Maybe add tests against something else other than docker like podman?

## Compatibility :closed_lock_with_key:
Expand Down
14 changes: 14 additions & 0 deletions bin/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
Implements all the common docker cli commands except for login and logout because I don't want to have to deal with credential helpers

```
run Create and run a new container from an image
exec Execute a command in a running container
ps List containers
build Build an image from a Dockerfile
pull Download an image from a registry
push Upload an image to a registry
images List images
search Search Docker Hub for images
version Show the Docker version information
info Display system-wide information
```
Empty file added bin/build.ts
Empty file.
Empty file added bin/cli.ts
Empty file.
Empty file added bin/exec.ts
Empty file.
Empty file added bin/images.ts
Empty file.
Empty file added bin/info.ts
Empty file.
Empty file added bin/ps.ts
Empty file.
Empty file added bin/pull.ts
Empty file.
Empty file added bin/push.ts
Empty file.
Empty file added bin/run.ts
Empty file.
Empty file added bin/search.ts
Empty file.
Empty file added bin/version.ts
Empty file.
14 changes: 5 additions & 9 deletions examples/container-attach.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import * as NodeSocket from "@effect/experimental/Socket";
import * as NodeRuntime from "@effect/platform-node/Runtime";
import * as Console from "effect/Console";
import * as Effect from "effect/Effect";
Expand All @@ -13,8 +12,8 @@ const localDocker: MobyApi.MobyApi = MobyApi.fromConnectionOptions({
const program = Effect.gen(function* (_: Effect.Adapter) {
const containers: MobyApi.Containers.Containers = yield* _(MobyApi.Containers.Containers);

const { Id: containerId, Name: containerName } = yield* _(
MobyApi.run({
const { Id: containerId } = yield* _(
MobyApi.DockerCommon.runScoped({
imageOptions: { kind: "pull", fromImage: "docker.io/library/alpine:latest" },
containerOptions: {
spec: {
Expand All @@ -30,7 +29,7 @@ const program = Effect.gen(function* (_: Effect.Adapter) {
})
);

const socket: NodeSocket.Socket = yield* _(
const socket = yield* _(
containers.attach({
id: containerId!,
stdin: true,
Expand All @@ -41,11 +40,8 @@ const program = Effect.gen(function* (_: Effect.Adapter) {
})
);

yield* _(MobyApi.demuxToStdinAndStdout(socket));

yield* _(MobyApi.DemuxHelpers.demuxSocketFromStdinToStdoutAndStderr(socket));
yield* _(Console.log("Disconnected from container"));
yield* _(Console.log(`Removing container ${containerName}...`));
yield* _(containers.delete({ id: containerId!, force: true }));
});

program.pipe(Effect.provide(localDocker)).pipe(NodeRuntime.runMain);
program.pipe(Effect.provide(localDocker)).pipe(Effect.scoped).pipe(NodeRuntime.runMain);
2 changes: 1 addition & 1 deletion examples/container-top.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const program = Effect.gen(function* (_: Effect.Adapter) {
const containers: MobyApi.Containers.Containers = yield* _(MobyApi.Containers.Containers);

const containerInspectResponse: MobyApi.Schemas.ContainerInspectResponse = yield* _(
MobyApi.run({
MobyApi.DockerCommon.run({
imageOptions: { kind: "pull", fromImage: "ubuntu:latest" },
containerOptions: {
spec: { Image: "ubuntu:latest", Cmd: ["sleep", "infinity"] },
Expand Down
2 changes: 1 addition & 1 deletion examples/container-with-volume.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const program = Effect.gen(function* (_: Effect.Adapter) {
const containers: MobyApi.Containers.Containers = yield* _(MobyApi.Containers.Containers);

const containerInspectResponse: MobyApi.Schemas.ContainerInspectResponse = yield* _(
MobyApi.run({
MobyApi.DockerCommon.run({
imageOptions: { kind: "pull", fromImage: "ubuntu:latest" },
containerOptions: {
spec: {
Expand Down
35 changes: 14 additions & 21 deletions examples/execs.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import * as NodeSocket from "@effect/experimental/Socket";
import * as NodeRuntime from "@effect/platform-node/Runtime";
import * as Effect from "effect/Effect";

Expand All @@ -10,36 +9,30 @@ const localDocker: MobyApi.MobyApi = MobyApi.fromConnectionOptions({
});

const program = Effect.gen(function* (_: Effect.Adapter) {
const execs: MobyApi.Execs.Execs = yield* _(MobyApi.Execs.Execs);
const containers: MobyApi.Containers.Containers = yield* _(MobyApi.Containers.Containers);

const containerInspectResponse: MobyApi.Schemas.ContainerInspectResponse = yield* _(
MobyApi.run({
MobyApi.DockerCommon.runScoped({
imageOptions: { kind: "pull", fromImage: "ubuntu:latest" },
containerOptions: {
spec: { Image: "ubuntu:latest", Cmd: ["sleep", "infinity"] },
},
})
);

const execCreateResponse: Readonly<MobyApi.Schemas.IdResponse> = yield* _(
execs.container({
id: containerInspectResponse.Id!,
execConfig: {
Cmd: ["echo", "hello world"],
AttachStdout: true,
AttachStderr: true,
const socket = yield* _(
MobyApi.DockerCommon.exec(
{
id: containerInspectResponse.Id!,
execConfig: {
Cmd: ["echo", "hello world"],
AttachStdout: true,
AttachStderr: true,
},
},
})
);

const socket: NodeSocket.Socket = yield* _(
execs.start({ id: execCreateResponse.Id!, execStartConfig: { Detach: false } })
{ Detach: false }
)
);

yield* _(MobyApi.demuxToStdinAndStdout(socket));
yield* _(containers.kill({ id: containerInspectResponse.Id! }));
yield* _(containers.delete({ id: containerInspectResponse.Id! }));
yield* _(MobyApi.DemuxHelpers.demuxSocketFromStdinToStdoutAndStderr(socket));
});

program.pipe(Effect.provide(localDocker)).pipe(NodeRuntime.runMain);
program.pipe(Effect.provide(localDocker)).pipe(Effect.scoped).pipe(NodeRuntime.runMain);
32 changes: 16 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,26 @@
"ssh2": "^1.15.0"
},
"devDependencies": {
"@effect/experimental": "0.6.2",
"@effect/platform": "0.41.0",
"@effect/platform-node": "0.41.0",
"@effect/schema": "0.59.1",
"@rushstack/eslint-config": "3.5.1",
"@rushstack/heft": "0.63.6",
"@rushstack/heft-jest-plugin": "0.10.8",
"@rushstack/heft-lint-plugin": "0.2.16",
"@rushstack/heft-typescript-plugin": "0.2.16",
"@effect/experimental": "0.6.8",
"@effect/platform": "0.42.4",
"@effect/platform-node": "0.41.5",
"@effect/schema": "0.60.4",
"@rushstack/eslint-config": "3.6.0",
"@rushstack/heft": "0.64.0",
"@rushstack/heft-jest-plugin": "0.11.0",
"@rushstack/heft-lint-plugin": "0.3.0",
"@rushstack/heft-typescript-plugin": "0.3.0",
"@types/heft-jest": "1.0.6",
"@types/node": "20.11.0",
"@types/node": "20.11.5",
"@types/ssh2": "1.11.18",
"@types/tar-fs": "2.0.4",
"effect": "2.0.3",
"effect": "2.1.1",
"eslint": "8.56.0",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-prettier": "5.1.3",
"eslint-plugin-unicorn": "50.0.1",
"fast-check": "3.15.0",
"prettier": "3.2.1",
"prettier": "3.2.4",
"prettier-plugin-jsdoc": "1.3.0",
"prettier-plugin-packagejson": "2.4.9",
"tar-fs": "3.0.4",
Expand All @@ -53,10 +53,10 @@
"ws": "8.16.0"
},
"peerDependencies": {
"@effect/experimental": "0.6.2",
"@effect/platform-node": "~0.41.0",
"@effect/schema": "~0.59.1",
"effect": "~2.0.3"
"@effect/experimental": "0.6.8",
"@effect/platform-node": "~0.41.5",
"@effect/schema": "~0.60.4",
"effect": "~2.1.1"
},
"engines": {
"node": ">=16"
Expand Down
Loading