Skip to content

Commit

Permalink
feat: support event token response of Project.Clone (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
nscuro authored Oct 27, 2024
1 parent 782de96 commit 8714936
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 19 deletions.
9 changes: 8 additions & 1 deletion about_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package dtrack

import (
"context"
"fmt"
"github.com/google/uuid"
"github.com/testcontainers/testcontainers-go"
"github.com/testcontainers/testcontainers-go/wait"
Expand Down Expand Up @@ -31,15 +32,21 @@ func TestAboutService_Get(t *testing.T) {
}

type testContainerOptions struct {
Version string
APIPermissions []string
}

func setUpContainer(t *testing.T, options testContainerOptions) *Client {
ctx := context.Background()

version := "latest"
if options.Version != "" {
version = options.Version
}

container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
ContainerRequest: testcontainers.ContainerRequest{
Image: "dependencytrack/apiserver:latest",
Image: fmt.Sprintf("dependencytrack/apiserver:%s", version),
Env: map[string]string{
"JAVA_OPTIONS": "-Xmx1g",
"SYSTEM_REQUIREMENT_CHECK_ENABLED": "false",
Expand Down
7 changes: 4 additions & 3 deletions bom.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"github.com/google/uuid"
"net/http"
"net/url"
"strconv"
"strings"
)

Expand All @@ -21,7 +22,7 @@ type BOMUploadRequest struct {
ParentUUID *uuid.UUID `json:"parentUUID,omitempty"` // Since v4.8.0
ParentName string `json:"parentName,omitempty"` // Since v4.8.0
ParentVersion string `json:"parentVersion,omitempty"` // Since v4.8.0
IsLatest bool `json:"isLatestProjectVersion,omitempty"` // Since v4.12.0
IsLatest *bool `json:"isLatestProjectVersion,omitempty"` // Since v4.12.0
AutoCreate bool `json:"autoCreate"`
BOM string `json:"bom"`
}
Expand Down Expand Up @@ -121,8 +122,8 @@ func (bs BOMService) PostBom(ctx context.Context, uploadReq BOMUploadRequest) (t
}
params["projectTags"] = append(params["projectTags"], strings.Join(tagNames, ","))
}
if uploadReq.IsLatest {
params["isLatest"] = append(params["isLatest"], "true")
if uploadReq.IsLatest != nil {
params["isLatest"] = append(params["isLatest"], strconv.FormatBool(*uploadReq.IsLatest))
}
if uploadReq.ParentUUID != nil {
params["parentUUID"] = append(params["parentUUID"], uploadReq.ParentUUID.String())
Expand Down
10 changes: 6 additions & 4 deletions bom_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestBOMService_Upload(t *testing.T) {
{Name: "foo"},
{Name: "bar"},
},
IsLatest: true,
IsLatest: OptionalBoolOf(true),
AutoCreate: true,
BOM: base64.StdEncoding.EncodeToString([]byte(`
{
Expand All @@ -39,7 +39,8 @@ func TestBOMService_Upload(t *testing.T) {
require.NoError(t, err)
require.Contains(t, project.Tags, Tag{Name: "foo"})
require.Contains(t, project.Tags, Tag{Name: "bar"})
require.True(t, project.IsLatest)
require.NotNil(t, project.IsLatest)
require.True(t, *project.IsLatest)
}

func TestBOMService_PostBom(t *testing.T) {
Expand All @@ -58,7 +59,7 @@ func TestBOMService_PostBom(t *testing.T) {
{Name: "foo"},
{Name: "bar"},
},
IsLatest: true,
IsLatest: OptionalBoolOf(true),
AutoCreate: true,
BOM: `
{
Expand All @@ -74,5 +75,6 @@ func TestBOMService_PostBom(t *testing.T) {
require.NoError(t, err)
require.Contains(t, project.Tags, Tag{Name: "foo"})
require.Contains(t, project.Tags, Tag{Name: "bar"})
require.True(t, project.IsLatest)
require.NotNil(t, project.IsLatest)
require.True(t, *project.IsLatest)
}
2 changes: 1 addition & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func (c Client) isServerVersionAtLeast(targetVersion string) bool {
// and doesn't support "-SNAPSHOT" suffixes.
targetVersionNormalized := fmt.Sprintf("v%s", targetVersion)
actualVersionNormalized := fmt.Sprintf("v%s", strings.TrimSuffix(c.about.Version, "-SNAPSHOT"))
return semver.Compare(targetVersionNormalized, actualVersionNormalized) >= 0
return semver.Compare(targetVersionNormalized, actualVersionNormalized) <= 0
}

func (c Client) assertServerVersionAtLeast(targetVersion string) error {
Expand Down
4 changes: 4 additions & 0 deletions event.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ type EventService struct {

type EventToken string

type EventTokenResponse struct {
Token EventToken `json:"token"`
}

type eventProcessingResponse struct {
Processing bool `json:"processing"`
}
Expand Down
32 changes: 22 additions & 10 deletions project.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ type Project struct {
Properties []ProjectProperty `json:"properties,omitempty"`
Tags []Tag `json:"tags,omitempty"`
Active bool `json:"active"`
IsLatest bool `json:"isLatest"` // Since v4.12.0
IsLatest *bool `json:"isLatest,omitempty"` // Since v4.12.0
Metrics ProjectMetrics `json:"metrics"`
ParentRef *ParentRef `json:"parent,omitempty"`
LastBOMImport int `json:"lastBomImport"`
Expand Down Expand Up @@ -160,21 +160,33 @@ func (ps ProjectService) GetAllByTag(ctx context.Context, tag string, excludeIna
}

type ProjectCloneRequest struct {
ProjectUUID uuid.UUID `json:"project"`
Version string `json:"version"`
IncludeAuditHistory bool `json:"includeAuditHistory"`
IncludeComponents bool `json:"includeComponents"`
IncludeProperties bool `json:"includeProperties"`
IncludeServices bool `json:"includeServices"`
IncludeTags bool `json:"includeTags"`
ProjectUUID uuid.UUID `json:"project"`
Version string `json:"version"`
IncludeACL bool `json:"includeACL"`
IncludeAuditHistory bool `json:"includeAuditHistory"`
IncludeComponents bool `json:"includeComponents"`
IncludePolicyViolations *bool `json:"includePolicyViolations,omitempty"` // Since v4.11.0
IncludeProperties bool `json:"includeProperties"`
IncludeServices bool `json:"includeServices"`
IncludeTags bool `json:"includeTags"`
MakeCloneLatest *bool `json:"makeCloneLatest,omitempty"` // Since v4.12.0
}

func (ps ProjectService) Clone(ctx context.Context, cloneReq ProjectCloneRequest) (err error) {
// Clone triggers a cloning operation.
// An EventToken is only returned for server versions 4.11.0 and newer.
func (ps ProjectService) Clone(ctx context.Context, cloneReq ProjectCloneRequest) (token EventToken, err error) {
req, err := ps.client.newRequest(ctx, http.MethodPut, "/api/v1/project/clone", withBody(cloneReq))
if err != nil {
return
}

_, err = ps.client.doRequest(req, nil)
if ps.client.isServerVersionAtLeast("4.11.0") {
var tokenResponse EventTokenResponse
_, err = ps.client.doRequest(req, &tokenResponse)
token = tokenResponse.Token
} else {
_, err = ps.client.doRequest(req, nil)
}

return
}
50 changes: 50 additions & 0 deletions project_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package dtrack

import (
"context"
"github.com/stretchr/testify/require"
"testing"
)

func TestProjectService_Clone(t *testing.T) {
client := setUpContainer(t, testContainerOptions{
APIPermissions: []string{
PermissionPortfolioManagement,
},
})

project, err := client.Project.Create(context.Background(), Project{
Name: "acme-app",
Version: "1.0.0",
})
require.NoError(t, err)

token, err := client.Project.Clone(context.Background(), ProjectCloneRequest{
ProjectUUID: project.UUID,
Version: "2.0.0",
})
require.NoError(t, err)
require.NotEmpty(t, token)
}

func TestProjectService_Clone_v4_10(t *testing.T) {
client := setUpContainer(t, testContainerOptions{
Version: "4.10.1",
APIPermissions: []string{
PermissionPortfolioManagement,
},
})

project, err := client.Project.Create(context.Background(), Project{
Name: "acme-app",
Version: "1.0.0",
})
require.NoError(t, err)

token, err := client.Project.Clone(context.Background(), ProjectCloneRequest{
ProjectUUID: project.UUID,
Version: "2.0.0",
})
require.NoError(t, err)
require.Empty(t, token)
}
8 changes: 8 additions & 0 deletions util.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,11 @@ func ForEach[T any](pageFetchFunc func(po PageOptions) (Page[T], error), handler

return
}

func OptionalBoolOf(value bool) *bool {
return &value
}

func OptionalBool() *bool {
return nil
}
10 changes: 10 additions & 0 deletions util_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package dtrack

import (
"errors"
"github.com/stretchr/testify/require"
"testing"

"github.com/google/go-cmp/cmp"
Expand Down Expand Up @@ -103,3 +104,12 @@ func TestForEach_HandlerFuncErr(t *testing.T) {
t.Errorf("expected error from handlerFunc but got nil")
}
}

func TestOptionalBoolOf(t *testing.T) {
require.True(t, *OptionalBoolOf(true))
require.False(t, *OptionalBoolOf(false))
}

func TestOptionalBool(t *testing.T) {
require.Nil(t, OptionalBool())
}

0 comments on commit 8714936

Please sign in to comment.