Skip to content

Commit d16df52

Browse files
authoredOct 15, 2024··
feat: manage clusters via proxy (#20374)
* feat: proxy support Signed-off-by: pashakostohrys <pavel@codefresh.io> * feat: proxy support Signed-off-by: pashakostohrys <pavel@codefresh.io> * feat: proxy support Signed-off-by: pashakostohrys <pavel@codefresh.io> * fix linter Signed-off-by: pashakostohrys <pavel@codefresh.io> * small improvements Signed-off-by: pashakostohrys <pavel@codefresh.io> * add cluster test Signed-off-by: pashakostohrys <pavel@codefresh.io> * fix linter Signed-off-by: pashakostohrys <pavel@codefresh.io> * change error message Signed-off-by: pashakostohrys <pavel@codefresh.io> * override always will change proxy url Signed-off-by: pashakostohrys <pavel@codefresh.io> --------- Signed-off-by: pashakostohrys <pavel@codefresh.io>
1 parent b2e52de commit d16df52

File tree

9 files changed

+844
-718
lines changed

9 files changed

+844
-718
lines changed
 

‎assets/swagger.json

+4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎cmd/argocd/commands/cluster.go

+8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package commands
22

33
import (
44
"fmt"
5+
"net/http"
56
"os"
67
"regexp"
78
"strings"
@@ -106,6 +107,11 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie
106107
contextName := args[0]
107108
conf, err := getRestConfig(pathOpts, contextName)
108109
errors.CheckError(err)
110+
if clusterOpts.ProxyUrl != "" {
111+
u, err := argoappv1.ParseProxyUrl(clusterOpts.ProxyUrl)
112+
errors.CheckError(err)
113+
conf.Proxy = http.ProxyURL(u)
114+
}
109115
clientset, err := kubernetes.NewForConfig(conf)
110116
errors.CheckError(err)
111117
managerBearerToken := ""
@@ -191,6 +197,7 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie
191197
command.Flags().BoolVarP(&skipConfirmation, "yes", "y", false, "Skip explicit confirmation")
192198
command.Flags().StringArrayVar(&labels, "label", nil, "Set metadata labels (e.g. --label key=value)")
193199
command.Flags().StringArrayVar(&annotations, "annotation", nil, "Set metadata annotations (e.g. --annotation key=value)")
200+
command.Flags().StringVar(&clusterOpts.ProxyUrl, "proxy-url", "", "use proxy to connect cluster")
194201
cmdutil.AddClusterFlags(command, &clusterOpts)
195202
return command
196203
}
@@ -374,6 +381,7 @@ func printClusterDetails(clusters []argoappv1.Cluster) {
374381
fmt.Printf(" oAuth authentication: %v\n", cluster.Config.BearerToken != "")
375382
fmt.Printf(" AWS authentication: %v\n", cluster.Config.AWSAuthConfig != nil)
376383
fmt.Printf("\nDisable compression: %v\n", cluster.Config.DisableCompression)
384+
fmt.Printf("\nUse proxy: %v\n", cluster.Config.ProxyUrl != "")
377385
fmt.Println()
378386
}
379387
}

‎cmd/util/cluster.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,13 @@ func NewCluster(name string, namespaces []string, clusterResources bool, conf *r
105105
Labels: labels,
106106
Annotations: annotations,
107107
}
108-
108+
// it's a tradeoff to get proxy url from rest config
109+
// more detail: https://github.com/kubernetes/kubernetes/pull/81443
110+
if conf.Proxy != nil {
111+
if url, err := conf.Proxy(nil); err == nil {
112+
clst.Config.ProxyUrl = url.String()
113+
}
114+
}
109115
// Bearer token will preferentially be used for auth if present,
110116
// Even in presence of key/cert credentials
111117
// So set bearer token only if the key/cert data is absent
@@ -160,6 +166,7 @@ type ClusterOptions struct {
160166
ExecProviderInstallHint string
161167
ClusterEndpoint string
162168
DisableCompression bool
169+
ProxyUrl string
163170
}
164171

165172
// InClusterEndpoint returns true if ArgoCD should reference the in-cluster

‎docs/operator-manual/declarative-setup.md

+2
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,8 @@ execProviderConfig:
567567
}
568568
apiVersion: string
569569
installHint: string
570+
# Proxy URL for the kubernetes client to use when connecting to the cluster api server
571+
proxyUrl: string
570572
# Transport layer security configuration settings
571573
tlsClientConfig:
572574
# Base64 encoded PEM-encoded bytes (typically read from a client certificate file).

‎docs/user-guide/commands/argocd_cluster_add.md

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎pkg/apis/application/v1alpha1/generated.pb.go

