Skip to content

Commit 551ba1d

Browse files
committed
Add support for .spec.proxySecretRef for gcp provider of Bucket API
Signed-off-by: Matheus Pimenta <matheuscscp@gmail.com>
1 parent 95ee307 commit 551ba1d

File tree

5 files changed

+69
-30
lines changed

5 files changed

+69
-30
lines changed

internal/controller/bucket_controller.go

Lines changed: 1 addition & 1 deletion
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

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import (
2121
"errors"
2222
"fmt"
2323
"io"
24+
"net/http"
25+
"net/url"
2426
"os"
2527
"path/filepath"
2628

@@ -30,6 +32,8 @@ import (
3032
"google.golang.org/api/option"
3133
corev1 "k8s.io/api/core/v1"
3234
ctrl "sigs.k8s.io/controller-runtime"
35+
36+
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
3337
)
3438

3539
var (
@@ -48,24 +52,28 @@ type GCSClient struct {
4852
*gcpstorage.Client
4953
}
5054

51-
// NewClient creates a new GCP storage client. The Client will automatically look for the Google Application
55+
// NewClient creates a new GCP storage client. The Client will automatically look for the Google Application
5256
// 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{}
57+
func NewClient(ctx context.Context, bucket *sourcev1.Bucket,
58+
secret *corev1.Secret, proxyURL *url.URL) (*GCSClient, error) {
59+
var opts []option.ClientOption
60+
5561
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
65-
}
66-
c.Client = client
62+
opts = append(opts, option.WithCredentialsJSON(secret.Data["serviceaccount"]))
6763
}
68-
return c, nil
64+
65+
if proxyURL != nil {
66+
transport := http.DefaultTransport.(*http.Transport).Clone()
67+
transport.Proxy = http.ProxyURL(proxyURL)
68+
opts = append(opts, option.WithHTTPClient(&http.Client{Transport: transport}))
69+
}
70+
71+
client, err := gcpstorage.NewClient(ctx, opts...)
72+
if err != nil {
73+
return nil, err
74+
}
75+
76+
return &GCSClient{Client: client}, nil
6977
}
7078

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

pkg/gcp/gcp_test.go

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,13 @@ 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+
pkgtesting "github.com/fluxcd/source-controller/pkg/testing"
4243
)
4344

4445
const (
@@ -49,11 +50,12 @@ const (
4950
)
5051

5152
var (
52-
hc *http.Client
53-
client *gcpstorage.Client
54-
close func()
55-
err error
56-
secret = corev1.Secret{
53+
hc *http.Client
54+
serverAddr string
55+
client *gcpstorage.Client
56+
close func()
57+
err error
58+
secret = corev1.Secret{
5759
ObjectMeta: v1.ObjectMeta{
5860
Name: "gcp-secret",
5961
Namespace: "default",
@@ -76,7 +78,7 @@ var (
7678
)
7779

7880
func TestMain(m *testing.M) {
79-
hc, close = newTestServer(func(w http.ResponseWriter, r *http.Request) {
81+
hc, serverAddr, close = newTestServer(func(w http.ResponseWriter, r *http.Request) {
8082
io.Copy(io.Discard, r.Body)
8183
switch r.RequestURI {
8284
case fmt.Sprintf("/storage/v1/b/%s?alt=json&prettyPrint=false&projection=full", bucketName):
@@ -140,7 +142,7 @@ func TestMain(m *testing.M) {
140142
}
141143

142144
func TestNewClientWithSecretErr(t *testing.T) {
143-
gcpClient, err := NewClient(context.Background(), secret.DeepCopy())
145+
gcpClient, err := NewClient(context.Background(), nil, secret.DeepCopy(), nil)
144146
t.Log(err)
145147
assert.Error(t, err, "dialing: invalid character 'e' looking for beginning of value")
146148
assert.Assert(t, gcpClient == nil)
@@ -216,6 +218,27 @@ func TestFGetObject(t *testing.T) {
216218
assert.Equal(t, etag, objectEtag)
217219
}
218220

221+
func TestNewClientAndFGetObjectWithProxy(t *testing.T) {
222+
proxyURL, closeProxy := pkgtesting.NewHTTPProxy(t, serverAddr)
223+
defer closeProxy()
224+
transport := http.DefaultTransport.(*http.Transport).Clone()
225+
transport.Proxy = http.ProxyURL(proxyURL)
226+
transport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true} // needed because the server is a mock
227+
httpClient := &http.Client{Transport: transport}
228+
client, err := gcpstorage.NewClient(context.Background(), option.WithHTTPClient(httpClient))
229+
assert.NilError(t, err)
230+
gcpClient := &GCSClient{
231+
Client: client,
232+
}
233+
tempDir := t.TempDir()
234+
localPath := filepath.Join(tempDir, objectName)
235+
etag, err := gcpClient.FGetObject(context.Background(), bucketName, objectName, localPath)
236+
if err != io.EOF {
237+
assert.NilError(t, err)
238+
}
239+
assert.Equal(t, etag, objectEtag)
240+
}
241+
219242
func TestFGetObjectNotExists(t *testing.T) {
220243
object := "notexists.txt"
221244
tempDir := t.TempDir()
@@ -272,16 +295,17 @@ func TestValidateSecret(t *testing.T) {
272295
}
273296
}
274297

275-
func newTestServer(handler func(w http.ResponseWriter, r *http.Request)) (*http.Client, func()) {
276-
ts := httptest.NewTLSServer(http.HandlerFunc(handler))
298+
func newTestServer(handler http.HandlerFunc) (*http.Client, string, func()) {
299+
ts := httptest.NewTLSServer(handler)
300+
serverAddr := ts.Listener.Addr().String()
277301
tlsConf := &tls.Config{InsecureSkipVerify: true}
278302
tr := &http.Transport{
279303
TLSClientConfig: tlsConf,
280304
DialTLS: func(netw, addr string) (net.Conn, error) {
281-
return tls.Dial("tcp", ts.Listener.Addr().String(), tlsConf)
305+
return tls.Dial("tcp", serverAddr, tlsConf)
282306
},
283307
}
284-
return &http.Client{Transport: tr}, func() {
308+
return &http.Client{Transport: tr}, serverAddr, func() {
285309
tr.CloseIdleConnections()
286310
ts.Close()
287311
}

pkg/minio/minio_test.go

Lines changed: 1 addition & 1 deletion
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

Lines changed: 8 additions & 1 deletion
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)