Skip to content

Commit

Permalink
New XSC analytics metrics capabilities. (#928)
Browse files Browse the repository at this point in the history
  • Loading branch information
gailazar300 authored Apr 3, 2024
1 parent 41100a4 commit 8292671
Show file tree
Hide file tree
Showing 12 changed files with 586 additions and 25 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ jobs:
strategy:
fail-fast: false
matrix:
suite: [ distribution, xray, mpu ]
suite: [ distribution, xray, xsc, mpu ]
os: [ ubuntu, windows, macos ]
runs-on: ${{ matrix.os }}-latest
steps:
Expand All @@ -114,7 +114,7 @@ jobs:
restore-keys: ${{ runner.os }}-go-

- name: ${{ matrix.suite }} tests
run: go test -v github.com/jfrog/jfrog-client-go/tests --timeout 0 --test.${{ matrix.suite }} --rt.url=${{ secrets.PLATFORM_URL }}/artifactory --ds.url=${{ secrets.PLATFORM_URL }}/distribution --xr.url=${{ secrets.PLATFORM_URL }}/xray --access.url=${{ secrets.PLATFORM_URL }}/access --rt.user=${{ secrets.PLATFORM_USER }} --rt.password=${{ secrets.PLATFORM_PASSWORD }} --access.token=${{ secrets.PLATFORM_ADMIN_TOKEN }} --ci.runId=${{ runner.os }}-${{ matrix.suite }}
run: go test -v github.com/jfrog/jfrog-client-go/tests --timeout 0 --test.${{ matrix.suite }} --rt.url=${{ secrets.PLATFORM_URL }}/artifactory --ds.url=${{ secrets.PLATFORM_URL }}/distribution --xr.url=${{ secrets.PLATFORM_URL }}/xray --xsc.url=${{ secrets.PLATFORM_URL }}/xsc --access.url=${{ secrets.PLATFORM_URL }}/access --rt.user=${{ secrets.PLATFORM_USER }} --rt.password=${{ secrets.PLATFORM_PASSWORD }} --access.token=${{ secrets.PLATFORM_ADMIN_TOKEN }} --ci.runId=${{ runner.os }}-${{ matrix.suite }}

JFrog-Client-Go-Pipelines-Tests:
needs: Pretest
Expand Down
98 changes: 88 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,9 +170,17 @@
- [Delete Violations Report](#delete-violations-report)
- [Get Artifact Summary](#get-artifact-summary)
- [Get Entitlement info](#get-entitlement-info)
- [Using XSC Service](#using-xsc-service)
- [Check if xsc is enabled](#check-if-xsc-is-enabled)
- [Send git info details to xsc](#send-git-info-details-to-xsc)
- [XSC APIs](#xsc-apis)
- [Creating XSC Service Manager](#creating-xray-service-manager)
- [Creating XSC Details](#creating-xsc-details)
- [Creating XSC Service Config](#creating-xsc-service-config)
- [Creating New XSC Service Manager](#creating-new-xsc-service-manager)
- [Using XSC Services](#using-xsc-services)
- [Fetching XSC's Version](#fetching-xscs-version)
- [Report XSC analytics metrics](#report-xsc-analytics-metrics)
- [Add analytics general event](#add-analytics-general-event)
- [Update analytics general event](#update-analytics-general-event)
- [Get analytics general event](#get-analytics-general-event)
- [Pipelines APIs](#pipelines-apis)
- [Creating Pipelines Service Manager](#creating-pipelines-service-manager)
- [Creating Pipelines Details](#creating-pipelines-details)
Expand Down Expand Up @@ -265,6 +273,7 @@ content of this repository is deleted.
| `-test.artifactory` | Artifactory tests | Artifactory Pro |
| `-test.distribution` | Distribution tests | Artifactory with Distribution |
| `-test.xray` | Xray tests | Artifactory with Xray |
| `-test.xsc` | Xsc tests | Xray with Xsc |
| `-test.pipelines` | Pipelines tests | JFrog Pipelines |
| `-test.access` | Access tests | Artifactory Pro |
| `-test.repositories` | Repositories tests | Artifactory Pro |
Expand All @@ -277,6 +286,7 @@ content of this repository is deleted.
| `-rt.url` | [Default: http://localhost:8081/artifactory] Artifactory URL. |
| `-ds.url` | [Optional] JFrog Distribution URL. |
| `-xr.url` | [Optional] JFrog Xray URL. |
| `-xsc.url` | [Optional] JFrog Xsc URL. |
| `-pipe.url` | [Optional] JFrog Pipelines URL. |
| `-access.url` | [Optional] JFrog Access URL. |
| `-rt.user` | [Default: admin] Artifactory username. |
Expand Down Expand Up @@ -2233,20 +2243,88 @@ artifactSummary, err := xrayManager.ArtifactSummary(artifactSummaryRequest)
isEntitled, err := xrayManager.IsEntitled(featureId)
```
### Using XSC Service
#### Check if xsc is enabled
## XSC APIs
### Creating XSC Service Manager
#### Creating XSC Details
```go
xscDetails := auth.NewXscDetails()
xscDetails.SetUrl("http://localhost:8081/xsc")
xscDetails.SetSshKeyPath("path/to/.ssh/")
xscDetails.SetApiKey("apikey")
xscDetails.SetUser("user")
xscDetails.SetPassword("password")
xscDetails.SetAccessToken("accesstoken")
// if client certificates are required
xscDetails.SetClientCertPath("path/to/.cer")
xscDetails.SetClientCertKeyPath("path/to/.key")
```
#### Creating XSC Service Config
```go
serviceConfig, err := config.NewConfigBuilder().
SetServiceDetails(xscDetails).
SetCertificatesPath(certPath).
// Optionally overwrite the default HTTP retries, which is set to 3.
SetHttpRetries(8).
Build()
```
#### Creating New XSC Service Manager
```go
// Will try to get XSC version. If route is not available, user is not entitled for XSC.
xscVersion, err := scanService.IsXscEnabled()
xscManager, err := xsc.New(serviceConfig)
```
#### Send git info details to xsc
### Using XSC Services
#### Fetching XSC's Version
```go
version, err := xscManager.GetVersion()
```
#### Report XSC analytics metrics
##### Add analytics general event
Sent XSC a new event which contains analytics data, and get multi-scan id back from XSC.
```go
event := services.XscAnalyticsGeneralEvent{
XscAnalyticsBasicGeneralEvent: services.XscAnalyticsBasicGeneralEvent{
EventType: services.CliEventType,
Product: services.CliProduct,
ProductVersion: "2.53.1",
IsDefaultConfig: false,
JfrogUser: "gail",
OsPlatform: "mac",
OsArchitecture: "arm64",
AnalyzerManagerVersion: "1.1.1",
EventStatus: services.Started,
}}
msi, err := xscManager.AddAnalyticsGeneralEvent(event)
```
##### Update analytics general event
Sent XSC a finalized analytics metrics event with information matching an existing event's msi.
```go
finalizeEvent := services.XscAnalyticsGeneralEventFinalize{
MultiScanId: msi,
XscAnalyticsBasicGeneralEvent: services.XscAnalyticsBasicGeneralEvent{
EventStatus: services.Completed,
TotalFindings: 10,
TotalIgnoredFindings: 5,
TotalScanDuration: "15s",
},
}
err := xscManager.UpdateAnalyticsGeneralEvent(finalizeEvent)
```
##### Get analytics general event
Get a general event from XSC matching the provided msi.
```go
// Details are the git info details (gitRepoUrl, branchName, commitHash are required fields). Returns multi scan id.
multiScanId, err := scanService.SendScanGitInfoContext(details)
event, err := xscManager.GetAnalyticsGeneralEvent(msi)
```
## Pipelines APIs
Expand Down
12 changes: 12 additions & 0 deletions tests/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,23 @@ import (
"github.com/jfrog/jfrog-client-go/utils/log"
xrayAuth "github.com/jfrog/jfrog-client-go/xray/auth"
xrayServices "github.com/jfrog/jfrog-client-go/xray/services"
xscAuth "github.com/jfrog/jfrog-client-go/xsc/auth"
"github.com/stretchr/testify/assert"
)

var (
TestArtifactory *bool
TestDistribution *bool
TestXray *bool
TestXsc *bool
TestPipelines *bool
TestAccess *bool
TestRepositories *bool
TestMultipartUpload *bool
RtUrl *string
DistUrl *string
XrayUrl *string
XscUrl *string
PipelinesUrl *string
RtUser *string
RtPassword *string
Expand Down Expand Up @@ -145,13 +148,15 @@ func init() {
TestArtifactory = flag.Bool("test.artifactory", false, "Test Artifactory")
TestDistribution = flag.Bool("test.distribution", false, "Test distribution")
TestXray = flag.Bool("test.xray", false, "Test xray")
TestXsc = flag.Bool("test.xsc", false, "Test xsc")
TestPipelines = flag.Bool("test.pipelines", false, "Test pipelines")
TestAccess = flag.Bool("test.access", false, "Test access")
TestRepositories = flag.Bool("test.repositories", false, "Test repositories in Artifactory")
TestMultipartUpload = flag.Bool("test.mpu", false, "Test Artifactory multipart upload")
RtUrl = flag.String("rt.url", "http://localhost:8081/artifactory", "Artifactory url")
DistUrl = flag.String("ds.url", "", "Distribution url")
XrayUrl = flag.String("xr.url", "", "Xray url")
XscUrl = flag.String("xsc.url", "", "Xsc url")
PipelinesUrl = flag.String("pipe.url", "", "Pipelines url")
AccessUrl = flag.String("access.url", "http://localhost:8081/access", "Access url")
RtUser = flag.String("rt.user", "admin", "Artifactory username")
Expand Down Expand Up @@ -563,6 +568,13 @@ func GetXrayDetails() auth.ServiceDetails {
return xrayDetails
}

func GetXscDetails() auth.ServiceDetails {
xscDetails := xscAuth.NewXscDetails()
xscDetails.SetUrl(clientutils.AddTrailingSlashIfNeeded(*XscUrl))
setAuthenticationDetail(xscDetails)
return xscDetails
}

func GetPipelinesDetails() auth.ServiceDetails {
pDetails := pipelinesAuth.NewPipelinesDetails()
pDetails.SetUrl(clientutils.AddTrailingSlashIfNeeded(*PipelinesUrl))
Expand Down
36 changes: 36 additions & 0 deletions tests/xsc_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package tests

import (
clientUtils "github.com/jfrog/jfrog-client-go/utils"
"testing"
)

func TestXscVersion(t *testing.T) {
initXscTest(t, "")
version, err := GetXscDetails().GetVersion()
if err != nil {
t.Error(err)
}
if version == "" {
t.Error("Expected a version, got empty string")
}
}

func initXscTest(t *testing.T, minVersion string) {
if !*TestXsc {
t.Skip("Skipping xsc test. To run xsc test add the '-test.xsc=true' option.")
}
validateXscVersion(t, minVersion)
}
func validateXscVersion(t *testing.T, minVersion string) {
// Validate active XSC server.
version, err := GetXscDetails().GetVersion()
if err != nil {
t.Skip(err)
}
// Validate minimum XSC version.
err = clientUtils.ValidateMinimumVersion(clientUtils.Xsc, version, minVersion)
if err != nil {
t.Skip(err)
}
}
79 changes: 79 additions & 0 deletions tests/xscanalyticsevent_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package tests

import (
"github.com/jfrog/jfrog-client-go/auth"
"github.com/jfrog/jfrog-client-go/http/jfroghttpclient"
"github.com/jfrog/jfrog-client-go/xsc/services"
"github.com/stretchr/testify/assert"
"regexp"
"testing"
)

var testsEventService *services.AnalyticsEventService

func TestXscAddAndUpdateGeneralEvent(t *testing.T) {
xscDetails, client := initXscEventTest(t)
testsEventService = services.NewAnalyticsEventService(client)
testsEventService.XscDetails = xscDetails

event := services.XscAnalyticsGeneralEvent{XscAnalyticsBasicGeneralEvent: services.XscAnalyticsBasicGeneralEvent{
EventType: services.CliEventType,
EventStatus: services.Started,
Product: services.CliProduct,
ProductVersion: "2.53.1",
IsDefaultConfig: false,
JfrogUser: "gail",
OsPlatform: "mac",
OsArchitecture: "arm64",
MachineId: "id",
AnalyzerManagerVersion: "1.1.1",
}}
msi, err := testsEventService.AddGeneralEvent(event)
assert.NoError(t, err)
assert.True(t, isValidUUID(msi))

// Validate that the event sent and saved properly in XSC.
resp, err := testsEventService.GetGeneralEvent(msi)
assert.NoError(t, err)
assert.Equal(t, event, *resp)

finalizeEvent := services.XscAnalyticsGeneralEventFinalize{
MultiScanId: msi,
XscAnalyticsBasicGeneralEvent: services.XscAnalyticsBasicGeneralEvent{
EventStatus: services.Completed,
TotalFindings: 10,
TotalIgnoredFindings: 5,
TotalScanDuration: "15s",
},
}

err = testsEventService.UpdateGeneralEvent(finalizeEvent)
assert.NoError(t, err)

// Validate that the event's update sent and saved properly in XSC.
resp, err = testsEventService.GetGeneralEvent(msi)
assert.NoError(t, err)
event.EventStatus = services.Completed
event.TotalFindings = 10
event.TotalIgnoredFindings = 5
event.TotalScanDuration = "15s"
assert.Equal(t, event, *resp)
}

func isValidUUID(str string) bool {
uuidRegex := regexp.MustCompile(`^[0-9a-f]{8}-[0-9a-f]{4}-1[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$`)
return uuidRegex.MatchString(str)
}

func initXscEventTest(t *testing.T) (xscDetails auth.ServiceDetails, client *jfroghttpclient.JfrogHttpClient) {
var err error
initXscTest(t, services.AnalyticsMetricsMinXscVersion)
xscDetails = GetXscDetails()
client, err = jfroghttpclient.JfrogClientBuilder().
SetClientCertPath(xscDetails.GetClientCertPath()).
SetClientCertKeyPath(xscDetails.GetClientCertKeyPath()).
AppendPreRequestInterceptor(xscDetails.RunPreRequestFunctions).
Build()
assert.NoError(t, err)
return
}
16 changes: 16 additions & 0 deletions utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type MinVersionProduct string
const (
Artifactory MinVersionProduct = "JFrog Artifactory"
Xray MinVersionProduct = "JFrog Xray"
Xsc MinVersionProduct = "JFrog Xsc"
DataTransfer MinVersionProduct = "Data Transfer"
DockerApi MinVersionProduct = "Docker API"
Projects MinVersionProduct = "JFrog Projects"
Expand Down Expand Up @@ -601,3 +602,18 @@ func ExtractSha256FromResponseBody(body []byte) (string, error) {
func Pointer[K any](val K) *K {
return &val
}

func SetEnvWithResetCallback(key, value string) (func() error, error) {
oldValue, exist := os.LookupEnv(key)
if err := os.Setenv(key, value); err != nil {
return func() error { return nil }, errorutils.CheckError(err)
}
if exist {
return func() error {
return errorutils.CheckError(os.Setenv(key, oldValue))
}, nil
}
return func() error {
return errorutils.CheckError(os.Unsetenv(key))
}, nil
}
Loading

0 comments on commit 8292671

Please sign in to comment.