mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-06 09:36:58 +02:00
oracle provider: dns zone cache
Signed-off-by: Anders Swanson <anders.swanson@oracle.com>
This commit is contained in:
parent
3573a7d981
commit
dbaca73de2
@ -180,6 +180,9 @@ spec:
|
||||
# Specifies the OCI DNS Zone scope, defaults to GLOBAL.
|
||||
# May be GLOBAL, PRIVATE, or an empty value to specify both GLOBAL and PRIVATE OCI DNS Zones
|
||||
# - --oci-zone-scope=GLOBAL
|
||||
# Specifies the zone cache duration, defaults to 0s. If set to 0s, the zone cache is disabled.
|
||||
# Use of zone caching is recommended to reduce the amount of requests sent to OCI DNS.
|
||||
# - --oci-zones-cache-duration=0s
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /etc/kubernetes/
|
||||
|
2
main.go
2
main.go
@ -360,7 +360,7 @@ func main() {
|
||||
} else {
|
||||
config, err = oci.LoadOCIConfig(cfg.OCIConfigFile)
|
||||
}
|
||||
|
||||
config.ZoneCacheDuration = cfg.OCIZoneCacheDuration
|
||||
if err == nil {
|
||||
p, err = oci.NewOCIProvider(*config, domainFilter, zoneIDFilter, cfg.OCIZoneScope, cfg.DryRun)
|
||||
}
|
||||
|
@ -136,6 +136,7 @@ type Config struct {
|
||||
OCICompartmentOCID string
|
||||
OCIAuthInstancePrincipal bool
|
||||
OCIZoneScope string
|
||||
OCIZoneCacheDuration time.Duration
|
||||
InMemoryZones []string
|
||||
OVHEndpoint string
|
||||
OVHApiRateLimit int
|
||||
@ -293,6 +294,7 @@ var defaultConfig = &Config{
|
||||
InfobloxCacheDuration: 0,
|
||||
OCIConfigFile: "/etc/kubernetes/oci.yaml",
|
||||
OCIZoneScope: "GLOBAL",
|
||||
OCIZoneCacheDuration: 0 * time.Second,
|
||||
InMemoryZones: []string{},
|
||||
OVHEndpoint: "ovh-eu",
|
||||
OVHApiRateLimit: 20,
|
||||
@ -527,6 +529,7 @@ func (cfg *Config) ParseFlags(args []string) error {
|
||||
app.Flag("oci-compartment-ocid", "When using the OCI provider, specify the OCID of the OCI compartment containing all managed zones and records. Required when using OCI IAM instance principal authentication.").StringVar(&cfg.OCICompartmentOCID)
|
||||
app.Flag("oci-zone-scope", "When using OCI provider, filter for zones with this scope (optional, options: GLOBAL, PRIVATE). Defaults to GLOBAL, setting to empty value will target both.").Default(defaultConfig.OCIZoneScope).EnumVar(&cfg.OCIZoneScope, "", "GLOBAL", "PRIVATE")
|
||||
app.Flag("oci-auth-instance-principal", "When using the OCI provider, specify whether OCI IAM instance principal authentication should be used (instead of key-based auth via the OCI config file).").Default(strconv.FormatBool(defaultConfig.OCIAuthInstancePrincipal)).BoolVar(&cfg.OCIAuthInstancePrincipal)
|
||||
app.Flag("oci-zones-cache-duration", "When using the OCI provider, set the zones list cache TTL (0s to disable).").Default(defaultConfig.OCIZoneCacheDuration.String()).DurationVar(&cfg.OCIZoneCacheDuration)
|
||||
app.Flag("rcodezero-txt-encrypt", "When using the Rcodezero provider with txt registry option, set if TXT rrs are encrypted (default: false)").Default(strconv.FormatBool(defaultConfig.RcodezeroTXTEncrypt)).BoolVar(&cfg.RcodezeroTXTEncrypt)
|
||||
app.Flag("inmemory-zone", "Provide a list of pre-configured zones for the inmemory provider; specify multiple times for multiple zones (optional)").Default("").StringsVar(&cfg.InMemoryZones)
|
||||
app.Flag("ovh-endpoint", "When using the OVH provider, specify the endpoint (default: ovh-eu)").Default(defaultConfig.OVHEndpoint).StringVar(&cfg.OVHEndpoint)
|
||||
|
@ -95,6 +95,7 @@ var (
|
||||
InfobloxMaxResults: 0,
|
||||
OCIConfigFile: "/etc/kubernetes/oci.yaml",
|
||||
OCIZoneScope: "GLOBAL",
|
||||
OCIZoneCacheDuration: 0 * time.Second,
|
||||
InMemoryZones: []string{""},
|
||||
OVHEndpoint: "ovh-eu",
|
||||
OVHApiRateLimit: 20,
|
||||
@ -205,6 +206,7 @@ var (
|
||||
InfobloxMaxResults: 2000,
|
||||
OCIConfigFile: "oci.yaml",
|
||||
OCIZoneScope: "PRIVATE",
|
||||
OCIZoneCacheDuration: 30 * time.Second,
|
||||
InMemoryZones: []string{"example.org", "company.com"},
|
||||
OVHEndpoint: "ovh-ca",
|
||||
OVHApiRateLimit: 42,
|
||||
@ -328,6 +330,7 @@ func TestParseFlags(t *testing.T) {
|
||||
"--pdns-skip-tls-verify",
|
||||
"--oci-config-file=oci.yaml",
|
||||
"--oci-zone-scope=PRIVATE",
|
||||
"--oci-zones-cache-duration=30s",
|
||||
"--tls-ca=/path/to/ca.crt",
|
||||
"--tls-client-cert=/path/to/cert.pem",
|
||||
"--tls-client-cert-key=/path/to/key.pem",
|
||||
@ -449,6 +452,7 @@ func TestParseFlags(t *testing.T) {
|
||||
"EXTERNAL_DNS_INFOBLOX_MAX_RESULTS": "2000",
|
||||
"EXTERNAL_DNS_OCI_CONFIG_FILE": "oci.yaml",
|
||||
"EXTERNAL_DNS_OCI_ZONE_SCOPE": "PRIVATE",
|
||||
"EXTERNAL_DNS_OCI_ZONES_CACHE_DURATION": "30s",
|
||||
"EXTERNAL_DNS_INMEMORY_ZONE": "example.org\ncompany.com",
|
||||
"EXTERNAL_DNS_OVH_ENDPOINT": "ovh-ca",
|
||||
"EXTERNAL_DNS_OVH_API_RATE_LIMIT": "42",
|
||||
|
44
provider/oci/cache.go
Normal file
44
provider/oci/cache.go
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
Copyright 2023 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package oci
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/oracle/oci-go-sdk/v65/dns"
|
||||
)
|
||||
|
||||
type zoneCache struct {
|
||||
age time.Time
|
||||
duration time.Duration
|
||||
zones map[string]dns.ZoneSummary
|
||||
}
|
||||
|
||||
func (z *zoneCache) Reset(zones map[string]dns.ZoneSummary) {
|
||||
if z.duration > time.Duration(0) {
|
||||
z.age = time.Now()
|
||||
z.zones = zones
|
||||
}
|
||||
}
|
||||
|
||||
func (z *zoneCache) Get() map[string]dns.ZoneSummary {
|
||||
return z.zones
|
||||
}
|
||||
|
||||
func (z *zoneCache) Expired() bool {
|
||||
return len(z.zones) < 1 || time.Since(z.age) > z.duration
|
||||
}
|
75
provider/oci/cache_test.go
Normal file
75
provider/oci/cache_test.go
Normal file
@ -0,0 +1,75 @@
|
||||
/*
|
||||
Copyright 2023 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package oci
|
||||
|
||||
import (
|
||||
"github.com/oracle/oci-go-sdk/v65/dns"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestZoneCache(t *testing.T) {
|
||||
now := time.Now()
|
||||
var testCases = map[string]struct {
|
||||
z *zoneCache
|
||||
expired bool
|
||||
}{
|
||||
"inactive-zone-cache": {
|
||||
&zoneCache{
|
||||
duration: 0 * time.Second,
|
||||
},
|
||||
true,
|
||||
},
|
||||
"empty-active-zone-cache": {
|
||||
&zoneCache{
|
||||
duration: 30 * time.Second,
|
||||
},
|
||||
true,
|
||||
},
|
||||
"expired-zone-cache": {
|
||||
&zoneCache{
|
||||
age: now.Add(300 * time.Second),
|
||||
duration: 30 * time.Second,
|
||||
},
|
||||
true,
|
||||
},
|
||||
"active-zone-cache": {
|
||||
&zoneCache{
|
||||
zones: map[string]dns.ZoneSummary{
|
||||
zoneIdBaz: testPrivateZoneSummaryBaz,
|
||||
},
|
||||
duration: 30 * time.Second,
|
||||
},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, testCase := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert.Equal(t, testCase.expired, testCase.z.Expired())
|
||||
var resetZoneLength = 1
|
||||
if testCase.z.duration == 0 {
|
||||
resetZoneLength = 0
|
||||
}
|
||||
testCase.z.Reset(map[string]dns.ZoneSummary{
|
||||
zoneIdQux: testPrivateZoneSummaryQux,
|
||||
})
|
||||
assert.Len(t, testCase.z.Get(), resetZoneLength)
|
||||
})
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@ import (
|
||||
"context"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/oracle/oci-go-sdk/v65/common"
|
||||
"github.com/oracle/oci-go-sdk/v65/common/auth"
|
||||
@ -51,6 +52,7 @@ type OCIAuthConfig struct {
|
||||
type OCIConfig struct {
|
||||
Auth OCIAuthConfig `yaml:"auth"`
|
||||
CompartmentID string `yaml:"compartment"`
|
||||
ZoneCacheDuration time.Duration
|
||||
}
|
||||
|
||||
// OCIProvider is an implementation of Provider for Oracle Cloud Infrastructure
|
||||
@ -63,6 +65,7 @@ type OCIProvider struct {
|
||||
domainFilter endpoint.DomainFilter
|
||||
zoneIDFilter provider.ZoneIDFilter
|
||||
zoneScope string
|
||||
zoneCache *zoneCache
|
||||
dryRun bool
|
||||
}
|
||||
|
||||
@ -135,11 +138,18 @@ func NewOCIProvider(cfg OCIConfig, domainFilter endpoint.DomainFilter, zoneIDFil
|
||||
domainFilter: domainFilter,
|
||||
zoneIDFilter: zoneIDFilter,
|
||||
zoneScope: zoneScope,
|
||||
zoneCache: &zoneCache{
|
||||
duration: cfg.ZoneCacheDuration,
|
||||
},
|
||||
dryRun: dryRun,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (p *OCIProvider) zones(ctx context.Context) (map[string]dns.ZoneSummary, error) {
|
||||
if !p.zoneCache.Expired() {
|
||||
log.Debug("Using cached zones list")
|
||||
return p.zoneCache.zones, nil
|
||||
}
|
||||
zones := make(map[string]dns.ZoneSummary)
|
||||
scopes := []dns.GetZoneScopeEnum{dns.GetZoneScopeEnum(p.zoneScope)}
|
||||
// If zone scope is empty, list all zones types.
|
||||
@ -155,6 +165,7 @@ func (p *OCIProvider) zones(ctx context.Context) (map[string]dns.ZoneSummary, er
|
||||
if len(zones) == 0 {
|
||||
log.Warnf("No zones in compartment %q match domain filters %v", p.cfg.CompartmentID, p.domainFilter)
|
||||
}
|
||||
p.zoneCache.Reset(zones)
|
||||
return zones, nil
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/oracle/oci-go-sdk/v65/common"
|
||||
"github.com/oracle/oci-go-sdk/v65/dns"
|
||||
@ -137,6 +138,9 @@ func newOCIProvider(client ociDNSClient, domainFilter endpoint.DomainFilter, zon
|
||||
domainFilter: domainFilter,
|
||||
zoneIDFilter: zoneIDFilter,
|
||||
zoneScope: zoneScope,
|
||||
zoneCache: &zoneCache{
|
||||
duration: 0 * time.Second,
|
||||
},
|
||||
dryRun: dryRun,
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user