github.com/jfrog/jfrog-cli-core/v2@v2.51.0/utils/dependencies/utils.go (about) 1 package dependencies 2 3 import ( 4 "errors" 5 "fmt" 6 "net/http" 7 "os" 8 "path" 9 10 biutils "github.com/jfrog/build-info-go/utils" 11 "github.com/jfrog/jfrog-cli-core/v2/utils/config" 12 "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" 13 "github.com/jfrog/jfrog-client-go/http/httpclient" 14 "github.com/jfrog/jfrog-client-go/http/jfroghttpclient" 15 "github.com/jfrog/jfrog-client-go/utils/errorutils" 16 "github.com/jfrog/jfrog-client-go/utils/io/fileutils" 17 "github.com/jfrog/jfrog-client-go/utils/io/httputils" 18 "github.com/jfrog/jfrog-client-go/utils/log" 19 ) 20 21 const ( 22 ChecksumFileName = "checksum.sha2" 23 ) 24 25 // Download the relevant build-info-extractor jar. 26 // By default, the jar is downloaded directly from jfrog releases. 27 // 28 // targetPath: The local download path (without the file name). 29 // downloadPath: Artifactory download path. 30 func DownloadExtractor(targetPath, downloadPath string) error { 31 artDetails, remotePath, err := GetExtractorsRemoteDetails(downloadPath) 32 if err != nil { 33 return err 34 } 35 36 return DownloadDependency(artDetails, remotePath, targetPath, false) 37 } 38 39 func CreateChecksumFile(targetPath, checksum string) (err error) { 40 out, err := os.Create(targetPath) 41 defer func() { 42 err = errors.Join(err, errorutils.CheckError(out.Close())) 43 }() 44 if errorutils.CheckError(err) != nil { 45 return err 46 } 47 if _, err = out.Write([]byte(checksum)); err != nil { 48 return errorutils.CheckError(err) 49 } 50 return 51 } 52 53 // GetExtractorsRemoteDetails retrieves the server details necessary to download the build-info extractors from a remote repository. 54 // downloadPath - specifies the path in the remote repository from which the extractors will be downloaded. 55 func GetExtractorsRemoteDetails(downloadPath string) (server *config.ServerDetails, remoteRepo string, err error) { 56 // Download from the remote repository that proxies https://releases.jfrog.io 57 server, remoteRepo, err = getExtractorsRemoteDetailsFromEnv(downloadPath) 58 if remoteRepo == "" && err == nil { 59 // Fallback to the deprecated JFROG_CLI_EXTRACTORS_REMOTE environment variable 60 server, remoteRepo, err = getExtractorsRemoteDetailsFromLegacyEnv(downloadPath) 61 } 62 if remoteRepo != "" || err != nil { 63 return 64 } 65 // Download directly from https://releases.jfrog.io 66 log.Info("The build-info-extractor jar is not cached locally. Downloading it now...\n" + 67 "You can set the repository from which this jar is downloaded.\n" + 68 "Read more about it at " + coreutils.JFrogHelpUrl + "jfrog-cli/downloading-the-maven-and-gradle-extractor-jars") 69 log.Debug("'" + coreutils.ReleasesRemoteEnv + "' environment variable is not configured. Downloading directly from releases.jfrog.io.") 70 // If not configured to download through a remote repository in Artifactory, download from releases.jfrog.io. 71 return &config.ServerDetails{ArtifactoryUrl: coreutils.JfrogReleasesUrl}, path.Join("oss-release-local", downloadPath), nil 72 } 73 74 func getExtractorsRemoteDetailsFromEnv(downloadPath string) (server *config.ServerDetails, remoteRepo string, err error) { 75 server, remoteRepo, err = GetRemoteDetails(coreutils.ReleasesRemoteEnv) 76 if remoteRepo != "" && err == nil { 77 remoteRepo = getFullExtractorsPathInArtifactory(remoteRepo, coreutils.ReleasesRemoteEnv, downloadPath) 78 } 79 return 80 } 81 82 func getExtractorsRemoteDetailsFromLegacyEnv(downloadPath string) (server *config.ServerDetails, remoteRepo string, err error) { 83 server, remoteRepo, err = GetRemoteDetails(coreutils.DeprecatedExtractorsRemoteEnv) 84 if remoteRepo != "" && err == nil { 85 log.Warn(fmt.Sprintf("You are using the deprecated %q environment variable. Use %q instead.\nRead more about it at %sjfrog-cli/downloading-the-maven-and-gradle-extractor-jars", 86 coreutils.DeprecatedExtractorsRemoteEnv, coreutils.ReleasesRemoteEnv, coreutils.JFrogHelpUrl)) 87 remoteRepo = getFullExtractorsPathInArtifactory(remoteRepo, coreutils.DeprecatedExtractorsRemoteEnv, downloadPath) 88 } 89 return 90 } 91 92 // GetRemoteDetails function retrieves the server details and downloads path for the build-info extractor file. 93 // serverAndRepo - the server id and the remote repository that proxies releases.jfrog.io, in form of '<ServerID>/<RemoteRepo>'. 94 // downloadPath - specifies the path in the remote repository from which the extractors will be downloaded. 95 // remoteEnv - the relevant environment variable that was used: releasesRemoteEnv/ExtractorsRemoteEnv. 96 // The function returns the server that matches the given server ID, the complete path of the build-info extractor concatenated with the specified remote repository, and an error if occurred. 97 func GetRemoteDetails(remoteEnv string) (server *config.ServerDetails, repoName string, err error) { 98 serverID, repoName, err := coreutils.GetServerIdAndRepo(remoteEnv) 99 if err != nil { 100 return 101 } 102 if serverID == "" && repoName == "" { 103 // Remote details weren't configured. Assuming that https://releases.jfrog.io should be used. 104 return 105 } 106 server, err = config.GetSpecificConfig(serverID, false, true) 107 return 108 } 109 110 func getFullExtractorsPathInArtifactory(repoName, remoteEnv, downloadPath string) string { 111 if remoteEnv == coreutils.ReleasesRemoteEnv { 112 return path.Join(repoName, "artifactory", "oss-release-local", downloadPath) 113 } 114 return path.Join(repoName, downloadPath) 115 } 116 117 // Downloads the requested resource. 118 // 119 // artDetails: The artifactory server details to download the resource from. 120 // downloadPath: Artifactory download path. 121 // targetPath: The local download path (without the file name). 122 func DownloadDependency(artDetails *config.ServerDetails, downloadPath, targetPath string, shouldExplode bool) (err error) { 123 downloadUrl := artDetails.ArtifactoryUrl + downloadPath 124 log.Info("Downloading JFrog's Dependency from", downloadUrl) 125 filename, localDir := fileutils.GetFileAndDirFromPath(targetPath) 126 tempDirPath, err := fileutils.CreateTempDir() 127 if err != nil { 128 return err 129 } 130 defer func() { 131 err = errors.Join(err, fileutils.RemoveTempDir(tempDirPath)) 132 }() 133 134 // Get the expected check-sum before downloading 135 client, httpClientDetails, err := CreateHttpClient(artDetails) 136 if err != nil { 137 return err 138 } 139 expectedSha1 := "" 140 remoteFileDetails, _, err := client.GetRemoteFileDetails(downloadUrl, &httpClientDetails) 141 if err == nil { 142 expectedSha1 = remoteFileDetails.Checksum.Sha1 143 } else { 144 log.Warn(fmt.Sprintf("Failed to get remote file details.\n Got: %s", err)) 145 } 146 // Download the file 147 downloadFileDetails := &httpclient.DownloadFileDetails{ 148 FileName: filename, 149 DownloadPath: downloadUrl, 150 LocalPath: tempDirPath, 151 LocalFileName: filename, 152 ExpectedSha1: expectedSha1, 153 } 154 client, httpClientDetails, err = CreateHttpClient(artDetails) 155 if err != nil { 156 return err 157 } 158 resp, err := client.DownloadFile(downloadFileDetails, "", &httpClientDetails, shouldExplode, false) 159 if err != nil { 160 err = errorutils.CheckErrorf("received error while attempting to download '%s': %s"+downloadUrl, err.Error()) 161 } 162 if err = errorutils.CheckResponseStatus(resp, http.StatusOK); err != nil { 163 return err 164 } 165 err = coreutils.SetPermissionsRecursively(tempDirPath, 0755) 166 if err != nil { 167 return err 168 } 169 return biutils.CopyDir(tempDirPath, localDir, true, nil) 170 } 171 172 func CreateHttpClient(artDetails *config.ServerDetails) (rtHttpClient *jfroghttpclient.JfrogHttpClient, httpClientDetails httputils.HttpClientDetails, err error) { 173 auth, err := artDetails.CreateArtAuthConfig() 174 if err != nil { 175 return 176 } 177 certsPath, err := coreutils.GetJfrogCertsDir() 178 if err != nil { 179 return 180 } 181 182 httpClientDetails = auth.CreateHttpClientDetails() 183 rtHttpClient, err = jfroghttpclient.JfrogClientBuilder(). 184 SetCertificatesPath(certsPath). 185 SetInsecureTls(artDetails.InsecureTls). 186 SetClientCertPath(auth.GetClientCertPath()). 187 SetClientCertKeyPath(auth.GetClientCertKeyPath()). 188 AppendPreRequestInterceptor(auth.RunPreRequestFunctions). 189 Build() 190 return 191 }