feat: Allow Jfrog Artifactory authentication to be configured via env var

This commit is contained in:
iofq
2026-04-30 14:07:36 -05:00
committed by André Roth
parent 3333a643cb
commit 4655f10048
2 changed files with 86 additions and 31 deletions
+47 -30
View File
@@ -30,28 +30,45 @@ var (
_ aptly.PublishedStorage = (*PublishedStorage)(nil) _ aptly.PublishedStorage = (*PublishedStorage)(nil)
) )
func createPublishedStorageConfig(url, user, password, apiKey, accessToken string) (config.Config, error) {
artDetails := auth.NewArtifactoryDetails()
artDetails.SetUrl(url)
if user == "" {
user = os.Getenv("JFROG_USERNAME");
}
if password == "" {
password = os.Getenv("JFROG_PASSWORD");
}
if apiKey == "" {
apiKey = os.Getenv("JFROG_APIKEY");
}
if accessToken == "" {
accessToken = os.Getenv("JFROG_ACCESSTOKEN");
}
if user != "" && password != "" {
artDetails.SetUser(user)
artDetails.SetPassword(password)
} else if apiKey != "" {
artDetails.SetApiKey(apiKey)
} else if accessToken != "" {
artDetails.SetAccessToken(accessToken)
}
return config.NewConfigBuilder().
SetServiceDetails(artDetails).
SetDryRun(false).
Build()
}
// NewPublishedStorageRaw creates jfrog PublishedStorage from raw connection specs // NewPublishedStorageRaw creates jfrog PublishedStorage from raw connection specs
func NewPublishedStorageRaw( func NewPublishedStorageRaw(
repository, url, user, password, apiKey, accessToken, prefix string, repository, url, user, password, apiKey, accessToken, prefix string,
plusWorkaround, debug bool, plusWorkaround, debug bool,
) (*PublishedStorage, error) { ) (*PublishedStorage, error) {
artDetails := auth.NewArtifactoryDetails() serviceConfig, err := createPublishedStorageConfig(url, user, password, apiKey, accessToken)
artDetails.SetUrl(url)
if user != "" && password != "" {
artDetails.SetUser(user)
artDetails.SetPassword(password)
} else if apiKey != "" {
artDetails.SetApiKey(apiKey)
} else if accessToken != "" {
artDetails.SetAccessToken(accessToken)
}
serviceConfig, err := config.NewConfigBuilder().
SetServiceDetails(artDetails).
SetDryRun(false).
Build()
if err != nil { if err != nil {
return nil, errors.Wrap(err, "error building jfrog client config") return nil, errors.Wrap(err, "error building jfrog client config")
} }
@@ -91,7 +108,7 @@ func (storage *PublishedStorage) PutFile(path string, sourceFilename string) err
if storage.plusWorkaround { if storage.plusWorkaround {
targetPath = strings.Replace(targetPath, "+", "%2B", -1) targetPath = strings.Replace(targetPath, "+", "%2B", -1)
} }
params := services.NewUploadParams() params := services.NewUploadParams()
params.Pattern = sourceFilename params.Pattern = sourceFilename
params.Target = targetPath params.Target = targetPath
@@ -106,7 +123,7 @@ func (storage *PublishedStorage) Remove(path string) error {
if storage.plusWorkaround { if storage.plusWorkaround {
targetPath = strings.Replace(targetPath, "+", "%2B", -1) targetPath = strings.Replace(targetPath, "+", "%2B", -1)
} }
deleteParams := services.NewDeleteParams() deleteParams := services.NewDeleteParams()
deleteParams.SetPattern(targetPath) deleteParams.SetPattern(targetPath)
@@ -175,7 +192,7 @@ func (storage *PublishedStorage) Filelist(prefix string) ([]string, error) {
return nil, err return nil, err
} }
defer reader.Close() defer reader.Close()
var paths []string var paths []string
for element := new(utils.ResultItem); reader.NextRecord(element) == nil; element = new(utils.ResultItem) { for element := new(utils.ResultItem); reader.NextRecord(element) == nil; element = new(utils.ResultItem) {
@@ -186,19 +203,19 @@ func (storage *PublishedStorage) Filelist(prefix string) ([]string, error) {
} }
paths = append(paths, relPath) paths = append(paths, relPath)
} }
return paths, nil return paths, nil
} }
func (storage *PublishedStorage) RenameFile(oldName, newName string) error { func (storage *PublishedStorage) RenameFile(oldName, newName string) error {
oldTarget := filepath.Join(storage.repository, storage.prefix, oldName) oldTarget := filepath.Join(storage.repository, storage.prefix, oldName)
newTarget := filepath.Join(storage.repository, storage.prefix, newName) newTarget := filepath.Join(storage.repository, storage.prefix, newName)
if storage.plusWorkaround { if storage.plusWorkaround {
oldTarget = strings.Replace(oldTarget, "+", "%2B", -1) oldTarget = strings.Replace(oldTarget, "+", "%2B", -1)
newTarget = strings.Replace(newTarget, "+", "%2B", -1) newTarget = strings.Replace(newTarget, "+", "%2B", -1)
} }
params := services.NewMoveCopyParams() params := services.NewMoveCopyParams()
params.Pattern = oldTarget params.Pattern = oldTarget
params.Target = newTarget params.Target = newTarget
@@ -211,17 +228,17 @@ func (storage *PublishedStorage) RenameFile(oldName, newName string) error {
func (storage *PublishedStorage) SymLink(src string, dst string) error { func (storage *PublishedStorage) SymLink(src string, dst string) error {
oldTarget := filepath.Join(storage.repository, storage.prefix, src) oldTarget := filepath.Join(storage.repository, storage.prefix, src)
newTarget := filepath.Join(storage.repository, storage.prefix, dst) newTarget := filepath.Join(storage.repository, storage.prefix, dst)
if storage.plusWorkaround { if storage.plusWorkaround {
oldTarget = strings.Replace(oldTarget, "+", "%2B", -1) oldTarget = strings.Replace(oldTarget, "+", "%2B", -1)
newTarget = strings.Replace(newTarget, "+", "%2B", -1) newTarget = strings.Replace(newTarget, "+", "%2B", -1)
} }
params := services.NewMoveCopyParams() params := services.NewMoveCopyParams()
params.Pattern = oldTarget params.Pattern = oldTarget
params.Target = newTarget params.Target = newTarget
params.Flat = true params.Flat = true
props := utils.NewProperties() props := utils.NewProperties()
props.AddProperty("SymLink", src) props.AddProperty("SymLink", src)
params.SetTargetProps(props) params.SetTargetProps(props)
@@ -239,7 +256,7 @@ func (storage *PublishedStorage) FileExists(path string) (bool, error) {
if storage.plusWorkaround { if storage.plusWorkaround {
targetPath = strings.Replace(targetPath, "+", "%2B", -1) targetPath = strings.Replace(targetPath, "+", "%2B", -1)
} }
params := services.NewSearchParams() params := services.NewSearchParams()
params.Pattern = targetPath params.Pattern = targetPath
@@ -248,7 +265,7 @@ func (storage *PublishedStorage) FileExists(path string) (bool, error) {
return false, err return false, err
} }
defer reader.Close() defer reader.Close()
length, err := reader.Length() length, err := reader.Length()
isEmpty := length == 0 isEmpty := length == 0
return !isEmpty, err return !isEmpty, err
@@ -259,17 +276,17 @@ func (storage *PublishedStorage) ReadLink(path string) (string, error) {
if storage.plusWorkaround { if storage.plusWorkaround {
targetPath = strings.Replace(targetPath, "+", "%2B", -1) targetPath = strings.Replace(targetPath, "+", "%2B", -1)
} }
props, err := storage.manager.GetItemProps(targetPath) props, err := storage.manager.GetItemProps(targetPath)
if err != nil { if err != nil {
return "", nil return "", nil
} }
for k, v := range props.Properties { for k, v := range props.Properties {
if k == "SymLink" && len(v) > 0 { if k == "SymLink" && len(v) > 0 {
return v[0], nil return v[0], nil
} }
} }
return "", nil return "", nil
} }
+39 -1
View File
@@ -18,7 +18,10 @@ import (
. "gopkg.in/check.v1" . "gopkg.in/check.v1"
) )
func Test(t *testing.T) { TestingT(t) } func Test(t *testing.T) {
t.Setenv("JFROG_USERNAME", "userfromenv")
TestingT(t)
}
type fakeJFrogManager struct { type fakeJFrogManager struct {
artifactory.EmptyArtifactoryServicesManager artifactory.EmptyArtifactoryServicesManager
@@ -425,6 +428,41 @@ func (s *PublishedStorageSuite) TestReadLinkPlusWorkaround(c *C) {
c.Assert(s.manager.itemPropsErr, IsNil) c.Assert(s.manager.itemPropsErr, IsNil)
} }
func (s *PublishedStorageSuite) TestCreatePublishedStorageConfig(c *C) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK)
}))
defer server.Close()
withUserPassword, err := createPublishedStorageConfig(server.URL, "user", "password", "", "")
c.Assert(err, IsNil)
withUserPasswordDetails := withUserPassword.GetServiceDetails()
c.Assert(withUserPasswordDetails, NotNil)
c.Assert(withUserPasswordDetails.GetUser(), Equals, "user")
withAPIKey, err := createPublishedStorageConfig(server.URL, "", "", "api-123", "")
c.Assert(err, IsNil)
withAPIKeyDetails := withAPIKey.GetServiceDetails()
c.Assert(withAPIKeyDetails, NotNil)
c.Assert(withAPIKeyDetails.GetApiKey(), Equals, "api-123")
withAccessToken, err := createPublishedStorageConfig(server.URL, "", "", "", "token")
c.Assert(err, IsNil)
withAccessTokenDetails := withAccessToken.GetServiceDetails()
c.Assert(withAccessTokenDetails, NotNil)
c.Assert(withAccessTokenDetails.GetAccessToken(), Equals, "token")
withUserPasswordFromEnv, err := createPublishedStorageConfig(server.URL, "", "password", "", "")
c.Assert(err, IsNil)
withUserPasswordFromEnvDetails := withUserPasswordFromEnv.GetServiceDetails()
c.Assert(withUserPasswordFromEnvDetails, NotNil)
c.Assert(withUserPasswordFromEnvDetails.GetUser(), Equals, "userfromenv")
}
func (s *PublishedStorageSuite) TestNewPublishedStorageRaw(c *C) { func (s *PublishedStorageSuite) TestNewPublishedStorageRaw(c *C) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
w.WriteHeader(http.StatusOK) w.WriteHeader(http.StatusOK)