0

神器版本:5.8.4

在 Artifactory 中,文件通过文件的校验和 (SHA1) 存储在内部数据库中,出于检索目的,SHA-256 很有用(用于验证文件是否完整)。

首先阅读:https ://www.jfrog.com/confluence/display/RTF/Checksum-Based+Storage

假设有 2 个 Jenkins 作业,它们创建的工件/文件(rpm/jar/etc)很少。就我而言,我将采用一个简单的 .txt 文件,它以 MM/DD/YYYY 格式存储日期和其他一些 jobA/B 特定的构建结果文件(jars/rpms 等)。

如果我们只关注文本文件(如上所述),那么:

Jenkins_jobA > 生成 jobA.date_mm_dd_yy.txt

Jenkins_jobA > 生成jobB.date_mm_dd_yy.txt

Jenkins jobA 和 jobB 每天运行多次,没有给定的运行顺序。有时jobA首先运行,有时jobB。

由于两个作业的文件内容基本相同(每天),jobA 的 .txt 文件和 jobB.txt 文件上的 SHA-1 值将相同,即在 Artifactory 中,两个文件都将存储在前 2 个字符中目录文件夹结构(根据基于校验和的存储机制)。

基本上在 Linux 的两个文件上运行 sha1sum 和 sha256sum 会返回完全相同的输出。

随着时间的推移,这些工件(.txt 等)从一个存储库提升到另一个存储库(提升过程,即从快照 -> 阶段 -> 发布存储库),所以我目前用 Groovy 编写的逻辑是找到位于后面的工件的URI下面列出了“虚拟”存储库(其中包含一组按某种顺序排列的物理本地存储库):

// Groovy code
import groovy.json.JsonSlurper
import groovy.json.JsonOutput
jsonSlurper = new JsonSlurper()

// The following function will take artifact.SHA_256 as it's parameter to find URI of the artifact

def checkSumBasedSearch(artifactSha) {
virt_repo = "jar-repo"    // this virtual may have many physical repos release/stage/snapshot for jar(maven) or it can be a YUM repo for (rpm) or generic repo for (.txt file)
// Note: Virtual repos don't span different repo types (i.e. a virtual repository in Artifactory for "Maven" artifacts (jar/war/etc) can NOT see YUM/PyPi/Generic physical Repos).

// Run aqlCmd on Linux, requires "...", "..", "..." for every distinctive words / characters in the cmd line.
checkSum_URL = artifactoryURL + "/api/search/checksum?sha256="
aqlCmd = ["curl", "-u", username + ":" + password, "${checkSum_URL}" + artifactSha + "&repos=" + virt_repo]
  }

  def procedure = aqlCmd.execute()
  def standardOut = new StringBuilder(), standardErr = new StringBuilder()
  procedure.waitForProcessOutput(standardOut, standardErr) 
  // Fail early

  if (! standardErr ) {
    println "\n\n-- checkSumBasedSearch() - standardErr exists ---\n" + standardErr +"\n\n-- Exiting with error 12!!!\n\n"
    System.exit(12)
  }

  def obj = jsonSlurper.parseText(standardOut.toString())
  def results = obj.results
  def uri = results[0].uri       // This would work, if a file's sha-1 /256 is always different or sits in different repo at least. 
  return uri

  // to get the URL, I can use:
  //aqlCmd = ["curl", "-u", username + ":" + password, "${uri}"]
  //def procedure = aqlCmd.execute()
  //def obj = jsonSlurper.parseText(standardOut.toString())
  //def url = obj.downloadUri 
  //return url
  //aqlCmd = [ "curl", "-u", username + ":" + password, "${url}", "-o", somedirectory + "/" + variableContainingSomeArtifactFilenameThatIWant ]
  //
  // def procedure = aqlCmd.execute()
  //def standardOut = new StringBuilder(), standardErr = new StringBuilder()
  //procedure.waitForProcessOutput(standardOut, standardErr)
  // Now, I'll get the artifact downloaded in some Directory as some Filename.

}

我担心的是,由于两个文件(即使名称不同-or file-<versioned-timestamp>.txt)在其中具有相同的内容并且每天生成多次,我如何才能为 jobA 或 jobB 下载特定版本的文件?

在 Artifactory 中,包含相同内容的所有文件的 SHA_256 属性将相同!!(Artifactory 将使用 SHA-1 有效地存储这些文件以节省空间,新的上传将只是对用户透明的最小数据库级事务)。

问题:

  1. 上述逻辑是否会返回jobA的文件或jobB的.txt文件或任何Job的.txt文件,它首先上传它的文件或latest/acc。到 LastModified -aka- 最后上传时间?

  2. 如何为给定的时间戳下载 jobA 的 .txt 文件和 jobB 的 .txt 文件?

  3. 我需要在我的休息 Api 调用期间添加更多属性吗?

如果我只是关心文件内容,那么无论它来自 JobA .txt 还是来自作业的 .txt 文件都没有多大关系(取决于 sha-1/256),但在复杂的情况下,文件名可能包含他们想知道的有意义的信息,以找到下载的文件(A / B)!

4

2 回答 2

0

您可以使用 AQL(人工查询语言)

https://www.jfrog.com/confluence/display/RTF/Artifactory+Query+Language

curl -u<username>:<password> -XPOST https://repo.jfrog.io/artifactory/api/search/aql -H "Content-Type: text/plain" -T ./search

名为search的文件内容为:

items.find(
  {
    "artifact.module.build.name":{"$eq":"<build name>"},
    "artifact.sha1":"<sha1>"
  }
)
  1. 上述逻辑(在原始问题中)将任意返回其中一个,因为您正在获取返回的第一个结果并且无法保证订单。

  2. 由于您的文本文件在名称中包含时间戳,因此您可以将名称添加到上面给出的 aql,它也会按名称过滤。

  3. AQL 搜索 API 比校验和搜索更灵活,使用它并根据您需要的参数自定义查询。

于 2018-08-21T14:50:58.900 回答
0

所以,我最终这样做了,而不是在每种情况下都从数组中返回第 [0] 个元素。

  // Do NOT return [0] first element as yet as Artifactory uses SHA-1/256 so return [Nth].uri where artifact's full name matches with the sha256
  // def uri = results[0].uri

  def nThIndex=0
  def foundFlag = 'false'
  for (r in results) {
    println "> " + r.uri + " < " + r.uri.toString() + " artifact: " + artFullName
    if ( r.uri.toString().contains(artFullName) ) {
       foundFlag = 'true'
       println "- OK - Found artifact: " + artFullName + " at results[" + nThIndex + "] index."
       break; // i.e. a match for the artifact name with SHA-256 we want - has been found.
    } else {
       nThIndex++;
    }
  }

  if ( foundFlag == 'true' ) {
      def uri = results[nThIndex].uri
      return uri
  } else {
    // Fail early if results were found based on SHA256 but not for the artifact but for some other filename with same SHA256
    if (! standardErr ) {
      println "\n\n\n\n-- [Cool] -- checkSum_Search() - SHA-256 unwanted situation occurred !!! -- results Array was set with some values BUT it didn't contain the artifact (" + artFullName + ") that we were looking for \n\n\n-- !!! Artifact NOT FOUND in the results array during checkSum_Search()---\n\n\n-- Exiting with error 17!!!\n\n\n\n"
      System.exit(17)   // Nooka
    }
  }
于 2018-08-24T17:48:14.427 回答