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

Support docker machine #6

Closed
wants to merge 2 commits into from
Closed
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
4 changes: 3 additions & 1 deletion NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Generated by roxygen2 (4.0.2): do not edit by hand
# Generated by roxygen2 (4.1.1): do not edit by hand

S3method(as.container,character)
S3method(as.container,container)
Expand All @@ -15,6 +15,8 @@ export(container_update_info)
export(containers)
export(docker_cmd)
export(docker_inspect)
export(docker_machine_init)
export(docker_pull)
export(docker_run)
export(localhost)
export(localhost_ip)
27 changes: 0 additions & 27 deletions R/boot2docker.R

This file was deleted.

154 changes: 154 additions & 0 deletions R/docker-machine.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
##' Initialise environment variables to connect to a docker machine.
##'
##' In the case where there is only a single docker machine and no
##' machine is specified there is no difficult logic.
##'
##' \enumerate{
##' \item{If \code{machine} is not specified (or is \code{NULL}) then
##' \enumerate{
##' \item{If \code{DOCKER_MACHINE_NAME} is set (i.e., \emph{something}
##' has already set \code{docker-machine} variables) do nothing and
##' use these.}
##'
##' \item{Otherwise pick the first name listed among running machines
##' (see \code{docker ls --filter state=Running}) with a message if
##' more than one was found}
##' }}
##'
##' \item{If \code{machine} is specified and non-\code{NULL} then use
##' this machine only, throwing an error if it is not running}
##' }
##'
##' @title Connect to a docker machine
##' @param machine Name of a machine
##' @export
docker_machine_init <- function(machine=NULL) {
machine <- docker_machine_init_which(machine)
if (!is.null(machine)) {
message(sprintf("Setting up docker-machine '%s'", machine))
docker_machine <- callr_Sys_which("docker-machine")
status <- callr_call_system(docker_machine, c("status", machine))
if (!identical(status, "Running")) {
stop(sprintf("docker-machine '%s' not running? Status: '%s'",
machine, status))
}

res <- callr_call_system(docker_machine, paste("env ", machine),
stderr=FALSE)

## Filter to lines containing `export`
re <- "^\\s*export\\s+"
res <- res[grep(re, res)]
vars <- strsplit(sub("^\\s*export\\s+", "", res), "=", fixed=TRUE)
if (!all(vapply(vars, length, integer(1)) == 2)) {
stop("Unexpected output from docker-machine")
}

strip_quotes <- function(x) {
gsub('(^"|"$)', "", x)
}
vcapply <- function(...) vapply(..., FUN.VALUE=character(1))
var_name <- vcapply(vars, function(x) x[[1]])
var_val <- as.list(strip_quotes(vcapply(vars, function(x) x[[2]])))

names(var_val) <- var_name
do.call("Sys.setenv", var_val)

if (Sys.getenv("DOCKER_MACHINE_NAME") == "") {
stop("Failed to set docker_machine variables")
}
tryCatch(callr_call_system(callr_Sys_which("docker"), "ps"),
error=function(e)
stop("While trying to test docker:\n", e$message))
}
}

docker_machine_init_which <- function(machine) {
if (Sys.getenv("DOCKER_MACHINE_NAME") == "") {
docker_machine <- callr_Sys_which("docker-machine")
args <- c("ls", "-q", "--filter", "state=Running")
machines <- callr_call_system(docker_machine, args)
if (is.null(machine)) {
if (length(machines) < 1L) {
stop("No running docker machines detected")
} else if (length(machines) > 1L) {
message("More than one machine present, taking the first")
}
machines[[1]]
} else {
if (!(machine %in% machines)) {
stop(sprintf("machine '%s' requested but not in running set: %s",
machine, paste(machines, collapse=", ")))
}
machine
}
} else if (!is.null(machine) && Sys.getenv("DOCKER_MACHINE_NAME") != machine) {
machine
} else {
NULL
}
}


##' Return the IP address for the "local" machine. On Linux this is
##' just the localhost, but on Mac and Windows system it will be the
##' IP of the docker-machine VM.
##'
##' @title IP address of docker server
##' @param machine Name of the machine
##' @export
localhost_ip <- function(machine=NULL) {
if (Sys.info()["sysname"] %in% c("Darwin", "Windows")) {
machine <- docker_machine_init(machine)
ip <- callr_call_system(callr_Sys_which("docker-machine"),
c("ip", Sys.getenv("DOCKER_MACHINE_NAME")))
ip
} else {
"127.0.0.1"
}
}

## Ported from callr for now (sorry) - I can refactor this later or
## depend on callr later.
callr_Sys_which <- function(name) {
ret <- Sys.which(name)
if (ret == "") {
stop(sprintf("%s not found in $PATH", name))
}
ret
}

