chore!: remove unmaintained providers

This commit is contained in:
Michel Loiseleur 2025-05-25 09:42:58 +02:00
parent b0cc39a2ae
commit 756a7288da
14 changed files with 3 additions and 2284 deletions

2
OWNERS
View File

@ -51,6 +51,6 @@ filters:
"provider/cloudflare":
labels:
- provider/cloudflare
"provider/(akamai|alibabacloud|civo|designate|digitalocean|dnsimple|exoscale|gandi|godaddy|ibmcloud|linode|ns1|oci|ovh|pihole|plural|scaleway|tencentcloud|transip|ultradns)":
"provider/(akamai|alibabacloud|civo|designate|digitalocean|dnsimple|exoscale|gandi|godaddy|linode|ns1|oci|ovh|pihole|plural|scaleway|tencentcloud|transip|ultradns)":
labels:
- provider

View File

@ -151,7 +151,6 @@ The following table clarifies the current status of the providers according to t
| UltraDNS | Alpha | |
| GoDaddy | Alpha | |
| Gandi | Alpha | @packi |
| IBMCloud | Alpha | @hughhuangzh |
| TencentCloud | Alpha | @Hyzhou |
| Plural | Alpha | @michaeljguarino |
| Pi-hole | Alpha | @tinyzimmer |
@ -213,7 +212,6 @@ The following tutorials are provided:
- [UltraDNS](docs/tutorials/ultradns.md)
- [GoDaddy](docs/tutorials/godaddy.md)
- [Gandi](docs/tutorials/gandi.md)
- [IBM Cloud](docs/tutorials/ibmcloud.md)
- [Nodes as source](docs/sources/nodes.md)
- [TencentCloud](docs/tutorials/tencentcloud.md)
- [Plural](docs/tutorials/plural.md)

View File

@ -53,7 +53,6 @@ import (
"sigs.k8s.io/external-dns/provider/gandi"
"sigs.k8s.io/external-dns/provider/godaddy"
"sigs.k8s.io/external-dns/provider/google"
"sigs.k8s.io/external-dns/provider/ibmcloud"
"sigs.k8s.io/external-dns/provider/inmemory"
"sigs.k8s.io/external-dns/provider/linode"
"sigs.k8s.io/external-dns/provider/ns1"
@ -307,8 +306,6 @@ func Execute() {
APIVersion: cfg.PiholeApiVersion,
},
)
case "ibmcloud":
p, err = ibmcloud.NewIBMCloudProvider(cfg.IBMCloudConfigFile, domainFilter, zoneIDFilter, endpointsSource, cfg.IBMCloudProxied, cfg.DryRun)
case "plural":
p, err = plural.NewPluralProvider(cfg.PluralCluster, cfg.PluralProvider)
case "tencentcloud":

View File

@ -107,7 +107,6 @@ Some providers define their own annotations. Cloud-specific annotations have key
|------------|------------------------------------------------|
| AWS | `external-dns.alpha.kubernetes.io/aws-` |
| CloudFlare | `external-dns.alpha.kubernetes.io/cloudflare-` |
| IBM Cloud | `external-dns.alpha.kubernetes.io/ibmcloud-` |
| Scaleway | `external-dns.alpha.kubernetes.io/scw-` |
Additional annotations that are currently implemented only by AWS are:

View File

