// AUTO-GENERATED BY DAGGER_GLEAM - DO NOT EDIT import dagger/types.{type Client, type Try} as types import dagger/interpreter import dagger/dsl/types as t import gleam/dynamic/decode import gleam/list import gleam/option.{type Option, None, Some} pub type Opts { Opts( platform: Option(String), args: Option(List(String)), use_entrypoint: Option(Bool), experimental_privileged_nesting: Option(Bool), insecure_root_capabilities: Option(Bool), expand: Option(Bool), no_init: Option(Bool), platform_variants: Option(List(t.Container)), forced_compression: Option(t.ImageLayerCompression), media_types: Option(t.ImageMediaTypes), expected_type: Option(t.ExistsType), do_not_follow_symlinks: Option(Bool), tag: Option(String), cmd: Option(List(String)), random: Option(Bool), ports: Option(List(t.PortForward)), exclude: Option(List(String)), include: Option(List(String)), gitignore: Option(Bool), owner: Option(String), keep_default_args: Option(Bool), stdin: Option(String), redirect_stdin: Option(String), redirect_stdout: Option(String), redirect_stderr: Option(String), expect: Option(t.ReturnType), protocol: Option(t.NetworkProtocol), description: Option(String), experimental_skip_healthcheck: Option(Bool), permissions: Option(Int), source: Option(t.Directory), sharing: Option(t.CacheSharingMode), mode: Option(Int), size: Option(Int), ) } fn defaults() -> Opts { Opts( platform: None, args: None, use_entrypoint: None, experimental_privileged_nesting: None, insecure_root_capabilities: None, expand: None, no_init: None, platform_variants: None, forced_compression: None, media_types: None, expected_type: None, do_not_follow_symlinks: None, tag: None, cmd: None, random: None, ports: None, exclude: None, include: None, gitignore: None, owner: None, keep_default_args: None, stdin: None, redirect_stdin: None, redirect_stdout: None, redirect_stderr: None, expect: None, protocol: None, description: None, experimental_skip_healthcheck: None, permissions: None, source: None, sharing: None, mode: None, size: None, ) } pub fn none(opts: Opts) -> Opts { opts } pub fn opt_platform(opts: Opts, val: String) -> Opts { Opts(..opts, platform: Some(val)) } pub fn args(opts: Opts, val: List(String)) -> Opts { Opts(..opts, args: Some(val)) } pub fn use_entrypoint(opts: Opts, val: Bool) -> Opts { Opts(..opts, use_entrypoint: Some(val)) } pub fn experimental_privileged_nesting(opts: Opts, val: Bool) -> Opts { Opts(..opts, experimental_privileged_nesting: Some(val)) } pub fn insecure_root_capabilities(opts: Opts, val: Bool) -> Opts { Opts(..opts, insecure_root_capabilities: Some(val)) } pub fn expand(opts: Opts, val: Bool) -> Opts { Opts(..opts, expand: Some(val)) } pub fn no_init(opts: Opts, val: Bool) -> Opts { Opts(..opts, no_init: Some(val)) } pub fn platform_variants(opts: Opts, val: List(t.Container)) -> Opts { Opts(..opts, platform_variants: Some(val)) } pub fn forced_compression(opts: Opts, val: t.ImageLayerCompression) -> Opts { Opts(..opts, forced_compression: Some(val)) } pub fn media_types(opts: Opts, val: t.ImageMediaTypes) -> Opts { Opts(..opts, media_types: Some(val)) } pub fn expected_type(opts: Opts, val: t.ExistsType) -> Opts { Opts(..opts, expected_type: Some(val)) } pub fn do_not_follow_symlinks(opts: Opts, val: Bool) -> Opts { Opts(..opts, do_not_follow_symlinks: Some(val)) } pub fn tag(opts: Opts, val: String) -> Opts { Opts(..opts, tag: Some(val)) } pub fn cmd(opts: Opts, val: List(String)) -> Opts { Opts(..opts, cmd: Some(val)) } pub fn random(opts: Opts, val: Bool) -> Opts { Opts(..opts, random: Some(val)) } pub fn ports(opts: Opts, val: List(t.PortForward)) -> Opts { Opts(..opts, ports: Some(val)) } pub fn exclude(opts: Opts, val: List(String)) -> Opts { Opts(..opts, exclude: Some(val)) } pub fn include(opts: Opts, val: List(String)) -> Opts { Opts(..opts, include: Some(val)) } pub fn gitignore(opts: Opts, val: Bool) -> Opts { Opts(..opts, gitignore: Some(val)) } pub fn owner(opts: Opts, val: String) -> Opts { Opts(..opts, owner: Some(val)) } pub fn keep_default_args(opts: Opts, val: Bool) -> Opts { Opts(..opts, keep_default_args: Some(val)) } pub fn stdin(opts: Opts, val: String) -> Opts { Opts(..opts, stdin: Some(val)) } pub fn redirect_stdin(opts: Opts, val: String) -> Opts { Opts(..opts, redirect_stdin: Some(val)) } pub fn redirect_stdout(opts: Opts, val: String) -> Opts { Opts(..opts, redirect_stdout: Some(val)) } pub fn redirect_stderr(opts: Opts, val: String) -> Opts { Opts(..opts, redirect_stderr: Some(val)) } pub fn expect(opts: Opts, val: t.ReturnType) -> Opts { Opts(..opts, expect: Some(val)) } pub fn protocol(opts: Opts, val: t.NetworkProtocol) -> Opts { Opts(..opts, protocol: Some(val)) } pub fn description(opts: Opts, val: String) -> Opts { Opts(..opts, description: Some(val)) } pub fn experimental_skip_healthcheck(opts: Opts, val: Bool) -> Opts { Opts(..opts, experimental_skip_healthcheck: Some(val)) } pub fn permissions(opts: Opts, val: Int) -> Opts { Opts(..opts, permissions: Some(val)) } pub fn source(opts: Opts, val: t.Directory) -> Opts { Opts(..opts, source: Some(val)) } pub fn sharing(opts: Opts, val: t.CacheSharingMode) -> Opts { Opts(..opts, sharing: Some(val)) } pub fn mode(opts: Opts, val: Int) -> Opts { Opts(..opts, mode: Some(val)) } pub fn size(opts: Opts, val: Int) -> Opts { Opts(..opts, size: Some(val)) } fn encode_container(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.platform { Some(val) -> Ok(#("platform", types.GString(val))) None -> Error(Nil) } ], fn(x) { x }) } pub fn container(with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "container", args: encode_container(opts), subfields: []) t.Container(op: types.Pure([field])) } fn encode_as_service(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.args { Some(val) -> Ok(#("args", types.GList(list.map(val, fn(x) { types.GString(x) })))) None -> Error(Nil) }, case opts.use_entrypoint { Some(val) -> Ok(#("useEntrypoint", types.GBool(val))) None -> Error(Nil) }, case opts.experimental_privileged_nesting { Some(val) -> Ok(#("experimentalPrivilegedNesting", types.GBool(val))) None -> Error(Nil) }, case opts.insecure_root_capabilities { Some(val) -> Ok(#("insecureRootCapabilities", types.GBool(val))) None -> Error(Nil) }, case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) }, case opts.no_init { Some(val) -> Ok(#("noInit", types.GBool(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Turn the container into a Service. /// Be sure to set any exposed ports before this conversion. pub fn as_service(parent: t.Container, with with_fn: fn(Opts) -> Opts) -> t.Service { let opts = with_fn(defaults()) let field = types.Field(name: "asService", args: encode_as_service(opts), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Service(op: new_op) } fn encode_as_tarball(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.platform_variants { Some(val) -> Ok(#("platformVariants", types.GList(list.map(val, fn(x) { types.GDeferred(x.op) })))) None -> Error(Nil) }, case opts.forced_compression { Some(val) -> Ok(#("forcedCompression", types.GString(t.image_layer_compression_to_json(val)))) None -> Error(Nil) }, case opts.media_types { Some(val) -> Ok(#("mediaTypes", types.GString(t.image_media_types_to_json(val)))) None -> Error(Nil) } ], fn(x) { x }) } /// Package the container state as an OCI image, and return it as a tar archive pub fn as_tarball(parent: t.Container, with with_fn: fn(Opts) -> Opts) -> t.File { let opts = with_fn(defaults()) let field = types.Field(name: "asTarball", args: encode_as_tarball(opts), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.File(op: new_op) } /// The combined buffered standard output and standard error stream of the last executed command /// Returns an error if no command was executed pub fn combined_output(parent: t.Container, client client: Client, then handler: fn(Try(String)) -> a) -> a { let field = types.Field(name: "combinedOutput", args: [], subfields: []) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.string)) { Ok(val) -> types.Pure(Ok(val)) Error(_) -> types.Pure(Error(types.DecodingError("combinedOutput"))) } } ) } handler(interpreter.run(op, client)) } /// Return the container's default arguments. pub fn default_args(parent: t.Container, client client: Client, then handler: fn(Try(List(String))) -> a) -> a { let field = types.Field(name: "defaultArgs", args: [], subfields: []) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.list(decode.string))) { Ok(val) -> types.Pure(Ok(val)) Error(_) -> types.Pure(Error(types.DecodingError("defaultArgs"))) } } ) } handler(interpreter.run(op, client)) } fn encode_directory(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Retrieve a directory from the container's root filesystem /// Mounts are included. pub fn directory(parent: t.Container, path path: String, with with_fn: fn(Opts) -> Opts) -> t.Directory { let opts = with_fn(defaults()) let field = types.Field(name: "directory", args: list.append([#("path", types.GString(path))], encode_directory(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Directory(op: new_op) } /// Return the container's OCI entrypoint. pub fn entrypoint(parent: t.Container, client client: Client, then handler: fn(Try(List(String))) -> a) -> a { let field = types.Field(name: "entrypoint", args: [], subfields: []) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.list(decode.string))) { Ok(val) -> types.Pure(Ok(val)) Error(_) -> types.Pure(Error(types.DecodingError("entrypoint"))) } } ) } handler(interpreter.run(op, client)) } /// Retrieves the value of the specified environment variable. pub fn env_variable(parent: t.Container, name name: String, client client: Client, then handler: fn(Try(String)) -> a) -> a { let field = types.Field(name: "envVariable", args: [#("name", types.GString(name))], subfields: []) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.string)) { Ok(val) -> types.Pure(Ok(val)) Error(_) -> types.Pure(Error(types.DecodingError("envVariable"))) } } ) } handler(interpreter.run(op, client)) } /// Retrieves the list of environment variables passed to commands. pub fn env_variables(parent: t.Container, select select: fn(t.EnvVariable) -> List(types.Field), client client: Client, then handler: fn(Try(List(t.EnvVariable))) -> a) -> a { let subfields = select(t.EnvVariable(op: types.Pure([]))) let field = types.Field(name: "envVariables", args: [], subfields: subfields) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.list(decode.dynamic))) { Ok(items) -> types.Pure(Ok(list.map(items, fn(_) { t.EnvVariable(op: types.Pure(full_query)) }))) Error(_) -> types.Pure(Error(types.DecodingError("envVariables"))) } } ) } handler(interpreter.run(op, client)) } fn encode_exists(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expected_type { Some(val) -> Ok(#("expectedType", types.GString(t.exists_type_to_json(val)))) None -> Error(Nil) }, case opts.do_not_follow_symlinks { Some(val) -> Ok(#("doNotFollowSymlinks", types.GBool(val))) None -> Error(Nil) } ], fn(x) { x }) } /// check if a file or directory exists pub fn exists(parent: t.Container, path path: String, with with_fn: fn(Opts) -> Opts, client client: Client, then handler: fn(Try(Bool)) -> a) -> a { let opts = with_fn(defaults()) let field = types.Field(name: "exists", args: list.append([#("path", types.GString(path))], encode_exists(opts)), subfields: []) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.bool)) { Ok(val) -> types.Pure(Ok(val)) Error(_) -> types.Pure(Error(types.DecodingError("exists"))) } } ) } handler(interpreter.run(op, client)) } /// The exit code of the last executed command /// Returns an error if no command was executed pub fn exit_code(parent: t.Container, client client: Client, then handler: fn(Try(Int)) -> a) -> a { let field = types.Field(name: "exitCode", args: [], subfields: []) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.int)) { Ok(val) -> types.Pure(Ok(val)) Error(_) -> types.Pure(Error(types.DecodingError("exitCode"))) } } ) } handler(interpreter.run(op, client)) } /// EXPERIMENTAL API! Subject to change/removal at any time. /// Configures all available GPUs on the host to be accessible to this container. /// This currently works for Nvidia devices only. pub fn experimental_with_all_g_p_us(parent: t.Container) -> t.Container { let field = types.Field(name: "experimentalWithAllGPUs", args: [], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// EXPERIMENTAL API! Subject to change/removal at any time. /// Configures the provided list of devices to be accessible to this container. /// This currently works for Nvidia devices only. pub fn experimental_with_g_p_u(parent: t.Container, devices devices: List(String)) -> t.Container { let field = types.Field(name: "experimentalWithGPU", args: [#("devices", types.GList(list.map(devices, fn(x) { types.GString(x) })))], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_export(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) }, case opts.platform_variants { Some(val) -> Ok(#("platformVariants", types.GList(list.map(val, fn(x) { types.GDeferred(x.op) })))) None -> Error(Nil) }, case opts.forced_compression { Some(val) -> Ok(#("forcedCompression", types.GString(t.image_layer_compression_to_json(val)))) None -> Error(Nil) }, case opts.media_types { Some(val) -> Ok(#("mediaTypes", types.GString(t.image_media_types_to_json(val)))) None -> Error(Nil) } ], fn(x) { x }) } /// Writes the container as an OCI tarball to the destination file path on the host. /// It can also export platform variants. pub fn export(parent: t.Container, path path: String, with with_fn: fn(Opts) -> Opts, client client: Client, then handler: fn(Try(String)) -> a) -> a { let opts = with_fn(defaults()) let field = types.Field(name: "export", args: list.append([#("path", types.GString(path))], encode_export(opts)), subfields: []) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.string)) { Ok(val) -> types.Pure(Ok(val)) Error(_) -> types.Pure(Error(types.DecodingError("export"))) } } ) } handler(interpreter.run(op, client)) } fn encode_export_image(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.platform_variants { Some(val) -> Ok(#("platformVariants", types.GList(list.map(val, fn(x) { types.GDeferred(x.op) })))) None -> Error(Nil) }, case opts.forced_compression { Some(val) -> Ok(#("forcedCompression", types.GString(t.image_layer_compression_to_json(val)))) None -> Error(Nil) }, case opts.media_types { Some(val) -> Ok(#("mediaTypes", types.GString(t.image_media_types_to_json(val)))) None -> Error(Nil) } ], fn(x) { x }) } /// Exports the container as an image to the host's container image store. pub fn export_image(parent: t.Container, name name: String, with with_fn: fn(Opts) -> Opts, client client: Client, then handler: fn(Try(Nil)) -> a) -> a { let opts = with_fn(defaults()) let field = types.Field(name: "exportImage", args: list.append([#("name", types.GString(name))], encode_export_image(opts)), subfields: []) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.dynamic)) { Ok(_) -> types.Pure(Ok(Nil)) Error(_) -> types.Pure(Error(types.DecodingError("exportImage"))) } } ) } handler(interpreter.run(op, client)) } /// Retrieves the list of exposed ports. /// This includes ports already exposed by the image, even if not explicitly added with dagger. pub fn exposed_ports(parent: t.Container, select select: fn(t.Port) -> List(types.Field), client client: Client, then handler: fn(Try(List(t.Port))) -> a) -> a { let subfields = select(t.Port(op: types.Pure([]))) let field = types.Field(name: "exposedPorts", args: [], subfields: subfields) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.list(decode.dynamic))) { Ok(items) -> types.Pure(Ok(list.map(items, fn(_) { t.Port(op: types.Pure(full_query)) }))) Error(_) -> types.Pure(Error(types.DecodingError("exposedPorts"))) } } ) } handler(interpreter.run(op, client)) } fn encode_file(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Retrieves a file at the given path. /// Mounts are included. pub fn file(parent: t.Container, path path: String, with with_fn: fn(Opts) -> Opts) -> t.File { let opts = with_fn(defaults()) let field = types.Field(name: "file", args: list.append([#("path", types.GString(path))], encode_file(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.File(op: new_op) } /// Download a container image, and apply it to the container state. All previous state will be lost. pub fn from(parent: t.Container, address address: String) -> t.Container { let field = types.Field(name: "from", args: [#("address", types.GString(address))], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// A unique identifier for this Container. pub fn id(parent: t.Container) -> t.Container { let field = types.Field(name: "id", args: [], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// The unique image reference which can only be retrieved immediately after the 'Container.From' call. pub fn image_ref(parent: t.Container, client client: Client, then handler: fn(Try(String)) -> a) -> a { let field = types.Field(name: "imageRef", args: [], subfields: []) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.string)) { Ok(val) -> types.Pure(Ok(val)) Error(_) -> types.Pure(Error(types.DecodingError("imageRef"))) } } ) } handler(interpreter.run(op, client)) } fn encode_import_(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.tag { Some(val) -> Ok(#("tag", types.GString(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Reads the container from an OCI tarball. pub fn import_(parent: t.Container, source source: t.File, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "import", args: list.append([#("source", types.GDeferred(source.op))], encode_import_(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Retrieves the value of the specified label. pub fn label(parent: t.Container, name name: String, client client: Client, then handler: fn(Try(String)) -> a) -> a { let field = types.Field(name: "label", args: [#("name", types.GString(name))], subfields: []) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.string)) { Ok(val) -> types.Pure(Ok(val)) Error(_) -> types.Pure(Error(types.DecodingError("label"))) } } ) } handler(interpreter.run(op, client)) } /// Retrieves the list of labels passed to container. pub fn labels(parent: t.Container, select select: fn(t.Label) -> List(types.Field), client client: Client, then handler: fn(Try(List(t.Label))) -> a) -> a { let subfields = select(t.Label(op: types.Pure([]))) let field = types.Field(name: "labels", args: [], subfields: subfields) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.list(decode.dynamic))) { Ok(items) -> types.Pure(Ok(list.map(items, fn(_) { t.Label(op: types.Pure(full_query)) }))) Error(_) -> types.Pure(Error(types.DecodingError("labels"))) } } ) } handler(interpreter.run(op, client)) } /// Retrieves the list of paths where a directory is mounted. pub fn mounts(parent: t.Container, client client: Client, then handler: fn(Try(List(String))) -> a) -> a { let field = types.Field(name: "mounts", args: [], subfields: []) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.list(decode.string))) { Ok(val) -> types.Pure(Ok(val)) Error(_) -> types.Pure(Error(types.DecodingError("mounts"))) } } ) } handler(interpreter.run(op, client)) } /// The platform this container executes and publishes as. pub fn platform(parent: t.Container, client client: Client, then handler: fn(Try(String)) -> a) -> a { let field = types.Field(name: "platform", args: [], subfields: []) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.string)) { Ok(val) -> types.Pure(Ok(val)) Error(_) -> types.Pure(Error(types.DecodingError("platform"))) } } ) } handler(interpreter.run(op, client)) } fn encode_publish(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.platform_variants { Some(val) -> Ok(#("platformVariants", types.GList(list.map(val, fn(x) { types.GDeferred(x.op) })))) None -> Error(Nil) }, case opts.forced_compression { Some(val) -> Ok(#("forcedCompression", types.GString(t.image_layer_compression_to_json(val)))) None -> Error(Nil) }, case opts.media_types { Some(val) -> Ok(#("mediaTypes", types.GString(t.image_media_types_to_json(val)))) None -> Error(Nil) } ], fn(x) { x }) } /// Package the container state as an OCI image, and publish it to a registry /// Returns the fully qualified address of the published image, with digest pub fn publish(parent: t.Container, address address: String, with with_fn: fn(Opts) -> Opts, client client: Client, then handler: fn(Try(String)) -> a) -> a { let opts = with_fn(defaults()) let field = types.Field(name: "publish", args: list.append([#("address", types.GString(address))], encode_publish(opts)), subfields: []) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.string)) { Ok(val) -> types.Pure(Ok(val)) Error(_) -> types.Pure(Error(types.DecodingError("publish"))) } } ) } handler(interpreter.run(op, client)) } /// Return a snapshot of the container's root filesystem. The snapshot can be modified then written back using withRootfs. Use that method for filesystem modifications. pub fn rootfs(parent: t.Container) -> t.Directory { let field = types.Field(name: "rootfs", args: [], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Directory(op: new_op) } fn encode_stat(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.do_not_follow_symlinks { Some(val) -> Ok(#("doNotFollowSymlinks", types.GBool(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Return file status pub fn stat(parent: t.Container, path path: String, with with_fn: fn(Opts) -> Opts) -> t.Stat { let opts = with_fn(defaults()) let field = types.Field(name: "stat", args: list.append([#("path", types.GString(path))], encode_stat(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Stat(op: new_op) } /// The buffered standard error stream of the last executed command /// Returns an error if no command was executed pub fn stderr(parent: t.Container, client client: Client, then handler: fn(Try(String)) -> a) -> a { let field = types.Field(name: "stderr", args: [], subfields: []) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.string)) { Ok(val) -> types.Pure(Ok(val)) Error(_) -> types.Pure(Error(types.DecodingError("stderr"))) } } ) } handler(interpreter.run(op, client)) } /// The buffered standard output stream of the last executed command /// Returns an error if no command was executed pub fn stdout(parent: t.Container, client client: Client, then handler: fn(Try(String)) -> a) -> a { let field = types.Field(name: "stdout", args: [], subfields: []) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.string)) { Ok(val) -> types.Pure(Ok(val)) Error(_) -> types.Pure(Error(types.DecodingError("stdout"))) } } ) } handler(interpreter.run(op, client)) } /// Forces evaluation of the pipeline in the engine. /// It doesn't run the default command if no exec has been set. pub fn sync(parent: t.Container) -> t.Container { let field = types.Field(name: "sync", args: [], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_terminal(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.experimental_privileged_nesting { Some(val) -> Ok(#("experimentalPrivilegedNesting", types.GBool(val))) None -> Error(Nil) }, case opts.insecure_root_capabilities { Some(val) -> Ok(#("insecureRootCapabilities", types.GBool(val))) None -> Error(Nil) }, case opts.cmd { Some(val) -> Ok(#("cmd", types.GList(list.map(val, fn(x) { types.GString(x) })))) None -> Error(Nil) } ], fn(x) { x }) } /// Opens an interactive terminal for this container using its configured default terminal command if not overridden by args (or sh as a fallback default). pub fn terminal(parent: t.Container, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "terminal", args: encode_terminal(opts), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_up(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.args { Some(val) -> Ok(#("args", types.GList(list.map(val, fn(x) { types.GString(x) })))) None -> Error(Nil) }, case opts.use_entrypoint { Some(val) -> Ok(#("useEntrypoint", types.GBool(val))) None -> Error(Nil) }, case opts.experimental_privileged_nesting { Some(val) -> Ok(#("experimentalPrivilegedNesting", types.GBool(val))) None -> Error(Nil) }, case opts.insecure_root_capabilities { Some(val) -> Ok(#("insecureRootCapabilities", types.GBool(val))) None -> Error(Nil) }, case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) }, case opts.no_init { Some(val) -> Ok(#("noInit", types.GBool(val))) None -> Error(Nil) }, case opts.random { Some(val) -> Ok(#("random", types.GBool(val))) None -> Error(Nil) }, case opts.ports { Some(val) -> Ok(#("ports", types.GList(list.map(val, fn(x) { types.GObject(t.port_forward_to_json(x)) })))) None -> Error(Nil) } ], fn(x) { x }) } /// Starts a Service and creates a tunnel that forwards traffic from the caller's network to that service. /// Be sure to set any exposed ports before calling this api. pub fn up(parent: t.Container, with with_fn: fn(Opts) -> Opts, client client: Client, then handler: fn(Try(Nil)) -> a) -> a { let opts = with_fn(defaults()) let field = types.Field(name: "up", args: encode_up(opts), subfields: []) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.dynamic)) { Ok(_) -> types.Pure(Ok(Nil)) Error(_) -> types.Pure(Error(types.DecodingError("up"))) } } ) } handler(interpreter.run(op, client)) } /// Retrieves the user to be set for all commands. pub fn user(parent: t.Container, client client: Client, then handler: fn(Try(String)) -> a) -> a { let field = types.Field(name: "user", args: [], subfields: []) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.string)) { Ok(val) -> types.Pure(Ok(val)) Error(_) -> types.Pure(Error(types.DecodingError("user"))) } } ) } handler(interpreter.run(op, client)) } /// Retrieves this container plus the given OCI annotation. pub fn with_annotation(parent: t.Container, name name: String, value value: String) -> t.Container { let field = types.Field(name: "withAnnotation", args: [#("name", types.GString(name)), #("value", types.GString(value))], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Configures default arguments for future commands. Like CMD in Dockerfile. pub fn with_default_args(parent: t.Container, args args: List(String)) -> t.Container { let field = types.Field(name: "withDefaultArgs", args: [#("args", types.GList(list.map(args, fn(x) { types.GString(x) })))], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_with_default_terminal_cmd(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.experimental_privileged_nesting { Some(val) -> Ok(#("experimentalPrivilegedNesting", types.GBool(val))) None -> Error(Nil) }, case opts.insecure_root_capabilities { Some(val) -> Ok(#("insecureRootCapabilities", types.GBool(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Set the default command to invoke for the container's terminal API. pub fn with_default_terminal_cmd(parent: t.Container, args args: List(String), with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withDefaultTerminalCmd", args: list.append([#("args", types.GList(list.map(args, fn(x) { types.GString(x) })))], encode_with_default_terminal_cmd(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_with_directory(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) }, case opts.exclude { Some(val) -> Ok(#("exclude", types.GList(list.map(val, fn(x) { types.GString(x) })))) None -> Error(Nil) }, case opts.include { Some(val) -> Ok(#("include", types.GList(list.map(val, fn(x) { types.GString(x) })))) None -> Error(Nil) }, case opts.gitignore { Some(val) -> Ok(#("gitignore", types.GBool(val))) None -> Error(Nil) }, case opts.owner { Some(val) -> Ok(#("owner", types.GString(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Return a new container snapshot, with a directory added to its filesystem pub fn with_directory(parent: t.Container, path path: String, source source: t.Directory, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withDirectory", args: list.append([#("path", types.GString(path)), #("source", types.GDeferred(source.op))], encode_with_directory(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_with_entrypoint(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.keep_default_args { Some(val) -> Ok(#("keepDefaultArgs", types.GBool(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Set an OCI-style entrypoint. It will be included in the container's OCI configuration. Note, withExec ignores the entrypoint by default. pub fn with_entrypoint(parent: t.Container, args args: List(String), with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withEntrypoint", args: list.append([#("args", types.GList(list.map(args, fn(x) { types.GString(x) })))], encode_with_entrypoint(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Export environment variables from an env-file to the container. pub fn with_env_file_variables(parent: t.Container, source source: t.EnvFile) -> t.Container { let field = types.Field(name: "withEnvFileVariables", args: [#("source", types.GDeferred(source.op))], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_with_env_variable(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Set a new environment variable in the container. pub fn with_env_variable(parent: t.Container, name name: String, value value: String, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withEnvVariable", args: list.append([#("name", types.GString(name)), #("value", types.GString(value))], encode_with_env_variable(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Raise an error. pub fn with_error(parent: t.Container, err err: String) -> t.Container { let field = types.Field(name: "withError", args: [#("err", types.GString(err))], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_with_exec(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.use_entrypoint { Some(val) -> Ok(#("useEntrypoint", types.GBool(val))) None -> Error(Nil) }, case opts.experimental_privileged_nesting { Some(val) -> Ok(#("experimentalPrivilegedNesting", types.GBool(val))) None -> Error(Nil) }, case opts.insecure_root_capabilities { Some(val) -> Ok(#("insecureRootCapabilities", types.GBool(val))) None -> Error(Nil) }, case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) }, case opts.no_init { Some(val) -> Ok(#("noInit", types.GBool(val))) None -> Error(Nil) }, case opts.stdin { Some(val) -> Ok(#("stdin", types.GString(val))) None -> Error(Nil) }, case opts.redirect_stdin { Some(val) -> Ok(#("redirectStdin", types.GString(val))) None -> Error(Nil) }, case opts.redirect_stdout { Some(val) -> Ok(#("redirectStdout", types.GString(val))) None -> Error(Nil) }, case opts.redirect_stderr { Some(val) -> Ok(#("redirectStderr", types.GString(val))) None -> Error(Nil) }, case opts.expect { Some(val) -> Ok(#("expect", types.GString(t.return_type_to_json(val)))) None -> Error(Nil) } ], fn(x) { x }) } /// Execute a command in the container, and return a new snapshot of the container state after execution. pub fn with_exec(parent: t.Container, args args: List(String), with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withExec", args: list.append([#("args", types.GList(list.map(args, fn(x) { types.GString(x) })))], encode_with_exec(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_with_exposed_port(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.protocol { Some(val) -> Ok(#("protocol", types.GString(t.network_protocol_to_json(val)))) None -> Error(Nil) }, case opts.description { Some(val) -> Ok(#("description", types.GString(val))) None -> Error(Nil) }, case opts.experimental_skip_healthcheck { Some(val) -> Ok(#("experimentalSkipHealthcheck", types.GBool(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Expose a network port. Like EXPOSE in Dockerfile (but with healthcheck support) /// Exposed ports serve two purposes: /// - For health checks and introspection, when running services /// - For setting the EXPOSE OCI field when publishing the container pub fn with_exposed_port(parent: t.Container, port port: Int, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withExposedPort", args: list.append([#("port", types.GInt(port))], encode_with_exposed_port(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_with_file(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) }, case opts.owner { Some(val) -> Ok(#("owner", types.GString(val))) None -> Error(Nil) }, case opts.permissions { Some(val) -> Ok(#("permissions", types.GInt(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Return a container snapshot with a file added pub fn with_file(parent: t.Container, path path: String, source source: t.File, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withFile", args: list.append([#("path", types.GString(path)), #("source", types.GDeferred(source.op))], encode_with_file(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_with_files(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) }, case opts.owner { Some(val) -> Ok(#("owner", types.GString(val))) None -> Error(Nil) }, case opts.permissions { Some(val) -> Ok(#("permissions", types.GInt(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Retrieves this container plus the contents of the given files copied to the given path. pub fn with_files(parent: t.Container, path path: String, sources sources: List(t.File), with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withFiles", args: list.append([#("path", types.GString(path)), #("sources", types.GList(list.map(sources, fn(x) { types.GDeferred(x.op) })))], encode_with_files(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Retrieves this container plus the given label. pub fn with_label(parent: t.Container, name name: String, value value: String) -> t.Container { let field = types.Field(name: "withLabel", args: [#("name", types.GString(name)), #("value", types.GString(value))], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_with_mounted_cache(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) }, case opts.owner { Some(val) -> Ok(#("owner", types.GString(val))) None -> Error(Nil) }, case opts.source { Some(val) -> Ok(#("source", types.GDeferred(val.op))) None -> Error(Nil) }, case opts.sharing { Some(val) -> Ok(#("sharing", types.GString(t.cache_sharing_mode_to_json(val)))) None -> Error(Nil) } ], fn(x) { x }) } /// Retrieves this container plus a cache volume mounted at the given path. pub fn with_mounted_cache(parent: t.Container, path path: String, cache cache: t.CacheVolume, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withMountedCache", args: list.append([#("path", types.GString(path)), #("cache", types.GDeferred(cache.op))], encode_with_mounted_cache(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_with_mounted_directory(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) }, case opts.owner { Some(val) -> Ok(#("owner", types.GString(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Retrieves this container plus a directory mounted at the given path. pub fn with_mounted_directory(parent: t.Container, path path: String, source source: t.Directory, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withMountedDirectory", args: list.append([#("path", types.GString(path)), #("source", types.GDeferred(source.op))], encode_with_mounted_directory(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_with_mounted_file(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) }, case opts.owner { Some(val) -> Ok(#("owner", types.GString(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Retrieves this container plus a file mounted at the given path. pub fn with_mounted_file(parent: t.Container, path path: String, source source: t.File, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withMountedFile", args: list.append([#("path", types.GString(path)), #("source", types.GDeferred(source.op))], encode_with_mounted_file(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_with_mounted_secret(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) }, case opts.owner { Some(val) -> Ok(#("owner", types.GString(val))) None -> Error(Nil) }, case opts.mode { Some(val) -> Ok(#("mode", types.GInt(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Retrieves this container plus a secret mounted into a file at the given path. pub fn with_mounted_secret(parent: t.Container, path path: String, source source: t.Secret, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withMountedSecret", args: list.append([#("path", types.GString(path)), #("source", types.GDeferred(source.op))], encode_with_mounted_secret(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_with_mounted_temp(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) }, case opts.size { Some(val) -> Ok(#("size", types.GInt(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Retrieves this container plus a temporary directory mounted at the given path. Any writes will be ephemeral to a single withExec call; they will not be persisted to subsequent withExecs. pub fn with_mounted_temp(parent: t.Container, path path: String, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withMountedTemp", args: list.append([#("path", types.GString(path))], encode_with_mounted_temp(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_with_new_file(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) }, case opts.owner { Some(val) -> Ok(#("owner", types.GString(val))) None -> Error(Nil) }, case opts.permissions { Some(val) -> Ok(#("permissions", types.GInt(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Return a new container snapshot, with a file added to its filesystem with text content pub fn with_new_file(parent: t.Container, path path: String, contents contents: String, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withNewFile", args: list.append([#("path", types.GString(path)), #("contents", types.GString(contents))], encode_with_new_file(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Attach credentials for future publishing to a registry. Use in combination with publish pub fn with_registry_auth(parent: t.Container, address address: String, username username: String, secret secret: t.Secret) -> t.Container { let field = types.Field(name: "withRegistryAuth", args: [#("address", types.GString(address)), #("username", types.GString(username)), #("secret", types.GDeferred(secret.op))], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Change the container's root filesystem. The previous root filesystem will be lost. pub fn with_rootfs(parent: t.Container, directory directory: t.Directory) -> t.Container { let field = types.Field(name: "withRootfs", args: [#("directory", types.GDeferred(directory.op))], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Set a new environment variable, using a secret value pub fn with_secret_variable(parent: t.Container, name name: String, secret secret: t.Secret) -> t.Container { let field = types.Field(name: "withSecretVariable", args: [#("name", types.GString(name)), #("secret", types.GDeferred(secret.op))], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Establish a runtime dependency from a container to a network service. /// The service will be started automatically when needed and detached when it is no longer needed, executing the default command if none is set. /// The service will be reachable from the container via the provided hostname alias. /// The service dependency will also convey to any files or directories produced by the container. pub fn with_service_binding(parent: t.Container, alias alias: String, service service: t.Service) -> t.Container { let field = types.Field(name: "withServiceBinding", args: [#("alias", types.GString(alias)), #("service", types.GDeferred(service.op))], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_with_symlink(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Return a snapshot with a symlink pub fn with_symlink(parent: t.Container, target target: String, link_name link_name: String, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withSymlink", args: list.append([#("target", types.GString(target)), #("linkName", types.GString(link_name))], encode_with_symlink(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_with_unix_socket(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) }, case opts.owner { Some(val) -> Ok(#("owner", types.GString(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Retrieves this container plus a socket forwarded to the given Unix socket path. pub fn with_unix_socket(parent: t.Container, path path: String, source source: t.Socket, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withUnixSocket", args: list.append([#("path", types.GString(path)), #("source", types.GDeferred(source.op))], encode_with_unix_socket(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Retrieves this container with a different command user. pub fn with_user(parent: t.Container, name name: String) -> t.Container { let field = types.Field(name: "withUser", args: [#("name", types.GString(name))], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_with_workdir(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Change the container's working directory. Like WORKDIR in Dockerfile. pub fn with_workdir(parent: t.Container, path path: String, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withWorkdir", args: list.append([#("path", types.GString(path))], encode_with_workdir(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Retrieves this container minus the given OCI annotation. pub fn without_annotation(parent: t.Container, name name: String) -> t.Container { let field = types.Field(name: "withoutAnnotation", args: [#("name", types.GString(name))], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Remove the container's default arguments. pub fn without_default_args(parent: t.Container) -> t.Container { let field = types.Field(name: "withoutDefaultArgs", args: [], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_without_directory(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Return a new container snapshot, with a directory removed from its filesystem pub fn without_directory(parent: t.Container, path path: String, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withoutDirectory", args: list.append([#("path", types.GString(path))], encode_without_directory(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_without_entrypoint(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.keep_default_args { Some(val) -> Ok(#("keepDefaultArgs", types.GBool(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Reset the container's OCI entrypoint. pub fn without_entrypoint(parent: t.Container, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withoutEntrypoint", args: encode_without_entrypoint(opts), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Retrieves this container minus the given environment variable. pub fn without_env_variable(parent: t.Container, name name: String) -> t.Container { let field = types.Field(name: "withoutEnvVariable", args: [#("name", types.GString(name))], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_without_exposed_port(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.protocol { Some(val) -> Ok(#("protocol", types.GString(t.network_protocol_to_json(val)))) None -> Error(Nil) } ], fn(x) { x }) } /// Unexpose a previously exposed port. pub fn without_exposed_port(parent: t.Container, port port: Int, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withoutExposedPort", args: list.append([#("port", types.GInt(port))], encode_without_exposed_port(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_without_file(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Retrieves this container with the file at the given path removed. pub fn without_file(parent: t.Container, path path: String, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withoutFile", args: list.append([#("path", types.GString(path))], encode_without_file(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_without_files(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Return a new container spanshot with specified files removed pub fn without_files(parent: t.Container, paths paths: List(String), with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withoutFiles", args: list.append([#("paths", types.GList(list.map(paths, fn(x) { types.GString(x) })))], encode_without_files(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Retrieves this container minus the given environment label. pub fn without_label(parent: t.Container, name name: String) -> t.Container { let field = types.Field(name: "withoutLabel", args: [#("name", types.GString(name))], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_without_mount(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Retrieves this container after unmounting everything at the given path. pub fn without_mount(parent: t.Container, path path: String, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withoutMount", args: list.append([#("path", types.GString(path))], encode_without_mount(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Retrieves this container without the registry authentication of a given address. pub fn without_registry_auth(parent: t.Container, address address: String) -> t.Container { let field = types.Field(name: "withoutRegistryAuth", args: [#("address", types.GString(address))], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Retrieves this container minus the given environment variable containing the secret. pub fn without_secret_variable(parent: t.Container, name name: String) -> t.Container { let field = types.Field(name: "withoutSecretVariable", args: [#("name", types.GString(name))], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } fn encode_without_unix_socket(opts: Opts) -> List(#(String, types.Value)) { list.filter_map([ case opts.expand { Some(val) -> Ok(#("expand", types.GBool(val))) None -> Error(Nil) } ], fn(x) { x }) } /// Retrieves this container with a previously added Unix socket removed. pub fn without_unix_socket(parent: t.Container, path path: String, with with_fn: fn(Opts) -> Opts) -> t.Container { let opts = with_fn(defaults()) let field = types.Field(name: "withoutUnixSocket", args: list.append([#("path", types.GString(path))], encode_without_unix_socket(opts)), subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Retrieves this container with an unset command user. /// Should default to root. pub fn without_user(parent: t.Container) -> t.Container { let field = types.Field(name: "withoutUser", args: [], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Unset the container's working directory. /// Should default to "/". pub fn without_workdir(parent: t.Container) -> t.Container { let field = types.Field(name: "withoutWorkdir", args: [], subfields: []) let new_op = { use q <- types.bind(parent.op) types.Pure(list.append(q, [field])) } t.Container(op: new_op) } /// Retrieves the working directory for all commands. pub fn workdir(parent: t.Container, client client: Client, then handler: fn(Try(String)) -> a) -> a { let field = types.Field(name: "workdir", args: [], subfields: []) let op = { use q <- types.bind(parent.op) let full_query = list.append(q, [field]) types.Fetch( fields: full_query, decoder: decode.dynamic, next: fn(dyn) { let path = types.make_path(full_query) case decode.run(dyn, decode.at(path, decode.string)) { Ok(val) -> types.Pure(Ok(val)) Error(_) -> types.Pure(Error(types.DecodingError("workdir"))) } } ) } handler(interpreter.run(op, client)) }