///|
priv suberror DockerError {
InvalidConfig(String)
NotStarted
ServiceNotFound(String)
AmbiguousService(String, Int32)
UnexpectedOutput(String)
CommandFailed(Array[String], Int32, String, String)
} derive(Debug)
///|
impl Show for DockerError with fn output(self, logger) {
logger.write_string(Repr(self).to_string())
}
///|
async fn docker_checked(args : Array[String], cwd? : String) -> (Bytes, Bytes) {
let cwd = cwd.map(path => path[:])
let (exit_code, stdout, stderr) = @process.collect_output(
"docker",
args,
cwd?,
)
if exit_code != 0 {
raise DockerError::CommandFailed(
args,
exit_code,
@utf8.decode_lossy(stdout.binary()),
@utf8.decode_lossy(stderr.binary()),
)
}
(stdout.binary(), stderr.binary())
}
///|
async fn docker_host() -> String {
let context = @env.get_env_var("DOCKER_CONTEXT").unwrap_or("")
if context == "" &&
@env.get_env_var("DOCKER_HOST") is Some(endpoint) &&
endpoint != "" {
return endpoint_host(endpoint)
}
let args = ["context", "inspect", "--format", "{{.Endpoints.docker.Host}}"]
if context != "" {
args.push(context)
}
let output = docker_checked(args)
endpoint_host(@utf8.decode(output.0).trim().to_owned())
}
///|
fn endpoint_host(endpoint : String) -> String raise {
let url = @url.Url::parse(endpoint)
match url.scheme {
"unix" | "npipe" => "localhost"
"tcp" | "http" | "https" | "ssh" => {
guard url.host is Some(host) else {
raise DockerError::InvalidConfig("Docker endpoint requires a host")
}
match host {
IPv4(ip) => ip.to_string()
IPv6(ip) => ip.to_string()
Domain(name) | Opaque(name) => {
guard name != "" else {
raise DockerError::InvalidConfig("Docker endpoint requires a host")
}
name
}
}
}
_ => raise DockerError::InvalidConfig("unsupported Docker endpoint scheme")
}
}