Skip to content

Commit 4194aab

Browse files
author
andrey.menzhinskiy
committed
Add cache for the PowerDNS REST API requests
1 parent b26c0eb commit 4194aab

File tree

7 files changed

+101
-27
lines changed

7 files changed

+101
-27
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ website/node_modules
2222
*~
2323
.*.swp
2424
.idea
25+
.vscode
2526
*.iml
2627
*.test
2728
*.iml

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ require (
66
github.com/hashicorp/go-cleanhttp v0.5.1
77
github.com/hashicorp/terraform-plugin-sdk v1.1.0
88
github.com/stretchr/testify v1.3.0
9+
github.com/coocood/freecache v1.1.1
910
)

go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbf
99
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
1010
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
1111
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
12+
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
1213
github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
1314
github.com/agext/levenshtein v1.2.2 h1:0S/Yg6LYmFJ5stwQeRp6EeOcCbj7xiqQSdNelsXvaqE=
1415
github.com/agext/levenshtein v1.2.2/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
@@ -30,8 +31,12 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ
3031
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
3132
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
3233
github.com/bsm/go-vlq v0.0.0-20150828105119-ec6e8d4f5f4e/go.mod h1:N+BjUcTjSxc2mtRGSCPsat1kze3CUtvJN3/jTXlp29k=
34+
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
35+
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
3336
github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
3437
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
38+
github.com/coocood/freecache v1.1.1 h1:uukNF7QKCZEdZ9gAV7WQzvh0SbjwdMF6m3x3rxEkaPc=
39+
github.com/coocood/freecache v1.1.1/go.mod h1:OKrEjkGVoxZhyWAJoeFi5BMLUJm2Tit0kpGkIr7NGYY=
3540
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3641
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
3742
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -168,6 +173,7 @@ github.com/posener/complete v1.2.1 h1:LrvDIY//XNo65Lq84G/akBuMGlawHvGBABv8f/ZN6D
168173
github.com/posener/complete v1.2.1/go.mod h1:6gapUrK/U1TAN7ciCoNRIdVC5sbdBTUh1DKN0g6uH7E=
169174
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
170175
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
176+
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
171177
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
172178
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
173179
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=

powerdns/client.go

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,30 @@ import (
1111
"strconv"
1212
"strings"
1313

14+
freecache "github.com/coocood/freecache"
1415
cleanhttp "github.com/hashicorp/go-cleanhttp"
1516
)
1617

1718
// DefaultSchema is the value used for the URL in case
1819
// no schema is explicitly defined
1920
var DefaultSchema = "https"
2021

22+
// DefaultCacheSize is client default cache size
23+
var DefaultCacheSize int
24+
2125
// Client is a PowerDNS client representation
2226
type Client struct {
2327
ServerURL string // Location of PowerDNS server to use
2428
ServerVersion string
2529
APIKey string // REST API Static authentication key
2630
APIVersion int // API version to use
2731
HTTP *http.Client
32+
CacheEnable bool // Enable/Disable chache for REST API requests
33+
Cache *freecache.Cache
2834
}
2935

