From 9a7336ff7dcf23567953af23f59740102769e83b Mon Sep 17 00:00:00 2001 From: Robi Nino Date: Mon, 8 Mar 2021 19:08:17 +0200 Subject: [PATCH] Fix failure due to empty fields in permission target --- README.md | 8 ++++- artifactory/emptymanager.go | 5 +++ artifactory/manager.go | 6 ++++ artifactory/services/permissiontarget.go | 31 +++++++++++++--- tests/artifactorypermissiontarget_test.go | 44 +++++++++++++---------- 5 files changed, 70 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 5a990366a..15f6f81b9 100644 --- a/README.md +++ b/README.md @@ -728,7 +728,13 @@ err = servicesManager.UpdatePermissionTarget(params) #### Removing a Permission Target You can remove a permission target from Artifactory using its name: ```go -servicesManager.DeletePermissionTarget("java-developers") +err = servicesManager.DeletePermissionTarget("java-developers") +``` + +#### Fetching a Permission Target +You can fetch a permission target from Artifactory using its name: +```go +permissionTargetParams, err = servicesManager.GetPermissionTarget("java-developers") ``` #### Fetching Artifactory's Version diff --git a/artifactory/emptymanager.go b/artifactory/emptymanager.go index df23263b9..1735140ba 100644 --- a/artifactory/emptymanager.go +++ b/artifactory/emptymanager.go @@ -25,6 +25,7 @@ type ArtifactoryServicesManager interface { CreatePermissionTarget(params services.PermissionTargetParams) error UpdatePermissionTarget(params services.PermissionTargetParams) error DeletePermissionTarget(permissionTargetName string) error + GetPermissionTarget(permissionTargetName string) (*services.PermissionTargetParams, error) PublishBuildInfo(build *buildinfo.BuildInfo, projectKey string) error DistributeBuild(params services.BuildDistributionParams) error PromoteBuild(params services.PromotionParams) error @@ -121,6 +122,10 @@ func (esm *EmptyArtifactoryServicesManager) DeletePermissionTarget(permissionTar panic("Failed: Method is not implemented") } +func (esm *EmptyArtifactoryServicesManager) GetPermissionTarget(permissionTargetName string) (*services.PermissionTargetParams, error) { + panic("Failed: Method is not implemented") +} + func (esm *EmptyArtifactoryServicesManager) PublishBuildInfo(build *buildinfo.BuildInfo, project string) error { panic("Failed: Method is not implemented") } diff --git a/artifactory/manager.go b/artifactory/manager.go index 19706741e..1f7b9269b 100644 --- a/artifactory/manager.go +++ b/artifactory/manager.go @@ -114,6 +114,12 @@ func (sm *ArtifactoryServicesManagerImp) DeletePermissionTarget(permissionTarget return permissionTargetService.Delete(permissionTargetName) } +func (sm *ArtifactoryServicesManagerImp) GetPermissionTarget(permissionTargetName string) (*services.PermissionTargetParams, error) { + permissionTargetService := services.NewPermissionTargetService(sm.client) + permissionTargetService.ArtDetails = sm.config.GetServiceDetails() + return permissionTargetService.Get(permissionTargetName) +} + func (sm *ArtifactoryServicesManagerImp) PublishBuildInfo(build *buildinfo.BuildInfo, projectKey string) error { buildInfoService := services.NewBuildInfoService(sm.client) buildInfoService.DryRun = sm.config.IsDryRun() diff --git a/artifactory/services/permissiontarget.go b/artifactory/services/permissiontarget.go index 4196c0368..1dd28544c 100644 --- a/artifactory/services/permissiontarget.go +++ b/artifactory/services/permissiontarget.go @@ -42,6 +42,25 @@ func (pts *PermissionTargetService) Delete(permissionTargetName string) error { return nil } +func (pts *PermissionTargetService) Get(permissionTargetName string) (*PermissionTargetParams, error) { + httpClientsDetails := pts.ArtDetails.CreateHttpClientDetails() + log.Info("Getting permission target...") + resp, body, _, err := pts.client.SendGet(pts.ArtDetails.GetUrl()+"api/v2/security/permissions/"+permissionTargetName, true, &httpClientsDetails) + if err != nil { + return nil, err + } + if resp.StatusCode != http.StatusOK { + return nil, errorutils.CheckError(errors.New("Artifactory response: " + resp.Status + "\n" + clientutils.IndentJson(body))) + } + + log.Debug("Artifactory response:", resp.Status) + permissionTarget := &PermissionTargetParams{} + if err := json.Unmarshal(body, permissionTarget); err != nil { + return nil, err + } + return permissionTarget, nil +} + func (pts *PermissionTargetService) Create(params PermissionTargetParams) error { return pts.performRequest(params, false) } @@ -85,18 +104,20 @@ func NewPermissionTargetParams() PermissionTargetParams { return PermissionTargetParams{} } +// Using struct pointers to keep the fields null if they are empty. +// Artifactory evaluates inner struct typed fields if they are not null, which can lead to failures in the request. type PermissionTargetParams struct { - Name string `json:"name"` - Repo PermissionTargetSection `json:"repo,omitempty"` - Build PermissionTargetSection `json:"build,omitempty"` - ReleaseBundle PermissionTargetSection `json:"releaseBundle,omitempty"` + Name string `json:"name"` + Repo *PermissionTargetSection `json:"repo,omitempty"` + Build *PermissionTargetSection `json:"build,omitempty"` + ReleaseBundle *PermissionTargetSection `json:"releaseBundle,omitempty"` } type PermissionTargetSection struct { IncludePatterns []string `json:"include-patterns,omitempty"` ExcludePatterns []string `json:"exclude-patterns,omitempty"` Repositories []string `json:"repositories"` - Actions Actions `json:"actions,omitempty"` + Actions *Actions `json:"actions,omitempty"` } type Actions struct { diff --git a/tests/artifactorypermissiontarget_test.go b/tests/artifactorypermissiontarget_test.go index 3982208ea..b88c1edc7 100644 --- a/tests/artifactorypermissiontarget_test.go +++ b/tests/artifactorypermissiontarget_test.go @@ -1,12 +1,8 @@ package tests import ( - "encoding/json" - "errors" "fmt" "github.com/jfrog/jfrog-client-go/artifactory/services" - "github.com/jfrog/jfrog-client-go/http/httpclient" - "net/http" "testing" "time" @@ -20,12 +16,16 @@ const ( func TestPermissionTarget(t *testing.T) { params := services.NewPermissionTargetParams() params.Name = fmt.Sprintf("%s-%d", PermissionTargetNamePrefix, time.Now().Unix()) + params.Repo = &services.PermissionTargetSection{} params.Repo.Repositories = []string{"ANY"} params.Repo.ExcludePatterns = []string{"dir/*"} + params.Repo.Actions = &services.Actions{} params.Repo.Actions.Users = map[string][]string{ "anonymous": {"read"}, } + params.Build = &services.PermissionTargetSection{} params.Build.Repositories = []string{"artifactory-build-info"} + params.Build.Actions = &services.Actions{} params.Build.Actions.Users = map[string][]string{ "anonymous": {"annotate"}, } @@ -54,22 +54,30 @@ func validatePermissionTarget(t *testing.T, params services.PermissionTargetPara assert.Equal(t, params.Name, targetConfig.Name) assert.Equal(t, params.Repo, targetConfig.Repo) assert.Equal(t, params.Build, targetConfig.Build) - return + assert.Equal(t, params.ReleaseBundle, targetConfig.ReleaseBundle) } func getPermissionTarget(targetName string) (targetParams *services.PermissionTargetParams, err error) { - artDetails := GetRtDetails() - artHttpDetails := artDetails.CreateHttpClientDetails() - client, err := httpclient.ClientBuilder().Build() - if err != nil { - return - } - resp, body, _, err := client.SendGet(artDetails.GetUrl()+"api/v2/security/permissions/"+targetName, false, artHttpDetails) - if err != nil || resp.StatusCode != http.StatusOK { - return - } - if err = json.Unmarshal(body, &targetParams); err != nil { - return nil, errors.New("failed unmarshalling permission target " + targetName) + return testsPermissionTargetService.Get(targetName) +} + +// Assert empty inner structs remain nil unless explicitly set. +func TestPermissionTargetEmptyFields(t *testing.T) { + params := services.NewPermissionTargetParams() + params.Name = fmt.Sprintf("%s-%d", PermissionTargetNamePrefix, time.Now().Unix()) + + assert.Nil(t, params.Repo) + params.Repo = &services.PermissionTargetSection{} + params.Repo.Repositories = []string{"ANY"} + params.Repo.IncludePatterns = []string{"**"} + params.Repo.ExcludePatterns = []string{"dir/*"} + params.Repo.Actions = &services.Actions{} + params.Repo.Actions.Users = map[string][]string{ + "anonymous": {"read"}, } - return + + assert.Nil(t, params.Build) + assert.Nil(t, params.ReleaseBundle) + assert.NoError(t, testsPermissionTargetService.Create(params)) + validatePermissionTarget(t, params) }