Skip to content

Commit af782ad

Browse files
authored
fix: preserve default proxy settings (#1656)
* chore: don't reset default proxy settings * chore: consmetic changes Signed-off-by: Anatolii Bazko <abazko@redhat.com>
1 parent e31ead1 commit af782ad

3 files changed

Lines changed: 124 additions & 149 deletions

File tree

controllers/workspace/http.go

Lines changed: 52 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"time"
2626

2727
controller "github.com/devfile/devworkspace-operator/apis/controller/v1alpha1"
28+
"github.com/devfile/devworkspace-operator/pkg/config"
2829
"k8s.io/apimachinery/pkg/types"
2930

3031
"github.com/go-logr/logr"
@@ -44,7 +45,7 @@ type HttpClientsFactory interface {
4445
// GetHealthCheckHttpClient returns an HTTP client that skips TLS verification.
4546
// This client MUST only be used for workspace health/readiness checks, not for
4647
// fetching external content or making security-sensitive requests.
47-
GetHealthCheckHttpClient(*controller.RoutingConfig) *http.Client
48+
GetHealthCheckHttpClient() *http.Client
4849
}
4950

5051
// DefaultHttpClientsFactory is a thread-safe, caching implementation of HttpClientsFactory.
@@ -59,13 +60,11 @@ type DefaultHttpClientsFactory struct {
5960

6061
mu sync.RWMutex
6162

62-
httpClientProxyConfig *controller.Proxy
6363
httpClientConfigmapRef *controller.ConfigmapReference
6464
httpClientCertsVersion string
6565

66-
healthCheckHttpClientProxyConfig *controller.Proxy
67-
6866
systemCertPool *x509.CertPool
67+
proxyFunc func(*http.Request) (*url.URL, error)
6968
}
7069

7170
func SetupHttpClientsFactory(k8s client.Client, logger logr.Logger) error {
@@ -74,10 +73,26 @@ func SetupHttpClientsFactory(k8s client.Client, logger logr.Logger) error {
7473
return fmt.Errorf("failed to load system cert pool: %w", err)
7574
}
7675

76+
proxyFunc := getProxyFunc()
77+
78+
healthCheckHttpClientTransport := http.DefaultTransport.(*http.Transport).Clone()
79+
if proxyFunc != nil {
80+
// Preserve the default proxy (from env vars) when no explicit proxy is configured.
81+
healthCheckHttpClientTransport.Proxy = proxyFunc
82+
}
83+
healthCheckHttpClientTransport.TLSClientConfig = &tls.Config{
84+
InsecureSkipVerify: true,
85+
}
86+
7787
httpClientsFactory = &DefaultHttpClientsFactory{
7888
k8s: k8s,
7989
logger: logger,
8090
systemCertPool: systemCertPool,
91+
proxyFunc: proxyFunc,
92+
healthCheckHttpClient: &http.Client{
93+
Transport: healthCheckHttpClientTransport,
94+
Timeout: 500 * time.Millisecond,
95+
},
8196
}
8297

8398
return nil
@@ -97,13 +112,7 @@ func (h *DefaultHttpClientsFactory) GetHttpClient(ctx context.Context, routingCo
97112
defer h.mu.Unlock()
98113

99114
if h.shouldCreateHttpClient(routingConfig, certsCM) {
100-
h.httpClient = h.createHttpClient(routingConfig, certsCM)
101-
102-
if routingConfig == nil {
103-
h.httpClientProxyConfig = nil
104-
} else {
105-
h.httpClientProxyConfig = routingConfig.ProxyConfig.DeepCopy()
106-
}
115+
h.httpClient = h.createHttpClient(certsCM)
107116

108117
if certsCM == nil {
109118
h.httpClientCertsVersion = ""
@@ -120,9 +129,12 @@ func (h *DefaultHttpClientsFactory) GetHttpClient(ctx context.Context, routingCo
120129
return h.httpClient
121130
}
122131

123-
func (h *DefaultHttpClientsFactory) createHttpClient(routingConfig *controller.RoutingConfig, certsCM *corev1.ConfigMap) *http.Client {
132+
func (h *DefaultHttpClientsFactory) createHttpClient(certsCM *corev1.ConfigMap) *http.Client {
124133
transport := http.DefaultTransport.(*http.Transport).Clone()
125-
transport.Proxy = h.getProxyFunc(routingConfig)
134+
if h.proxyFunc != nil {
135+
// Preserve the default proxy (from env vars) when no explicit proxy is configured.
136+
transport.Proxy = h.proxyFunc
137+
}
126138
transport.TLSClientConfig = &tls.Config{
127139
RootCAs: h.getCaCertPool(certsCM),
128140
}
@@ -140,7 +152,6 @@ func (h *DefaultHttpClientsFactory) shouldCreateHttpClient(routingConfig *contro
140152

141153
var certsVersion string
142154
var configmapRef *controller.ConfigmapReference
143-
var proxyConfig *controller.Proxy
144155

145156
if certsCM != nil {
146157
certsVersion = certsCM.ResourceVersion
@@ -150,88 +161,46 @@ func (h *DefaultHttpClientsFactory) shouldCreateHttpClient(routingConfig *contro
150161
}
151162
}
152163

153-
if routingConfig != nil {
154-
proxyConfig = routingConfig.ProxyConfig
155-
}
156-
157164
return certsVersion != h.httpClientCertsVersion ||
158-
!reflect.DeepEqual(configmapRef, h.httpClientConfigmapRef) ||
159-
!reflect.DeepEqual(proxyConfig, h.httpClientProxyConfig)
165+
!reflect.DeepEqual(configmapRef, h.httpClientConfigmapRef)
160166
}
161167

162-
func (h *DefaultHttpClientsFactory) GetHealthCheckHttpClient(routingConfig *controller.RoutingConfig) *http.Client {
168+
func (h *DefaultHttpClientsFactory) GetHealthCheckHttpClient() *http.Client {
163169
h.mu.RLock()
164-
if !h.shouldCreateHealthCheckHttpClient(routingConfig) {
165-
defer h.mu.RUnlock()
166-
return h.healthCheckHttpClient
167-
}
168-
h.mu.RUnlock()
169-
170-
h.mu.Lock()
171-
defer h.mu.Unlock()
172-
173-
if h.shouldCreateHealthCheckHttpClient(routingConfig) {
174-
h.healthCheckHttpClient = h.createHealthCheckHttpClient(routingConfig)
175-
176-
if routingConfig == nil {
177-
h.healthCheckHttpClientProxyConfig = nil
178-
} else {
179-
h.healthCheckHttpClientProxyConfig = routingConfig.ProxyConfig.DeepCopy()
180-
}
181-
}
170+
defer h.mu.RUnlock()
182171

183172
return h.healthCheckHttpClient
184173
}
185174

186-
func (h *DefaultHttpClientsFactory) shouldCreateHealthCheckHttpClient(routingConfig *controller.RoutingConfig) bool {
187-
if h.healthCheckHttpClient == nil {
188-
return true
189-
}
190-
191-
var proxyConfig *controller.Proxy
192-
193-
if routingConfig != nil {
194-
proxyConfig = routingConfig.ProxyConfig
195-
}
196-
197-
return !reflect.DeepEqual(proxyConfig, h.healthCheckHttpClientProxyConfig)
198-
}
199-
200-
func (h *DefaultHttpClientsFactory) createHealthCheckHttpClient(routingConfig *controller.RoutingConfig) *http.Client {
201-
transport := http.DefaultTransport.(*http.Transport).Clone()
202-
transport.Proxy = h.getProxyFunc(routingConfig)
203-
transport.TLSClientConfig = &tls.Config{
204-
InsecureSkipVerify: true,
205-
}
206-
207-
return &http.Client{
208-
Transport: transport,
209-
Timeout: 500 * time.Millisecond,
210-
}
211-
}
212-
213-
// getProxyFunc returns a proxy function based on the proxy settings in routingConfig.
175+
// getProxyFunc returns a proxy function based on the global operator configuration.
214176
// Returns nil if no proxy is configured; a nil proxy func causes the HTTP transport to
215177
// use the default proxy settings from environment variables.
216-
func (h *DefaultHttpClientsFactory) getProxyFunc(routingConfig *controller.RoutingConfig) func(*http.Request) (*url.URL, error) {
217-
if routingConfig == nil || routingConfig.ProxyConfig == nil {
218-
return nil
219-
}
178+
func getProxyFunc() func(*http.Request) (*url.URL, error) {
179+
globalConfig := config.GetGlobalConfig()
220180

221-
proxyConfig := httpproxy.Config{}
222-
if routingConfig.ProxyConfig.HttpProxy != nil {
223-
proxyConfig.HTTPProxy = *routingConfig.ProxyConfig.HttpProxy
224-
}
225-
if routingConfig.ProxyConfig.HttpsProxy != nil {
226-
proxyConfig.HTTPSProxy = *routingConfig.ProxyConfig.HttpsProxy
227-
}
228-
if routingConfig.ProxyConfig.NoProxy != nil {
229-
proxyConfig.NoProxy = *routingConfig.ProxyConfig.NoProxy
230-
}
181+
if globalConfig.Routing != nil && globalConfig.Routing.ProxyConfig != nil {
182+
proxyConf := httpproxy.Config{}
183+
if globalConfig.Routing.ProxyConfig.HttpProxy != nil {
184+
proxyConf.HTTPProxy = *globalConfig.Routing.ProxyConfig.HttpProxy
185+
}
186+
if globalConfig.Routing.ProxyConfig.HttpsProxy != nil {
187+
proxyConf.HTTPSProxy = *globalConfig.Routing.ProxyConfig.HttpsProxy
188+
}
189+
if globalConfig.Routing.ProxyConfig.NoProxy != nil {
190+
proxyConf.NoProxy = *globalConfig.Routing.ProxyConfig.NoProxy
191+
}
192+
193+
if proxyConf.HTTPProxy == "" && proxyConf.HTTPSProxy == "" {
194+
return nil
195+
}
231196

232-
return func(req *http.Request) (*url.URL, error) {
233-
return proxyConfig.ProxyFunc()(req.URL)
197+
proxyFn := proxyConf.ProxyFunc()
198+
return func(req *http.Request) (*url.URL, error) {
199+
return proxyFn(req.URL)
200+
}
234201
}
202+
203+
return nil
235204
}
236205

237206
// getCaCertPool returns a CA cert pool that includes system certs and any additional certs from the ConfigMap.

0 commit comments

Comments
 (0)