3036
// NewClient returns a new PowerDNS client
31-
func NewClient(serverURL string, apiKey string, configTLS *tls.Config) (*Client, error) {
37+
func NewClient(serverURL string, apiKey string, configTLS *tls.Config, cacheEnable bool, cacheSizeMB string) (*Client, error) {
3238

3339
cleanURL, err := sanitizeURL(serverURL)
3440

@@ -39,11 +45,21 @@ func NewClient(serverURL string, apiKey string, configTLS *tls.Config) (*Client,
3945
return nil, fmt.Errorf("Error while creating client: %s", err)
4046
}
4147

48+
if cacheEnable {
49+
cacheSize, err := strconv.Atoi(cacheSizeMB)
50+
if err != nil {
51+
return nil, fmt.Errorf("Error while creating client: %s", err)
52+
}
53+
DefaultCacheSize = cacheSize * 1024 * 1024
54+
}
55+
4256
client := Client{
43-
ServerURL: cleanURL,
44-
APIKey: apiKey,
45-
HTTP: httpClient,
46-
APIVersion: -1,
57+
ServerURL: cleanURL,
58+
APIKey: apiKey,
59+
HTTP: httpClient,
60+
APIVersion: -1,
61+
CacheEnable: cacheEnable,
62+
Cache: freecache.NewCache(DefaultCacheSize),
4763
}
4864

4965
if err := client.setServerVersion(); err != nil {
@@ -420,23 +436,55 @@ func (client *Client) DeleteZone(name string) error {
420436
return nil
421437
}
422438

439+
// GetZoneInfoFromCache return ZoneInfo struct
440+
func (client *Client) GetZoneInfoFromCache(zone string) (*ZoneInfo, error) {
441+
if client.CacheEnable {
442+
cacheZoneInfo, err := client.Cache.Get([]byte(zone))
443+
444+
if err != nil {
445+
return nil, err
446+
}
447+
zoneInfo := new(ZoneInfo)
448+
json.Unmarshal(cacheZoneInfo, &zoneInfo)
449+
return zoneInfo, err
450+
}
451+
return nil, nil
452+
}
453+
423454
// ListRecords returns all records in Zone
424455
func (client *Client) ListRecords(zone string) ([]Record, error) {
425-
req, err := client.newRequest("GET", fmt.Sprintf("/servers/localhost/zones/%s", zone), nil)
426-
if err != nil {
427-
return nil, err
428-
}
456+
zoneInfo, _ := client.GetZoneInfoFromCache(zone)
429457

430-
resp, err := client.HTTP.Do(req)
431-
if err != nil {
432-
return nil, err
433-
}
434-
defer resp.Body.Close()
458+
if zoneInfo == nil {
459+
req, err := client.newRequest("GET", fmt.Sprintf("/servers/localhost/zones/%s", zone), nil)
460+
if err != nil {
461+
return nil, err
462+
}
435463

436-
zoneInfo := new(ZoneInfo)
437-
err = json.NewDecoder(resp.Body).Decode(zoneInfo)
438-
if err != nil {
439-
return nil, err
464+
resp, err := client.HTTP.Do(req)
465+
if err != nil {
466+
return nil, err
467+
}
468+
defer resp.Body.Close()
469+
470+
zoneInfo = new(ZoneInfo)
471+
err = json.NewDecoder(resp.Body).Decode(zoneInfo)
472+
if err != nil {
473+
return nil, err
474+
}
475+
476+
if client.CacheEnable {
477+
cacheValue, err := json.Marshal(zoneInfo)
478+
if err != nil {
479+
return nil, err
480+
}
481+
// Default cache ttl is 30 sec, I think that is enough
482+
err = client.Cache.Set([]byte(zone), cacheValue, 30)
483+
if err != nil {
484+
return nil, fmt.Errorf("The cache for REST API requests is enabled but the size isn't enough: cacheSize: %db \n %s",
485+
DefaultCacheSize, err)
486+
}
487+
}
440488
}
441489

442490
records := zoneInfo.Records

powerdns/config.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ import (
1111

1212
// Config describes de configuration interface of this provider
1313
type Config struct {
14-
ServerURL string
15-
APIKey string
16-
InsecureHTTPS bool
17-
CACertificate string
14+
ServerURL string
15+
APIKey string
16+
InsecureHTTPS bool
17+
CACertificate string
18+
CacheEnable bool
19+
CacheMemorySize string
1820
}
1921

2022
// Client returns a new client for accessing PowerDNS
@@ -36,7 +38,7 @@ func (c *Config) Client() (*Client, error) {
3638

3739
tlsConfig.InsecureSkipVerify = c.InsecureHTTPS
3840

39-
client, err := NewClient(c.ServerURL, c.APIKey, tlsConfig)
41+
client, err := NewClient(c.ServerURL, c.APIKey, tlsConfig, c.CacheEnable, c.CacheMemorySize)
4042

4143
if err != nil {
4244
return nil, fmt.Errorf("Error setting up PowerDNS client: %s", err)

powerdns/provider.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ func Provider() terraform.ResourceProvider {
3333
DefaultFunc: schema.EnvDefaultFunc("PDNS_CACERT", ""),
3434
Description: "Content or path of a Root CA to be used to verify PowerDNS's SSL certificate",
3535
},
36+
"cache_requests": {
37+
Type: schema.TypeBool,
38+
Optional: true,
39+
DefaultFunc: schema.EnvDefaultFunc("PDNS_CACHE_REQUESTS", false),
40+
Description: "Enable cache REST API requests",
41+
},
42+
"cache_mem_size": {
43+
Type: schema.TypeString,
44+
Optional: true,
45+
DefaultFunc: schema.EnvDefaultFunc("PDNS_CACHE_MEM_SIZE", "100"),
46+
Description: "Set cache memory size in Mb",
47+
},
3648
},
3749

3850
ResourcesMap: map[string]*schema.Resource{
@@ -46,10 +58,12 @@ func Provider() terraform.ResourceProvider {
4658

4759
func providerConfigure(data *schema.ResourceData) (interface{}, error) {
4860
config := Config{
49-
APIKey: data.Get("api_key").(string),
50-
ServerURL: data.Get("server_url").(string),
51-
InsecureHTTPS: data.Get("insecure_https").(bool),
52-
CACertificate: data.Get("ca_certificate").(string),
61+
APIKey: data.Get("api_key").(string),
62+
ServerURL: data.Get("server_url").(string),
63+
InsecureHTTPS: data.Get("insecure_https").(bool),
64+
CACertificate: data.Get("ca_certificate").(string),
65+
CacheEnable: data.Get("cache_requests").(bool),
66+
CacheMemorySize: data.Get("cache_mem_size").(string),
5367
}
5468

5569
return config.Client()

website/docs/index.html.markdown

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,5 @@ The following arguments are supported:
4040
* `server_url` - (Required) The address of PowerDNS server. This can also be specified with `PDNS_SERVER_URL` environment variable. When no schema is provided, the default is `https`.
4141
* `ca_certificate` - (Optional) A valid path of a Root CA Certificate in PEM format _or_ the content of a Root CA certificate in PEM format. This can also be specified with `PDNS_CACERT` environment variable.
4242
* `insecure_https` - (Optional) Set this to `true` to disable verification of the PowerDNS server's TLS certificate. This can also be specified with the `PDNS_INSECURE_HTTPS` environment variable.
43+
* `cache_requests` - (Optional) Set this to `true` to enable cache of the PowerDNS REST API requests. This can also be specified with the `PDNS_CACHE_REQUESTS` environment variable.
44+
* `cache_mem_size` - (Optional) Memory size in MB for a cache of the PowerDNS REST API requests. This can also be specified with the `PDNS_CACHE_MEM_SIZE` environment variable.

0 commit comments

Comments
 (0)