Skip to content

Commit 5a5403b

Browse files
committed
Merge branch 'add_client_cache_for_rest_api_requests' of https://github.com/menai34/terraform-provider-powerdns into menai34-add_client_cache_for_rest_api_requests
2 parents c97d5a1 + 7c0cc45 commit 5a5403b

File tree

7 files changed

+118
-25
lines changed

7 files changed

+118
-25
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: 74 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,37 @@ import (
66
"encoding/json"
77
"fmt"
88
"io"
9+
"log"
910
"net/http"
1011
"net/url"
1112
"strconv"
1213
"strings"
1314

15+
freecache "github.com/coocood/freecache"
1416
cleanhttp "github.com/hashicorp/go-cleanhttp"
1517
)
1618

1719
// DefaultSchema is the value used for the URL in case
1820
// no schema is explicitly defined
1921
var DefaultSchema = "https"
2022

23+
// DefaultCacheSize is client default cache size
24+
var DefaultCacheSize int
25+
2126
// Client is a PowerDNS client representation
2227
type Client struct {
2328
ServerURL string // Location of PowerDNS server to use
2429
ServerVersion string
2530
APIKey string // REST API Static authentication key
2631
APIVersion int // API version to use
2732
HTTP *http.Client
33+
CacheEnable bool // Enable/Disable chache for REST API requests
34+
Cache *freecache.Cache
35+
CacheTTL int
2836
}
2937

3038
// NewClient returns a new PowerDNS client
31-
func NewClient(serverURL string, apiKey string, configTLS *tls.Config) (*Client, error) {
39+
func NewClient(serverURL string, apiKey string, configTLS *tls.Config, cacheEnable bool, cacheSizeMB string, cacheTTL int) (*Client, error) {
3240

3341
cleanURL, err := sanitizeURL(serverURL)
3442

@@ -39,11 +47,22 @@ func NewClient(serverURL string, apiKey string, configTLS *tls.Config) (*Client,
3947
return nil, fmt.Errorf("Error while creating client: %s", err)
4048
}
4149

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

4968
if err := client.setServerVersion(); err != nil {
@@ -420,23 +439,62 @@ func (client *Client) DeleteZone(name string) error {
420439
return nil
421440
}
422441

442+
// GetZoneInfoFromCache return ZoneInfo struct
443+
func (client *Client) GetZoneInfoFromCache(zone string) (*ZoneInfo, error) {
444+
if client.CacheEnable {
445+
cacheZoneInfo, err := client.Cache.Get([]byte(zone))
446+
if err != nil {
447+
return nil, err
448+
}
449+
450+
zoneInfo := new(ZoneInfo)
451+
err = json.Unmarshal(cacheZoneInfo, &zoneInfo)
452+
if err != nil {
453+
return nil, err
454+
}
455+
456+
return zoneInfo, err
457+
}
458+
return nil, nil
459+
}
460+
423461
// ListRecords returns all records in Zone
424462
func (client *Client) ListRecords(zone string) ([]Record, error) {
425-
req, err := client.newRequest("GET", fmt.Sprintf("/servers/localhost/zones/%s", zone), nil)
463+
zoneInfo, err := client.GetZoneInfoFromCache(zone)
426464
if err != nil {
427-
return nil, err
465+
log.Printf("[WARN] module.freecache: %s: %s", zone, err)
428466
}
429467

430-
resp, err := client.HTTP.Do(req)
431-
if err != nil {
432-
return nil, err
433-
}
434-
defer resp.Body.Close()
468+
if zoneInfo == nil {
469+
req, err := client.newRequest("GET", fmt.Sprintf("/servers/localhost/zones/%s", zone), nil)
470+
if err != nil {
471+
return nil, err
472+
}
435473

436-
zoneInfo := new(ZoneInfo)
437-
err = json.NewDecoder(resp.Body).Decode(zoneInfo)
438-
if err != nil {
439-
return nil, err
474+
resp, err := client.HTTP.Do(req)
475+
if err != nil {
476+
return nil, err
477+
}
478+
defer resp.Body.Close()
479+
480+
zoneInfo = new(ZoneInfo)
481+
err = json.NewDecoder(resp.Body).Decode(zoneInfo)
482+
if err != nil {
483+
return nil, err
484+
}
485+
486+
if client.CacheEnable {
487+
cacheValue, err := json.Marshal(zoneInfo)
488+
if err != nil {
489+
return nil, err
490+
}
491+
492+
err = client.Cache.Set([]byte(zone), cacheValue, client.CacheTTL)
493+
if err != nil {
494+
return nil, fmt.Errorf("The cache for REST API requests is enabled but the size isn't enough: cacheSize: %db \n %s",
495+
DefaultCacheSize, err)
496+
}
497+
}
440498
}
441499

442500
records := zoneInfo.Records

powerdns/config.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@ 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
20+
CacheTTL int
1821
}
1922

2023
// Client returns a new client for accessing PowerDNS
@@ -36,7 +39,7 @@ func (c *Config) Client() (*Client, error) {
3639

3740
tlsConfig.InsecureSkipVerify = c.InsecureHTTPS
3841

39-
client, err := NewClient(c.ServerURL, c.APIKey, tlsConfig)
42+
client, err := NewClient(c.ServerURL, c.APIKey, tlsConfig, c.CacheEnable, c.CacheMemorySize, c.CacheTTL)
4043

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

powerdns/provider.go

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,24 @@ 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+
},
48+
"cache_ttl": {
49+
Type: schema.TypeInt,
50+
Optional: true,
51+
DefaultFunc: schema.EnvDefaultFunc("PDNS_CACHE_TTL", 30),
52+
Description: "Set cache TTL in seconds",
53+
},
3654
},
3755

3856
ResourcesMap: map[string]*schema.Resource{
@@ -46,10 +64,13 @@ func Provider() terraform.ResourceProvider {
4664

4765
func providerConfigure(data *schema.ResourceData) (interface{}, error) {
4866
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),
67+
APIKey: data.Get("api_key").(string),
68+
ServerURL: data.Get("server_url").(string),
69+
InsecureHTTPS: data.Get("insecure_https").(bool),
70+
CACertificate: data.Get("ca_certificate").(string),
71+
CacheEnable: data.Get("cache_requests").(bool),
72+
CacheMemorySize: data.Get("cache_mem_size").(string),
73+
CacheTTL: data.Get("cache_ttl").(int),
5374
}
5475

5576
return config.Client()

website/docs/index.html.markdown

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,6 @@ 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. `WARNING! Enabling this option can lead to the use of stale records when you use other automation to populate the DNS zone records at the same time.`
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.
45+
* `cache_ttl` - (Optional) TTL in seconds for a cache of the PowerDNS REST API requests. This can also be specified with the `PDNS_CACHE_TTL` environment variable.

0 commit comments

Comments
 (0)