+758-717
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎pkg/apis/application/v1alpha1/generated.proto

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎pkg/apis/application/v1alpha1/types.go

+28
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"math"
88
"net"
99
"net/http"
10+
"net/url"
1011
"os"
1112
"path/filepath"
1213
"reflect"
@@ -2042,6 +2043,9 @@ type ClusterConfig struct {
20422043

20432044
// DisableCompression bypasses automatic GZip compression requests to the server.
20442045
DisableCompression bool `json:"disableCompression,omitempty" protobuf:"bytes,7,opt,name=disableCompression"`
2046+
2047+
// ProxyURL is the URL to the proxy to be used for all requests send to the server
2048+
ProxyUrl string `json:"proxyUrl,omitempty" protobuf:"bytes,8,opt,name=proxyUrl"`
20452049
}
20462050

20472051
// TLSClientConfig contains settings to enable transport layer security
@@ -3105,6 +3109,9 @@ func SetK8SConfigDefaults(config *rest.Config) error {
31053109
DisableCompression: config.DisableCompression,
31063110
IdleConnTimeout: K8sTCPIdleConnTimeout,
31073111
})
3112+
if config.Proxy != nil {
3113+
transport.Proxy = config.Proxy
3114+
}
31083115
tr, err := rest.HTTPWrappersForConfig(config, transport)
31093116
if err != nil {
31103117
return err
@@ -3128,6 +3135,20 @@ func SetK8SConfigDefaults(config *rest.Config) error {
31283135
return nil
31293136
}
31303137

3138+
// ParseProxyUrl returns a parsed url and verifies that schema is correct
3139+
func ParseProxyUrl(proxyUrl string) (*url.URL, error) {
3140+
u, err := url.Parse(proxyUrl)
3141+
if err != nil {
3142+
return nil, err
3143+
}
3144+
switch u.Scheme {
3145+
case "http", "https", "socks5":
3146+
default:
3147+
return nil, fmt.Errorf("Failed to parse proxy url, unsupported scheme %q, must be http, https, or socks5", u.Scheme)
3148+
}
3149+
return u, nil
3150+
}
3151+
31313152
// RawRestConfig returns a go-client REST config from cluster that might be serialized into the file using kube.WriteKubeConfig method.
31323153
func (c *Cluster) RawRestConfig() (*rest.Config, error) {
31333154
var config *rest.Config
@@ -3215,6 +3236,13 @@ func (c *Cluster) RawRestConfig() (*rest.Config, error) {
32153236
if err != nil {
32163237
return nil, fmt.Errorf("Unable to create K8s REST config: %w", err)
32173238
}
3239+
if c.Config.ProxyUrl != "" {
3240+
u, err := ParseProxyUrl(c.Config.ProxyUrl)
3241+
if err != nil {
3242+
return nil, fmt.Errorf("Unable to create K8s REST config, can`t parse proxy url: %w", err)
3243+
}
3244+
config.Proxy = http.ProxyURL(u)
3245+
}
32183246
config.DisableCompression = c.Config.DisableCompression
32193247
config.Timeout = K8sServerSideTimeout
32203248
config.QPS = K8sClientConfigQPS

‎pkg/apis/application/v1alpha1/types_test.go

+32
Original file line numberDiff line numberDiff line change
@@ -4265,3 +4265,35 @@ func TestAppProject_ValidateDestinationServiceAccount(t *testing.T) {
42654265
}
42664266
}
42674267
}
4268+
4269+
func TestCluster_ParseProxyUrl(t *testing.T) {
4270+
testData := []struct {
4271+
url string
4272+
expectedErrMsg string
4273+
}{
4274+
{
4275+
url: "https://192.168.99.100:8443",
4276+
expectedErrMsg: "",
4277+
},
4278+
{
4279+
url: "test://!abc",
4280+
expectedErrMsg: "Failed to parse proxy url, unsupported scheme \"test\", must be http, https, or socks5",
4281+
},
4282+
{
4283+
url: "http://192.168.99.100:8443",
4284+
expectedErrMsg: "",
4285+
},
4286+
{
4287+
url: "socks5://192.168.99.100:8443",
4288+
expectedErrMsg: "",
4289+
},
4290+
}
4291+
for _, data := range testData {
4292+
_, err := ParseProxyUrl(data.url)
4293+
if data.expectedErrMsg == "" {
4294+
require.NoError(t, err)
4295+
} else {
4296+
require.ErrorContains(t, err, data.expectedErrMsg)
4297+
}
4298+
}
4299+
}

0 commit comments

Comments
 (0)
Please sign in to comment.