@ -51,7 +51,7 @@
| `--target-net-filter=TARGET-NET-FILTER` | Limit possible targets by a net filter; specify multiple times for multiple possible nets (optional) |
| `--[no-]traefik-disable-legacy` | Disable listeners on Resources under the traefik.containo.us API Group |
| `--[no-]traefik-disable-new` | Disable listeners on Resources under the traefik.io API Group |
| `--provider=provider` | The DNS provider where the DNS records will be created (required, options: akamai, alibabacloud, aws, aws-sd, azure, azure-dns, azure-private-dns, civo, cloudflare, coredns, digitalocean, dnsimple, exoscale, gandi, godaddy, google, ibmcloud, inmemory, linode, ns1, oci, ovh, pdns, pihole, plural, rfc2136, scaleway, skydns, tencentcloud, transip, ultradns, webhook) |
| `--provider=provider` | The DNS provider where the DNS records will be created (required, options: akamai, alibabacloud, aws, aws-sd, azure, azure-dns, azure-private-dns, civo, cloudflare, coredns, digitalocean, dnsimple, exoscale, gandi, godaddy, google, inmemory, linode, ns1, oci, ovh, pdns, pihole, plural, rfc2136, scaleway, skydns, tencentcloud, transip, ultradns, webhook) |
| `--provider-cache-time=0s` | The time to cache the DNS provider record list requests. |
| `--domain-filter=` | Limit possible target zones by a domain suffix; specify multiple times for multiple domains (optional) |
| `--exclude-domains=` | Exclude subdomains (optional) |
@ -120,8 +120,6 @@
| `--[no-]ns1-ignoressl` | When using the NS1 provider, specify whether to verify the SSL certificate (default: false) |
| `--ns1-min-ttl=NS1-MIN-TTL` | Minimal TTL (in seconds) for records. This value will be used if the provided TTL for a service/ingress is lower than this. |
| `--digitalocean-api-page-size=50` | Configure the page size used when querying the DigitalOcean API. |
| `--ibmcloud-config-file="/etc/kubernetes/ibmcloud.json"` | When using the IBM Cloud provider, specify the IBM Cloud configuration file (required when --provider=ibmcloud |
| `--[no-]ibmcloud-proxied` | When using the IBM provider, specify if the proxy mode must be enabled (default: disabled) |
| `--godaddy-api-key=""` | When using the GoDaddy provider, specify the API Key (required when --provider=godaddy) |
| `--godaddy-api-secret=""` | When using the GoDaddy provider, specify the API secret (required when --provider=godaddy) |
| `--godaddy-api-ttl=GODADDY-API-TTL` | TTL (in seconds) for records. This value will be used if the provided TTL for a service/ingress is not provided. |

View File

@ -18,7 +18,6 @@ Provider supported configurations
| Gandi | n/a | no | 600 |
| GoDaddy | n/a | yes | 600 |
| Google GCP | n/a | yes | 300 |
| IBMCloud | n/a | yes | 1 |
| InMemory | n/a | n/a | n/a |
| Linode | n/a | n/a | n/a |
| NS1 | n/a | yes | 10 |

View File

@ -1,277 +0,0 @@
# IBMCloud
This tutorial describes how to setup ExternalDNS for usage within a Kubernetes cluster using IBMCloud DNS.
This tutorial uses [IBMCloud CLI](https://cloud.ibm.com/docs/cli?topic=cli-getting-started) for all
IBM Cloud commands and assumes that the Kubernetes cluster was created via IBM Cloud Kubernetes Service and `kubectl` commands
are being run on an orchestration node.
## Creating a IBMCloud DNS zone
The IBMCloud provider for ExternalDNS will find suitable zones for domains it manages; it will
not automatically create zones.
For public zone, This tutorial assume that the [IBMCloud Internet Services](https://cloud.ibm.com/catalog/services/internet-services) was provisioned and the [cis cli plugin](https://cloud.ibm.com/docs/cis?topic=cis-cli-plugin-cis-cli) was installed with IBMCloud CLI
For private zone, This tutorial assume that the [IBMCloud DNS Services](https://cloud.ibm.com/catalog/services/dns-services) was provisioned and the [dns cli plugin](https://cloud.ibm.com/docs/dns-svcs?topic=dns-svcs-cli-plugin-dns-services-cli-commands) was installed with IBMCloud CLI
### Public Zone
For this tutorial, we create public zone named `example.com` on IBMCloud Internet Services instance `external-dns-public`
```sh
ibmcloud cis domain-add example.com -i external-dns-public
```
Follow [step](https://cloud.ibm.com/docs/cis?topic=cis-getting-started#configure-your-name-servers-with-the-registrar-or-existing-dns-provider) to active your zone
### Private Zone
For this tutorial, we create private zone named `example.com` on IBMCloud DNS Services instance `external-dns-private`
```sh
ibmcloud dns zone-create example.com -i external-dns-private
```
## Creating configuration file
The preferred way to inject the configuration file is by using a Kubernetes secret. The secret should contain an object named azure.json with content similar to this:
```json
{
"apiKey": "1234567890abcdefghijklmnopqrstuvwxyz",
"instanceCrn": "crn:v1:bluemix:public:internet-svcs:global:a/bcf1865e99742d38d2d5fc3fb80a5496:b950da8a-5be6-4691-810e-36388c77b0a3::"
}
```
You can create or find the `apiKey` in your ibmcloud IAM --> [API Keys page](https://cloud.ibm.com/iam/apikeys)
You can find the `instanceCrn` in your service instance details
Now you can create a file named 'ibmcloud.json' with values gathered above and with the structure of the example above. Use this file to create a Kubernetes secret:
```sh
kubectl create secret generic ibmcloud-config-file --from-file=/local/path/to/ibmcloud.json
```
## Deploy ExternalDNS
Connect your `kubectl` client to the cluster you want to test ExternalDNS with.
Then apply one of the following manifests file to deploy ExternalDNS.
### Manifest (for clusters without RBAC enabled)
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: external-dns
template:
metadata:
labels:
app: external-dns
spec:
containers:
- name: external-dns
image: registry.k8s.io/external-dns/external-dns:v0.17.0
args:
- --source=service # ingress is also possible
- --domain-filter=example.com # (optional) limit to only example.com domains; change to match the zone created above.
- --provider=ibmcloud
- --ibmcloud-proxied # (optional) enable the proxy feature of IBMCloud
volumeMounts:
- name: ibmcloud-config-file
mountPath: /etc/kubernetes
readOnly: true
volumes:
- name: ibmcloud-config-file
secret:
secretName: ibmcloud-config-file
items:
- key: externaldns-config.json
path: ibmcloud.json
```
### Manifest (for clusters with RBAC enabled)
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: external-dns
rules:
- apiGroups: [""]
resources: ["services","endpoints","pods"]
verbs: ["get","watch","list"]
- apiGroups: ["extensions","networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get","watch","list"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: external-dns-viewer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: external-dns
subjects:
- kind: ServiceAccount
name: external-dns
namespace: default
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: external-dns
template:
metadata:
labels:
app: external-dns
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: registry.k8s.io/external-dns/external-dns:v0.17.0
args:
- --source=service # ingress is also possible
- --domain-filter=example.com # (optional) limit to only example.com domains; change to match the zone created above.
- --provider=ibmcloud
- --ibmcloud-proxied # (optional) enable the proxy feature of IBMCloud public zone
volumeMounts:
- name: ibmcloud-config-file
mountPath: /etc/kubernetes
readOnly: true
volumes:
- name: ibmcloud-config-file
secret:
secretName: ibmcloud-config-file
items:
- key: externaldns-config.json
path: ibmcloud.json
```
## Deploying an Nginx Service
Create a service file called `nginx.yaml` with the following contents:
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx
name: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginx
annotations:
external-dns.alpha.kubernetes.io/hostname: www.example.com
external-dns.alpha.kubernetes.io/ttl: "120" #optional
spec:
selector:
app: nginx
type: LoadBalancer
ports:
- protocol: TCP
port: 80
targetPort: 80
```
Note the annotation on the service; use the hostname as the IBMCloud DNS zone created above. The annotation may also be a subdomain
of the DNS zone (e.g. 'www.example.com').
By setting the TTL annotation on the service, you have to pass a valid TTL, which must be 120 or above.
This annotation is optional, if you won't set it, it will be 1 (automatic) which is 300.
ExternalDNS uses this annotation to determine what services should be registered with DNS. Removing the annotation
will cause ExternalDNS to remove the corresponding DNS records.
Create the deployment and service:
```sh
kubectl create -f nginx.yaml
```
Depending where you run your service it can take a little while for your cloud provider to create an external IP for the service.
Once the service has an external IP assigned, ExternalDNS will notice the new service IP address and synchronize
the IBMCloud DNS records.
## Verifying IBMCloud DNS records
Run the following command to view the A records:
### Public Zone
```sh
# Get the domain ID with below command on IBMCloud Internet Services instance `external-dns-public`
$ ibmcloud cis domains -i external-dns-public
# Get the records with domain ID
$ ibmcloud cis dns-records DOMAIN_ID -i external-dns-public
```
### Private Zone
```sh
# Get the domain ID with below command on IBMCloud DNS Services instance `external-dns-private`
$ ibmcloud dns zones -i external-dns-private
# Get the records with domain ID
$ ibmcloud dns resource-records ZONE_ID -i external-dns-public
```
This should show the external IP address of the service as the A record for your domain.
## Cleanup
Now that we have verified that ExternalDNS will automatically manage IBMCloud DNS records, we can delete the tutorial's example:
```sh
kubectl delete -f nginx.yaml
kubectl delete -f externaldns.yaml
```
## Setting proxied records on public zone
Using the `external-dns.alpha.kubernetes.io/ibmcloud-proxied: "true"` annotation on your ingress or service, you can specify if the proxy feature of IBMCloud public DNS should be enabled for that record. This setting will override the global `--ibmcloud-proxied` setting.
## Active priviate zone with VPC allocated
By default, IBMCloud DNS Services don't active your private zone with new zone added.
With External DNS, you can use `external-dns.alpha.kubernetes.io/ibmcloud-vpc: "crn:v1:bluemix:public:is:us-south:a/bcf1865e99742d38d2d5fc3fb80a5496::vpc:r006-74353823-a60d-42e4-97c5-5e2551278435"` annotation on your ingress or service.
It will active your private zone with in specific VPC for that record created in.
This setting won't work if the private zone was active already.
Note: the annotaion value is the VPC CRN, every IBM Cloud service have a valid CRN.

View File

@ -199,8 +199,6 @@ type Config struct {
GoDaddyTTL int64
GoDaddyOTE bool
OCPRouterName string
IBMCloudProxied bool
IBMCloudConfigFile string
TencentCloudConfigFile string
TencentCloudZoneType string
PiholeServer string
@ -293,8 +291,6 @@ var defaultConfig = &Config{
GoogleBatchChangeSize: 1000,
GoogleProject: "",
GoogleZoneVisibility: "",
IBMCloudConfigFile: "/etc/kubernetes/ibmcloud.json",
IBMCloudProxied: false,
IgnoreHostnameAnnotation: false,
IgnoreIngressRulesSpec: false,
IgnoreIngressTLSSpec: false,
@ -495,7 +491,7 @@ func App(cfg *Config) *kingpin.Application {
app.Flag("traefik-disable-new", "Disable listeners on Resources under the traefik.io API Group").Default(strconv.FormatBool(defaultConfig.TraefikDisableNew)).BoolVar(&cfg.TraefikDisableNew)
// Flags related to providers
providers := []string{"akamai", "alibabacloud", "aws", "aws-sd", "azure", "azure-dns", "azure-private-dns", "civo", "cloudflare", "coredns", "digitalocean", "dnsimple", "exoscale", "gandi", "godaddy", "google", "ibmcloud", "inmemory", "linode", "ns1", "oci", "ovh", "pdns", "pihole", "plural", "rfc2136", "scaleway", "skydns", "tencentcloud", "transip", "ultradns", "webhook"}
providers := []string{"akamai", "alibabacloud", "aws", "aws-sd", "azure", "azure-dns", "azure-private-dns", "civo", "cloudflare", "coredns", "digitalocean", "dnsimple", "exoscale", "gandi", "godaddy", "google", "inmemory", "linode", "ns1", "oci", "ovh", "pdns", "pihole", "plural", "rfc2136", "scaleway", "skydns", "tencentcloud", "transip", "ultradns", "webhook"}
app.Flag("provider", "The DNS provider where the DNS records will be created (required, options: "+strings.Join(providers, ", ")+")").Required().PlaceHolder("provider").EnumVar(&cfg.Provider, providers...)
app.Flag("provider-cache-time", "The time to cache the DNS provider record list requests.").Default(defaultConfig.ProviderCacheTime.String()).DurationVar(&cfg.ProviderCacheTime)
app.Flag("domain-filter", "Limit possible target zones by a domain suffix; specify multiple times for multiple domains (optional)").Default("").StringsVar(&cfg.DomainFilter)
@ -567,8 +563,6 @@ func App(cfg *Config) *kingpin.Application {
app.Flag("ns1-ignoressl", "When using the NS1 provider, specify whether to verify the SSL certificate (default: false)").Default(strconv.FormatBool(defaultConfig.NS1IgnoreSSL)).BoolVar(&cfg.NS1IgnoreSSL)
app.Flag("ns1-min-ttl", "Minimal TTL (in seconds) for records. This value will be used if the provided TTL for a service/ingress is lower than this.").IntVar(&cfg.NS1MinTTLSeconds)
app.Flag("digitalocean-api-page-size", "Configure the page size used when querying the DigitalOcean API.").Default(strconv.Itoa(defaultConfig.DigitalOceanAPIPageSize)).IntVar(&cfg.DigitalOceanAPIPageSize)
app.Flag("ibmcloud-config-file", "When using the IBM Cloud provider, specify the IBM Cloud configuration file (required when --provider=ibmcloud").Default(defaultConfig.IBMCloudConfigFile).StringVar(&cfg.IBMCloudConfigFile)
app.Flag("ibmcloud-proxied", "When using the IBM provider, specify if the proxy mode must be enabled (default: disabled)").BoolVar(&cfg.IBMCloudProxied)
// GoDaddy flags
app.Flag("godaddy-api-key", "When using the GoDaddy provider, specify the API Key (required when --provider=godaddy)").Default(defaultConfig.GoDaddyAPIKey).StringVar(&cfg.GoDaddyAPIKey)
app.Flag("godaddy-api-secret", "When using the GoDaddy provider, specify the API secret (required when --provider=godaddy)").Default(defaultConfig.GoDaddySecretKey).StringVar(&cfg.GoDaddySecretKey)

View File

@ -125,8 +125,6 @@ var (
RFC2136Host: []string{""},
RFC2136LoadBalancingStrategy: "disabled",
OCPRouterName: "default",
IBMCloudProxied: false,
IBMCloudConfigFile: "/etc/kubernetes/ibmcloud.json",
TencentCloudConfigFile: "/etc/kubernetes/tencent-cloud.json",
TencentCloudZoneType: "",
PiholeApiVersion: "5",
@ -242,8 +240,6 @@ var (
RFC2136BatchChangeSize: 100,
RFC2136Host: []string{"rfc2136-host1", "rfc2136-host2"},
RFC2136LoadBalancingStrategy: "round-robin",
IBMCloudProxied: true,
IBMCloudConfigFile: "ibmcloud.json",
TencentCloudConfigFile: "tencent-cloud.json",
TencentCloudZoneType: "private",
PiholeApiVersion: "6",
@ -396,8 +392,6 @@ func TestParseFlags(t *testing.T) {
"--rfc2136-load-balancing-strategy=round-robin",
"--rfc2136-host=rfc2136-host1",
"--rfc2136-host=rfc2136-host2",
"--ibmcloud-proxied",
"--ibmcloud-config-file=ibmcloud.json",
"--tencent-cloud-config-file=tencent-cloud.json",
"--tencent-cloud-zone-type=private",
},
@ -516,8 +510,6 @@ func TestParseFlags(t *testing.T) {
"EXTERNAL_DNS_RFC2136_BATCH_CHANGE_SIZE": "100",
"EXTERNAL_DNS_RFC2136_LOAD_BALANCING_STRATEGY": "round-robin",
"EXTERNAL_DNS_RFC2136_HOST": "rfc2136-host1\nrfc2136-host2",
"EXTERNAL_DNS_IBMCLOUD_PROXIED": "1",
"EXTERNAL_DNS_IBMCLOUD_CONFIG_FILE": "ibmcloud.json",
"EXTERNAL_DNS_TENCENT_CLOUD_CONFIG_FILE": "tencent-cloud.json",
"EXTERNAL_DNS_TENCENT_CLOUD_ZONE_TYPE": "private",
},

File diff suppressed because it is too large Load Diff

View File

@ -1,953 +0,0 @@
/*
Copyright 2022 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 ibmcloud
import (
"context"
"fmt"
"net/http"
"net/http/httptest"
"testing"
"time"
"github.com/IBM/go-sdk-core/v5/core"
"github.com/IBM/networking-go-sdk/dnsrecordsv1"
"github.com/stretchr/testify/require"
"github.com/IBM/networking-go-sdk/dnssvcsv1"
. "github.com/onsi/ginkgo"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
"sigs.k8s.io/external-dns/endpoint"
"sigs.k8s.io/external-dns/plan"
"sigs.k8s.io/external-dns/provider"
)
func NewMockIBMCloudDNSAPI() *mockIbmcloudClientInterface {
// Setup public example responses
firstPublicRecord := dnsrecordsv1.DnsrecordDetails{
ID: core.StringPtr("123"),
Name: core.StringPtr("test.example.com"),
Type: core.StringPtr("A"),
Content: core.StringPtr("1.2.3.4"),
Proxied: core.BoolPtr(true),
TTL: core.Int64Ptr(int64(120)),
}
secondPublicRecord := dnsrecordsv1.DnsrecordDetails{
ID: core.StringPtr("456"),
Name: core.StringPtr("test.example.com"),
Type: core.StringPtr("TXT"),
Proxied: core.BoolPtr(false),
Content: core.StringPtr("\"heritage=external-dns,external-dns/owner=tower-pdns\""),
TTL: core.Int64Ptr(int64(120)),
}
publicRecordsResult := []dnsrecordsv1.DnsrecordDetails{firstPublicRecord, secondPublicRecord}
publicRecordsResultInfo := &dnsrecordsv1.ResultInfo{
Page: core.Int64Ptr(int64(1)),
TotalCount: core.Int64Ptr(int64(1)),
}
publicRecordsResp := &dnsrecordsv1.ListDnsrecordsResp{
Result: publicRecordsResult,
ResultInfo: publicRecordsResultInfo,
}
// Setup private example responses
firstPrivateZone := dnssvcsv1.Dnszone{
ID: core.StringPtr("123"),
Name: core.StringPtr("example.com"),
State: core.StringPtr(zoneStatePendingNetwork),
}
secondPrivateZone := dnssvcsv1.Dnszone{
ID: core.StringPtr("456"),
Name: core.StringPtr("example1.com"),
State: core.StringPtr(zoneStateActive),
}
privateZones := []dnssvcsv1.Dnszone{firstPrivateZone, secondPrivateZone}
listZonesResp := &dnssvcsv1.ListDnszones{
Dnszones: privateZones,
}
firstPrivateRecord := dnssvcsv1.ResourceRecord{
ID: core.StringPtr("123"),
Name: core.StringPtr("test.example.com"),
Type: core.StringPtr("A"),
Rdata: map[string]interface{}{"ip": "1.2.3.4"},
TTL: core.Int64Ptr(int64(120)),
}
secondPrivateRecord := dnssvcsv1.ResourceRecord{
ID: core.StringPtr("456"),
Name: core.StringPtr("testCNAME.example.com"),
Type: core.StringPtr("CNAME"),
Rdata: map[string]interface{}{"cname": "test.example.com"},
TTL: core.Int64Ptr(int64(120)),
}
thirdPrivateRecord := dnssvcsv1.ResourceRecord{
ID: core.StringPtr("789"),
Name: core.StringPtr("test.example.com"),
Type: core.StringPtr("TXT"),
Rdata: map[string]interface{}{"text": "\"heritage=external-dns,external-dns/owner=tower-pdns\""},
TTL: core.Int64Ptr(int64(120)),
}
privateRecords := []dnssvcsv1.ResourceRecord{firstPrivateRecord, secondPrivateRecord, thirdPrivateRecord}
privateRecordsResop := &dnssvcsv1.ListResourceRecords{
ResourceRecords: privateRecords,
Offset: core.Int64Ptr(int64(0)),
TotalCount: core.Int64Ptr(int64(1)),
}
// Setup record rData
inputARecord := &dnssvcsv1.ResourceRecordInputRdataRdataARecord{
Ip: core.StringPtr("1.2.3.4"),
}
inputCnameRecord := &dnssvcsv1.ResourceRecordInputRdataRdataCnameRecord{
Cname: core.StringPtr("test.example.com"),
}
inputTxtRecord := &dnssvcsv1.ResourceRecordInputRdataRdataTxtRecord{
Text: core.StringPtr("test"),
}
updateARecord := &dnssvcsv1.ResourceRecordUpdateInputRdataRdataARecord{
Ip: core.StringPtr("1.2.3.4"),
}
updateCnameRecord := &dnssvcsv1.ResourceRecordUpdateInputRdataRdataCnameRecord{
Cname: core.StringPtr("test.example.com"),
}
updateTxtRecord := &dnssvcsv1.ResourceRecordUpdateInputRdataRdataTxtRecord{
Text: core.StringPtr("test"),
}
// Setup mock services
mockDNSClient := &mockIbmcloudClientInterface{}
mockDNSClient.On("CreateDNSRecordWithContext", mock.Anything, mock.Anything).Return(nil, nil, nil)
mockDNSClient.On("UpdateDNSRecordWithContext", mock.Anything, mock.Anything).Return(nil, nil, nil)
mockDNSClient.On("DeleteDNSRecordWithContext", mock.Anything, mock.Anything).Return(nil, nil, nil)
mockDNSClient.On("ListAllDDNSRecordsWithContext", mock.Anything, mock.Anything).Return(publicRecordsResp, nil, nil)
mockDNSClient.On("ListDnszonesWithContext", mock.Anything, mock.Anything).Return(listZonesResp, nil, nil)
mockDNSClient.On("GetDnszoneWithContext", mock.Anything, mock.Anything).Return(&firstPrivateZone, nil, nil)
mockDNSClient.On("ListResourceRecordsWithContext", mock.Anything, mock.Anything).Return(privateRecordsResop, nil, nil)
mockDNSClient.On("CreatePermittedNetworkWithContext", mock.Anything, mock.Anything).Return(nil, nil, nil)
mockDNSClient.On("CreateResourceRecordWithContext", mock.Anything, mock.Anything).Return(nil, nil, nil)
mockDNSClient.On("DeleteResourceRecordWithContext", mock.Anything, mock.Anything).Return(nil, nil, nil)
mockDNSClient.On("UpdateResourceRecordWithContext", mock.Anything, mock.Anything).Return(nil, nil, nil)
mockDNSClient.On("NewResourceRecordInputRdataRdataARecord", mock.Anything).Return(inputARecord, nil)
mockDNSClient.On("NewResourceRecordInputRdataRdataCnameRecord", mock.Anything).Return(inputCnameRecord, nil)
mockDNSClient.On("NewResourceRecordInputRdataRdataTxtRecord", mock.Anything).Return(inputTxtRecord, nil)
mockDNSClient.On("NewResourceRecordUpdateInputRdataRdataARecord", mock.Anything).Return(updateARecord, nil)
mockDNSClient.On("NewResourceRecordUpdateInputRdataRdataCnameRecord", mock.Anything).Return(updateCnameRecord, nil)
mockDNSClient.On("NewResourceRecordUpdateInputRdataRdataTxtRecord", mock.Anything).Return(updateTxtRecord, nil)
return mockDNSClient
}
func newTestIBMCloudProvider(private bool) *IBMCloudProvider {
mockSource := &mockSource{}
endpoints := []*endpoint.Endpoint{
{
DNSName: "new.example.com",
Targets: endpoint.Targets{"4.3.2.1"},
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "ibmcloud-vpc",
Value: "crn:v1:staging:public:is:us-south:a/0821fa9f9ebcc7b7c9a0d6e9bf9442a4::vpc:be33cdad-9a03-4bfa-82ca-eadb9f1de688",
},
},
},
}
mockSource.On("Endpoints", mock.Anything).Return(endpoints, nil, nil)
domainFilterTest := endpoint.NewDomainFilter([]string{"example.com"})
return &IBMCloudProvider{
Client: NewMockIBMCloudDNSAPI(),
source: mockSource,
domainFilter: domainFilterTest,
DryRun: false,
instanceID: "test123",
privateZone: private,
}
}
func TestPublic_Records(t *testing.T) {
p := newTestIBMCloudProvider(false)
endpoints, err := p.Records(context.Background())
if err != nil {
t.Errorf("Failed to get records: %v", err)
} else {
if len(endpoints) != 2 {
t.Errorf("Incorrect number of records: %d", len(endpoints))
}
for _, endpoint := range endpoints {
t.Logf("Endpoint for %++v", *endpoint)
}
}
}
func TestPrivate_Records(t *testing.T) {
p := newTestIBMCloudProvider(true)
endpoints, err := p.Records(context.Background())
if err != nil {
t.Errorf("Failed to get records: %v", err)
} else {
if len(endpoints) != 3 {
t.Errorf("Incorrect number of records: %d", len(endpoints))
}
for _, endpoint := range endpoints {
t.Logf("Endpoint for %++v", *endpoint)
}
}
}
func TestPublic_ApplyChanges(t *testing.T) {
p := newTestIBMCloudProvider(false)
changes := plan.Changes{
Create: []*endpoint.Endpoint{
{
DNSName: "newA.example.com",
RecordType: "A",
RecordTTL: 300,
Targets: endpoint.NewTargets("4.3.2.1"),
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "ibmcloud-proxied",
Value: "false",
},
},
},
},
UpdateOld: []*endpoint.Endpoint{
{
DNSName: "test.example.com",
RecordType: "A",
RecordTTL: 180,
Targets: endpoint.NewTargets("1.2.3.4"),
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "ibmcloud-proxied",
Value: "false",
},
},
},
},
UpdateNew: []*endpoint.Endpoint{
{
DNSName: "test.example.com",
RecordType: "A",
RecordTTL: 180,
Targets: endpoint.NewTargets("1.2.3.4", "5.6.7.8"),
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "ibmcloud-proxied",
Value: "true",
},
},
},
},
Delete: []*endpoint.Endpoint{
{
DNSName: "test.example.com",
RecordType: "TXT",
RecordTTL: 300,
Targets: endpoint.NewTargets("\"heritage=external-dns,external-dns/owner=tower-pdns\""),
},
},
}
ctx := context.Background()
err := p.ApplyChanges(ctx, &changes)
if err != nil {
t.Errorf("should not fail, %s", err)
}
}
func TestPrivate_ApplyChanges(t *testing.T) {
p := newTestIBMCloudProvider(true)
endpointsCreate, err := p.AdjustEndpoints([]*endpoint.Endpoint{
{
DNSName: "newA.example.com",
RecordType: "A",
RecordTTL: 120,
Targets: endpoint.NewTargets("4.3.2.1"),
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "ibmcloud-vpc",
Value: "crn:v1:staging:public:is:us-south:a/0821fa9f9ebcc7b7c9a0d6e9bf9442a4::vpc:be33cdad-9a03-4bfa-82ca-eadb9f1de688",
},
},
},
{
DNSName: "newCNAME.example.com",
RecordType: "CNAME",
RecordTTL: 180,
Targets: endpoint.NewTargets("newA.example.com"),
},
{
DNSName: "newTXT.example.com",
RecordType: "TXT",
RecordTTL: 240,
Targets: endpoint.NewTargets("\"heritage=external-dns,external-dns/owner=tower-pdns\""),
},
})
require.NoError(t, err)
endpointsUpdate, err := p.AdjustEndpoints([]*endpoint.Endpoint{
{
DNSName: "test.example.com",
RecordType: "A",
RecordTTL: 180,
Targets: endpoint.NewTargets("1.2.3.4", "5.6.7.8"),
},
})
require.NoError(t, err)
changes := plan.Changes{
Create: endpointsCreate,
UpdateOld: []*endpoint.Endpoint{
{
DNSName: "test.example.com",
RecordType: "A",
RecordTTL: 180,
Targets: endpoint.NewTargets("1.2.3.4"),
},
},
UpdateNew: endpointsUpdate,
Delete: []*endpoint.Endpoint{
{
DNSName: "test.example.com",
RecordType: "TXT",
RecordTTL: 300,
Targets: endpoint.NewTargets("\"heritage=external-dns,external-dns/owner=tower-pdns\""),
},
},
}
ctx := context.Background()
err = p.ApplyChanges(ctx, &changes)
if err != nil {
t.Errorf("should not fail, %s", err)
}
}
func TestAdjustEndpoints(t *testing.T) {
p := newTestIBMCloudProvider(false)
endpoints := []*endpoint.Endpoint{
{
DNSName: "test.example.com",
Targets: endpoint.Targets{"1.2.3.4"},
RecordType: endpoint.RecordTypeA,
RecordTTL: 300,
Labels: endpoint.Labels{},
ProviderSpecific: endpoint.ProviderSpecific{
{
Name: "ibmcloud-proxied",
Value: "1",
},
},
},
}
ep, err := p.AdjustEndpoints(endpoints)
assert.NoError(t, err)
assert.Equal(t, endpoint.TTL(0), ep[0].RecordTTL)
assert.Equal(t, "test.example.com", ep[0].DNSName)
proxied, _ := ep[0].GetProviderSpecificProperty("ibmcloud-proxied")
assert.Equal(t, "true", proxied)
}
func TestPrivateZone_withFilterID(t *testing.T) {
p := newTestIBMCloudProvider(true)
p.zoneIDFilter = provider.NewZoneIDFilter([]string{"123", "456"})
zones, err := p.privateZones(context.Background())
if err != nil {
t.Errorf("should not fail, %s", err)
} else {
if len(zones) != 2 {
t.Errorf("Incorrect number of zones: %d", len(zones))
}
for _, zone := range zones {
t.Logf("zone %s", *zone.ID)
}
}
}
func TestPublicConfig_Validate(t *testing.T) {
// mock http server
testServer := httptest.NewServer(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {
defer GinkgoRecover()
time.Sleep(0)
// Set mock response
res.Header().Set("Content-type", "application/json")
res.WriteHeader(http.StatusOK)
fmt.Fprintf(res, "%s", `{"success": true, "errors": [["Errors"]], "messages": [["Messages"]], "result": [{"id": "123", "created_on": "2014-01-01T05:20:00.12345Z", "modified_on": "2014-01-01T05:20:00.12345Z", "name": "example.com", "original_registrar": "GoDaddy", "original_dnshost": "NameCheap", "status": "active", "paused": false, "original_name_servers": ["ns1.originaldnshost.com"], "name_servers": ["ns001.name.cloud.ibm.com"]}], "result_info": {"page": 1, "per_page": 20, "count": 1, "total_count": 2000}}`)
}))
zoneIDFilterTest := provider.NewZoneIDFilter([]string{"123"})
domainFilterTest := endpoint.NewDomainFilter([]string{"example.com"})
cfg := &ibmcloudConfig{
Endpoint: testServer.URL,
CRN: "crn:v1:bluemix:public:internet-svcs:global:a/bcf1865e99742d38d2d5fc3fb80a5496:a6338168-9510-4951-9d67-425612de96f0::",
}
crn := cfg.CRN
authenticator := &core.NoAuthAuthenticator{}
service, isPrivate, err := cfg.Validate(authenticator, domainFilterTest, provider.NewZoneIDFilter([]string{""}))
assert.NoError(t, err)
assert.False(t, isPrivate)
assert.Equal(t, crn, *service.publicRecordsService.Crn)
assert.Equal(t, "123", *service.publicRecordsService.ZoneIdentifier)
service, isPrivate, err = cfg.Validate(authenticator, endpoint.NewDomainFilter([]string{""}), zoneIDFilterTest)
assert.NoError(t, err)
assert.False(t, isPrivate)
assert.Equal(t, crn, *service.publicRecordsService.Crn)
assert.Equal(t, "123", *service.publicRecordsService.ZoneIdentifier)
testServer.Close()
}
func TestPrivateConfig_Validate(t *testing.T) {
zoneIDFilterTest := provider.NewZoneIDFilter([]string{"123"})
domainFilterTest := endpoint.NewDomainFilter([]string{"example.com"})
authenticator := &core.NoAuthAuthenticator{}
cfg := &ibmcloudConfig{
Endpoint: "XXX",
CRN: "crn:v1:bluemix:public:dns-svcs:global:a/bcf1865e99742d38d2d5fc3fb80a5496:a6338168-9510-4951-9d67-425612de96f0::",
}
_, isPrivate, err := cfg.Validate(authenticator, domainFilterTest, zoneIDFilterTest)
assert.NoError(t, err)
assert.True(t, isPrivate)
}
// mockIbmcloudClientInterface is an autogenerated mock type for the ibmcloudClient type
type mockIbmcloudClientInterface struct {
mock.Mock
}
// CreateDNSRecordWithContext provides a mock function with given fields: ctx, createDnsRecordOptions
func (_m *mockIbmcloudClientInterface) CreateDNSRecordWithContext(ctx context.Context, createDnsRecordOptions *dnsrecordsv1.CreateDnsRecordOptions) (*dnsrecordsv1.DnsrecordResp, *core.DetailedResponse, error) {
ret := _m.Called(ctx, createDnsRecordOptions)
var r0 *dnsrecordsv1.DnsrecordResp
if rf, ok := ret.Get(0).(func(context.Context, *dnsrecordsv1.CreateDnsRecordOptions) *dnsrecordsv1.DnsrecordResp); ok {
r0 = rf(ctx, createDnsRecordOptions)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*dnsrecordsv1.DnsrecordResp)
}
}
var r1 *core.DetailedResponse
if rf, ok := ret.Get(1).(func(context.Context, *dnsrecordsv1.CreateDnsRecordOptions) *core.DetailedResponse); ok {
r1 = rf(ctx, createDnsRecordOptions)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*core.DetailedResponse)
}
}
var r2 error
if rf, ok := ret.Get(2).(func(context.Context, *dnsrecordsv1.CreateDnsRecordOptions) error); ok {
r2 = rf(ctx, createDnsRecordOptions)
} else {
r2 = ret.Error(2)
}
return r0, r1, r2
}
// CreatePermittedNetworkWithContext provides a mock function with given fields: ctx, createPermittedNetworkOptions
func (_m *mockIbmcloudClientInterface) CreatePermittedNetworkWithContext(ctx context.Context, createPermittedNetworkOptions *dnssvcsv1.CreatePermittedNetworkOptions) (*dnssvcsv1.PermittedNetwork, *core.DetailedResponse, error) {
ret := _m.Called(ctx, createPermittedNetworkOptions)
var r0 *dnssvcsv1.PermittedNetwork
if rf, ok := ret.Get(0).(func(context.Context, *dnssvcsv1.CreatePermittedNetworkOptions) *dnssvcsv1.PermittedNetwork); ok {
r0 = rf(ctx, createPermittedNetworkOptions)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*dnssvcsv1.PermittedNetwork)
}
}
var r1 *core.DetailedResponse
if rf, ok := ret.Get(1).(func(context.Context, *dnssvcsv1.CreatePermittedNetworkOptions) *core.DetailedResponse); ok {
r1 = rf(ctx, createPermittedNetworkOptions)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*core.DetailedResponse)
}
}
var r2 error
if rf, ok := ret.Get(2).(func(context.Context, *dnssvcsv1.CreatePermittedNetworkOptions) error); ok {
r2 = rf(ctx, createPermittedNetworkOptions)
} else {
r2 = ret.Error(2)
}
return r0, r1, r2
}
// CreateResourceRecordWithContext provides a mock function with given fields: ctx, createResourceRecordOptions
func (_m *mockIbmcloudClientInterface) CreateResourceRecordWithContext(ctx context.Context, createResourceRecordOptions *dnssvcsv1.CreateResourceRecordOptions) (*dnssvcsv1.ResourceRecord, *core.DetailedResponse, error) {
ret := _m.Called(ctx, createResourceRecordOptions)
var r0 *dnssvcsv1.ResourceRecord
if rf, ok := ret.Get(0).(func(context.Context, *dnssvcsv1.CreateResourceRecordOptions) *dnssvcsv1.ResourceRecord); ok {
r0 = rf(ctx, createResourceRecordOptions)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*dnssvcsv1.ResourceRecord)
}
}
var r1 *core.DetailedResponse
if rf, ok := ret.Get(1).(func(context.Context, *dnssvcsv1.CreateResourceRecordOptions) *core.DetailedResponse); ok {
r1 = rf(ctx, createResourceRecordOptions)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*core.DetailedResponse)
}
}
var r2 error
if rf, ok := ret.Get(2).(func(context.Context, *dnssvcsv1.CreateResourceRecordOptions) error); ok {
r2 = rf(ctx, createResourceRecordOptions)
} else {
r2 = ret.Error(2)
}
return r0, r1, r2
}
// DeleteDNSRecordWithContext provides a mock function with given fields: ctx, deleteDnsRecordOptions
func (_m *mockIbmcloudClientInterface) DeleteDNSRecordWithContext(ctx context.Context, deleteDnsRecordOptions *dnsrecordsv1.DeleteDnsRecordOptions) (*dnsrecordsv1.DeleteDnsrecordResp, *core.DetailedResponse, error) {
ret := _m.Called(ctx, deleteDnsRecordOptions)
var r0 *dnsrecordsv1.DeleteDnsrecordResp
if rf, ok := ret.Get(0).(func(context.Context, *dnsrecordsv1.DeleteDnsRecordOptions) *dnsrecordsv1.DeleteDnsrecordResp); ok {
r0 = rf(ctx, deleteDnsRecordOptions)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*dnsrecordsv1.DeleteDnsrecordResp)
}
}
var r1 *core.DetailedResponse
if rf, ok := ret.Get(1).(func(context.Context, *dnsrecordsv1.DeleteDnsRecordOptions) *core.DetailedResponse); ok {
r1 = rf(ctx, deleteDnsRecordOptions)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*core.DetailedResponse)
}
}
var r2 error
if rf, ok := ret.Get(2).(func(context.Context, *dnsrecordsv1.DeleteDnsRecordOptions) error); ok {
r2 = rf(ctx, deleteDnsRecordOptions)
} else {
r2 = ret.Error(2)
}
return r0, r1, r2
}
// DeleteResourceRecordWithContext provides a mock function with given fields: ctx, deleteResourceRecordOptions
func (_m *mockIbmcloudClientInterface) DeleteResourceRecordWithContext(ctx context.Context, deleteResourceRecordOptions *dnssvcsv1.DeleteResourceRecordOptions) (*core.DetailedResponse, error) {
ret := _m.Called(ctx, deleteResourceRecordOptions)
var r0 *core.DetailedResponse
if rf, ok := ret.Get(0).(func(context.Context, *dnssvcsv1.DeleteResourceRecordOptions) *core.DetailedResponse); ok {
r0 = rf(ctx, deleteResourceRecordOptions)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*core.DetailedResponse)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *dnssvcsv1.DeleteResourceRecordOptions) error); ok {
r1 = rf(ctx, deleteResourceRecordOptions)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// GetDnszoneWithContext provides a mock function with given fields: ctx, getDnszoneOptions
func (_m *mockIbmcloudClientInterface) GetDnszoneWithContext(ctx context.Context, getDnszoneOptions *dnssvcsv1.GetDnszoneOptions) (*dnssvcsv1.Dnszone, *core.DetailedResponse, error) {
ret := _m.Called(ctx, getDnszoneOptions)
var r0 *dnssvcsv1.Dnszone
if rf, ok := ret.Get(0).(func(context.Context, *dnssvcsv1.GetDnszoneOptions) *dnssvcsv1.Dnszone); ok {
r0 = rf(ctx, getDnszoneOptions)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*dnssvcsv1.Dnszone)
}
}
var r1 *core.DetailedResponse
if rf, ok := ret.Get(1).(func(context.Context, *dnssvcsv1.GetDnszoneOptions) *core.DetailedResponse); ok {
r1 = rf(ctx, getDnszoneOptions)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*core.DetailedResponse)
}
}
var r2 error
if rf, ok := ret.Get(2).(func(context.Context, *dnssvcsv1.GetDnszoneOptions) error); ok {
r2 = rf(ctx, getDnszoneOptions)
} else {
r2 = ret.Error(2)
}
return r0, r1, r2
}
// ListAllDDNSRecordsWithContext provides a mock function with given fields: ctx, listAllDnsRecordsOptions
func (_m *mockIbmcloudClientInterface) ListAllDDNSRecordsWithContext(ctx context.Context, listAllDnsRecordsOptions *dnsrecordsv1.ListAllDnsRecordsOptions) (*dnsrecordsv1.ListDnsrecordsResp, *core.DetailedResponse, error) {
ret := _m.Called(ctx, listAllDnsRecordsOptions)
var r0 *dnsrecordsv1.ListDnsrecordsResp
if rf, ok := ret.Get(0).(func(context.Context, *dnsrecordsv1.ListAllDnsRecordsOptions) *dnsrecordsv1.ListDnsrecordsResp); ok {
r0 = rf(ctx, listAllDnsRecordsOptions)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*dnsrecordsv1.ListDnsrecordsResp)
}
}
var r1 *core.DetailedResponse
if rf, ok := ret.Get(1).(func(context.Context, *dnsrecordsv1.ListAllDnsRecordsOptions) *core.DetailedResponse); ok {
r1 = rf(ctx, listAllDnsRecordsOptions)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*core.DetailedResponse)
}
}
var r2 error
if rf, ok := ret.Get(2).(func(context.Context, *dnsrecordsv1.ListAllDnsRecordsOptions) error); ok {
r2 = rf(ctx, listAllDnsRecordsOptions)
} else {
r2 = ret.Error(2)
}
return r0, r1, r2
}
// ListDnszonesWithContext provides a mock function with given fields: ctx, listDnszonesOptions
func (_m *mockIbmcloudClientInterface) ListDnszonesWithContext(ctx context.Context, listDnszonesOptions *dnssvcsv1.ListDnszonesOptions) (*dnssvcsv1.ListDnszones, *core.DetailedResponse, error) {
ret := _m.Called(ctx, listDnszonesOptions)
var r0 *dnssvcsv1.ListDnszones
if rf, ok := ret.Get(0).(func(context.Context, *dnssvcsv1.ListDnszonesOptions) *dnssvcsv1.ListDnszones); ok {
r0 = rf(ctx, listDnszonesOptions)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*dnssvcsv1.ListDnszones)
}
}
var r1 *core.DetailedResponse
if rf, ok := ret.Get(1).(func(context.Context, *dnssvcsv1.ListDnszonesOptions) *core.DetailedResponse); ok {
r1 = rf(ctx, listDnszonesOptions)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*core.DetailedResponse)
}
}
var r2 error
if rf, ok := ret.Get(2).(func(context.Context, *dnssvcsv1.ListDnszonesOptions) error); ok {
r2 = rf(ctx, listDnszonesOptions)
} else {
r2 = ret.Error(2)
}
return r0, r1, r2
}
// ListResourceRecordsWithContext provides a mock function with given fields: ctx, listResourceRecordsOptions
func (_m *mockIbmcloudClientInterface) ListResourceRecordsWithContext(ctx context.Context, listResourceRecordsOptions *dnssvcsv1.ListResourceRecordsOptions) (*dnssvcsv1.ListResourceRecords, *core.DetailedResponse, error) {
ret := _m.Called(ctx, listResourceRecordsOptions)
var r0 *dnssvcsv1.ListResourceRecords
if rf, ok := ret.Get(0).(func(context.Context, *dnssvcsv1.ListResourceRecordsOptions) *dnssvcsv1.ListResourceRecords); ok {
r0 = rf(ctx, listResourceRecordsOptions)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*dnssvcsv1.ListResourceRecords)
}
}
var r1 *core.DetailedResponse
if rf, ok := ret.Get(1).(func(context.Context, *dnssvcsv1.ListResourceRecordsOptions) *core.DetailedResponse); ok {
r1 = rf(ctx, listResourceRecordsOptions)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*core.DetailedResponse)
}
}
var r2 error
if rf, ok := ret.Get(2).(func(context.Context, *dnssvcsv1.ListResourceRecordsOptions) error); ok {
r2 = rf(ctx, listResourceRecordsOptions)
} else {
r2 = ret.Error(2)
}
return r0, r1, r2
}
// NewResourceRecordInputRdataRdataARecord provides a mock function with given fields: ip
func (_m *mockIbmcloudClientInterface) NewResourceRecordInputRdataRdataARecord(ip string) (*dnssvcsv1.ResourceRecordInputRdataRdataARecord, error) {
ret := _m.Called(ip)
var r0 *dnssvcsv1.ResourceRecordInputRdataRdataARecord
if rf, ok := ret.Get(0).(func(string) *dnssvcsv1.ResourceRecordInputRdataRdataARecord); ok {
r0 = rf(ip)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*dnssvcsv1.ResourceRecordInputRdataRdataARecord)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(ip)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// NewResourceRecordInputRdataRdataCnameRecord provides a mock function with given fields: cname
func (_m *mockIbmcloudClientInterface) NewResourceRecordInputRdataRdataCnameRecord(cname string) (*dnssvcsv1.ResourceRecordInputRdataRdataCnameRecord, error) {
ret := _m.Called(cname)
var r0 *dnssvcsv1.ResourceRecordInputRdataRdataCnameRecord
if rf, ok := ret.Get(0).(func(string) *dnssvcsv1.ResourceRecordInputRdataRdataCnameRecord); ok {
r0 = rf(cname)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*dnssvcsv1.ResourceRecordInputRdataRdataCnameRecord)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(cname)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// NewResourceRecordInputRdataRdataTxtRecord provides a mock function with given fields: text
func (_m *mockIbmcloudClientInterface) NewResourceRecordInputRdataRdataTxtRecord(text string) (*dnssvcsv1.ResourceRecordInputRdataRdataTxtRecord, error) {
ret := _m.Called(text)
var r0 *dnssvcsv1.ResourceRecordInputRdataRdataTxtRecord
if rf, ok := ret.Get(0).(func(string) *dnssvcsv1.ResourceRecordInputRdataRdataTxtRecord); ok {
r0 = rf(text)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*dnssvcsv1.ResourceRecordInputRdataRdataTxtRecord)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(text)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// NewResourceRecordUpdateInputRdataRdataARecord provides a mock function with given fields: ip
func (_m *mockIbmcloudClientInterface) NewResourceRecordUpdateInputRdataRdataARecord(ip string) (*dnssvcsv1.ResourceRecordUpdateInputRdataRdataARecord, error) {
ret := _m.Called(ip)
var r0 *dnssvcsv1.ResourceRecordUpdateInputRdataRdataARecord
if rf, ok := ret.Get(0).(func(string) *dnssvcsv1.ResourceRecordUpdateInputRdataRdataARecord); ok {
r0 = rf(ip)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*dnssvcsv1.ResourceRecordUpdateInputRdataRdataARecord)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(ip)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// NewResourceRecordUpdateInputRdataRdataCnameRecord provides a mock function with given fields: cname
func (_m *mockIbmcloudClientInterface) NewResourceRecordUpdateInputRdataRdataCnameRecord(cname string) (*dnssvcsv1.ResourceRecordUpdateInputRdataRdataCnameRecord, error) {
ret := _m.Called(cname)
var r0 *dnssvcsv1.ResourceRecordUpdateInputRdataRdataCnameRecord
if rf, ok := ret.Get(0).(func(string) *dnssvcsv1.ResourceRecordUpdateInputRdataRdataCnameRecord); ok {
r0 = rf(cname)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*dnssvcsv1.ResourceRecordUpdateInputRdataRdataCnameRecord)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(cname)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// NewResourceRecordUpdateInputRdataRdataTxtRecord provides a mock function with given fields: text
func (_m *mockIbmcloudClientInterface) NewResourceRecordUpdateInputRdataRdataTxtRecord(text string) (*dnssvcsv1.ResourceRecordUpdateInputRdataRdataTxtRecord, error) {
ret := _m.Called(text)
var r0 *dnssvcsv1.ResourceRecordUpdateInputRdataRdataTxtRecord
if rf, ok := ret.Get(0).(func(string) *dnssvcsv1.ResourceRecordUpdateInputRdataRdataTxtRecord); ok {
r0 = rf(text)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*dnssvcsv1.ResourceRecordUpdateInputRdataRdataTxtRecord)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(string) error); ok {
r1 = rf(text)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// UpdateDNSRecordWithContext provides a mock function with given fields: ctx, updateDnsRecordOptions
func (_m *mockIbmcloudClientInterface) UpdateDNSRecordWithContext(ctx context.Context, updateDnsRecordOptions *dnsrecordsv1.UpdateDnsRecordOptions) (*dnsrecordsv1.DnsrecordResp, *core.DetailedResponse, error) {
ret := _m.Called(ctx, updateDnsRecordOptions)
var r0 *dnsrecordsv1.DnsrecordResp
if rf, ok := ret.Get(0).(func(context.Context, *dnsrecordsv1.UpdateDnsRecordOptions) *dnsrecordsv1.DnsrecordResp); ok {
r0 = rf(ctx, updateDnsRecordOptions)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*dnsrecordsv1.DnsrecordResp)
}
}
var r1 *core.DetailedResponse
if rf, ok := ret.Get(1).(func(context.Context, *dnsrecordsv1.UpdateDnsRecordOptions) *core.DetailedResponse); ok {
r1 = rf(ctx, updateDnsRecordOptions)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*core.DetailedResponse)
}
}
var r2 error
if rf, ok := ret.Get(2).(func(context.Context, *dnsrecordsv1.UpdateDnsRecordOptions) error); ok {
r2 = rf(ctx, updateDnsRecordOptions)
} else {
r2 = ret.Error(2)
}
return r0, r1, r2
}
// UpdateResourceRecordWithContext provides a mock function with given fields: ctx, updateResourceRecordOptions
func (_m *mockIbmcloudClientInterface) UpdateResourceRecordWithContext(ctx context.Context, updateResourceRecordOptions *dnssvcsv1.UpdateResourceRecordOptions) (*dnssvcsv1.ResourceRecord, *core.DetailedResponse, error) {
ret := _m.Called(ctx, updateResourceRecordOptions)
var r0 *dnssvcsv1.ResourceRecord
if rf, ok := ret.Get(0).(func(context.Context, *dnssvcsv1.UpdateResourceRecordOptions) *dnssvcsv1.ResourceRecord); ok {
r0 = rf(ctx, updateResourceRecordOptions)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*dnssvcsv1.ResourceRecord)
}
}
var r1 *core.DetailedResponse
if rf, ok := ret.Get(1).(func(context.Context, *dnssvcsv1.UpdateResourceRecordOptions) *core.DetailedResponse); ok {
r1 = rf(ctx, updateResourceRecordOptions)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*core.DetailedResponse)
}
}
var r2 error
if rf, ok := ret.Get(2).(func(context.Context, *dnssvcsv1.UpdateResourceRecordOptions) error); ok {
r2 = rf(ctx, updateResourceRecordOptions)
} else {
r2 = ret.Error(2)
}
return r0, r1, r2
}
type mockSource struct {
mock.Mock
}
// Endpoints provides a mock function with given fields: ctx
func (_m *mockSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error) {
ret := _m.Called(ctx)
var r0 []*endpoint.Endpoint
if rf, ok := ret.Get(0).(func(context.Context) []*endpoint.Endpoint); ok {
r0 = rf(ctx)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*endpoint.Endpoint)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
r1 = rf(ctx)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// AddEventHandler provides a mock function with given fields: _a0, _a1
func (_m *mockSource) AddEventHandler(_a0 context.Context, _a1 func()) {
_m.Called(_a0, _a1)
}

View File

@ -26,7 +26,6 @@ const (
AWSPrefix = "external-dns.alpha.kubernetes.io/aws-"
SCWPrefix = "external-dns.alpha.kubernetes.io/scw-"
IBMCloudPrefix = "external-dns.alpha.kubernetes.io/ibmcloud-"
WebhookPrefix = "external-dns.alpha.kubernetes.io/webhook-"
CloudflarePrefix = "external-dns.alpha.kubernetes.io/cloudflare-"

View File

@ -45,12 +45,6 @@ func ProviderSpecificAnnotations(annotations map[string]string) (endpoint.Provid
Name: fmt.Sprintf("scw/%s", attr),
Value: v,
})
} else if strings.HasPrefix(k, IBMCloudPrefix) {
attr := strings.TrimPrefix(k, IBMCloudPrefix)
providerSpecificAnnotations = append(providerSpecificAnnotations, endpoint.ProviderSpecificProperty{
Name: fmt.Sprintf("ibmcloud-%s", attr),
Value: v,
})
} else if strings.HasPrefix(k, WebhookPrefix) {
// Support for wildcard annotations for webhook providers
attr := strings.TrimPrefix(k, WebhookPrefix)

View File

@ -300,19 +300,6 @@ func TestGetProviderSpecificIdentifierAnnotations(t *testing.T) {
},
expectedIdentifier: "id1",
},
{
title: "ibmcloud- provider specific annotations are set correctly",
annotations: map[string]string{
"external-dns.alpha.kubernetes.io/ibmcloud-annotation-1": "value 1",
SetIdentifierKey: "id1",
"external-dns.alpha.kubernetes.io/ibmcloud-annotation-2": "value 2",
},
expectedResult: map[string]string{
"ibmcloud-annotation-1": "value 1",
"ibmcloud-annotation-2": "value 2",
},
expectedIdentifier: "id1",
},
{
title: "webhook- provider specific annotations are set correctly",
annotations: map[string]string{