wch / harbor

An R package for controlling docker containers on local and remote hosts
101 stars 8 forks source link

R6 Class - Enhancement #10

Open The-Dub opened 7 years ago

The-Dub commented 7 years ago

I was looking at the source code of harbor to figure out why splashr wasn't working and - I don't know if it's a good idea or not, but throwing it out there - I was wondering if it would be easier for debug & sanity check within functions to use R6 classes?

The structure for opening a docker would be something like boat <- harbor$new('NameOfTheDocker')

Other packages (let's say harbor) having dependency on harbor would also be R6 class being sub-class of the harbor class, for example:

splash <- R6Class('splash', 
inheritance = harbor::harbor, 
public = list(
initialize =  function(host = harbor::localhost) {
  harbor::docker_run(host,
                     image = "scrapinghub/splash",
                     detach = TRUE,
                     docker_opts = c("-p", "5023:5023",
                                     "-p", "8050:8050",
                                     "-p", "8051:8051"))
},
...
)

I forked the repo and will try to get a crack at it tonight, but if @hrbrmstr think it's a bad idea, I'll just let it go :) !

Cheers

hrbrmstr commented 7 years ago

Definitely not against switching to R6 (I was initially just trying to "get'er done").

An S3 class is always the path of least resistance but right now I can see a few different flavors of harbor:

Those could be crammed into S3 but R6 might make sense. We'd just need to design the base class to support all that (and anything others can come up with).

The-Dub commented 7 years ago

I'm learning about dockers, but I can clearly see why they are so powerful. I feel like localhost is the easiest, and probably should be implemented first, as a "solid base"

One problem might be being cross platform, to please the windows people...

hrbrmstr commented 7 years ago

Some possible beginnings of underpinnings for querying the API directly below. Needs a source build of curl on macOS and those environment variables set.

library(curl)
library(jsonlite)
library(openssl)

docker_auth <- function(username=Sys.getenv("DOCKER_USERNAME"),
                        password=Sys.getenv("DOCKER_PASSWORD"),
                        email=Sys.getenv("DOCKER_EMAIL"),
                        server_address=Sys.getenv("DOCKER_REGISTRY"),
                        encode=TRUE) {

  toJSON(
    list(
      username=unbox(username),
      password=unbox(password),
      email=unbox(email),
      auth=unbox(""),
      serveraddress=unbox(server_address)
    )
  ) -> auth_json

  if (encode) auth_json <- openssl::base64_encode(auth_json)

  auth_json

}

docker_handle <- function(verbose=FALSE) {
  h <- curl::new_handle()
  h <- curl::handle_reset(h)
  h <- curl::handle_setopt(h, UNIX_SOCKET_PATH = "/var/run/docker.sock")
  h <- curl::handle_setopt(h, VERBOSE = verbose)
  h <- curl::handle_setheaders(h,
                               `Content-Type` = "application/json",
                               `X-Registry-Auth` = docker_auth())
  h
}

# Auth check ------------------------------------------------------------------------
h <- docker_handle(TRUE)
handle_setopt(h, copypostfields = docker_auth(encode=FALSE))
res <- curl_fetch_memory(url = "http://v1.26/auth", handle = h)
str(fromJSON(rawToChar(res$content)))

# Docker info -----------------------------------------------------------------------
h <- docker_handle()
res <- curl_fetch_memory(url = "http://v1.26/info", handle = h)
str(fromJSON(rawToChar(res$content)))

# Docker version --------------------------------------------------------------------
h <- docker_handle()
res <- curl_fetch_memory(url = "http://v1.26/version", handle = h)
str(fromJSON(rawToChar(res$content)))

# Docker ping -----------------------------------------------------------------------
h <- docker_handle()
res <- curl_fetch_memory(url = "http://v1.26/_ping", handle = h)
cat(rawToChar(res$content))

# Data usage ------------------------------------------------------------------------
h <- docker_handle()
res <- curl_fetch_memory(url = "http://v1.26/system/df", handle = h)
str(fromJSON(rawToChar(res$content)))

# List images -----------------------------------------------------------------------
h <- docker_handle()
res <- curl_fetch_memory(url = "http://v1.26/images/json", handle = h)
str(fromJSON(rawToChar(res$content)))

# Search images ---------------------------------------------------------------------
h <- docker_handle()
res <- curl_fetch_memory(url = "http://v1.26/images/search?term=alpine&limit=10", handle = h)
str(fromJSON(rawToChar(res$content)))

# Pull an image ---------------------------------------------------
h <- docker_handle(verbose = TRUE)
handle_setopt(h, copypostfields = '')
res <- curl_fetch_memory(url = "http://v1.26/images/create?fromImage=alpine&tag=latest", handle = h)
cat(rawToChar(res$content))

# List running containers -----------------------------------------------------------
h <- docker_handle()
res <- curl_fetch_memory(url = "http://v1.26/containers/json", handle = h)
str(fromJSON(rawToChar(res$content)))

# all: true/false
# limit: int
# size: true/false
# filters: json
h <- docker_handle()
res <- curl_fetch_memory(url = "http://v1.26/containers/json", handle = h)
str(fromJSON(rawToChar(res$content)))

# Inspect a container ---------------------------------------------------------------

# size: true/false
h <- docker_handle(verbose = TRUE)
res <- curl_fetch_memory(url = "http://v1.26/containers/b834259b9e9ed70cd00a43c9a539ab0601dab68a5966e531fea76ec91bc76940/json", handle = h)
str(fromJSON(rawToChar(res$content)))

# List container processes ----------------------------------------------------------

# ps_args: string
h <- docker_handle(verbose = TRUE)
res <- curl_fetch_memory(url = "http://v1.26/containers/b834259b9e9ed70cd00a43c9a539ab0601dab68a5966e531fea76ec91bc76940/top", handle = h)
str(fromJSON(rawToChar(res$content)))

# Get container logs ----------------------------------------------------------------

# follow: true/false
# stdout: t/f
# stderr: r/f
# since: int
# timestamps: t/f
# tail: string
h <- docker_handle(verbose = TRUE)
res <- curl_fetch_memory(url = "http://v1.26/containers/b834259b9e9ed70cd00a43c9a539ab0601dab68a5966e531fea76ec91bc76940/logs?stdout=true&stderr=true", handle = h)
cat(rawToChar(res$content[res$content > 0x09]))

# Run a container -------------------------------------------------------------------
h <- docker_handle()
handle_setopt(h, copypostfields = '{"Image": "alpine", "Cmd": ["echo", "hello world"]}')
res <- curl_fetch_memory(url = "http:/v1.26/containers/create", handle = h)
str(fromJSON(rawToChar(res$content)))
hrbrmstr commented 7 years ago

Moving API discussion to #11