mirror of
https://github.com/hanzoai/deploy.git
synced 2026-10-07 08:44:50 +00:00
feat: make appset proxy-url param a native flag (#27788)
Signed-off-by: Patroklos Papapetrou <[email protected]>
This commit is contained in:
committed by
GitHub
parent
cf42d9fb5e
commit
e2e43de458
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
@@ -153,7 +152,7 @@ func (g *PullRequestGenerator) selectServiceProvider(ctx context.Context, genera
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Secret token: %w", err)
|
||||
}
|
||||
return pullrequest.NewGitLabService(token, providerConfig.API, providerConfig.Project, providerConfig.Labels, providerConfig.PullRequestState, g.scmRootCAPath, providerConfig.Insecure, caCerts)
|
||||
return pullrequest.NewGitLabService(token, providerConfig.API, providerConfig.Project, providerConfig.Labels, providerConfig.PullRequestState, g.scmRootCAPath, providerConfig.Insecure, caCerts, g.scmProxyURL, g.scmNoProxy)
|
||||
}
|
||||
if generatorConfig.Gitea != nil {
|
||||
providerConfig := generatorConfig.Gitea
|
||||
@@ -162,7 +161,7 @@ func (g *PullRequestGenerator) selectServiceProvider(ctx context.Context, genera
|
||||
return nil, fmt.Errorf("error fetching Secret token: %w", err)
|
||||
}
|
||||
|
||||
return pullrequest.NewGiteaService(token, providerConfig.API, providerConfig.Owner, providerConfig.Repo, providerConfig.Labels, providerConfig.Insecure)
|
||||
return pullrequest.NewGiteaService(token, providerConfig.API, providerConfig.Owner, providerConfig.Repo, providerConfig.Labels, providerConfig.Insecure, g.scmProxyURL, g.scmNoProxy)
|
||||
}
|
||||
if generatorConfig.BitbucketServer != nil {
|
||||
providerConfig := generatorConfig.BitbucketServer
|
||||
@@ -179,15 +178,15 @@ func (g *PullRequestGenerator) selectServiceProvider(ctx context.Context, genera
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Secret Bearer token: %w", err)
|
||||
}
|
||||
return pullrequest.NewBitbucketServiceBearerToken(ctx, appToken, providerConfig.API, providerConfig.Project, providerConfig.Repo, g.scmRootCAPath, providerConfig.Insecure, caCerts)
|
||||
return pullrequest.NewBitbucketServiceBearerToken(ctx, appToken, providerConfig.API, providerConfig.Project, providerConfig.Repo, g.scmRootCAPath, providerConfig.Insecure, caCerts, g.scmProxyURL, g.scmNoProxy)
|
||||
} else if providerConfig.BasicAuth != nil {
|
||||
password, err := utils.GetSecretRef(ctx, g.client, providerConfig.BasicAuth.PasswordRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Secret token: %w", err)
|
||||
}
|
||||
return pullrequest.NewBitbucketServiceBasicAuth(ctx, providerConfig.BasicAuth.Username, password, providerConfig.API, providerConfig.Project, providerConfig.Repo, g.scmRootCAPath, providerConfig.Insecure, caCerts)
|
||||
return pullrequest.NewBitbucketServiceBasicAuth(ctx, providerConfig.BasicAuth.Username, password, providerConfig.API, providerConfig.Project, providerConfig.Repo, g.scmRootCAPath, providerConfig.Insecure, caCerts, g.scmProxyURL, g.scmNoProxy)
|
||||
}
|
||||
return pullrequest.NewBitbucketServiceNoAuth(ctx, providerConfig.API, providerConfig.Project, providerConfig.Repo, g.scmRootCAPath, providerConfig.Insecure, caCerts)
|
||||
return pullrequest.NewBitbucketServiceNoAuth(ctx, providerConfig.API, providerConfig.Project, providerConfig.Repo, g.scmRootCAPath, providerConfig.Insecure, caCerts, g.scmProxyURL, g.scmNoProxy)
|
||||
}
|
||||
if generatorConfig.Bitbucket != nil {
|
||||
providerConfig := generatorConfig.Bitbucket
|
||||
@@ -218,15 +217,13 @@ func (g *PullRequestGenerator) selectServiceProvider(ctx context.Context, genera
|
||||
}
|
||||
|
||||
func (g *PullRequestGenerator) github(ctx context.Context, cfg *argoprojiov1alpha1.PullRequestGeneratorGithub, applicationSetInfo *argoprojiov1alpha1.ApplicationSet) (pullrequest.PullRequestService, error) {
|
||||
var metricsCtx *services.MetricsContext
|
||||
var httpClient *http.Client
|
||||
|
||||
httpClient := g.newSCMHTTPClient()
|
||||
if g.enableGitHubAPIMetrics {
|
||||
metricsCtx = &services.MetricsContext{
|
||||
metricsCtx := &services.MetricsContext{
|
||||
AppSetNamespace: applicationSetInfo.Namespace,
|
||||
AppSetName: applicationSetInfo.Name,
|
||||
}
|
||||
httpClient = services.NewGitHubMetricsClient(metricsCtx)
|
||||
httpClient = services.NewGitHubMetricsClientFrom(httpClient, metricsCtx)
|
||||
}
|
||||
|
||||
// use an app if it was configured
|
||||
@@ -235,11 +232,7 @@ func (g *PullRequestGenerator) github(ctx context.Context, cfg *argoprojiov1alph
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error getting GitHub App secret: %w", err)
|
||||
}
|
||||
|
||||
if g.enableGitHubAPIMetrics {
|
||||
return pullrequest.NewGithubAppService(ctx, *auth, cfg.API, cfg.Owner, cfg.Repo, cfg.Labels, httpClient)
|
||||
}
|
||||
return pullrequest.NewGithubAppService(ctx, *auth, cfg.API, cfg.Owner, cfg.Repo, cfg.Labels)
|
||||
return pullrequest.NewGithubAppService(ctx, *auth, cfg.API, cfg.Owner, cfg.Repo, cfg.Labels, httpClient)
|
||||
}
|
||||
|
||||
// always default to token, even if not set (public access)
|
||||
@@ -247,9 +240,5 @@ func (g *PullRequestGenerator) github(ctx context.Context, cfg *argoprojiov1alph
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Secret token: %w", err)
|
||||
}
|
||||
|
||||
if g.enableGitHubAPIMetrics {
|
||||
return pullrequest.NewGithubService(token, cfg.API, cfg.Owner, cfg.Repo, cfg.Labels, httpClient)
|
||||
}
|
||||
return pullrequest.NewGithubService(token, cfg.API, cfg.Owner, cfg.Repo, cfg.Labels)
|
||||
return pullrequest.NewGithubService(token, cfg.API, cfg.Owner, cfg.Repo, cfg.Labels, httpClient)
|
||||
}
|
||||
|
||||
@@ -11,6 +11,8 @@ import (
|
||||
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/argoproj/argo-cd/v3/util/proxy"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/argoproj/argo-cd/v3/applicationset/services"
|
||||
@@ -40,10 +42,12 @@ type SCMConfig struct {
|
||||
enableGitHubAPIMetrics bool
|
||||
GitHubApps github_app_auth.Credentials
|
||||
tokenRefStrictMode bool
|
||||
scmProxyURL string
|
||||
scmNoProxy string
|
||||
}
|
||||
|
||||
func NewSCMConfig(scmRootCAPath string, allowedSCMProviders []string, enableSCMProviders bool, enableGitHubAPIMetrics bool, gitHubApps github_app_auth.Credentials, tokenRefStrictMode bool) SCMConfig {
|
||||
return SCMConfig{
|
||||
func NewSCMConfig(scmRootCAPath string, allowedSCMProviders []string, enableSCMProviders bool, enableGitHubAPIMetrics bool, gitHubApps github_app_auth.Credentials, tokenRefStrictMode bool, opts ...SCMConfigOpts) SCMConfig {
|
||||
c := SCMConfig{
|
||||
scmRootCAPath: scmRootCAPath,
|
||||
allowedSCMProviders: allowedSCMProviders,
|
||||
enableSCMProviders: enableSCMProviders,
|
||||
@@ -51,6 +55,25 @@ func NewSCMConfig(scmRootCAPath string, allowedSCMProviders []string, enableSCMP
|
||||
GitHubApps: gitHubApps,
|
||||
tokenRefStrictMode: tokenRefStrictMode,
|
||||
}
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(&c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
type SCMConfigOpts func(c *SCMConfig)
|
||||
|
||||
func WithNoProxyList(noProxyList string) SCMConfigOpts {
|
||||
return func(config *SCMConfig) {
|
||||
config.scmNoProxy = noProxyList
|
||||
}
|
||||
}
|
||||
|
||||
func WithProxyURL(scmProxyURL string) SCMConfigOpts {
|
||||
return func(config *SCMConfig) {
|
||||
config.scmProxyURL = scmProxyURL
|
||||
}
|
||||
}
|
||||
|
||||
func NewSCMProviderGenerator(client client.Client, scmConfig SCMConfig) Generator {
|
||||
@@ -140,13 +163,14 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
scmHTTPClient := g.newSCMHTTPClient()
|
||||
var provider scm_provider.SCMProviderService
|
||||
switch {
|
||||
case g.overrideProvider != nil:
|
||||
provider = g.overrideProvider
|
||||
case providerConfig.Github != nil:
|
||||
var err error
|
||||
provider, err = g.githubProvider(ctx, providerConfig.Github, applicationSetInfo)
|
||||
provider, err = g.githubProvider(ctx, providerConfig.Github, applicationSetInfo, scmHTTPClient)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("scm provider: %w", err)
|
||||
}
|
||||
@@ -164,7 +188,7 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Gitlab token: %w", err)
|
||||
}
|
||||
provider, err = scm_provider.NewGitlabProvider(providerConfig.Group, token, providerConfig.API, providerConfig.AllBranches, providerConfig.IncludeSubgroups, providerConfig.WillIncludeSharedProjects(), providerConfig.IncludeArchivedRepos, providerConfig.Insecure, g.scmRootCAPath, providerConfig.Topic, caCerts)
|
||||
provider, err = scm_provider.NewGitlabProvider(providerConfig.Group, token, providerConfig.API, providerConfig.AllBranches, providerConfig.IncludeSubgroups, providerConfig.WillIncludeSharedProjects(), providerConfig.IncludeArchivedRepos, providerConfig.Insecure, g.scmRootCAPath, providerConfig.Topic, caCerts, g.scmProxyURL, g.scmNoProxy)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error initializing Gitlab service: %w", err)
|
||||
}
|
||||
@@ -173,7 +197,7 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Gitea token: %w", err)
|
||||
}
|
||||
provider, err = scm_provider.NewGiteaProvider(providerConfig.Gitea.Owner, token, providerConfig.Gitea.API, providerConfig.Gitea.AllBranches, providerConfig.Gitea.Insecure, providerConfig.Gitea.ExcludeArchivedRepos)
|
||||
provider, err = scm_provider.NewGiteaProvider(providerConfig.Gitea.Owner, token, providerConfig.Gitea.API, providerConfig.Gitea.AllBranches, providerConfig.Gitea.Insecure, providerConfig.Gitea.ExcludeArchivedRepos, g.scmProxyURL, g.scmNoProxy)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error initializing Gitea service: %w", err)
|
||||
}
|
||||
@@ -193,15 +217,15 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Secret Bearer token: %w", err)
|
||||
}
|
||||
provider, scmError = scm_provider.NewBitbucketServerProviderBearerToken(ctx, appToken, providerConfig.API, providerConfig.Project, providerConfig.AllBranches, g.scmRootCAPath, providerConfig.Insecure, caCerts)
|
||||
provider, scmError = scm_provider.NewBitbucketServerProviderBearerToken(ctx, appToken, providerConfig.API, providerConfig.Project, providerConfig.AllBranches, g.scmRootCAPath, providerConfig.Insecure, caCerts, g.scmProxyURL, g.scmNoProxy)
|
||||
case providerConfig.BasicAuth != nil:
|
||||
password, err := utils.GetSecretRef(ctx, g.client, providerConfig.BasicAuth.PasswordRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Secret token: %w", err)
|
||||
}
|
||||
provider, scmError = scm_provider.NewBitbucketServerProviderBasicAuth(ctx, providerConfig.BasicAuth.Username, password, providerConfig.API, providerConfig.Project, providerConfig.AllBranches, g.scmRootCAPath, providerConfig.Insecure, caCerts)
|
||||
provider, scmError = scm_provider.NewBitbucketServerProviderBasicAuth(ctx, providerConfig.BasicAuth.Username, password, providerConfig.API, providerConfig.Project, providerConfig.AllBranches, g.scmRootCAPath, providerConfig.Insecure, caCerts, g.scmProxyURL, g.scmNoProxy)
|
||||
default:
|
||||
provider, scmError = scm_provider.NewBitbucketServerProviderNoAuth(ctx, providerConfig.API, providerConfig.Project, providerConfig.AllBranches, g.scmRootCAPath, providerConfig.Insecure, caCerts)
|
||||
provider, scmError = scm_provider.NewBitbucketServerProviderNoAuth(ctx, providerConfig.API, providerConfig.Project, providerConfig.AllBranches, g.scmRootCAPath, providerConfig.Insecure, caCerts, g.scmProxyURL, g.scmNoProxy)
|
||||
}
|
||||
if scmError != nil {
|
||||
return nil, fmt.Errorf("error initializing Bitbucket Server service: %w", scmError)
|
||||
@@ -270,16 +294,14 @@ func (g *SCMProviderGenerator) GenerateParams(appSetGenerator *argoprojiov1alpha
|
||||
return paramsArray, nil
|
||||
}
|
||||
|
||||
func (g *SCMProviderGenerator) githubProvider(ctx context.Context, github *argoprojiov1alpha1.SCMProviderGeneratorGithub, applicationSetInfo *argoprojiov1alpha1.ApplicationSet) (scm_provider.SCMProviderService, error) {
|
||||
var metricsCtx *services.MetricsContext
|
||||
var httpClient *http.Client
|
||||
|
||||
func (g *SCMProviderGenerator) githubProvider(ctx context.Context, github *argoprojiov1alpha1.SCMProviderGeneratorGithub, applicationSetInfo *argoprojiov1alpha1.ApplicationSet, baseHTTPClient *http.Client) (scm_provider.SCMProviderService, error) {
|
||||
httpClient := baseHTTPClient
|
||||
if g.enableGitHubAPIMetrics {
|
||||
metricsCtx = &services.MetricsContext{
|
||||
metricsCtx := &services.MetricsContext{
|
||||
AppSetNamespace: applicationSetInfo.Namespace,
|
||||
AppSetName: applicationSetInfo.Name,
|
||||
}
|
||||
httpClient = services.NewGitHubMetricsClient(metricsCtx)
|
||||
httpClient = services.NewGitHubMetricsClientFrom(httpClient, metricsCtx)
|
||||
}
|
||||
|
||||
if github.AppSecretName != "" {
|
||||
@@ -287,20 +309,21 @@ func (g *SCMProviderGenerator) githubProvider(ctx context.Context, github *argop
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Github app secret: %w", err)
|
||||
}
|
||||
|
||||
if g.enableGitHubAPIMetrics {
|
||||
return scm_provider.NewGithubAppProviderFor(ctx, *auth, github.Organization, github.API, github.AllBranches, github.ExcludeArchivedRepos, httpClient)
|
||||
}
|
||||
return scm_provider.NewGithubAppProviderFor(ctx, *auth, github.Organization, github.API, github.AllBranches, github.ExcludeArchivedRepos)
|
||||
return scm_provider.NewGithubAppProviderFor(ctx, *auth, github.Organization, github.API, github.AllBranches, github.ExcludeArchivedRepos, httpClient)
|
||||
}
|
||||
|
||||
token, err := utils.GetSecretRef(ctx, g.client, github.TokenRef, applicationSetInfo.Namespace, g.tokenRefStrictMode)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching Github token: %w", err)
|
||||
}
|
||||
return scm_provider.NewGithubProvider(github.Organization, token, github.API, github.AllBranches, github.ExcludeArchivedRepos, httpClient)
|
||||
}
|
||||
|
||||
if g.enableGitHubAPIMetrics {
|
||||
return scm_provider.NewGithubProvider(github.Organization, token, github.API, github.AllBranches, github.ExcludeArchivedRepos, httpClient)
|
||||
func (g *SCMConfig) newSCMHTTPClient() *http.Client {
|
||||
if g.scmProxyURL == "" {
|
||||
return &http.Client{}
|
||||
}
|
||||
return scm_provider.NewGithubProvider(github.Organization, token, github.API, github.AllBranches, github.ExcludeArchivedRepos)
|
||||
tr := http.DefaultTransport.(*http.Transport).Clone()
|
||||
tr.Proxy = proxy.GetCallback(g.scmProxyURL, g.scmNoProxy)
|
||||
return &http.Client{Transport: tr}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package generators
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/argoproj/argo-cd/v3/applicationset/services/github_app_auth"
|
||||
"github.com/argoproj/argo-cd/v3/applicationset/services/scm_provider"
|
||||
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
|
||||
)
|
||||
@@ -295,3 +298,113 @@ func TestSCMProviderDisabled_SCMGenerator(t *testing.T) {
|
||||
_, err := generator.GenerateParams(&applicationSetInfo.Spec.Generators[0], &applicationSetInfo, nil)
|
||||
assert.ErrorIs(t, err, ErrSCMProvidersDisabled)
|
||||
}
|
||||
|
||||
func TestNewSCMHTTPClient(t *testing.T) {
|
||||
t.Run("no proxy", func(t *testing.T) {
|
||||
g := &SCMProviderGenerator{
|
||||
SCMConfig: SCMConfig{
|
||||
scmProxyURL: "",
|
||||
},
|
||||
}
|
||||
client := g.newSCMHTTPClient()
|
||||
assert.NotNil(t, client)
|
||||
assert.Nil(t, client.Transport)
|
||||
})
|
||||
|
||||
t.Run("with proxy", func(t *testing.T) {
|
||||
proxyURL := "http://proxy.example.com:8080"
|
||||
g := &SCMProviderGenerator{
|
||||
SCMConfig: SCMConfig{
|
||||
scmProxyURL: proxyURL,
|
||||
scmNoProxy: "example.com",
|
||||
},
|
||||
}
|
||||
client := g.newSCMHTTPClient()
|
||||
assert.NotNil(t, client)
|
||||
require.NotNil(t, client.Transport)
|
||||
tr, ok := client.Transport.(*http.Transport)
|
||||
assert.True(t, ok)
|
||||
assert.NotNil(t, tr.Proxy)
|
||||
|
||||
req, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "http://github.com", http.NoBody)
|
||||
u, err := tr.Proxy(req)
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, u)
|
||||
assert.Equal(t, "proxy.example.com:8080", u.Host)
|
||||
|
||||
reqNoProxy, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "http://example.com", http.NoBody)
|
||||
u, err = tr.Proxy(reqNoProxy)
|
||||
require.NoError(t, err)
|
||||
assert.Nil(t, u)
|
||||
})
|
||||
}
|
||||
|
||||
func TestNewSCMConfig(t *testing.T) {
|
||||
scmRootCAPath := "/path/to/ca"
|
||||
allowedSCMProviders := []string{"github.com", "gitlab.com"}
|
||||
enableSCMProviders := true
|
||||
enableGitHubAPIMetrics := true
|
||||
gitHubApps := github_app_auth.Credentials(nil)
|
||||
tokenRefStrictMode := true
|
||||
|
||||
t.Run("default config", func(t *testing.T) {
|
||||
config := NewSCMConfig(scmRootCAPath, allowedSCMProviders, enableSCMProviders, enableGitHubAPIMetrics, gitHubApps, tokenRefStrictMode)
|
||||
assert.Equal(t, scmRootCAPath, config.scmRootCAPath)
|
||||
assert.Equal(t, allowedSCMProviders, config.allowedSCMProviders)
|
||||
assert.Equal(t, enableSCMProviders, config.enableSCMProviders)
|
||||
assert.Equal(t, enableGitHubAPIMetrics, config.enableGitHubAPIMetrics)
|
||||
assert.Equal(t, gitHubApps, config.GitHubApps)
|
||||
assert.Equal(t, tokenRefStrictMode, config.tokenRefStrictMode)
|
||||
assert.Empty(t, config.scmProxyURL)
|
||||
assert.Empty(t, config.scmNoProxy)
|
||||
})
|
||||
|
||||
t.Run("config with options", func(t *testing.T) {
|
||||
proxyURL := "http://proxy.example.com"
|
||||
noProxy := "localhost,127.0.0.1"
|
||||
config := NewSCMConfig(scmRootCAPath, allowedSCMProviders, enableSCMProviders, enableGitHubAPIMetrics, gitHubApps, tokenRefStrictMode,
|
||||
WithProxyURL(proxyURL),
|
||||
WithNoProxyList(noProxy),
|
||||
)
|
||||
assert.Equal(t, proxyURL, config.scmProxyURL)
|
||||
assert.Equal(t, noProxy, config.scmNoProxy)
|
||||
})
|
||||
}
|
||||
|
||||
func TestGithubProvider_ProxyWithoutMetrics(t *testing.T) {
|
||||
proxyURL := "http://proxy.example.com:8080"
|
||||
|
||||
t.Run("token-based auth passes httpClient when metrics disabled", func(t *testing.T) {
|
||||
g := &SCMProviderGenerator{
|
||||
SCMConfig: SCMConfig{
|
||||
enableGitHubAPIMetrics: false,
|
||||
scmProxyURL: proxyURL,
|
||||
},
|
||||
}
|
||||
httpClient := g.newSCMHTTPClient()
|
||||
|
||||
// Verify the client has a proxy-configured transport
|
||||
require.NotNil(t, httpClient.Transport)
|
||||
tr, ok := httpClient.Transport.(*http.Transport)
|
||||
require.True(t, ok)
|
||||
require.NotNil(t, tr.Proxy)
|
||||
|
||||
req, _ := http.NewRequestWithContext(context.Background(), http.MethodGet, "http://github.com", http.NoBody)
|
||||
u, err := tr.Proxy(req)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "proxy.example.com:8080", u.Host)
|
||||
})
|
||||
|
||||
t.Run("no proxy configured returns bare client when metrics disabled", func(t *testing.T) {
|
||||
g := &SCMProviderGenerator{
|
||||
SCMConfig: SCMConfig{
|
||||
enableGitHubAPIMetrics: false,
|
||||
scmProxyURL: "",
|
||||
},
|
||||
}
|
||||
httpClient := g.newSCMHTTPClient()
|
||||
|
||||
assert.NotNil(t, httpClient)
|
||||
assert.Nil(t, httpClient.Transport) // bare &http.Client{} — uses DefaultTransport
|
||||
})
|
||||
}
|
||||
|
||||
@@ -239,3 +239,15 @@ func NewGitHubMetricsClient(metricsContext *MetricsContext) *http.Client {
|
||||
Transport: NewDefaultGitHubMetricsTransport(http.DefaultTransport, metricsContext),
|
||||
}
|
||||
}
|
||||
|
||||
// NewGitHubMetricsClientFrom returns a new http.Client wrapping the provided one with metrics middleware
|
||||
func NewGitHubMetricsClientFrom(httpClient *http.Client, metricsContext *MetricsContext) *http.Client {
|
||||
log.Debug("Creating new GitHub metrics client")
|
||||
httpClientCopy := *httpClient
|
||||
transport := httpClient.Transport
|
||||
if transport == nil {
|
||||
transport = http.DefaultTransport
|
||||
}
|
||||
httpClientCopy.Transport = NewDefaultGitHubMetricsTransport(transport, metricsContext)
|
||||
return &httpClientCopy
|
||||
}
|
||||
|
||||
@@ -233,3 +233,53 @@ func TestNewGitHubMetricsClient(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewGitHubMetricsClientFrom(t *testing.T) {
|
||||
metricsCtx := &MetricsContext{
|
||||
AppSetNamespace: appsetNamespace,
|
||||
AppSetName: appsetName,
|
||||
}
|
||||
|
||||
customTransport := &http.Transport{
|
||||
MaxIdleConns: 10,
|
||||
}
|
||||
customClient := &http.Client{
|
||||
Transport: customTransport,
|
||||
}
|
||||
|
||||
client := NewGitHubMetricsClientFrom(customClient, metricsCtx)
|
||||
|
||||
assert.NotNil(t, client)
|
||||
assert.NotEqual(t, customClient, client, "Should return a new client instance")
|
||||
assert.NotEqual(t, customClient.Transport, client.Transport, "Original client transport should not be modified")
|
||||
|
||||
transport, ok := client.Transport.(*GitHubMetricsTransport)
|
||||
assert.True(t, ok, "Transport should be GitHubMetricsTransport")
|
||||
|
||||
assert.Equal(t, metricsCtx, transport.metricsContext)
|
||||
assert.Equal(t, customTransport, transport.transport, "Base transport should be the custom transport")
|
||||
assert.Equal(t, globalGitHubMetrics, transport.metrics, "Should use global metrics")
|
||||
}
|
||||
|
||||
func TestNewGitHubMetricsClientFrom_NilTransport(t *testing.T) {
|
||||
metricsCtx := &MetricsContext{
|
||||
AppSetNamespace: appsetNamespace,
|
||||
AppSetName: appsetName,
|
||||
}
|
||||
|
||||
customClient := &http.Client{
|
||||
Transport: nil,
|
||||
}
|
||||
|
||||
client := NewGitHubMetricsClientFrom(customClient, metricsCtx)
|
||||
|
||||
assert.NotNil(t, client)
|
||||
assert.NotEqual(t, customClient, client, "Should return a new client instance")
|
||||
|
||||
transport, ok := client.Transport.(*GitHubMetricsTransport)
|
||||
assert.True(t, ok, "Transport should be GitHubMetricsTransport")
|
||||
|
||||
assert.Equal(t, metricsCtx, transport.metricsContext)
|
||||
assert.Equal(t, http.DefaultTransport, transport.transport, "Base transport should be http.DefaultTransport")
|
||||
assert.Equal(t, globalGitHubMetrics, transport.metrics, "Should use global metrics")
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ type BitbucketService struct {
|
||||
|
||||
var _ PullRequestService = (*BitbucketService)(nil)
|
||||
|
||||
func NewBitbucketServiceBasicAuth(ctx context.Context, username, password, url, projectKey, repositorySlug string, scmRootCAPath string, insecure bool, caCerts []byte) (PullRequestService, error) {
|
||||
func NewBitbucketServiceBasicAuth(ctx context.Context, username, password, url, projectKey, repositorySlug string, scmRootCAPath string, insecure bool, caCerts []byte, proxyURL, noProxy string) (PullRequestService, error) {
|
||||
bitbucketConfig := bitbucketv1.NewConfiguration(url)
|
||||
// Avoid the XSRF check
|
||||
bitbucketConfig.AddDefaultHeader("x-atlassian-token", "no-check")
|
||||
@@ -31,25 +31,25 @@ func NewBitbucketServiceBasicAuth(ctx context.Context, username, password, url,
|
||||
UserName: username,
|
||||
Password: password,
|
||||
})
|
||||
return newBitbucketService(ctx, bitbucketConfig, projectKey, repositorySlug, scmRootCAPath, insecure, caCerts)
|
||||
return newBitbucketService(ctx, bitbucketConfig, projectKey, repositorySlug, scmRootCAPath, insecure, caCerts, proxyURL, noProxy)
|
||||
}
|
||||
|
||||
func NewBitbucketServiceBearerToken(ctx context.Context, bearerToken, url, projectKey, repositorySlug string, scmRootCAPath string, insecure bool, caCerts []byte) (PullRequestService, error) {
|
||||
func NewBitbucketServiceBearerToken(ctx context.Context, bearerToken, url, projectKey, repositorySlug string, scmRootCAPath string, insecure bool, caCerts []byte, proxyURL, noProxy string) (PullRequestService, error) {
|
||||
bitbucketConfig := bitbucketv1.NewConfiguration(url)
|
||||
// Avoid the XSRF check
|
||||
bitbucketConfig.AddDefaultHeader("x-atlassian-token", "no-check")
|
||||
bitbucketConfig.AddDefaultHeader("x-requested-with", "XMLHttpRequest")
|
||||
|
||||
ctx = context.WithValue(ctx, bitbucketv1.ContextAccessToken, bearerToken)
|
||||
return newBitbucketService(ctx, bitbucketConfig, projectKey, repositorySlug, scmRootCAPath, insecure, caCerts)
|
||||
return newBitbucketService(ctx, bitbucketConfig, projectKey, repositorySlug, scmRootCAPath, insecure, caCerts, proxyURL, noProxy)
|
||||
}
|
||||
|
||||
func NewBitbucketServiceNoAuth(ctx context.Context, url, projectKey, repositorySlug string, scmRootCAPath string, insecure bool, caCerts []byte) (PullRequestService, error) {
|
||||
return newBitbucketService(ctx, bitbucketv1.NewConfiguration(url), projectKey, repositorySlug, scmRootCAPath, insecure, caCerts)
|
||||
func NewBitbucketServiceNoAuth(ctx context.Context, url, projectKey, repositorySlug string, scmRootCAPath string, insecure bool, caCerts []byte, proxyURL, noProxy string) (PullRequestService, error) {
|
||||
return newBitbucketService(ctx, bitbucketv1.NewConfiguration(url), projectKey, repositorySlug, scmRootCAPath, insecure, caCerts, proxyURL, noProxy)
|
||||
}
|
||||
|
||||
func newBitbucketService(ctx context.Context, bitbucketConfig *bitbucketv1.Configuration, projectKey, repositorySlug string, scmRootCAPath string, insecure bool, caCerts []byte) (PullRequestService, error) {
|
||||
bbClient := services.SetupBitbucketClient(ctx, bitbucketConfig, scmRootCAPath, insecure, caCerts)
|
||||
func newBitbucketService(ctx context.Context, bitbucketConfig *bitbucketv1.Configuration, projectKey, repositorySlug string, scmRootCAPath string, insecure bool, caCerts []byte, proxyURL, noProxy string) (PullRequestService, error) {
|
||||
bbClient := services.SetupBitbucketClient(ctx, bitbucketConfig, scmRootCAPath, insecure, caCerts, proxyURL, noProxy)
|
||||
|
||||
return &BitbucketService{
|
||||
client: bbClient,
|
||||
|
||||
@@ -63,7 +63,7 @@ func TestListPullRequestNoAuth(t *testing.T) {
|
||||
defaultHandler(t)(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
svc, err := NewBitbucketServiceNoAuth(t.Context(), ts.URL, "PROJECT", "REPO", "", false, nil)
|
||||
svc, err := NewBitbucketServiceNoAuth(t.Context(), ts.URL, "PROJECT", "REPO", "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
pullRequests, err := ListPullRequests(t.Context(), svc, []v1alpha1.PullRequestGeneratorFilter{})
|
||||
require.NoError(t, err)
|
||||
@@ -164,7 +164,7 @@ func TestListPullRequestPagination(t *testing.T) {
|
||||
}
|
||||
}))
|
||||
defer ts.Close()
|
||||
svc, err := NewBitbucketServiceNoAuth(t.Context(), ts.URL, "PROJECT", "REPO", "", false, nil)
|
||||
svc, err := NewBitbucketServiceNoAuth(t.Context(), ts.URL, "PROJECT", "REPO", "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
pullRequests, err := ListPullRequests(t.Context(), svc, []v1alpha1.PullRequestGeneratorFilter{})
|
||||
require.NoError(t, err)
|
||||
@@ -206,7 +206,7 @@ func TestListPullRequestBasicAuth(t *testing.T) {
|
||||
defaultHandler(t)(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
svc, err := NewBitbucketServiceBasicAuth(t.Context(), "user", "password", ts.URL, "PROJECT", "REPO", "", false, nil)
|
||||
svc, err := NewBitbucketServiceBasicAuth(t.Context(), "user", "password", ts.URL, "PROJECT", "REPO", "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
pullRequests, err := ListPullRequests(t.Context(), svc, []v1alpha1.PullRequestGeneratorFilter{})
|
||||
require.NoError(t, err)
|
||||
@@ -223,7 +223,7 @@ func TestListPullRequestBearerAuth(t *testing.T) {
|
||||
defaultHandler(t)(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
svc, err := NewBitbucketServiceBearerToken(t.Context(), "tolkien", ts.URL, "PROJECT", "REPO", "", false, nil)
|
||||
svc, err := NewBitbucketServiceBearerToken(t.Context(), "tolkien", ts.URL, "PROJECT", "REPO", "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
pullRequests, err := ListPullRequests(t.Context(), svc, []v1alpha1.PullRequestGeneratorFilter{})
|
||||
require.NoError(t, err)
|
||||
@@ -288,7 +288,7 @@ func TestListPullRequestTLS(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
svc, err := NewBitbucketServiceBasicAuth(t.Context(), "user", "password", ts.URL, "PROJECT", "REPO", "", test.tlsInsecure, certs)
|
||||
svc, err := NewBitbucketServiceBasicAuth(t.Context(), "user", "password", ts.URL, "PROJECT", "REPO", "", test.tlsInsecure, certs, "", "")
|
||||
require.NoError(t, err)
|
||||
_, err = ListPullRequests(t.Context(), svc, []v1alpha1.PullRequestGeneratorFilter{})
|
||||
if test.requireErr {
|
||||
@@ -305,7 +305,7 @@ func TestListResponseError(t *testing.T) {
|
||||
w.WriteHeader(http.StatusInternalServerError)
|
||||
}))
|
||||
defer ts.Close()
|
||||
svc, _ := NewBitbucketServiceNoAuth(t.Context(), ts.URL, "PROJECT", "REPO", "", false, nil)
|
||||
svc, _ := NewBitbucketServiceNoAuth(t.Context(), ts.URL, "PROJECT", "REPO", "", false, nil, "", "")
|
||||
_, err := ListPullRequests(t.Context(), svc, []v1alpha1.PullRequestGeneratorFilter{})
|
||||
require.Error(t, err)
|
||||
}
|
||||
@@ -330,7 +330,7 @@ func TestListResponseMalformed(t *testing.T) {
|
||||
}
|
||||
}))
|
||||
defer ts.Close()
|
||||
svc, _ := NewBitbucketServiceNoAuth(t.Context(), ts.URL, "PROJECT", "REPO", "", false, nil)
|
||||
svc, _ := NewBitbucketServiceNoAuth(t.Context(), ts.URL, "PROJECT", "REPO", "", false, nil, "", "")
|
||||
_, err := ListPullRequests(t.Context(), svc, []v1alpha1.PullRequestGeneratorFilter{})
|
||||
require.Error(t, err)
|
||||
}
|
||||
@@ -355,7 +355,7 @@ func TestListResponseEmpty(t *testing.T) {
|
||||
}
|
||||
}))
|
||||
defer ts.Close()
|
||||
svc, err := NewBitbucketServiceNoAuth(t.Context(), ts.URL, "PROJECT", "REPO", "", false, nil)
|
||||
svc, err := NewBitbucketServiceNoAuth(t.Context(), ts.URL, "PROJECT", "REPO", "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
pullRequests, err := ListPullRequests(t.Context(), svc, []v1alpha1.PullRequestGeneratorFilter{})
|
||||
require.NoError(t, err)
|
||||
@@ -451,7 +451,7 @@ func TestListPullRequestBranchMatch(t *testing.T) {
|
||||
}))
|
||||
defer ts.Close()
|
||||
regexp := `feature-1[\d]{2}`
|
||||
svc, err := NewBitbucketServiceNoAuth(t.Context(), ts.URL, "PROJECT", "REPO", "", false, nil)
|
||||
svc, err := NewBitbucketServiceNoAuth(t.Context(), ts.URL, "PROJECT", "REPO", "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
pullRequests, err := ListPullRequests(t.Context(), svc, []v1alpha1.PullRequestGeneratorFilter{
|
||||
{
|
||||
@@ -480,7 +480,7 @@ func TestListPullRequestBranchMatch(t *testing.T) {
|
||||
}, *pullRequests[1])
|
||||
|
||||
regexp = `.*2$`
|
||||
svc, err = NewBitbucketServiceNoAuth(t.Context(), ts.URL, "PROJECT", "REPO", "", false, nil)
|
||||
svc, err = NewBitbucketServiceNoAuth(t.Context(), ts.URL, "PROJECT", "REPO", "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
pullRequests, err = ListPullRequests(t.Context(), svc, []v1alpha1.PullRequestGeneratorFilter{
|
||||
{
|
||||
@@ -500,7 +500,7 @@ func TestListPullRequestBranchMatch(t *testing.T) {
|
||||
}, *pullRequests[0])
|
||||
|
||||
regexp = `[\d{2}`
|
||||
svc, err = NewBitbucketServiceNoAuth(t.Context(), ts.URL, "PROJECT", "REPO", "", false, nil)
|
||||
svc, err = NewBitbucketServiceNoAuth(t.Context(), ts.URL, "PROJECT", "REPO", "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
_, err = ListPullRequests(t.Context(), svc, []v1alpha1.PullRequestGeneratorFilter{
|
||||
{
|
||||
@@ -523,7 +523,7 @@ func TestBitbucketServerListReturnsRepositoryNotFoundError(t *testing.T) {
|
||||
_, _ = w.Write([]byte(`{"message": "404 Project Not Found"}`))
|
||||
})
|
||||
|
||||
svc, err := NewBitbucketServiceNoAuth(t.Context(), server.URL, "nonexistent", "nonexistent", "", false, nil)
|
||||
svc, err := NewBitbucketServiceNoAuth(t.Context(), server.URL, "nonexistent", "nonexistent", "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
|
||||
prs, err := svc.List(t.Context())
|
||||
|
||||
@@ -8,6 +8,8 @@ import (
|
||||
"os"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
|
||||
"github.com/argoproj/argo-cd/v3/util/proxy"
|
||||
)
|
||||
|
||||
type GiteaService struct {
|
||||
@@ -19,21 +21,21 @@ type GiteaService struct {
|
||||
|
||||
var _ PullRequestService = (*GiteaService)(nil)
|
||||
|
||||
func NewGiteaService(token, url, owner, repo string, labels []string, insecure bool) (PullRequestService, error) {
|
||||
func NewGiteaService(token, url, owner, repo string, labels []string, insecure bool, proxyURL, noProxy string) (PullRequestService, error) {
|
||||
if token == "" {
|
||||
token = os.Getenv("GITEA_TOKEN")
|
||||
}
|
||||
httpClient := &http.Client{}
|
||||
cookieJar, _ := cookiejar.New(nil)
|
||||
|
||||
tr := http.DefaultTransport.(*http.Transport).Clone()
|
||||
if insecure {
|
||||
cookieJar, _ := cookiejar.New(nil)
|
||||
|
||||
tr := http.DefaultTransport.(*http.Transport).Clone()
|
||||
tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
}
|
||||
tr.Proxy = proxy.GetCallback(proxyURL, noProxy)
|
||||
|
||||
httpClient = &http.Client{
|
||||
Jar: cookieJar,
|
||||
Transport: tr,
|
||||
}
|
||||
httpClient := &http.Client{
|
||||
Jar: cookieJar,
|
||||
Transport: tr,
|
||||
}
|
||||
client, err := gitea.NewClient(url, gitea.SetToken(token), gitea.SetHTTPClient(httpClient))
|
||||
if err != nil {
|
||||
|
||||
@@ -298,7 +298,7 @@ func TestGiteaList(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
giteaMockHandler(t)(w, r)
|
||||
}))
|
||||
host, err := NewGiteaService("", ts.URL, "test-argocd", "pr-test", []string{"label1"}, false)
|
||||
host, err := NewGiteaService("", ts.URL, "test-argocd", "pr-test", []string{"label1"}, false, "", "")
|
||||
require.NoError(t, err)
|
||||
prs, err := host.List(t.Context())
|
||||
require.NoError(t, err)
|
||||
@@ -359,7 +359,7 @@ func TestGiteaListReturnsRepositoryNotFoundError(t *testing.T) {
|
||||
_, _ = w.Write([]byte(`{"message": "404 Project Not Found"}`))
|
||||
})
|
||||
|
||||
svc, err := NewGiteaService("", server.URL, "nonexistent", "nonexistent", []string{}, false)
|
||||
svc, err := NewGiteaService("", server.URL, "nonexistent", "nonexistent", []string{}, false, "", "")
|
||||
require.NoError(t, err)
|
||||
|
||||
prs, err := svc.List(t.Context())
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
gitlab "gitlab.com/gitlab-org/api/client-go"
|
||||
|
||||
"github.com/argoproj/argo-cd/v3/applicationset/utils"
|
||||
"github.com/argoproj/argo-cd/v3/util/proxy"
|
||||
)
|
||||
|
||||
type GitLabService struct {
|
||||
@@ -21,7 +22,7 @@ type GitLabService struct {
|
||||
|
||||
var _ PullRequestService = (*GitLabService)(nil)
|
||||
|
||||
func NewGitLabService(token, url, project string, labels []string, pullRequestState string, scmRootCAPath string, insecure bool, caCerts []byte) (PullRequestService, error) {
|
||||
func NewGitLabService(token, url, project string, labels []string, pullRequestState string, scmRootCAPath string, insecure bool, caCerts []byte, proxyURL, noProxy string) (PullRequestService, error) {
|
||||
var clientOptionFns []gitlab.ClientOptionFunc
|
||||
|
||||
// Set a custom Gitlab base URL if one is provided
|
||||
@@ -35,6 +36,7 @@ func NewGitLabService(token, url, project string, labels []string, pullRequestSt
|
||||
|
||||
tr := http.DefaultTransport.(*http.Transport).Clone()
|
||||
tr.TLSClientConfig = utils.GetTlsConfig(scmRootCAPath, insecure, caCerts)
|
||||
tr.Proxy = proxy.GetCallback(proxyURL, noProxy)
|
||||
|
||||
retryClient := retryablehttp.NewClient()
|
||||
retryClient.HTTPClient.Transport = tr
|
||||
|
||||
@@ -34,7 +34,7 @@ func TestGitLabServiceCustomBaseURL(t *testing.T) {
|
||||
writeMRListResponse(t, w)
|
||||
})
|
||||
|
||||
svc, err := NewGitLabService("", server.URL, "278964", nil, "", "", false, nil)
|
||||
svc, err := NewGitLabService("", server.URL, "278964", nil, "", "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = svc.List(t.Context())
|
||||
@@ -53,7 +53,7 @@ func TestGitLabServiceToken(t *testing.T) {
|
||||
writeMRListResponse(t, w)
|
||||
})
|
||||
|
||||
svc, err := NewGitLabService("token-123", server.URL, "278964", nil, "", "", false, nil)
|
||||
svc, err := NewGitLabService("token-123", server.URL, "278964", nil, "", "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = svc.List(t.Context())
|
||||
@@ -72,7 +72,7 @@ func TestList(t *testing.T) {
|
||||
writeMRListResponse(t, w)
|
||||
})
|
||||
|
||||
svc, err := NewGitLabService("", server.URL, "278964", []string{}, "", "", false, nil)
|
||||
svc, err := NewGitLabService("", server.URL, "278964", []string{}, "", "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
|
||||
prs, err := svc.List(t.Context())
|
||||
@@ -98,7 +98,7 @@ func TestListWithLabels(t *testing.T) {
|
||||
writeMRListResponse(t, w)
|
||||
})
|
||||
|
||||
svc, err := NewGitLabService("", server.URL, "278964", []string{"feature", "ready"}, "", "", false, nil)
|
||||
svc, err := NewGitLabService("", server.URL, "278964", []string{"feature", "ready"}, "", "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = svc.List(t.Context())
|
||||
@@ -117,7 +117,7 @@ func TestListWithState(t *testing.T) {
|
||||
writeMRListResponse(t, w)
|
||||
})
|
||||
|
||||
svc, err := NewGitLabService("", server.URL, "278964", []string{}, "opened", "", false, nil)
|
||||
svc, err := NewGitLabService("", server.URL, "278964", []string{}, "opened", "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = svc.List(t.Context())
|
||||
@@ -178,7 +178,7 @@ func TestListWithStateTLS(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
svc, err := NewGitLabService("", ts.URL, "278964", []string{}, "opened", "", test.tlsInsecure, certs)
|
||||
svc, err := NewGitLabService("", ts.URL, "278964", []string{}, "opened", "", test.tlsInsecure, certs, "", "")
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = svc.List(t.Context())
|
||||
@@ -204,7 +204,7 @@ func TestGitLabListReturnsRepositoryNotFoundError(t *testing.T) {
|
||||
_, _ = w.Write([]byte(`{"message": "404 Project Not Found"}`))
|
||||
})
|
||||
|
||||
svc, err := NewGitLabService("", server.URL, "nonexistent", []string{}, "", "", false, nil)
|
||||
svc, err := NewGitLabService("", server.URL, "nonexistent", []string{}, "", "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
|
||||
prs, err := svc.List(t.Context())
|
||||
|
||||
@@ -21,7 +21,7 @@ type BitbucketServerProvider struct {
|
||||
|
||||
var _ SCMProviderService = &BitbucketServerProvider{}
|
||||
|
||||
func NewBitbucketServerProviderBasicAuth(ctx context.Context, username, password, url, projectKey string, allBranches bool, scmRootCAPath string, insecure bool, caCerts []byte) (*BitbucketServerProvider, error) {
|
||||
func NewBitbucketServerProviderBasicAuth(ctx context.Context, username, password, url, projectKey string, allBranches bool, scmRootCAPath string, insecure bool, caCerts []byte, proxyURL, noProxy string) (*BitbucketServerProvider, error) {
|
||||
bitbucketConfig := bitbucketv1.NewConfiguration(url)
|
||||
// Avoid the XSRF check
|
||||
bitbucketConfig.AddDefaultHeader("x-atlassian-token", "no-check")
|
||||
@@ -31,25 +31,25 @@ func NewBitbucketServerProviderBasicAuth(ctx context.Context, username, password
|
||||
UserName: username,
|
||||
Password: password,
|
||||
})
|
||||
return newBitbucketServerProvider(ctx, bitbucketConfig, projectKey, allBranches, scmRootCAPath, insecure, caCerts)
|
||||
return newBitbucketServerProvider(ctx, bitbucketConfig, projectKey, allBranches, scmRootCAPath, insecure, caCerts, proxyURL, noProxy)
|
||||
}
|
||||
|
||||
func NewBitbucketServerProviderBearerToken(ctx context.Context, bearerToken, url, projectKey string, allBranches bool, scmRootCAPath string, insecure bool, caCerts []byte) (*BitbucketServerProvider, error) {
|
||||
func NewBitbucketServerProviderBearerToken(ctx context.Context, bearerToken, url, projectKey string, allBranches bool, scmRootCAPath string, insecure bool, caCerts []byte, proxyURL, noProxy string) (*BitbucketServerProvider, error) {
|
||||
bitbucketConfig := bitbucketv1.NewConfiguration(url)
|
||||
// Avoid the XSRF check
|
||||
bitbucketConfig.AddDefaultHeader("x-atlassian-token", "no-check")
|
||||
bitbucketConfig.AddDefaultHeader("x-requested-with", "XMLHttpRequest")
|
||||
|
||||
ctx = context.WithValue(ctx, bitbucketv1.ContextAccessToken, bearerToken)
|
||||
return newBitbucketServerProvider(ctx, bitbucketConfig, projectKey, allBranches, scmRootCAPath, insecure, caCerts)
|
||||
return newBitbucketServerProvider(ctx, bitbucketConfig, projectKey, allBranches, scmRootCAPath, insecure, caCerts, proxyURL, noProxy)
|
||||
}
|
||||
|
||||
func NewBitbucketServerProviderNoAuth(ctx context.Context, url, projectKey string, allBranches bool, scmRootCAPath string, insecure bool, caCerts []byte) (*BitbucketServerProvider, error) {
|
||||
return newBitbucketServerProvider(ctx, bitbucketv1.NewConfiguration(url), projectKey, allBranches, scmRootCAPath, insecure, caCerts)
|
||||
func NewBitbucketServerProviderNoAuth(ctx context.Context, url, projectKey string, allBranches bool, scmRootCAPath string, insecure bool, caCerts []byte, proxyURL, noProxy string) (*BitbucketServerProvider, error) {
|
||||
return newBitbucketServerProvider(ctx, bitbucketv1.NewConfiguration(url), projectKey, allBranches, scmRootCAPath, insecure, caCerts, proxyURL, noProxy)
|
||||
}
|
||||
|
||||
func newBitbucketServerProvider(ctx context.Context, bitbucketConfig *bitbucketv1.Configuration, projectKey string, allBranches bool, scmRootCAPath string, insecure bool, caCerts []byte) (*BitbucketServerProvider, error) {
|
||||
bbClient := services.SetupBitbucketClient(ctx, bitbucketConfig, scmRootCAPath, insecure, caCerts)
|
||||
func newBitbucketServerProvider(ctx context.Context, bitbucketConfig *bitbucketv1.Configuration, projectKey string, allBranches bool, scmRootCAPath string, insecure bool, caCerts []byte, proxyURL, noProxy string) (*BitbucketServerProvider, error) {
|
||||
bbClient := services.SetupBitbucketClient(ctx, bitbucketConfig, scmRootCAPath, insecure, caCerts, proxyURL, noProxy)
|
||||
|
||||
return &BitbucketServerProvider{
|
||||
client: bbClient,
|
||||
|
||||
@@ -102,7 +102,7 @@ func TestListReposNoAuth(t *testing.T) {
|
||||
defaultHandler(t)(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", true, "", false, nil)
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", true, "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
repos, err := provider.ListRepos(t.Context(), "ssh")
|
||||
verifyDefaultRepo(t, err, repos)
|
||||
@@ -194,7 +194,7 @@ func TestListReposPagination(t *testing.T) {
|
||||
}
|
||||
}))
|
||||
defer ts.Close()
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", true, "", false, nil)
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", true, "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
repos, err := provider.ListRepos(t.Context(), "ssh")
|
||||
require.NoError(t, err)
|
||||
@@ -271,7 +271,7 @@ func TestGetBranchesBranchPagination(t *testing.T) {
|
||||
defaultHandler(t)(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", true, "", false, nil)
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", true, "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
repos, err := provider.GetBranches(t.Context(), &Repository{
|
||||
Organization: "PROJECT",
|
||||
@@ -323,7 +323,7 @@ func TestGetBranchesDefaultOnly(t *testing.T) {
|
||||
defaultHandler(t)(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", false, "", false, nil)
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", false, "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
repos, err := provider.GetBranches(t.Context(), &Repository{
|
||||
Organization: "PROJECT",
|
||||
@@ -355,7 +355,7 @@ func TestGetBranchesMissingDefault(t *testing.T) {
|
||||
defaultHandler(t)(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", false, "", false, nil)
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", false, "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
repos, err := provider.GetBranches(t.Context(), &Repository{
|
||||
Organization: "PROJECT",
|
||||
@@ -376,7 +376,7 @@ func TestGetBranchesEmptyRepo(t *testing.T) {
|
||||
}
|
||||
}))
|
||||
defer ts.Close()
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", false, "", false, nil)
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", false, "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
repos, err := provider.GetBranches(t.Context(), &Repository{
|
||||
Organization: "PROJECT",
|
||||
@@ -399,7 +399,7 @@ func TestGetBranchesErrorDefaultBranch(t *testing.T) {
|
||||
defaultHandler(t)(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", false, "", false, nil)
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", false, "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
_, err = provider.GetBranches(t.Context(), &Repository{
|
||||
Organization: "PROJECT",
|
||||
@@ -465,7 +465,7 @@ func TestListReposTLS(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
provider, err := NewBitbucketServerProviderBasicAuth(t.Context(), "user", "password", ts.URL, "PROJECT", true, "", test.tlsInsecure, certs)
|
||||
provider, err := NewBitbucketServerProviderBasicAuth(t.Context(), "user", "password", ts.URL, "PROJECT", true, "", test.tlsInsecure, certs, "", "")
|
||||
require.NoError(t, err)
|
||||
_, err = provider.ListRepos(t.Context(), "ssh")
|
||||
if test.requireErr {
|
||||
@@ -484,7 +484,7 @@ func TestListReposBasicAuth(t *testing.T) {
|
||||
defaultHandler(t)(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
provider, err := NewBitbucketServerProviderBasicAuth(t.Context(), "user", "password", ts.URL, "PROJECT", true, "", false, nil)
|
||||
provider, err := NewBitbucketServerProviderBasicAuth(t.Context(), "user", "password", ts.URL, "PROJECT", true, "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
repos, err := provider.ListRepos(t.Context(), "ssh")
|
||||
verifyDefaultRepo(t, err, repos)
|
||||
@@ -497,7 +497,7 @@ func TestListReposBearerAuth(t *testing.T) {
|
||||
defaultHandler(t)(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
provider, err := NewBitbucketServerProviderBearerToken(t.Context(), "tolkien", ts.URL, "PROJECT", true, "", false, nil)
|
||||
provider, err := NewBitbucketServerProviderBearerToken(t.Context(), "tolkien", ts.URL, "PROJECT", true, "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
repos, err := provider.ListRepos(t.Context(), "ssh")
|
||||
verifyDefaultRepo(t, err, repos)
|
||||
@@ -523,7 +523,7 @@ func TestListReposDefaultBranch(t *testing.T) {
|
||||
defaultHandler(t)(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", false, "", false, nil)
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", false, "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
repos, err := provider.ListRepos(t.Context(), "ssh")
|
||||
require.NoError(t, err)
|
||||
@@ -549,7 +549,7 @@ func TestListReposMissingDefaultBranch(t *testing.T) {
|
||||
defaultHandler(t)(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", false, "", false, nil)
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", false, "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
repos, err := provider.ListRepos(t.Context(), "ssh")
|
||||
require.NoError(t, err)
|
||||
@@ -566,7 +566,7 @@ func TestListReposErrorDefaultBranch(t *testing.T) {
|
||||
defaultHandler(t)(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", false, "", false, nil)
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", false, "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
_, err = provider.ListRepos(t.Context(), "ssh")
|
||||
require.Error(t, err)
|
||||
@@ -578,7 +578,7 @@ func TestListReposCloneProtocol(t *testing.T) {
|
||||
defaultHandler(t)(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", true, "", false, nil)
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", true, "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
repos, err := provider.ListRepos(t.Context(), "https")
|
||||
require.NoError(t, err)
|
||||
@@ -600,7 +600,7 @@ func TestListReposUnknownProtocol(t *testing.T) {
|
||||
defaultHandler(t)(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", true, "", false, nil)
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", true, "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
_, errProtocol := provider.ListRepos(t.Context(), "http")
|
||||
require.Error(t, errProtocol)
|
||||
@@ -638,7 +638,7 @@ func TestBitbucketServerHasPath(t *testing.T) {
|
||||
}
|
||||
}))
|
||||
defer ts.Close()
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", true, "", false, nil)
|
||||
provider, err := NewBitbucketServerProviderNoAuth(t.Context(), ts.URL, "PROJECT", true, "", false, nil, "", "")
|
||||
require.NoError(t, err)
|
||||
repo := &Repository{
|
||||
Organization: "PROJECT",
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"os"
|
||||
|
||||
"code.gitea.io/sdk/gitea"
|
||||
|
||||
"github.com/argoproj/argo-cd/v3/util/proxy"
|
||||
)
|
||||
|
||||
type GiteaProvider struct {
|
||||
@@ -20,22 +22,19 @@ type GiteaProvider struct {
|
||||
|
||||
var _ SCMProviderService = &GiteaProvider{}
|
||||
|
||||
func NewGiteaProvider(owner, token, url string, allBranches, insecure, excludeArchivedRepos bool) (*GiteaProvider, error) {
|
||||
func NewGiteaProvider(owner, token, url string, allBranches, insecure, excludeArchivedRepos bool, proxyURL, noProxy string) (*GiteaProvider, error) {
|
||||
if token == "" {
|
||||
token = os.Getenv("GITEA_TOKEN")
|
||||
}
|
||||
httpClient := &http.Client{}
|
||||
|
||||
transport := http.DefaultTransport.(*http.Transport).Clone()
|
||||
if insecure {
|
||||
cookieJar, _ := cookiejar.New(nil)
|
||||
|
||||
tr := http.DefaultTransport.(*http.Transport).Clone()
|
||||
tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
|
||||
httpClient = &http.Client{
|
||||
Jar: cookieJar,
|
||||
Transport: tr,
|
||||
}
|
||||
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
}
|
||||
transport.Proxy = proxy.GetCallback(proxyURL, noProxy)
|
||||
|
||||
cookieJar, _ := cookiejar.New(nil)
|
||||
httpClient := &http.Client{Jar: cookieJar, Transport: transport}
|
||||
client, err := gitea.NewClient(url, gitea.SetToken(token), gitea.SetHTTPClient(httpClient))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error creating a new gitea client: %w", err)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -808,7 +809,7 @@ func TestGiteaListRepos(t *testing.T) {
|
||||
defer ts.Close()
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
provider, _ := NewGiteaProvider("test-argocd", "", ts.URL, c.allBranches, false, c.excludeArchivedRepos)
|
||||
provider, _ := NewGiteaProvider("test-argocd", "", ts.URL, c.allBranches, false, c.excludeArchivedRepos, "", "")
|
||||
rawRepos, err := ListRepos(t.Context(), provider, c.filters, c.proto)
|
||||
|
||||
if c.hasError {
|
||||
@@ -831,7 +832,7 @@ func TestGiteaHasPath(t *testing.T) {
|
||||
giteaMockHandler(t)(w, r)
|
||||
}))
|
||||
defer ts.Close()
|
||||
host, _ := NewGiteaProvider("gitea", "", ts.URL, false, false, false)
|
||||
host, _ := NewGiteaProvider("gitea", "", ts.URL, false, false, false, "", "")
|
||||
repo := &Repository{
|
||||
Organization: "gitea",
|
||||
Repository: "go-sdk",
|
||||
@@ -856,3 +857,56 @@ func TestGiteaHasPath(t *testing.T) {
|
||||
assert.False(t, ok)
|
||||
})
|
||||
}
|
||||
|
||||
func TestNewGiteaProvider_Proxy(t *testing.T) {
|
||||
targetTS := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if r.URL.Path == "/api/v1/version" {
|
||||
_, _ = w.Write([]byte(`{"version":"1.17.0"}`))
|
||||
return
|
||||
}
|
||||
_, _ = w.Write([]byte(`{"id": 1, "name": "test-repo"}`))
|
||||
}))
|
||||
defer targetTS.Close()
|
||||
|
||||
proxyCalled := 0
|
||||
proxyTS := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
proxyCalled++
|
||||
r.RequestURI = ""
|
||||
u, _ := url.Parse(targetTS.URL)
|
||||
r.URL.Scheme = u.Scheme
|
||||
r.URL.Host = u.Host
|
||||
r.Host = u.Host
|
||||
|
||||
resp, err := http.DefaultClient.Do(r)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
for k, vv := range resp.Header {
|
||||
for _, v := range vv {
|
||||
w.Header().Add(k, v)
|
||||
}
|
||||
}
|
||||
w.WriteHeader(resp.StatusCode)
|
||||
_, _ = io.Copy(w, resp.Body)
|
||||
}))
|
||||
defer proxyTS.Close()
|
||||
|
||||
targetURL := "http://gitea.example.com"
|
||||
|
||||
provider, err := NewGiteaProvider("test-owner", "test-token", targetURL, false, false, false, proxyTS.URL, "")
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, provider)
|
||||
|
||||
repo := &Repository{
|
||||
Organization: "test-owner",
|
||||
Repository: "test-repo",
|
||||
Branch: "main",
|
||||
}
|
||||
_, err = provider.RepoHasPath(t.Context(), repo, "README.md")
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Positive(t, proxyCalled, "Proxy should have been called")
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
gitlab "gitlab.com/gitlab-org/api/client-go"
|
||||
|
||||
"github.com/argoproj/argo-cd/v3/applicationset/utils"
|
||||
"github.com/argoproj/argo-cd/v3/util/proxy"
|
||||
)
|
||||
|
||||
type GitlabProvider struct {
|
||||
@@ -25,7 +26,7 @@ type GitlabProvider struct {
|
||||
|
||||
var _ SCMProviderService = &GitlabProvider{}
|
||||
|
||||
func NewGitlabProvider(organization string, token string, url string, allBranches, includeSubgroups, includeSharedProjects, includeArchivedRepos, insecure bool, scmRootCAPath, topic string, caCerts []byte) (*GitlabProvider, error) {
|
||||
func NewGitlabProvider(organization string, token string, url string, allBranches, includeSubgroups, includeSharedProjects, includeArchivedRepos, insecure bool, scmRootCAPath, topic string, caCerts []byte, proxyURL, noProxy string) (*GitlabProvider, error) {
|
||||
// Undocumented environment variable to set a default token, to be used in testing to dodge anonymous rate limits.
|
||||
if token == "" {
|
||||
token = os.Getenv("GITLAB_TOKEN")
|
||||
@@ -34,6 +35,7 @@ func NewGitlabProvider(organization string, token string, url string, allBranche
|
||||
|
||||
tr := http.DefaultTransport.(*http.Transport).Clone()
|
||||
tr.TLSClientConfig = utils.GetTlsConfig(scmRootCAPath, insecure, caCerts)
|
||||
tr.Proxy = proxy.GetCallback(proxyURL, noProxy)
|
||||
|
||||
retryClient := retryablehttp.NewClient()
|
||||
retryClient.HTTPClient.Transport = tr
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -1630,7 +1632,7 @@ func TestGitlabListRepos(t *testing.T) {
|
||||
}))
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
provider, _ := NewGitlabProvider("test-argocd-proton", "", ts.URL, c.allBranches, c.includeSubgroups, c.includeSharedProjects, c.includeArchivedRepos, c.insecure, "", c.topic, nil)
|
||||
provider, _ := NewGitlabProvider("test-argocd-proton", "", ts.URL, c.allBranches, c.includeSubgroups, c.includeSharedProjects, c.includeArchivedRepos, c.insecure, "", c.topic, nil, "", "")
|
||||
rawRepos, err := ListRepos(t.Context(), provider, c.filters, c.proto)
|
||||
if c.hasError {
|
||||
require.Error(t, err)
|
||||
@@ -1667,7 +1669,7 @@ func TestGitlabHasPath(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
gitlabMockHandler(t)(w, r)
|
||||
}))
|
||||
host, _ := NewGitlabProvider("test-argocd-proton", "", ts.URL, false, true, true, false, false, "", "", nil)
|
||||
host, _ := NewGitlabProvider("test-argocd-proton", "", ts.URL, false, true, true, false, false, "", "", nil, "", "")
|
||||
repo := &Repository{
|
||||
Organization: "test-argocd-proton",
|
||||
Repository: "argocd",
|
||||
@@ -1723,7 +1725,7 @@ func TestGitlabGetBranches(t *testing.T) {
|
||||
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
gitlabMockHandler(t)(w, r)
|
||||
}))
|
||||
host, _ := NewGitlabProvider("test-argocd-proton", "", ts.URL, false, true, true, false, false, "", "", nil)
|
||||
host, _ := NewGitlabProvider("test-argocd-proton", "", ts.URL, false, true, true, false, false, "", "", nil, "", "")
|
||||
|
||||
repo := &Repository{
|
||||
RepositoryId: int64(27084533),
|
||||
@@ -1799,7 +1801,7 @@ func TestGetBranchesTLS(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
host, err := NewGitlabProvider("test-argocd-proton", "", ts.URL, false, true, true, false, test.tlsInsecure, "", "", certs)
|
||||
host, err := NewGitlabProvider("test-argocd-proton", "", ts.URL, false, true, true, false, test.tlsInsecure, "", "", certs, "", "")
|
||||
require.NoError(t, err)
|
||||
repo := &Repository{
|
||||
RepositoryId: int64(27084533),
|
||||
@@ -1814,3 +1816,63 @@ func TestGetBranchesTLS(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewGitlabProvider_Proxy(t *testing.T) {
|
||||
targetTS := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if r.URL.Path == "/api/v4" || r.URL.Path == "/api/v4/" {
|
||||
_, _ = w.Write([]byte(`{}`))
|
||||
return
|
||||
}
|
||||
// Return a branch list that won't cause panic
|
||||
// We need to check if the request is for listing branches (returns array) or getting one (returns object)
|
||||
if strings.Contains(r.URL.Path, "/repository/branches/master") {
|
||||
_, _ = w.Write([]byte(`{"name":"master","commit":{"id":"123456"}}`))
|
||||
} else {
|
||||
_, _ = w.Write([]byte(`[{"name":"master","commit":{"id":"123456"}}]`))
|
||||
}
|
||||
}))
|
||||
defer targetTS.Close()
|
||||
|
||||
proxyCalled := 0
|
||||
proxyTS := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
proxyCalled++
|
||||
r.RequestURI = ""
|
||||
u, _ := url.Parse(targetTS.URL)
|
||||
r.URL.Scheme = u.Scheme
|
||||
r.URL.Host = u.Host
|
||||
r.Host = u.Host
|
||||
|
||||
resp, err := http.DefaultClient.Do(r)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
for k, vv := range resp.Header {
|
||||
for _, v := range vv {
|
||||
w.Header().Add(k, v)
|
||||
}
|
||||
}
|
||||
w.WriteHeader(resp.StatusCode)
|
||||
_, _ = io.Copy(w, resp.Body)
|
||||
}))
|
||||
defer proxyTS.Close()
|
||||
|
||||
targetURL := "http://gitlab.example.com"
|
||||
|
||||
provider, err := NewGitlabProvider("test-org", "test-token", targetURL, false, false, false, false, false, "", "", nil, proxyTS.URL, "")
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, provider)
|
||||
|
||||
repo := &Repository{
|
||||
Organization: "test-org",
|
||||
Repository: "test-repo",
|
||||
Branch: "master",
|
||||
RepositoryId: 1,
|
||||
}
|
||||
_, err = provider.GetBranches(t.Context(), repo)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Positive(t, proxyCalled, "Proxy should have been called")
|
||||
}
|
||||
|
||||
@@ -7,15 +7,17 @@ import (
|
||||
bitbucketv1 "github.com/gfleury/go-bitbucket-v1"
|
||||
|
||||
"github.com/argoproj/argo-cd/v3/applicationset/utils"
|
||||
"github.com/argoproj/argo-cd/v3/util/proxy"
|
||||
)
|
||||
|
||||
// SetupBitbucketClient configures and creates a Bitbucket API client with TLS settings
|
||||
func SetupBitbucketClient(ctx context.Context, config *bitbucketv1.Configuration, scmRootCAPath string, insecure bool, caCerts []byte) *bitbucketv1.APIClient {
|
||||
func SetupBitbucketClient(ctx context.Context, config *bitbucketv1.Configuration, scmRootCAPath string, insecure bool, caCerts []byte, proxyURL, noProxy string) *bitbucketv1.APIClient {
|
||||
config.BasePath = utils.NormalizeBitbucketBasePath(config.BasePath)
|
||||
tlsConfig := utils.GetTlsConfig(scmRootCAPath, insecure, caCerts)
|
||||
|
||||
transport := http.DefaultTransport.(*http.Transport).Clone()
|
||||
transport.TLSClientConfig = tlsConfig
|
||||
transport.Proxy = proxy.GetCallback(proxyURL, noProxy)
|
||||
config.HTTPClient = &http.Client{Transport: transport}
|
||||
|
||||
return bitbucketv1.NewAPIClient(ctx, config)
|
||||
|
||||
@@ -15,7 +15,7 @@ func TestSetupBitbucketClient(t *testing.T) {
|
||||
cfg := &bitbucketv1.Configuration{}
|
||||
|
||||
// Act
|
||||
client := SetupBitbucketClient(ctx, cfg, "", false, nil)
|
||||
client := SetupBitbucketClient(ctx, cfg, "", false, nil, "", "")
|
||||
|
||||
// Assert
|
||||
require.NotNil(t, client, "expected client to be created")
|
||||
|
||||
@@ -82,6 +82,8 @@ func NewCommand() *cobra.Command {
|
||||
maxResourcesStatusCount int
|
||||
cacheSyncPeriod time.Duration
|
||||
concurrentApplicationUpdates int
|
||||
scmProxyURL string
|
||||
scmNoProxy string
|
||||
)
|
||||
scheme := runtime.NewScheme()
|
||||
_ = clientgoscheme.AddToScheme(scheme)
|
||||
@@ -204,7 +206,14 @@ func NewCommand() *cobra.Command {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
scmConfig := generators.NewSCMConfig(scmRootCAPath, allowedScmProviders, enableScmProviders, enableGitHubAPIMetrics, github_app.NewAuthCredentials(argoCDDB.(db.RepoCredsDB)), tokenRefStrictMode)
|
||||
scmConfig := generators.NewSCMConfig(
|
||||
scmRootCAPath,
|
||||
allowedScmProviders,
|
||||
enableScmProviders,
|
||||
enableGitHubAPIMetrics,
|
||||
github_app.NewAuthCredentials(argoCDDB.(db.RepoCredsDB)),
|
||||
tokenRefStrictMode, generators.WithProxyURL(scmProxyURL),
|
||||
generators.WithNoProxyList(scmNoProxy))
|
||||
|
||||
tlsConfig := apiclient.TLSConfiguration{
|
||||
DisableTLS: repoServerPlaintext,
|
||||
@@ -303,6 +312,8 @@ func NewCommand() *cobra.Command {
|
||||
command.Flags().IntVar(&repoServerTimeoutSeconds, "repo-server-timeout-seconds", env.ParseNumFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_REPO_SERVER_TIMEOUT_SECONDS", 60, 0, math.MaxInt64), "Repo server RPC call timeout seconds.")
|
||||
command.Flags().IntVar(&maxConcurrentReconciliations, "concurrent-reconciliations", env.ParseNumFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_CONCURRENT_RECONCILIATIONS", 10, 1, math.MaxInt), "Max concurrent reconciliations limit for the controller")
|
||||
command.Flags().StringVar(&scmRootCAPath, "scm-root-ca-path", env.StringFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_SCM_ROOT_CA_PATH", ""), "Provide Root CA Path for self-signed TLS Certificates")
|
||||
command.Flags().StringVar(&scmProxyURL, "scm-proxy-url", env.StringFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_SCM_PROXY_URL", ""), "HTTP/HTTPS proxy URL for outbound SCM provider API requests (GitHub, GitLab, etc.). Does NOT affect Kubernetes API server connectivity — use --proxy-url (kubectl flag) for that.")
|
||||
command.Flags().StringVar(&scmNoProxy, "scm-no-proxy", env.StringFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_SCM_NO_PROXY", ""), "Comma-separated list of hosts that should bypass the --scm-proxy-url proxy.")
|
||||
command.Flags().StringSliceVar(&globalPreservedAnnotations, "preserved-annotations", env.StringsFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_GLOBAL_PRESERVED_ANNOTATIONS", []string{}, ","), "Sets global preserved field values for annotations")
|
||||
command.Flags().StringSliceVar(&globalPreservedLabels, "preserved-labels", env.StringsFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_GLOBAL_PRESERVED_LABELS", []string{}, ","), "Sets global preserved field values for labels")
|
||||
command.Flags().IntVar(&webhookParallelism, "webhook-parallelism-limit", env.ParseNumFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_WEBHOOK_PARALLELISM_LIMIT", 50, 1, 1000), "Number of webhook requests processed concurrently")
|
||||
@@ -311,7 +322,6 @@ func NewCommand() *cobra.Command {
|
||||
command.Flags().IntVar(&maxResourcesStatusCount, "max-resources-status-count", env.ParseNumFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_MAX_RESOURCES_STATUS_COUNT", 5000, 0, math.MaxInt), "Max number of resources stored in appset status.")
|
||||
command.Flags().DurationVar(&cacheSyncPeriod, "cache-sync-period", env.ParseDurationFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_CACHE_SYNC_PERIOD", time.Hour*10, 0, time.Hour*24), "Period at which the manager client cache is forcefully resynced with the Kubernetes API server. 0 disables periodic resync.")
|
||||
command.Flags().IntVar(&concurrentApplicationUpdates, "concurrent-application-updates", env.ParseNumFromEnv("ARGOCD_APPLICATIONSET_CONTROLLER_CONCURRENT_APPLICATION_UPDATES", 1, 1, 200), "Number of concurrent Application create/update/delete operations per ApplicationSet reconcile.")
|
||||
|
||||
return &command
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,24 @@ spec:
|
||||
> `project` field of an ApplicationSet with an SCM generator is templated, to avoid granting management of
|
||||
> out-of-bounds resources.
|
||||
|
||||
## Proxy Configuration
|
||||
|
||||
If your ApplicationSet controller needs to reach SCM provider APIs (GitHub, GitLab, Gitea, Bitbucket Server) through an HTTP/HTTPS proxy, use the dedicated SCM proxy flags:
|
||||
|
||||
```sh
|
||||
argocd-applicationset-controller \
|
||||
--scm-proxy-url=http://proxy.corp.example.com:3128 \
|
||||
--scm-no-proxy=internal.gitlab.corp.example.com,10.0.0.0/8
|
||||
```
|
||||
These flags can also be set via environment variables:
|
||||
|
||||
- `ARGOCD_APPLICATIONSET_CONTROLLER_SCM_PROXY_URL`
|
||||
- `ARGOCD_APPLICATIONSET_CONTROLLER_SCM_NO_PROXY`
|
||||
|
||||
> [!NOTE]
|
||||
> --scm-proxy-url only affects outbound SCM API requests. It does not affect Kubernetes API server connectivity.
|
||||
> Use --proxy-url (the standard kubectl flag) to proxy Kubernetes API traffic.
|
||||
|
||||
## GitHub
|
||||
|
||||
The GitHub mode uses the GitHub API to scan an organization in either github.com or GitHub Enterprise.
|
||||
|
||||
@@ -53,6 +53,8 @@ argocd-applicationset-controller [flags]
|
||||
--repo-server-strict-tls Whether to use strict validation of the TLS cert presented by the repo server
|
||||
--repo-server-timeout-seconds int Repo server RPC call timeout seconds. (default 60)
|
||||
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
|
||||
--scm-no-proxy string Comma-separated list of hosts that should bypass the --scm-proxy-url proxy.
|
||||
--scm-proxy-url string HTTP/HTTPS proxy URL for outbound SCM provider API requests (GitHub, GitLab, etc.). Does NOT affect Kubernetes API server connectivity — use --proxy-url (kubectl flag) for that.
|
||||
--scm-root-ca-path string Provide Root CA Path for self-signed TLS Certificates
|
||||
--server string The address and port of the Kubernetes API server
|
||||
--tls-server-name string If provided, this name will be used to validate server certificate. If this is not provided, hostname used to contact the server is used.
|
||||
|
||||
Reference in New Issue
Block a user