All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.codacy.plugins.utils.BinaryDockerHelper.scala Maven / Gradle / Ivy

package com.codacy.plugins.utils

import java.nio.file.{Files, Path}

import com.codacy.plugins.api.PatternDescription
import com.codacy.plugins.runners.{DockerConstants, IDocker}
import com.codacy.plugins.utils.impl.CacheDockerHelper

import scala.util.{Properties, Try}

class BinaryDockerHelper(useCachedDocs: Boolean = true) extends DockerHelper {

  private val cacheDockerHelper = new CacheDockerHelper()

  override def readDescription(docker: IDocker): Option[Set[PatternDescription]] = {
    val cachedDescriptions = if (useCachedDocs) cacheDockerHelper.readDescription(docker) else None

    cachedDescriptions.orElse {
      val cmd =
        s"${DockerConstants.dockerRunCmd} --entrypoint=cat ${docker.dockerImageName} ${cachedDescriptionsPathPrefix.resolve("description.json")}"
          .split(" ")
          .toList

      val descriptionsOpt: Option[String] = CommandRunner.exec(cmd).map(_.mkString(System.lineSeparator())).toOption
      parseDescriptions(docker, descriptionsOpt)
    }
  }

  override def readRaw(docker: IDocker, path: Path): Option[String] =
    Try {
      val cachedFile = if (useCachedDocs) cacheDockerHelper.readRaw(docker, path) else None

      cachedFile.orElse {
        val shCmd =
          s"""if [ -f $path ]; then
             |  cat $path;
             |  if [ $$? -ne 0 ]; then
             |    exit 2;
             |  fi
             |else exit 1; fi""".stripMargin
        val cmd =
          s"""${DockerConstants.dockerRunCmd} --entrypoint=sh ${docker.dockerImageName} -c"""
            .split(' ')
            .filter(_ != "")
            .toList :+ shCmd
        val errorMsg = s"Failed to read docs from ${docker.dockerName} path $path"
        CommandRunner.execSync(cmd) match {
          case Right(CommandResult(0, stdout, stderr)) =>
            Some(stdout.mkString(Properties.lineSeparator))
          case Right(CommandResult(1, stdout, stderr)) => // file doesn't exist
            None
          case Right(CommandResult(code, stdout, stderr)) =>
            Log.error(s"""$errorMsg
                          |stdout: ${stdout.mkString(Properties.lineSeparator)}
                          |stderr: ${stderr.mkString(Properties.lineSeparator)}""".stripMargin)
            None
          case Left(e) =>
            Log.error(errorMsg, e)
            None
        }
      }
    }.toOption.flatten

  protected def parseDescriptions(docker: IDocker, rawDescriptions: Option[String]): Option[Set[PatternDescription]] = {

    rawDescriptions.flatMap(parseJsonDescriptions).map { descriptions =>
      withDescriptionsDirectory(docker.dockerImageName) { directory =>
        descriptions.map { pattern =>
          val descPath = directory.resolve(s"${pattern.patternId}.md")
          val fileContents = FileHelper.read(descPath.toFile).map(_.mkString(Properties.lineSeparator))
          pattern.copy(explanation = fileContents)
        }
      }
    }
  }

  private def withDescriptionsDirectory[T](dockerImageName: String)(block: Path => T): T = {
    val sourceDir = Files.createTempDirectory("docker-test-folders")
    val dockerStartedCmd = s"${DockerConstants.dockerRunNonDaemonCmd} -d --entrypoint=sh $dockerImageName"

    for {
      output <- CommandRunner.exec(dockerStartedCmd.split(" ").toList).toOption
      containerId <- output.headOption
      // Copy files from running container
      _ <- CommandRunner.exec(s"docker cp $containerId:/docs/description $sourceDir".split(" ").toList).toOption
      // Remove container
      _ <- CommandRunner.exec(s"docker rm -f $containerId".split(" ").toList).toOption
    } yield ()

    val result = block(sourceDir.resolve("description"))

    CommandRunner.exec(s"rm -f ${sourceDir.toString}".split(" ").toList)

    result
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy