< prev index next >

test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java

Print this page




 122         return true;
 123     }
 124 
 125 
 126     /**
 127      * Build a docker image that contains JDK under test.
 128      * The jdk will be placed under the "/jdk/" folder inside the docker file system.
 129      *
 130      * @param imageName     name of the image to be created, including version tag
 131      * @param dockerfile    name of the dockerfile residing in the test source;
 132      *                      we check for a platform specific dockerfile as well
 133      *                      and use this one in case it exists
 134      * @param buildDirName  name of the docker build/staging directory, which will
 135      *                      be created in the jtreg's scratch folder
 136      * @throws Exception
 137      */
 138     public static void
 139         buildJdkDockerImage(String imageName, String dockerfile, String buildDirName)
 140             throws Exception {
 141 























 142         Path buildDir = Paths.get(".", buildDirName);
 143         if (Files.exists(buildDir)) {
 144             throw new RuntimeException("The docker build directory already exists: " + buildDir);
 145         }
 146 
 147         Path jdkSrcDir = Paths.get(JDK_UNDER_TEST);
 148         Path jdkDstDir = buildDir.resolve("jdk");
 149 
 150         Files.createDirectories(jdkDstDir);
 151 
 152         // Copy JDK-under-test tree to the docker build directory.
 153         // This step is required for building a docker image.
 154         Files.walkFileTree(jdkSrcDir, new CopyFileVisitor(jdkSrcDir, jdkDstDir));
 155         buildDockerImage(imageName, Paths.get(Utils.TEST_SRC, dockerfile), buildDir);

 156     }
 157 
 158 
 159     /**
 160      * Build a docker image based on given docker file and docker build directory.
 161      *
 162      * @param imageName  name of the image to be created, including version tag
 163      * @param dockerfile  path to the Dockerfile to be used for building the docker
 164      *        image. The specified dockerfile will be copied to the docker build
 165      *        directory as 'Dockerfile'
 166      * @param buildDir  build directory; it should already contain all the content
 167      *        needed to build the docker image.


 168      * @throws Exception
 169      */
 170     public static void
 171         buildDockerImage(String imageName, Path dockerfile, Path buildDir) throws Exception {

 172 
 173         generateDockerFile(buildDir.resolve("Dockerfile"),
 174                            DockerfileConfig.getBaseImageName(),
 175                            DockerfileConfig.getBaseImageVersion());

 176         try {
 177             // Build the docker
 178             execute(Container.ENGINE_COMMAND, "build", "--no-cache", "--tag", imageName, buildDir.toString())
 179                 .shouldHaveExitValue(0);

 180         } catch (Exception e) {
 181             // If docker image building fails there is a good chance it happens due to environment and/or
 182             // configuration other than product failure. Throw jtreg skipped exception in such case
 183             // instead of failing the test.
 184             throw new SkippedException("Building docker image failed. Details: \n" + e.getMessage());
 185         }

















 186     }
 187 
 188 
 189     /**
 190      * Build the docker command to run java inside a container
 191      *
 192      * @param DockerRunOptions options for running docker
 193      *
 194      * @return command
 195      * @throws Exception
 196      */
 197     public static List<String> buildJavaCommand(DockerRunOptions opts) throws Exception {
 198         List<String> cmd = new ArrayList<>();
 199 
 200         cmd.add(Container.ENGINE_COMMAND);
 201         cmd.add("run");
 202         if (opts.tty)
 203             cmd.add("--tty=true");
 204         if (opts.removeContainerAfterUse)
 205             cmd.add("--rm");


 270 
 271         long started = System.currentTimeMillis();
 272         Process p = pb.start();
 273         long pid = p.pid();
 274         OutputAnalyzer output = new OutputAnalyzer(p);
 275 
 276         String stdoutLogFile = String.format("docker-stdout-%d.log", pid);
 277         System.out.println("[ELAPSED: " + (System.currentTimeMillis() - started) + " ms]");
 278         System.out.println("[STDERR]\n" + output.getStderr());
 279         System.out.println("[STDOUT]\n" +
 280                            trimLines(output.getStdout(),MAX_LINES_TO_COPY_FOR_CHILD_STDOUT));
 281         System.out.printf("Child process STDOUT is trimmed to %d lines \n",
 282                            MAX_LINES_TO_COPY_FOR_CHILD_STDOUT);
 283         writeOutputToFile(output.getStdout(), stdoutLogFile);
 284         System.out.println("Full child process STDOUT was saved to " + stdoutLogFile);
 285 
 286         return output;
 287     }
 288 
 289 













































 290     private static void writeOutputToFile(String output, String fileName) throws Exception {
 291         try (FileWriter fw = new FileWriter(fileName)) {
 292             fw.write(output, 0, output.length());
 293         }
 294     }
 295 
 296 
 297     private static String trimLines(String buffer, int nrOfLines) {
 298         List<String> l = Arrays.asList(buffer.split("\\R"));
 299         if (l.size() < nrOfLines) {
 300             return buffer;
 301         }
 302 
 303         return String.join("\n", l.subList(0, nrOfLines));
 304     }
 305 
 306 
 307     private static void generateDockerFile(Path dockerfile, String baseImage,
 308                                            String baseImageVersion) throws Exception {

 309         String template =
 310             "FROM %s:%s\n" +
 311             "COPY /jdk /jdk\n" +
 312             "ENV JAVA_HOME=/jdk\n" +
 313             "CMD [\"/bin/bash\"]\n";


 314         String dockerFileStr = String.format(template, baseImage, baseImageVersion);
 315         Files.writeString(dockerfile, dockerFileStr);
 316     }
 317 
 318 
 319     private static class CopyFileVisitor extends SimpleFileVisitor<Path> {
 320         private final Path src;
 321         private final Path dst;
 322 
 323         public CopyFileVisitor(Path src, Path dst) {
 324             this.src = src;
 325             this.dst = dst;
 326         }
 327 
 328 
 329         @Override
 330         public FileVisitResult preVisitDirectory(Path file,
 331                 BasicFileAttributes attrs) throws IOException {
 332             Path dstDir = dst.resolve(src.relativize(file));
 333             if (!dstDir.toFile().exists()) {
 334                 Files.createDirectories(dstDir);
 335             }
 336             return FileVisitResult.CONTINUE;
 337         }
 338 


 122         return true;
 123     }
 124 
 125 
 126     /**
 127      * Build a docker image that contains JDK under test.
 128      * The jdk will be placed under the "/jdk/" folder inside the docker file system.
 129      *
 130      * @param imageName     name of the image to be created, including version tag
 131      * @param dockerfile    name of the dockerfile residing in the test source;
 132      *                      we check for a platform specific dockerfile as well
 133      *                      and use this one in case it exists
 134      * @param buildDirName  name of the docker build/staging directory, which will
 135      *                      be created in the jtreg's scratch folder
 136      * @throws Exception
 137      */
 138     public static void
 139         buildJdkDockerImage(String imageName, String dockerfile, String buildDirName)
 140             throws Exception {
 141 
 142         buildJdkDockerImage(imageName, dockerfile, buildDirName, "");
 143     }
 144 
 145     /**
 146      * Build a docker image that contains JDK under test.
 147      * The jdk will be placed under the "/jdk/" folder inside the docker file system.
 148      *
 149      * @param imageName     name of the image to be created, including version tag
 150      * @param dockerfile    name of the dockerfile residing in the test source;
 151      *                      we check for a platform specific dockerfile as well
 152      *                      and use this one in case it exists
 153      * @param buildDirName  name of the docker build/staging directory, which will
 154      *                      be created in the jtreg's scratch folder
 155      * @param additionalDockerFileContent
 156      *                      additional docker file content to be appended to the
 157      *                      template
 158      * @throws Exception
 159      */
 160     public static void
 161         buildJdkDockerImage(String imageName, String dockerfile,
 162                             String buildDirName, String additionalDockerFileContent)
 163             throws Exception {
 164 
 165         Path buildDir = Paths.get(".", buildDirName);
 166         if (Files.exists(buildDir)) {
 167             throw new RuntimeException("The docker build directory already exists: " + buildDir);
 168         }
 169 
 170         Path jdkSrcDir = Paths.get(JDK_UNDER_TEST);
 171         Path jdkDstDir = buildDir.resolve("jdk");
 172 
 173         Files.createDirectories(jdkDstDir);
 174 
 175         // Copy JDK-under-test tree to the docker build directory.
 176         // This step is required for building a docker image.
 177         Files.walkFileTree(jdkSrcDir, new CopyFileVisitor(jdkSrcDir, jdkDstDir));
 178         buildDockerImage(imageName, Paths.get(Utils.TEST_SRC, dockerfile),
 179                          buildDir, additionalDockerFileContent);
 180     }
 181 
 182 
 183     /**
 184      * Build a docker image based on given docker file and docker build directory.
 185      *
 186      * @param imageName  name of the image to be created, including version tag
 187      * @param dockerfile  path to the Dockerfile to be used for building the docker
 188      *        image. The specified dockerfile will be copied to the docker build
 189      *        directory as 'Dockerfile'
 190      * @param buildDir  build directory; it should already contain all the content
 191      *        needed to build the docker image.
 192      * @param additionalDockerfileContent  additional docker file content, to be added
 193      *        after the basic template
 194      * @throws Exception
 195      */
 196     public static void
 197         buildDockerImage(String imageName, Path dockerfile,
 198                          Path buildDir, String additionalDockerfileContent) throws Exception {
 199 
 200         generateDockerFile(buildDir.resolve("Dockerfile"),
 201                            DockerfileConfig.getBaseImageName(),
 202                            DockerfileConfig.getBaseImageVersion(),
 203                            additionalDockerfileContent);
 204         try {
 205             // Build the docker
 206             execute(Container.ENGINE_COMMAND, "build", "--no-cache", "--tag", imageName, buildDir.toString())
 207                 .shouldHaveExitValue(0)
 208                 .shouldContain("Successfully built");
 209         } catch (Exception e) {
 210             // If docker image building fails there is a good chance it happens due to environment and/or
 211             // configuration other than product failure. Throw jtreg skipped exception in such case
 212             // instead of failing the test.
 213             throw new SkippedException("Building docker image failed. Details: \n" + e.getMessage());
 214         }
 215 
 216     }
 217 
 218     /**
 219      * Build a docker image based on given docker file and docker build directory.
 220      *
 221      * @param imageName  name of the image to be created, including version tag
 222      * @param dockerfile  path to the Dockerfile to be used for building the docker
 223      *        image. The specified dockerfile will be copied to the docker build
 224      *        directory as 'Dockerfile'
 225      * @param buildDir  build directory; it should already contain all the content
 226      *        needed to build the docker image.
 227      * @throws Exception
 228      */
 229     public static void
 230         buildDockerImage(String imageName, Path dockerfile, Path buildDir) throws Exception {
 231         buildDockerImage(imageName, dockerfile, buildDir, "");
 232     }
 233 
 234 
 235     /**
 236      * Build the docker command to run java inside a container
 237      *
 238      * @param DockerRunOptions options for running docker
 239      *
 240      * @return command
 241      * @throws Exception
 242      */
 243     public static List<String> buildJavaCommand(DockerRunOptions opts) throws Exception {
 244         List<String> cmd = new ArrayList<>();
 245 
 246         cmd.add(Container.ENGINE_COMMAND);
 247         cmd.add("run");
 248         if (opts.tty)
 249             cmd.add("--tty=true");
 250         if (opts.removeContainerAfterUse)
 251             cmd.add("--rm");


 316 
 317         long started = System.currentTimeMillis();
 318         Process p = pb.start();
 319         long pid = p.pid();
 320         OutputAnalyzer output = new OutputAnalyzer(p);
 321 
 322         String stdoutLogFile = String.format("docker-stdout-%d.log", pid);
 323         System.out.println("[ELAPSED: " + (System.currentTimeMillis() - started) + " ms]");
 324         System.out.println("[STDERR]\n" + output.getStderr());
 325         System.out.println("[STDOUT]\n" +
 326                            trimLines(output.getStdout(),MAX_LINES_TO_COPY_FOR_CHILD_STDOUT));
 327         System.out.printf("Child process STDOUT is trimmed to %d lines \n",
 328                            MAX_LINES_TO_COPY_FOR_CHILD_STDOUT);
 329         writeOutputToFile(output.getStdout(), stdoutLogFile);
 330         System.out.println("Full child process STDOUT was saved to " + stdoutLogFile);
 331 
 332         return output;
 333     }
 334 
 335 
 336     /**
 337      * Check if a container is running
 338      *
 339      * @param  name    container name
 340      * @return True if container is running
 341      * @throws Exception
 342      */
 343     public static boolean isContainerRunning(String name) throws Exception {
 344         OutputAnalyzer out =
 345             DockerTestUtils.execute(Container.ENGINE_COMMAND,
 346                                     "ps", "--no-trunc",
 347                                     "--filter", "name=" + name);
 348         return out.getStdout().contains(name);
 349     }
 350 
 351 
 352     /**
 353      * Wait for container to start
 354      *
 355      * @param  name            container name
 356      * @param  initialDelay    initial delay (milliseconds) before the first check
 357      * @param  checkDelay      delay between checks (milliseconds)
 358      * @param  count           how many times to check before giving up
 359      * @throws Exception       will throw an exception if a specified container did not start
 360      */
 361     public static void waitForContainerToStart(String name, int initialDelay,
 362                                                 int checkDelay, int count) throws Exception {
 363         boolean started = false;
 364 
 365         try { Thread.sleep(initialDelay); } catch (InterruptedException e) {}
 366 
 367         for(int i=0; i < count; i++) {
 368             try { Thread.sleep(checkDelay); } catch (InterruptedException e) {}
 369             if (isContainerRunning(name)) {
 370                 started = true;
 371                 break;
 372             }
 373             System.out.println("The main container has not started yet, count = " + i);
 374         }
 375         if (!started) {
 376             throw new RuntimeException("Main container did not start");
 377         }
 378     }
 379 
 380 
 381     private static void writeOutputToFile(String output, String fileName) throws Exception {
 382         try (FileWriter fw = new FileWriter(fileName)) {
 383             fw.write(output, 0, output.length());
 384         }
 385     }
 386 
 387 
 388     private static String trimLines(String buffer, int nrOfLines) {
 389         List<String> l = Arrays.asList(buffer.split("\\R"));
 390         if (l.size() < nrOfLines) {
 391             return buffer;
 392         }
 393 
 394         return String.join("\n", l.subList(0, nrOfLines));
 395     }
 396 
 397 
 398     private static void generateDockerFile(Path dockerfile, String baseImage,
 399                                            String baseImageVersion,
 400                                            String additionalDockerfileContent) throws Exception {
 401         String template =
 402             "FROM %s:%s\n" +
 403             "COPY /jdk /jdk\n" +
 404             "ENV JAVA_HOME=/jdk\n" +
 405             "CMD [\"/bin/bash\"]\n" +
 406             additionalDockerfileContent;
 407 
 408         String dockerFileStr = String.format(template, baseImage, baseImageVersion);
 409         Files.writeString(dockerfile, dockerFileStr);
 410     }
 411 

 412     private static class CopyFileVisitor extends SimpleFileVisitor<Path> {
 413         private final Path src;
 414         private final Path dst;
 415 
 416         public CopyFileVisitor(Path src, Path dst) {
 417             this.src = src;
 418             this.dst = dst;
 419         }
 420 
 421 
 422         @Override
 423         public FileVisitResult preVisitDirectory(Path file,
 424                 BasicFileAttributes attrs) throws IOException {
 425             Path dstDir = dst.resolve(src.relativize(file));
 426             if (!dstDir.toFile().exists()) {
 427                 Files.createDirectories(dstDir);
 428             }
 429             return FileVisitResult.CONTINUE;
 430         }
 431 
< prev index next >