Skip to content

Commit

Permalink
Adding Metadata Service Manager (jfrog#997)
Browse files Browse the repository at this point in the history
  • Loading branch information
osaidwtd authored Aug 11, 2024
1 parent 01bb7dc commit ab97155
Show file tree
Hide file tree
Showing 6 changed files with 234 additions and 0 deletions.
52 changes: 52 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,13 @@
- [Creating New Evidence Service Manager](#creating-new-evidence-service-manager)
- [Using Evidence Services](#using-evidence-services)
- [Upload Evidence](#upload-evidence)
- [Metadata APIs](#metadata-apis)
- [Creating Metadata Service Manager](#creating-metadata-service-manager)
- [Creating Metadata Details](#creating-metadata-details)
- [Creating Metadata Service Config](#creating-metadata-service-config)
- [Creating New Metadata Service Manager](#creating-new-metadata-service-manager)
- [Using Metadata Services](#using-metadata-services)
- [Graphql query](#graphql-query)

## General

Expand Down Expand Up @@ -2964,3 +2971,48 @@ evidenceDetails := evidenceService.EvidenceDetails{
}
body, err = evideceManager.UploadEvidence(evidenceDetails)
```
## Metadata APIs
### Creating Metadata Service Manager
#### Creating Metadata Details
```go
mdDetails := auth.NewMetadataDetails()
mdDetails.SetUrl("http://localhost:8081/metadata")
mdDetails.SetAccessToken("access-token")
// if client certificates are required
mdDetails.SetClientCertPath("path/to/.cer")
mdDetails.SetClientCertKeyPath("path/to/.key")
```
#### Creating Metadata Service Config
```go
serviceConfig, err := config.NewConfigBuilder().
SetServiceDetails(mdDetails).
SetCertificatesPath(mdDetails.GetClientCertPath()).
// Optionally overwrite the default HTTP retries, which is set to 3.
SetHttpRetries(3).
Build()
```
#### Creating New Metadata Service Manager
```go
metadataManager, err := metadata.NewManager(serviceConfig)
```
### Using Metadata Services
#### Graphql query
```go
queryBytes := []byte(`{"query":"someGraphqlQuery"}`)

queryDetails := metadataService.QueryDetails{
Body: queryBytes,
}

body, err = metadataManager.GraphqlQuery(queryDetails)
```
17 changes: 17 additions & 0 deletions metadata/auth/metadatadetails.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package auth

import (
"github.com/jfrog/jfrog-client-go/auth"
)

type metadataDetails struct {
auth.CommonConfigFields
}

func NewMetadataDetails() auth.ServiceDetails {
return &metadataDetails{}
}

func (rt *metadataDetails) GetVersion() (string, error) {
panic("Failed: Method is not implemented")
}
45 changes: 45 additions & 0 deletions metadata/manager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package metadata

import (
"github.com/jfrog/jfrog-client-go/config"
"github.com/jfrog/jfrog-client-go/http/jfroghttpclient"
"github.com/jfrog/jfrog-client-go/metadata/services"
)

type Manager interface {
GraphqlQuery(query []byte) ([]byte, error)
}

type metadataManager struct {
client *jfroghttpclient.JfrogHttpClient
config config.Config
}

func NewManager(config config.Config) (Manager, error) {
details := config.GetServiceDetails()
var err error
manager := &metadataManager{config: config}
manager.client, err = jfroghttpclient.JfrogClientBuilder().
SetCertificatesPath(config.GetCertificatesPath()).
SetInsecureTls(config.IsInsecureTls()).
SetClientCertPath(details.GetClientCertPath()).
SetClientCertKeyPath(details.GetClientCertKeyPath()).
AppendPreRequestInterceptor(details.RunPreRequestFunctions).
SetContext(config.GetContext()).
SetDialTimeout(config.GetDialTimeout()).
SetOverallRequestTimeout(config.GetOverallRequestTimeout()).
SetRetries(config.GetHttpRetries()).
SetRetryWaitMilliSecs(config.GetHttpRetryWaitMilliSecs()).
Build()

return manager, err
}

func (mm *metadataManager) Client() *jfroghttpclient.JfrogHttpClient {
return mm.client
}

func (mm *metadataManager) GraphqlQuery(query []byte) ([]byte, error) {
metadataService := services.NewMetadataService(mm.config.GetServiceDetails(), mm.client)
return metadataService.Query(query)
}
45 changes: 45 additions & 0 deletions metadata/services/graphql.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package services

import (
"fmt"
rtUtils "github.com/jfrog/jfrog-client-go/artifactory/services/utils"
"github.com/jfrog/jfrog-client-go/auth"
"github.com/jfrog/jfrog-client-go/http/jfroghttpclient"
"github.com/jfrog/jfrog-client-go/utils/errorutils"
"net/http"
"net/url"
)

const queryUrl = "api/v1/query"

type Service interface {
Query(query []byte) ([]byte, error)
}

type metadataService struct {
client *jfroghttpclient.JfrogHttpClient
serviceDetails *auth.ServiceDetails
}

func NewMetadataService(serviceDetails auth.ServiceDetails, client *jfroghttpclient.JfrogHttpClient) Service {
return &metadataService{serviceDetails: &serviceDetails, client: client}
}

func (m *metadataService) GetMetadataDetails() auth.ServiceDetails {
return *m.serviceDetails
}

func (m *metadataService) Query(query []byte) ([]byte, error) {
graphqlUrl, err := url.Parse(m.GetMetadataDetails().GetUrl() + queryUrl)
if err != nil {
return nil, fmt.Errorf("failed to parse URL: %w", err)
}
httpClientDetails := m.GetMetadataDetails().CreateHttpClientDetails()
rtUtils.SetContentType("application/json", &httpClientDetails.Headers)

resp, body, err := m.client.SendPost(graphqlUrl.String(), query, &httpClientDetails)
if err != nil {
return []byte{}, err
}
return body, errorutils.CheckResponseStatusWithBody(resp, body, http.StatusOK)
}
55 changes: 55 additions & 0 deletions metadata/services/graphql_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package services

import (
"encoding/json"
"github.com/jfrog/jfrog-client-go/artifactory/auth"
"github.com/jfrog/jfrog-client-go/http/jfroghttpclient"
"github.com/stretchr/testify/assert"
"net/http"
"net/http/httptest"
"testing"
)

const queryData = `{"query":"someGraphqlQuery"}`

func TestMetadataService_Query(t *testing.T) {
handlerFunc, requestNum := createMetadataHandlerFunc(t)

mockServer, metadataService := createMockMetadataServer(t, handlerFunc)
defer mockServer.Close()

_, err := metadataService.Query([]byte(queryData))
assert.NoError(t, err)
assert.Equal(t, 1, *requestNum)
}

func createMockMetadataServer(t *testing.T, testHandler http.HandlerFunc) (*httptest.Server, *metadataService) {
testServer := httptest.NewServer(testHandler)

serviceDetails := auth.NewArtifactoryDetails()
serviceDetails.SetUrl(testServer.URL + "/")

client, err := jfroghttpclient.JfrogClientBuilder().Build()
assert.NoError(t, err)
return testServer, &metadataService{serviceDetails: &serviceDetails, client: client}
}

func createMetadataHandlerFunc(t *testing.T) (http.HandlerFunc, *int) {
requestNum := 0
return func(w http.ResponseWriter, r *http.Request) {
if r.RequestURI == "/api/v1/query" {
assert.Equal(t, "application/json", r.Header.Get("Content-Type"))

w.WriteHeader(http.StatusOK)
requestNum++
writeMockMetadataResponse(t, w, []byte(queryData))
}
}, &requestNum
}

func writeMockMetadataResponse(t *testing.T, w http.ResponseWriter, payload []byte) {
content, err := json.Marshal(payload)
assert.NoError(t, err)
_, err = w.Write(content)
assert.NoError(t, err)
}
20 changes: 20 additions & 0 deletions tests/timeout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package tests
import (
"github.com/jfrog/jfrog-client-go/evidence"
"github.com/jfrog/jfrog-client-go/evidence/services"
"github.com/jfrog/jfrog-client-go/metadata"
"net/http"
"net/http/httptest"
"testing"
Expand All @@ -23,6 +24,7 @@ import (
evidenceAuth "github.com/jfrog/jfrog-client-go/evidence/auth"
lifecycleAuth "github.com/jfrog/jfrog-client-go/lifecycle/auth"
lifecycleServices "github.com/jfrog/jfrog-client-go/lifecycle/services"
metadataAuth "github.com/jfrog/jfrog-client-go/metadata/auth"
pipelinesAuth "github.com/jfrog/jfrog-client-go/pipelines/auth"
"github.com/jfrog/jfrog-client-go/utils/log"
"github.com/jfrog/jfrog-client-go/utils/tests"
Expand All @@ -48,6 +50,7 @@ func TestTimeout(t *testing.T) {
t.Run("testPipelinesTimeout", testPipelinesTimeout)
t.Run("testXrayTimeout", testXrayTimeout)
t.Run("testEvidenceTimeout", testEvidenceTimeout)
t.Run("testMetadataTimeout", testMetadataTimeout)
}

func testAccessTimeout(t *testing.T) {
Expand Down Expand Up @@ -136,6 +139,23 @@ func testEvidenceTimeout(t *testing.T) {
assert.ErrorContains(t, err, "context deadline exceeded")
}

func testMetadataTimeout(t *testing.T) {
// Create mock server
url, cleanup := createSleepyRequestServer()
defer cleanup()

// Create services manager configuring to work with the mock server
details := metadataAuth.NewMetadataDetails()
details.SetUrl(url)
servicesManager, err := metadata.NewManager(createServiceConfigWithTimeout(t, details))
assert.NoError(t, err)

query := []byte("query body")
// Expect timeout
_, err = servicesManager.GraphqlQuery(query)
assert.ErrorContains(t, err, "context deadline exceeded")
}

func testPipelinesTimeout(t *testing.T) {
// Create mock server
url, cleanup := createSleepyRequestServer()
Expand Down

0 comments on commit ab97155

Please sign in to comment.