Skip to content

Commit 756afe8

Browse files
committed
Add support for .spec.proxySecretRef for gcp provider of Bucket API
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
1 parent 5de61f0 commit 756afe8

File tree

5 files changed

+67
-29
lines changed

5 files changed

+67
-29
lines changed

internal/controller/bucket_controller.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ func (r *BucketReconciler) reconcileSource(ctx context.Context, sp *patch.Serial
448448
conditions.MarkTrue(obj, sourcev1.FetchFailedCondition, e.Reason, e.Error())
449449
return sreconcile.ResultEmpty, e
450450
}
451-
if provider, err = gcp.NewClient(ctx, secret); err != nil {
451+
if provider, err = gcp.NewClient(ctx, obj, secret, proxyURL); err != nil {
452452
e := serror.NewGeneric(err, "ClientError")
453453
conditions.MarkTrue(obj, sourcev1.FetchFailedCondition, e.Reason, e.Error())
454454
return sreconcile.ResultEmpty, e

pkg/gcp/gcp.go

+26-14
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,12 @@ package gcp
1818

1919
import (
2020
"context"
21+
"crypto/tls"
2122
"errors"
2223
"fmt"
2324
"io"
25+
"net/http"
26+
"net/url"
2427
"os"
2528
"path/filepath"
2629

@@ -30,6 +33,8 @@ import (
3033
"google.golang.org/api/option"
3134
corev1 "k8s.io/api/core/v1"
3235
ctrl "sigs.k8s.io/controller-runtime"
36+
37+
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
3338
)
3439

3540
var (
@@ -48,24 +53,31 @@ type GCSClient struct {
4853
*gcpstorage.Client
4954
}
5055

51-
// NewClient creates a new GCP storage client. The Client will automatically look for the Google Application
56+
// NewClient creates a new GCP storage client. The Client will automatically look for the Google Application
5257
// Credential environment variable or look for the Google Application Credential file.
53-
func NewClient(ctx context.Context, secret *corev1.Secret) (*GCSClient, error) {
54-
c := &GCSClient{}
58+
func NewClient(ctx context.Context, bucket *sourcev1.Bucket,
59+
secret *corev1.Secret, proxyURL *url.URL) (*GCSClient, error) {
60+
var opts []option.ClientOption
61+
5562
if secret != nil {
56-
client, err := gcpstorage.NewClient(ctx, option.WithCredentialsJSON(secret.Data["serviceaccount"]))
57-
if err != nil {
58-
return nil, err
59-
}
60-
c.Client = client
61-
} else {
62-
client, err := gcpstorage.NewClient(ctx)
63-
if err != nil {
64-
return nil, err
63+
opts = append(opts, option.WithCredentialsJSON(secret.Data["serviceaccount"]))
64+
}
65+
66+
if proxyURL != nil {
67+
transport := http.DefaultTransport.(*http.Transport).Clone()
68+
transport.Proxy = http.ProxyURL(proxyURL)
69+
if bucket.Spec.Insecure {
70+
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
6571
}
66-
c.Client = client
72+
opts = append(opts, option.WithHTTPClient(&http.Client{Transport: transport}))
6773
}
68-
return c, nil
74+
75+
client, err := gcpstorage.NewClient(ctx, opts...)
76+
if err != nil {
77+
return nil, err
78+
}
79+
80+
return &GCSClient{Client: client}, nil
6981
}
7082

7183
// ValidateSecret validates the credential secret. The provided Secret may

pkg/gcp/gcp_test.go

+31-12
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,14 @@ import (
3333

3434
gcpstorage "cloud.google.com/go/storage"
3535
"google.golang.org/api/googleapi"
36+
"google.golang.org/api/option"
3637
raw "google.golang.org/api/storage/v1"
3738
"gotest.tools/assert"
3839
corev1 "k8s.io/api/core/v1"
3940
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
4041

41-
"google.golang.org/api/option"
42+
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
43+
pkgtesting "github.com/fluxcd/source-controller/pkg/testing"
4244
)
4345

4446
const (
@@ -49,11 +51,12 @@ const (
4951
)
5052

5153
var (
52-
hc *http.Client
53-
client *gcpstorage.Client
54-
close func()
55-
err error
56-
secret = corev1.Secret{
54+
hc *http.Client
55+
serverAddr string
56+
client *gcpstorage.Client
57+
close func()
58+
err error
59+
secret = corev1.Secret{
5760
ObjectMeta: v1.ObjectMeta{
5861
Name: "gcp-secret",
5962
Namespace: "default",
@@ -76,7 +79,7 @@ var (
7679
)
7780

7881
func TestMain(m *testing.M) {
79-
hc, close = newTestServer(func(w http.ResponseWriter, r *http.Request) {
82+
hc, serverAddr, close = newTestServer(func(w http.ResponseWriter, r *http.Request) {
8083
io.Copy(io.Discard, r.Body)
8184
switch r.RequestURI {
8285
case fmt.Sprintf("/storage/v1/b/%s?alt=json&prettyPrint=false&projection=full", bucketName):
@@ -140,7 +143,7 @@ func TestMain(m *testing.M) {
140143
}
141144

142145
func TestNewClientWithSecretErr(t *testing.T) {
143-
gcpClient, err := NewClient(context.Background(), secret.DeepCopy())
146+
gcpClient, err := NewClient(context.Background(), nil, secret.DeepCopy(), nil)
144147
t.Log(err)
145148
assert.Error(t, err, "dialing: invalid character 'e' looking for beginning of value")
146149
assert.Assert(t, gcpClient == nil)
@@ -216,6 +219,21 @@ func TestFGetObject(t *testing.T) {
216219
assert.Equal(t, etag, objectEtag)
217220
}
218221

222+
func TestNewClientAndFGetObjectWithProxy(t *testing.T) {
223+
proxyURL, closeProxy := pkgtesting.NewHTTPProxy(t, serverAddr)
224+
defer closeProxy()
225+
bucket := &sourcev1.Bucket{Spec: sourcev1.BucketSpec{Insecure: true}} // needed because the server is a mock
226+
client, err := NewClient(context.Background(), bucket, secret.DeepCopy(), proxyURL)
227+
assert.NilError(t, err)
228+
tempDir := t.TempDir()
229+
localPath := filepath.Join(tempDir, objectName)
230+
etag, err := client.FGetObject(context.Background(), bucketName, objectName, localPath)
231+
if err != io.EOF {
232+
assert.NilError(t, err)
233+
}
234+
assert.Equal(t, etag, objectEtag)
235+
}
236+
219237
func TestFGetObjectNotExists(t *testing.T) {
220238
object := "notexists.txt"
221239
tempDir := t.TempDir()
@@ -272,16 +290,17 @@ func TestValidateSecret(t *testing.T) {
272290
}
273291
}
274292

275-
func newTestServer(handler func(w http.ResponseWriter, r *http.Request)) (*http.Client, func()) {
276-
ts := httptest.NewTLSServer(http.HandlerFunc(handler))
293+
func newTestServer(handler http.HandlerFunc) (*http.Client, string, func()) {
294+
ts := httptest.NewTLSServer(handler)
295+
serverAddr := ts.Listener.Addr().String()
277296
tlsConf := &tls.Config{InsecureSkipVerify: true}
278297
tr := &http.Transport{
279298
TLSClientConfig: tlsConf,
280299
DialTLS: func(netw, addr string) (net.Conn, error) {
281-
return tls.Dial("tcp", ts.Listener.Addr().String(), tlsConf)
300+
return tls.Dial("tcp", serverAddr, tlsConf)
282301
},
283302
}
284-
return &http.Client{Transport: tr}, func() {
303+
return &http.Client{Transport: tr}, serverAddr, func() {
285304
tr.CloseIdleConnections()
286305
ts.Close()
287306
}

pkg/minio/minio_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ func TestFGetObject(t *testing.T) {
236236
}
237237

238238
func TestNewClientAndFGetObjectWithProxy(t *testing.T) {
239-
proxyURL, closeProxy := pkgtesting.NewHTTPProxy(t)
239+
proxyURL, closeProxy := pkgtesting.NewHTTPProxy(t, "")
240240
defer closeProxy()
241241
minioClient, err := NewClient(bucketStub(bucket, testMinioAddress), secret.DeepCopy(), testTLSConfig, proxyURL)
242242
assert.NilError(t, err)

pkg/testing/http_proxy.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,20 @@ import (
1313

1414
// NewHTTPProxy starts an HTTP proxy server in a random port and returns the
1515
// URL of the proxy server and a function to stop the server.
16-
func NewHTTPProxy(t *testing.T) (*url.URL, func()) {
16+
// If httpsTargetAddr is not empty, the proxy server will handle CONNECT
17+
// HTTPS requests to that address.
18+
func NewHTTPProxy(t *testing.T, httpsTargetAddr string) (*url.URL, func()) {
1719
listener, err := net.Listen("tcp", ":0")
1820
assert.NilError(t, err, "could not start proxy server")
1921

2022
addr := listener.Addr().String()
2123
proxy := goproxy.NewProxyHttpServer()
2224
proxy.Verbose = true
25+
if httpsTargetAddr != "" {
26+
proxy.OnRequest().HandleConnectFunc(func(host string, ctx *goproxy.ProxyCtx) (*goproxy.ConnectAction, string) {
27+
return goproxy.OkConnect, httpsTargetAddr
28+
})
29+
}
2330
server := &http.Server{
2431
Addr: addr,
2532
Handler: proxy,

0 commit comments

Comments
 (0)