Skip to content

Commit ea5e3bc

Browse files
committed
Add http transport for cincinnati to enable proxy
- Modified Cincinnati client to accept a url.URL so that a https proxy can be set - Created new function getHTTPSProxyURL() that retrieves the proxy config, creates the url.URL and returns the url ptr. - Modified tests to include proxy lister - Added ProxyLister to Operator struct, modified New() - Modified start.go for ProxyLister operator struct change
1 parent 08cac1c commit ea5e3bc

File tree

6 files changed

+104
-19
lines changed

6 files changed

+104
-19
lines changed

pkg/cincinnati/cincinnati.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@ const (
2020
// Client is a Cincinnati client which can be used to fetch update graphs from
2121
// an upstream Cincinnati stack.
2222
type Client struct {
23-
id uuid.UUID
23+
id uuid.UUID
24+
proxyURL *url.URL
2425
}
2526

2627
// NewClient creates a new Cincinnati client with the given client identifier.
27-
func NewClient(id uuid.UUID) Client {
28-
return Client{id: id}
28+
func NewClient(id uuid.UUID, proxyURL *url.URL) Client {
29+
return Client{id: id, proxyURL: proxyURL}
2930
}
3031

3132
// Update is a single node from the update graph.
@@ -39,6 +40,7 @@ type Update node
3940
// the current version and their payloads indicate from where the actual update
4041
// image can be downloaded.
4142
func (c Client) GetUpdates(upstream string, channel string, version semver.Version) ([]Update, error) {
43+
transport := http.Transport{}
4244
// Prepare parametrized cincinnati query.
4345
cincinnatiURL, err := url.Parse(upstream)
4446
if err != nil {
@@ -57,7 +59,11 @@ func (c Client) GetUpdates(upstream string, channel string, version semver.Versi
5759
}
5860
req.Header.Add("Accept", GraphMediaType)
5961

60-
client := http.Client{}
62+
if c.proxyURL != nil {
63+
transport.Proxy = http.ProxyURL(c.proxyURL)
64+
}
65+
66+
client := http.Client{Transport: &transport}
6167
resp, err := client.Do(req)
6268
if err != nil {
6369
return nil, err

pkg/cincinnati/cincinnati_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import (
1010
"testing"
1111

1212
"github.com/blang/semver"
13-
_ "k8s.io/klog" // integration tests set glog flags.
1413
"github.com/google/uuid"
14+
_ "k8s.io/klog" // integration tests set glog flags.
1515
)
1616

1717
func TestGetUpdates(t *testing.T) {
@@ -120,8 +120,9 @@ func TestGetUpdates(t *testing.T) {
120120

121121
ts := httptest.NewServer(http.HandlerFunc(handler))
122122
defer ts.Close()
123+
var proxyURL *url.URL
123124

124-
c := NewClient(clientID)
125+
c := NewClient(clientID, proxyURL)
125126

126127
updates, err := c.GetUpdates(ts.URL, channelName, semver.MustParse(test.version))
127128
if test.err == "" {

pkg/cvo/availableupdates.go

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ import (
44
"fmt"
55
"time"
66

7+
"net/url"
8+
79
"github.com/blang/semver"
8-
"k8s.io/klog"
910
"github.com/google/uuid"
11+
"k8s.io/apimachinery/pkg/api/errors"
12+
"k8s.io/klog"
1013

1114
"k8s.io/apimachinery/pkg/api/equality"
1215
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -36,7 +39,12 @@ func (optr *Operator) syncAvailableUpdates(config *configv1.ClusterVersion) erro
3639
return nil
3740
}
3841

39-
updates, condition := calculateAvailableUpdatesStatus(string(config.Spec.ClusterID), upstream, channel, optr.releaseVersion)
42+
proxyURL, err := optr.getHTTPSProxyURL()
43+
if err != nil {
44+
return err
45+
}
46+
47+
updates, condition := calculateAvailableUpdatesStatus(string(config.Spec.ClusterID), proxyURL, upstream, channel, optr.releaseVersion)
4048

4149
if usedDefaultUpstream {
4250
upstream = ""
@@ -103,7 +111,7 @@ func (optr *Operator) getAvailableUpdates() *availableUpdates {
103111
return optr.availableUpdates
104112
}
105113

106-
func calculateAvailableUpdatesStatus(clusterID, upstream, channel, version string) ([]configv1.Update, configv1.ClusterOperatorStatusCondition) {
114+
func calculateAvailableUpdatesStatus(clusterID string, proxyURL *url.URL, upstream, channel, version string) ([]configv1.Update, configv1.ClusterOperatorStatusCondition) {
107115
if len(upstream) == 0 {
108116
return nil, configv1.ClusterOperatorStatusCondition{
109117
Type: configv1.RetrievedUpdates, Status: configv1.ConditionFalse, Reason: "NoUpstream",
@@ -134,7 +142,7 @@ func calculateAvailableUpdatesStatus(clusterID, upstream, channel, version strin
134142
}
135143
}
136144

137-
updates, err := checkForUpdate(clusterID, upstream, channel, currentVersion)
145+
updates, err := checkForUpdate(clusterID, proxyURL, upstream, channel, currentVersion)
138146
if err != nil {
139147
klog.V(2).Infof("Upstream server %s could not return available updates: %v", upstream, err)
140148
return nil, configv1.ClusterOperatorStatusCondition{
@@ -159,13 +167,38 @@ func calculateAvailableUpdatesStatus(clusterID, upstream, channel, version strin
159167
}
160168
}
161169

162-
func checkForUpdate(clusterID, upstream, channel string, currentVersion semver.Version) ([]cincinnati.Update, error) {
170+
func checkForUpdate(clusterID string, proxyURL *url.URL, upstream, channel string, currentVersion semver.Version) ([]cincinnati.Update, error) {
163171
uuid, err := uuid.Parse(string(clusterID))
164172
if err != nil {
165173
return nil, err
166174
}
175+
167176
if len(upstream) == 0 {
168177
return nil, fmt.Errorf("no upstream URL set for cluster version")
169178
}
170-
return cincinnati.NewClient(uuid).GetUpdates(upstream, channel, currentVersion)
179+
return cincinnati.NewClient(uuid, proxyURL).GetUpdates(upstream, channel, currentVersion)
180+
}
181+
182+
// getHTTPSProxyURL returns a url.URL object for the configured
183+
// https proxy only. It can be nil if does not exist or there is an error.
184+
func (optr *Operator) getHTTPSProxyURL() (*url.URL, error) {
185+
proxy, err := optr.proxyLister.Get("cluster")
186+
187+
if errors.IsNotFound(err) {
188+
return nil, nil
189+
}
190+
if err != nil {
191+
return nil, err
192+
}
193+
194+
if &proxy.Spec != nil {
195+
if proxy.Spec.HTTPSProxy != "" {
196+
proxyURL, err := url.Parse(proxy.Spec.HTTPSProxy)
197+
if err != nil {
198+
return nil, err
199+
}
200+
return proxyURL, nil
201+
}
202+
}
203+
return nil, nil
171204
}

pkg/cvo/cvo.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import (
1010
"github.com/openshift/cluster-version-operator/pkg/verify"
1111

1212
"github.com/blang/semver"
13-
"k8s.io/klog"
1413
"github.com/google/uuid"
14+
"k8s.io/klog"
1515

1616
corev1 "k8s.io/api/core/v1"
1717
apierrors "k8s.io/apimachinery/pkg/api/errors"
@@ -101,6 +101,7 @@ type Operator struct {
101101

102102
cvLister configlistersv1.ClusterVersionLister
103103
coLister configlistersv1.ClusterOperatorLister
104+
proxyLister configlistersv1.ProxyLister
104105
cacheSynced []cache.InformerSynced
105106

106107
// queue tracks applying updates to a cluster.
@@ -135,6 +136,7 @@ func New(
135136
minimumInterval time.Duration,
136137
cvInformer configinformersv1.ClusterVersionInformer,
137138
coInformer configinformersv1.ClusterOperatorInformer,
139+
proxyInformer configinformersv1.ProxyInformer,
138140
client clientset.Interface,
139141
kubeClient kubernetes.Interface,
140142
enableMetrics bool,
@@ -162,6 +164,9 @@ func New(
162164
availableUpdatesQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "availableupdates"),
163165
}
164166

167+
optr.proxyLister = proxyInformer.Lister()
168+
proxyInformer.Informer().AddEventHandler(optr.eventHandler())
169+
165170
cvInformer.Informer().AddEventHandler(optr.eventHandler())
166171

167172
optr.coLister = coInformer.Lister()

pkg/cvo/cvo_test.go

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"time"
1212

1313
"github.com/davecgh/go-spew/spew"
14-
"k8s.io/klog"
1514
"github.com/google/uuid"
1615
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
1716
apiextclientv1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
@@ -27,6 +26,7 @@ import (
2726
"k8s.io/client-go/rest"
2827
ktesting "k8s.io/client-go/testing"
2928
"k8s.io/client-go/util/workqueue"
29+
"k8s.io/klog"
3030

3131
configv1 "github.com/openshift/api/config/v1"
3232
clientset "github.com/openshift/client-go/config/clientset/versioned"
@@ -42,15 +42,35 @@ var (
4242
defaultCompletionTime = metav1.Time{Time: time.Unix(2, 0)}
4343
)
4444

45+
type clientProxyLister struct {
46+
client clientset.Interface
47+
}
48+
49+
func (c *clientProxyLister) Get(name string) (*configv1.Proxy, error) {
50+
return c.client.ConfigV1().Proxies().Get(name, metav1.GetOptions{})
51+
}
52+
53+
func (c *clientProxyLister) List(selector labels.Selector) (ret []*configv1.Proxy, err error) {
54+
list, err := c.client.ConfigV1().Proxies().List(metav1.ListOptions{LabelSelector: selector.String()})
55+
if err != nil {
56+
return nil, err
57+
}
58+
var items []*configv1.Proxy
59+
for i := range list.Items {
60+
items = append(items, &list.Items[i])
61+
}
62+
return items, nil
63+
}
64+
4565
type clientCVLister struct {
4666
client clientset.Interface
4767
}
4868

4969
func (c *clientCVLister) Get(name string) (*configv1.ClusterVersion, error) {
50-
return c.client.Config().ClusterVersions().Get(name, metav1.GetOptions{})
70+
return c.client.ConfigV1().ClusterVersions().Get(name, metav1.GetOptions{})
5171
}
5272
func (c *clientCVLister) List(selector labels.Selector) (ret []*configv1.ClusterVersion, err error) {
53-
list, err := c.client.Config().ClusterVersions().List(metav1.ListOptions{LabelSelector: selector.String()})
73+
list, err := c.client.ConfigV1().ClusterVersions().List(metav1.ListOptions{LabelSelector: selector.String()})
5474
if err != nil {
5575
return nil, err
5676
}
@@ -61,15 +81,32 @@ func (c *clientCVLister) List(selector labels.Selector) (ret []*configv1.Cluster
6181
return items, nil
6282
}
6383

84+
type proxyLister struct {
85+
Err error
86+
Items []*configv1.Proxy
87+
}
88+
89+
func (r *proxyLister) List(selector labels.Selector) (ret []*configv1.Proxy, err error) {
90+
return r.Items, r.Err
91+
}
92+
func (r *proxyLister) Get(name string) (*configv1.Proxy, error) {
93+
for _, s := range r.Items {
94+
if s.Name == name {
95+
return s, nil
96+
}
97+
}
98+
return nil, errors.NewNotFound(schema.GroupResource{}, name)
99+
}
100+
64101
type clientCOLister struct {
65102
client clientset.Interface
66103
}
67104

68105
func (c *clientCOLister) Get(name string) (*configv1.ClusterOperator, error) {
69-
return c.client.Config().ClusterOperators().Get(name, metav1.GetOptions{})
106+
return c.client.ConfigV1().ClusterOperators().Get(name, metav1.GetOptions{})
70107
}
71108
func (c *clientCOLister) List(selector labels.Selector) (ret []*configv1.ClusterOperator, err error) {
72-
list, err := c.client.Config().ClusterOperators().List(metav1.ListOptions{LabelSelector: selector.String()})
109+
list, err := c.client.ConfigV1().ClusterOperators().List(metav1.ListOptions{LabelSelector: selector.String()})
73110
if err != nil {
74111
return nil, err
75112
}
@@ -1959,6 +1996,7 @@ func TestOperator_sync(t *testing.T) {
19591996
if tt.init != nil {
19601997
tt.init(optr)
19611998
}
1999+
optr.proxyLister = &clientProxyLister{client: optr.client}
19622000
optr.cvLister = &clientCVLister{client: optr.client}
19632001
optr.coLister = &clientCOLister{client: optr.client}
19642002
if optr.configSync == nil {
@@ -2332,6 +2370,7 @@ func TestOperator_availableUpdatesSync(t *testing.T) {
23322370
t.Run(tt.name, func(t *testing.T) {
23332371
optr := tt.optr
23342372
optr.queue = workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter())
2373+
optr.proxyLister = &clientProxyLister{client: optr.client}
23352374
optr.coLister = &clientCOLister{client: optr.client}
23362375
optr.cvLister = &clientCVLister{client: optr.client}
23372376

pkg/start/start.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ import (
1313
"syscall"
1414
"time"
1515

16-
"k8s.io/klog"
1716
"github.com/google/uuid"
1817
"github.com/prometheus/client_golang/prometheus/promhttp"
18+
"k8s.io/klog"
1919

2020
v1 "k8s.io/api/core/v1"
2121
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -325,6 +325,7 @@ func (o *Options) NewControllerContext(cb *ClientBuilder) *Context {
325325
resyncPeriod(o.ResyncInterval)(),
326326
cvInformer.Config().V1().ClusterVersions(),
327327
sharedInformers.Config().V1().ClusterOperators(),
328+
sharedInformers.Config().V1().Proxies(),
328329
cb.ClientOrDie(o.Namespace),
329330
cb.KubeClientOrDie(o.Namespace, useProtobuf),
330331
o.EnableMetrics,

0 commit comments

Comments
 (0)