diff --git a/controllers/cloudflare_api_test.go b/controllers/cloudflare_api_test.go new file mode 100644 index 0000000..e9680ae --- /dev/null +++ b/controllers/cloudflare_api_test.go @@ -0,0 +1,195 @@ +package controllers_test + +import ( + "context" + "encoding/json" + "fmt" + "strings" + "testing" + "time" + + "github.com/adyanth/cloudflare-operator/controllers" + cf "github.com/cloudflare/cloudflare-go" + "github.com/go-logr/logr" + "github.com/stretchr/testify/assert" +) + +type credfile struct { + AccountTag string + TunnelID string + TunnelName string + TunnelSecret string +} + +type cfGoClient struct { + accountID string + accountName string + tunnelName string + tunnelID string + tunnelSecret string + domain string + records map[string]cf.DNSRecord + + cleanedUp bool + deleted bool +} + +func (c *cfGoClient) CreateTunnel(ctx context.Context, rc *cf.ResourceContainer, params cf.TunnelCreateParams) (cf.Tunnel, error) { + if params.Name != c.tunnelName { + return cf.Tunnel{}, fmt.Errorf("Invalid tunnel name") + } + now := time.Now() + c.tunnelSecret = params.Secret + return cf.Tunnel{ + ID: c.tunnelID, + Name: c.tunnelName, + Secret: params.Secret, + CreatedAt: &now, + RemoteConfig: false, + }, nil +} + +func (c *cfGoClient) CleanupTunnelConnections(ctx context.Context, rc *cf.ResourceContainer, tunnelID string) error { + c.cleanedUp = true + return nil +} + +func (c *cfGoClient) DeleteTunnel(ctx context.Context, rc *cf.ResourceContainer, tunnelID string) error { + c.deleted = true + return nil +} + +func (c *cfGoClient) Account(ctx context.Context, accountID string) (cf.Account, cf.ResultInfo, error) { + return cf.Account{ + ID: c.accountID, + Name: c.accountName, + Type: "", + CreatedOn: time.Now(), + }, cf.ResultInfo{}, nil +} + +func (c *cfGoClient) Accounts(ctx context.Context, params cf.AccountsListParams) ([]cf.Account, cf.ResultInfo, error) { + if params.Name == c.accountName { + return []cf.Account{{ + ID: c.accountID, + Name: c.accountName, + Type: "", + CreatedOn: time.Now(), + }}, cf.ResultInfo{}, nil + } + return []cf.Account{}, cf.ResultInfo{}, fmt.Errorf("No such account ID") +} + +func (c *cfGoClient) GetTunnel(ctx context.Context, rc *cf.ResourceContainer, tunnelID string) (cf.Tunnel, error) { + now := time.Now() + return cf.Tunnel{ + ID: c.tunnelID, + Name: c.tunnelName, + Secret: c.tunnelSecret, + CreatedAt: &now, + RemoteConfig: false, + }, nil +} + +func (c *cfGoClient) ListTunnels(ctx context.Context, rc *cf.ResourceContainer, params cf.TunnelListParams) ([]cf.Tunnel, *cf.ResultInfo, error) { + if params.Name == c.tunnelName { + now := time.Now() + return []cf.Tunnel{{ + ID: c.tunnelID, + Name: c.tunnelName, + Secret: c.tunnelSecret, + CreatedAt: &now, + RemoteConfig: false, + }}, &cf.ResultInfo{}, nil + } + return []cf.Tunnel{}, &cf.ResultInfo{}, fmt.Errorf("No such tunnel") +} + +func (c *cfGoClient) ListZones(ctx context.Context, z ...string) ([]cf.Zone, error) { + if strings.HasSuffix(z[0], c.domain) { + return []cf.Zone{{ + ID: "zone-id", + Name: "zone-name", + }}, nil + } + return []cf.Zone{}, fmt.Errorf("No such zone") +} + +func (c *cfGoClient) UpdateDNSRecord(ctx context.Context, rc *cf.ResourceContainer, params cf.UpdateDNSRecordParams) error { + if rec, ok := c.records[params.ID]; ok && (params.Name == "" || params.Name == rec.Name) && params.Type == rec.Type { + rec.Content = params.Content + c.records[params.ID] = rec + return nil + } + return fmt.Errorf("Error updating DNS") +} + +func (c *cfGoClient) CreateDNSRecord(ctx context.Context, rc *cf.ResourceContainer, params cf.CreateDNSRecordParams) (*cf.DNSRecordResponse, error) { + id := fmt.Sprint(len(c.records)) + c.records[id] = cf.DNSRecord{ + ID: id, + Type: params.Type, + Name: params.Name, + Content: params.Content, + } + return &cf.DNSRecordResponse{ + Result: c.records[id], + }, nil +} + +func (c *cfGoClient) DeleteDNSRecord(ctx context.Context, rc *cf.ResourceContainer, recordID string) error { + if _, ok := c.records[recordID]; ok { + delete(c.records, recordID) + return nil + } + return fmt.Errorf("no record to delete") +} + +func (c *cfGoClient) ListDNSRecords(ctx context.Context, rc *cf.ResourceContainer, params cf.ListDNSRecordsParams) ([]cf.DNSRecord, *cf.ResultInfo, error) { + recs := []cf.DNSRecord{} + for _, v := range c.records { + if params.Type == v.Type && (params.Name == v.Name || params.Content == v.Comment) { + recs = append(recs, v) + } + } + return recs, &cf.ResultInfo{}, nil +} + +func setup() (*controllers.CloudflareAPI, *cfGoClient) { + log, _ := logr.FromContext(context.Background()) + cc := cfGoClient{ + accountName: "account-name", + accountID: "account-id", + tunnelName: "tunnel-name", + tunnelID: "tunnel-id", + tunnelSecret: "secret", + domain: "domain", + } + return &controllers.CloudflareAPI{ + Log: log, + TunnelName: cc.tunnelName, + TunnelId: cc.tunnelID, + AccountName: cc.accountName, + AccountId: cc.accountID, + Domain: cc.domain, + APIToken: "api-token", + APIKey: "api-key", + APIEmail: "api-email", + CloudflareClient: &cc, + }, &cc +} + +func TestCreateCloudflareTunnel(t *testing.T) { + c, cc := setup() + id, creds, err := c.CreateCloudflareTunnel() + if assert.NoError(t, err, "expected no error") { + assert.Equal(t, c.TunnelId, id) + v := credfile{} + if assert.NoError(t, json.Unmarshal([]byte(creds), &v)) { + assert.Equal(t, cc.accountID, v.AccountTag) + assert.Equal(t, cc.tunnelID, v.TunnelID) + assert.Equal(t, cc.tunnelName, v.TunnelName) + assert.Equal(t, cc.tunnelSecret, v.TunnelSecret) + } + } +} diff --git a/go.mod b/go.mod index f7244ad..fd3c47e 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/go-logr/logr v1.2.3 github.com/onsi/ginkgo v1.16.5 github.com/onsi/gomega v1.19.0 + github.com/stretchr/testify v1.8.2 gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.25.0 k8s.io/apimachinery v0.25.0 @@ -15,7 +16,6 @@ require ( ) require ( - 9fans.net/go v0.0.0-20181112161441-237454027057 // indirect cloud.google.com/go v0.97.0 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect github.com/Azure/go-autorest/autorest v0.11.27 // indirect @@ -56,24 +56,22 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nxadm/tail v1.4.8 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_golang v1.12.2 // indirect github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect - github.com/rogpeppe/godef v1.1.2 // indirect github.com/spf13/pflag v1.0.5 // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.21.0 // indirect golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect - golang.org/x/mod v0.8.0 // indirect golang.org/x/net v0.8.0 // indirect golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect golang.org/x/sys v0.6.0 // indirect golang.org/x/term v0.6.0 // indirect golang.org/x/text v0.8.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.6.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.0 // indirect diff --git a/go.sum b/go.sum index 5df1cdd..81fb052 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,3 @@ -9fans.net/go v0.0.0-20181112161441-237454027057 h1:OcHlKWkAMJEF1ndWLGxp5dnJQkYM/YImUOvsBoz6h5E= -9fans.net/go v0.0.0-20181112161441-237454027057/go.mod h1:diCsxrliIURU9xsYtjCp5AbpQKqdhKmf0ujWDUSkfoY= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -337,8 +335,6 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= -github.com/rogpeppe/godef v1.1.2 h1:c5mCx0EcCORJOdVMREX7Lgh1raTxAHFmOfXdEB9u8Jw= -github.com/rogpeppe/godef v1.1.2/go.mod h1:WtY9A/ovuQ+UakAJ1/CEqwwulX/WJjb2kgkokCHi/GY= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= @@ -349,13 +345,18 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -424,8 +425,6 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -609,7 +608,6 @@ golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapK golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200226224502-204d844ad48d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= @@ -635,8 +633,6 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=