diff --git a/R/dockerfile.R b/R/dockerfile.R index d2be369..4a0ab3f 100644 --- a/R/dockerfile.R +++ b/R/dockerfile.R @@ -1,3 +1,15 @@ +## for normalizing post_installation_steps +.normalize_docker_steps <- function(steps) { + fx <- function(step) { + docker_regex <- "^#|^ADD |^COPY |^ENV |^EXPOSE |^FROM |^LABEL |^STOPSIGNAL |^USER |^VOLUME |^WORKDIR |^ONBUILD |^RUN |^CMD |^ENTRYPOINT |^ARG |^HEALTHCHECK |^SHELL " + splitted_step <- strsplit(step, "\n")[[1]] + docker_line_lgl <- grepl(docker_regex, splitted_step) + splitted_step[!docker_line_lgl] <- paste0("RUN ", splitted_step[!docker_line_lgl]) + paste0(splitted_step, collapse = "\n") + } + vapply(steps, fx, character(1), USE.NAMES = FALSE) +} + .generate_debian_eol_dockerfile_content <- function(r_version, lib, sysreqs_cmd, cache, debian_version = "lenny", post_installation_steps = NULL, rel_dir = "", @@ -24,7 +36,7 @@ containerfile_content$FROM <- c("FROM scratch", paste0("ADD ", file.path(rel_dir, "cache/debian/rootfs.tar.xz"), " /")) containerfile_content$ENV <- append(containerfile_content$ENV, paste0("ENV CACHE_PATH ", cache_path)) } - containerfile_content$RUN <- append(containerfile_content$RUN, post_installation_steps) + containerfile_content$RUN <- append(containerfile_content$RUN, .normalize_docker_steps(post_installation_steps)) if (isTRUE(copy_all)) { containerfile_content$COPY <- c("COPY . /") } @@ -55,7 +67,7 @@ if (image == "rstudio") { containerfile_content$CMD <- c("EXPOSE 8787", "CMD [\"/init\"]") } - containerfile_content$RUN <- append(containerfile_content$RUN, post_installation_steps) + containerfile_content$RUN <- append(containerfile_content$RUN, .normalize_docker_steps(post_installation_steps)) if (isTRUE(copy_all)) { containerfile_content$COPY <- c("COPY . /") } diff --git a/R/memo_misc.R b/R/memo_misc.R index 852a670..6261015 100644 --- a/R/memo_misc.R +++ b/R/memo_misc.R @@ -64,11 +64,11 @@ NULL ## data generation ## --- ## recipes <- list() -## recipes["texlive"] <- "## install texlive\nRUN apt-get install -y pandoc pandoc-citeproc texlive" -## recipes["texlivefull"] <- "## install texlive-full\nRUN apt-get install -y pandoc pandoc-citeproc texlive-full" -## recipes["quarto"] <- "## install quarto (latest)\nRUN apt-get install -y curl git && curl -LO https://quarto.org/download/latest/quarto-linux-amd64.deb && dpkg -i quarto-linux-amd64.deb && quarto install tool tinytex && rm quarto-linux-amd64.deb" -## recipes["clean"] <- "## Clean up caches\nRUN rm -rf /var/lib/apt/lists/* && if [ -d \"$CACHE_PATH\" ]; then rm -rf $CACHE_PATH; fi" -## recipes["make"] <- "## install GNU make\nRUN apt-get -y install make" +## recipes["texlive"] <- "## install texlive\napt-get install -y pandoc pandoc-citeproc texlive" +## recipes["texlivefull"] <- "## install texlive-full\napt-get install -y pandoc pandoc-citeproc texlive-full" +## recipes["quarto"] <- "## install quarto (latest)\napt-get install -y curl git && curl -LO https://quarto.org/download/latest/quarto-linux-amd64.deb && dpkg -i quarto-linux-amd64.deb && quarto install tool tinytex && rm quarto-linux-amd64.deb" +## recipes["clean"] <- "## Clean up caches\nrm -rf /var/lib/apt/lists/* && if [ -d \"$CACHE_PATH\" ]; then rm -rf $CACHE_PATH; fi" +## recipes["make"] <- "## install GNU make\napt-get -y install make" ## usethis::use_data(recipes, overwrite = TRUE) #' Recipes for Building Container Images diff --git a/data/recipes.rda b/data/recipes.rda index af25546..9d708a5 100644 Binary files a/data/recipes.rda and b/data/recipes.rda differ diff --git a/tests/testthat/test_apptainerize.R b/tests/testthat/test_apptainerize.R index f1f95d6..4790f6e 100644 --- a/tests/testthat/test_apptainerize.R +++ b/tests/testthat/test_apptainerize.R @@ -309,3 +309,12 @@ test_that(".insert_materials_dir with actual outcome", { expect_identical(names(.insert_materials_dir(container_content, verb = "apptainerize/singularize")), "FILES") expect_false(names(.insert_materials_dir(container_content, verb = "apptainerize/singularize")) %in% "COPY") }) + +test_that("No .normalize_docker_steps integration in apptainerize", { + graph <- readRDS("../testdata/graph.RDS") + temp_dir <- .generate_temp_dir() + apptainerize(graph, output_dir = temp_dir, post_installation_steps = c(recipes[["texlive"]], "RUN apt-get install -y make")) + def_file <- readLines(file.path(temp_dir, "container.def")) + expect_true("RUN apt-get install -y make" %in% def_file) ## you ask for it + expect_false("RUN apt-get install -y pandoc pandoc-citeproc texlive" %in% def_file) +}) diff --git a/tests/testthat/test_dockerize.R b/tests/testthat/test_dockerize.R index 71dbaea..479ce1f 100644 --- a/tests/testthat/test_dockerize.R +++ b/tests/testthat/test_dockerize.R @@ -317,25 +317,42 @@ test_that("dockerize with inst/rang", { expect_true("ENV RANG_PATH inst/rang/rang.R" %in% dockerfile) }) +test_that(".normalize_docker_steps", { + expect_equal(.normalize_docker_steps("RUN apt-get install -y pandoc"), "RUN apt-get install -y pandoc") + expect_equal(.normalize_docker_steps("apt-get install -y pandoc"), "RUN apt-get install -y pandoc") + expect_equal(.normalize_docker_steps(c("apt-get install -y pandoc", "RUN apt-get install -y pandoc")), + rep("RUN apt-get install -y pandoc", 2)) + expect_equal(.normalize_docker_steps(recipes[["quarto"]]), "## install quarto (latest)\nRUN apt-get install -y curl git && curl -LO https://quarto.org/download/latest/quarto-linux-amd64.deb && dpkg -i quarto-linux-amd64.deb && quarto install tool tinytex && rm quarto-linux-amd64.deb") +}) + +test_that(".normalize_docker_steps integration", { + graph <- readRDS("../testdata/graph.RDS") + temp_dir <- .generate_temp_dir() + dockerize(graph, output_dir = temp_dir, post_installation_steps = c(recipes[["texlive"]], "RUN apt-get install -y make")) + dockerfile <- readLines(file.path(temp_dir, "Dockerfile")) + expect_true("RUN apt-get install -y make" %in% dockerfile) + expect_true("RUN apt-get install -y pandoc pandoc-citeproc texlive" %in% dockerfile) +}) + test_that(".generate_wrapped_line", { - graph <- readRDS("../testdata/graph.RDS") - temp_dir <- .generate_temp_dir() - dockerize(graph, output_dir = temp_dir) - Dockerfile <- readLines(file.path(temp_dir, "Dockerfile")) - expect_equal(max(lengths(regmatches(Dockerfile, gregexpr("&&", Dockerfile)))), 1) - expect_true(all(grepl("^\t&&", Dockerfile[grepl("&&", Dockerfile)]))) - graph <- readRDS("../testdata/rang_bioc.RDS") - temp_dir <- .generate_temp_dir() - dockerize(graph, output_dir = temp_dir) - Dockerfile <- readLines(file.path(temp_dir, "Dockerfile")) - expect_equal(max(lengths(regmatches(Dockerfile, gregexpr("&&", Dockerfile)))), 1) - expect_true(all(grepl("^\t&&", Dockerfile[grepl("&&", Dockerfile)]))) - graph <- readRDS("../testdata/rang_rio_old.RDS") - temp_dir <- .generate_temp_dir() - dockerize(graph, output_dir = temp_dir) - Dockerfile <- readLines(file.path(temp_dir, "Dockerfile")) - expect_equal(max(lengths(regmatches(Dockerfile, gregexpr("&&", Dockerfile)))), 1) - expect_true(all(grepl("^\t&&", Dockerfile[grepl("&&", Dockerfile)]))) + graph <- readRDS("../testdata/graph.RDS") + temp_dir <- .generate_temp_dir() + dockerize(graph, output_dir = temp_dir) + Dockerfile <- readLines(file.path(temp_dir, "Dockerfile")) + expect_equal(max(lengths(regmatches(Dockerfile, gregexpr("&&", Dockerfile)))), 1) + expect_true(all(grepl("^\t&&", Dockerfile[grepl("&&", Dockerfile)]))) + graph <- readRDS("../testdata/rang_bioc.RDS") + temp_dir <- .generate_temp_dir() + dockerize(graph, output_dir = temp_dir) + Dockerfile <- readLines(file.path(temp_dir, "Dockerfile")) + expect_equal(max(lengths(regmatches(Dockerfile, gregexpr("&&", Dockerfile)))), 1) + expect_true(all(grepl("^\t&&", Dockerfile[grepl("&&", Dockerfile)]))) + graph <- readRDS("../testdata/rang_rio_old.RDS") + temp_dir <- .generate_temp_dir() + dockerize(graph, output_dir = temp_dir) + Dockerfile <- readLines(file.path(temp_dir, "Dockerfile")) + expect_equal(max(lengths(regmatches(Dockerfile, gregexpr("&&", Dockerfile)))), 1) + expect_true(all(grepl("^\t&&", Dockerfile[grepl("&&", Dockerfile)]))) }) test_that(".generate_wrapped_line with actual outcome", {