github.com/jfrog/jfrog-cli-core/v2@v2.52.0/utils/python/utils.go (about)

     1  package utils
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
     6  	"net/url"
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  
    11  	"github.com/jfrog/build-info-go/utils/pythonutils"
    12  	"github.com/jfrog/gofrog/io"
    13  	gofrogcmd "github.com/jfrog/gofrog/io"
    14  	"github.com/jfrog/jfrog-cli-core/v2/utils/config"
    15  	"github.com/jfrog/jfrog-client-go/auth"
    16  	"github.com/jfrog/jfrog-client-go/utils/errorutils"
    17  	"github.com/jfrog/jfrog-client-go/utils/log"
    18  	"github.com/spf13/viper"
    19  )
    20  
    21  const (
    22  	pipenvRemoteRegistryFlag = "--pypi-mirror"
    23  	pipRemoteRegistryFlag    = "-i"
    24  	poetryConfigAuthPrefix   = "http-basic."
    25  	poetryConfigRepoPrefix   = "repositories."
    26  	pyproject                = "pyproject.toml"
    27  )
    28  
    29  func GetPypiRepoUrlWithCredentials(serverDetails *config.ServerDetails, repository string, isCurationCmd bool) (*url.URL, string, string, error) {
    30  	rtUrl, err := url.Parse(serverDetails.GetArtifactoryUrl())
    31  	if err != nil {
    32  		return nil, "", "", errorutils.CheckError(err)
    33  	}
    34  
    35  	username := serverDetails.GetUser()
    36  	password := serverDetails.GetPassword()
    37  
    38  	// Get credentials from access-token if exists.
    39  	if serverDetails.GetAccessToken() != "" {
    40  		if username == "" {
    41  			username = auth.ExtractUsernameFromAccessToken(serverDetails.GetAccessToken())
    42  		}
    43  		password = serverDetails.GetAccessToken()
    44  	}
    45  	// In case of curation command, the download urls should be routed through a dedicated api.
    46  	if isCurationCmd {
    47  		rtUrl.Path += coreutils.CurationPassThroughApi
    48  	}
    49  	rtUrl.Path += "api/pypi/" + repository + "/simple"
    50  	return rtUrl, username, password, err
    51  }
    52  
    53  func GetPypiRemoteRegistryFlag(tool pythonutils.PythonTool) string {
    54  	if tool == pythonutils.Pip {
    55  		return pipRemoteRegistryFlag
    56  	}
    57  	return pipenvRemoteRegistryFlag
    58  }
    59  
    60  func GetPypiRepoUrl(serverDetails *config.ServerDetails, repository string, isCurationCmd bool) (string, error) {
    61  	rtUrl, username, password, err := GetPypiRepoUrlWithCredentials(serverDetails, repository, isCurationCmd)
    62  	if err != nil {
    63  		return "", err
    64  	}
    65  	if password != "" {
    66  		rtUrl.User = url.UserPassword(username, password)
    67  	}
    68  	return rtUrl.String(), err
    69  }
    70  
    71  func ConfigPoetryRepo(url, username, password, configRepoName string) error {
    72  	// Add the poetry repository config
    73  	err := runPoetryConfigCommand([]string{poetryConfigRepoPrefix + configRepoName, url}, false)
    74  	if err != nil {
    75  		return err
    76  	}
    77  
    78  	// Set the poetry repository credentials
    79  	err = runPoetryConfigCommand([]string{poetryConfigAuthPrefix + configRepoName, username, password}, true)
    80  	if err != nil {
    81  		return err
    82  	}
    83  
    84  	// Add the repository config to the pyproject.toml
    85  	currentDir, err := os.Getwd()
    86  	if err != nil {
    87  		return errorutils.CheckError(err)
    88  	}
    89  	if err = addRepoToPyprojectFile(filepath.Join(currentDir, pyproject), configRepoName, url); err != nil {
    90  		return err
    91  	}
    92  	return poetryUpdate()
    93  }
    94  
    95  func poetryUpdate() (err error) {
    96  	log.Info("Running Poetry update")
    97  	cmd := io.NewCommand("poetry", "update", []string{})
    98  	err = gofrogcmd.RunCmd(cmd)
    99  	if err != nil {
   100  		return errorutils.CheckErrorf("Poetry config command failed with: %s", err.Error())
   101  	}
   102  	return
   103  }
   104  
   105  func runPoetryConfigCommand(args []string, maskArgs bool) error {
   106  	logMessage := "config "
   107  	if maskArgs {
   108  		logMessage += "***"
   109  	} else {
   110  		logMessage += strings.Join(args, " ")
   111  	}
   112  	log.Info(fmt.Sprintf("Running Poetry %s", logMessage))
   113  	cmd := io.NewCommand("poetry", "config", args)
   114  	err := gofrogcmd.RunCmd(cmd)
   115  	if err != nil {
   116  		return errorutils.CheckErrorf("Poetry config command failed with: %s", err.Error())
   117  	}
   118  	return nil
   119  }
   120  
   121  func addRepoToPyprojectFile(filepath, poetryRepoName, repoUrl string) error {
   122  	viper.SetConfigType("toml")
   123  	viper.SetConfigFile(filepath)
   124  	err := viper.ReadInConfig()
   125  	if err != nil {
   126  		return errorutils.CheckErrorf("Failed to read pyproject.toml: %s", err.Error())
   127  	}
   128  	viper.Set("tool.poetry.source", []map[string]string{{"name": poetryRepoName, "url": repoUrl}})
   129  	err = viper.WriteConfig()
   130  	if err != nil {
   131  		return errorutils.CheckErrorf("Failed to add tool.poetry.source to pyproject.toml: %s", err.Error())
   132  	}
   133  	log.Info(fmt.Sprintf("Added tool.poetry.source name:%q url:%q", poetryRepoName, repoUrl))
   134  	return err
   135  }