callr_call_system <- function(command, args, env=character(), max_lines=20,
p=0.8, stdout=TRUE, stderr=TRUE) {
res <- suppressWarnings(system2(command, args,
env=env, stdin="",
stdout=stdout, stderr=stderr))
ok <- attr(res, "status")
if (!is.null(ok) && ok != 0) {
max_nc <- getOption("warning.length")

cmd <- paste(c(env, shQuote(command), args), collapse = " ")
msg <- sprintf("Running command:\n %s\nhad status %d", cmd, ok)
errmsg <- attr(cmd, "errmsg")
if (!is.null(errmsg)) {
msg <- c(msg, sprintf("%s\nerrmsg: %s", errmsg))
}
sep <- paste(rep("-", getOption("width")), collapse="")

## Truncate message:
if (length(res) > max_lines) {
n <- ceiling(max_lines * p)
res <- c(head(res, ceiling(max_lines - n)),
sprintf("[[... %d lines dropped ...]]", length(res) - max_lines),
tail(res, ceiling(n)))
}

## compute the number of characters so far, including three new lines:
nc <- (nchar(msg) + nchar(sep) * 2) + 3
i <- max(1, which(cumsum(rev(nchar(res) + 1L)) < (max_nc - nc)))
res <- res[(length(res) - i + 1L):length(res)]
msg <- c(msg, "Program output:", sep, res, sep)
stop(paste(msg, collapse="\n"))
}
invisible(res)
}
5 changes: 4 additions & 1 deletion R/zzz.R
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
.onLoad <- function(libname, pkgname) {
if (Sys.info()["sysname"] %in% c("Darwin", "Windows")) {
boot2docker_shellinit()
machine <- getOption("harbor.autoconnect", FALSE)
if (!identical(machine, FALSE)) {
docker_machine_init(if (isTRUE(machine)) NULL else machine)
}
}
}
3 changes: 2 additions & 1 deletion man/as.container.Rd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
% Generated by roxygen2 (4.0.2): do not edit by hand
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/container.R
\name{as.container}
\alias{as.container}
\title{Coerce an object into a container object.}
Expand Down
3 changes: 2 additions & 1 deletion man/container_logs.Rd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
% Generated by roxygen2 (4.0.2): do not edit by hand
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/container.R
\name{container_logs}
\alias{container_logs}
\title{Retrieve logs for a container.}
Expand Down
3 changes: 2 additions & 1 deletion man/container_rm.Rd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
% Generated by roxygen2 (4.0.2): do not edit by hand
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/container.R
\name{container_rm}
\alias{container_rm}
\title{Delete a container.}
Expand Down
3 changes: 2 additions & 1 deletion man/container_running.Rd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
% Generated by roxygen2 (4.0.2): do not edit by hand
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/container.R
\name{container_running}
\alias{container_running}
\title{Report whether a container is currently running.}
Expand Down
3 changes: 2 additions & 1 deletion man/container_update_info.Rd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
% Generated by roxygen2 (4.0.2): do not edit by hand
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/container.R
\name{container_update_info}
\alias{container_update_info}
\title{Update the information about a container.}
Expand Down
3 changes: 2 additions & 1 deletion man/containers.Rd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
% Generated by roxygen2 (4.0.2): do not edit by hand
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/containers.R
\name{containers}
\alias{containers}
\title{Get list of all containers on a host.}
Expand Down
3 changes: 2 additions & 1 deletion man/docker_cmd.Rd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
% Generated by roxygen2 (4.0.2): do not edit by hand
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/docker.R
\name{docker_cmd}
\alias{docker_cmd}
\title{Run a docker command on a host.}
Expand Down
3 changes: 2 additions & 1 deletion man/docker_inspect.Rd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
% Generated by roxygen2 (4.0.2): do not edit by hand
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/docker.R
\name{docker_inspect}
\alias{docker_inspect}
\title{Inspect one or more containers, given name(s) or ID(s).}
Expand Down
35 changes: 35 additions & 0 deletions man/docker_machine_init.Rd
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/docker-machine.R
\name{docker_machine_init}
\alias{docker_machine_init}
\title{Connect to a docker machine}
\usage{
docker_machine_init(machine = NULL)
}
\arguments{
\item{machine}{Name of a machine}
}
\description{
Initialise environment variables to connect to a docker machine.
}
\details{
In the case where there is only a single docker machine and no
machine is specified there is no difficult logic.

\enumerate{
\item{If \code{machine} is not specified (or is \code{NULL}) then
\enumerate{
\item{If \code{DOCKER_MACHINE_NAME} is set (i.e., \emph{something}
has already set \code{docker-machine} variables) do nothing and
use these.}

\item{Otherwise pick the first name listed among running machines
(see \code{docker ls --filter state=Running}) with a message if
more than one was found}
}}

\item{If \code{machine} is specified and non-\code{NULL} then use
this machine only, throwing an error if it is not running}
}
}

3 changes: 2 additions & 1 deletion man/docker_pull.Rd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
% Generated by roxygen2 (4.0.2): do not edit by hand
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/docker.R
\name{docker_pull}
\alias{docker_pull}
\title{Pull a docker image onto a host.}
Expand Down
3 changes: 2 additions & 1 deletion man/docker_run.Rd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
% Generated by roxygen2 (4.0.2): do not edit by hand
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/docker.R
\name{docker_run}
\alias{docker_run}
\title{Run a command in a new container on a host.}
Expand Down
3 changes: 2 additions & 1 deletion man/localhost.Rd
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
% Generated by roxygen2 (4.0.2): do not edit by hand
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/localhost.R
\docType{data}
\name{localhost}
\alias{localhost}
Expand Down
17 changes: 17 additions & 0 deletions man/localhost_ip.Rd
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
% Generated by roxygen2 (4.1.1): do not edit by hand
% Please edit documentation in R/docker-machine.R
\name{localhost_ip}
\alias{localhost_ip}
\title{IP address of docker server}
\usage{
localhost_ip(machine = NULL)
}
\arguments{
\item{machine}{Name of the machine}
}
\description{
Return the IP address for the "local" machine. On Linux this is
just the localhost, but on Mac and Windows system it will be the
IP of the docker-machine VM.
}