Skip to content

Commit 185f7a8

Browse files
committed
Merge remote-tracking branch 'upstream/dev'
2 parents b4a5421 + b502034 commit 185f7a8

File tree

13 files changed

+407
-15
lines changed

13 files changed

+407
-15
lines changed

README.md

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,13 @@
257257
- [Creating New Metadata Service Manager](#creating-new-metadata-service-manager)
258258
- [Using Metadata Services](#using-metadata-services)
259259
- [Graphql query](#graphql-query)
260+
- [Onemodel APIs](#onemodel-apis)
261+
- [Creating Onemodel Service Manager](#creating-onemodel-service-manager)
262+
- [Creating Onemodel Details](#creating-onemodel-details)
263+
- [Creating Onemodel Service Config](#creating-onemodel-service-config)
264+
- [Creating New Onemodel Service Manager](#creating-new-onemodel-service-manager)
265+
- [Using Onemodel Services](#using-onemodel-services)
266+
- [Graphql query](#graphql-query)
260267

261268
## General
262269

@@ -3134,4 +3141,49 @@ queryDetails := metadataService.QueryDetails{
31343141
}
31353142

31363143
body, err = metadataManager.GraphqlQuery(queryDetails)
3144+
```
3145+
## Onemodel APIs
3146+
3147+
### Creating Onemodel Service Manager
3148+
3149+
#### Creating Onemodel Details
3150+
3151+
```go
3152+
omDetails := auth.NewOnemodelDetails()
3153+
omDetails.SetUrl("http://localhost:8081/onemodel")
3154+
omDetails.SetAccessToken("access-token")
3155+
// if client certificates are required
3156+
omDetails.SetClientCertPath("path/to/.cer")
3157+
omDetails.SetClientCertKeyPath("path/to/.key")
3158+
```
3159+
3160+
#### Creating Onemodel Service Config
3161+
3162+
```go
3163+
serviceConfig, err := config.NewConfigBuilder().
3164+
SetServiceDetails(omDetails).
3165+
SetCertificatesPath(omDetails.GetClientCertPath()).
3166+
// Optionally overwrite the default HTTP retries, which is set to 3.
3167+
SetHttpRetries(3).
3168+
Build()
3169+
```
3170+
3171+
#### Creating New Onemodel Service Manager
3172+
3173+
```go
3174+
onemodelManager, err := onemodel.NewManager(serviceConfig)
3175+
```
3176+
3177+
### Using Onemodel Services
3178+
3179+
#### Graphql query
3180+
3181+
```go
3182+
queryBytes := []byte(`{"query":"someGraphqlQuery"}`)
3183+
3184+
queryDetails := onemodelService.QueryDetails{
3185+
Body: queryBytes,
3186+
}
3187+
3188+
body, err = onemodelManager.GraphqlQuery(queryDetails)
31373189
```

access/services/accesstoken.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ type CreateOidcTokenParams struct {
4343
Repo string `json:"repo,omitempty"`
4444
ApplicationKey string `json:"application_key,omitempty"`
4545
Audience string `json:"audience,omitempty"`
46+
ProviderType string `json:"provider_type,omitempty"`
4647
IdentityMappingName string `json:"identity_mapping_name,omitempty"`
4748
IncludeReferenceToken *bool `json:"include_reference_token,omitempty"`
4849
}

artifactory/services/promote.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"github.com/jfrog/jfrog-client-go/artifactory/services/utils"
99
"github.com/jfrog/jfrog-client-go/auth"
1010
"github.com/jfrog/jfrog-client-go/http/jfroghttpclient"
11-
clientutils "github.com/jfrog/jfrog-client-go/utils"
1211
"github.com/jfrog/jfrog-client-go/utils/errorutils"
1312
"github.com/jfrog/jfrog-client-go/utils/log"
1413
)
@@ -35,17 +34,21 @@ func (ps *PromoteService) BuildPromote(promotionParams PromotionParams) error {
3534
log.Info(message)
3635

3736
promoteUrl := ps.ArtDetails.GetUrl()
38-
restApi := path.Join("api/build/promote/", promotionParams.GetBuildName(), promotionParams.GetBuildNumber())
37+
restApi := path.Join("api/build/promote/")
3938

4039
queryParams := make(map[string]string)
4140
if promotionParams.ProjectKey != "" {
4241
queryParams["project"] = promotionParams.ProjectKey
4342
}
4443

45-
requestFullUrl, err := clientutils.BuildUrl(promoteUrl, restApi, queryParams)
44+
buildName := promotionParams.GetBuildName()
45+
buildNumber := promotionParams.GetBuildNumber()
46+
47+
requestURLWithEscapedSlash, err := utils.BuildUrlWithEscapingSlash(promoteUrl, restApi, buildName, buildNumber, queryParams)
4648
if err != nil {
4749
return err
4850
}
51+
4952
props, err := utils.ParseProperties(promotionParams.GetProperties())
5053
if err != nil {
5154
return err
@@ -69,11 +72,11 @@ func (ps *PromoteService) BuildPromote(promotionParams PromotionParams) error {
6972
httpClientsDetails := ps.ArtDetails.CreateHttpClientDetails()
7073
utils.SetContentType("application/vnd.org.jfrog.artifactory.build.PromotionRequest+json", &httpClientsDetails.Headers)
7174

72-
resp, body, err := ps.client.SendPost(requestFullUrl, requestContent, &httpClientsDetails)
75+
resp, body, err := ps.client.SendPost(requestURLWithEscapedSlash, requestContent, &httpClientsDetails)
7376
if err != nil {
7477
return err
7578
}
76-
79+
7780
if err = errorutils.CheckResponseStatusWithBody(resp, body, http.StatusOK); err != nil {
7881
return err
7982
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package utils
2+
3+
import (
4+
"net/url"
5+
"path"
6+
"strings"
7+
8+
"github.com/jfrog/jfrog-client-go/utils/errorutils"
9+
)
10+
11+
func BuildUrlWithEscapingSlash(baseUrl, restApi, buildName, buildNumber string, queryParams map[string]string) (string, error) {
12+
u := url.URL{Path: restApi}
13+
parsedUrl, err := url.Parse(baseUrl + u.String())
14+
if err = errorutils.CheckError(err); err != nil {
15+
return "", err
16+
}
17+
q := parsedUrl.Query()
18+
for k, v := range queryParams {
19+
q.Set(k, v)
20+
}
21+
parsedUrl.RawQuery = q.Encode()
22+
23+
// Semicolons are reserved as separators in some Artifactory APIs, so they'd better be encoded when used for other purposes
24+
encodedUrl := strings.ReplaceAll(parsedUrl.String(), ";", url.QueryEscape(";"))
25+
26+
escapedBuildPath := path.Join(url.QueryEscape(buildName), url.QueryEscape(buildNumber))
27+
urlParts := strings.Split(encodedUrl, "?")
28+
resultUrl := urlParts[0] + "/" + escapedBuildPath
29+
if len(urlParts) > 1 && urlParts[1] != "" {
30+
resultUrl += "?" + urlParts[1]
31+
}
32+
33+
return resultUrl, nil
34+
}

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ require (
1010
github.com/golang-jwt/jwt/v4 v4.5.2
1111
github.com/gookit/color v1.5.4
1212
github.com/jfrog/archiver/v3 v3.6.1
13-
github.com/jfrog/build-info-go v1.10.12
13+
github.com/jfrog/build-info-go v1.10.13
1414
github.com/jfrog/gofrog v1.7.6
1515
github.com/minio/sha256-simd v1.0.1
1616
github.com/stretchr/testify v1.10.0
@@ -25,7 +25,7 @@ require (
2525
github.com/CycloneDX/cyclonedx-go v0.9.2 // indirect
2626
github.com/Microsoft/go-winio v0.6.2 // indirect
2727
github.com/andybalholm/brotli v1.1.1 // indirect
28-
github.com/cloudflare/circl v1.6.0 // indirect
28+
github.com/cloudflare/circl v1.6.1 // indirect
2929
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
3030
github.com/davecgh/go-spew v1.1.1 // indirect
3131
github.com/dsnet/compress v0.0.1 // indirect

go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oM
1717
github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
1818
github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs=
1919
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
20-
github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk=
21-
github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
20+
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
21+
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
2222
github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s=
2323
github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
2424
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -57,8 +57,8 @@ github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOl
5757
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
5858
github.com/jfrog/archiver/v3 v3.6.1 h1:LOxnkw9pOn45DzCbZNFV6K0+6dCsQ0L8mR3ZcujO5eI=
5959
github.com/jfrog/archiver/v3 v3.6.1/go.mod h1:VgR+3WZS4N+i9FaDwLZbq+jeU4B4zctXL+gL4EMzfLw=
60-
github.com/jfrog/build-info-go v1.10.12 h1:KO/YUeKYtDrnpcmsXmwqr6akjzrwA0hSTUB+Op/HF88=
61-
github.com/jfrog/build-info-go v1.10.12/go.mod h1:JcISnovFXKx3wWf3p1fcMmlPdt6adxScXvoJN4WXqIE=
60+
github.com/jfrog/build-info-go v1.10.13 h1:gWx4e99aRGb3VdMQ9DIE0MN7Orevkif6WtBGfN6uVNg=
61+
github.com/jfrog/build-info-go v1.10.13/go.mod h1:JcISnovFXKx3wWf3p1fcMmlPdt6adxScXvoJN4WXqIE=
6262
github.com/jfrog/gofrog v1.7.6 h1:QmfAiRzVyaI7JYGsB7cxfAJePAZTzFz0gRWZSE27c6s=
6363
github.com/jfrog/gofrog v1.7.6/go.mod h1:ntr1txqNOZtHplmaNd7rS4f8jpA5Apx8em70oYEe7+4=
6464
github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4=

onemodel/auth/onemodeldetails.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package auth
2+
3+
import (
4+
"github.com/jfrog/jfrog-client-go/auth"
5+
)
6+
7+
type onemodelDetails struct {
8+
auth.CommonConfigFields
9+
}
10+
11+
func NewOnemodelDetails() auth.ServiceDetails {
12+
return &onemodelDetails{}
13+
}
14+
15+
func (rt *onemodelDetails) GetVersion() (string, error) {
16+
panic("Failed: Method is not implemented")
17+
}

onemodel/manager.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package onemodel
2+
3+
import (
4+
"github.com/jfrog/jfrog-client-go/config"
5+
"github.com/jfrog/jfrog-client-go/http/jfroghttpclient"
6+
"github.com/jfrog/jfrog-client-go/onemodel/services"
7+
)
8+
9+
type Manager interface {
10+
GraphqlQuery(query []byte) ([]byte, error)
11+
}
12+
13+
type onemodelManager struct {
14+
client *jfroghttpclient.JfrogHttpClient
15+
config config.Config
16+
}
17+
18+
func NewManager(config config.Config) (Manager, error) {
19+
details := config.GetServiceDetails()
20+
var err error
21+
manager := &onemodelManager{config: config}
22+
manager.client, err = jfroghttpclient.JfrogClientBuilder().
23+
SetCertificatesPath(config.GetCertificatesPath()).
24+
SetInsecureTls(config.IsInsecureTls()).
25+
SetClientCertPath(details.GetClientCertPath()).
26+
SetClientCertKeyPath(details.GetClientCertKeyPath()).
27+
AppendPreRequestInterceptor(details.RunPreRequestFunctions).
28+
SetContext(config.GetContext()).
29+
SetDialTimeout(config.GetDialTimeout()).
30+
SetOverallRequestTimeout(config.GetOverallRequestTimeout()).
31+
SetRetries(config.GetHttpRetries()).
32+
SetRetryWaitMilliSecs(config.GetHttpRetryWaitMilliSecs()).
33+
Build()
34+
35+
return manager, err
36+
}
37+
38+
func (omm *onemodelManager) Client() *jfroghttpclient.JfrogHttpClient {
39+
return omm.client
40+
}
41+
42+
func (omm *onemodelManager) GraphqlQuery(query []byte) ([]byte, error) {
43+
onemodelService := services.NewOnemodelService(omm.config.GetServiceDetails(), omm.client)
44+
return onemodelService.Query(query)
45+
}

onemodel/services/graphql.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package services
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"net/url"
7+
8+
rtUtils "github.com/jfrog/jfrog-client-go/artifactory/services/utils"
9+
"github.com/jfrog/jfrog-client-go/auth"
10+
"github.com/jfrog/jfrog-client-go/http/jfroghttpclient"
11+
"github.com/jfrog/jfrog-client-go/utils/errorutils"
12+
)
13+
14+
const queryUrl = "api/v1/graphql"
15+
16+
type Service interface {
17+
Query(query []byte) ([]byte, error)
18+
}
19+
20+
type onemodelService struct {
21+
client *jfroghttpclient.JfrogHttpClient
22+
serviceDetails *auth.ServiceDetails
23+
}
24+
25+
func NewOnemodelService(serviceDetails auth.ServiceDetails, client *jfroghttpclient.JfrogHttpClient) Service {
26+
return &onemodelService{serviceDetails: &serviceDetails, client: client}
27+
}
28+
29+
func (m *onemodelService) GetOnemodelDetails() auth.ServiceDetails {
30+
return *m.serviceDetails
31+
}
32+
33+
func (m *onemodelService) Query(query []byte) ([]byte, error) {
34+
graphqlUrl, err := url.Parse(m.GetOnemodelDetails().GetUrl() + queryUrl)
35+
if err != nil {
36+
return nil, fmt.Errorf("failed to parse URL: %w", err)
37+
}
38+
httpClientDetails := m.GetOnemodelDetails().CreateHttpClientDetails()
39+
rtUtils.SetContentType("application/json", &httpClientDetails.Headers)
40+
41+
resp, body, err := m.client.SendPost(graphqlUrl.String(), query, &httpClientDetails)
42+
if err != nil {
43+
return []byte{}, err
44+
}
45+
return body, errorutils.CheckResponseStatusWithBody(resp, body, http.StatusOK)
46+
}

onemodel/services/graphql_test.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package services
2+
3+
import (
4+
"encoding/json"
5+
"net/http"
6+
"net/http/httptest"
7+
"testing"
8+
9+
"github.com/jfrog/jfrog-client-go/artifactory/auth"
10+
"github.com/jfrog/jfrog-client-go/http/jfroghttpclient"
11+
"github.com/stretchr/testify/assert"
12+
)
13+
14+
const queryData = `{"query":"someGraphqlQuery"}`
15+
16+
func TestOnemodelService_Query(t *testing.T) {
17+
handlerFunc, requestNum := createOnemodelHandlerFunc(t)
18+
19+
mockServer, onemodelService := createMockonemodelServer(t, handlerFunc)
20+
defer mockServer.Close()
21+
22+
_, err := onemodelService.Query([]byte(queryData))
23+
assert.NoError(t, err)
24+
assert.Equal(t, 1, *requestNum)
25+
}
26+
27+
func createMockonemodelServer(t *testing.T, testHandler http.HandlerFunc) (*httptest.Server, *onemodelService) {
28+
testServer := httptest.NewServer(testHandler)
29+
30+
serviceDetails := auth.NewArtifactoryDetails()
31+
serviceDetails.SetUrl(testServer.URL + "/")
32+
33+
client, err := jfroghttpclient.JfrogClientBuilder().Build()
34+
assert.NoError(t, err)
35+
return testServer, &onemodelService{serviceDetails: &serviceDetails, client: client}
36+
}
37+
38+
func createOnemodelHandlerFunc(t *testing.T) (http.HandlerFunc, *int) {
39+
requestNum := 0
40+
return func(w http.ResponseWriter, r *http.Request) {
41+
if r.RequestURI == "/api/v1/graphql" {
42+
assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
43+
44+
w.WriteHeader(http.StatusOK)
45+
requestNum++
46+
writeMockonemodelResponse(t, w, []byte(queryData))
47+
}
48+
}, &requestNum
49+
}
50+
51+
func writeMockonemodelResponse(t *testing.T, w http.ResponseWriter, payload []byte) {
52+
content, err := json.Marshal(payload)
53+
assert.NoError(t, err)
54+
_, err = w.Write(content)
55+
assert.NoError(t, err)
56+
}

0 commit comments

Comments
 (0)