mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2025-08-06 17:46:57 +02:00
chore(source): code cleanup
This commit is contained in:
commit
fe83c0d2d0
11
.github/workflows/ci.yaml
vendored
11
.github/workflows/ci.yaml
vendored
@ -17,7 +17,11 @@ jobs:
|
|||||||
checks: write # to create a new check based on the results (shogo82148/actions-goveralls)
|
checks: write # to create a new check based on the results (shogo82148/actions-goveralls)
|
||||||
|
|
||||||
name: Build
|
name: Build
|
||||||
runs-on: ubuntu-latest
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
# tests for target OS
|
||||||
|
os: [ubuntu-latest, macos-latest]
|
||||||
steps:
|
steps:
|
||||||
|
|
||||||
- name: Check out code into the Go module directory
|
- name: Check out code into the Go module directory
|
||||||
@ -27,6 +31,7 @@ jobs:
|
|||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
|
check-latest: true
|
||||||
id: go
|
id: go
|
||||||
|
|
||||||
- name: Install CI
|
- name: Install CI
|
||||||
@ -37,7 +42,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
apt update
|
apt update
|
||||||
apt install -y make gcc libc-dev git
|
apt install -y make gcc libc-dev git
|
||||||
if: github.actor == 'nektos/act'
|
if: github.actor == 'nektos/act' && matrix.os == 'ubuntu-latest'
|
||||||
|
|
||||||
- name: Test
|
- name: Test
|
||||||
run: make test
|
run: make test
|
||||||
@ -46,5 +51,5 @@ jobs:
|
|||||||
uses: shogo82148/actions-goveralls@v1
|
uses: shogo82148/actions-goveralls@v1
|
||||||
with:
|
with:
|
||||||
path-to-profile: profile.cov
|
path-to-profile: profile.cov
|
||||||
if: github.actor != 'nektos/act'
|
if: github.actor != 'nektos/act' && matrix.os == 'ubuntu-latest'
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
|
2
.github/workflows/dependency-update.yaml
vendored
2
.github/workflows/dependency-update.yaml
vendored
@ -17,7 +17,7 @@ jobs:
|
|||||||
uses: actions/checkout@v4.2.2
|
uses: actions/checkout@v4.2.2
|
||||||
# https://github.com/renovatebot/github-action
|
# https://github.com/renovatebot/github-action
|
||||||
- name: self-hosted renovate
|
- name: self-hosted renovate
|
||||||
uses: renovatebot/github-action@v41.0.18
|
uses: renovatebot/github-action@v41.0.22
|
||||||
with:
|
with:
|
||||||
# https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication
|
# https://docs.github.com/en/actions/security-for-github-actions/security-guides/automatic-token-authentication
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
2
.github/workflows/docs.yaml
vendored
2
.github/workflows/docs.yaml
vendored
@ -19,7 +19,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
|
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
||||||
with:
|
with:
|
||||||
python-version: "3.12"
|
python-version: "3.12"
|
||||||
cache: "pip"
|
cache: "pip"
|
||||||
|
2
.github/workflows/json-yaml-validate.yml
vendored
2
.github/workflows/json-yaml-validate.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
|||||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||||
|
|
||||||
- name: json-yaml-validate
|
- name: json-yaml-validate
|
||||||
uses: GrantBirki/json-yaml-validate@v3.2.1
|
uses: GrantBirki/json-yaml-validate@v3.3.0
|
||||||
with:
|
with:
|
||||||
comment: "true" # enable comment mode
|
comment: "true" # enable comment mode
|
||||||
yaml_exclude_regex: "(charts/external-dns/templates.*|mkdocs.yml)"
|
yaml_exclude_regex: "(charts/external-dns/templates.*|mkdocs.yml)"
|
||||||
|
2
.github/workflows/lint-test-chart.yaml
vendored
2
.github/workflows/lint-test-chart.yaml
vendored
@ -78,7 +78,7 @@ jobs:
|
|||||||
run: ah lint --kind helm || exit 1
|
run: ah lint --kind helm || exit 1
|
||||||
|
|
||||||
- name: Install Python
|
- name: Install Python
|
||||||
uses: actions/setup-python@8d9ed9ac5c53483de85588cdf95a591a75ab9f55 # v5.5.0
|
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
|
||||||
with:
|
with:
|
||||||
token: ${{ github.token }}
|
token: ${{ github.token }}
|
||||||
python-version: "3.x"
|
python-version: "3.x"
|
||||||
|
6
.github/workflows/lint.yaml
vendored
6
.github/workflows/lint.yaml
vendored
@ -26,7 +26,7 @@ jobs:
|
|||||||
files: '.'
|
files: '.'
|
||||||
config_file: ".markdownlint.json"
|
config_file: ".markdownlint.json"
|
||||||
|
|
||||||
- name: Set up Go 1.x
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version-file: go.mod
|
go-version-file: go.mod
|
||||||
@ -44,11 +44,11 @@ jobs:
|
|||||||
|
|
||||||
# https://github.com/golangci/golangci-lint-action?tab=readme-ov-file#verify
|
# https://github.com/golangci/golangci-lint-action?tab=readme-ov-file#verify
|
||||||
- name: Verify linter configuration and Lint go code
|
- name: Verify linter configuration and Lint go code
|
||||||
uses: golangci/golangci-lint-action@v7
|
uses: golangci/golangci-lint-action@v8
|
||||||
with:
|
with:
|
||||||
verify: true
|
verify: true
|
||||||
args: --timeout=30m
|
args: --timeout=30m
|
||||||
version: v2.0
|
version: v2.1
|
||||||
|
|
||||||
# Run Spectral
|
# Run Spectral
|
||||||
- name: Lint OpenAPI spec
|
- name: Lint OpenAPI spec
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
|
# https://golangci-lint.run/usage/configuration/
|
||||||
version: "2"
|
version: "2"
|
||||||
linters:
|
linters:
|
||||||
default: none
|
default: none
|
||||||
enable:
|
enable: # golangci-lint help linters
|
||||||
- dogsled
|
- dogsled
|
||||||
- goprintffuncname
|
- goprintffuncname
|
||||||
- govet
|
- govet
|
||||||
@ -13,6 +14,9 @@ linters:
|
|||||||
- unconvert
|
- unconvert
|
||||||
- unused
|
- unused
|
||||||
- whitespace
|
- whitespace
|
||||||
|
- predeclared # Find code that shadows one of Go's predeclared identifiers
|
||||||
|
- sloglint # Ensure consistent code style when using log/slog
|
||||||
|
- asciicheck # Checks that all code identifiers does not have non-ASCII symbols in the name
|
||||||
settings:
|
settings:
|
||||||
exhaustive:
|
exhaustive:
|
||||||
default-signifies-exhaustive: false
|
default-signifies-exhaustive: false
|
||||||
|
@ -12,6 +12,8 @@ We have full documentation on how to get started contributing here:
|
|||||||
- [Kubernetes Contributor Guide](https://git.k8s.io/community/contributors/guide) - Main contributor documentation, or you can just jump directly to the [contributing section](https://git.k8s.io/community/contributors/guide#contributing)
|
- [Kubernetes Contributor Guide](https://git.k8s.io/community/contributors/guide) - Main contributor documentation, or you can just jump directly to the [contributing section](https://git.k8s.io/community/contributors/guide#contributing)
|
||||||
- [Contributor Cheat Sheet](https://git.k8s.io/community/contributors/guide/contributor-cheatsheet) - Common resources for existing developers
|
- [Contributor Cheat Sheet](https://git.k8s.io/community/contributors/guide/contributor-cheatsheet) - Common resources for existing developers
|
||||||
|
|
||||||
|
This project follows the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) specification on PR title. The explicit commit history is used, among other things, to provide a readable changelog in release notes.
|
||||||
|
|
||||||
## Mentorship
|
## Mentorship
|
||||||
|
|
||||||
- [Mentoring Initiatives](https://git.k8s.io/community/mentoring) - We have a diverse set of mentorship programs available that are always looking for volunteers!
|
- [Mentoring Initiatives](https://git.k8s.io/community/mentoring) - We have a diverse set of mentorship programs available that are always looking for volunteers!
|
||||||
|
13
Makefile
13
Makefile
@ -32,10 +32,6 @@ else
|
|||||||
CONTROLLER_GEN=$(shell which controller-gen)
|
CONTROLLER_GEN=$(shell which controller-gen)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
#? controller-gen-install: download controller-gen if necessary
|
|
||||||
controller-gen-install:
|
|
||||||
@scripts/install-tools.sh --generator
|
|
||||||
|
|
||||||
#? golangci-lint-install: Install golangci-lint tool
|
#? golangci-lint-install: Install golangci-lint tool
|
||||||
golangci-lint-install:
|
golangci-lint-install:
|
||||||
@scripts/install-tools.sh --golangci
|
@scripts/install-tools.sh --golangci
|
||||||
@ -67,10 +63,11 @@ oas-lint:
|
|||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint: licensecheck go-lint oas-lint
|
lint: licensecheck go-lint oas-lint
|
||||||
|
|
||||||
#? crd: Generates CRD using controller-gen
|
#? crd: Generates CRD using controller-gen and copy it into chart
|
||||||
.PHONY: crd
|
.PHONY: crd
|
||||||
crd: controller-gen-install
|
crd: controller-gen-install
|
||||||
${CONTROLLER_GEN} crd:crdVersions=v1 paths="./endpoint/..." output:crd:stdout > docs/contributing/crd-source/crd-manifest.yaml
|
${CONTROLLER_GEN} crd:crdVersions=v1 paths="./endpoint/..." output:crd:stdout > config/crd/standard/dnsendpoint.yaml
|
||||||
|
cp -f config/crd/standard/dnsendpoint.yaml charts/external-dns/crds/dnsendpoint.yaml
|
||||||
|
|
||||||
#? test: The verify target runs tasks similar to the CI tasks, but without code coverage
|
#? test: The verify target runs tasks similar to the CI tasks, but without code coverage
|
||||||
.PHONY: test
|
.PHONY: test
|
||||||
@ -201,3 +198,7 @@ helm-template:
|
|||||||
helm-lint:
|
helm-lint:
|
||||||
scripts/helm-tools.sh --schema
|
scripts/helm-tools.sh --schema
|
||||||
scripts/helm-tools.sh --docs
|
scripts/helm-tools.sh --docs
|
||||||
|
|
||||||
|
.PHONY: go-dependency
|
||||||
|
go-dependency: ## Dependency maintanance
|
||||||
|
go mod tidy
|
||||||
|
@ -18,6 +18,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
## [UNRELEASED]
|
## [UNRELEASED]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Allow extraArgs to also be a map enabling overrides of individual values ([#5293](https://github.com/kubernetes-sigs/external-dns/pull/5293)) _@frittentheke
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed wrong type definitions for webhook probes. ([#5297](https://github.com/kubernetes-sigs/external-dns/pull/5297)) _@semnell_
|
||||||
|
|
||||||
## [v1.16.1] - 2025-04-10
|
## [v1.16.1] - 2025-04-10
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
@ -104,7 +104,7 @@ If `namespaced` is set to `true`, please ensure that `sources` my only contains
|
|||||||
| enabled | bool | `nil` | No effect - reserved for use in sub-charting. |
|
| enabled | bool | `nil` | No effect - reserved for use in sub-charting. |
|
||||||
| env | list | `[]` | [Environment variables](https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/) for the `external-dns` container. |
|
| env | list | `[]` | [Environment variables](https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/) for the `external-dns` container. |
|
||||||
| excludeDomains | list | `[]` | Intentionally exclude domains from being managed. |
|
| excludeDomains | list | `[]` | Intentionally exclude domains from being managed. |
|
||||||
| extraArgs | list | `[]` | Extra arguments to provide to _ExternalDNS_. |
|
| extraArgs | object | `{}` | Extra arguments to provide to _ExternalDNS_. An array or map can be used, with maps allowing for value overrides; maps also support slice values to use the same arg multiple times. |
|
||||||
| extraContainers | object | `{}` | Extra containers to add to the `Deployment`. |
|
| extraContainers | object | `{}` | Extra containers to add to the `Deployment`. |
|
||||||
| extraVolumeMounts | list | `[]` | Extra [volume mounts](https://kubernetes.io/docs/concepts/storage/volumes/) for the `external-dns` container. |
|
| extraVolumeMounts | list | `[]` | Extra [volume mounts](https://kubernetes.io/docs/concepts/storage/volumes/) for the `external-dns` container. |
|
||||||
| extraVolumes | list | `[]` | Extra [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) for the `Pod`. |
|
| extraVolumes | list | `[]` | Extra [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) for the `Pod`. |
|
||||||
@ -180,7 +180,7 @@ If `namespaced` is set to `true`, please ensure that `sources` my only contains
|
|||||||
| tolerations | list | `[]` | Node taints which will be tolerated for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). |
|
| tolerations | list | `[]` | Node taints which will be tolerated for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). |
|
||||||
| topologySpreadConstraints | list | `[]` | Topology spread constraints for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). If an explicit label selector is not provided one will be created from the pod selector labels. |
|
| topologySpreadConstraints | list | `[]` | Topology spread constraints for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). If an explicit label selector is not provided one will be created from the pod selector labels. |
|
||||||
| triggerLoopOnEvent | bool | `false` | If `true`, triggers run loop on create/update/delete events in addition of regular interval. |
|
| triggerLoopOnEvent | bool | `false` | If `true`, triggers run loop on create/update/delete events in addition of regular interval. |
|
||||||
| txtOwnerId | string | `nil` | Specify an identifier for this instance of _ExternalDNS_ wWhen using a registry other than `noop`. |
|
| txtOwnerId | string | `nil` | Specify an identifier for this instance of _ExternalDNS_ when using a registry other than `noop`. |
|
||||||
| txtPrefix | string | `nil` | Specify a prefix for the domain names of TXT records created for the `txt` registry. Mutually exclusive with `txtSuffix`. |
|
| txtPrefix | string | `nil` | Specify a prefix for the domain names of TXT records created for the `txt` registry. Mutually exclusive with `txtSuffix`. |
|
||||||
| txtSuffix | string | `nil` | Specify a suffix for the domain names of TXT records created for the `txt` registry. Mutually exclusive with `txtPrefix`. |
|
| txtSuffix | string | `nil` | Specify a suffix for the domain names of TXT records created for the `txt` registry. Mutually exclusive with `txtPrefix`. |
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
|
---
|
||||||
apiVersion: apiextensions.k8s.io/v1
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
kind: CustomResourceDefinition
|
kind: CustomResourceDefinition
|
||||||
metadata:
|
metadata:
|
||||||
name: dnsendpoints.externaldns.k8s.io
|
|
||||||
annotations:
|
annotations:
|
||||||
api-approved.kubernetes.io: https://github.com/kubernetes-sigs/external-dns/pull/2007
|
api-approved.kubernetes.io: https://github.com/kubernetes-sigs/external-dns/pull/2007
|
||||||
|
controller-gen.kubebuilder.io/version: v0.17.2
|
||||||
|
name: dnsendpoints.externaldns.k8s.io
|
||||||
spec:
|
spec:
|
||||||
group: externaldns.k8s.io
|
group: externaldns.k8s.io
|
||||||
names:
|
names:
|
||||||
@ -13,90 +15,86 @@ spec:
|
|||||||
singular: dnsendpoint
|
singular: dnsendpoint
|
||||||
scope: Namespaced
|
scope: Namespaced
|
||||||
versions:
|
versions:
|
||||||
- name: v1alpha1
|
- name: v1alpha1
|
||||||
schema:
|
schema:
|
||||||
openAPIV3Schema:
|
openAPIV3Schema:
|
||||||
properties:
|
properties:
|
||||||
apiVersion:
|
apiVersion:
|
||||||
description: |-
|
description: |-
|
||||||
APIVersion defines the versioned schema of this representation of an object.
|
APIVersion defines the versioned schema of this representation of an object.
|
||||||
Servers should convert recognized schemas to the latest internal value, and
|
Servers should convert recognized schemas to the latest internal value, and
|
||||||
may reject unrecognized values.
|
may reject unrecognized values.
|
||||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||||
type: string
|
type: string
|
||||||
kind:
|
kind:
|
||||||
description: |-
|
description: |-
|
||||||
Kind is a string value representing the REST resource this object represents.
|
Kind is a string value representing the REST resource this object represents.
|
||||||
Servers may infer this from the endpoint the client submits requests to.
|
Servers may infer this from the endpoint the client submits requests to.
|
||||||
Cannot be updated.
|
Cannot be updated.
|
||||||
In CamelCase.
|
In CamelCase.
|
||||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||||
type: string
|
type: string
|
||||||
metadata:
|
metadata:
|
||||||
type: object
|
type: object
|
||||||
spec:
|
spec:
|
||||||
description: DNSEndpointSpec defines the desired state of DNSEndpoint
|
description: DNSEndpointSpec defines the desired state of DNSEndpoint
|
||||||
properties:
|
properties:
|
||||||
endpoints:
|
endpoints:
|
||||||
items:
|
items:
|
||||||
description:
|
description: Endpoint is a high-level way of a connection between
|
||||||
Endpoint is a high-level way of a connection between
|
a service and an IP
|
||||||
a service and an IP
|
properties:
|
||||||
properties:
|
dnsName:
|
||||||
dnsName:
|
description: The hostname of the DNS record
|
||||||
description: The hostname of the DNS record
|
type: string
|
||||||
|
labels:
|
||||||
|
additionalProperties:
|
||||||
type: string
|
type: string
|
||||||
labels:
|
description: Labels stores labels defined for the Endpoint
|
||||||
additionalProperties:
|
type: object
|
||||||
type: string
|
providerSpecific:
|
||||||
description: Labels stores labels defined for the Endpoint
|
description: ProviderSpecific stores provider specific config
|
||||||
|
items:
|
||||||
|
description: ProviderSpecificProperty holds the name and value
|
||||||
|
of a configuration which is specific to individual DNS providers
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
value:
|
||||||
|
type: string
|
||||||
type: object
|
type: object
|
||||||
providerSpecific:
|
type: array
|
||||||
description: ProviderSpecific stores provider specific config
|
recordTTL:
|
||||||
items:
|
description: TTL for the record
|
||||||
description:
|
format: int64
|
||||||
ProviderSpecificProperty holds the name and value
|
type: integer
|
||||||
of a configuration which is specific to individual DNS providers
|
recordType:
|
||||||
properties:
|
description: RecordType type of record, e.g. CNAME, A, AAAA,
|
||||||
name:
|
SRV, TXT etc
|
||||||
type: string
|
type: string
|
||||||
value:
|
setIdentifier:
|
||||||
type: string
|
description: Identifier to distinguish multiple records with
|
||||||
type: object
|
the same name and type (e.g. Route53 records with routing
|
||||||
type: array
|
policies other than 'simple')
|
||||||
recordTTL:
|
type: string
|
||||||
description: TTL for the record
|
targets:
|
||||||
format: int64
|
description: The targets the DNS record points to
|
||||||
type: integer
|
items:
|
||||||
recordType:
|
|
||||||
description:
|
|
||||||
RecordType type of record, e.g. CNAME, A, AAAA,
|
|
||||||
SRV, TXT etc
|
|
||||||
type: string
|
type: string
|
||||||
setIdentifier:
|
type: array
|
||||||
description:
|
type: object
|
||||||
Identifier to distinguish multiple records with
|
type: array
|
||||||
the same name and type (e.g. Route53 records with routing
|
type: object
|
||||||
policies other than 'simple')
|
status:
|
||||||
type: string
|
description: DNSEndpointStatus defines the observed state of DNSEndpoint
|
||||||
targets:
|
properties:
|
||||||
description: The targets the DNS record points to
|
observedGeneration:
|
||||||
items:
|
description: The generation observed by the external-dns controller.
|
||||||
type: string
|
format: int64
|
||||||
type: array
|
type: integer
|
||||||
type: object
|
type: object
|
||||||
type: array
|
type: object
|
||||||
type: object
|
served: true
|
||||||
status:
|
storage: true
|
||||||
description: DNSEndpointStatus defines the observed state of DNSEndpoint
|
subresources:
|
||||||
properties:
|
status: {}
|
||||||
observedGeneration:
|
|
||||||
description: The generation observed by the external-dns controller.
|
|
||||||
format: int64
|
|
||||||
type: integer
|
|
||||||
type: object
|
|
||||||
type: object
|
|
||||||
served: true
|
|
||||||
storage: true
|
|
||||||
subresources:
|
|
||||||
status: {}
|
|
||||||
|
@ -124,9 +124,26 @@ spec:
|
|||||||
- --managed-record-types={{ . }}
|
- --managed-record-types={{ . }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
- --provider={{ $providerName }}
|
- --provider={{ $providerName }}
|
||||||
{{- range .Values.extraArgs }}
|
{{- if kindIs "map" .Values.extraArgs }}
|
||||||
|
{{- range $key, $value := .Values.extraArgs }}
|
||||||
|
{{- if not (kindIs "invalid" $value) }}
|
||||||
|
{{- if kindIs "slice" $value }}
|
||||||
|
{{- range $value }}
|
||||||
|
- --{{ $key }}={{ tpl (. | toString) $ }}
|
||||||
|
{{- end }}
|
||||||
|
{{- else }}
|
||||||
|
- --{{ $key }}={{ tpl ($value | toString) $ }}
|
||||||
|
{{- end }}
|
||||||
|
{{- else }}
|
||||||
|
- --{{ $key }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if kindIs "slice" .Values.extraArgs }}
|
||||||
|
{{- range .Values.extraArgs }}
|
||||||
- {{ tpl . $ }}
|
- {{ tpl . $ }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
|
@ -103,6 +103,60 @@ tests:
|
|||||||
- --zone-id-filter=/hostedzone/Z00004
|
- --zone-id-filter=/hostedzone/Z00004
|
||||||
- --zone-id-filter=/hostedzone/Z00005
|
- --zone-id-filter=/hostedzone/Z00005
|
||||||
|
|
||||||
|
|
||||||
|
- it: should allow 'extraArgs' to be a slice
|
||||||
|
set:
|
||||||
|
extraArgs:
|
||||||
|
- --extraArgA=valueA
|
||||||
|
- --extraArgB=valueB
|
||||||
|
- --extraArgC=valueC-1
|
||||||
|
- --extraArgC=valueC-2
|
||||||
|
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[?(@.name == "external-dns")].args
|
||||||
|
value:
|
||||||
|
- --log-level=info
|
||||||
|
- --log-format=text
|
||||||
|
- --interval=1m
|
||||||
|
- --source=service
|
||||||
|
- --source=ingress
|
||||||
|
- --policy=upsert-only
|
||||||
|
- --registry=txt
|
||||||
|
- --provider=aws
|
||||||
|
- --extraArgA=valueA
|
||||||
|
- --extraArgB=valueB
|
||||||
|
- --extraArgC=valueC-1
|
||||||
|
- --extraArgC=valueC-2
|
||||||
|
|
||||||
|
|
||||||
|
- it: should allow 'extraArgs' to be a map with its entries potentially being slices (lists) themselves
|
||||||
|
set:
|
||||||
|
extraArgs:
|
||||||
|
extraArgA: valueA
|
||||||
|
extraArgB: valueB
|
||||||
|
extraArgC:
|
||||||
|
- valueC-1
|
||||||
|
- valueC-2
|
||||||
|
|
||||||
|
asserts:
|
||||||
|
- equal:
|
||||||
|
path: spec.template.spec.containers[?(@.name == "external-dns")].args
|
||||||
|
value:
|
||||||
|
- --log-level=info
|
||||||
|
- --log-format=text
|
||||||
|
- --interval=1m
|
||||||
|
- --source=service
|
||||||
|
- --source=ingress
|
||||||
|
- --policy=upsert-only
|
||||||
|
- --registry=txt
|
||||||
|
- --provider=aws
|
||||||
|
- --extraArgA=valueA
|
||||||
|
- --extraArgB=valueB
|
||||||
|
- --extraArgC=valueC-1
|
||||||
|
- --extraArgC=valueC-2
|
||||||
|
|
||||||
|
|
||||||
- it: should throw error when txtPrefix and txtSuffix are set
|
- it: should throw error when txtPrefix and txtSuffix are set
|
||||||
set:
|
set:
|
||||||
txtPrefix: "test-prefix"
|
txtPrefix: "test-prefix"
|
||||||
|
@ -50,3 +50,15 @@ tests:
|
|||||||
labelFilter: "mydomain.io/enable-dns-record in (true)"
|
labelFilter: "mydomain.io/enable-dns-record in (true)"
|
||||||
asserts:
|
asserts:
|
||||||
- notFailedTemplate: {}
|
- notFailedTemplate: {}
|
||||||
|
|
||||||
|
- it: should not fail when livenessProbe is null
|
||||||
|
set:
|
||||||
|
livenessProbe: null
|
||||||
|
asserts:
|
||||||
|
- notFailedTemplate: {}
|
||||||
|
|
||||||
|
- it: should not fail when readinessProbe is null
|
||||||
|
set:
|
||||||
|
readinessProbe: null
|
||||||
|
asserts:
|
||||||
|
- notFailedTemplate: {}
|
||||||
|
@ -64,9 +64,11 @@
|
|||||||
"items": {
|
"items": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
|
"properties": {},
|
||||||
"type": [
|
"type": [
|
||||||
"array",
|
"array",
|
||||||
"null"
|
"null",
|
||||||
|
"object"
|
||||||
],
|
],
|
||||||
"uniqueItems": true
|
"uniqueItems": true
|
||||||
},
|
},
|
||||||
@ -308,30 +310,51 @@
|
|||||||
"livenessProbe": {
|
"livenessProbe": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"failureThreshold": {
|
"failureThreshold": {
|
||||||
"type": "integer"
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"httpGet": {
|
"httpGet": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string"
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"port": {
|
"port": {
|
||||||
"type": "string"
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"initialDelaySeconds": {
|
"initialDelaySeconds": {
|
||||||
"type": "integer"
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"periodSeconds": {
|
"periodSeconds": {
|
||||||
"type": "integer"
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"successThreshold": {
|
"successThreshold": {
|
||||||
"type": "integer"
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"timeoutSeconds": {
|
"timeoutSeconds": {
|
||||||
"type": "integer"
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
@ -339,30 +362,51 @@
|
|||||||
"readinessProbe": {
|
"readinessProbe": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"failureThreshold": {
|
"failureThreshold": {
|
||||||
"type": "integer"
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"httpGet": {
|
"httpGet": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"path": {
|
"path": {
|
||||||
"type": "string"
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"port": {
|
"port": {
|
||||||
"type": "string"
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"string"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"initialDelaySeconds": {
|
"initialDelaySeconds": {
|
||||||
"type": "integer"
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"periodSeconds": {
|
"periodSeconds": {
|
||||||
"type": "integer"
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"successThreshold": {
|
"successThreshold": {
|
||||||
"type": "integer"
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
"timeoutSeconds": {
|
"timeoutSeconds": {
|
||||||
"type": "integer"
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
|
@ -216,7 +216,7 @@ policy: upsert-only # @schema enum:[sync, upsert-only]; type:string; default: "
|
|||||||
# -- Specify the registry for storing ownership and labels.
|
# -- Specify the registry for storing ownership and labels.
|
||||||
# Valid values are `txt`, `aws-sd`, `dynamodb` & `noop`.
|
# Valid values are `txt`, `aws-sd`, `dynamodb` & `noop`.
|
||||||
registry: txt # @schema enum:[txt, aws-sd, dynamodb, noop]; default: "txt"
|
registry: txt # @schema enum:[txt, aws-sd, dynamodb, noop]; default: "txt"
|
||||||
# -- (string) Specify an identifier for this instance of _ExternalDNS_ wWhen using a registry other than `noop`.
|
# -- (string) Specify an identifier for this instance of _ExternalDNS_ when using a registry other than `noop`.
|
||||||
txtOwnerId: # @schema type:[string, null]; default: null
|
txtOwnerId: # @schema type:[string, null]; default: null
|
||||||
# -- (string) Specify a prefix for the domain names of TXT records created for the `txt` registry.
|
# -- (string) Specify a prefix for the domain names of TXT records created for the `txt` registry.
|
||||||
# Mutually exclusive with `txtSuffix`.
|
# Mutually exclusive with `txtSuffix`.
|
||||||
@ -263,24 +263,24 @@ provider: # @schema type: [object, string];
|
|||||||
# @default -- See _values.yaml_
|
# @default -- See _values.yaml_
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /healthz
|
path: /healthz # @schema type:[string, null]; default: null
|
||||||
port: http-webhook
|
port: http-webhook # @schema type:[integer,string]; default: string
|
||||||
initialDelaySeconds: 10
|
initialDelaySeconds: 10 # @schema type:[integer, null]; default: null
|
||||||
periodSeconds: 10
|
periodSeconds: 10 # @schema type:[integer, null]; default: null
|
||||||
timeoutSeconds: 5
|
timeoutSeconds: 5 # @schema type:[integer, null]; default: null
|
||||||
failureThreshold: 2
|
failureThreshold: 2 # @schema type:[integer, null]; default: null
|
||||||
successThreshold: 1
|
successThreshold: 1 # @schema type:[integer, null]; default: null
|
||||||
# -- [Readiness probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) configuration for the `webhook` container.
|
# -- [Readiness probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) configuration for the `webhook` container.
|
||||||
# @default -- See _values.yaml_
|
# @default -- See _values.yaml_
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /healthz
|
path: /healthz # @schema type:[string, null]; default: null
|
||||||
port: http-webhook
|
port: http-webhook # @schema type:[integer,string]; default: string
|
||||||
initialDelaySeconds: 5
|
initialDelaySeconds: 5 # @schema type:[integer, null]; default: null
|
||||||
periodSeconds: 10
|
periodSeconds: 10 # @schema type:[integer, null]; default: null
|
||||||
timeoutSeconds: 5
|
timeoutSeconds: 5 # @schema type:[integer, null]; default: null
|
||||||
failureThreshold: 6
|
failureThreshold: 6 # @schema type:[integer, null]; default: null
|
||||||
successThreshold: 1
|
successThreshold: 1 # @schema type:[integer, null]; default: null
|
||||||
service:
|
service:
|
||||||
# -- Webhook exposed HTTP port for the service.
|
# -- Webhook exposed HTTP port for the service.
|
||||||
port: 8080
|
port: 8080
|
||||||
@ -296,7 +296,8 @@ provider: # @schema type: [object, string];
|
|||||||
relabelings: []
|
relabelings: []
|
||||||
|
|
||||||
# -- Extra arguments to provide to _ExternalDNS_.
|
# -- Extra arguments to provide to _ExternalDNS_.
|
||||||
extraArgs: [] # @schema type: [array, null]; item: string; uniqueItems: true;
|
# An array or map can be used, with maps allowing for value overrides; maps also support slice values to use the same arg multiple times.
|
||||||
|
extraArgs: {} # @schema type: [array, null, object]; item: string; uniqueItems: true;
|
||||||
|
|
||||||
secretConfiguration:
|
secretConfiguration:
|
||||||
# -- If `true`, create a `Secret` to store sensitive provider configuration (**DEPRECATED**).
|
# -- If `true`, create a `Secret` to store sensitive provider configuration (**DEPRECATED**).
|
||||||
|
@ -4,7 +4,7 @@ kind: CustomResourceDefinition
|
|||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
api-approved.kubernetes.io: https://github.com/kubernetes-sigs/external-dns/pull/2007
|
api-approved.kubernetes.io: https://github.com/kubernetes-sigs/external-dns/pull/2007
|
||||||
controller-gen.kubebuilder.io/version: v0.15.0
|
controller-gen.kubebuilder.io/version: v0.17.2
|
||||||
name: dnsendpoints.externaldns.k8s.io
|
name: dnsendpoints.externaldns.k8s.io
|
||||||
spec:
|
spec:
|
||||||
group: externaldns.k8s.io
|
group: externaldns.k8s.io
|
@ -18,6 +18,7 @@ package controller
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -29,10 +30,9 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"context"
|
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
"sigs.k8s.io/external-dns/endpoint"
|
"sigs.k8s.io/external-dns/endpoint"
|
||||||
"sigs.k8s.io/external-dns/pkg/apis/externaldns"
|
"sigs.k8s.io/external-dns/pkg/apis/externaldns"
|
||||||
"sigs.k8s.io/external-dns/plan"
|
"sigs.k8s.io/external-dns/plan"
|
||||||
@ -219,18 +219,45 @@ func TestHandleSigterm(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServeMetrics(t *testing.T) {
|
func getRandomPort() (int, error) {
|
||||||
l, _ := net.Listen("tcp", ":0")
|
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
|
||||||
_ = l.Close()
|
if err != nil {
|
||||||
_, port, _ := net.SplitHostPort(l.Addr().String())
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
go serveMetrics(fmt.Sprintf(":%s", port))
|
l, err := net.ListenTCP("tcp", addr)
|
||||||
resp, err := http.Get(fmt.Sprintf("http://localhost:%s", port) + "/healthz")
|
if err != nil {
|
||||||
assert.NoError(t, err)
|
return 0, err
|
||||||
|
}
|
||||||
|
defer l.Close()
|
||||||
|
return l.Addr().(*net.TCPAddr).Port, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestServeMetrics(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
port, err := getRandomPort()
|
||||||
|
require.NoError(t, err)
|
||||||
|
addresse := fmt.Sprintf("localhost:%d", port)
|
||||||
|
|
||||||
|
go serveMetrics(fmt.Sprintf(":%d", port))
|
||||||
|
|
||||||
|
// Wait for the TCP socket to be ready
|
||||||
|
require.Eventually(t, func() bool {
|
||||||
|
conn, err := net.Dial("tcp", addresse)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
_ = conn.Close()
|
||||||
|
return true
|
||||||
|
}, 1*time.Second, 5*time.Millisecond, "server not ready with port open in time")
|
||||||
|
|
||||||
|
resp, err := http.Get(fmt.Sprintf("http://%s/healthz", addresse))
|
||||||
|
require.NoError(t, err)
|
||||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
|
||||||
resp, err = http.Get(fmt.Sprintf("http://localhost:%s", port) + "/metrics")
|
resp, err = http.Get(fmt.Sprintf("http://%s/metrics", addresse))
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,7 +335,6 @@ func (m *MockProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *MockProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
|
func (p *MockProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
306
docs/advanced/fqdn-templating.md
Normal file
306
docs/advanced/fqdn-templating.md
Normal file
@ -0,0 +1,306 @@
|
|||||||
|
# FQDN Templating Guide
|
||||||
|
|
||||||
|
## What is FQDN Templating?
|
||||||
|
|
||||||
|
**FQDN templating** is a feature that allows to dynamically construct Fully Qualified Domain Names (FQDNs) using a Go templating engine.
|
||||||
|
Instead of relying solely on annotations or static names, you can use metadata from Kubernetes objects—such as service names, namespaces, and labels—to generate DNS records programmatically and dynamically.
|
||||||
|
|
||||||
|
This is useful for:
|
||||||
|
|
||||||
|
- Creating consistent naming conventions across environments.
|
||||||
|
- Reducing boilerplate annotations.
|
||||||
|
- Supporting multi-tenant or dynamic environments.
|
||||||
|
- Migrating from one DNS scheme to another
|
||||||
|
- Supporting multiple variants, such as a regional one and then one that doesn't or similar.
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
ExternalDNS has a flag: `--fqdn-template`, which defines a Go template for rendering the desired DNS names.
|
||||||
|
|
||||||
|
The template uses the following data from the source object (e.g., a `Service` or `Ingress`):
|
||||||
|
|
||||||
|
| Field | Description |
|
||||||
|
|:--------------|:------------------------------------------------------------------|
|
||||||
|
| `Name` | Name of the object (e.g., service) |
|
||||||
|
| `Namespace` | Namespace of the object |
|
||||||
|
| `Labels` | Map of labels applied to the object |
|
||||||
|
| `Annotations` | Map of annotations |
|
||||||
|
| `TargetName` | For `Service`, it's the service name; for `Ingress`, the hostname |
|
||||||
|
| `Endpoint` | Contains more contextual endpoint info, such as IP/target |
|
||||||
|
| `Controller` | Controller type (optional) |
|
||||||
|
|
||||||
|
## Supported Sources
|
||||||
|
|
||||||
|
<!-- TODO: generate from code -->
|
||||||
|
|
||||||
|
| Source | Description | FQDN Supported |
|
||||||
|
|:-----------------------|:----------------------------------------------------------------|:--------------:|
|
||||||
|
| `ambassador-host` | Queries Ambassador Host resources for endpoints. | ❌ |
|
||||||
|
| `cloudfoundry` | Queries Cloud Foundry resources for endpoints. | ❌ |
|
||||||
|
| `connector` | Queries a custom connector source for endpoints. | ❌ |
|
||||||
|
| `contour-httpproxy` | Queries Contour HTTPProxy resources for endpoints. | ✅ |
|
||||||
|
| `crd` | Queries Custom Resource Definitions (CRDs) for endpoints. | ❌ |
|
||||||
|
| `empty` | Uses an empty source, typically for testing or no-op scenarios. | ❌ |
|
||||||
|
| `f5-transportserver` | Queries F5 TransportServer resources for endpoints. | ❌ |
|
||||||
|
| `f5-virtualserver` | Queries F5 VirtualServer resources for endpoints. | ❌ |
|
||||||
|
| `fake` | Uses a fake source for testing purposes. | ❌ |
|
||||||
|
| `gateway-grpcroute` | Queries GRPCRoute resources from the Gateway API. | ✅ |
|
||||||
|
| `gateway-httproute` | Queries HTTPRoute resources from the Gateway API. | ✅ |
|
||||||
|
| `gateway-tcproute` | Queries TCPRoute resources from the Gateway API. | ✅ |
|
||||||
|
| `gateway-tlsroute` | Queries TLSRoute resources from the Gateway API. | ❌ |
|
||||||
|
| `gateway-udproute` | Queries UDPRoute resources from the Gateway API. | ❌ |
|
||||||
|
| `gloo-proxy` | Queries Gloo Proxy resources for endpoints. | ❌ |
|
||||||
|
| `ingress` | Queries Kubernetes Ingress resources for endpoints. | ✅ |
|
||||||
|
| `istio-gateway` | Queries Istio Gateway resources for endpoints. | ✅ |
|
||||||
|
| `istio-virtualservice` | Queries Istio VirtualService resources for endpoints. | ✅ |
|
||||||
|
| `kong-tcpingress` | Queries Kong TCPIngress resources for endpoints. | ❌ |
|
||||||
|
| `node` | Queries Kubernetes Node resources for endpoints. | ✅ |
|
||||||
|
| `openshift-route` | Queries OpenShift Route resources for endpoints. | ✅ |
|
||||||
|
| `pod` | Queries Kubernetes Pod resources for endpoints. | ❌ |
|
||||||
|
| `service` | Queries Kubernetes Service resources for endpoints. | ✅ |
|
||||||
|
| `skipper-routegroup` | Queries Skipper RouteGroup resources for endpoints. | ✅ |
|
||||||
|
| `traefik-proxy` | Queries Traefik Proxy resources for endpoints. | ❌ |
|
||||||
|
|
||||||
|
## Custom Functions
|
||||||
|
|
||||||
|
<!-- TODO: generate from code -->
|
||||||
|
|
||||||
|
| Function | Description |
|
||||||
|
|:-------------|:-----------------------------------------------------------------------------------------|
|
||||||
|
| `trimPrefix` | Function from the `strings` package. Returns `string` without the provided leading prefix. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Example Usage
|
||||||
|
|
||||||
|
> These examples should provide a solid foundation for implementing FQDN templating in your ExternalDNS setup.
|
||||||
|
> If you have specific requirements or encounter issues, feel free to explore the issues or update this guide.
|
||||||
|
|
||||||
|
### Basic Usage
|
||||||
|
|
||||||
|
```yml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: my-service
|
||||||
|
namespace: my-namespace
|
||||||
|
```
|
||||||
|
|
||||||
|
```sh
|
||||||
|
external-dns \
|
||||||
|
--provider=aws \
|
||||||
|
--source=service \
|
||||||
|
--fqdn-template="{{ .Name }}.example.com,{{ .Name }}.{{ .Namespace }}.example.tld"
|
||||||
|
|
||||||
|
# This will result in DNS entries like
|
||||||
|
>route53> my-service.example.com
|
||||||
|
>route53> my-service.my-namespace.example.tld
|
||||||
|
```
|
||||||
|
|
||||||
|
### With Namespace
|
||||||
|
|
||||||
|
```yml
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: my-service
|
||||||
|
namespace: default
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: other-service
|
||||||
|
namespace: kube-system
|
||||||
|
```
|
||||||
|
|
||||||
|
```yml
|
||||||
|
args:
|
||||||
|
--fqdn-template="{{.Name}}.{{.Namespace}}.example.com"
|
||||||
|
|
||||||
|
# This will result in DNS entries like
|
||||||
|
# route53> my-service.default.example.com
|
||||||
|
# route53> other-service.kube-system.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using Labels in Templates
|
||||||
|
|
||||||
|
You can also utilize labels in your FQDN templates to create more dynamic DNS entries. Assuming your service has:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: my-service
|
||||||
|
labels:
|
||||||
|
environment: staging
|
||||||
|
```
|
||||||
|
|
||||||
|
```yml
|
||||||
|
args:
|
||||||
|
--fqdn-template="{{ .Labels.environment }}.{{ .Name }}.example.com"
|
||||||
|
|
||||||
|
# This will result in DNS entries like
|
||||||
|
# route53> staging.my-service.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multiple FQDN Templates
|
||||||
|
|
||||||
|
ExternalDNS allows specifying multiple FQDN templates, which can be useful when you want to create multiple DNS entries for a single service or ingress.
|
||||||
|
|
||||||
|
> Be cautious, as this will create multiple DNS records per resource, potentially increasing the number of API calls to your DNS provider.
|
||||||
|
|
||||||
|
```yml
|
||||||
|
args:
|
||||||
|
--fqdn-template={{.Name}}.example.com,{{.Name}}.svc.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Conditional Templating combined with Annotations processing
|
||||||
|
|
||||||
|
In scenarios where you want to conditionally generate FQDNs based on annotations, you can use Go template functions like or to provide defaults.
|
||||||
|
|
||||||
|
```yml
|
||||||
|
args:
|
||||||
|
- --combine-fqdn-annotation # this is required to combine FQDN templating and annotation processing
|
||||||
|
- --fqdn-template={{ or .Annotations.dns "invalid" }}.example.com
|
||||||
|
- --exclude-domains=invalid.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
### Using Annotations for FQDN Templating
|
||||||
|
|
||||||
|
This example demonstrates how to use annotations in Kubernetes objects to dynamically generate Fully Qualified Domain Names (FQDNs) using the --fqdn-template flag in ExternalDNS.
|
||||||
|
|
||||||
|
The Service object includes an annotation dns.company.com/label with the value my-org-tld-v2. This annotation is used as part of the FQDN template to construct the DNS name.
|
||||||
|
|
||||||
|
```yml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: nginx-v2
|
||||||
|
namespace: my-namespace
|
||||||
|
annotations:
|
||||||
|
dns.company.com/label: my-org-tld-v2
|
||||||
|
spec:
|
||||||
|
type: ClusterIP
|
||||||
|
clusterIP: None
|
||||||
|
```
|
||||||
|
|
||||||
|
The --fqdn-template flag is configured to use the annotation value (dns.company.com/label) and append the namespace and a custom domain (company.local) to generate the FQDN.
|
||||||
|
|
||||||
|
```yml
|
||||||
|
args:
|
||||||
|
--source=service
|
||||||
|
--fqdn-template='{{ index .ObjectMeta.Annotations "dns.company.com/label" }}.{{ .Namespace }}.company.local'
|
||||||
|
|
||||||
|
# For the given Service object, the resulting FQDN will be:
|
||||||
|
# route53> my-org-tld-v2.my-namespace.company.local
|
||||||
|
```
|
||||||
|
|
||||||
|
### DNS Scheme Migration
|
||||||
|
|
||||||
|
If you're transitioning from one naming convention to another (e.g., from svc.cluster.local to svc.example.com), --fqdn-template allows you to generate the new records alongside or in place of the old ones — without requiring changes to your Kubernetes manifests.
|
||||||
|
|
||||||
|
```yml
|
||||||
|
args:
|
||||||
|
- --fqdn-template='{{.Name}}.new-dns.example.com'
|
||||||
|
```
|
||||||
|
|
||||||
|
This helps automate DNS record migration while maintaining service continuity.
|
||||||
|
|
||||||
|
### Multi-Variant Domain Support
|
||||||
|
|
||||||
|
You can also support regional variants or multi-tenant architectures, where the same service is deployed to different regions or environments:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
--fqdn-template='{{ .Name }}.{{ .Labels.env }}.{{ .Labels.region }}.example.com, {{ if eq .Labels.env "prod" }}{{ .Name }}.my-company.tld{{ end }}'
|
||||||
|
```
|
||||||
|
|
||||||
|
With additional context (e.g., annotations), this can produce FQDNs like:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
api.prod.us-east-1.example.com
|
||||||
|
api.my-company.tld
|
||||||
|
```
|
||||||
|
|
||||||
|
This is helpful in scenarios such as:
|
||||||
|
|
||||||
|
- Blue/green deployments across domains
|
||||||
|
- Staging vs. production resolution
|
||||||
|
- Multi-cloud or multi-region failover strategies
|
||||||
|
|
||||||
|
## Tips
|
||||||
|
|
||||||
|
- If `--fqdn-template` is specified, ExternalDNS ignores any `external-dns.alpha.kubernetes.io/hostname` annotations.
|
||||||
|
- You must still ensure the resulting FQDN is valid and unique.
|
||||||
|
- Since Go templates can be error-prone, test your template with simple examples before deploying. Mismatched field names or nil values (e.g., missing labels) will result in errors or skipped entries.
|
||||||
|
|
||||||
|
## FaQ
|
||||||
|
|
||||||
|
### Can I specify multiple global FQDN templates?
|
||||||
|
|
||||||
|
Yes, you can. Pass in a comma separated list to --fqdn-template. Beware this will double (triple, etc) the amount of DNS entries based on how many services, ingresses and so on you have and will get you faster towards the API request limit of your DNS provider.
|
||||||
|
|
||||||
|
### Where to find template syntax
|
||||||
|
|
||||||
|
- [Go template syntax](https://pkg.go.dev/text/template)
|
||||||
|
- [Go func builtins](https://github.com/golang/go/blob/master/src/text/template/funcs.go#L39-L63)
|
||||||
|
|
||||||
|
### FQDN Templating, Helm and improper templating syntax
|
||||||
|
|
||||||
|
The user encountered errors due to improper templating syntax:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
extraArgs:
|
||||||
|
- --fqdn-template={{name}}.uat.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
The correct syntax should include a dot prefix: `{{ .Name }}`.
|
||||||
|
Additionally, when using Helm's `tpl` function, it's necessary to escape the braces to prevent premature evaluation:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
extraArgs:
|
||||||
|
- --fqdn-template={{ `{{ .Name }}.uat.example.com` }}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Handling Subdomain-Only Hostnames
|
||||||
|
|
||||||
|
In [Issue #1872](https://github.com/kubernetes-sigs/external-dns/issues/1872), it was observed that ExternalDNS ignores the `--fqdn-template` when the ingress host field is set to a subdomain (e.g., foo) without a full domain.
|
||||||
|
The expectation was that the template would still apply, generating entries like `foo.bar.example.com.`
|
||||||
|
This highlights a limitation to be aware of when designing FQDN templates.
|
||||||
|
|
||||||
|
> :warning: This is currently not supported ! User would expect external-dns to generate a dns record according to the fqdnTemplate
|
||||||
|
> e.g. if the ingress name: foo and host: foo is created while fqdnTemplate={{.Name}}.bar.example.com then a dns record foo.bar.example.com should be created
|
||||||
|
|
||||||
|
```yml
|
||||||
|
apiVersion: extensions/v1beta1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: foo
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: foo
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- backend:
|
||||||
|
serviceName: foo
|
||||||
|
servicePort: 80
|
||||||
|
path: /
|
||||||
|
```
|
||||||
|
|
||||||
|
### Combining FQDN Template with Annotations
|
||||||
|
|
||||||
|
In [Issue #3318](https://github.com/kubernetes-sigs/external-dns/issues/3318), a question was raised about the interaction between --fqdn-template and --combine-fqdn-annotation.
|
||||||
|
The discussion clarified that when both flags are used, ExternalDNS combines the FQDN generated from the template with the annotation value, providing flexibility in DNS name construction.
|
||||||
|
|
||||||
|
### Using Annotations for Dynamic FQDNs
|
||||||
|
|
||||||
|
In [Issue #2627](https://github.com/kubernetes-sigs/external-dns/issues/2627), a user aimed to generate DNS entries based on ingress annotations:
|
||||||
|
|
||||||
|
```yml
|
||||||
|
args:
|
||||||
|
- --fqdn-template={{.Annotations.hostname}}.example.com
|
||||||
|
- --combine-fqdn-annotation
|
||||||
|
- --domain-filter=example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
By setting the hostname annotation in the ingress resource, ExternalDNS constructs the FQDN accordingly. This approach allows for dynamic DNS entries without hardcoding hostnames.
|
@ -48,6 +48,36 @@ make generate-metrics-documentation
|
|||||||
We require all changes to be covered by acceptance tests and/or unit tests, depending on the situation.
|
We require all changes to be covered by acceptance tests and/or unit tests, depending on the situation.
|
||||||
In the context of the `external-dns`, acceptance tests are tests of interactions with providers, such as creating, reading information about, and destroying DNS resources. In contrast, unit tests test functionality wholly within the codebase itself, such as function tests.
|
In the context of the `external-dns`, acceptance tests are tests of interactions with providers, such as creating, reading information about, and destroying DNS resources. In contrast, unit tests test functionality wholly within the codebase itself, such as function tests.
|
||||||
|
|
||||||
|
### Log Unit Testing
|
||||||
|
|
||||||
|
Testing log messages within codebase provides significant advantages, especially when it comes to debugging, monitoring, and gaining a deeper understanding of system behavior. Log library [build-in testing functionality](https://github.com/sirupsen/logrus?tab=readme-ov-file#testing)
|
||||||
|
|
||||||
|
This practice enables:
|
||||||
|
|
||||||
|
- Early detection of logging issues
|
||||||
|
- Verification of Important Information
|
||||||
|
- Ensuring Correct Severity Levels
|
||||||
|
- Improving Observability and Monitoring
|
||||||
|
- Driving Better Logging Practices
|
||||||
|
|
||||||
|
To illustrate how to unit test log output within functions, consider the following example:
|
||||||
|
|
||||||
|
```go
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"sigs.k8s.io/external-dns/internal/testutils"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestMe(t *testing.T) {
|
||||||
|
hook := testutils.LogsUnderTestWithLogLeve(log.WarnLevel, t)
|
||||||
|
... function under tests ...
|
||||||
|
testutils.TestHelperLogContains("example warning message", hook, t)
|
||||||
|
// provide negative assertion
|
||||||
|
testuitls.TestHelperLogNotContains("this message should not be shown", hook, t)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Continuous Integration
|
### Continuous Integration
|
||||||
|
|
||||||
When submitting a pull request, you'll notice that we run several automated processes on your proposed change. Some of these processes are tests to ensure your contribution aligns with our standards. While we strive for accuracy, some users may find these tests confusing.
|
When submitting a pull request, you'll notice that we run several automated processes on your proposed change. Some of these processes are tests to ensure your contribution aligns with our standards. While we strive for accuracy, some users may find these tests confusing.
|
||||||
|
@ -50,10 +50,6 @@ There are three sources of information for ExternalDNS to decide on DNS name. Ex
|
|||||||
|
|
||||||
3. If `--fqdn-template` flag is specified, e.g. `--fqdn-template={{.Name}}.my-org.com`, ExternalDNS will use service/ingress specifications for the provided template to generate DNS name.
|
3. If `--fqdn-template` flag is specified, e.g. `--fqdn-template={{.Name}}.my-org.com`, ExternalDNS will use service/ingress specifications for the provided template to generate DNS name.
|
||||||
|
|
||||||
## Can I specify multiple global FQDN templates?
|
|
||||||
|
|
||||||
Yes, you can. Pass in a comma separated list to `--fqdn-template`. Beaware this will double (triple, etc) the amount of DNS entries based on how many services, ingresses and so on you have and will get you faster towards the API request limit of your DNS provider.
|
|
||||||
|
|
||||||
## Which Service and Ingress controllers are supported?
|
## Which Service and Ingress controllers are supported?
|
||||||
|
|
||||||
Regarding Services, we'll support the OSI Layer 4 load balancers that Kubernetes creates on AWS and Google Kubernetes Engine, and possibly other clusters running on Google Compute Engine.
|
Regarding Services, we'll support the OSI Layer 4 load balancers that Kubernetes creates on AWS and Google Kubernetes Engine, and possibly other clusters running on Google Compute Engine.
|
||||||
|
@ -17,40 +17,40 @@
|
|||||||
| `--cf-password=""` | The password to log into the cloud foundry API |
|
| `--cf-password=""` | The password to log into the cloud foundry API |
|
||||||
| `--gloo-namespace=gloo-system` | The Gloo Proxy namespace; specify multiple times for multiple namespaces. (default: gloo-system) |
|
| `--gloo-namespace=gloo-system` | The Gloo Proxy namespace; specify multiple times for multiple namespaces. (default: gloo-system) |
|
||||||
| `--skipper-routegroup-groupversion="zalando.org/v1"` | The resource version for skipper routegroup |
|
| `--skipper-routegroup-groupversion="zalando.org/v1"` | The resource version for skipper routegroup |
|
||||||
| `--source=source` | The resource types that are queried for endpoints; specify multiple times for multiple sources (required, options: service, ingress, node, pod, fake, connector, gateway-httproute, gateway-grpcroute, gateway-tlsroute, gateway-tcproute, gateway-udproute, istio-gateway, istio-virtualservice, cloudfoundry, contour-httpproxy, gloo-proxy, crd, empty, skipper-routegroup, openshift-route, ambassador-host, kong-tcpingress, f5-virtualserver, f5-transportserver, traefik-proxy) |
|
|
||||||
| `--openshift-router-name=OPENSHIFT-ROUTER-NAME` | if source is openshift-route then you can pass the ingress controller name. Based on this name external-dns will select the respective router from the route status and map that routerCanonicalHostname to the route host while creating a CNAME record. |
|
|
||||||
| `--namespace=""` | Limit resources queried for endpoints to a specific namespace (default: all namespaces) |
|
|
||||||
| `--annotation-filter=""` | Filter resources queried for endpoints by annotation, using label selector semantics |
|
|
||||||
| `--label-filter=""` | Filter resources queried for endpoints by label selector; currently supported by source types crd, gateway-httproute, gateway-grpcroute, gateway-tlsroute, gateway-tcproute, gateway-udproute, ingress, node, openshift-route, service and ambassador-host |
|
|
||||||
| `--ingress-class=INGRESS-CLASS` | Require an Ingress to have this class name (defaults to any class; specify multiple times to allow more than one class) |
|
|
||||||
| `--fqdn-template=""` | A templated string that's used to generate DNS names from sources that don't define a hostname themselves, or to add a hostname suffix when paired with the fake source (optional). Accepts comma separated list for multiple global FQDN. |
|
|
||||||
| `--[no-]combine-fqdn-annotation` | Combine FQDN template and Annotations instead of overwriting |
|
|
||||||
| `--[no-]ignore-hostname-annotation` | Ignore hostname annotation when generating DNS names, valid only when --fqdn-template is set (default: false) |
|
|
||||||
| `--[no-]ignore-non-host-network-pods` | Ignore pods not running on host network when using pod source (default: true) |
|
|
||||||
| `--[no-]ignore-ingress-tls-spec` | Ignore the spec.tls section in Ingress resources (default: false) |
|
|
||||||
| `--gateway-name=GATEWAY-NAME` | Limit Gateways of Route endpoints to a specific name (default: all names) |
|
|
||||||
| `--gateway-namespace=GATEWAY-NAMESPACE` | Limit Gateways of Route endpoints to a specific namespace (default: all namespaces) |
|
|
||||||
| `--gateway-label-filter=GATEWAY-LABEL-FILTER` | Filter Gateways of Route endpoints via label selector (default: all gateways) |
|
|
||||||
| `--compatibility=` | Process annotation semantics from legacy implementations (optional, options: mate, molecule, kops-dns-controller) |
|
|
||||||
| `--[no-]ignore-ingress-rules-spec` | Ignore the spec.rules section in Ingress resources (default: false) |
|
|
||||||
| `--pod-source-domain=""` | Domain to use for pods records (optional) |
|
|
||||||
| `--[no-]publish-internal-services` | Allow external-dns to publish DNS records for ClusterIP services (optional) |
|
|
||||||
| `--[no-]publish-host-ip` | Allow external-dns to publish host-ip for headless services (optional) |
|
|
||||||
| `--[no-]always-publish-not-ready-addresses` | Always publish also not ready addresses for headless services (optional) |
|
| `--[no-]always-publish-not-ready-addresses` | Always publish also not ready addresses for headless services (optional) |
|
||||||
|
| `--annotation-filter=""` | Filter resources queried for endpoints by annotation, using label selector semantics |
|
||||||
|
| `--[no-]combine-fqdn-annotation` | Combine FQDN template and Annotations instead of overwriting |
|
||||||
|
| `--compatibility=` | Process annotation semantics from legacy implementations (optional, options: mate, molecule, kops-dns-controller) |
|
||||||
| `--connector-source-server="localhost:8080"` | The server to connect for connector source, valid only when using connector source |
|
| `--connector-source-server="localhost:8080"` | The server to connect for connector source, valid only when using connector source |
|
||||||
| `--crd-source-apiversion="externaldns.k8s.io/v1alpha1"` | API version of the CRD for crd source, e.g. `externaldns.k8s.io/v1alpha1`, valid only when using crd source |
|
| `--crd-source-apiversion="externaldns.k8s.io/v1alpha1"` | API version of the CRD for crd source, e.g. `externaldns.k8s.io/v1alpha1`, valid only when using crd source |
|
||||||
| `--crd-source-kind="DNSEndpoint"` | Kind of the CRD for the crd source in API group and version specified by crd-source-apiversion |
|
| `--crd-source-kind="DNSEndpoint"` | Kind of the CRD for the crd source in API group and version specified by crd-source-apiversion |
|
||||||
| `--service-type-filter=SERVICE-TYPE-FILTER` | The service types to take care about (default: all, expected: ClusterIP, NodePort, LoadBalancer or ExternalName) |
|
|
||||||
| `--managed-record-types=A...` | Record types to manage; specify multiple times to include many; (default: A, AAAA, CNAME) (supported records: A, AAAA, CNAME, NS, SRV, TXT) |
|
|
||||||
| `--exclude-record-types=EXCLUDE-RECORD-TYPES` | Record types to exclude from management; specify multiple times to exclude many; (optional) |
|
|
||||||
| `--default-targets=DEFAULT-TARGETS` | Set globally default host/IP that will apply as a target instead of source addresses. Specify multiple times for multiple targets (optional) |
|
| `--default-targets=DEFAULT-TARGETS` | Set globally default host/IP that will apply as a target instead of source addresses. Specify multiple times for multiple targets (optional) |
|
||||||
| `--target-net-filter=TARGET-NET-FILTER` | Limit possible targets by a net filter; specify multiple times for multiple possible nets (optional) |
|
| `--exclude-record-types=EXCLUDE-RECORD-TYPES` | Record types to exclude from management; specify multiple times to exclude many; (optional) |
|
||||||
| `--exclude-target-net=EXCLUDE-TARGET-NET` | Exclude target nets (optional) |
|
| `--exclude-target-net=EXCLUDE-TARGET-NET` | Exclude target 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 |
|
|
||||||
| `--nat64-networks=NAT64-NETWORKS` | Adding an A record for each AAAA record in NAT64-enabled networks; specify multiple times for multiple possible nets (optional) |
|
|
||||||
| `--[no-]exclude-unschedulable` | Exclude nodes that are considered unschedulable (default: true) |
|
| `--[no-]exclude-unschedulable` | Exclude nodes that are considered unschedulable (default: true) |
|
||||||
| `--[no-]expose-internal-ipv6` | When using the node source, expose internal IPv6 addresses (optional). Default is true. |
|
| `--[no-]expose-internal-ipv6` | When using the node source, expose internal IPv6 addresses (optional). Default is true. |
|
||||||
|
| `--fqdn-template=""` | A templated string that's used to generate DNS names from sources that don't define a hostname themselves, or to add a hostname suffix when paired with the fake source (optional). Accepts comma separated list for multiple global FQDN. |
|
||||||
|
| `--gateway-label-filter=GATEWAY-LABEL-FILTER` | Filter Gateways of Route endpoints via label selector (default: all gateways) |
|
||||||
|
| `--gateway-name=GATEWAY-NAME` | Limit Gateways of Route endpoints to a specific name (default: all names) |
|
||||||
|
| `--gateway-namespace=GATEWAY-NAMESPACE` | Limit Gateways of Route endpoints to a specific namespace (default: all namespaces) |
|
||||||
|
| `--[no-]ignore-hostname-annotation` | Ignore hostname annotation when generating DNS names, valid only when --fqdn-template is set (default: false) |
|
||||||
|
| `--[no-]ignore-ingress-rules-spec` | Ignore the spec.rules section in Ingress resources (default: false) |
|
||||||
|
| `--[no-]ignore-ingress-tls-spec` | Ignore the spec.tls section in Ingress resources (default: false) |
|
||||||
|
| `--[no-]ignore-non-host-network-pods` | Ignore pods not running on host network when using pod source (default: true) |
|
||||||
|
| `--ingress-class=INGRESS-CLASS` | Require an Ingress to have this class name (defaults to any class; specify multiple times to allow more than one class) |
|
||||||
|
| `--label-filter=""` | Filter resources queried for endpoints by label selector; currently supported by source types crd, gateway-httproute, gateway-grpcroute, gateway-tlsroute, gateway-tcproute, gateway-udproute, ingress, node, openshift-route, service and ambassador-host |
|
||||||
|
| `--managed-record-types=A...` | Record types to manage; specify multiple times to include many; (default: A,AAAA,CNAME) (supported records: A, AAAA, CNAME, NS, SRV, TXT) |
|
||||||
|
| `--namespace=""` | Limit resources queried for endpoints to a specific namespace (default: all namespaces) |
|
||||||
|
| `--nat64-networks=NAT64-NETWORKS` | Adding an A record for each AAAA record in NAT64-enabled networks; specify multiple times for multiple possible nets (optional) |
|
||||||
|
| `--openshift-router-name=OPENSHIFT-ROUTER-NAME` | if source is openshift-route then you can pass the ingress controller name. Based on this name external-dns will select the respective router from the route status and map that routerCanonicalHostname to the route host while creating a CNAME record. |
|
||||||
|
| `--pod-source-domain=""` | Domain to use for pods records (optional) |
|
||||||
|
| `--[no-]publish-host-ip` | Allow external-dns to publish host-ip for headless services (optional) |
|
||||||
|
| `--[no-]publish-internal-services` | Allow external-dns to publish DNS records for ClusterIP services (optional) |
|
||||||
|
| `--service-type-filter=SERVICE-TYPE-FILTER` | The service types to take care about (default: all, expected: ClusterIP, NodePort, LoadBalancer or ExternalName) |
|
||||||
|
| `--source=source` | The resource types that are queried for endpoints; specify multiple times for multiple sources (required, options: service, ingress, node, pod, fake, connector, gateway-httproute, gateway-grpcroute, gateway-tlsroute, gateway-tcproute, gateway-udproute, istio-gateway, istio-virtualservice, cloudfoundry, contour-httpproxy, gloo-proxy, crd, empty, skipper-routegroup, openshift-route, ambassador-host, kong-tcpingress, f5-virtualserver, f5-transportserver, traefik-proxy) |
|
||||||
|
| `--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, ibmcloud, 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. |
|
| `--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) |
|
| `--domain-filter=` | Limit possible target zones by a domain suffix; specify multiple times for multiple domains (optional) |
|
||||||
@ -133,7 +133,7 @@
|
|||||||
| `--exoscale-apisecret=""` | Provide your API Secret for the Exoscale provider |
|
| `--exoscale-apisecret=""` | Provide your API Secret for the Exoscale provider |
|
||||||
| `--rfc2136-host=` | When using the RFC2136 provider, specify the host of the DNS server (optionally specify multiple times when when using --rfc2136-load-balancing-strategy) |
|
| `--rfc2136-host=` | When using the RFC2136 provider, specify the host of the DNS server (optionally specify multiple times when when using --rfc2136-load-balancing-strategy) |
|
||||||
| `--rfc2136-port=0` | When using the RFC2136 provider, specify the port of the DNS server |
|
| `--rfc2136-port=0` | When using the RFC2136 provider, specify the port of the DNS server |
|
||||||
| `--rfc2136-zone=RFC2136-ZONE` | When using the RFC2136 provider, specify zone entries of the DNS server to use |
|
| `--rfc2136-zone=RFC2136-ZONE` | When using the RFC2136 provider, specify zone entry of the DNS server to use (can be specified multiple times) |
|
||||||
| `--[no-]rfc2136-create-ptr` | When using the RFC2136 provider, enable PTR management |
|
| `--[no-]rfc2136-create-ptr` | When using the RFC2136 provider, enable PTR management |
|
||||||
| `--[no-]rfc2136-insecure` | When using the RFC2136 provider, specify whether to attach TSIG or not (default: false, requires --rfc2136-tsig-keyname and rfc2136-tsig-secret) |
|
| `--[no-]rfc2136-insecure` | When using the RFC2136 provider, specify whether to attach TSIG or not (default: false, requires --rfc2136-tsig-keyname and rfc2136-tsig-secret) |
|
||||||
| `--rfc2136-tsig-keyname=""` | When using the RFC2136 provider, specify the TSIG key to attached to DNS messages (required when --rfc2136-insecure=false) |
|
| `--rfc2136-tsig-keyname=""` | When using the RFC2136 provider, specify the TSIG key to attached to DNS messages (required when --rfc2136-insecure=false) |
|
||||||
|
35
docs/providers.md
Normal file
35
docs/providers.md
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# Providers
|
||||||
|
|
||||||
|
Provider supported configurations
|
||||||
|
|
||||||
|
| Provider Name | Zone Cache | Dry Run | Default TTL (seconds) |
|
||||||
|
|:--------------|:-----------|:--------|:----------------------|
|
||||||
|
| Akamai | n/a | yes | 600 |
|
||||||
|
| AlibabaCloud | n/a | yes | 600 |
|
||||||
|
| AWS | yes | yes | 300 |
|
||||||
|
| AWSSD | n/a | yes | 300 |
|
||||||
|
| Azure | yes | yes | 300 |
|
||||||
|
| Civo | n/a | yes | n/a |
|
||||||
|
| Cloudflare | n/a | yes | 1 |
|
||||||
|
| CoreDNS | n/a | yes | n/a |
|
||||||
|
| DigitalOcean | n/a | yes | 300 |
|
||||||
|
| DNSSimple | n/a | yes | 3600 |
|
||||||
|
| Exoscale | n/a | yes | n/a |
|
||||||
|
| 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 |
|
||||||
|
| OCI | yes | yes | 300 |
|
||||||
|
| OVH | n/a | yes | 0 |
|
||||||
|
| PDNS | n/a | yes | 300 |
|
||||||
|
| PiHole | n/a | yes | n/a |
|
||||||
|
| Plural | n/a | n/a | n/a |
|
||||||
|
| RFC2136 | n/a | yes | n/a |
|
||||||
|
| Scaleway | n/a | n/a | 300 |
|
||||||
|
| TencentCloud | n/a | n/a | n/a |
|
||||||
|
| Transip | n/a | yes | 60 |
|
||||||
|
| Ultradns | n/a | yes | n/a |
|
||||||
|
| Webhook | n/a | n/a | n/a |
|
@ -81,11 +81,11 @@ Create the objects of CRD type by filling in the fields of CRD and DNS record wo
|
|||||||
|
|
||||||
### Example
|
### Example
|
||||||
|
|
||||||
Here is an example [CRD manifest](crd/crd-manifest.yaml) generated by kubebuilder.
|
Here is an example [CRD manifest](https://github.com/kubernetes-sigs/external-dns/blob/HEAD/charts/external-dns/crds/dnsendpoint.yaml) generated by kubebuilder.
|
||||||
Apply this to register the CRD
|
Apply this to register the CRD
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
$ kubectl apply --validate=false -f docs/sources/crd/crd-manifest.yaml
|
$ kubectl apply --server-side=true -f "https://raw.githubusercontent.com/kubernetes-sigs/external-dns/master/config/crd/standard/dnsendpoint.yaml"
|
||||||
customresourcedefinition.apiextensions.k8s.io "dnsendpoints.externaldns.k8s.io" created
|
customresourcedefinition.apiextensions.k8s.io "dnsendpoints.externaldns.k8s.io" created
|
||||||
```
|
```
|
||||||
|
|
||||||
|
256
docs/tutorials/ionoscloud.md
Normal file
256
docs/tutorials/ionoscloud.md
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
# IONOS Cloud
|
||||||
|
|
||||||
|
This tutorial describes how to set up ExternalDNS for use within a Kubernetes cluster using IONOS Cloud DNS.
|
||||||
|
For more details, visit the [IONOS external-dns webhook repository](https://github.com/ionos-cloud/external-dns-ionos-webhook).
|
||||||
|
You can also find the [external-dns-ionos-webhook container image](https://github.com/ionos-cloud/external-dns-ionos-webhook/pkgs/container/external-dns-ionos-webhook) required for this setup.
|
||||||
|
|
||||||
|
## Creating a DNS Zone with IONOS Cloud DNS
|
||||||
|
|
||||||
|
If you are new to IONOS Cloud DNS, we recommend you first read the following instructions for creating a DNS zone:
|
||||||
|
|
||||||
|
- [Manage DNS Zones in Data Centre Designer](https://docs.ionos.com/cloud/network-services/cloud-dns/dcd-how-tos/manage-dns-zone)
|
||||||
|
- [Creating a DNS Zone using the IONOS Cloud DNS API](https://docs.ionos.com/cloud/network-services/cloud-dns/api-how-tos/create-dns-zone)
|
||||||
|
|
||||||
|
### Steps to Create a DNS Zone
|
||||||
|
|
||||||
|
1. Log in to the [IONOS Cloud Data Center Designer](https://dcd.ionos.com/).
|
||||||
|
2. Navigate to the **Network Services** section and select **Cloud DNS**.
|
||||||
|
3. Click on **Create Zone** and provide the following details:
|
||||||
|
- **Zone Name**: Enter the domain name (e.g., `example.com`).
|
||||||
|
- **Description**: It is optional to provide a description of your zone.
|
||||||
|
4. Save the zone configuration.
|
||||||
|
|
||||||
|
For more advanced configurations, such as adding records or managing subdomains, refer to the [IONOS Cloud DNS Documentation](https://docs.ionos.com/cloud/network-services/cloud-dns/).
|
||||||
|
|
||||||
|
## Creating an IONOS API Token
|
||||||
|
|
||||||
|
To use ExternalDNS with IONOS Cloud DNS, you need an API token with sufficient privileges to manage DNS zones and records. Follow these steps to create an API token:
|
||||||
|
|
||||||
|
1. Log in to the [IONOS Cloud Data Center Designer](https://dcd.ionos.com/).
|
||||||
|
2. Navigate to the **Management** section in the top right corner and select **Token Manager**.
|
||||||
|
3. Select the Time To Live(TTL) of the token and click on **Create Token**.
|
||||||
|
4. Copy the generated token and store it securely. You will use this token to authenticate ExternalDNS.
|
||||||
|
|
||||||
|
## Deploy ExternalDNS
|
||||||
|
|
||||||
|
### Step 1: Create a Kubernetes Secret for the IONOS API Token
|
||||||
|
|
||||||
|
Store your IONOS API token securely in a Kubernetes secret:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl create secret generic ionos-credentials --from-literal=api-key='<IONOS_API_TOKEN>'
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace `<IONOS_API_TOKEN>` with your actual IONOS API token.
|
||||||
|
|
||||||
|
### Step 2: Configure ExternalDNS
|
||||||
|
|
||||||
|
Create a Helm values file for the ExternalDNS Helm chart that includes the webhook configuration. In this example, the values file is called `external-dns-ionos-values.yaml` .
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
logLevel: debug # ExternalDNS Log level, reduce in production
|
||||||
|
|
||||||
|
namespaced: false # if true, ExternalDNS will run in a namespaced scope (Role and Rolebinding will be namespaced too).
|
||||||
|
triggerLoopOnEvent: true # if true, ExternalDNS will trigger a loop on every event (create/update/delete) on the resources it watches.
|
||||||
|
|
||||||
|
logLevel: debug
|
||||||
|
sources:
|
||||||
|
- ingress
|
||||||
|
- service
|
||||||
|
provider:
|
||||||
|
name: webhook
|
||||||
|
webhook:
|
||||||
|
image:
|
||||||
|
repository: ghcr.io/ionos-cloud/external-dns-ionos-webhook
|
||||||
|
tag: latest
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
env:
|
||||||
|
- name: IONOS_API_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: ionos-credentials
|
||||||
|
key: api-key
|
||||||
|
- name: SERVER_PORT
|
||||||
|
value: "8888"
|
||||||
|
- name: METRICS_PORT
|
||||||
|
value: "8080"
|
||||||
|
- name: DRY_RUN
|
||||||
|
value: "false"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 3: Install ExternalDNS Using Helm
|
||||||
|
|
||||||
|
Install ExternalDNS with the IONOS webhook provider:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm repo add external-dns https://kubernetes-sigs.github.io/external-dns/
|
||||||
|
helm upgrade --install external-dns external-dns/external-dns -f external-dns-ionos-values.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Deploying an Example Application
|
||||||
|
|
||||||
|
### Step 1: Create a Deployment
|
||||||
|
|
||||||
|
In this step we will create `echoserver` application manifest with the following content:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: echoserver
|
||||||
|
namespace: default
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: echoserver
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: echoserver
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: echoserver
|
||||||
|
image: ealen/echo-server:latest
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
```
|
||||||
|
|
||||||
|
Deployment manifest can be saved in `echoserver-deployment.yaml` file.
|
||||||
|
|
||||||
|
Next, we will apply the deployment:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f echoserver-deployment.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
### Step 2: Create a Service
|
||||||
|
|
||||||
|
In this step, we will create a `Service` manifest to expose the `echoserver` application within the cluster. The service will also include an annotation for ExternalDNS to create a DNS record for the specified hostname.
|
||||||
|
|
||||||
|
Save the following content in a file named `echoserver-service.yaml`:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: echoserver
|
||||||
|
annotations:
|
||||||
|
external-dns.alpha.kubernetes.io/hostname: app.example.com
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- port: 80
|
||||||
|
targetPort: 80
|
||||||
|
selector:
|
||||||
|
app: echoserver
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** Replace `app.example.com` with a subdomain of your DNS zone configured in IONOS Cloud DNS. For example, if your DNS zone is `example.com`, you can use a subdomain like `app.example.com`.
|
||||||
|
|
||||||
|
Next, apply the service:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f echoserver-service.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
This service will expose the echoserver application on port 80 and instruct ExternalDNS to create a DNS record for `app.example.com`.
|
||||||
|
|
||||||
|
### Step 3: Create an Ingress
|
||||||
|
|
||||||
|
In this step, we will create an `Ingress` resource to expose the `echoserver` application externally. The ingress will route HTTP traffic to the `echoserver` service and include a hostname that ExternalDNS will use to create the corresponding DNS record.
|
||||||
|
|
||||||
|
Save the following content in a file named `echoserver-ingress.yaml` :
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: echoserver
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: app.example.com
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: echoserver
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** Replace `app.example.com` with a subdomain of your DNS zone configured in IONOS Cloud DNS. For example, if your DNS zone is `example.com`, you can use a subdomain like `app.example.com`.
|
||||||
|
|
||||||
|
Next, apply the ingress manifest:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl apply -f echoserver-ingress.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
This ingress will expose the `echoserver` application at `http://app.example.com` and instruct ExternalDNS to create a DNS record for the specified hostname.
|
||||||
|
|
||||||
|
## Accessing the Application
|
||||||
|
|
||||||
|
Once the `Ingress` resource has been applied and the DNS records have been created, you can access the application using the hostname specified in the ingress (`app.example.com`).
|
||||||
|
|
||||||
|
### Verify Application Access
|
||||||
|
|
||||||
|
Use the following `curl` command to verify that the application is accessible:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -I http://app.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace app.example.com with the subdomain you configured in your DNS zone.
|
||||||
|
|
||||||
|
**Note:** Ensure that your DNS changes have propagated and that the hostname resolves to the correct IP address before running the command.
|
||||||
|
|
||||||
|
### Expected result
|
||||||
|
|
||||||
|
You should see an HTTP response header indicating that the application is running, such as:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
HTTP/1.1 200 OK
|
||||||
|
```
|
||||||
|
|
||||||
|
> **Troubleshooting:**
|
||||||
|
>
|
||||||
|
>If you encounter any issues, verify the following:
|
||||||
|
>
|
||||||
|
> - The DNS record for `app.example.com` (replace with your own subdomain configured in IONOS Cloud DNS) has been created in IONOS Cloud DNS.
|
||||||
|
> - The ingress controller is running and properly configured in your Kubernetes cluster.
|
||||||
|
> - The `echoserver` application is running and accessible within the cluster.
|
||||||
|
|
||||||
|
## Verifying IONOS Cloud DNS Records
|
||||||
|
|
||||||
|
Use the IONOS Cloud Console or API to verify that the A and TXT records for your domain have been created. For example, you can use the following API call:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl --location --request GET 'https://dns.de-fra.ionos.com/records?filter.name=app' \
|
||||||
|
--header 'Authorization: Bearer <IONOS_API_TOKEN>'
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace `<IONOS_API_TOKEN>` with your actual API token.
|
||||||
|
|
||||||
|
The API response should include the `A` and `TXT` records for the subdomain you configured.
|
||||||
|
|
||||||
|
> **Note:** DNS changes may take a few minutes to propagate. If the records are not visible immediately, wait and try again.
|
||||||
|
|
||||||
|
## Cleanup
|
||||||
|
|
||||||
|
> **Optional:** Perform the cleanup step only if you no longer need the deployed resources.
|
||||||
|
|
||||||
|
Once you have verified the setup, you can clean up the resources created during this tutorial:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl delete -f echoserver-deployment.yaml
|
||||||
|
kubectl delete -f echoserver-service.yaml
|
||||||
|
kubectl delete -f echoserver-ingress.yaml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
In this tutorial, you successfully deployed ExternalDNS webhook with IONOS Cloud DNS as the provider.
|
||||||
|
You created a Kubernetes deployment, service, and ingress, and verified that DNS records were created and the application was accessible.
|
||||||
|
You also learned how to clean up the resources when they are no longer needed.
|
@ -497,6 +497,35 @@ external-dns \
|
|||||||
--rfc2136-insecure
|
--rfc2136-insecure
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Helm
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
extraArgs:
|
||||||
|
- --rfc2136-host="dns-host-1.yourdomain.com"
|
||||||
|
- --rfc2136-port=53
|
||||||
|
- --rfc2136-zone=example.com
|
||||||
|
- --rfc2136-tsig-secret-alg=hmac-sha256
|
||||||
|
- --rfc2136-tsig-axfr
|
||||||
|
|
||||||
|
env:
|
||||||
|
- name: "EXTERNAL_DNS_RFC2136_TSIG_SECRET"
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: rfc2136-keys
|
||||||
|
key: rfc2136-tsig-secret
|
||||||
|
- name: "EXTERNAL_DNS_RFC2136_TSIG_KEYNAME"
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: rfc2136-keys
|
||||||
|
key: rfc2136-tsig-keyname
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Secret creation
|
||||||
|
|
||||||
|
```shell
|
||||||
|
kubectl create secret generic rfc2136-keys --from-literal=rfc2136-tsig-secret='xxx' --from-literal=rfc2136-tsig-keyname='k8s-external-dns-key' -n external-dns
|
||||||
|
```
|
||||||
|
|
||||||
### Benefits
|
### Benefits
|
||||||
|
|
||||||
- Distributes the load of DNS updates across multiple data centers, preventing any single DC from becoming a bottleneck.
|
- Distributes the load of DNS updates across multiple data centers, preventing any single DC from becoming a bottleneck.
|
||||||
|
@ -204,6 +204,7 @@ type EndpointKey struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Endpoint is a high-level way of a connection between a service and an IP
|
// Endpoint is a high-level way of a connection between a service and an IP
|
||||||
|
// +kubebuilder:object:generate=true
|
||||||
type Endpoint struct {
|
type Endpoint struct {
|
||||||
// The hostname of the DNS record
|
// The hostname of the DNS record
|
||||||
DNSName string `json:"dnsName,omitempty"`
|
DNSName string `json:"dnsName,omitempty"`
|
||||||
@ -337,6 +338,7 @@ func FilterEndpointsByOwnerID(ownerID string, eps []*Endpoint) []*Endpoint {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DNSEndpointSpec defines the desired state of DNSEndpoint
|
// DNSEndpointSpec defines the desired state of DNSEndpoint
|
||||||
|
// +kubebuilder:object:generate=true
|
||||||
type DNSEndpointSpec struct {
|
type DNSEndpointSpec struct {
|
||||||
Endpoints []*Endpoint `json:"endpoints,omitempty"`
|
Endpoints []*Endpoint `json:"endpoints,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -1,28 +1,11 @@
|
|||||||
//go:build !ignore_autogenerated
|
//go:build !ignore_autogenerated
|
||||||
// +build !ignore_autogenerated
|
|
||||||
|
|
||||||
/*
|
// Code generated by controller-gen. DO NOT EDIT.
|
||||||
Copyright 2018 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Code generated by deepcopy-gen. DO NOT EDIT.
|
|
||||||
|
|
||||||
package endpoint
|
package endpoint
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
@ -32,7 +15,6 @@ func (in *DNSEndpoint) DeepCopyInto(out *DNSEndpoint) {
|
|||||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||||
in.Spec.DeepCopyInto(&out.Spec)
|
in.Spec.DeepCopyInto(&out.Spec)
|
||||||
out.Status = in.Status
|
out.Status = in.Status
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSEndpoint.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSEndpoint.
|
||||||
@ -57,7 +39,7 @@ func (in *DNSEndpoint) DeepCopyObject() runtime.Object {
|
|||||||
func (in *DNSEndpointList) DeepCopyInto(out *DNSEndpointList) {
|
func (in *DNSEndpointList) DeepCopyInto(out *DNSEndpointList) {
|
||||||
*out = *in
|
*out = *in
|
||||||
out.TypeMeta = in.TypeMeta
|
out.TypeMeta = in.TypeMeta
|
||||||
out.ListMeta = in.ListMeta
|
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||||
if in.Items != nil {
|
if in.Items != nil {
|
||||||
in, out := &in.Items, &out.Items
|
in, out := &in.Items, &out.Items
|
||||||
*out = make([]DNSEndpoint, len(*in))
|
*out = make([]DNSEndpoint, len(*in))
|
||||||
@ -65,7 +47,6 @@ func (in *DNSEndpointList) DeepCopyInto(out *DNSEndpointList) {
|
|||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSEndpointList.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSEndpointList.
|
||||||
@ -93,15 +74,13 @@ func (in *DNSEndpointSpec) DeepCopyInto(out *DNSEndpointSpec) {
|
|||||||
in, out := &in.Endpoints, &out.Endpoints
|
in, out := &in.Endpoints, &out.Endpoints
|
||||||
*out = make([]*Endpoint, len(*in))
|
*out = make([]*Endpoint, len(*in))
|
||||||
for i := range *in {
|
for i := range *in {
|
||||||
if (*in)[i] == nil {
|
if (*in)[i] != nil {
|
||||||
(*out)[i] = nil
|
in, out := &(*in)[i], &(*out)[i]
|
||||||
} else {
|
*out = new(Endpoint)
|
||||||
(*out)[i] = new(Endpoint)
|
(*in).DeepCopyInto(*out)
|
||||||
(*in)[i].DeepCopyInto((*out)[i])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSEndpointSpec.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSEndpointSpec.
|
||||||
@ -114,22 +93,6 @@ func (in *DNSEndpointSpec) DeepCopy() *DNSEndpointSpec {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *DNSEndpointStatus) DeepCopyInto(out *DNSEndpointStatus) {
|
|
||||||
*out = *in
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSEndpointStatus.
|
|
||||||
func (in *DNSEndpointStatus) DeepCopy() *DNSEndpointStatus {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(DNSEndpointStatus)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *Endpoint) DeepCopyInto(out *Endpoint) {
|
func (in *Endpoint) DeepCopyInto(out *Endpoint) {
|
||||||
*out = *in
|
*out = *in
|
||||||
@ -148,11 +111,8 @@ func (in *Endpoint) DeepCopyInto(out *Endpoint) {
|
|||||||
if in.ProviderSpecific != nil {
|
if in.ProviderSpecific != nil {
|
||||||
in, out := &in.ProviderSpecific, &out.ProviderSpecific
|
in, out := &in.ProviderSpecific, &out.ProviderSpecific
|
||||||
*out = make(ProviderSpecific, len(*in))
|
*out = make(ProviderSpecific, len(*in))
|
||||||
for key, val := range *in {
|
copy(*out, *in)
|
||||||
(*out)[key] = val
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Endpoint.
|
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Endpoint.
|
||||||
@ -164,67 +124,3 @@ func (in *Endpoint) DeepCopy() *Endpoint {
|
|||||||
in.DeepCopyInto(out)
|
in.DeepCopyInto(out)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in Labels) DeepCopyInto(out *Labels) {
|
|
||||||
{
|
|
||||||
in := &in
|
|
||||||
*out = make(Labels, len(*in))
|
|
||||||
for key, val := range *in {
|
|
||||||
(*out)[key] = val
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Labels.
|
|
||||||
func (in Labels) DeepCopy() Labels {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(Labels)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return *out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in ProviderSpecific) DeepCopyInto(out *ProviderSpecific) {
|
|
||||||
{
|
|
||||||
in := &in
|
|
||||||
*out = make(ProviderSpecific, len(*in))
|
|
||||||
for key, val := range *in {
|
|
||||||
(*out)[key] = val
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProviderSpecific.
|
|
||||||
func (in ProviderSpecific) DeepCopy() ProviderSpecific {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(ProviderSpecific)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return *out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in Targets) DeepCopyInto(out *Targets) {
|
|
||||||
{
|
|
||||||
in := &in
|
|
||||||
*out = make(Targets, len(*in))
|
|
||||||
copy(*out, *in)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Targets.
|
|
||||||
func (in Targets) DeepCopy() Targets {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(Targets)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return *out
|
|
||||||
}
|
|
||||||
|
105
go.mod
105
go.mod
@ -1,37 +1,37 @@
|
|||||||
module sigs.k8s.io/external-dns
|
module sigs.k8s.io/external-dns
|
||||||
|
|
||||||
go 1.24.0
|
go 1.24.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/compute/metadata v0.6.0
|
cloud.google.com/go/compute/metadata v0.6.0
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.3.0
|
||||||
github.com/F5Networks/k8s-bigip-ctlr/v2 v2.19.1
|
github.com/F5Networks/k8s-bigip-ctlr/v2 v2.19.1
|
||||||
github.com/IBM-Cloud/ibm-cloud-cli-sdk v1.7.0
|
github.com/IBM-Cloud/ibm-cloud-cli-sdk v1.7.2
|
||||||
github.com/IBM/go-sdk-core/v5 v5.19.0
|
github.com/IBM/go-sdk-core/v5 v5.19.1
|
||||||
github.com/IBM/networking-go-sdk v0.51.3
|
github.com/IBM/networking-go-sdk v0.51.4
|
||||||
github.com/Yamashou/gqlgenc v0.31.0
|
github.com/Yamashou/gqlgenc v0.32.1
|
||||||
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2
|
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2
|
||||||
github.com/alecthomas/kingpin/v2 v2.4.0
|
github.com/alecthomas/kingpin/v2 v2.4.0
|
||||||
github.com/aliyun/alibaba-cloud-sdk-go v1.63.104
|
github.com/aliyun/alibaba-cloud-sdk-go v1.63.107
|
||||||
github.com/aws/aws-sdk-go-v2 v1.36.3
|
github.com/aws/aws-sdk-go-v2 v1.36.3
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.29.13
|
github.com/aws/aws-sdk-go-v2/config v1.29.14
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.66
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.67
|
||||||
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.18.9
|
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.19.0
|
||||||
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.42.1
|
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.43.1
|
||||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.51.0
|
github.com/aws/aws-sdk-go-v2/service/route53 v1.51.1
|
||||||
github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.35.2
|
github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.35.4
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.18
|
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19
|
||||||
github.com/bodgit/tsig v1.2.2
|
github.com/bodgit/tsig v1.2.2
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0
|
github.com/cenkalti/backoff/v5 v5.0.2
|
||||||
github.com/civo/civogo v0.3.96
|
github.com/civo/civogo v0.4.1
|
||||||
github.com/cloudflare/cloudflare-go v0.115.0
|
github.com/cloudflare/cloudflare-go v0.115.0
|
||||||
github.com/cloudfoundry-community/go-cfclient v0.0.0-20190201205600-f136f9222381
|
github.com/cloudfoundry-community/go-cfclient v0.0.0-20190201205600-f136f9222381
|
||||||
github.com/datawire/ambassador v1.12.4
|
github.com/datawire/ambassador v1.12.4
|
||||||
github.com/denverdino/aliyungo v0.0.0-20230411124812-ab98a9173ace
|
github.com/denverdino/aliyungo v0.0.0-20230411124812-ab98a9173ace
|
||||||
github.com/digitalocean/godo v1.142.0
|
github.com/digitalocean/godo v1.145.0
|
||||||
github.com/dnsimple/dnsimple-go v1.7.0
|
github.com/dnsimple/dnsimple-go v1.7.0
|
||||||
github.com/exoscale/egoscale v0.102.3
|
github.com/exoscale/egoscale v0.102.3
|
||||||
github.com/ffledgling/pdns-go v0.0.0-20180219074714-524e7daccd99
|
github.com/ffledgling/pdns-go v0.0.0-20180219074714-524e7daccd99
|
||||||
@ -47,19 +47,18 @@ require (
|
|||||||
github.com/onsi/ginkgo v1.16.5
|
github.com/onsi/ginkgo v1.16.5
|
||||||
github.com/openshift/api v0.0.0-20230607130528-611114dca681
|
github.com/openshift/api v0.0.0-20230607130528-611114dca681
|
||||||
github.com/openshift/client-go v0.0.0-20230607134213-3cd0021bbee3
|
github.com/openshift/client-go v0.0.0-20230607134213-3cd0021bbee3
|
||||||
github.com/oracle/oci-go-sdk/v65 v65.88.1
|
github.com/oracle/oci-go-sdk/v65 v65.89.3
|
||||||
github.com/ovh/go-ovh v1.7.0
|
github.com/ovh/go-ovh v1.7.0
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/pkg/errors v0.9.1
|
|
||||||
github.com/pluralsh/gqlclient v1.12.2
|
github.com/pluralsh/gqlclient v1.12.2
|
||||||
github.com/projectcontour/contour v1.30.3
|
github.com/projectcontour/contour v1.30.3
|
||||||
github.com/prometheus/client_golang v1.21.1
|
github.com/prometheus/client_golang v1.22.0
|
||||||
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.33
|
github.com/scaleway/scaleway-sdk-go v1.0.0-beta.33
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1140
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1158
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/privatedns v1.0.1132
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/privatedns v1.0.1145
|
||||||
github.com/transip/gotransip/v6 v6.26.0
|
github.com/transip/gotransip/v6 v6.26.0
|
||||||
github.com/ultradns/ultradns-sdk-go v1.3.7
|
github.com/ultradns/ultradns-sdk-go v1.3.7
|
||||||
go.etcd.io/etcd/client/v3 v3.5.21
|
go.etcd.io/etcd/client/v3 v3.5.21
|
||||||
@ -69,25 +68,25 @@ require (
|
|||||||
golang.org/x/sync v0.13.0
|
golang.org/x/sync v0.13.0
|
||||||
golang.org/x/text v0.24.0
|
golang.org/x/text v0.24.0
|
||||||
golang.org/x/time v0.11.0
|
golang.org/x/time v0.11.0
|
||||||
google.golang.org/api v0.228.0
|
google.golang.org/api v0.231.0
|
||||||
gopkg.in/ns1/ns1-go.v2 v2.14.2
|
gopkg.in/ns1/ns1-go.v2 v2.14.2
|
||||||
istio.io/api v1.25.1
|
istio.io/api v1.25.2
|
||||||
istio.io/client-go v1.25.1
|
istio.io/client-go v1.25.2
|
||||||
k8s.io/api v0.32.3
|
k8s.io/api v0.33.0
|
||||||
k8s.io/apimachinery v0.32.3
|
k8s.io/apimachinery v0.33.0
|
||||||
k8s.io/client-go v0.32.3
|
k8s.io/client-go v0.33.0
|
||||||
k8s.io/klog/v2 v2.130.1
|
k8s.io/klog/v2 v2.130.1
|
||||||
sigs.k8s.io/gateway-api v1.2.1
|
sigs.k8s.io/gateway-api v1.3.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go/auth v0.15.0 // indirect
|
cloud.google.com/go/auth v0.16.1 // indirect
|
||||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||||
code.cloudfoundry.org/gofileutils v0.0.0-20170111115228-4d0c80011a0f // indirect
|
code.cloudfoundry.org/gofileutils v0.0.0-20170111115228-4d0c80011a0f // indirect
|
||||||
github.com/99designs/gqlgen v0.17.61 // indirect
|
github.com/99designs/gqlgen v0.17.71 // indirect
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.0 // indirect
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
|
||||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect
|
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect
|
||||||
github.com/Masterminds/semver v1.4.2 // indirect
|
github.com/Masterminds/semver v1.5.0 // indirect
|
||||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
|
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect
|
||||||
github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5 // indirect
|
github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5 // indirect
|
||||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||||
@ -95,7 +94,7 @@ require (
|
|||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.25.2 // indirect
|
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.25.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.15 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.15 // indirect
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect
|
||||||
@ -123,7 +122,7 @@ require (
|
|||||||
github.com/go-openapi/swag v0.23.0 // indirect
|
github.com/go-openapi/swag v0.23.0 // indirect
|
||||||
github.com/go-playground/locales v0.14.1 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.24.0 // indirect
|
github.com/go-playground/validator/v10 v10.26.0 // indirect
|
||||||
github.com/go-resty/resty/v2 v2.16.5 // indirect
|
github.com/go-resty/resty/v2 v2.16.5 // indirect
|
||||||
github.com/goccy/go-json v0.10.5 // indirect
|
github.com/goccy/go-json v0.10.5 // indirect
|
||||||
github.com/gofrs/flock v0.8.1 // indirect
|
github.com/gofrs/flock v0.8.1 // indirect
|
||||||
@ -131,9 +130,8 @@ require (
|
|||||||
github.com/gogo/protobuf v1.3.2 // indirect
|
github.com/gogo/protobuf v1.3.2 // indirect
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
|
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
|
||||||
github.com/golang/protobuf v1.5.4 // indirect
|
github.com/golang/protobuf v1.5.4 // indirect
|
||||||
github.com/google/gnostic-models v0.6.8 // indirect
|
github.com/google/gnostic-models v0.6.9 // indirect
|
||||||
github.com/google/go-querystring v1.1.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/google/gofuzz v1.2.0 // indirect
|
|
||||||
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
|
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect
|
||||||
github.com/google/s2a-go v0.1.9 // indirect
|
github.com/google/s2a-go v0.1.9 // indirect
|
||||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
||||||
@ -154,7 +152,6 @@ require (
|
|||||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/klauspost/compress v1.17.11 // indirect
|
|
||||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||||
github.com/leodido/go-urn v1.4.0 // indirect
|
github.com/leodido/go-urn v1.4.0 // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
@ -171,6 +168,7 @@ require (
|
|||||||
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
|
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
|
||||||
github.com/peterhellberg/link v1.1.0 // indirect
|
github.com/peterhellberg/link v1.1.0 // indirect
|
||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||||
|
github.com/pkg/errors v0.9.1 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
github.com/prometheus/client_model v0.6.1 // indirect
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
github.com/prometheus/common v0.62.0 // indirect
|
github.com/prometheus/common v0.62.0 // indirect
|
||||||
@ -180,10 +178,10 @@ require (
|
|||||||
github.com/shopspring/decimal v1.3.1 // indirect
|
github.com/shopspring/decimal v1.3.1 // indirect
|
||||||
github.com/sony/gobreaker v0.5.0 // indirect
|
github.com/sony/gobreaker v0.5.0 // indirect
|
||||||
github.com/sosodev/duration v1.3.1 // indirect
|
github.com/sosodev/duration v1.3.1 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.6 // indirect
|
||||||
github.com/stretchr/objx v0.5.2 // indirect
|
github.com/stretchr/objx v0.5.2 // indirect
|
||||||
github.com/terra-farm/udnssdk v1.3.5 // indirect
|
github.com/terra-farm/udnssdk v1.3.5 // indirect
|
||||||
github.com/vektah/gqlparser/v2 v2.5.20 // indirect
|
github.com/vektah/gqlparser/v2 v2.5.25 // indirect
|
||||||
github.com/x448/float16 v0.8.4 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
|
github.com/xhit/go-str2duration/v2 v2.1.0 // indirect
|
||||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||||
@ -191,21 +189,21 @@ require (
|
|||||||
go.etcd.io/etcd/client/pkg/v3 v3.5.21 // indirect
|
go.etcd.io/etcd/client/pkg/v3 v3.5.21 // indirect
|
||||||
go.mongodb.org/mongo-driver v1.17.2 // indirect
|
go.mongodb.org/mongo-driver v1.17.2 // indirect
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.34.0 // indirect
|
go.opentelemetry.io/otel v1.35.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.34.0 // indirect
|
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.34.0 // indirect
|
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
||||||
go.uber.org/atomic v1.10.0 // indirect
|
go.uber.org/atomic v1.10.0 // indirect
|
||||||
go.uber.org/multierr v1.11.0 // indirect
|
go.uber.org/multierr v1.11.0 // indirect
|
||||||
go.uber.org/zap v1.26.0 // indirect
|
go.uber.org/zap v1.27.0 // indirect
|
||||||
golang.org/x/crypto v0.37.0 // indirect
|
golang.org/x/crypto v0.37.0 // indirect
|
||||||
golang.org/x/mod v0.23.0 // indirect
|
golang.org/x/mod v0.24.0 // indirect
|
||||||
golang.org/x/sys v0.32.0 // indirect
|
golang.org/x/sys v0.32.0 // indirect
|
||||||
golang.org/x/term v0.31.0 // indirect
|
golang.org/x/term v0.31.0 // indirect
|
||||||
golang.org/x/tools v0.30.0 // indirect
|
golang.org/x/tools v0.32.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250425173222-7b384671a197 // indirect
|
||||||
google.golang.org/grpc v1.71.0 // indirect
|
google.golang.org/grpc v1.72.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.6 // indirect
|
google.golang.org/protobuf v1.36.6 // indirect
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
@ -213,11 +211,12 @@ require (
|
|||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
|
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff // indirect
|
||||||
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
|
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
|
||||||
moul.io/http2curl v1.0.0 // indirect
|
moul.io/http2curl v1.0.0 // indirect
|
||||||
sigs.k8s.io/controller-runtime v0.18.7 // indirect
|
sigs.k8s.io/controller-runtime v0.20.4 // indirect
|
||||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
|
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 // indirect
|
sigs.k8s.io/randfill v1.0.0 // indirect
|
||||||
|
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 // indirect
|
||||||
sigs.k8s.io/yaml v1.4.0 // indirect
|
sigs.k8s.io/yaml v1.4.0 // indirect
|
||||||
)
|
)
|
||||||
|
241
go.sum
241
go.sum
@ -2,8 +2,8 @@ bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxo
|
|||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
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.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||||
cloud.google.com/go/auth v0.15.0 h1:Ly0u4aA5vG/fsSsxu98qCQBemXtAtJf+95z9HK+cxps=
|
cloud.google.com/go/auth v0.16.1 h1:XrXauHMd30LhQYVRHLGvJiYeczweKQXZxsTbV9TiguU=
|
||||||
cloud.google.com/go/auth v0.15.0/go.mod h1:WJDGqZ1o9E9wKIL+IwStfyn/+s59zl4Bi+1KQNVXLZ8=
|
cloud.google.com/go/auth v0.16.1/go.mod h1:1howDHJ5IETh/LwYs3ZxvlkXF48aSqqJUM+5o02dNOI=
|
||||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
|
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
|
||||||
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
|
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
|
||||||
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
|
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
|
||||||
@ -12,18 +12,18 @@ code.cloudfoundry.org/gofileutils v0.0.0-20170111115228-4d0c80011a0f h1:UrKzEwTg
|
|||||||
code.cloudfoundry.org/gofileutils v0.0.0-20170111115228-4d0c80011a0f/go.mod h1:sk5LnIjB/nIEU7yP5sDQExVm62wu0pBh3yrElngUisI=
|
code.cloudfoundry.org/gofileutils v0.0.0-20170111115228-4d0c80011a0f/go.mod h1:sk5LnIjB/nIEU7yP5sDQExVm62wu0pBh3yrElngUisI=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
git.lukeshu.com/go/libsystemd v0.5.3/go.mod h1:FfDoP0i92r4p5Vn4NCLxvjkd7rCOe6otPa4L6hZg9WM=
|
git.lukeshu.com/go/libsystemd v0.5.3/go.mod h1:FfDoP0i92r4p5Vn4NCLxvjkd7rCOe6otPa4L6hZg9WM=
|
||||||
github.com/99designs/gqlgen v0.17.61 h1:vE7xLRC066n9wehgjeplILOWtwz75zbzcV2/Iv9i3pw=
|
github.com/99designs/gqlgen v0.17.71 h1:6JdwweHlSMWGY+6VWY5ey0tO+sF8LckbUV0NmdOQi04=
|
||||||
github.com/99designs/gqlgen v0.17.61/go.mod h1:rFU1T3lhv/tPeAlww/DJ4ol2YxT/pPpue+xxPbkd3r4=
|
github.com/99designs/gqlgen v0.17.71/go.mod h1:3yz6ekwCAjC90zaFvPoy+mEjaKiyYJjhtCnwn1seoxE=
|
||||||
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible h1:KnPIugL51v3N3WwvaSmZbxukD1WuWXOiE9fRdu32f2I=
|
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible h1:KnPIugL51v3N3WwvaSmZbxukD1WuWXOiE9fRdu32f2I=
|
||||||
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U=
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM=
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2 h1:F0gBpfdPLGsw+nsgk6aqqkZS1jiixa5WwFe3fk/T3Ys=
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 h1:OVoM452qUFBrX+URdH3VpR299ma4kfom0yB0URYky9g=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.2/go.mod h1:SqINnQ9lVVdRlyC8cd1lCI0SdX4n2paeABd2K8ggfnE=
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0/go.mod h1:kUjrAo8bgEwLeZ/CmHqNl3Z/kPm7y6FKfxxK0izYUg4=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.0 h1:Bg8m3nq/X1DeePkAbCfb6ml6F3F0IunEhE8TMh+lY48=
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.0/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA=
|
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 h1:lpOxwrQ919lCZoNCd69rVt8u1eLZuMORrGXqy8sNf3c=
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0 h1:lpOxwrQ919lCZoNCd69rVt8u1eLZuMORrGXqy8sNf3c=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0/go.mod h1:fSvRkb8d26z9dbL40Uf/OO6Vo9iExtZK3D0ulRV+8M0=
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/dns/armdns v1.2.0/go.mod h1:fSvRkb8d26z9dbL40Uf/OO6Vo9iExtZK3D0ulRV+8M0=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.0 h1:2qsIIvxVT+uE6yrNldntJKlLRgxGbZ85kgtz5SNBhMw=
|
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v3 v3.1.0 h1:2qsIIvxVT+uE6yrNldntJKlLRgxGbZ85kgtz5SNBhMw=
|
||||||
@ -51,17 +51,18 @@ github.com/DATA-DOG/go-sqlmock v1.4.1/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q
|
|||||||
github.com/F5Networks/k8s-bigip-ctlr/v2 v2.19.1 h1:NHWjSBeXbL8mlx+0QyCl4OrUvytCZ3nkEIRqX7t97wQ=
|
github.com/F5Networks/k8s-bigip-ctlr/v2 v2.19.1 h1:NHWjSBeXbL8mlx+0QyCl4OrUvytCZ3nkEIRqX7t97wQ=
|
||||||
github.com/F5Networks/k8s-bigip-ctlr/v2 v2.19.1/go.mod h1:JwdtGjHFTmUM1zjzvvCotCCyP55S146IuVPOJZ7D/Jw=
|
github.com/F5Networks/k8s-bigip-ctlr/v2 v2.19.1/go.mod h1:JwdtGjHFTmUM1zjzvvCotCCyP55S146IuVPOJZ7D/Jw=
|
||||||
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
|
github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo=
|
||||||
github.com/IBM-Cloud/ibm-cloud-cli-sdk v1.7.0 h1:VMMr9Yu2QkIdXtQfi3v/+qoqlnzUuFx7vfU+GDfuhh0=
|
github.com/IBM-Cloud/ibm-cloud-cli-sdk v1.7.2 h1:eW5o8NpblAyqPjwOlZ+XISdhlYynjf7B7dsCmsvfC/s=
|
||||||
github.com/IBM-Cloud/ibm-cloud-cli-sdk v1.7.0/go.mod h1:+fXHt9ZUw/AlSAHvQXkTcEMKXLVwSBvA7uReQXqDwmU=
|
github.com/IBM-Cloud/ibm-cloud-cli-sdk v1.7.2/go.mod h1:HulyrJLLc9FSZlwKQ9vu5Jq83thNlUfg1afonOdhrRA=
|
||||||
github.com/IBM/go-sdk-core/v5 v5.19.0 h1:YN2S5JUvq/EwYulmcNFwgyYBxZhVWl9nkY22H7Hpghw=
|
github.com/IBM/go-sdk-core/v5 v5.19.1 h1:sleVks1O4XjgF4YEGvyDh6PZbP6iZhlTPeDkQc8nWDs=
|
||||||
github.com/IBM/go-sdk-core/v5 v5.19.0/go.mod h1:deZO1J5TSlU69bCnl/YV7nPxFZA2UEaup7cq/7ZTOgw=
|
github.com/IBM/go-sdk-core/v5 v5.19.1/go.mod h1:Q3BYO6iDA2zweQPDGbNTtqft5tDcEpm6RTuqMlPcvbw=
|
||||||
github.com/IBM/networking-go-sdk v0.51.3 h1:GW2VLP7XVcAHin6eWnCNA9l3gsv5tnyjf5UgGwMA7hk=
|
github.com/IBM/networking-go-sdk v0.51.4 h1:rkbR+gUkksLKjNYL5YEWEAMv3qddR0mUkxObDMa4l/s=
|
||||||
github.com/IBM/networking-go-sdk v0.51.3/go.mod h1:T27XI2gtPjT7tW9nkHgrpBUNbmAc9OR41Z78Y493PoA=
|
github.com/IBM/networking-go-sdk v0.51.4/go.mod h1:gjCFEp+UVP7FUlcq2C1RaoZAXFcD39CQdlUk7uVKko4=
|
||||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||||
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
|
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E=
|
||||||
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||||
github.com/Masterminds/semver v1.4.2 h1:WBLTQ37jOCzSLtXNdoo8bNM8876KhNqOKvrlGITgsTc=
|
|
||||||
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||||
|
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||||
|
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||||
github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||||
github.com/Masterminds/sprig v2.17.1+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
|
github.com/Masterminds/sprig v2.17.1+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
|
||||||
github.com/Masterminds/sprig/v3 v3.1.0/go.mod h1:ONGMf7UfYGAbMXCZmQLy8x3lCDIPrEZE/rU8pmrbihA=
|
github.com/Masterminds/sprig/v3 v3.1.0/go.mod h1:ONGMf7UfYGAbMXCZmQLy8x3lCDIPrEZE/rU8pmrbihA=
|
||||||
@ -81,8 +82,8 @@ github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:H
|
|||||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||||
github.com/Yamashou/gqlgenc v0.31.0 h1:t54Gi6Zx9Ub1oa/RvJ+DkOC1c2wdK1R4n7wyRBuQkyc=
|
github.com/Yamashou/gqlgenc v0.32.1 h1:EHs9//xQxXlyltkSFXM+fhO2rTXcWNw6FPKRJ6t+iQQ=
|
||||||
github.com/Yamashou/gqlgenc v0.31.0/go.mod h1:0VNZtzXhyDofkNNZXXPw8LSLvi3vyG6LXo7XvcWv2X4=
|
github.com/Yamashou/gqlgenc v0.32.1/go.mod h1:o5SxKt9d3+oUZ2i0V3CW8lHFyunfLR+KcKHubS4zf5E=
|
||||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||||
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||||
@ -98,8 +99,8 @@ github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 h1:s6gZFSlWYmbqAu
|
|||||||
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
|
github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8VM1Kc9e19TLln2VL61YJF0x1XFtfdL4JdbSyE=
|
||||||
github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5 h1:P5U+E4x5OkVEKQDklVPmzs71WM56RTTRqV4OrDC//Y4=
|
github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5 h1:P5U+E4x5OkVEKQDklVPmzs71WM56RTTRqV4OrDC//Y4=
|
||||||
github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5/go.mod h1:976q2ETgjT2snVCf2ZaBnyBbVoPERGjUz+0sofzEfro=
|
github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5/go.mod h1:976q2ETgjT2snVCf2ZaBnyBbVoPERGjUz+0sofzEfro=
|
||||||
github.com/aliyun/alibaba-cloud-sdk-go v1.63.104 h1:/6jF6rhmKZzvZZhzFXWqATazSKL5OSv7p+8PfoT6MG0=
|
github.com/aliyun/alibaba-cloud-sdk-go v1.63.107 h1:qagvUyrgOnBIlVRQWOyCZGVKUIYbMBdGdJ104vBpRFU=
|
||||||
github.com/aliyun/alibaba-cloud-sdk-go v1.63.104/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ=
|
github.com/aliyun/alibaba-cloud-sdk-go v1.63.107/go.mod h1:SOSDHfe1kX91v3W5QiBsWSLqeLxImobbMX1mxrFHsVQ=
|
||||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883 h1:bvNMNQO63//z+xNgfBlViaCIJKLlCJ6/fmUseuG0wVQ=
|
||||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||||
github.com/andybalholm/brotli v0.0.0-20190621154722-5f990b63d2d6/go.mod h1:+lx6/Aqd1kLJ1GQfkvOnaZ1WGmLpMpbprPuIOOZX30U=
|
github.com/andybalholm/brotli v0.0.0-20190621154722-5f990b63d2d6/go.mod h1:+lx6/Aqd1kLJ1GQfkvOnaZ1WGmLpMpbprPuIOOZX30U=
|
||||||
@ -123,12 +124,12 @@ github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN
|
|||||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM=
|
github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg=
|
github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg=
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.29.13 h1:RgdPqWoE8nPpIekpVpDJsBckbqT4Liiaq9f35pbTh1Y=
|
github.com/aws/aws-sdk-go-v2/config v1.29.14 h1:f+eEi/2cKCg9pqKBoAIwRGzVb70MRKqWX4dg1BDcSJM=
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.29.13/go.mod h1:NI28qs/IOUIRhsR7GQ/JdexoqRN9tDxkIrYZq0SOF44=
|
github.com/aws/aws-sdk-go-v2/config v1.29.14/go.mod h1:wVPHWcIFv3WO89w0rE10gzf17ZYy+UVS1Geq8Iei34g=
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.66 h1:aKpEKaTy6n4CEJeYI1MNj97oSDLi4xro3UzQfwf5RWE=
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM=
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.66/go.mod h1:xQ5SusDmHb/fy55wU0QqTy0yNfLqxzec59YcsRZB+rI=
|
github.com/aws/aws-sdk-go-v2/credentials v1.17.67/go.mod h1:p3C44m+cfnbv763s52gCqrjaqyPikj9Sg47kUVaNZQQ=
|
||||||
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.18.9 h1:EU6VkY8G4N+IFl0D2Cd9LcUeJHyNdLJAbHfMD9v5GHQ=
|
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.19.0 h1:F3W0YqWZrpCcelbvXMP9LWSTOI620aAq1+8fZ/71TBg=
|
||||||
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.18.9/go.mod h1:JlH7zEPanxEEBLAAnKBRNZz+nrxTTMVKO40P5+umoUQ=
|
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.19.0/go.mod h1:34X+UzFJwsQfyk5U1hYiCO/gv9ZVL+Hh8w+bJQ6+HbU=
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw=
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw=
|
||||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M=
|
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q=
|
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q=
|
||||||
@ -137,26 +138,26 @@ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0io
|
|||||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q=
|
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
|
||||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
|
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
|
||||||
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.42.1 h1:67oYHlAdIoWS65kdTKatf9o1eDNkR2wan6TlBdP3oe4=
|
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.43.1 h1:YYjNTAyPL0425ECmq6Xm48NSXdT6hDVQmLOJZxyhNTM=
|
||||||
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.42.1/go.mod h1:yYaWRnVSPyAmexW5t7G3TcuYoalYfT+xQwzWsvtUQ7M=
|
github.com/aws/aws-sdk-go-v2/service/dynamodb v1.43.1/go.mod h1:yYaWRnVSPyAmexW5t7G3TcuYoalYfT+xQwzWsvtUQ7M=
|
||||||
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.25.2 h1:D1Af/NlGfG2/8S3EY/hCUlvPcfu2UrX4+XaGeiFzJQM=
|
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.25.3 h1:GHC1WTF3ZBZy+gvz2qtYB6ttALVx35hlwc4IzOIUY7g=
|
||||||
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.25.2/go.mod h1:lUqWdw5/esjPTkITXhN4C66o1ltwDq2qQ12j3SOzhVg=
|
github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.25.3/go.mod h1:lUqWdw5/esjPTkITXhN4C66o1ltwDq2qQ12j3SOzhVg=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE=
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA=
|
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.15 h1:M1R1rud7HzDrfCdlBQ7NjnRsDNEhXO/vGhuD189Ggmk=
|
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.15 h1:M1R1rud7HzDrfCdlBQ7NjnRsDNEhXO/vGhuD189Ggmk=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.15/go.mod h1:uvFKBSq9yMPV4LGAi7N4awn4tLY+hKE35f8THes2mzQ=
|
github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.10.15/go.mod h1:uvFKBSq9yMPV4LGAi7N4awn4tLY+hKE35f8THes2mzQ=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM=
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM=
|
||||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY=
|
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY=
|
||||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.51.0 h1:pK3YJIgOzYqctprqQ67kGSjeL+77r9Ue/4/gBonsGNc=
|
github.com/aws/aws-sdk-go-v2/service/route53 v1.51.1 h1:41HrH51fydStW2Tah74zkqZlJfyx4gXeuGOdsIFuckY=
|
||||||
github.com/aws/aws-sdk-go-v2/service/route53 v1.51.0/go.mod h1:kGYOjvTa0Vw0qxrqrOLut1vMnui6qLxqv/SX3vYeM8Y=
|
github.com/aws/aws-sdk-go-v2/service/route53 v1.51.1/go.mod h1:kGYOjvTa0Vw0qxrqrOLut1vMnui6qLxqv/SX3vYeM8Y=
|
||||||
github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.35.2 h1:KDXGFjFqMc31WyGljYA1Jb6yMH+YS22iC32NcYR8mZ8=
|
github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.35.4 h1:zZvziql5vgfDs2hTfF8fRF4pySG7A28/qNJQihJvpwc=
|
||||||
github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.35.2/go.mod h1:IbC8X3WZvsN+w48OrHBDUKcVnhhzO1YpXkCkFlr0qs8=
|
github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.35.4/go.mod h1:IbC8X3WZvsN+w48OrHBDUKcVnhhzO1YpXkCkFlr0qs8=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 h1:1Gw+9ajCV1jogloEv1RRnvfRFia2cL6c9cuKV2Ps+G8=
|
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 h1:1Gw+9ajCV1jogloEv1RRnvfRFia2cL6c9cuKV2Ps+G8=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI=
|
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI=
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 h1:hXmVKytPfTy5axZ+fYbR5d0cFmC3JvwLm5kM83luako=
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 h1:hXmVKytPfTy5axZ+fYbR5d0cFmC3JvwLm5kM83luako=
|
||||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs=
|
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.18 h1:xz7WvTMfSStb9Y8NpCT82FXLNC3QasqBfuAFHY4Pk5g=
|
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 h1:1XuUZ8mYJw9B6lzAkXhqHlJd/XvaX32evhproijJEZY=
|
||||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.18/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4=
|
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4=
|
||||||
github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
|
github.com/aws/smithy-go v1.22.2 h1:6D9hW43xKFrRx/tXXfAlIZc4JI+yQe6snnWcQyxSyLQ=
|
||||||
github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
github.com/aws/smithy-go v1.22.2/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
||||||
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
|
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
|
||||||
@ -179,16 +180,16 @@ github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b/go.mod h1:obH5gd0Bsq
|
|||||||
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0/go.mod h1:D/8v3kj0zr8ZAKg1AQ6crr+5VwKN5eIywRkfhyM/+dE=
|
||||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
|
github.com/cenkalti/backoff/v5 v5.0.2 h1:rIfFVxEf1QsI7E1ZHfp/B4DF/6QBAUhmgkxc0H7Zss8=
|
||||||
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
github.com/cenkalti/backoff/v5 v5.0.2/go.mod h1:rkhZdG3JZukswDf7f0cwqPNk4K0sa+F97BxZthm/crw=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
|
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5/go.mod h1:/iP1qXHoty45bqomnu2LM+VVyAEdWN+vtSHGlQgyxbw=
|
||||||
github.com/civo/civogo v0.3.96 h1:9R3yZS3B8B0oAqIlNDnMvsONk0mqZUkHREd0EH6HRIc=
|
github.com/civo/civogo v0.4.1 h1:C+lwZ7hBqKy6eKy6qgviuselF0V5Z/um0x7X/eLEQ64=
|
||||||
github.com/civo/civogo v0.3.96/go.mod h1:LaEbkszc+9nXSh4YNG0sYXFGYqdQFmXXzQg0gESs2hc=
|
github.com/civo/civogo v0.4.1/go.mod h1:LaEbkszc+9nXSh4YNG0sYXFGYqdQFmXXzQg0gESs2hc=
|
||||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cloudflare/cloudflare-go v0.115.0 h1:84/dxeeXweCc0PN5Cto44iTA8AkG1fyT11yPO5ZB7sM=
|
github.com/cloudflare/cloudflare-go v0.115.0 h1:84/dxeeXweCc0PN5Cto44iTA8AkG1fyT11yPO5ZB7sM=
|
||||||
@ -257,8 +258,8 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
|
|||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
github.com/digitalocean/godo v1.142.0 h1:OZwDccTSL7yrgkGIiPMcJ4DXD8tCpu3xfbEVHAIB8mw=
|
github.com/digitalocean/godo v1.145.0 h1:xBhWr+vCBy7GsexCUsWC+dKhPAWBMRLazavvXwyPBp8=
|
||||||
github.com/digitalocean/godo v1.142.0/go.mod h1:tYeiWY5ZXVpU48YaFv0M5irUFHXGorZpDNm7zzdWMzM=
|
github.com/digitalocean/godo v1.145.0/go.mod h1:tYeiWY5ZXVpU48YaFv0M5irUFHXGorZpDNm7zzdWMzM=
|
||||||
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E=
|
||||||
github.com/dnsimple/dnsimple-go v1.7.0 h1:JKu9xJtZ3SqOC+BuYgAWeab7+EEx0sz422vu8j611ZY=
|
github.com/dnsimple/dnsimple-go v1.7.0 h1:JKu9xJtZ3SqOC+BuYgAWeab7+EEx0sz422vu8j611ZY=
|
||||||
github.com/dnsimple/dnsimple-go v1.7.0/go.mod h1:EKpuihlWizqYafSnQHGCd/gyvy3HkEQJ7ODB4KdV8T8=
|
github.com/dnsimple/dnsimple-go v1.7.0/go.mod h1:EKpuihlWizqYafSnQHGCd/gyvy3HkEQJ7ODB4KdV8T8=
|
||||||
@ -303,8 +304,8 @@ github.com/exoscale/egoscale v0.102.3/go.mod h1:RPf2Gah6up+6kAEayHTQwqapzXlm93f0
|
|||||||
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
|
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
|
||||||
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
|
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
|
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||||
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
|
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||||
@ -418,15 +419,15 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn
|
|||||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
|
||||||
github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
||||||
github.com/go-playground/validator/v10 v10.24.0 h1:KHQckvo8G6hlWnrPX4NJJ+aBfWNAE/HH+qdL2cBpCmg=
|
github.com/go-playground/validator/v10 v10.26.0 h1:SP05Nqhjcvz81uJaRfEV0YBSSSGMc/iMaVtFbr3Sw2k=
|
||||||
github.com/go-playground/validator/v10 v10.24.0/go.mod h1:GGzBIJMuE98Ic/kJsBXbz1x/7cByt++cQ+YOuDM5wus=
|
github.com/go-playground/validator/v10 v10.26.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo=
|
||||||
github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM=
|
github.com/go-resty/resty/v2 v2.16.5 h1:hBKqmWrr7uRc3euHVqmh1HTHcKn99Smr7o5spptdhTM=
|
||||||
github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=
|
github.com/go-resty/resty/v2 v2.16.5/go.mod h1:hkJtXbA2iKHzJheXYvQ8snQES5ZLGKMwQ07xAwp/fiA=
|
||||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI=
|
||||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||||
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
|
||||||
@ -492,8 +493,8 @@ github.com/golangplus/fmt v0.0.0-20150411045040-2a5d6d7d2995/go.mod h1:lJgMEyOkY
|
|||||||
github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk=
|
github.com/golangplus/testing v0.0.0-20180327235837-af21d9c3145e/go.mod h1:0AA//k/eakGydO4jKRoRL2j92ZKSzTgj9tclaCrvXHk=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I=
|
github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw=
|
||||||
github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U=
|
github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
@ -509,8 +510,6 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD
|
|||||||
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
|
|
||||||
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
|
||||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
|
github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg=
|
||||||
@ -650,16 +649,16 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V
|
|||||||
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
|
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||||
github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs=
|
github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU=
|
||||||
github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw=
|
github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k=
|
||||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||||
github.com/klauspost/compress v1.9.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
github.com/klauspost/compress v1.9.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||||
github.com/klauspost/pgzip v1.2.1/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
github.com/klauspost/pgzip v1.2.1/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
@ -724,8 +723,8 @@ github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIG
|
|||||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
@ -810,16 +809,16 @@ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+
|
|||||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||||
github.com/onsi/ginkgo/v2 v2.23.0 h1:FA1xjp8ieYDzlgS5ABTpdUDB7wtngggONc8a7ku2NqQ=
|
github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
|
||||||
github.com/onsi/ginkgo/v2 v2.23.0/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM=
|
github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
|
||||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||||
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
|
||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||||
github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8=
|
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
|
||||||
github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY=
|
github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||||
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
@ -848,8 +847,8 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS
|
|||||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||||
github.com/oracle/oci-go-sdk/v65 v65.88.1 h1:Y9Y5jlQX8oVDe3UN+O4IcQnLN/aQmi4jR1/2RsXMN3M=
|
github.com/oracle/oci-go-sdk/v65 v65.89.3 h1:KSUykb5Ou54jF4SeJNjBwcDg+umbAwcvT+xhrvNDog0=
|
||||||
github.com/oracle/oci-go-sdk/v65 v65.88.1/go.mod h1:u6XRPsw9tPziBh76K7GrrRXPa8P8W3BQeqJ6ZZt9VLA=
|
github.com/oracle/oci-go-sdk/v65 v65.89.3/go.mod h1:u6XRPsw9tPziBh76K7GrrRXPa8P8W3BQeqJ6ZZt9VLA=
|
||||||
github.com/ovh/go-ovh v1.7.0 h1:V14nF7FwDjQrZt9g7jzcvAAQ3HN6DNShRFRMC3jLoPw=
|
github.com/ovh/go-ovh v1.7.0 h1:V14nF7FwDjQrZt9g7jzcvAAQ3HN6DNShRFRMC3jLoPw=
|
||||||
github.com/ovh/go-ovh v1.7.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c=
|
github.com/ovh/go-ovh v1.7.0/go.mod h1:cTVDnl94z4tl8pP1uZ/8jlVxntjSIf09bNcQ5TJSC7c=
|
||||||
github.com/oxtoacart/bpool v0.0.0-20150712133111-4e1c5567d7c2 h1:CXwSGu/LYmbjEab5aMCs5usQRVBGThelUKBNnoSOuso=
|
github.com/oxtoacart/bpool v0.0.0-20150712133111-4e1c5567d7c2 h1:CXwSGu/LYmbjEab5aMCs5usQRVBGThelUKBNnoSOuso=
|
||||||
@ -893,8 +892,8 @@ github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDf
|
|||||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
|
github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
|
||||||
github.com/prometheus/client_golang v1.6.0/go.mod h1:ZLOG9ck3JLRdB5MgO8f+lLTe83AXG6ro35rLTxvnIl4=
|
github.com/prometheus/client_golang v1.6.0/go.mod h1:ZLOG9ck3JLRdB5MgO8f+lLTe83AXG6ro35rLTxvnIl4=
|
||||||
github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
|
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||||
github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
|
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||||
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||||
@ -925,8 +924,8 @@ github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0leargg
|
|||||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E=
|
github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
|
||||||
github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
|
github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
|
||||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
@ -991,8 +990,9 @@ github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzu
|
|||||||
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||||
|
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||||
@ -1018,14 +1018,14 @@ github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXl
|
|||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1132/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1136/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1136/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1140 h1:F/vuesfLQmJhBZTHYOktz8IVWTs1nHwZYh74/H64uEs=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1145/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1140/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1158 h1:N+C8Tz6JKGwnDFDfd3g5CkTsiKTa6/Uia0uAL0OhimE=
|
||||||
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.1158/go.mod h1:r5r4xbfxSaeR04b166HGsBa/R4U3SueirEUpXGuw+Q0=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136 h1:kMIdSU5IvpOROh27ToVQ3hlm6ym3lCRs9tnGCOBoZqk=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136 h1:kMIdSU5IvpOROh27ToVQ3hlm6ym3lCRs9tnGCOBoZqk=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136/go.mod h1:FpyIz3mymKaExVs6Fz27kxDBS42jqZn7vbACtxdeEH4=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.1136/go.mod h1:FpyIz3mymKaExVs6Fz27kxDBS42jqZn7vbACtxdeEH4=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/privatedns v1.0.1132 h1:YjVToKgm2V8aUxiDahVEFOvXYgswXiROUhrfSc3jamE=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/privatedns v1.0.1145 h1:K5N0Uxqm9kM7KU6DFBekCTKbldlXq6UD1ekOyXn4zEc=
|
||||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/privatedns v1.0.1132/go.mod h1:2xDMNe2ohV2hRBldVgv++eByAhj3vSMnh0xl9jRFiEU=
|
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/privatedns v1.0.1145/go.mod h1:mgwxarWzLxIylWtHmkoMg0dX8aqhO5lwfrHkK4IGLKE=
|
||||||
github.com/terra-farm/udnssdk v1.3.5 h1:MNR3adfuuEK/l04+jzo8WW/0fnorY+nW515qb3vEr6I=
|
github.com/terra-farm/udnssdk v1.3.5 h1:MNR3adfuuEK/l04+jzo8WW/0fnorY+nW515qb3vEr6I=
|
||||||
github.com/terra-farm/udnssdk v1.3.5/go.mod h1:8RnM56yZTR7mYyUIvrDgXzdRaEyFIzqdEi7+um26Sv8=
|
github.com/terra-farm/udnssdk v1.3.5/go.mod h1:8RnM56yZTR7mYyUIvrDgXzdRaEyFIzqdEi7+um26Sv8=
|
||||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||||
@ -1052,8 +1052,8 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX
|
|||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||||
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw=
|
||||||
github.com/vektah/gqlparser/v2 v2.5.20 h1:kPaWbhBntxoZPaNdBaIPT1Kh0i1b/onb5kXgEdP5JCo=
|
github.com/vektah/gqlparser/v2 v2.5.25 h1:FmWtFEa+invTIzWlWK6Vk7BVEZU/97QBzeI8Z1JjGt8=
|
||||||
github.com/vektah/gqlparser/v2 v2.5.20/go.mod h1:xMl+ta8a5M1Yo1A1Iwt/k7gSpscwSnHZdw7tfhEGfTM=
|
github.com/vektah/gqlparser/v2 v2.5.25/go.mod h1:D1/VCZtV3LPnQrcPBeR/q5jkSQIPti0uYCP/RI0gIeo=
|
||||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||||
@ -1098,24 +1098,26 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
|||||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I=
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
|
||||||
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
|
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||||
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
|
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||||
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
|
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||||
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
|
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||||
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
|
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
||||||
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
|
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
|
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
|
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
||||||
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
|
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||||
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
|
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||||
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||||
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
|
go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
|
||||||
|
go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
@ -1127,8 +1129,8 @@ go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJh
|
|||||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||||
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
|
||||||
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
|
||||||
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
@ -1182,8 +1184,8 @@ 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.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM=
|
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||||
golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||||
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
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-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@ -1366,8 +1368,8 @@ golang.org/x/tools v0.0.0-20210114065538-d78b04bdf963/go.mod h1:emZCQorbCU4vsT4f
|
|||||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY=
|
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
|
||||||
golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY=
|
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
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-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@ -1380,8 +1382,8 @@ gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZ
|
|||||||
google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
|
||||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
|
||||||
google.golang.org/api v0.228.0 h1:X2DJ/uoWGnY5obVjewbp8icSL5U4FzuCfy9OjbLSnLs=
|
google.golang.org/api v0.231.0 h1:LbUD5FUl0C4qwia2bjXhCMH65yz1MLPzA/0OYEsYY7Q=
|
||||||
google.golang.org/api v0.228.0/go.mod h1:wNvRS1Pbe8r4+IfBIniV8fwCpGwTrYa+kMUDiC5z5a4=
|
google.golang.org/api v0.231.0/go.mod h1:H52180fPI/QQlUc0F4xWfGZILdv09GCWKt2bcsn164A=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
@ -1395,10 +1397,10 @@ google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRn
|
|||||||
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||||
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 h1:GVIKPyP/kLIyVOgOnTwFOrvQaQUzOzGMCxgFUOEmm24=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a h1:nwKuGPlUAt+aR+pcrkfFRrTU1BVrSmYyYMxYbUIVHr0=
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422/go.mod h1:b6h1vNKhxaSoEI+5jc3PJUCustfli/mRab7295pY7rw=
|
google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a/go.mod h1:3kWAYMk1I75K4vykHtKt2ycnOgpA6974V7bREqbsenU=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250425173222-7b384671a197 h1:29cjnHVylHwTzH66WfFZqgSQgnxzvWE+jvBwpZCLRxY=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20250425173222-7b384671a197/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||||
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
@ -1412,8 +1414,8 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ
|
|||||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||||
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
|
google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM=
|
||||||
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
|
google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
@ -1480,23 +1482,23 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
|
|||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
istio.io/api v1.25.1 h1:l3JS6Rh4bH+6ox84hRvtsJsr7gMJLsoJG2BQZGbXRyc=
|
istio.io/api v1.25.2 h1:FCRQy7iaTreKJdLemlQ1vRJEsf1soCHoTAuSf68w5I8=
|
||||||
istio.io/api v1.25.1/go.mod h1:QFzEXv/IT582T0FHZVp1QoolvE4ws0zz/vVO55blmlE=
|
istio.io/api v1.25.2/go.mod h1:QFzEXv/IT582T0FHZVp1QoolvE4ws0zz/vVO55blmlE=
|
||||||
istio.io/client-go v1.25.1 h1:1Asibz5v2NBA6w4Sqa85NS7TkpEolZcPKAT5oUAXWi8=
|
istio.io/client-go v1.25.2 h1:faupTqeMD0PkuNTZdFlpxxT35jBSQapK5k+MNAkXvqA=
|
||||||
istio.io/client-go v1.25.1/go.mod h1:Vap9OyHJMvvDegYoZczcNybS4wbPaTk+4bZcWMb8+vE=
|
istio.io/client-go v1.25.2/go.mod h1:E2LTxTcCVe4cqpKy4/9Y4VmwSoLiH6ff9MEG7EhfSDo=
|
||||||
k8s.io/api v0.18.0/go.mod h1:q2HRQkfDzHMBZL9l/y9rH63PkQl4vae0xRT+8prbrK8=
|
k8s.io/api v0.18.0/go.mod h1:q2HRQkfDzHMBZL9l/y9rH63PkQl4vae0xRT+8prbrK8=
|
||||||
k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78=
|
k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78=
|
||||||
k8s.io/api v0.18.4/go.mod h1:lOIQAKYgai1+vz9J7YcDZwC26Z0zQewYOGWdyIPUUQ4=
|
k8s.io/api v0.18.4/go.mod h1:lOIQAKYgai1+vz9J7YcDZwC26Z0zQewYOGWdyIPUUQ4=
|
||||||
k8s.io/api v0.32.3 h1:Hw7KqxRusq+6QSplE3NYG4MBxZw1BZnq4aP4cJVINls=
|
k8s.io/api v0.33.0 h1:yTgZVn1XEe6opVpP1FylmNrIFWuDqe2H0V8CT5gxfIU=
|
||||||
k8s.io/api v0.32.3/go.mod h1:2wEDTXADtm/HA7CCMD8D8bK4yuBUptzaRhYcYEEYA3k=
|
k8s.io/api v0.33.0/go.mod h1:CTO61ECK/KU7haa3qq8sarQ0biLq2ju405IZAd9zsiM=
|
||||||
k8s.io/apiextensions-apiserver v0.18.0/go.mod h1:18Cwn1Xws4xnWQNC00FLq1E350b9lUF+aOdIWDOZxgo=
|
k8s.io/apiextensions-apiserver v0.18.0/go.mod h1:18Cwn1Xws4xnWQNC00FLq1E350b9lUF+aOdIWDOZxgo=
|
||||||
k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY=
|
k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY=
|
||||||
k8s.io/apiextensions-apiserver v0.18.4/go.mod h1:NYeyeYq4SIpFlPxSAB6jHPIdvu3hL0pc36wuRChybio=
|
k8s.io/apiextensions-apiserver v0.18.4/go.mod h1:NYeyeYq4SIpFlPxSAB6jHPIdvu3hL0pc36wuRChybio=
|
||||||
k8s.io/apimachinery v0.18.0/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
|
k8s.io/apimachinery v0.18.0/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
|
||||||
k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
|
k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA=
|
||||||
k8s.io/apimachinery v0.18.4/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
|
k8s.io/apimachinery v0.18.4/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
|
||||||
k8s.io/apimachinery v0.32.3 h1:JmDuDarhDmA/Li7j3aPrwhpNBA94Nvk5zLeOge9HH1U=
|
k8s.io/apimachinery v0.33.0 h1:1a6kHrJxb2hs4t8EE5wuR/WxKDwGN1FKH3JvDtA0CIQ=
|
||||||
k8s.io/apimachinery v0.32.3/go.mod h1:GpHVgxoKlTxClKcteaeuF1Ul/lDVb74KpZcxcmLDElE=
|
k8s.io/apimachinery v0.33.0/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
|
||||||
k8s.io/apiserver v0.18.0/go.mod h1:3S2O6FeBBd6XTo0njUrLxiqk8GNy6wWOftjhJcXYnjw=
|
k8s.io/apiserver v0.18.0/go.mod h1:3S2O6FeBBd6XTo0njUrLxiqk8GNy6wWOftjhJcXYnjw=
|
||||||
k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw=
|
k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw=
|
||||||
k8s.io/apiserver v0.18.4/go.mod h1:q+zoFct5ABNnYkGIaGQ3bcbUNdmPyOCoEBcg51LChY8=
|
k8s.io/apiserver v0.18.4/go.mod h1:q+zoFct5ABNnYkGIaGQ3bcbUNdmPyOCoEBcg51LChY8=
|
||||||
@ -1505,8 +1507,8 @@ k8s.io/cli-runtime v0.18.4/go.mod h1:9/hS/Cuf7NVzWR5F/5tyS6xsnclxoPLVtwhnkJG1Y4g
|
|||||||
k8s.io/client-go v0.18.0/go.mod h1:uQSYDYs4WhVZ9i6AIoEZuwUggLVEF64HOD37boKAtF8=
|
k8s.io/client-go v0.18.0/go.mod h1:uQSYDYs4WhVZ9i6AIoEZuwUggLVEF64HOD37boKAtF8=
|
||||||
k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU=
|
k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU=
|
||||||
k8s.io/client-go v0.18.4/go.mod h1:f5sXwL4yAZRkAtzOxRWUhA/N8XzGCb+nPZI8PfobZ9g=
|
k8s.io/client-go v0.18.4/go.mod h1:f5sXwL4yAZRkAtzOxRWUhA/N8XzGCb+nPZI8PfobZ9g=
|
||||||
k8s.io/client-go v0.32.3 h1:RKPVltzopkSgHS7aS98QdscAgtgah/+zmpAogooIqVU=
|
k8s.io/client-go v0.33.0 h1:UASR0sAYVUzs2kYuKn/ZakZlcs2bEHaizrrHUZg0G98=
|
||||||
k8s.io/client-go v0.32.3/go.mod h1:3v0+3k4IcT9bXTc4V2rt+d2ZPPG700Xy6Oi0Gdl2PaY=
|
k8s.io/client-go v0.33.0/go.mod h1:kGkd+l/gNGg8GYWAPr0xF1rRKvVWvzh9vmZAMXtaKOg=
|
||||||
k8s.io/code-generator v0.18.0/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
|
k8s.io/code-generator v0.18.0/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
|
||||||
k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
|
k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc=
|
||||||
k8s.io/code-generator v0.18.4/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
|
k8s.io/code-generator v0.18.4/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
|
||||||
@ -1524,8 +1526,8 @@ k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
|
|||||||
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
|
||||||
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
||||||
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
|
||||||
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f h1:GA7//TjRY9yWGy1poLzYYJJ4JRdzg3+O6e8I+e+8T5Y=
|
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=
|
||||||
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f/go.mod h1:R/HEjbvWI0qdfb8viZUeVZm0X6IZnxAydC7YU42CMw4=
|
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff/go.mod h1:5jIi+8yX4RIb8wk3XwBo5Pq2ccx4FP10ohkbSKCZoK8=
|
||||||
k8s.io/kubectl v0.18.0/go.mod h1:LOkWx9Z5DXMEg5KtOjHhRiC1fqJPLyCr3KtQgEolCkU=
|
k8s.io/kubectl v0.18.0/go.mod h1:LOkWx9Z5DXMEg5KtOjHhRiC1fqJPLyCr3KtQgEolCkU=
|
||||||
k8s.io/kubectl v0.18.4/go.mod h1:EzB+nfeUWk6fm6giXQ8P4Fayw3dsN+M7Wjy23mTRtB0=
|
k8s.io/kubectl v0.18.4/go.mod h1:EzB+nfeUWk6fm6giXQ8P4Fayw3dsN+M7Wjy23mTRtB0=
|
||||||
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
|
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
|
||||||
@ -1541,18 +1543,21 @@ rsc.io/letsencrypt v0.0.3/go.mod h1:buyQKZ6IXrRnB7TdkHP0RyEybLx18HHyOSoTyoOLqNY=
|
|||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=
|
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0=
|
||||||
sigs.k8s.io/controller-runtime v0.6.1/go.mod h1:XRYBPdbf5XJu9kpS84VJiZ7h/u1hF3gEORz0efEja7A=
|
sigs.k8s.io/controller-runtime v0.6.1/go.mod h1:XRYBPdbf5XJu9kpS84VJiZ7h/u1hF3gEORz0efEja7A=
|
||||||
sigs.k8s.io/controller-runtime v0.18.7 h1:WDnx8LTRY8Fn1j/7B+S/R9MeDjWNAzpDBoaSvMSrQME=
|
sigs.k8s.io/controller-runtime v0.20.4 h1:X3c+Odnxz+iPTRobG4tp092+CvBU9UK0t/bRf+n0DGU=
|
||||||
sigs.k8s.io/controller-runtime v0.18.7/go.mod h1:L9r3fUZhID7Q9eK9mseNskpaTg2n11f/tlb8odyzJ4Y=
|
sigs.k8s.io/controller-runtime v0.20.4/go.mod h1:xg2XB0K5ShQzAgsoujxuKN4LNXR2LfwwHsPj7Iaw+XY=
|
||||||
sigs.k8s.io/controller-tools v0.3.1-0.20200517180335-820a4a27ea84/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI=
|
sigs.k8s.io/controller-tools v0.3.1-0.20200517180335-820a4a27ea84/go.mod h1:enhtKGfxZD1GFEoMgP8Fdbu+uKQ/cq1/WGJhdVChfvI=
|
||||||
sigs.k8s.io/gateway-api v1.2.1 h1:fZZ/+RyRb+Y5tGkwxFKuYuSRQHu9dZtbjenblleOLHM=
|
sigs.k8s.io/gateway-api v1.3.0 h1:q6okN+/UKDATola4JY7zXzx40WO4VISk7i9DIfOvr9M=
|
||||||
sigs.k8s.io/gateway-api v1.2.1/go.mod h1:EpNfEXNjiYfUJypf0eZ0P5iXA9ekSGWaS1WgPaM42X0=
|
sigs.k8s.io/gateway-api v1.3.0/go.mod h1:d8NV8nJbaRbEKem+5IuxkL8gJGOZ+FJ+NvOIltV8gDk=
|
||||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
|
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 h1:/Rv+M11QRah1itp8VhT6HoVx1Ray9eB4DBr+K+/sCJ8=
|
||||||
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
|
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3/go.mod h1:18nIHnGi6636UCz6m8i4DhaJ65T6EruyzmoQqI2BVDo=
|
||||||
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
|
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
|
||||||
|
sigs.k8s.io/randfill v0.0.0-20250304075658-069ef1bbf016/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||||
|
sigs.k8s.io/randfill v1.0.0 h1:JfjMILfT8A6RbawdsK2JXGBR5AQVfd+9TbzrlneTyrU=
|
||||||
|
sigs.k8s.io/randfill v1.0.0/go.mod h1:XeLlZ/jmk4i1HRopwe7/aU3H5n1zNUcX6TM94b3QxOY=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.5.0 h1:nbCitCK2hfnhyiKo6uf2HxUPTCodY6Qaf85SbDIaMBk=
|
sigs.k8s.io/structured-merge-diff/v4 v4.7.0 h1:qPeWmscJcXP0snki5IYF79Z8xrl8ETFxgMd7wez1XkI=
|
||||||
sigs.k8s.io/structured-merge-diff/v4 v4.5.0/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4=
|
sigs.k8s.io/structured-merge-diff/v4 v4.7.0/go.mod h1:dDy58f92j70zLsuZVuUX5Wp9vtxXpaZnkPGWeqDfCps=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||||
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
|
||||||
|
@ -17,33 +17,100 @@ limitations under the License.
|
|||||||
package testutils
|
package testutils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"strings"
|
||||||
"flag"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"k8s.io/klog/v2"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
|
"github.com/sirupsen/logrus/hooks/test"
|
||||||
)
|
)
|
||||||
|
|
||||||
// LogsToBuffer redirects log(s) output to a buffer for testing purposes
|
// LogsUnderTestWithLogLevel redirects log(s) output to a buffer for testing purposes
|
||||||
//
|
//
|
||||||
// Usage: LogsToBuffer(t)
|
// Usage: LogsUnderTestWithLogLevel(t)
|
||||||
// Example:
|
// Example:
|
||||||
//
|
//
|
||||||
// buf := LogsToBuffer(log.DebugLevel, t)
|
// hook := testutils.LogsUnderTestWithLogLevel(log.DebugLevel, t)
|
||||||
// ... do something that logs ...
|
// ... do something that logs ...
|
||||||
// assert.Contains(t, buf.String(), "expected debug log message")
|
//
|
||||||
func LogsToBuffer(level log.Level, t *testing.T) *bytes.Buffer {
|
// testutils.TestHelperLogContains("expected debug log message", hook, t)
|
||||||
|
func LogsUnderTestWithLogLevel(level log.Level, t *testing.T) *test.Hook {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
buf := new(bytes.Buffer)
|
logger, hook := test.NewNullLogger()
|
||||||
log.SetOutput(buf)
|
|
||||||
|
log.AddHook(hook)
|
||||||
|
log.SetOutput(logger.Out)
|
||||||
log.SetLevel(level)
|
log.SetLevel(level)
|
||||||
klog.SetOutput(buf)
|
return hook
|
||||||
flags := &flag.FlagSet{}
|
}
|
||||||
klog.InitFlags(flags)
|
|
||||||
// make sure klog doesn't write to stderr by default in tests
|
// TestHelperLogContains verifies that a specific log message is present
|
||||||
_ = flags.Set("logtostderr", "false")
|
// in the captured log entries. It asserts that the provided message `msg`
|
||||||
_ = flags.Set("alsologtostderr", "false")
|
// appears in at least one of the log entries recorded by the `hook`.
|
||||||
_ = flags.Set("stderrthreshold", "4")
|
//
|
||||||
return buf
|
// Parameters:
|
||||||
|
// - msg: The log message that should be found.
|
||||||
|
// - hook: The test hook capturing log entries.
|
||||||
|
// - t: The testing object used for assertions.
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
// This helper is used in tests to ensure that certain log messages are
|
||||||
|
// logged during the execution of the code under test.
|
||||||
|
func TestHelperLogContains(msg string, hook *test.Hook, t *testing.T) {
|
||||||
|
t.Helper()
|
||||||
|
isContains := false
|
||||||
|
for _, entry := range hook.AllEntries() {
|
||||||
|
if strings.Contains(entry.Message, msg) {
|
||||||
|
isContains = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert.True(t, isContains, "Expected log message not found: %s", msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestHelperLogNotContains verifies that a specific log message is not present
|
||||||
|
// in the captured log entries. It asserts that the provided message `msg`
|
||||||
|
// does not appear in any of the log entries recorded by the `hook`.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - msg: The log message that should not be found.
|
||||||
|
// - hook: The test hook capturing log entries.
|
||||||
|
// - t: The testing object used for assertions.
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
// This helper is used in tests to ensure that certain log messages are not
|
||||||
|
// logged during the execution of the code under test.
|
||||||
|
func TestHelperLogNotContains(msg string, hook *test.Hook, t *testing.T) {
|
||||||
|
t.Helper()
|
||||||
|
isContains := false
|
||||||
|
for _, entry := range hook.AllEntries() {
|
||||||
|
if strings.Contains(entry.Message, msg) {
|
||||||
|
isContains = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert.False(t, isContains, "Expected log message found when should not: %s", msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestHelperLogContainsWithLogLevel verifies that a specific log message with a given log level
|
||||||
|
// is present in the captured log entries. It asserts that the provided message `msg`
|
||||||
|
// appears in at least one of the log entries recorded by the `hook` with the specified log level.
|
||||||
|
//
|
||||||
|
// Parameters:
|
||||||
|
// - msg: The log message that should be found.
|
||||||
|
// - level: The log level that the message should have.
|
||||||
|
// - hook: The test hook capturing log entries.
|
||||||
|
// - t: The testing object used for assertions.
|
||||||
|
//
|
||||||
|
// Usage:
|
||||||
|
// This helper is used in tests to ensure that certain log messages with a specific log level
|
||||||
|
// are logged during the execution of the code under test.
|
||||||
|
func TestHelperLogContainsWithLogLevel(msg string, level log.Level, hook *test.Hook, t *testing.T) {
|
||||||
|
t.Helper()
|
||||||
|
isContains := false
|
||||||
|
for _, entry := range hook.AllEntries() {
|
||||||
|
if strings.Contains(entry.Message, msg) && entry.Level == level {
|
||||||
|
isContains = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert.True(t, isContains, "Expected log message not found: %s with level %s", msg, level)
|
||||||
}
|
}
|
||||||
|
@ -29,9 +29,10 @@ nav:
|
|||||||
- Leader Election: docs/proposal/001-leader-election.md
|
- Leader Election: docs/proposal/001-leader-election.md
|
||||||
- Monitoring: docs/monitoring/*
|
- Monitoring: docs/monitoring/*
|
||||||
- MultiTarget: docs/proposal/multi-target.md
|
- MultiTarget: docs/proposal/multi-target.md
|
||||||
- NAT64: docs/nat64.md
|
- NAT64: docs/advanced/nat64.md
|
||||||
- Rate Limits: docs/rate-limits.md
|
- Rate Limits: docs/advanced/rate-limits.md
|
||||||
- TTL: docs/ttl.md
|
- TTL: docs/advanced/ttl.md
|
||||||
|
- FQDN Templating: docs/advanced/fqdn-templating.md
|
||||||
- Contributing:
|
- Contributing:
|
||||||
- Kubernetes Contributions: CONTRIBUTING.md
|
- Kubernetes Contributions: CONTRIBUTING.md
|
||||||
- Release: docs/release.
|
- Release: docs/release.
|
||||||
|
@ -217,167 +217,168 @@ type Config struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var defaultConfig = &Config{
|
var defaultConfig = &Config{
|
||||||
APIServerURL: "",
|
AkamaiAccessToken: "",
|
||||||
KubeConfig: "",
|
AkamaiClientSecret: "",
|
||||||
RequestTimeout: time.Second * 30,
|
AkamaiClientToken: "",
|
||||||
DefaultTargets: []string{},
|
AkamaiEdgercPath: "",
|
||||||
GlooNamespaces: []string{"gloo-system"},
|
AkamaiEdgercSection: "",
|
||||||
SkipperRouteGroupVersion: "zalando.org/v1",
|
AkamaiServiceConsumerDomain: "",
|
||||||
Sources: nil,
|
AlibabaCloudConfigFile: "/etc/kubernetes/alibaba-cloud.json",
|
||||||
Namespace: "",
|
AnnotationFilter: "",
|
||||||
AnnotationFilter: "",
|
APIServerURL: "",
|
||||||
LabelFilter: labels.Everything().String(),
|
AWSAPIRetries: 3,
|
||||||
IngressClassNames: nil,
|
AWSAssumeRole: "",
|
||||||
FQDNTemplate: "",
|
AWSAssumeRoleExternalID: "",
|
||||||
CombineFQDNAndAnnotation: false,
|
AWSBatchChangeInterval: time.Second,
|
||||||
IgnoreHostnameAnnotation: false,
|
AWSBatchChangeSize: 1000,
|
||||||
IgnoreIngressTLSSpec: false,
|
AWSBatchChangeSizeBytes: 32000,
|
||||||
IgnoreIngressRulesSpec: false,
|
AWSBatchChangeSizeValues: 1000,
|
||||||
GatewayName: "",
|
AWSDynamoDBRegion: "",
|
||||||
GatewayNamespace: "",
|
AWSDynamoDBTable: "external-dns",
|
||||||
GatewayLabelFilter: "",
|
AWSEvaluateTargetHealth: true,
|
||||||
Compatibility: "",
|
AWSPreferCNAME: false,
|
||||||
PublishInternal: false,
|
AWSSDCreateTag: map[string]string{},
|
||||||
PublishHostIP: false,
|
AWSSDServiceCleanup: false,
|
||||||
ExposeInternalIPV6: true,
|
AWSZoneCacheDuration: 0 * time.Second,
|
||||||
ConnectorSourceServer: "localhost:8080",
|
AWSZoneMatchParent: false,
|
||||||
Provider: "",
|
AWSZoneTagFilter: []string{},
|
||||||
ProviderCacheTime: 0,
|
AWSZoneType: "",
|
||||||
GoogleProject: "",
|
AzureConfigFile: "/etc/kubernetes/azure.json",
|
||||||
GoogleBatchChangeSize: 1000,
|
AzureResourceGroup: "",
|
||||||
GoogleBatchChangeInterval: time.Second,
|
AzureSubscriptionID: "",
|
||||||
GoogleZoneVisibility: "",
|
AzureZonesCacheDuration: 0 * time.Second,
|
||||||
DomainFilter: []string{},
|
CFAPIEndpoint: "",
|
||||||
ZoneIDFilter: []string{},
|
CFPassword: "",
|
||||||
ExcludeDomains: []string{},
|
CFUsername: "",
|
||||||
RegexDomainFilter: regexp.MustCompile(""),
|
|
||||||
RegexDomainExclusion: regexp.MustCompile(""),
|
|
||||||
TargetNetFilter: []string{},
|
|
||||||
ExcludeTargetNets: []string{},
|
|
||||||
AlibabaCloudConfigFile: "/etc/kubernetes/alibaba-cloud.json",
|
|
||||||
AWSZoneType: "",
|
|
||||||
AWSZoneTagFilter: []string{},
|
|
||||||
AWSZoneMatchParent: false,
|
|
||||||
AWSAssumeRole: "",
|
|
||||||
AWSAssumeRoleExternalID: "",
|
|
||||||
AWSBatchChangeSize: 1000,
|
|
||||||
AWSBatchChangeSizeBytes: 32000,
|
|
||||||
AWSBatchChangeSizeValues: 1000,
|
|
||||||
AWSBatchChangeInterval: time.Second,
|
|
||||||
AWSEvaluateTargetHealth: true,
|
|
||||||
AWSAPIRetries: 3,
|
|
||||||
AWSPreferCNAME: false,
|
|
||||||
AWSZoneCacheDuration: 0 * time.Second,
|
|
||||||
AWSSDServiceCleanup: false,
|
|
||||||
AWSSDCreateTag: map[string]string{},
|
|
||||||
AWSDynamoDBRegion: "",
|
|
||||||
AWSDynamoDBTable: "external-dns",
|
|
||||||
AzureConfigFile: "/etc/kubernetes/azure.json",
|
|
||||||
AzureResourceGroup: "",
|
|
||||||
AzureSubscriptionID: "",
|
|
||||||
AzureZonesCacheDuration: 0 * time.Second,
|
|
||||||
CloudflareProxied: false,
|
|
||||||
CloudflareCustomHostnames: false,
|
|
||||||
CloudflareCustomHostnamesMinTLSVersion: "1.0",
|
|
||||||
CloudflareCustomHostnamesCertificateAuthority: "google",
|
CloudflareCustomHostnamesCertificateAuthority: "google",
|
||||||
|
CloudflareCustomHostnames: false,
|
||||||
|
CloudflareCustomHostnamesMinTLSVersion: "1.0",
|
||||||
CloudflareDNSRecordsPerPage: 100,
|
CloudflareDNSRecordsPerPage: 100,
|
||||||
|
CloudflareProxied: false,
|
||||||
CloudflareRegionKey: "earth",
|
CloudflareRegionKey: "earth",
|
||||||
CoreDNSPrefix: "/skydns/",
|
|
||||||
AkamaiServiceConsumerDomain: "",
|
CombineFQDNAndAnnotation: false,
|
||||||
AkamaiClientToken: "",
|
Compatibility: "",
|
||||||
AkamaiClientSecret: "",
|
ConnectorSourceServer: "localhost:8080",
|
||||||
AkamaiAccessToken: "",
|
CoreDNSPrefix: "/skydns/",
|
||||||
AkamaiEdgercSection: "",
|
CRDSourceAPIVersion: "externaldns.k8s.io/v1alpha1",
|
||||||
AkamaiEdgercPath: "",
|
CRDSourceKind: "DNSEndpoint",
|
||||||
OCIConfigFile: "/etc/kubernetes/oci.yaml",
|
DefaultTargets: []string{},
|
||||||
OCIZoneScope: "GLOBAL",
|
DigitalOceanAPIPageSize: 50,
|
||||||
OCIZoneCacheDuration: 0 * time.Second,
|
DomainFilter: []string{},
|
||||||
InMemoryZones: []string{},
|
DryRun: false,
|
||||||
OVHEndpoint: "ovh-eu",
|
ExcludeDNSRecordTypes: []string{},
|
||||||
OVHApiRateLimit: 20,
|
ExcludeDomains: []string{},
|
||||||
OVHEnableCNAMERelative: false,
|
ExcludeTargetNets: []string{},
|
||||||
PDNSServer: "http://localhost:8081",
|
ExcludeUnschedulable: true,
|
||||||
PDNSServerID: "localhost",
|
ExoscaleAPIEnvironment: "api",
|
||||||
PDNSAPIKey: "",
|
ExoscaleAPIKey: "",
|
||||||
PDNSSkipTLSVerify: false,
|
ExoscaleAPISecret: "",
|
||||||
PodSourceDomain: "",
|
ExoscaleAPIZone: "ch-gva-2",
|
||||||
TLSCA: "",
|
ExposeInternalIPV6: true,
|
||||||
TLSClientCert: "",
|
FQDNTemplate: "",
|
||||||
TLSClientCertKey: "",
|
GatewayLabelFilter: "",
|
||||||
Policy: "sync",
|
GatewayName: "",
|
||||||
Registry: "txt",
|
GatewayNamespace: "",
|
||||||
TXTOwnerID: "default",
|
GlooNamespaces: []string{"gloo-system"},
|
||||||
TXTPrefix: "",
|
GoDaddyAPIKey: "",
|
||||||
TXTSuffix: "",
|
GoDaddyOTE: false,
|
||||||
TXTCacheInterval: 0,
|
GoDaddySecretKey: "",
|
||||||
TXTWildcardReplacement: "",
|
GoDaddyTTL: 600,
|
||||||
MinEventSyncInterval: 5 * time.Second,
|
GoogleBatchChangeInterval: time.Second,
|
||||||
TXTEncryptEnabled: false,
|
GoogleBatchChangeSize: 1000,
|
||||||
TXTEncryptAESKey: "",
|
GoogleProject: "",
|
||||||
TXTNewFormatOnly: false,
|
GoogleZoneVisibility: "",
|
||||||
Interval: time.Minute,
|
IBMCloudConfigFile: "/etc/kubernetes/ibmcloud.json",
|
||||||
Once: false,
|
IBMCloudProxied: false,
|
||||||
DryRun: false,
|
IgnoreHostnameAnnotation: false,
|
||||||
UpdateEvents: false,
|
IgnoreIngressRulesSpec: false,
|
||||||
LogFormat: "text",
|
IgnoreIngressTLSSpec: false,
|
||||||
MetricsAddress: ":7979",
|
IngressClassNames: nil,
|
||||||
LogLevel: logrus.InfoLevel.String(),
|
InMemoryZones: []string{},
|
||||||
ExoscaleAPIEnvironment: "api",
|
Interval: time.Minute,
|
||||||
ExoscaleAPIZone: "ch-gva-2",
|
KubeConfig: "",
|
||||||
ExoscaleAPIKey: "",
|
LabelFilter: labels.Everything().String(),
|
||||||
ExoscaleAPISecret: "",
|
LogFormat: "text",
|
||||||
CRDSourceAPIVersion: "externaldns.k8s.io/v1alpha1",
|
LogLevel: logrus.InfoLevel.String(),
|
||||||
CRDSourceKind: "DNSEndpoint",
|
ManagedDNSRecordTypes: []string{endpoint.RecordTypeA, endpoint.RecordTypeAAAA, endpoint.RecordTypeCNAME},
|
||||||
ServiceTypeFilter: []string{},
|
MetricsAddress: ":7979",
|
||||||
CFAPIEndpoint: "",
|
MinEventSyncInterval: 5 * time.Second,
|
||||||
CFUsername: "",
|
Namespace: "",
|
||||||
CFPassword: "",
|
NAT64Networks: []string{},
|
||||||
RFC2136Host: []string{""},
|
NS1Endpoint: "",
|
||||||
RFC2136Port: 0,
|
NS1IgnoreSSL: false,
|
||||||
RFC2136Zone: []string{},
|
OCIConfigFile: "/etc/kubernetes/oci.yaml",
|
||||||
RFC2136Insecure: false,
|
OCIZoneCacheDuration: 0 * time.Second,
|
||||||
RFC2136GSSTSIG: false,
|
OCIZoneScope: "GLOBAL",
|
||||||
RFC2136KerberosRealm: "",
|
Once: false,
|
||||||
RFC2136KerberosUsername: "",
|
OVHApiRateLimit: 20,
|
||||||
RFC2136KerberosPassword: "",
|
OVHEnableCNAMERelative: false,
|
||||||
RFC2136TSIGKeyName: "",
|
OVHEndpoint: "ovh-eu",
|
||||||
RFC2136TSIGSecret: "",
|
PDNSAPIKey: "",
|
||||||
RFC2136TSIGSecretAlg: "",
|
PDNSServer: "http://localhost:8081",
|
||||||
RFC2136TAXFR: true,
|
PDNSServerID: "localhost",
|
||||||
RFC2136MinTTL: 0,
|
PDNSSkipTLSVerify: false,
|
||||||
RFC2136BatchChangeSize: 50,
|
PiholeApiVersion: "5",
|
||||||
RFC2136UseTLS: false,
|
PiholePassword: "",
|
||||||
RFC2136LoadBalancingStrategy: "disabled",
|
PiholeServer: "",
|
||||||
RFC2136SkipTLSVerify: false,
|
PiholeTLSInsecureSkipVerify: false,
|
||||||
NS1Endpoint: "",
|
PluralCluster: "",
|
||||||
NS1IgnoreSSL: false,
|
PluralProvider: "",
|
||||||
TransIPAccountName: "",
|
PodSourceDomain: "",
|
||||||
TransIPPrivateKeyFile: "",
|
Policy: "sync",
|
||||||
DigitalOceanAPIPageSize: 50,
|
Provider: "",
|
||||||
ManagedDNSRecordTypes: []string{endpoint.RecordTypeA, endpoint.RecordTypeAAAA, endpoint.RecordTypeCNAME},
|
ProviderCacheTime: 0,
|
||||||
ExcludeDNSRecordTypes: []string{},
|
PublishHostIP: false,
|
||||||
GoDaddyAPIKey: "",
|
PublishInternal: false,
|
||||||
GoDaddySecretKey: "",
|
RegexDomainExclusion: regexp.MustCompile(""),
|
||||||
GoDaddyTTL: 600,
|
RegexDomainFilter: regexp.MustCompile(""),
|
||||||
GoDaddyOTE: false,
|
Registry: "txt",
|
||||||
IBMCloudProxied: false,
|
RequestTimeout: time.Second * 30,
|
||||||
IBMCloudConfigFile: "/etc/kubernetes/ibmcloud.json",
|
RFC2136BatchChangeSize: 50,
|
||||||
TencentCloudConfigFile: "/etc/kubernetes/tencent-cloud.json",
|
RFC2136GSSTSIG: false,
|
||||||
TencentCloudZoneType: "",
|
RFC2136Host: []string{""},
|
||||||
PiholeServer: "",
|
RFC2136Insecure: false,
|
||||||
PiholePassword: "",
|
RFC2136KerberosPassword: "",
|
||||||
PiholeTLSInsecureSkipVerify: false,
|
RFC2136KerberosRealm: "",
|
||||||
PiholeApiVersion: "5",
|
RFC2136KerberosUsername: "",
|
||||||
PluralCluster: "",
|
RFC2136LoadBalancingStrategy: "disabled",
|
||||||
PluralProvider: "",
|
RFC2136MinTTL: 0,
|
||||||
WebhookProviderURL: "http://localhost:8888",
|
RFC2136Port: 0,
|
||||||
WebhookProviderReadTimeout: 5 * time.Second,
|
RFC2136SkipTLSVerify: false,
|
||||||
WebhookProviderWriteTimeout: 10 * time.Second,
|
RFC2136TAXFR: true,
|
||||||
WebhookServer: false,
|
RFC2136TSIGKeyName: "",
|
||||||
TraefikDisableLegacy: false,
|
RFC2136TSIGSecret: "",
|
||||||
TraefikDisableNew: false,
|
RFC2136TSIGSecretAlg: "",
|
||||||
NAT64Networks: []string{},
|
RFC2136UseTLS: false,
|
||||||
ExcludeUnschedulable: true,
|
RFC2136Zone: []string{},
|
||||||
|
ServiceTypeFilter: []string{},
|
||||||
|
SkipperRouteGroupVersion: "zalando.org/v1",
|
||||||
|
Sources: nil,
|
||||||
|
TargetNetFilter: []string{},
|
||||||
|
TencentCloudConfigFile: "/etc/kubernetes/tencent-cloud.json",
|
||||||
|
TencentCloudZoneType: "",
|
||||||
|
TLSCA: "",
|
||||||
|
TLSClientCert: "",
|
||||||
|
TLSClientCertKey: "",
|
||||||
|
TraefikDisableLegacy: false,
|
||||||
|
TraefikDisableNew: false,
|
||||||
|
TransIPAccountName: "",
|
||||||
|
TransIPPrivateKeyFile: "",
|
||||||
|
TXTCacheInterval: 0,
|
||||||
|
TXTEncryptAESKey: "",
|
||||||
|
TXTEncryptEnabled: false,
|
||||||
|
TXTNewFormatOnly: false,
|
||||||
|
TXTOwnerID: "default",
|
||||||
|
TXTPrefix: "",
|
||||||
|
TXTSuffix: "",
|
||||||
|
TXTWildcardReplacement: "",
|
||||||
|
UpdateEvents: false,
|
||||||
|
WebhookProviderReadTimeout: 5 * time.Second,
|
||||||
|
WebhookProviderURL: "http://localhost:8888",
|
||||||
|
WebhookProviderWriteTimeout: 10 * time.Second,
|
||||||
|
WebhookServer: false,
|
||||||
|
ZoneIDFilter: []string{},
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConfig returns new Config object
|
// NewConfig returns new Config object
|
||||||
@ -453,40 +454,41 @@ func App(cfg *Config) *kingpin.Application {
|
|||||||
app.Flag("skipper-routegroup-groupversion", "The resource version for skipper routegroup").Default(defaultConfig.SkipperRouteGroupVersion).StringVar(&cfg.SkipperRouteGroupVersion)
|
app.Flag("skipper-routegroup-groupversion", "The resource version for skipper routegroup").Default(defaultConfig.SkipperRouteGroupVersion).StringVar(&cfg.SkipperRouteGroupVersion)
|
||||||
|
|
||||||
// Flags related to processing source
|
// Flags related to processing source
|
||||||
app.Flag("source", "The resource types that are queried for endpoints; specify multiple times for multiple sources (required, options: service, ingress, node, pod, fake, connector, gateway-httproute, gateway-grpcroute, gateway-tlsroute, gateway-tcproute, gateway-udproute, istio-gateway, istio-virtualservice, cloudfoundry, contour-httpproxy, gloo-proxy, crd, empty, skipper-routegroup, openshift-route, ambassador-host, kong-tcpingress, f5-virtualserver, f5-transportserver, traefik-proxy)").Required().PlaceHolder("source").EnumsVar(&cfg.Sources, "service", "ingress", "node", "pod", "gateway-httproute", "gateway-grpcroute", "gateway-tlsroute", "gateway-tcproute", "gateway-udproute", "istio-gateway", "istio-virtualservice", "cloudfoundry", "contour-httpproxy", "gloo-proxy", "fake", "connector", "crd", "empty", "skipper-routegroup", "openshift-route", "ambassador-host", "kong-tcpingress", "f5-virtualserver", "f5-transportserver", "traefik-proxy")
|
|
||||||
app.Flag("openshift-router-name", "if source is openshift-route then you can pass the ingress controller name. Based on this name external-dns will select the respective router from the route status and map that routerCanonicalHostname to the route host while creating a CNAME record.").StringVar(&cfg.OCPRouterName)
|
|
||||||
app.Flag("namespace", "Limit resources queried for endpoints to a specific namespace (default: all namespaces)").Default(defaultConfig.Namespace).StringVar(&cfg.Namespace)
|
|
||||||
app.Flag("annotation-filter", "Filter resources queried for endpoints by annotation, using label selector semantics").Default(defaultConfig.AnnotationFilter).StringVar(&cfg.AnnotationFilter)
|
|
||||||
app.Flag("label-filter", "Filter resources queried for endpoints by label selector; currently supported by source types crd, gateway-httproute, gateway-grpcroute, gateway-tlsroute, gateway-tcproute, gateway-udproute, ingress, node, openshift-route, service and ambassador-host").Default(defaultConfig.LabelFilter).StringVar(&cfg.LabelFilter)
|
|
||||||
app.Flag("ingress-class", "Require an Ingress to have this class name (defaults to any class; specify multiple times to allow more than one class)").StringsVar(&cfg.IngressClassNames)
|
|
||||||
app.Flag("fqdn-template", "A templated string that's used to generate DNS names from sources that don't define a hostname themselves, or to add a hostname suffix when paired with the fake source (optional). Accepts comma separated list for multiple global FQDN.").Default(defaultConfig.FQDNTemplate).StringVar(&cfg.FQDNTemplate)
|
|
||||||
app.Flag("combine-fqdn-annotation", "Combine FQDN template and Annotations instead of overwriting").BoolVar(&cfg.CombineFQDNAndAnnotation)
|
|
||||||
app.Flag("ignore-hostname-annotation", "Ignore hostname annotation when generating DNS names, valid only when --fqdn-template is set (default: false)").BoolVar(&cfg.IgnoreHostnameAnnotation)
|
|
||||||
app.Flag("ignore-non-host-network-pods", "Ignore pods not running on host network when using pod source (default: true)").BoolVar(&cfg.IgnoreNonHostNetworkPods)
|
|
||||||
app.Flag("ignore-ingress-tls-spec", "Ignore the spec.tls section in Ingress resources (default: false)").BoolVar(&cfg.IgnoreIngressTLSSpec)
|
|
||||||
app.Flag("gateway-name", "Limit Gateways of Route endpoints to a specific name (default: all names)").StringVar(&cfg.GatewayName)
|
|
||||||
app.Flag("gateway-namespace", "Limit Gateways of Route endpoints to a specific namespace (default: all namespaces)").StringVar(&cfg.GatewayNamespace)
|
|
||||||
app.Flag("gateway-label-filter", "Filter Gateways of Route endpoints via label selector (default: all gateways)").StringVar(&cfg.GatewayLabelFilter)
|
|
||||||
app.Flag("compatibility", "Process annotation semantics from legacy implementations (optional, options: mate, molecule, kops-dns-controller)").Default(defaultConfig.Compatibility).EnumVar(&cfg.Compatibility, "", "mate", "molecule", "kops-dns-controller")
|
|
||||||
app.Flag("ignore-ingress-rules-spec", "Ignore the spec.rules section in Ingress resources (default: false)").BoolVar(&cfg.IgnoreIngressRulesSpec)
|
|
||||||
app.Flag("pod-source-domain", "Domain to use for pods records (optional)").Default(defaultConfig.PodSourceDomain).StringVar(&cfg.PodSourceDomain)
|
|
||||||
app.Flag("publish-internal-services", "Allow external-dns to publish DNS records for ClusterIP services (optional)").BoolVar(&cfg.PublishInternal)
|
|
||||||
app.Flag("publish-host-ip", "Allow external-dns to publish host-ip for headless services (optional)").BoolVar(&cfg.PublishHostIP)
|
|
||||||
app.Flag("always-publish-not-ready-addresses", "Always publish also not ready addresses for headless services (optional)").BoolVar(&cfg.AlwaysPublishNotReadyAddresses)
|
app.Flag("always-publish-not-ready-addresses", "Always publish also not ready addresses for headless services (optional)").BoolVar(&cfg.AlwaysPublishNotReadyAddresses)
|
||||||
|
app.Flag("annotation-filter", "Filter resources queried for endpoints by annotation, using label selector semantics").Default(defaultConfig.AnnotationFilter).StringVar(&cfg.AnnotationFilter)
|
||||||
|
app.Flag("combine-fqdn-annotation", "Combine FQDN template and Annotations instead of overwriting").BoolVar(&cfg.CombineFQDNAndAnnotation)
|
||||||
|
app.Flag("compatibility", "Process annotation semantics from legacy implementations (optional, options: mate, molecule, kops-dns-controller)").Default(defaultConfig.Compatibility).EnumVar(&cfg.Compatibility, "", "mate", "molecule", "kops-dns-controller")
|
||||||
app.Flag("connector-source-server", "The server to connect for connector source, valid only when using connector source").Default(defaultConfig.ConnectorSourceServer).StringVar(&cfg.ConnectorSourceServer)
|
app.Flag("connector-source-server", "The server to connect for connector source, valid only when using connector source").Default(defaultConfig.ConnectorSourceServer).StringVar(&cfg.ConnectorSourceServer)
|
||||||
app.Flag("crd-source-apiversion", "API version of the CRD for crd source, e.g. `externaldns.k8s.io/v1alpha1`, valid only when using crd source").Default(defaultConfig.CRDSourceAPIVersion).StringVar(&cfg.CRDSourceAPIVersion)
|
app.Flag("crd-source-apiversion", "API version of the CRD for crd source, e.g. `externaldns.k8s.io/v1alpha1`, valid only when using crd source").Default(defaultConfig.CRDSourceAPIVersion).StringVar(&cfg.CRDSourceAPIVersion)
|
||||||
app.Flag("crd-source-kind", "Kind of the CRD for the crd source in API group and version specified by crd-source-apiversion").Default(defaultConfig.CRDSourceKind).StringVar(&cfg.CRDSourceKind)
|
app.Flag("crd-source-kind", "Kind of the CRD for the crd source in API group and version specified by crd-source-apiversion").Default(defaultConfig.CRDSourceKind).StringVar(&cfg.CRDSourceKind)
|
||||||
app.Flag("service-type-filter", "The service types to take care about (default: all, expected: ClusterIP, NodePort, LoadBalancer or ExternalName)").StringsVar(&cfg.ServiceTypeFilter)
|
|
||||||
app.Flag("managed-record-types", "Record types to manage; specify multiple times to include many; (default: A, AAAA, CNAME) (supported records: A, AAAA, CNAME, NS, SRV, TXT)").Default("A", "AAAA", "CNAME").StringsVar(&cfg.ManagedDNSRecordTypes)
|
|
||||||
app.Flag("exclude-record-types", "Record types to exclude from management; specify multiple times to exclude many; (optional)").Default().StringsVar(&cfg.ExcludeDNSRecordTypes)
|
|
||||||
app.Flag("default-targets", "Set globally default host/IP that will apply as a target instead of source addresses. Specify multiple times for multiple targets (optional)").StringsVar(&cfg.DefaultTargets)
|
app.Flag("default-targets", "Set globally default host/IP that will apply as a target instead of source addresses. Specify multiple times for multiple targets (optional)").StringsVar(&cfg.DefaultTargets)
|
||||||
app.Flag("target-net-filter", "Limit possible targets by a net filter; specify multiple times for multiple possible nets (optional)").StringsVar(&cfg.TargetNetFilter)
|
app.Flag("exclude-record-types", "Record types to exclude from management; specify multiple times to exclude many; (optional)").Default().StringsVar(&cfg.ExcludeDNSRecordTypes)
|
||||||
app.Flag("exclude-target-net", "Exclude target nets (optional)").StringsVar(&cfg.ExcludeTargetNets)
|
app.Flag("exclude-target-net", "Exclude target nets (optional)").StringsVar(&cfg.ExcludeTargetNets)
|
||||||
app.Flag("traefik-disable-legacy", "Disable listeners on Resources under the traefik.containo.us API Group").Default(strconv.FormatBool(defaultConfig.TraefikDisableLegacy)).BoolVar(&cfg.TraefikDisableLegacy)
|
|
||||||
app.Flag("traefik-disable-new", "Disable listeners on Resources under the traefik.io API Group").Default(strconv.FormatBool(defaultConfig.TraefikDisableNew)).BoolVar(&cfg.TraefikDisableNew)
|
|
||||||
app.Flag("nat64-networks", "Adding an A record for each AAAA record in NAT64-enabled networks; specify multiple times for multiple possible nets (optional)").StringsVar(&cfg.NAT64Networks)
|
|
||||||
app.Flag("exclude-unschedulable", "Exclude nodes that are considered unschedulable (default: true)").Default(strconv.FormatBool(defaultConfig.ExcludeUnschedulable)).BoolVar(&cfg.ExcludeUnschedulable)
|
app.Flag("exclude-unschedulable", "Exclude nodes that are considered unschedulable (default: true)").Default(strconv.FormatBool(defaultConfig.ExcludeUnschedulable)).BoolVar(&cfg.ExcludeUnschedulable)
|
||||||
app.Flag("expose-internal-ipv6", "When using the node source, expose internal IPv6 addresses (optional). Default is true.").BoolVar(&cfg.ExposeInternalIPV6)
|
app.Flag("expose-internal-ipv6", "When using the node source, expose internal IPv6 addresses (optional). Default is true.").BoolVar(&cfg.ExposeInternalIPV6)
|
||||||
|
app.Flag("fqdn-template", "A templated string that's used to generate DNS names from sources that don't define a hostname themselves, or to add a hostname suffix when paired with the fake source (optional). Accepts comma separated list for multiple global FQDN.").Default(defaultConfig.FQDNTemplate).StringVar(&cfg.FQDNTemplate)
|
||||||
|
app.Flag("gateway-label-filter", "Filter Gateways of Route endpoints via label selector (default: all gateways)").StringVar(&cfg.GatewayLabelFilter)
|
||||||
|
app.Flag("gateway-name", "Limit Gateways of Route endpoints to a specific name (default: all names)").StringVar(&cfg.GatewayName)
|
||||||
|
app.Flag("gateway-namespace", "Limit Gateways of Route endpoints to a specific namespace (default: all namespaces)").StringVar(&cfg.GatewayNamespace)
|
||||||
|
app.Flag("ignore-hostname-annotation", "Ignore hostname annotation when generating DNS names, valid only when --fqdn-template is set (default: false)").BoolVar(&cfg.IgnoreHostnameAnnotation)
|
||||||
|
app.Flag("ignore-ingress-rules-spec", "Ignore the spec.rules section in Ingress resources (default: false)").BoolVar(&cfg.IgnoreIngressRulesSpec)
|
||||||
|
app.Flag("ignore-ingress-tls-spec", "Ignore the spec.tls section in Ingress resources (default: false)").BoolVar(&cfg.IgnoreIngressTLSSpec)
|
||||||
|
app.Flag("ignore-non-host-network-pods", "Ignore pods not running on host network when using pod source (default: true)").BoolVar(&cfg.IgnoreNonHostNetworkPods)
|
||||||
|
app.Flag("ingress-class", "Require an Ingress to have this class name (defaults to any class; specify multiple times to allow more than one class)").StringsVar(&cfg.IngressClassNames)
|
||||||
|
app.Flag("label-filter", "Filter resources queried for endpoints by label selector; currently supported by source types crd, gateway-httproute, gateway-grpcroute, gateway-tlsroute, gateway-tcproute, gateway-udproute, ingress, node, openshift-route, service and ambassador-host").Default(defaultConfig.LabelFilter).StringVar(&cfg.LabelFilter)
|
||||||
|
managedRecordTypesHelp := fmt.Sprintf("Record types to manage; specify multiple times to include many; (default: %s) (supported records: A, AAAA, CNAME, NS, SRV, TXT)", strings.Join(defaultConfig.ManagedDNSRecordTypes, ","))
|
||||||
|
app.Flag("managed-record-types", managedRecordTypesHelp).Default(defaultConfig.ManagedDNSRecordTypes...).StringsVar(&cfg.ManagedDNSRecordTypes)
|
||||||
|
app.Flag("namespace", "Limit resources queried for endpoints to a specific namespace (default: all namespaces)").Default(defaultConfig.Namespace).StringVar(&cfg.Namespace)
|
||||||
|
app.Flag("nat64-networks", "Adding an A record for each AAAA record in NAT64-enabled networks; specify multiple times for multiple possible nets (optional)").StringsVar(&cfg.NAT64Networks)
|
||||||
|
app.Flag("openshift-router-name", "if source is openshift-route then you can pass the ingress controller name. Based on this name external-dns will select the respective router from the route status and map that routerCanonicalHostname to the route host while creating a CNAME record.").StringVar(&cfg.OCPRouterName)
|
||||||
|
app.Flag("pod-source-domain", "Domain to use for pods records (optional)").Default(defaultConfig.PodSourceDomain).StringVar(&cfg.PodSourceDomain)
|
||||||
|
app.Flag("publish-host-ip", "Allow external-dns to publish host-ip for headless services (optional)").BoolVar(&cfg.PublishHostIP)
|
||||||
|
app.Flag("publish-internal-services", "Allow external-dns to publish DNS records for ClusterIP services (optional)").BoolVar(&cfg.PublishInternal)
|
||||||
|
app.Flag("service-type-filter", "The service types to take care about (default: all, expected: ClusterIP, NodePort, LoadBalancer or ExternalName)").StringsVar(&cfg.ServiceTypeFilter)
|
||||||
|
app.Flag("source", "The resource types that are queried for endpoints; specify multiple times for multiple sources (required, options: service, ingress, node, pod, fake, connector, gateway-httproute, gateway-grpcroute, gateway-tlsroute, gateway-tcproute, gateway-udproute, istio-gateway, istio-virtualservice, cloudfoundry, contour-httpproxy, gloo-proxy, crd, empty, skipper-routegroup, openshift-route, ambassador-host, kong-tcpingress, f5-virtualserver, f5-transportserver, traefik-proxy)").Required().PlaceHolder("source").EnumsVar(&cfg.Sources, "service", "ingress", "node", "pod", "gateway-httproute", "gateway-grpcroute", "gateway-tlsroute", "gateway-tcproute", "gateway-udproute", "istio-gateway", "istio-virtualservice", "cloudfoundry", "contour-httpproxy", "gloo-proxy", "fake", "connector", "crd", "empty", "skipper-routegroup", "openshift-route", "ambassador-host", "kong-tcpingress", "f5-virtualserver", "f5-transportserver", "traefik-proxy")
|
||||||
|
app.Flag("target-net-filter", "Limit possible targets by a net filter; specify multiple times for multiple possible nets (optional)").StringsVar(&cfg.TargetNetFilter)
|
||||||
|
app.Flag("traefik-disable-legacy", "Disable listeners on Resources under the traefik.containo.us API Group").Default(strconv.FormatBool(defaultConfig.TraefikDisableLegacy)).BoolVar(&cfg.TraefikDisableLegacy)
|
||||||
|
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
|
// 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", "ibmcloud", "inmemory", "linode", "ns1", "oci", "ovh", "pdns", "pihole", "plural", "rfc2136", "scaleway", "skydns", "tencentcloud", "transip", "ultradns", "webhook"}
|
||||||
@ -580,7 +582,7 @@ func App(cfg *Config) *kingpin.Application {
|
|||||||
// Flags related to RFC2136 provider
|
// Flags related to RFC2136 provider
|
||||||
app.Flag("rfc2136-host", "When using the RFC2136 provider, specify the host of the DNS server (optionally specify multiple times when when using --rfc2136-load-balancing-strategy)").Default(defaultConfig.RFC2136Host[0]).StringsVar(&cfg.RFC2136Host)
|
app.Flag("rfc2136-host", "When using the RFC2136 provider, specify the host of the DNS server (optionally specify multiple times when when using --rfc2136-load-balancing-strategy)").Default(defaultConfig.RFC2136Host[0]).StringsVar(&cfg.RFC2136Host)
|
||||||
app.Flag("rfc2136-port", "When using the RFC2136 provider, specify the port of the DNS server").Default(strconv.Itoa(defaultConfig.RFC2136Port)).IntVar(&cfg.RFC2136Port)
|
app.Flag("rfc2136-port", "When using the RFC2136 provider, specify the port of the DNS server").Default(strconv.Itoa(defaultConfig.RFC2136Port)).IntVar(&cfg.RFC2136Port)
|
||||||
app.Flag("rfc2136-zone", "When using the RFC2136 provider, specify zone entries of the DNS server to use").StringsVar(&cfg.RFC2136Zone)
|
app.Flag("rfc2136-zone", "When using the RFC2136 provider, specify zone entry of the DNS server to use (can be specified multiple times)").StringsVar(&cfg.RFC2136Zone)
|
||||||
app.Flag("rfc2136-create-ptr", "When using the RFC2136 provider, enable PTR management").Default(strconv.FormatBool(defaultConfig.RFC2136CreatePTR)).BoolVar(&cfg.RFC2136CreatePTR)
|
app.Flag("rfc2136-create-ptr", "When using the RFC2136 provider, enable PTR management").Default(strconv.FormatBool(defaultConfig.RFC2136CreatePTR)).BoolVar(&cfg.RFC2136CreatePTR)
|
||||||
app.Flag("rfc2136-insecure", "When using the RFC2136 provider, specify whether to attach TSIG or not (default: false, requires --rfc2136-tsig-keyname and rfc2136-tsig-secret)").Default(strconv.FormatBool(defaultConfig.RFC2136Insecure)).BoolVar(&cfg.RFC2136Insecure)
|
app.Flag("rfc2136-insecure", "When using the RFC2136 provider, specify whether to attach TSIG or not (default: false, requires --rfc2136-tsig-keyname and rfc2136-tsig-secret)").Default(strconv.FormatBool(defaultConfig.RFC2136Insecure)).BoolVar(&cfg.RFC2136Insecure)
|
||||||
app.Flag("rfc2136-tsig-keyname", "When using the RFC2136 provider, specify the TSIG key to attached to DNS messages (required when --rfc2136-insecure=false)").Default(defaultConfig.RFC2136TSIGKeyName).StringVar(&cfg.RFC2136TSIGKeyName)
|
app.Flag("rfc2136-tsig-keyname", "When using the RFC2136 provider, specify the TSIG key to attached to DNS messages (required when --rfc2136-insecure=false)").Default(defaultConfig.RFC2136TSIGKeyName).StringVar(&cfg.RFC2136TSIGKeyName)
|
||||||
|
@ -84,13 +84,13 @@ func TestMustRegister(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestUnsupportedMetricWarning(t *testing.T) {
|
func TestUnsupportedMetricWarning(t *testing.T) {
|
||||||
buf := testutils.LogsToBuffer(log.WarnLevel, t)
|
hook := testutils.LogsUnderTestWithLogLevel(log.WarnLevel, t)
|
||||||
registry := NewMetricsRegister()
|
registry := NewMetricsRegister()
|
||||||
mockUnsupported := &MockMetric{FQDN: "unsupported_metric"}
|
mockUnsupported := &MockMetric{FQDN: "unsupported_metric"}
|
||||||
registry.MustRegister(mockUnsupported)
|
registry.MustRegister(mockUnsupported)
|
||||||
assert.NotContains(t, registry.mName, "unsupported_metric")
|
assert.NotContains(t, registry.mName, "unsupported_metric")
|
||||||
|
|
||||||
assert.Contains(t, buf.String(), "Unsupported metric type: *metrics.MockMetric")
|
testutils.TestHelperLogContains("Unsupported metric type: *metrics.MockMetric", hook, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewMetricsRegister(t *testing.T) {
|
func TestNewMetricsRegister(t *testing.T) {
|
||||||
|
147
pkg/tlsutils/tlsconfig_test.go
Normal file
147
pkg/tlsutils/tlsconfig_test.go
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
/*
|
||||||
|
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 tlsutils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/tls"
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"sigs.k8s.io/external-dns/internal/gen/docs/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
var rsaCertPEM = `-----BEGIN CERTIFICATE-----
|
||||||
|
MIIB0zCCAX2gAwIBAgIJAI/M7BYjwB+uMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
|
||||||
|
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
|
||||||
|
aWRnaXRzIFB0eSBMdGQwHhcNMTIwOTEyMjE1MjAyWhcNMTUwOTEyMjE1MjAyWjBF
|
||||||
|
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
|
||||||
|
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBANLJ
|
||||||
|
hPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wok/4xIA+ui35/MmNa
|
||||||
|
rtNuC+BdZ1tMuVCPFZcCAwEAAaNQME4wHQYDVR0OBBYEFJvKs8RfJaXTH08W+SGv
|
||||||
|
zQyKn0H8MB8GA1UdIwQYMBaAFJvKs8RfJaXTH08W+SGvzQyKn0H8MAwGA1UdEwQF
|
||||||
|
MAMBAf8wDQYJKoZIhvcNAQEFBQADQQBJlffJHybjDGxRMqaRmDhX0+6v02TUKZsW
|
||||||
|
r5QuVbpQhH6u+0UgcW0jp9QwpxoPTLTWGXEWBBBurxFwiCBhkQ+V
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
`
|
||||||
|
|
||||||
|
var rsaKeyPEM = testingKey(`-----BEGIN RSA TESTING KEY-----
|
||||||
|
MIIBOwIBAAJBANLJhPHhITqQbPklG3ibCVxwGMRfp/v4XqhfdQHdcVfHap6NQ5Wo
|
||||||
|
k/4xIA+ui35/MmNartNuC+BdZ1tMuVCPFZcCAwEAAQJAEJ2N+zsR0Xn8/Q6twa4G
|
||||||
|
6OB1M1WO+k+ztnX/1SvNeWu8D6GImtupLTYgjZcHufykj09jiHmjHx8u8ZZB/o1N
|
||||||
|
MQIhAPW+eyZo7ay3lMz1V01WVjNKK9QSn1MJlb06h/LuYv9FAiEA25WPedKgVyCW
|
||||||
|
SmUwbPw8fnTcpqDWE3yTO3vKcebqMSsCIBF3UmVue8YU3jybC3NxuXq3wNm34R8T
|
||||||
|
xVLHwDXh/6NJAiEAl2oHGGLz64BuAfjKrqwz7qMYr9HCLIe/YsoWq/olzScCIQDi
|
||||||
|
D2lWusoe2/nEqfDVVWGWlyJ7yOmqaVm/iNUN9B2N2g==
|
||||||
|
-----END RSA TESTING KEY-----
|
||||||
|
`)
|
||||||
|
|
||||||
|
func testingKey(s string) string { return strings.ReplaceAll(s, "TESTING KEY", "PRIVATE KEY") }
|
||||||
|
|
||||||
|
func TestCreateTLSConfig(t *testing.T) {
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
title string
|
||||||
|
prefix string
|
||||||
|
caFile string
|
||||||
|
certFile string
|
||||||
|
keyFile string
|
||||||
|
isInsecureStr string
|
||||||
|
serverName string
|
||||||
|
assertions func(actual *tls.Config, err error)
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
"Provide only CA returns error",
|
||||||
|
"prefix",
|
||||||
|
"",
|
||||||
|
rsaCertPEM,
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
func(actual *tls.Config, err error) {
|
||||||
|
assert.Contains(t, err.Error(), "either both cert and key or none must be provided")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Invalid cert and key returns error",
|
||||||
|
"prefix",
|
||||||
|
"",
|
||||||
|
"invalid-cert",
|
||||||
|
"invalid-key",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
func(actual *tls.Config, err error) {
|
||||||
|
assert.Contains(t, err.Error(), "could not load TLS cert")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Valid cert and key return a valid tls.Config with a certificate",
|
||||||
|
"prefix",
|
||||||
|
"",
|
||||||
|
rsaCertPEM,
|
||||||
|
rsaKeyPEM,
|
||||||
|
"",
|
||||||
|
"server-name",
|
||||||
|
func(actual *tls.Config, err error) {
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, actual.ServerName, "server-name")
|
||||||
|
assert.NotNil(t, actual.Certificates[0])
|
||||||
|
assert.Equal(t, actual.InsecureSkipVerify, false)
|
||||||
|
assert.Equal(t, actual.MinVersion, uint16(defaultMinVersion))
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range tests {
|
||||||
|
t.Run(tc.title, func(t *testing.T) {
|
||||||
|
// setup
|
||||||
|
dir := t.TempDir()
|
||||||
|
|
||||||
|
if tc.caFile != "" {
|
||||||
|
path := fmt.Sprintf("%s/caFile", dir)
|
||||||
|
utils.WriteToFile(path, tc.caFile)
|
||||||
|
t.Setenv(fmt.Sprintf("%s_CA_FILE", tc.prefix), path)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tc.certFile != "" {
|
||||||
|
path := fmt.Sprintf("%s/certFile", dir)
|
||||||
|
utils.WriteToFile(path, tc.certFile)
|
||||||
|
t.Setenv(fmt.Sprintf("%s_CERT_FILE", tc.prefix), path)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tc.keyFile != "" {
|
||||||
|
path := fmt.Sprintf("%s/keyFile", dir)
|
||||||
|
utils.WriteToFile(path, tc.keyFile)
|
||||||
|
t.Setenv(fmt.Sprintf("%s_KEY_FILE", tc.prefix), path)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tc.serverName != "" {
|
||||||
|
t.Setenv(fmt.Sprintf("%s_TLS_SERVER_NAME", tc.prefix), tc.serverName)
|
||||||
|
}
|
||||||
|
|
||||||
|
if tc.isInsecureStr != "" {
|
||||||
|
t.Setenv(fmt.Sprintf("%s_INSECURE", tc.prefix), tc.isInsecureStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// test
|
||||||
|
actual, err := CreateTLSConfig(tc.prefix)
|
||||||
|
tc.assertions(actual, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -25,7 +25,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ConflictResolver is used to make a decision in case of two or more different kubernetes resources
|
// ConflictResolver is used to make a decision in case of two or more different kubernetes resources
|
||||||
// are trying to acquire same DNS name
|
// are trying to acquire the same DNS name
|
||||||
type ConflictResolver interface {
|
type ConflictResolver interface {
|
||||||
ResolveCreate(candidates []*endpoint.Endpoint) *endpoint.Endpoint
|
ResolveCreate(candidates []*endpoint.Endpoint) *endpoint.Endpoint
|
||||||
ResolveUpdate(current *endpoint.Endpoint, candidates []*endpoint.Endpoint) *endpoint.Endpoint
|
ResolveUpdate(current *endpoint.Endpoint, candidates []*endpoint.Endpoint) *endpoint.Endpoint
|
||||||
@ -38,13 +38,13 @@ type PerResource struct{}
|
|||||||
// ResolveCreate is invoked when dns name is not owned by any resource
|
// ResolveCreate is invoked when dns name is not owned by any resource
|
||||||
// ResolveCreate takes "minimal" (string comparison of Target) endpoint to acquire the DNS record
|
// ResolveCreate takes "minimal" (string comparison of Target) endpoint to acquire the DNS record
|
||||||
func (s PerResource) ResolveCreate(candidates []*endpoint.Endpoint) *endpoint.Endpoint {
|
func (s PerResource) ResolveCreate(candidates []*endpoint.Endpoint) *endpoint.Endpoint {
|
||||||
var min *endpoint.Endpoint
|
var minE *endpoint.Endpoint
|
||||||
for _, ep := range candidates {
|
for _, ep := range candidates {
|
||||||
if min == nil || s.less(ep, min) {
|
if minE == nil || s.less(ep, minE) {
|
||||||
min = ep
|
minE = ep
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return min
|
return minE
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResolveUpdate is invoked when dns name is already owned by "current" endpoint
|
// ResolveUpdate is invoked when dns name is already owned by "current" endpoint
|
||||||
|
16
plan/plan.go
16
plan/plan.go
@ -54,13 +54,13 @@ type Plan struct {
|
|||||||
// Changes holds lists of actions to be executed by dns providers
|
// Changes holds lists of actions to be executed by dns providers
|
||||||
type Changes struct {
|
type Changes struct {
|
||||||
// Records that need to be created
|
// Records that need to be created
|
||||||
Create []*endpoint.Endpoint
|
Create []*endpoint.Endpoint `json:"create,omitempty"`
|
||||||
// Records that need to be updated (current data)
|
// Records that need to be updated (current data)
|
||||||
UpdateOld []*endpoint.Endpoint
|
UpdateOld []*endpoint.Endpoint `json:"updateOld,omitempty"`
|
||||||
// Records that need to be updated (desired data)
|
// Records that need to be updated (desired data)
|
||||||
UpdateNew []*endpoint.Endpoint
|
UpdateNew []*endpoint.Endpoint `json:"updateNew,omitempty"`
|
||||||
// Records that need to be deleted
|
// Records that need to be deleted
|
||||||
Delete []*endpoint.Endpoint
|
Delete []*endpoint.Endpoint `json:"delete,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// planKey is a key for a row in `planTable`.
|
// planKey is a key for a row in `planTable`.
|
||||||
@ -262,9 +262,11 @@ func (p *Plan) Calculate() *Plan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
plan := &Plan{
|
plan := &Plan{
|
||||||
Current: p.Current,
|
Current: p.Current,
|
||||||
Desired: p.Desired,
|
Desired: p.Desired,
|
||||||
Changes: changes,
|
Changes: changes,
|
||||||
|
// The default for ExternalDNS is to always only consider A/AAAA and CNAMEs.
|
||||||
|
// Everything else is an add on or something to be considered.
|
||||||
ManagedRecords: []string{endpoint.RecordTypeA, endpoint.RecordTypeAAAA, endpoint.RecordTypeCNAME},
|
ManagedRecords: []string{endpoint.RecordTypeA, endpoint.RecordTypeAAAA, endpoint.RecordTypeCNAME},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,9 @@ limitations under the License.
|
|||||||
package plan
|
package plan
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@ -245,6 +248,48 @@ func (suite *PlanTestSuite) SetupTest() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPlan_ChangesJson_DecodeEncode(t *testing.T) {
|
||||||
|
ch := &Changes{
|
||||||
|
Create: []*endpoint.Endpoint{
|
||||||
|
{
|
||||||
|
DNSName: "foo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
UpdateOld: []*endpoint.Endpoint{
|
||||||
|
{
|
||||||
|
DNSName: "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
UpdateNew: []*endpoint.Endpoint{
|
||||||
|
{
|
||||||
|
DNSName: "baz",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Delete: []*endpoint.Endpoint{
|
||||||
|
{
|
||||||
|
DNSName: "qux",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
jsonBytes, err := json.Marshal(ch)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t,
|
||||||
|
`{"create":[{"dnsName":"foo"}],"updateOld":[{"dnsName":"bar"}],"updateNew":[{"dnsName":"baz"}],"delete":[{"dnsName":"qux"}]}`,
|
||||||
|
string(jsonBytes))
|
||||||
|
var changes Changes
|
||||||
|
err = json.NewDecoder(bytes.NewBuffer(jsonBytes)).Decode(&changes)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, ch, &changes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPlan_ChangesJson_DecodeMixedCase(t *testing.T) {
|
||||||
|
input := `{"Create":[{"dnsName":"foo"}],"UpdateOld":[{"dnsName":"bar"}],"updateNew":[{"dnsName":"baz"}],"Delete":[{"dnsName":"qux"}]}`
|
||||||
|
var changes Changes
|
||||||
|
err := json.NewDecoder(strings.NewReader(input)).Decode(&changes)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, changes.Create, 1)
|
||||||
|
}
|
||||||
|
|
||||||
func (suite *PlanTestSuite) TestSyncFirstRound() {
|
func (suite *PlanTestSuite) TestSyncFirstRound() {
|
||||||
current := []*endpoint.Endpoint{}
|
current := []*endpoint.Endpoint{}
|
||||||
desired := []*endpoint.Endpoint{suite.fooV1Cname, suite.fooV2Cname, suite.bar127A}
|
desired := []*endpoint.Endpoint{suite.fooV1Cname, suite.fooV2Cname, suite.bar127A}
|
||||||
@ -367,9 +412,22 @@ func (suite *PlanTestSuite) TestSyncSecondRoundWithProviderSpecificNoChange() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
changes := p.Calculate().Changes
|
changes := p.Calculate().Changes
|
||||||
if changes.HasChanges() {
|
suite.Assert().False(changes.HasChanges())
|
||||||
suite.T().Fatal("test should not have changes")
|
}
|
||||||
|
|
||||||
|
func (suite *PlanTestSuite) TestHasChanges() {
|
||||||
|
current := []*endpoint.Endpoint{suite.bar127AWithProviderSpecificTrue}
|
||||||
|
desired := []*endpoint.Endpoint{suite.bar127AWithProviderSpecificFalse}
|
||||||
|
|
||||||
|
p := &Plan{
|
||||||
|
Policies: []Policy{&SyncPolicy{}},
|
||||||
|
Current: current,
|
||||||
|
Desired: desired,
|
||||||
|
ManagedRecords: []string{endpoint.RecordTypeA, endpoint.RecordTypeCNAME},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
changes := p.Calculate().Changes
|
||||||
|
suite.Assert().True(changes.HasChanges())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (suite *PlanTestSuite) TestSyncSecondRoundWithProviderSpecificRemoval() {
|
func (suite *PlanTestSuite) TestSyncSecondRoundWithProviderSpecificRemoval() {
|
||||||
|
@ -34,9 +34,9 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// Default Record TTL
|
// Default Record TTL
|
||||||
edgeDNSRecordTTL = 600
|
defaultTTL = 600
|
||||||
maxUint = ^uint(0)
|
maxUint = ^uint(0)
|
||||||
maxInt = int(maxUint >> 1)
|
maxInt = int(maxUint >> 1)
|
||||||
)
|
)
|
||||||
|
|
||||||
// edgeDNSClient is a proxy interface of the Akamai edgegrid configdns-v2 package that can be stubbed for testing.
|
// edgeDNSClient is a proxy interface of the Akamai edgegrid configdns-v2 package that can be stubbed for testing.
|
||||||
@ -90,14 +90,6 @@ type akamaiZone struct {
|
|||||||
func NewAkamaiProvider(akamaiConfig AkamaiConfig, akaService AkamaiDNSService) (provider.Provider, error) {
|
func NewAkamaiProvider(akamaiConfig AkamaiConfig, akaService AkamaiDNSService) (provider.Provider, error) {
|
||||||
var edgeGridConfig edgegrid.Config
|
var edgeGridConfig edgegrid.Config
|
||||||
|
|
||||||
/*
|
|
||||||
log.Debugf("Host: %s", akamaiConfig.ServiceConsumerDomain)
|
|
||||||
log.Debugf("ClientToken: %s", akamaiConfig.ClientToken)
|
|
||||||
log.Debugf("ClientSecret: %s", akamaiConfig.ClientSecret)
|
|
||||||
log.Debugf("AccessToken: %s", akamaiConfig.AccessToken)
|
|
||||||
log.Debugf("EdgePath: %s", akamaiConfig.EdgercPath)
|
|
||||||
log.Debugf("EdgeSection: %s", akamaiConfig.EdgercSection)
|
|
||||||
*/
|
|
||||||
// environment overrides edgerc file but config needs to be complete
|
// environment overrides edgerc file but config needs to be complete
|
||||||
if akamaiConfig.ServiceConsumerDomain == "" || akamaiConfig.ClientToken == "" || akamaiConfig.ClientSecret == "" || akamaiConfig.AccessToken == "" {
|
if akamaiConfig.ServiceConsumerDomain == "" || akamaiConfig.ClientToken == "" || akamaiConfig.ClientSecret == "" || akamaiConfig.AccessToken == "" {
|
||||||
// Kubernetes config incomplete or non existent. Can't mix and match.
|
// Kubernetes config incomplete or non existent. Can't mix and match.
|
||||||
@ -106,7 +98,7 @@ func NewAkamaiProvider(akamaiConfig AkamaiConfig, akaService AkamaiDNSService) (
|
|||||||
edgeGridConfig, err = edgegrid.Init(akamaiConfig.EdgercPath, akamaiConfig.EdgercSection) // use default .edgerc location and section
|
edgeGridConfig, err = edgegrid.Init(akamaiConfig.EdgercPath, akamaiConfig.EdgercSection) // use default .edgerc location and section
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Edgegrid Init Failed")
|
log.Errorf("Edgegrid Init Failed")
|
||||||
return &AkamaiProvider{}, err // return empty provider for backward compatibility
|
return &AkamaiProvider{}, err // return an empty provider for backward compatibility
|
||||||
}
|
}
|
||||||
edgeGridConfig.HeaderToSign = append(edgeGridConfig.HeaderToSign, "X-External-DNS")
|
edgeGridConfig.HeaderToSign = append(edgeGridConfig.HeaderToSign, "X-External-DNS")
|
||||||
} else {
|
} else {
|
||||||
@ -360,7 +352,7 @@ func trimTxtRdata(rdata []string, rtype string) []string {
|
|||||||
func ttlAsInt(src endpoint.TTL) int {
|
func ttlAsInt(src endpoint.TTL) int {
|
||||||
var temp interface{} = int64(src)
|
var temp interface{} = int64(src)
|
||||||
temp64 := temp.(int64)
|
temp64 := temp.(int64)
|
||||||
var ttl = edgeDNSRecordTTL
|
var ttl = defaultTTL
|
||||||
if temp64 > 0 && temp64 <= int64(maxInt) {
|
if temp64 > 0 && temp64 <= int64(maxInt) {
|
||||||
ttl = int(temp64)
|
ttl = int(temp64)
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultAlibabaCloudRecordTTL = 600
|
defaultTTL = 600
|
||||||
defaultAlibabaCloudPrivateZoneRecordTTL = 60
|
defaultAlibabaCloudPrivateZoneRecordTTL = 60
|
||||||
defaultAlibabaCloudPageSize = 50
|
defaultAlibabaCloudPageSize = 50
|
||||||
nullHostAlibabaCloud = "@"
|
nullHostAlibabaCloud = "@"
|
||||||
@ -606,12 +606,12 @@ func (p *AlibabaCloudProvider) deleteRecords(recordMap map[string][]alidns.Recor
|
|||||||
|
|
||||||
func (p *AlibabaCloudProvider) equals(record alidns.Record, endpoint *endpoint.Endpoint) bool {
|
func (p *AlibabaCloudProvider) equals(record alidns.Record, endpoint *endpoint.Endpoint) bool {
|
||||||
ttl1 := record.TTL
|
ttl1 := record.TTL
|
||||||
if ttl1 == defaultAlibabaCloudRecordTTL {
|
if ttl1 == defaultTTL {
|
||||||
ttl1 = 0
|
ttl1 = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
ttl2 := int64(endpoint.RecordTTL)
|
ttl2 := int64(endpoint.RecordTTL)
|
||||||
if ttl2 == defaultAlibabaCloudRecordTTL {
|
if ttl2 == defaultTTL {
|
||||||
ttl2 = 0
|
ttl2 = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
|
|
||||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/alidns"
|
"github.com/aliyun/alibaba-cloud-sdk-go/services/alidns"
|
||||||
"github.com/aliyun/alibaba-cloud-sdk-go/services/pvtz"
|
"github.com/aliyun/alibaba-cloud-sdk-go/services/pvtz"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"sigs.k8s.io/external-dns/endpoint"
|
"sigs.k8s.io/external-dns/endpoint"
|
||||||
"sigs.k8s.io/external-dns/plan"
|
"sigs.k8s.io/external-dns/plan"
|
||||||
@ -223,18 +224,7 @@ func newTestAlibabaCloudProvider(private bool) *AlibabaCloudProvider {
|
|||||||
cfg := alibabaCloudConfig{
|
cfg := alibabaCloudConfig{
|
||||||
VPCID: "vpc-xxxxxx",
|
VPCID: "vpc-xxxxxx",
|
||||||
}
|
}
|
||||||
//
|
|
||||||
//dnsClient, _ := alidns.NewClientWithAccessKey(
|
|
||||||
// cfg.RegionID,
|
|
||||||
// cfg.AccessKeyID,
|
|
||||||
// cfg.AccessKeySecret,
|
|
||||||
//)
|
|
||||||
//
|
|
||||||
//pvtzClient, _ := pvtz.NewClientWithAccessKey(
|
|
||||||
// "cn-hangzhou",
|
|
||||||
// cfg.AccessKeyID,
|
|
||||||
// cfg.AccessKeySecret,
|
|
||||||
//)
|
|
||||||
domainFilterTest := endpoint.NewDomainFilter([]string{"container-service.top.", "example.org"})
|
domainFilterTest := endpoint.NewDomainFilter([]string{"container-service.top.", "example.org"})
|
||||||
|
|
||||||
return &AlibabaCloudProvider{
|
return &AlibabaCloudProvider{
|
||||||
@ -256,8 +246,8 @@ func TestAlibabaCloudPrivateProvider_Records(t *testing.T) {
|
|||||||
if len(endpoints) != 2 {
|
if len(endpoints) != 2 {
|
||||||
t.Errorf("Incorrect number of records: %d", len(endpoints))
|
t.Errorf("Incorrect number of records: %d", len(endpoints))
|
||||||
}
|
}
|
||||||
for _, endpoint := range endpoints {
|
for _, ep := range endpoints {
|
||||||
t.Logf("Endpoint for %++v", *endpoint)
|
t.Logf("Endpoint for %++v", *ep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -271,8 +261,8 @@ func TestAlibabaCloudProvider_Records(t *testing.T) {
|
|||||||
if len(endpoints) != 2 {
|
if len(endpoints) != 2 {
|
||||||
t.Errorf("Incorrect number of records: %d", len(endpoints))
|
t.Errorf("Incorrect number of records: %d", len(endpoints))
|
||||||
}
|
}
|
||||||
for _, endpoint := range endpoints {
|
for _, ep := range endpoints {
|
||||||
t.Logf("Endpoint for %++v", *endpoint)
|
t.Logf("Endpoint for %++v", *ep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -282,7 +272,7 @@ func TestAlibabaCloudProvider_ApplyChanges(t *testing.T) {
|
|||||||
defaultTtlPlan := &endpoint.Endpoint{
|
defaultTtlPlan := &endpoint.Endpoint{
|
||||||
DNSName: "ttl.container-service.top",
|
DNSName: "ttl.container-service.top",
|
||||||
RecordType: "A",
|
RecordType: "A",
|
||||||
RecordTTL: defaultAlibabaCloudRecordTTL,
|
RecordTTL: defaultTTL,
|
||||||
Targets: endpoint.NewTargets("4.3.2.1"),
|
Targets: endpoint.NewTargets("4.3.2.1"),
|
||||||
}
|
}
|
||||||
changes := plan.Changes{
|
changes := plan.Changes{
|
||||||
@ -313,7 +303,8 @@ func TestAlibabaCloudProvider_ApplyChanges(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
p.ApplyChanges(ctx, &changes)
|
err := p.ApplyChanges(ctx, &changes)
|
||||||
|
assert.NoError(t, err)
|
||||||
endpoints, err := p.Records(ctx)
|
endpoints, err := p.Records(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to get records: %v", err)
|
t.Errorf("Failed to get records: %v", err)
|
||||||
@ -321,8 +312,8 @@ func TestAlibabaCloudProvider_ApplyChanges(t *testing.T) {
|
|||||||
if len(endpoints) != 3 {
|
if len(endpoints) != 3 {
|
||||||
t.Errorf("Incorrect number of records: %d", len(endpoints))
|
t.Errorf("Incorrect number of records: %d", len(endpoints))
|
||||||
}
|
}
|
||||||
for _, endpoint := range endpoints {
|
for _, ep := range endpoints {
|
||||||
t.Logf("Endpoint for %++v", *endpoint)
|
t.Logf("Endpoint for %++v", *ep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, ep := range endpoints {
|
for _, ep := range endpoints {
|
||||||
@ -343,8 +334,8 @@ func TestAlibabaCloudProvider_Records_PrivateZone(t *testing.T) {
|
|||||||
if len(endpoints) != 2 {
|
if len(endpoints) != 2 {
|
||||||
t.Errorf("Incorrect number of records: %d", len(endpoints))
|
t.Errorf("Incorrect number of records: %d", len(endpoints))
|
||||||
}
|
}
|
||||||
for _, endpoint := range endpoints {
|
for _, ep := range endpoints {
|
||||||
t.Logf("Endpoint for %++v", *endpoint)
|
t.Logf("Endpoint for %++v", *ep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -378,7 +369,8 @@ func TestAlibabaCloudProvider_ApplyChanges_PrivateZone(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
p.ApplyChanges(ctx, &changes)
|
err := p.ApplyChanges(ctx, &changes)
|
||||||
|
assert.NoError(t, err)
|
||||||
endpoints, err := p.Records(ctx)
|
endpoints, err := p.Records(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Failed to get records: %v", err)
|
t.Errorf("Failed to get records: %v", err)
|
||||||
@ -386,8 +378,8 @@ func TestAlibabaCloudProvider_ApplyChanges_PrivateZone(t *testing.T) {
|
|||||||
if len(endpoints) != 2 {
|
if len(endpoints) != 2 {
|
||||||
t.Errorf("Incorrect number of records: %d", len(endpoints))
|
t.Errorf("Incorrect number of records: %d", len(endpoints))
|
||||||
}
|
}
|
||||||
for _, endpoint := range endpoints {
|
for _, ep := range endpoints {
|
||||||
t.Logf("Endpoint for %++v", *endpoint)
|
t.Logf("Endpoint for %++v", *ep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
defaultAWSProfile = "default"
|
defaultAWSProfile = "default"
|
||||||
recordTTL = 300
|
defaultTTL = 300
|
||||||
// From the experiments, it seems that the default MaxItems applied is 100,
|
// From the experiments, it seems that the default MaxItems applied is 100,
|
||||||
// and that, on the server side, there is a hard limit of 300 elements per page.
|
// and that, on the server side, there is a hard limit of 300 elements per page.
|
||||||
// After a discussion with AWS representatives, clients should accept
|
// After a discussion with AWS representatives, clients should accept
|
||||||
@ -232,7 +232,7 @@ type profiledZone struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cs Route53Changes) Route53Changes() []route53types.Change {
|
func (cs Route53Changes) Route53Changes() []route53types.Change {
|
||||||
ret := []route53types.Change{}
|
var ret []route53types.Change
|
||||||
for _, c := range cs {
|
for _, c := range cs {
|
||||||
ret = append(ret, c.Change)
|
ret = append(ret, c.Change)
|
||||||
}
|
}
|
||||||
@ -313,7 +313,7 @@ type AWSConfig struct {
|
|||||||
|
|
||||||
// NewAWSProvider initializes a new AWS Route53 based Provider.
|
// NewAWSProvider initializes a new AWS Route53 based Provider.
|
||||||
func NewAWSProvider(awsConfig AWSConfig, clients map[string]Route53API) (*AWSProvider, error) {
|
func NewAWSProvider(awsConfig AWSConfig, clients map[string]Route53API) (*AWSProvider, error) {
|
||||||
provider := &AWSProvider{
|
pr := &AWSProvider{
|
||||||
clients: clients,
|
clients: clients,
|
||||||
domainFilter: awsConfig.DomainFilter,
|
domainFilter: awsConfig.DomainFilter,
|
||||||
zoneIDFilter: awsConfig.ZoneIDFilter,
|
zoneIDFilter: awsConfig.ZoneIDFilter,
|
||||||
@ -331,7 +331,7 @@ func NewAWSProvider(awsConfig AWSConfig, clients map[string]Route53API) (*AWSPro
|
|||||||
failedChangesQueue: make(map[string]Route53Changes),
|
failedChangesQueue: make(map[string]Route53Changes),
|
||||||
}
|
}
|
||||||
|
|
||||||
return provider, nil
|
return pr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zones returns the list of hosted zones.
|
// Zones returns the list of hosted zones.
|
||||||
@ -510,7 +510,7 @@ func (p *AWSProvider) records(ctx context.Context, zones map[string]*profiledZon
|
|||||||
if r.AliasTarget != nil {
|
if r.AliasTarget != nil {
|
||||||
// Alias records don't have TTLs so provide the default to match the TXT generation
|
// Alias records don't have TTLs so provide the default to match the TXT generation
|
||||||
if ttl == 0 {
|
if ttl == 0 {
|
||||||
ttl = recordTTL
|
ttl = defaultTTL
|
||||||
}
|
}
|
||||||
ep := endpoint.
|
ep := endpoint.
|
||||||
NewEndpointWithTTL(name, string(r.Type), ttl, *r.AliasTarget.DNSName).
|
NewEndpointWithTTL(name, string(r.Type), ttl, *r.AliasTarget.DNSName).
|
||||||
@ -561,33 +561,33 @@ func (p *AWSProvider) records(ctx context.Context, zones map[string]*profiledZon
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Identify if old and new endpoints require DELETE/CREATE instead of UPDATE.
|
// Identify if old and new endpoints require DELETE/CREATE instead of UPDATE.
|
||||||
func (p *AWSProvider) requiresDeleteCreate(old *endpoint.Endpoint, new *endpoint.Endpoint) bool {
|
func (p *AWSProvider) requiresDeleteCreate(old *endpoint.Endpoint, newE *endpoint.Endpoint) bool {
|
||||||
// a change of record type
|
// a change of a record type
|
||||||
if old.RecordType != new.RecordType {
|
if old.RecordType != newE.RecordType {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// an ALIAS record change to/from an A
|
// an ALIAS record change to/from an A
|
||||||
if old.RecordType == endpoint.RecordTypeA {
|
if old.RecordType == endpoint.RecordTypeA {
|
||||||
oldAlias, _ := old.GetProviderSpecificProperty(providerSpecificAlias)
|
oldAlias, _ := old.GetProviderSpecificProperty(providerSpecificAlias)
|
||||||
newAlias, _ := new.GetProviderSpecificProperty(providerSpecificAlias)
|
newAlias, _ := newE.GetProviderSpecificProperty(providerSpecificAlias)
|
||||||
if oldAlias != newAlias {
|
if oldAlias != newAlias {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// a set identifier change
|
// a set identifier change
|
||||||
if old.SetIdentifier != new.SetIdentifier {
|
if old.SetIdentifier != newE.SetIdentifier {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// a change of routing policy
|
// a change of routing policy
|
||||||
// default to true for geolocation properties if any geolocation property exists in old/new but not the other
|
// defaults to true for geolocation properties if any geolocation property exists in old/new but not the other
|
||||||
for _, propType := range [7]string{providerSpecificWeight, providerSpecificRegion, providerSpecificFailover,
|
for _, propType := range [7]string{providerSpecificWeight, providerSpecificRegion, providerSpecificFailover,
|
||||||
providerSpecificFailover, providerSpecificGeolocationContinentCode, providerSpecificGeolocationCountryCode,
|
providerSpecificFailover, providerSpecificGeolocationContinentCode, providerSpecificGeolocationCountryCode,
|
||||||
providerSpecificGeolocationSubdivisionCode} {
|
providerSpecificGeolocationSubdivisionCode} {
|
||||||
_, oldPolicy := old.GetProviderSpecificProperty(propType)
|
_, oldPolicy := old.GetProviderSpecificProperty(propType)
|
||||||
_, newPolicy := new.GetProviderSpecificProperty(propType)
|
_, newPolicy := newE.GetProviderSpecificProperty(propType)
|
||||||
if oldPolicy != newPolicy {
|
if oldPolicy != newPolicy {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@ -601,14 +601,14 @@ func (p *AWSProvider) createUpdateChanges(newEndpoints, oldEndpoints []*endpoint
|
|||||||
var creates []*endpoint.Endpoint
|
var creates []*endpoint.Endpoint
|
||||||
var updates []*endpoint.Endpoint
|
var updates []*endpoint.Endpoint
|
||||||
|
|
||||||
for i, new := range newEndpoints {
|
for i, newE := range newEndpoints {
|
||||||
old := oldEndpoints[i]
|
oldE := oldEndpoints[i]
|
||||||
if p.requiresDeleteCreate(old, new) {
|
if p.requiresDeleteCreate(oldE, newE) {
|
||||||
deletes = append(deletes, old)
|
deletes = append(deletes, oldE)
|
||||||
creates = append(creates, new)
|
creates = append(creates, newE)
|
||||||
} else {
|
} else {
|
||||||
// Safe to perform an UPSERT.
|
// Safe to perform an UPSERT.
|
||||||
updates = append(updates, new)
|
updates = append(updates, newE)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -760,8 +760,8 @@ func (p *AWSProvider) submitChanges(ctx context.Context, changes Route53Changes,
|
|||||||
func (p *AWSProvider) newChanges(action route53types.ChangeAction, endpoints []*endpoint.Endpoint) Route53Changes {
|
func (p *AWSProvider) newChanges(action route53types.ChangeAction, endpoints []*endpoint.Endpoint) Route53Changes {
|
||||||
changes := make(Route53Changes, 0, len(endpoints))
|
changes := make(Route53Changes, 0, len(endpoints))
|
||||||
|
|
||||||
for _, endpoint := range endpoints {
|
for _, ep := range endpoints {
|
||||||
change := p.newChange(action, endpoint)
|
change := p.newChange(action, ep)
|
||||||
changes = append(changes, change)
|
changes = append(changes, change)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -804,8 +804,8 @@ func (p *AWSProvider) AdjustEndpoints(endpoints []*endpoint.Endpoint) ([]*endpoi
|
|||||||
|
|
||||||
if alias {
|
if alias {
|
||||||
if ep.RecordTTL.IsConfigured() {
|
if ep.RecordTTL.IsConfigured() {
|
||||||
log.Debugf("Modifying endpoint: %v, setting ttl=%v", ep, recordTTL)
|
log.Debugf("Modifying endpoint: %v, setting ttl=%v", ep, defaultTTL)
|
||||||
ep.RecordTTL = recordTTL
|
ep.RecordTTL = defaultTTL
|
||||||
}
|
}
|
||||||
if prop, ok := ep.GetProviderSpecificProperty(providerSpecificEvaluateTargetHealth); ok {
|
if prop, ok := ep.GetProviderSpecificProperty(providerSpecificEvaluateTargetHealth); ok {
|
||||||
if prop != "true" && prop != "false" {
|
if prop != "true" && prop != "false" {
|
||||||
@ -866,7 +866,7 @@ func (p *AWSProvider) newChange(action route53types.ChangeAction, ep *endpoint.E
|
|||||||
change.sizeValues += 1
|
change.sizeValues += 1
|
||||||
} else {
|
} else {
|
||||||
if !ep.RecordTTL.IsConfigured() {
|
if !ep.RecordTTL.IsConfigured() {
|
||||||
change.ResourceRecordSet.TTL = aws.Int64(recordTTL)
|
change.ResourceRecordSet.TTL = aws.Int64(defaultTTL)
|
||||||
} else {
|
} else {
|
||||||
change.ResourceRecordSet.TTL = aws.Int64(int64(ep.RecordTTL))
|
change.ResourceRecordSet.TTL = aws.Int64(int64(ep.RecordTTL))
|
||||||
}
|
}
|
||||||
|
@ -101,7 +101,8 @@ func TestAWSZonesSecondRequestHitsTheCache(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
_, err := provider.Zones(ctx)
|
_, err := provider.Zones(ctx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
b := testutils.LogsToBuffer(log.DebugLevel, t)
|
hook := testutils.LogsUnderTestWithLogLevel(log.DebugLevel, t)
|
||||||
_, _ = provider.Zones(ctx)
|
_, _ = provider.Zones(ctx)
|
||||||
assert.Contains(t, b.String(), "level=debug msg=\"Using cached zones list\"")
|
|
||||||
|
testutils.TestHelperLogContainsWithLogLevel("Using cached zones list", log.DebugLevel, hook, t)
|
||||||
}
|
}
|
||||||
|
@ -400,37 +400,37 @@ func TestAWSRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("list-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("list-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("list-test.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("list-test.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String(wildcardEscape("*.wildcard-test.zone-2.ext-dns-test-2.teapot.zalan.do.")),
|
Name: aws.String(wildcardEscape("*.wildcard-test.zone-2.ext-dns-test-2.teapot.zalan.do.")),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String(specialCharactersEscape("escape-%!s(<nil>)-codes.zone-2.ext-dns-test-2.teapot.zalan.do.")),
|
Name: aws.String(specialCharactersEscape("escape-%!s(<nil>)-codes.zone-2.ext-dns-test-2.teapot.zalan.do.")),
|
||||||
Type: route53types.RRTypeCname,
|
Type: route53types.RRTypeCname,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("example")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("example")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String(specialCharactersEscape("escape-%!s(<nil>)-codes-a.zone-2.ext-dns-test-2.teapot.zalan.do.")),
|
Name: aws.String(specialCharactersEscape("escape-%!s(<nil>)-codes-a.zone-2.ext-dns-test-2.teapot.zalan.do.")),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String(specialCharactersEscape("escape-%!s(<nil>)-codes-alias.zone-2.ext-dns-test-2.teapot.zalan.do.")),
|
Name: aws.String(specialCharactersEscape("escape-%!s(<nil>)-codes-alias.zone-2.ext-dns-test-2.teapot.zalan.do.")),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
AliasTarget: &route53types.AliasTarget{
|
AliasTarget: &route53types.AliasTarget{
|
||||||
DNSName: aws.String("escape-codes.eu-central-1.elb.amazonaws.com."),
|
DNSName: aws.String("escape-codes.eu-central-1.elb.amazonaws.com."),
|
||||||
EvaluateTargetHealth: false,
|
EvaluateTargetHealth: false,
|
||||||
@ -440,7 +440,7 @@ func TestAWSRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String(specialCharactersEscape("escape-%!s(<nil>)-codes-alias.zone-2.ext-dns-test-2.teapot.zalan.do.")),
|
Name: aws.String(specialCharactersEscape("escape-%!s(<nil>)-codes-alias.zone-2.ext-dns-test-2.teapot.zalan.do.")),
|
||||||
Type: route53types.RRTypeAaaa,
|
Type: route53types.RRTypeAaaa,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
AliasTarget: &route53types.AliasTarget{
|
AliasTarget: &route53types.AliasTarget{
|
||||||
DNSName: aws.String("escape-codes.eu-central-1.elb.amazonaws.com."),
|
DNSName: aws.String("escape-codes.eu-central-1.elb.amazonaws.com."),
|
||||||
EvaluateTargetHealth: false,
|
EvaluateTargetHealth: false,
|
||||||
@ -504,19 +504,19 @@ func TestAWSRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("list-test-multiple.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("list-test-multiple.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}, {Value: aws.String("8.8.4.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}, {Value: aws.String("8.8.4.4")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("prefix-*.wildcard.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("prefix-*.wildcard.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeTxt,
|
Type: route53types.RRTypeTxt,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("random")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("random")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("weight-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("weight-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
SetIdentifier: aws.String("test-set-1"),
|
SetIdentifier: aws.String("test-set-1"),
|
||||||
Weight: aws.Int64(10),
|
Weight: aws.Int64(10),
|
||||||
@ -524,7 +524,7 @@ func TestAWSRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("weight-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("weight-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("4.3.2.1")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("4.3.2.1")}},
|
||||||
SetIdentifier: aws.String("test-set-2"),
|
SetIdentifier: aws.String("test-set-2"),
|
||||||
Weight: aws.Int64(20),
|
Weight: aws.Int64(20),
|
||||||
@ -532,7 +532,7 @@ func TestAWSRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("latency-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("latency-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
SetIdentifier: aws.String("test-set"),
|
SetIdentifier: aws.String("test-set"),
|
||||||
Region: route53types.ResourceRecordSetRegionUsEast1,
|
Region: route53types.ResourceRecordSetRegionUsEast1,
|
||||||
@ -540,7 +540,7 @@ func TestAWSRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("failover-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("failover-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
SetIdentifier: aws.String("test-set"),
|
SetIdentifier: aws.String("test-set"),
|
||||||
Failover: route53types.ResourceRecordSetFailoverPrimary,
|
Failover: route53types.ResourceRecordSetFailoverPrimary,
|
||||||
@ -548,7 +548,7 @@ func TestAWSRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("multi-value-answer-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("multi-value-answer-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
SetIdentifier: aws.String("test-set"),
|
SetIdentifier: aws.String("test-set"),
|
||||||
MultiValueAnswer: aws.Bool(true),
|
MultiValueAnswer: aws.Bool(true),
|
||||||
@ -556,7 +556,7 @@ func TestAWSRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("geolocation-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("geolocation-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
SetIdentifier: aws.String("test-set-1"),
|
SetIdentifier: aws.String("test-set-1"),
|
||||||
GeoLocation: &route53types.GeoLocation{
|
GeoLocation: &route53types.GeoLocation{
|
||||||
@ -566,7 +566,7 @@ func TestAWSRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("geolocation-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("geolocation-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("4.3.2.1")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("4.3.2.1")}},
|
||||||
SetIdentifier: aws.String("test-set-2"),
|
SetIdentifier: aws.String("test-set-2"),
|
||||||
GeoLocation: &route53types.GeoLocation{
|
GeoLocation: &route53types.GeoLocation{
|
||||||
@ -576,7 +576,7 @@ func TestAWSRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("geolocation-subdivision-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("geolocation-subdivision-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
SetIdentifier: aws.String("test-set-1"),
|
SetIdentifier: aws.String("test-set-1"),
|
||||||
GeoLocation: &route53types.GeoLocation{
|
GeoLocation: &route53types.GeoLocation{
|
||||||
@ -586,7 +586,7 @@ func TestAWSRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("healthcheck-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("healthcheck-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeCname,
|
Type: route53types.RRTypeCname,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("foo.example.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("foo.example.com")}},
|
||||||
SetIdentifier: aws.String("test-set-1"),
|
SetIdentifier: aws.String("test-set-1"),
|
||||||
HealthCheckId: aws.String("foo-bar-healthcheck-id"),
|
HealthCheckId: aws.String("foo-bar-healthcheck-id"),
|
||||||
@ -595,7 +595,7 @@ func TestAWSRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("healthcheck-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("healthcheck-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("4.3.2.1")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("4.3.2.1")}},
|
||||||
SetIdentifier: aws.String("test-set-2"),
|
SetIdentifier: aws.String("test-set-2"),
|
||||||
HealthCheckId: aws.String("abc-def-healthcheck-id"),
|
HealthCheckId: aws.String("abc-def-healthcheck-id"),
|
||||||
@ -604,7 +604,7 @@ func TestAWSRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("mail.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("mail.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeMx,
|
Type: route53types.RRTypeMx,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("10 mailhost1.example.com")}, {Value: aws.String("20 mailhost2.example.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("10 mailhost1.example.com")}, {Value: aws.String("20 mailhost2.example.com")}},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -613,32 +613,32 @@ func TestAWSRecords(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
validateEndpoints(t, provider, records, []*endpoint.Endpoint{
|
validateEndpoints(t, provider, records, []*endpoint.Endpoint{
|
||||||
endpoint.NewEndpointWithTTL("list-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.2.3.4"),
|
endpoint.NewEndpointWithTTL("list-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.2.3.4"),
|
||||||
endpoint.NewEndpointWithTTL("list-test.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "8.8.8.8"),
|
endpoint.NewEndpointWithTTL("list-test.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "8.8.8.8"),
|
||||||
endpoint.NewEndpointWithTTL("*.wildcard-test.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "8.8.8.8"),
|
endpoint.NewEndpointWithTTL("*.wildcard-test.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "8.8.8.8"),
|
||||||
endpoint.NewEndpointWithTTL("escape-%!s(<nil>)-codes.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, endpoint.TTL(recordTTL), "example").WithProviderSpecific(providerSpecificAlias, "false"),
|
endpoint.NewEndpointWithTTL("escape-%!s(<nil>)-codes.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, endpoint.TTL(defaultTTL), "example").WithProviderSpecific(providerSpecificAlias, "false"),
|
||||||
endpoint.NewEndpointWithTTL("escape-%!s(<nil>)-codes-a.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.2.3.4"),
|
endpoint.NewEndpointWithTTL("escape-%!s(<nil>)-codes-a.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.2.3.4"),
|
||||||
endpoint.NewEndpointWithTTL("escape-%!s(<nil>)-codes-alias.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "escape-codes.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false").WithProviderSpecific(providerSpecificAlias, "true"),
|
endpoint.NewEndpointWithTTL("escape-%!s(<nil>)-codes-alias.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "escape-codes.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false").WithProviderSpecific(providerSpecificAlias, "true"),
|
||||||
endpoint.NewEndpointWithTTL("escape-%!s(<nil>)-codes-alias.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, endpoint.TTL(recordTTL), "escape-codes.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false").WithProviderSpecific(providerSpecificAlias, "true"),
|
endpoint.NewEndpointWithTTL("escape-%!s(<nil>)-codes-alias.zone-2.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, endpoint.TTL(defaultTTL), "escape-codes.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false").WithProviderSpecific(providerSpecificAlias, "true"),
|
||||||
endpoint.NewEndpointWithTTL("list-test-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false").WithProviderSpecific(providerSpecificAlias, "true"),
|
endpoint.NewEndpointWithTTL("list-test-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false").WithProviderSpecific(providerSpecificAlias, "true"),
|
||||||
endpoint.NewEndpointWithTTL("list-test-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, endpoint.TTL(recordTTL), "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false").WithProviderSpecific(providerSpecificAlias, "true"),
|
endpoint.NewEndpointWithTTL("list-test-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, endpoint.TTL(defaultTTL), "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false").WithProviderSpecific(providerSpecificAlias, "true"),
|
||||||
endpoint.NewEndpointWithTTL("*.wildcard-test-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false").WithProviderSpecific(providerSpecificAlias, "true"),
|
endpoint.NewEndpointWithTTL("*.wildcard-test-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false").WithProviderSpecific(providerSpecificAlias, "true"),
|
||||||
endpoint.NewEndpointWithTTL("*.wildcard-test-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, endpoint.TTL(recordTTL), "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false").WithProviderSpecific(providerSpecificAlias, "true"),
|
endpoint.NewEndpointWithTTL("*.wildcard-test-alias.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, endpoint.TTL(defaultTTL), "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "false").WithProviderSpecific(providerSpecificAlias, "true"),
|
||||||
endpoint.NewEndpointWithTTL("list-test-alias-evaluate.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "true").WithProviderSpecific(providerSpecificAlias, "true"),
|
endpoint.NewEndpointWithTTL("list-test-alias-evaluate.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "true").WithProviderSpecific(providerSpecificAlias, "true"),
|
||||||
endpoint.NewEndpointWithTTL("list-test-alias-evaluate.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, endpoint.TTL(recordTTL), "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "true").WithProviderSpecific(providerSpecificAlias, "true"),
|
endpoint.NewEndpointWithTTL("list-test-alias-evaluate.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeAAAA, endpoint.TTL(defaultTTL), "foo.eu-central-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificEvaluateTargetHealth, "true").WithProviderSpecific(providerSpecificAlias, "true"),
|
||||||
endpoint.NewEndpointWithTTL("list-test-multiple.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "8.8.8.8", "8.8.4.4"),
|
endpoint.NewEndpointWithTTL("list-test-multiple.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "8.8.8.8", "8.8.4.4"),
|
||||||
endpoint.NewEndpointWithTTL("prefix-*.wildcard.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL), "random"),
|
endpoint.NewEndpointWithTTL("prefix-*.wildcard.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeTXT, endpoint.TTL(defaultTTL), "random"),
|
||||||
endpoint.NewEndpointWithTTL("weight-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.2.3.4").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificWeight, "10"),
|
endpoint.NewEndpointWithTTL("weight-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.2.3.4").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificWeight, "10"),
|
||||||
endpoint.NewEndpointWithTTL("weight-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "4.3.2.1").WithSetIdentifier("test-set-2").WithProviderSpecific(providerSpecificWeight, "20"),
|
endpoint.NewEndpointWithTTL("weight-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "4.3.2.1").WithSetIdentifier("test-set-2").WithProviderSpecific(providerSpecificWeight, "20"),
|
||||||
endpoint.NewEndpointWithTTL("latency-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.2.3.4").WithSetIdentifier("test-set").WithProviderSpecific(providerSpecificRegion, "us-east-1"),
|
endpoint.NewEndpointWithTTL("latency-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.2.3.4").WithSetIdentifier("test-set").WithProviderSpecific(providerSpecificRegion, "us-east-1"),
|
||||||
endpoint.NewEndpointWithTTL("failover-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.2.3.4").WithSetIdentifier("test-set").WithProviderSpecific(providerSpecificFailover, "PRIMARY"),
|
endpoint.NewEndpointWithTTL("failover-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.2.3.4").WithSetIdentifier("test-set").WithProviderSpecific(providerSpecificFailover, "PRIMARY"),
|
||||||
endpoint.NewEndpointWithTTL("multi-value-answer-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.2.3.4").WithSetIdentifier("test-set").WithProviderSpecific(providerSpecificMultiValueAnswer, ""),
|
endpoint.NewEndpointWithTTL("multi-value-answer-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.2.3.4").WithSetIdentifier("test-set").WithProviderSpecific(providerSpecificMultiValueAnswer, ""),
|
||||||
endpoint.NewEndpointWithTTL("geolocation-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.2.3.4").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificGeolocationContinentCode, "EU"),
|
endpoint.NewEndpointWithTTL("geolocation-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.2.3.4").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificGeolocationContinentCode, "EU"),
|
||||||
endpoint.NewEndpointWithTTL("geolocation-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "4.3.2.1").WithSetIdentifier("test-set-2").WithProviderSpecific(providerSpecificGeolocationCountryCode, "DE"),
|
endpoint.NewEndpointWithTTL("geolocation-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "4.3.2.1").WithSetIdentifier("test-set-2").WithProviderSpecific(providerSpecificGeolocationCountryCode, "DE"),
|
||||||
endpoint.NewEndpointWithTTL("geolocation-subdivision-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.2.3.4").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificGeolocationSubdivisionCode, "NY"),
|
endpoint.NewEndpointWithTTL("geolocation-subdivision-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.2.3.4").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificGeolocationSubdivisionCode, "NY"),
|
||||||
endpoint.NewEndpointWithTTL("healthcheck-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, endpoint.TTL(recordTTL), "foo.example.com").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificWeight, "10").WithProviderSpecific(providerSpecificHealthCheckID, "foo-bar-healthcheck-id").WithProviderSpecific(providerSpecificAlias, "false"),
|
endpoint.NewEndpointWithTTL("healthcheck-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeCNAME, endpoint.TTL(defaultTTL), "foo.example.com").WithSetIdentifier("test-set-1").WithProviderSpecific(providerSpecificWeight, "10").WithProviderSpecific(providerSpecificHealthCheckID, "foo-bar-healthcheck-id").WithProviderSpecific(providerSpecificAlias, "false"),
|
||||||
endpoint.NewEndpointWithTTL("healthcheck-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "4.3.2.1").WithSetIdentifier("test-set-2").WithProviderSpecific(providerSpecificWeight, "20").WithProviderSpecific(providerSpecificHealthCheckID, "abc-def-healthcheck-id"),
|
endpoint.NewEndpointWithTTL("healthcheck-test.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "4.3.2.1").WithSetIdentifier("test-set-2").WithProviderSpecific(providerSpecificWeight, "20").WithProviderSpecific(providerSpecificHealthCheckID, "abc-def-healthcheck-id"),
|
||||||
endpoint.NewEndpointWithTTL("mail.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeMX, endpoint.TTL(recordTTL), "10 mailhost1.example.com", "20 mailhost2.example.com"),
|
endpoint.NewEndpointWithTTL("mail.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeMX, endpoint.TTL(defaultTTL), "10 mailhost1.example.com", "20 mailhost2.example.com"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -647,7 +647,7 @@ func TestAWSRecordsSoftError(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("list-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("list-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -710,55 +710,55 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("update-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("update-test-aaaa.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test-aaaa.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeAaaa,
|
Type: route53types.RRTypeAaaa,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1111")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1111")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("delete-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("delete-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("delete-test-aaaa.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("delete-test-aaaa.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeAaaa,
|
Type: route53types.RRTypeAaaa,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1111")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1111")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("update-test.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.4.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.4.4")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("update-test-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeAaaa,
|
Type: route53types.RRTypeAaaa,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1001")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1001")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("delete-test.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("delete-test.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.4.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.4.4")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("delete-test-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("delete-test-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeAaaa,
|
Type: route53types.RRTypeAaaa,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1001")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1001")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("update-test-a-to-cname.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test-a-to-cname.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.1.1.1")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.1.1.1")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -782,7 +782,7 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("update-test-cname.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test-cname.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeCname,
|
Type: route53types.RRTypeCname,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("bar.elb.amazonaws.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("bar.elb.amazonaws.com")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -806,7 +806,7 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("delete-test-cname.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("delete-test-cname.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeCname,
|
Type: route53types.RRTypeCname,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("qux.elb.amazonaws.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("qux.elb.amazonaws.com")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -830,25 +830,25 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("update-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}, {Value: aws.String("8.8.4.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}, {Value: aws.String("8.8.4.4")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("delete-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("delete-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}, {Value: aws.String("4.3.2.1")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}, {Value: aws.String("4.3.2.1")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("delete-test-multiple-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("delete-test-multiple-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeAaaa,
|
Type: route53types.RRTypeAaaa,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1111")}, {Value: aws.String("2606:4700:4700::1001")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1111")}, {Value: aws.String("2606:4700:4700::1001")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("weighted-to-simple.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("weighted-to-simple.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
SetIdentifier: aws.String("weighted-to-simple"),
|
SetIdentifier: aws.String("weighted-to-simple"),
|
||||||
Weight: aws.Int64(10),
|
Weight: aws.Int64(10),
|
||||||
@ -856,13 +856,13 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("simple-to-weighted.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("simple-to-weighted.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("policy-change.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("policy-change.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
SetIdentifier: aws.String("policy-change"),
|
SetIdentifier: aws.String("policy-change"),
|
||||||
Weight: aws.Int64(10),
|
Weight: aws.Int64(10),
|
||||||
@ -870,7 +870,7 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("set-identifier-change.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("set-identifier-change.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
SetIdentifier: aws.String("before"),
|
SetIdentifier: aws.String("before"),
|
||||||
Weight: aws.Int64(10),
|
Weight: aws.Int64(10),
|
||||||
@ -878,7 +878,7 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("set-identifier-no-change.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("set-identifier-no-change.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
SetIdentifier: aws.String("no-change"),
|
SetIdentifier: aws.String("no-change"),
|
||||||
Weight: aws.Int64(10),
|
Weight: aws.Int64(10),
|
||||||
@ -886,19 +886,19 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("update-test-mx.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test-mx.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeMx,
|
Type: route53types.RRTypeMx,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("10 mailhost2.bar.elb.amazonaws.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("10 mailhost2.bar.elb.amazonaws.com")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("delete-test-mx.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("delete-test-mx.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeMx,
|
Type: route53types.RRTypeMx,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("30 mailhost1.foo.elb.amazonaws.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("30 mailhost1.foo.elb.amazonaws.com")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String(specialCharactersEscape("escape-%!s(<nil>)-codes.zone-2.ext-dns-test-2.teapot.zalan.do.")),
|
Name: aws.String(specialCharactersEscape("escape-%!s(<nil>)-codes.zone-2.ext-dns-test-2.teapot.zalan.do.")),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
SetIdentifier: aws.String("no-change"),
|
SetIdentifier: aws.String("no-change"),
|
||||||
Weight: aws.Int64(10),
|
Weight: aws.Int64(10),
|
||||||
@ -993,25 +993,25 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("create-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("create-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("create-test-aaaa.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("create-test-aaaa.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeAaaa,
|
Type: route53types.RRTypeAaaa,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1111")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1111")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("update-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("update-test-aaaa.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test-aaaa.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeAaaa,
|
Type: route53types.RRTypeAaaa,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1001")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1001")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1035,25 +1035,25 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("update-test-alias-to-cname.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test-alias-to-cname.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeCname,
|
Type: route53types.RRTypeCname,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("my-internal-host.example.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("my-internal-host.example.com")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("create-test-cname.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("create-test-cname.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeCname,
|
Type: route53types.RRTypeCname,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("foo.elb.amazonaws.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("foo.elb.amazonaws.com")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("update-test-cname.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test-cname.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeCname,
|
Type: route53types.RRTypeCname,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("baz.elb.amazonaws.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("baz.elb.amazonaws.com")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("create-test-cname-alias.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("create-test-cname-alias.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeCname,
|
Type: route53types.RRTypeCname,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("foo.elb.amazonaws.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("foo.elb.amazonaws.com")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -1077,13 +1077,13 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("weighted-to-simple.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("weighted-to-simple.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("simple-to-weighted.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("simple-to-weighted.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
SetIdentifier: aws.String("simple-to-weighted"),
|
SetIdentifier: aws.String("simple-to-weighted"),
|
||||||
Weight: aws.Int64(10),
|
Weight: aws.Int64(10),
|
||||||
@ -1091,7 +1091,7 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("policy-change.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("policy-change.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
SetIdentifier: aws.String("policy-change"),
|
SetIdentifier: aws.String("policy-change"),
|
||||||
Region: route53types.ResourceRecordSetRegionUsEast1,
|
Region: route53types.ResourceRecordSetRegionUsEast1,
|
||||||
@ -1099,7 +1099,7 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("set-identifier-change.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("set-identifier-change.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
SetIdentifier: aws.String("after"),
|
SetIdentifier: aws.String("after"),
|
||||||
Weight: aws.Int64(10),
|
Weight: aws.Int64(10),
|
||||||
@ -1107,7 +1107,7 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("set-identifier-no-change.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("set-identifier-no-change.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
SetIdentifier: aws.String("no-change"),
|
SetIdentifier: aws.String("no-change"),
|
||||||
Weight: aws.Int64(20),
|
Weight: aws.Int64(20),
|
||||||
@ -1115,7 +1115,7 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("create-test-mx.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("create-test-mx.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeMx,
|
Type: route53types.RRTypeMx,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("10 mailhost1.foo.elb.amazonaws.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("10 mailhost1.foo.elb.amazonaws.com")}},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -1123,7 +1123,7 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("escape-\\045\\041s\\050\\074nil\\076\\051-codes.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("escape-\\045\\041s\\050\\074nil\\076\\051-codes.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}},
|
||||||
SetIdentifier: aws.String("no-change"),
|
SetIdentifier: aws.String("no-change"),
|
||||||
Weight: aws.Int64(10),
|
Weight: aws.Int64(10),
|
||||||
@ -1131,55 +1131,55 @@ func TestAWSApplyChanges(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("create-test.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("create-test.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.4.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.4.4")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("create-test-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("create-test-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeAaaa,
|
Type: route53types.RRTypeAaaa,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1001")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1001")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("update-test.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("4.3.2.1")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("4.3.2.1")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("update-test-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeAaaa,
|
Type: route53types.RRTypeAaaa,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1111")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1111")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("create-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("create-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}, {Value: aws.String("8.8.4.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}, {Value: aws.String("8.8.4.4")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("create-test-multiple-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("create-test-multiple-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeAaaa,
|
Type: route53types.RRTypeAaaa,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1111")}, {Value: aws.String("2606:4700:4700::1001")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1111")}, {Value: aws.String("2606:4700:4700::1001")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("update-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}, {Value: aws.String("4.3.2.1")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}, {Value: aws.String("4.3.2.1")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("update-test-multiple-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test-multiple-aaaa.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeAaaa,
|
Type: route53types.RRTypeAaaa,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1001")}, {Value: aws.String("2606:4700:4700::1111")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("2606:4700:4700::1001")}, {Value: aws.String("2606:4700:4700::1111")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("update-test-mx.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test-mx.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeMx,
|
Type: route53types.RRTypeMx,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("20 mailhost3.foo.elb.amazonaws.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("20 mailhost3.foo.elb.amazonaws.com")}},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -1191,79 +1191,79 @@ func TestAWSApplyChangesDryRun(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: aws.String("update-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("delete-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("delete-test.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("update-test.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.4.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.4.4")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("delete-test.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("delete-test.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.4.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.4.4")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("update-test-a-to-cname.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test-a-to-cname.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.1.1.1")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.1.1.1")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("update-test-cname.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test-cname.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeCname,
|
Type: route53types.RRTypeCname,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("bar.elb.amazonaws.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("bar.elb.amazonaws.com")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("delete-test-cname.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("delete-test-cname.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeCname,
|
Type: route53types.RRTypeCname,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("qux.elb.amazonaws.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("qux.elb.amazonaws.com")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("update-test-cname-alias.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test-cname-alias.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeCname,
|
Type: route53types.RRTypeCname,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("bar.elb.amazonaws.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("bar.elb.amazonaws.com")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("delete-test-cname-alias.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("delete-test-cname-alias.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeCname,
|
Type: route53types.RRTypeCname,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("qux.elb.amazonaws.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("qux.elb.amazonaws.com")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("update-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}, {Value: aws.String("8.8.4.4")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("8.8.8.8")}, {Value: aws.String("8.8.4.4")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("delete-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("delete-test-multiple.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeA,
|
Type: route53types.RRTypeA,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}, {Value: aws.String("4.3.2.1")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("1.2.3.4")}, {Value: aws.String("4.3.2.1")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("update-test-mx.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("update-test-mx.zone-1.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeMx,
|
Type: route53types.RRTypeMx,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("20 mail.foo.elb.amazonaws.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("20 mail.foo.elb.amazonaws.com")}},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: aws.String("delete-test-mx.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
Name: aws.String("delete-test-mx.zone-2.ext-dns-test-2.teapot.zalan.do."),
|
||||||
Type: route53types.RRTypeMx,
|
Type: route53types.RRTypeMx,
|
||||||
TTL: aws.Int64(recordTTL),
|
TTL: aws.Int64(defaultTTL),
|
||||||
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("10 mail.bar.elb.amazonaws.com")}},
|
ResourceRecords: []route53types.ResourceRecord{{Value: aws.String("10 mail.bar.elb.amazonaws.com")}},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -1464,7 +1464,7 @@ func TestAWSsubmitChanges(t *testing.T) {
|
|||||||
for j := 1; j < (hosts + 1); j++ {
|
for j := 1; j < (hosts + 1); j++ {
|
||||||
hostname := fmt.Sprintf("subnet%dhost%d.zone-1.ext-dns-test-2.teapot.zalan.do", i, j)
|
hostname := fmt.Sprintf("subnet%dhost%d.zone-1.ext-dns-test-2.teapot.zalan.do", i, j)
|
||||||
ip := fmt.Sprintf("1.1.%d.%d", i, j)
|
ip := fmt.Sprintf("1.1.%d.%d", i, j)
|
||||||
ep := endpoint.NewEndpointWithTTL(hostname, endpoint.RecordTypeA, endpoint.TTL(recordTTL), ip)
|
ep := endpoint.NewEndpointWithTTL(hostname, endpoint.RecordTypeA, endpoint.TTL(defaultTTL), ip)
|
||||||
endpoints = append(endpoints, ep)
|
endpoints = append(endpoints, ep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1491,7 +1491,7 @@ func TestAWSsubmitChangesError(t *testing.T) {
|
|||||||
zones, err := provider.zones(ctx)
|
zones, err := provider.zones(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ep := endpoint.NewEndpointWithTTL("fail.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.0.0.1")
|
ep := endpoint.NewEndpointWithTTL("fail.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.0.0.1")
|
||||||
cs := provider.newChanges(route53types.ChangeActionCreate, []*endpoint.Endpoint{ep})
|
cs := provider.newChanges(route53types.ChangeActionCreate, []*endpoint.Endpoint{ep})
|
||||||
|
|
||||||
require.Error(t, provider.submitChanges(ctx, cs, zones))
|
require.Error(t, provider.submitChanges(ctx, cs, zones))
|
||||||
@ -1504,11 +1504,11 @@ func TestAWSsubmitChangesRetryOnError(t *testing.T) {
|
|||||||
zones, err := provider.zones(ctx)
|
zones, err := provider.zones(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ep1 := endpoint.NewEndpointWithTTL("success.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.0.0.1")
|
ep1 := endpoint.NewEndpointWithTTL("success.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.0.0.1")
|
||||||
ep2 := endpoint.NewEndpointWithTTL("fail.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.0.0.2")
|
ep2 := endpoint.NewEndpointWithTTL("fail.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.0.0.2")
|
||||||
ep3 := endpoint.NewEndpointWithTTL("success2.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.0.0.3")
|
ep3 := endpoint.NewEndpointWithTTL("success2.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.0.0.3")
|
||||||
|
|
||||||
ep2txt := endpoint.NewEndpointWithTTL("fail__edns_housekeeping.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeTXT, endpoint.TTL(recordTTL), "something") // "__edns_housekeeping" is the TXT suffix
|
ep2txt := endpoint.NewEndpointWithTTL("fail__edns_housekeeping.zone-1.ext-dns-test-2.teapot.zalan.do", endpoint.RecordTypeTXT, endpoint.TTL(defaultTTL), "something") // "__edns_housekeeping" is the TXT suffix
|
||||||
ep2txt.Labels = map[string]string{
|
ep2txt.Labels = map[string]string{
|
||||||
endpoint.OwnedRecordLabelKey: "fail.zone-1.ext-dns-test-2.teapot.zalan.do",
|
endpoint.OwnedRecordLabelKey: "fail.zone-1.ext-dns-test-2.teapot.zalan.do",
|
||||||
}
|
}
|
||||||
@ -2315,26 +2315,26 @@ func containsRecordWithDNSName(records []*endpoint.Endpoint, dnsName string) boo
|
|||||||
func TestRequiresDeleteCreate(t *testing.T) {
|
func TestRequiresDeleteCreate(t *testing.T) {
|
||||||
provider, _ := newAWSProvider(t, endpoint.NewDomainFilter([]string{"foo.bar."}), provider.NewZoneIDFilter([]string{}), provider.NewZoneTypeFilter(""), defaultEvaluateTargetHealth, false, nil)
|
provider, _ := newAWSProvider(t, endpoint.NewDomainFilter([]string{"foo.bar."}), provider.NewZoneIDFilter([]string{}), provider.NewZoneTypeFilter(""), defaultEvaluateTargetHealth, false, nil)
|
||||||
|
|
||||||
oldRecordType := endpoint.NewEndpointWithTTL("recordType", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "8.8.8.8")
|
oldRecordType := endpoint.NewEndpointWithTTL("recordType", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "8.8.8.8")
|
||||||
newRecordType := endpoint.NewEndpointWithTTL("recordType", endpoint.RecordTypeCNAME, endpoint.TTL(recordTTL), "bar").WithProviderSpecific(providerSpecificAlias, "false")
|
newRecordType := endpoint.NewEndpointWithTTL("recordType", endpoint.RecordTypeCNAME, endpoint.TTL(defaultTTL), "bar").WithProviderSpecific(providerSpecificAlias, "false")
|
||||||
|
|
||||||
assert.False(t, provider.requiresDeleteCreate(oldRecordType, oldRecordType), "actual and expected endpoints don't match. %+v:%+v", oldRecordType, oldRecordType)
|
assert.False(t, provider.requiresDeleteCreate(oldRecordType, oldRecordType), "actual and expected endpoints don't match. %+v:%+v", oldRecordType, oldRecordType)
|
||||||
assert.True(t, provider.requiresDeleteCreate(oldRecordType, newRecordType), "actual and expected endpoints don't match. %+v:%+v", oldRecordType, newRecordType)
|
assert.True(t, provider.requiresDeleteCreate(oldRecordType, newRecordType), "actual and expected endpoints don't match. %+v:%+v", oldRecordType, newRecordType)
|
||||||
|
|
||||||
oldAtoAlias := endpoint.NewEndpointWithTTL("AtoAlias", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "1.1.1.1")
|
oldAtoAlias := endpoint.NewEndpointWithTTL("AtoAlias", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "1.1.1.1")
|
||||||
newAtoAlias := endpoint.NewEndpointWithTTL("AtoAlias", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "bar.us-east-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificAlias, "true")
|
newAtoAlias := endpoint.NewEndpointWithTTL("AtoAlias", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "bar.us-east-1.elb.amazonaws.com").WithProviderSpecific(providerSpecificAlias, "true")
|
||||||
|
|
||||||
assert.False(t, provider.requiresDeleteCreate(oldAtoAlias, oldAtoAlias), "actual and expected endpoints don't match. %+v:%+v", oldAtoAlias, oldAtoAlias.DNSName)
|
assert.False(t, provider.requiresDeleteCreate(oldAtoAlias, oldAtoAlias), "actual and expected endpoints don't match. %+v:%+v", oldAtoAlias, oldAtoAlias.DNSName)
|
||||||
assert.True(t, provider.requiresDeleteCreate(oldAtoAlias, newAtoAlias), "actual and expected endpoints don't match. %+v:%+v", oldAtoAlias, newAtoAlias)
|
assert.True(t, provider.requiresDeleteCreate(oldAtoAlias, newAtoAlias), "actual and expected endpoints don't match. %+v:%+v", oldAtoAlias, newAtoAlias)
|
||||||
|
|
||||||
oldPolicy := endpoint.NewEndpointWithTTL("policy", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "8.8.8.8").WithSetIdentifier("nochange").WithProviderSpecific(providerSpecificRegion, "us-east-1")
|
oldPolicy := endpoint.NewEndpointWithTTL("policy", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "8.8.8.8").WithSetIdentifier("nochange").WithProviderSpecific(providerSpecificRegion, "us-east-1")
|
||||||
newPolicy := endpoint.NewEndpointWithTTL("policy", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "8.8.8.8").WithSetIdentifier("nochange").WithProviderSpecific(providerSpecificWeight, "10")
|
newPolicy := endpoint.NewEndpointWithTTL("policy", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "8.8.8.8").WithSetIdentifier("nochange").WithProviderSpecific(providerSpecificWeight, "10")
|
||||||
|
|
||||||
assert.False(t, provider.requiresDeleteCreate(oldPolicy, oldPolicy), "actual and expected endpoints don't match. %+v:%+v", oldPolicy, oldPolicy)
|
assert.False(t, provider.requiresDeleteCreate(oldPolicy, oldPolicy), "actual and expected endpoints don't match. %+v:%+v", oldPolicy, oldPolicy)
|
||||||
assert.True(t, provider.requiresDeleteCreate(oldPolicy, newPolicy), "actual and expected endpoints don't match. %+v:%+v", oldPolicy, newPolicy)
|
assert.True(t, provider.requiresDeleteCreate(oldPolicy, newPolicy), "actual and expected endpoints don't match. %+v:%+v", oldPolicy, newPolicy)
|
||||||
|
|
||||||
oldSetIdentifier := endpoint.NewEndpointWithTTL("setIdentifier", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "8.8.8.8").WithSetIdentifier("old")
|
oldSetIdentifier := endpoint.NewEndpointWithTTL("setIdentifier", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "8.8.8.8").WithSetIdentifier("old")
|
||||||
newSetIdentifier := endpoint.NewEndpointWithTTL("setIdentifier", endpoint.RecordTypeA, endpoint.TTL(recordTTL), "8.8.8.8").WithSetIdentifier("new")
|
newSetIdentifier := endpoint.NewEndpointWithTTL("setIdentifier", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "8.8.8.8").WithSetIdentifier("new")
|
||||||
|
|
||||||
assert.False(t, provider.requiresDeleteCreate(oldSetIdentifier, oldSetIdentifier), "actual and expected endpoints don't match. %+v:%+v", oldSetIdentifier, oldSetIdentifier)
|
assert.False(t, provider.requiresDeleteCreate(oldSetIdentifier, oldSetIdentifier), "actual and expected endpoints don't match. %+v:%+v", oldSetIdentifier, oldSetIdentifier)
|
||||||
assert.True(t, provider.requiresDeleteCreate(oldSetIdentifier, newSetIdentifier), "actual and expected endpoints don't match. %+v:%+v", oldSetIdentifier, newSetIdentifier)
|
assert.True(t, provider.requiresDeleteCreate(oldSetIdentifier, newSetIdentifier), "actual and expected endpoints don't match. %+v:%+v", oldSetIdentifier, newSetIdentifier)
|
||||||
|
@ -24,7 +24,7 @@ import (
|
|||||||
|
|
||||||
"github.com/aws/aws-sdk-go-v2/service/route53"
|
"github.com/aws/aws-sdk-go-v2/service/route53"
|
||||||
route53types "github.com/aws/aws-sdk-go-v2/service/route53/types"
|
route53types "github.com/aws/aws-sdk-go-v2/service/route53/types"
|
||||||
yaml "github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"sigs.k8s.io/external-dns/endpoint"
|
"sigs.k8s.io/external-dns/endpoint"
|
||||||
"sigs.k8s.io/external-dns/provider"
|
"sigs.k8s.io/external-dns/provider"
|
||||||
|
@ -35,7 +35,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
sdDefaultRecordTTL = 300
|
defaultTTL = 300
|
||||||
|
|
||||||
sdNamespaceTypePublic = "public"
|
sdNamespaceTypePublic = "public"
|
||||||
sdNamespaceTypePrivate = "private"
|
sdNamespaceTypePrivate = "private"
|
||||||
@ -407,7 +407,7 @@ func (p *AWSSDProvider) CreateService(ctx context.Context, namespaceID *string,
|
|||||||
srvType := p.serviceTypeFromEndpoint(ep)
|
srvType := p.serviceTypeFromEndpoint(ep)
|
||||||
routingPolicy := p.routingPolicyFromEndpoint(ep)
|
routingPolicy := p.routingPolicyFromEndpoint(ep)
|
||||||
|
|
||||||
ttl := int64(sdDefaultRecordTTL)
|
ttl := int64(defaultTTL)
|
||||||
if ep.RecordTTL.IsConfigured() {
|
if ep.RecordTTL.IsConfigured() {
|
||||||
ttl = int64(ep.RecordTTL)
|
ttl = int64(ep.RecordTTL)
|
||||||
}
|
}
|
||||||
@ -443,7 +443,7 @@ func (p *AWSSDProvider) UpdateService(ctx context.Context, service *sdtypes.Serv
|
|||||||
|
|
||||||
srvType := p.serviceTypeFromEndpoint(ep)
|
srvType := p.serviceTypeFromEndpoint(ep)
|
||||||
|
|
||||||
ttl := int64(sdDefaultRecordTTL)
|
ttl := int64(defaultTTL)
|
||||||
if ep.RecordTTL.IsConfigured() {
|
if ep.RecordTTL.IsConfigured() {
|
||||||
ttl = int64(ep.RecordTTL)
|
ttl = int64(ep.RecordTTL)
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
azureRecordTTL = 300
|
defaultTTL = 300
|
||||||
)
|
)
|
||||||
|
|
||||||
// ZonesClient is an interface of dns.ZoneClient that can be stubbed for testing.
|
// ZonesClient is an interface of dns.ZoneClient that can be stubbed for testing.
|
||||||
@ -337,7 +337,7 @@ func (p *AzureProvider) recordSetNameForZone(zone string, endpoint *endpoint.End
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *AzureProvider) newRecordSet(endpoint *endpoint.Endpoint) (dns.RecordSet, error) {
|
func (p *AzureProvider) newRecordSet(endpoint *endpoint.Endpoint) (dns.RecordSet, error) {
|
||||||
var ttl int64 = azureRecordTTL
|
var ttl int64 = defaultTTL
|
||||||
if endpoint.RecordTTL.IsConfigured() {
|
if endpoint.RecordTTL.IsConfigured() {
|
||||||
ttl = int64(endpoint.RecordTTL)
|
ttl = int64(endpoint.RecordTTL)
|
||||||
}
|
}
|
||||||
|
@ -344,7 +344,7 @@ func (p *AzurePrivateDNSProvider) recordSetNameForZone(zone string, endpoint *en
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *AzurePrivateDNSProvider) newRecordSet(endpoint *endpoint.Endpoint) (privatedns.RecordSet, error) {
|
func (p *AzurePrivateDNSProvider) newRecordSet(endpoint *endpoint.Endpoint) (privatedns.RecordSet, error) {
|
||||||
var ttl int64 = azureRecordTTL
|
var ttl int64 = defaultTTL
|
||||||
if endpoint.RecordTTL.IsConfigured() {
|
if endpoint.RecordTTL.IsConfigured() {
|
||||||
ttl = int64(endpoint.RecordTTL)
|
ttl = int64(endpoint.RecordTTL)
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ func TestGetCloudConfiguration(t *testing.T) {
|
|||||||
|
|
||||||
func TestOverrideConfiguration(t *testing.T) {
|
func TestOverrideConfiguration(t *testing.T) {
|
||||||
_, filename, _, _ := runtime.Caller(0)
|
_, filename, _, _ := runtime.Caller(0)
|
||||||
configFile := path.Join(path.Dir(filename), "config_test.json")
|
configFile := path.Join(path.Dir(filename), "fixtures/config_test.json")
|
||||||
cfg, err := getConfig(configFile, "subscription-override", "rg-override", "", "aad-endpoint-override")
|
cfg, err := getConfig(configFile, "subscription-override", "rg-override", "", "aad-endpoint-override")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("got unexpected err %v", err)
|
t.Errorf("got unexpected err %v", err)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"tenantId": "tenant",
|
"tenantId": "tenant",
|
||||||
"subscriptionId": "subscription",
|
"subscriptionId": "subscription",
|
||||||
"resourceGroup": "rg",
|
"resourceGroup": "rg",
|
||||||
"aadClientId": "clientId",
|
"aadClientId": "clientId",
|
||||||
"aadClientSecret": "clientSecret"
|
"aadClientSecret": "clientSecret"
|
||||||
}
|
}
|
@ -44,20 +44,20 @@ const (
|
|||||||
cloudFlareDelete = "DELETE"
|
cloudFlareDelete = "DELETE"
|
||||||
// cloudFlareUpdate is a ChangeAction enum value
|
// cloudFlareUpdate is a ChangeAction enum value
|
||||||
cloudFlareUpdate = "UPDATE"
|
cloudFlareUpdate = "UPDATE"
|
||||||
// defaultCloudFlareRecordTTL 1 = automatic
|
// defaultTTL 1 = automatic
|
||||||
defaultCloudFlareRecordTTL = 1
|
defaultTTL = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
// We have to use pointers to bools now, as the upstream cloudflare-go library requires them
|
// We have to use pointers to bools now, as the upstream cloudflare-go library requires them
|
||||||
// see: https://github.com/cloudflare/cloudflare-go/pull/595
|
// see: https://github.com/cloudflare/cloudflare-go/pull/595
|
||||||
|
|
||||||
// proxyEnabled is a pointer to a bool true showing the record should be proxied through cloudflare
|
var (
|
||||||
var proxyEnabled *bool = boolPtr(true)
|
// proxyEnabled is a pointer to a bool true showing the record should be proxied through cloudflare
|
||||||
|
proxyEnabled *bool = boolPtr(true)
|
||||||
|
// proxyDisabled is a pointer to a bool false showing the record should not be proxied through cloudflare
|
||||||
|
proxyDisabled *bool = boolPtr(false)
|
||||||
|
)
|
||||||
|
|
||||||
// proxyDisabled is a pointer to a bool false showing the record should not be proxied through cloudflare
|
|
||||||
var proxyDisabled *bool = boolPtr(false)
|
|
||||||
|
|
||||||
// for faster getRecordID() lookup
|
|
||||||
type DNSRecordIndex struct {
|
type DNSRecordIndex struct {
|
||||||
Name string
|
Name string
|
||||||
Type string
|
Type string
|
||||||
@ -279,8 +279,8 @@ func NewCloudFlareProvider(domainFilter endpoint.DomainFilter, zoneIDFilter prov
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to initialize cloudflare provider: %w", err)
|
return nil, fmt.Errorf("failed to initialize cloudflare provider: %w", err)
|
||||||
}
|
}
|
||||||
provider := &CloudFlareProvider{
|
|
||||||
// Client: config,
|
return &CloudFlareProvider{
|
||||||
Client: zoneService{config},
|
Client: zoneService{config},
|
||||||
domainFilter: domainFilter,
|
domainFilter: domainFilter,
|
||||||
zoneIDFilter: zoneIDFilter,
|
zoneIDFilter: zoneIDFilter,
|
||||||
@ -289,13 +289,12 @@ func NewCloudFlareProvider(domainFilter endpoint.DomainFilter, zoneIDFilter prov
|
|||||||
DryRun: dryRun,
|
DryRun: dryRun,
|
||||||
DNSRecordsPerPage: dnsRecordsPerPage,
|
DNSRecordsPerPage: dnsRecordsPerPage,
|
||||||
RegionKey: regionKey,
|
RegionKey: regionKey,
|
||||||
}
|
}, nil
|
||||||
return provider, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zones returns the list of hosted zones.
|
// Zones returns the list of hosted zones.
|
||||||
func (p *CloudFlareProvider) Zones(ctx context.Context) ([]cloudflare.Zone, error) {
|
func (p *CloudFlareProvider) Zones(ctx context.Context) ([]cloudflare.Zone, error) {
|
||||||
result := []cloudflare.Zone{}
|
var result []cloudflare.Zone
|
||||||
|
|
||||||
// if there is a zoneIDfilter configured
|
// if there is a zoneIDfilter configured
|
||||||
// && if the filter isn't just a blank string (used in tests)
|
// && if the filter isn't just a blank string (used in tests)
|
||||||
@ -349,7 +348,7 @@ func (p *CloudFlareProvider) Records(ctx context.Context) ([]*endpoint.Endpoint,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints := []*endpoint.Endpoint{}
|
var endpoints []*endpoint.Endpoint
|
||||||
for _, zone := range zones {
|
for _, zone := range zones {
|
||||||
records, err := p.listDNSRecordsWithAutoPagination(ctx, zone.ID)
|
records, err := p.listDNSRecordsWithAutoPagination(ctx, zone.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -373,7 +372,7 @@ func (p *CloudFlareProvider) Records(ctx context.Context) ([]*endpoint.Endpoint,
|
|||||||
|
|
||||||
// ApplyChanges applies a given set of changes in a given zone.
|
// ApplyChanges applies a given set of changes in a given zone.
|
||||||
func (p *CloudFlareProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
|
func (p *CloudFlareProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
|
||||||
cloudflareChanges := []*cloudFlareChange{}
|
var cloudflareChanges []*cloudFlareChange
|
||||||
|
|
||||||
// if custom hostnames are enabled, deleting first allows to avoid conflicts with the new ones
|
// if custom hostnames are enabled, deleting first allows to avoid conflicts with the new ones
|
||||||
if p.CustomHostnamesConfig.Enabled {
|
if p.CustomHostnamesConfig.Enabled {
|
||||||
@ -425,7 +424,7 @@ func (p *CloudFlareProvider) submitCustomHostnameChanges(ctx context.Context, zo
|
|||||||
failedChange := false
|
failedChange := false
|
||||||
// return early if disabled
|
// return early if disabled
|
||||||
if !p.CustomHostnamesConfig.Enabled {
|
if !p.CustomHostnamesConfig.Enabled {
|
||||||
return !failedChange
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
switch change.Action {
|
switch change.Action {
|
||||||
@ -730,7 +729,7 @@ func (p *CloudFlareProvider) submitChanges(ctx context.Context, changes []*cloud
|
|||||||
|
|
||||||
// AdjustEndpoints modifies the endpoints as needed by the specific provider
|
// AdjustEndpoints modifies the endpoints as needed by the specific provider
|
||||||
func (p *CloudFlareProvider) AdjustEndpoints(endpoints []*endpoint.Endpoint) ([]*endpoint.Endpoint, error) {
|
func (p *CloudFlareProvider) AdjustEndpoints(endpoints []*endpoint.Endpoint) ([]*endpoint.Endpoint, error) {
|
||||||
adjustedEndpoints := []*endpoint.Endpoint{}
|
var adjustedEndpoints []*endpoint.Endpoint
|
||||||
for _, e := range endpoints {
|
for _, e := range endpoints {
|
||||||
proxied := shouldBeProxied(e, p.proxiedByDefault)
|
proxied := shouldBeProxied(e, p.proxiedByDefault)
|
||||||
if proxied {
|
if proxied {
|
||||||
@ -802,7 +801,7 @@ func (p *CloudFlareProvider) newCustomHostname(customHostname string, origin str
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *CloudFlareProvider) newCloudFlareChange(action string, ep *endpoint.Endpoint, target string, current *endpoint.Endpoint) *cloudFlareChange {
|
func (p *CloudFlareProvider) newCloudFlareChange(action string, ep *endpoint.Endpoint, target string, current *endpoint.Endpoint) *cloudFlareChange {
|
||||||
ttl := defaultCloudFlareRecordTTL
|
ttl := defaultTTL
|
||||||
proxied := shouldBeProxied(ep, p.proxiedByDefault)
|
proxied := shouldBeProxied(ep, p.proxiedByDefault)
|
||||||
|
|
||||||
if ep.RecordTTL.IsConfigured() {
|
if ep.RecordTTL.IsConfigured() {
|
||||||
@ -969,7 +968,7 @@ func getEndpointCustomHostnames(ep *endpoint.Endpoint) []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func groupByNameAndTypeWithCustomHostnames(records DNSRecordsMap, chs CustomHostnamesMap) []*endpoint.Endpoint {
|
func groupByNameAndTypeWithCustomHostnames(records DNSRecordsMap, chs CustomHostnamesMap) []*endpoint.Endpoint {
|
||||||
endpoints := []*endpoint.Endpoint{}
|
var endpoints []*endpoint.Endpoint
|
||||||
|
|
||||||
// group supported records by name and type
|
// group supported records by name and type
|
||||||
groups := map[string][]cloudflare.DNSRecord{}
|
groups := map[string][]cloudflare.DNSRecord{}
|
||||||
@ -994,7 +993,7 @@ func groupByNameAndTypeWithCustomHostnames(records DNSRecordsMap, chs CustomHost
|
|||||||
customHostnames[c.CustomOriginServer] = append(customHostnames[c.CustomOriginServer], c.Hostname)
|
customHostnames[c.CustomOriginServer] = append(customHostnames[c.CustomOriginServer], c.Hostname)
|
||||||
}
|
}
|
||||||
|
|
||||||
// create single endpoint with all the targets for each name/type
|
// create a single endpoint with all the targets for each name/type
|
||||||
for _, records := range groups {
|
for _, records := range groups {
|
||||||
if len(records) == 0 {
|
if len(records) == 0 {
|
||||||
return endpoints
|
return endpoints
|
||||||
|
@ -51,6 +51,7 @@ type mockCloudFlareClient struct {
|
|||||||
Records map[string]map[string]cloudflare.DNSRecord
|
Records map[string]map[string]cloudflare.DNSRecord
|
||||||
Actions []MockAction
|
Actions []MockAction
|
||||||
listZonesError error
|
listZonesError error
|
||||||
|
zoneDetailsError error
|
||||||
listZonesContextError error
|
listZonesContextError error
|
||||||
dnsRecordsError error
|
dnsRecordsError error
|
||||||
customHostnames map[string][]cloudflare.CustomHostname
|
customHostnames map[string][]cloudflare.CustomHostname
|
||||||
@ -410,6 +411,10 @@ func (m *mockCloudFlareClient) ListZonesContext(ctx context.Context, opts ...clo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *mockCloudFlareClient) ZoneDetails(ctx context.Context, zoneID string) (cloudflare.Zone, error) {
|
func (m *mockCloudFlareClient) ZoneDetails(ctx context.Context, zoneID string) (cloudflare.Zone, error) {
|
||||||
|
if m.zoneDetailsError != nil {
|
||||||
|
return cloudflare.Zone{}, m.zoneDetailsError
|
||||||
|
}
|
||||||
|
|
||||||
for id, zoneName := range m.Zones {
|
for id, zoneName := range m.Zones {
|
||||||
if zoneID == id {
|
if zoneID == id {
|
||||||
return cloudflare.Zone{
|
return cloudflare.Zone{
|
||||||
@ -891,6 +896,24 @@ func TestCloudflareZones(t *testing.T) {
|
|||||||
assert.Equal(t, "bar.com", zones[0].Name)
|
assert.Equal(t, "bar.com", zones[0].Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test failures on zone lookup
|
||||||
|
func TestCloudflareZonesFailed(t *testing.T) {
|
||||||
|
|
||||||
|
client := NewMockCloudFlareClient()
|
||||||
|
client.zoneDetailsError = errors.New("zone lookup failed")
|
||||||
|
|
||||||
|
provider := &CloudFlareProvider{
|
||||||
|
Client: client,
|
||||||
|
domainFilter: endpoint.NewDomainFilter([]string{"bar.com"}),
|
||||||
|
zoneIDFilter: provider.NewZoneIDFilter([]string{"001"}),
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := provider.Zones(context.Background())
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("should fail, %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCloudFlareZonesWithIDFilter(t *testing.T) {
|
func TestCloudFlareZonesWithIDFilter(t *testing.T) {
|
||||||
client := NewMockCloudFlareClient()
|
client := NewMockCloudFlareClient()
|
||||||
client.listZonesError = errors.New("shouldn't need to list zones when ZoneIDFilter in use")
|
client.listZonesError = errors.New("shouldn't need to list zones when ZoneIDFilter in use")
|
||||||
@ -1002,64 +1025,88 @@ func TestCloudflareRecords(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCloudflareProvider(t *testing.T) {
|
func TestCloudflareProvider(t *testing.T) {
|
||||||
_ = os.Setenv("CF_API_TOKEN", "abc123def")
|
var err error
|
||||||
_, err := NewCloudFlareProvider(
|
|
||||||
endpoint.NewDomainFilter([]string{"bar.com"}),
|
type EnvVar struct {
|
||||||
provider.NewZoneIDFilter([]string{""}),
|
Key string
|
||||||
false,
|
Value string
|
||||||
true,
|
|
||||||
5000,
|
|
||||||
"",
|
|
||||||
CustomHostnamesConfig{Enabled: false})
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("should not fail, %s", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = os.Unsetenv("CF_API_TOKEN")
|
|
||||||
tokenFile := "/tmp/cf_api_token"
|
tokenFile := "/tmp/cf_api_token"
|
||||||
if err := os.WriteFile(tokenFile, []byte("abc123def"), 0o644); err != nil {
|
if err := os.WriteFile(tokenFile, []byte("abc123def"), 0o644); err != nil {
|
||||||
t.Errorf("failed to write token file, %s", err)
|
t.Errorf("failed to write token file, %s", err)
|
||||||
}
|
}
|
||||||
_ = os.Setenv("CF_API_TOKEN", tokenFile)
|
|
||||||
_, err = NewCloudFlareProvider(
|
testCases := []struct {
|
||||||
endpoint.NewDomainFilter([]string{"bar.com"}),
|
Name string
|
||||||
provider.NewZoneIDFilter([]string{""}),
|
Environment []EnvVar
|
||||||
false,
|
ShouldFail bool
|
||||||
true,
|
}{
|
||||||
5000,
|
{
|
||||||
"",
|
Name: "use_api_token",
|
||||||
CustomHostnamesConfig{Enabled: false})
|
Environment: []EnvVar{
|
||||||
if err != nil {
|
{Key: "CF_API_TOKEN", Value: "abc123def"},
|
||||||
t.Errorf("should not fail, %s", err)
|
},
|
||||||
|
ShouldFail: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "use_api_token_file_contents",
|
||||||
|
Environment: []EnvVar{
|
||||||
|
{Key: "CF_API_TOKEN", Value: tokenFile},
|
||||||
|
},
|
||||||
|
ShouldFail: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "use_email_and_key",
|
||||||
|
Environment: []EnvVar{
|
||||||
|
{Key: "CF_API_KEY", Value: "xxxxxxxxxxxxxxxxx"},
|
||||||
|
{Key: "CF_API_EMAIL", Value: "test@test.com"},
|
||||||
|
},
|
||||||
|
ShouldFail: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "no_use_email_and_key",
|
||||||
|
Environment: []EnvVar{},
|
||||||
|
ShouldFail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "use_credentials_in_missing_file",
|
||||||
|
Environment: []EnvVar{
|
||||||
|
{Key: "CF_API_TOKEN", Value: "file://abc"},
|
||||||
|
},
|
||||||
|
ShouldFail: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "use_credentials_in_missing_file",
|
||||||
|
Environment: []EnvVar{
|
||||||
|
{Key: "CF_API_TOKEN", Value: "file:/tmp/cf_api_token"},
|
||||||
|
},
|
||||||
|
ShouldFail: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = os.Unsetenv("CF_API_TOKEN")
|
for _, tc := range testCases {
|
||||||
_ = os.Setenv("CF_API_KEY", "xxxxxxxxxxxxxxxxx")
|
t.Run(tc.Name, func(t *testing.T) {
|
||||||
_ = os.Setenv("CF_API_EMAIL", "test@test.com")
|
for _, env := range tc.Environment {
|
||||||
_, err = NewCloudFlareProvider(
|
t.Setenv(env.Key, env.Value)
|
||||||
endpoint.NewDomainFilter([]string{"bar.com"}),
|
}
|
||||||
provider.NewZoneIDFilter([]string{""}),
|
|
||||||
false,
|
_, err = NewCloudFlareProvider(
|
||||||
true,
|
endpoint.NewDomainFilter([]string{"bar.com"}),
|
||||||
5000,
|
provider.NewZoneIDFilter([]string{""}),
|
||||||
"",
|
false,
|
||||||
CustomHostnamesConfig{Enabled: false})
|
true,
|
||||||
if err != nil {
|
5000,
|
||||||
t.Errorf("should not fail, %s", err)
|
"",
|
||||||
}
|
CustomHostnamesConfig{Enabled: false})
|
||||||
|
if err != nil && !tc.ShouldFail {
|
||||||
|
t.Errorf("should not fail, %s", err)
|
||||||
|
}
|
||||||
|
if err == nil && tc.ShouldFail {
|
||||||
|
t.Errorf("should fail, %s", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
_ = os.Unsetenv("CF_API_KEY")
|
|
||||||
_ = os.Unsetenv("CF_API_EMAIL")
|
|
||||||
_, err = NewCloudFlareProvider(
|
|
||||||
endpoint.NewDomainFilter([]string{"bar.com"}),
|
|
||||||
provider.NewZoneIDFilter([]string{""}),
|
|
||||||
false,
|
|
||||||
true,
|
|
||||||
5000,
|
|
||||||
"",
|
|
||||||
CustomHostnamesConfig{Enabled: false})
|
|
||||||
if err == nil {
|
|
||||||
t.Errorf("expected to fail")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1132,6 +1179,30 @@ func TestCloudflareApplyChanges(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCloudflareDryRunApplyChanges(t *testing.T) {
|
||||||
|
changes := &plan.Changes{}
|
||||||
|
client := NewMockCloudFlareClient()
|
||||||
|
|
||||||
|
provider := &CloudFlareProvider{
|
||||||
|
Client: client,
|
||||||
|
DryRun: true,
|
||||||
|
}
|
||||||
|
changes.Create = []*endpoint.Endpoint{{
|
||||||
|
DNSName: "new.bar.com",
|
||||||
|
Targets: endpoint.Targets{"target"},
|
||||||
|
}}
|
||||||
|
err := provider.ApplyChanges(context.Background(), changes)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("should not fail, %s", err)
|
||||||
|
}
|
||||||
|
ctx := context.Background()
|
||||||
|
records, err := provider.Records(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("should not fail, %s", err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, 0, len(records), "should not have any records")
|
||||||
|
}
|
||||||
|
|
||||||
func TestCloudflareApplyChangesError(t *testing.T) {
|
func TestCloudflareApplyChangesError(t *testing.T) {
|
||||||
changes := &plan.Changes{}
|
changes := &plan.Changes{}
|
||||||
client := NewMockCloudFlareClient()
|
client := NewMockCloudFlareClient()
|
||||||
@ -1217,7 +1288,7 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
|
|||||||
Name: "foo.com",
|
Name: "foo.com",
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Content: "10.10.10.1",
|
Content: "10.10.10.1",
|
||||||
TTL: defaultCloudFlareRecordTTL,
|
TTL: defaultTTL,
|
||||||
Proxied: proxyDisabled,
|
Proxied: proxyDisabled,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1226,7 +1297,7 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
|
|||||||
DNSName: "foo.com",
|
DNSName: "foo.com",
|
||||||
Targets: endpoint.Targets{"10.10.10.1"},
|
Targets: endpoint.Targets{"10.10.10.1"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -1244,14 +1315,14 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
|
|||||||
Name: "foo.com",
|
Name: "foo.com",
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Content: "10.10.10.1",
|
Content: "10.10.10.1",
|
||||||
TTL: defaultCloudFlareRecordTTL,
|
TTL: defaultTTL,
|
||||||
Proxied: proxyDisabled,
|
Proxied: proxyDisabled,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "foo.com",
|
Name: "foo.com",
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Content: "10.10.10.2",
|
Content: "10.10.10.2",
|
||||||
TTL: defaultCloudFlareRecordTTL,
|
TTL: defaultTTL,
|
||||||
Proxied: proxyDisabled,
|
Proxied: proxyDisabled,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1260,7 +1331,7 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
|
|||||||
DNSName: "foo.com",
|
DNSName: "foo.com",
|
||||||
Targets: endpoint.Targets{"10.10.10.1", "10.10.10.2"},
|
Targets: endpoint.Targets{"10.10.10.1", "10.10.10.2"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -1278,28 +1349,28 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
|
|||||||
Name: "foo.com",
|
Name: "foo.com",
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Content: "10.10.10.1",
|
Content: "10.10.10.1",
|
||||||
TTL: defaultCloudFlareRecordTTL,
|
TTL: defaultTTL,
|
||||||
Proxied: proxyDisabled,
|
Proxied: proxyDisabled,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "foo.com",
|
Name: "foo.com",
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Content: "10.10.10.2",
|
Content: "10.10.10.2",
|
||||||
TTL: defaultCloudFlareRecordTTL,
|
TTL: defaultTTL,
|
||||||
Proxied: proxyDisabled,
|
Proxied: proxyDisabled,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "bar.de",
|
Name: "bar.de",
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Content: "10.10.10.1",
|
Content: "10.10.10.1",
|
||||||
TTL: defaultCloudFlareRecordTTL,
|
TTL: defaultTTL,
|
||||||
Proxied: proxyDisabled,
|
Proxied: proxyDisabled,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "bar.de",
|
Name: "bar.de",
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Content: "10.10.10.2",
|
Content: "10.10.10.2",
|
||||||
TTL: defaultCloudFlareRecordTTL,
|
TTL: defaultTTL,
|
||||||
Proxied: proxyDisabled,
|
Proxied: proxyDisabled,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1308,7 +1379,7 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
|
|||||||
DNSName: "foo.com",
|
DNSName: "foo.com",
|
||||||
Targets: endpoint.Targets{"10.10.10.1", "10.10.10.2"},
|
Targets: endpoint.Targets{"10.10.10.1", "10.10.10.2"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -1321,7 +1392,7 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
|
|||||||
DNSName: "bar.de",
|
DNSName: "bar.de",
|
||||||
Targets: endpoint.Targets{"10.10.10.1", "10.10.10.2"},
|
Targets: endpoint.Targets{"10.10.10.1", "10.10.10.2"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -1339,21 +1410,21 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
|
|||||||
Name: "foo.com",
|
Name: "foo.com",
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Content: "10.10.10.1",
|
Content: "10.10.10.1",
|
||||||
TTL: defaultCloudFlareRecordTTL,
|
TTL: defaultTTL,
|
||||||
Proxied: proxyDisabled,
|
Proxied: proxyDisabled,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "foo.com",
|
Name: "foo.com",
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Content: "10.10.10.2",
|
Content: "10.10.10.2",
|
||||||
TTL: defaultCloudFlareRecordTTL,
|
TTL: defaultTTL,
|
||||||
Proxied: proxyDisabled,
|
Proxied: proxyDisabled,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "bar.de",
|
Name: "bar.de",
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Content: "10.10.10.1",
|
Content: "10.10.10.1",
|
||||||
TTL: defaultCloudFlareRecordTTL,
|
TTL: defaultTTL,
|
||||||
Proxied: proxyDisabled,
|
Proxied: proxyDisabled,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1362,7 +1433,7 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
|
|||||||
DNSName: "foo.com",
|
DNSName: "foo.com",
|
||||||
Targets: endpoint.Targets{"10.10.10.1", "10.10.10.2"},
|
Targets: endpoint.Targets{"10.10.10.1", "10.10.10.2"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -1375,7 +1446,7 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
|
|||||||
DNSName: "bar.de",
|
DNSName: "bar.de",
|
||||||
Targets: endpoint.Targets{"10.10.10.1"},
|
Targets: endpoint.Targets{"10.10.10.1"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -1393,21 +1464,21 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
|
|||||||
Name: "foo.com",
|
Name: "foo.com",
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Content: "10.10.10.1",
|
Content: "10.10.10.1",
|
||||||
TTL: defaultCloudFlareRecordTTL,
|
TTL: defaultTTL,
|
||||||
Proxied: proxyDisabled,
|
Proxied: proxyDisabled,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "foo.com",
|
Name: "foo.com",
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Content: "10.10.10.2",
|
Content: "10.10.10.2",
|
||||||
TTL: defaultCloudFlareRecordTTL,
|
TTL: defaultTTL,
|
||||||
Proxied: proxyDisabled,
|
Proxied: proxyDisabled,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "bar.de",
|
Name: "bar.de",
|
||||||
Type: "NOT SUPPORTED",
|
Type: "NOT SUPPORTED",
|
||||||
Content: "10.10.10.1",
|
Content: "10.10.10.1",
|
||||||
TTL: defaultCloudFlareRecordTTL,
|
TTL: defaultTTL,
|
||||||
Proxied: proxyDisabled,
|
Proxied: proxyDisabled,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1416,7 +1487,7 @@ func TestCloudflareGroupByNameAndType(t *testing.T) {
|
|||||||
DNSName: "foo.com",
|
DNSName: "foo.com",
|
||||||
Targets: endpoint.Targets{"10.10.10.1", "10.10.10.2"},
|
Targets: endpoint.Targets{"10.10.10.1", "10.10.10.2"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -1568,7 +1639,7 @@ func TestCloudflareComplexUpdate(t *testing.T) {
|
|||||||
DNSName: "foobar.bar.com",
|
DNSName: "foobar.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4", "2.3.4.5"},
|
Targets: endpoint.Targets{"1.2.3.4", "2.3.4.5"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -1889,7 +1960,7 @@ func TestCloudflareLongRecordsErrorLog(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
b := testutils.LogsToBuffer(log.InfoLevel, t)
|
hook := testutils.LogsUnderTestWithLogLevel(log.InfoLevel, t)
|
||||||
p := &CloudFlareProvider{
|
p := &CloudFlareProvider{
|
||||||
Client: client,
|
Client: client,
|
||||||
CustomHostnamesConfig: CustomHostnamesConfig{Enabled: true},
|
CustomHostnamesConfig: CustomHostnamesConfig{Enabled: true},
|
||||||
@ -1899,7 +1970,7 @@ func TestCloudflareLongRecordsErrorLog(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("should not fail - too long record, %s", err)
|
t.Errorf("should not fail - too long record, %s", err)
|
||||||
}
|
}
|
||||||
assert.Contains(t, b.String(), "is longer than 63 characters. Cannot create endpoint")
|
testutils.TestHelperLogContains("s longer than 63 characters. Cannot create endpoint", hook, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the error is expected
|
// check if the error is expected
|
||||||
@ -1935,7 +2006,7 @@ func TestCloudflareDNSRecordsOperationsFail(t *testing.T) {
|
|||||||
DNSName: "newerror.bar.com",
|
DNSName: "newerror.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1948,7 +2019,7 @@ func TestCloudflareDNSRecordsOperationsFail(t *testing.T) {
|
|||||||
DNSName: "newerror-list-1.foo.bar.com",
|
DNSName: "newerror-list-1.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -1966,7 +2037,7 @@ func TestCloudflareDNSRecordsOperationsFail(t *testing.T) {
|
|||||||
DNSName: "newerror-update-1.foo.bar.com",
|
DNSName: "newerror-update-1.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -2050,7 +2121,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "create.foo.bar.com",
|
DNSName: "create.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2069,7 +2140,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "origin.foo.bar.com",
|
DNSName: "origin.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4", "2.3.4.5"},
|
Targets: endpoint.Targets{"1.2.3.4", "2.3.4.5"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2082,7 +2153,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "another-origin.foo.bar.com",
|
DNSName: "another-origin.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"3.4.5.6"},
|
Targets: endpoint.Targets{"3.4.5.6"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2101,7 +2172,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "c.foo.bar.com",
|
DNSName: "c.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"c.cname.foo.bar.com"},
|
Targets: endpoint.Targets{"c.cname.foo.bar.com"},
|
||||||
RecordType: endpoint.RecordTypeCNAME,
|
RecordType: endpoint.RecordTypeCNAME,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2122,7 +2193,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/external-dns/my-domain-here-app",
|
"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/external-dns/my-domain-here-app",
|
||||||
},
|
},
|
||||||
RecordType: endpoint.RecordTypeTXT,
|
RecordType: endpoint.RecordTypeTXT,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2141,7 +2212,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "fail.foo.bar.com",
|
DNSName: "fail.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2160,7 +2231,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "fail.list.foo.bar.com",
|
DNSName: "fail.list.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2184,7 +2255,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "b.foo.bar.com",
|
DNSName: "b.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2203,7 +2274,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "b.foo.bar.com",
|
DNSName: "b.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2222,7 +2293,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "b.foo.bar.com",
|
DNSName: "b.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2241,7 +2312,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "b.foo.bar.com",
|
DNSName: "b.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -2254,7 +2325,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "b.foo.bar.com",
|
DNSName: "b.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2285,7 +2356,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "nocustomhostname.foo.bar.com",
|
DNSName: "nocustomhostname.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -2298,7 +2369,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "a.foo.bar.com",
|
DNSName: "a.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2311,7 +2382,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "txt.foo.bar.com",
|
DNSName: "txt.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"value"},
|
Targets: endpoint.Targets{"value"},
|
||||||
RecordType: endpoint.RecordTypeTXT,
|
RecordType: endpoint.RecordTypeTXT,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2332,7 +2403,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "a.foo.bar.com",
|
DNSName: "a.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2353,7 +2424,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "a.foo.bar.com",
|
DNSName: "a.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2376,7 +2447,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "a.foo.bar.com",
|
DNSName: "a.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2399,7 +2470,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "a.foo.bar.com",
|
DNSName: "a.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2420,7 +2491,7 @@ func TestCloudflareCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "a.foo.bar.com",
|
DNSName: "a.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -2509,7 +2580,7 @@ func TestCloudflareDisabledCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "a.foo.bar.com",
|
DNSName: "a.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.11"},
|
Targets: endpoint.Targets{"1.2.3.11"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2522,14 +2593,14 @@ func TestCloudflareDisabledCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "b.foo.bar.com",
|
DNSName: "b.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.12"},
|
Targets: endpoint.Targets{"1.2.3.12"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
DNSName: "c.foo.bar.com",
|
DNSName: "c.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.13"},
|
Targets: endpoint.Targets{"1.2.3.13"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2548,14 +2619,14 @@ func TestCloudflareDisabledCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "a.foo.bar.com",
|
DNSName: "a.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.11"},
|
Targets: endpoint.Targets{"1.2.3.11"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
DNSName: "b.foo.bar.com",
|
DNSName: "b.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.12"},
|
Targets: endpoint.Targets{"1.2.3.12"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2568,7 +2639,7 @@ func TestCloudflareDisabledCustomHostnameOperations(t *testing.T) {
|
|||||||
DNSName: "c.foo.bar.com",
|
DNSName: "c.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.13"},
|
Targets: endpoint.Targets{"1.2.3.13"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2632,7 +2703,7 @@ func TestCloudflareCustomHostnameNotFoundOnRecordDeletion(t *testing.T) {
|
|||||||
DNSName: "create.foo.bar.com",
|
DNSName: "create.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2649,7 +2720,7 @@ func TestCloudflareCustomHostnameNotFoundOnRecordDeletion(t *testing.T) {
|
|||||||
Name: "remove DNS record with unexpectedly missing custom hostname",
|
Name: "remove DNS record with unexpectedly missing custom hostname",
|
||||||
Endpoints: []*endpoint.Endpoint{},
|
Endpoints: []*endpoint.Endpoint{},
|
||||||
preApplyHook: "corrupt",
|
preApplyHook: "corrupt",
|
||||||
logOutput: "level=warning msg=\"failed to delete custom hostname \\\"newerror-getCustomHostnameOrigin.foo.fancybar.com\\\": failed to get custom hostname: \\\"newerror-getCustomHostnameOrigin.foo.fancybar.com\\\" not found\" action=DELETE record=create.foo.bar.com",
|
logOutput: "failed to delete custom hostname \"newerror-getCustomHostnameOrigin.foo.fancybar.com\": failed to get custom hostname: \"newerror-getCustomHostnameOrigin.foo.fancybar.com\" not found",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "duplicate custom hostname",
|
Name: "duplicate custom hostname",
|
||||||
@ -2664,7 +2735,7 @@ func TestCloudflareCustomHostnameNotFoundOnRecordDeletion(t *testing.T) {
|
|||||||
DNSName: "a.foo.bar.com",
|
DNSName: "a.foo.bar.com",
|
||||||
Targets: endpoint.Targets{"1.2.3.4"},
|
Targets: endpoint.Targets{"1.2.3.4"},
|
||||||
RecordType: endpoint.RecordTypeA,
|
RecordType: endpoint.RecordTypeA,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
@ -2675,12 +2746,12 @@ func TestCloudflareCustomHostnameNotFoundOnRecordDeletion(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
preApplyHook: "",
|
preApplyHook: "",
|
||||||
logOutput: "custom hostname \\\"a.foo.fancybar.com\\\" already exists with the same origin \\\"a.foo.bar.com\\\", continue",
|
logOutput: "custom hostname \"a.foo.fancybar.com\" already exists with the same origin \"a.foo.bar.com\", continue",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
b := testutils.LogsToBuffer(log.InfoLevel, t)
|
hook := testutils.LogsUnderTestWithLogLevel(log.InfoLevel, t)
|
||||||
|
|
||||||
records, err := provider.Records(ctx)
|
records, err := provider.Records(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -2730,7 +2801,8 @@ func TestCloudflareCustomHostnameNotFoundOnRecordDeletion(t *testing.T) {
|
|||||||
if e := checkFailed(tc.Name, err, false); !errors.Is(e, nil) {
|
if e := checkFailed(tc.Name, err, false); !errors.Is(e, nil) {
|
||||||
t.Error(e)
|
t.Error(e)
|
||||||
}
|
}
|
||||||
assert.Contains(t, b.String(), tc.logOutput)
|
|
||||||
|
testutils.TestHelperLogContains(tc.logOutput, hook, t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2751,7 +2823,7 @@ func TestCloudflareListCustomHostnamesWithPagionation(t *testing.T) {
|
|||||||
DNSName: fmt.Sprintf("host-%d.foo.bar.com", i),
|
DNSName: fmt.Sprintf("host-%d.foo.bar.com", i),
|
||||||
Targets: endpoint.Targets{fmt.Sprintf("cname-%d.foo.bar.com", i)},
|
Targets: endpoint.Targets{fmt.Sprintf("cname-%d.foo.bar.com", i)},
|
||||||
RecordType: endpoint.RecordTypeCNAME,
|
RecordType: endpoint.RecordTypeCNAME,
|
||||||
RecordTTL: endpoint.TTL(defaultCloudFlareRecordTTL),
|
RecordTTL: endpoint.TTL(defaultTTL),
|
||||||
Labels: endpoint.Labels{},
|
Labels: endpoint.Labels{},
|
||||||
ProviderSpecific: endpoint.ProviderSpecific{
|
ProviderSpecific: endpoint.ProviderSpecific{
|
||||||
{
|
{
|
||||||
|
@ -92,7 +92,7 @@ type etcdClient struct {
|
|||||||
|
|
||||||
var _ coreDNSClient = etcdClient{}
|
var _ coreDNSClient = etcdClient{}
|
||||||
|
|
||||||
// GetService return all Service records stored in etcd stored anywhere under the given key (recursively)
|
// GetServices GetService return all Service records stored in etcd stored anywhere under the given key (recursively)
|
||||||
func (c etcdClient) GetServices(prefix string) ([]*Service, error) {
|
func (c etcdClient) GetServices(prefix string) ([]*Service, error) {
|
||||||
ctx, cancel := context.WithTimeout(c.ctx, etcdTimeout)
|
ctx, cancel := context.WithTimeout(c.ctx, etcdTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
@ -34,8 +34,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// digitalOceanRecordTTL is the default TTL value
|
// defaultTTL is the default TTL value
|
||||||
digitalOceanRecordTTL = 300
|
defaultTTL = 300
|
||||||
)
|
)
|
||||||
|
|
||||||
// DigitalOceanProvider is an implementation of Provider for Digital Ocean's DNS.
|
// DigitalOceanProvider is an implementation of Provider for Digital Ocean's DNS.
|
||||||
@ -397,7 +397,7 @@ func getTTLFromEndpoint(ep *endpoint.Endpoint) int {
|
|||||||
if ep.RecordTTL.IsConfigured() {
|
if ep.RecordTTL.IsConfigured() {
|
||||||
return int(ep.RecordTTL)
|
return int(ep.RecordTTL)
|
||||||
}
|
}
|
||||||
return digitalOceanRecordTTL
|
return defaultTTL
|
||||||
}
|
}
|
||||||
|
|
||||||
func endpointsByZone(zoneNameIDMapper provider.ZoneIDName, endpoints []*endpoint.Endpoint) map[string][]*endpoint.Endpoint {
|
func endpointsByZone(zoneNameIDMapper provider.ZoneIDName, endpoints []*endpoint.Endpoint) map[string][]*endpoint.Endpoint {
|
||||||
|
@ -309,32 +309,32 @@ func TestDigitalOceanZones(t *testing.T) {
|
|||||||
func TestDigitalOceanMakeDomainEditRequest(t *testing.T) {
|
func TestDigitalOceanMakeDomainEditRequest(t *testing.T) {
|
||||||
// Ensure that records at the root of the zone get `@` as the name.
|
// Ensure that records at the root of the zone get `@` as the name.
|
||||||
r1 := makeDomainEditRequest("example.com", "example.com", endpoint.RecordTypeA,
|
r1 := makeDomainEditRequest("example.com", "example.com", endpoint.RecordTypeA,
|
||||||
"1.2.3.4", digitalOceanRecordTTL)
|
"1.2.3.4", defaultTTL)
|
||||||
assert.Equal(t, &godo.DomainRecordEditRequest{
|
assert.Equal(t, &godo.DomainRecordEditRequest{
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Name: "@",
|
Name: "@",
|
||||||
Data: "1.2.3.4",
|
Data: "1.2.3.4",
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
}, r1)
|
}, r1)
|
||||||
|
|
||||||
// Ensure the CNAME records have a `.` appended.
|
// Ensure the CNAME records have a `.` appended.
|
||||||
r2 := makeDomainEditRequest("example.com", "foo.example.com", endpoint.RecordTypeCNAME,
|
r2 := makeDomainEditRequest("example.com", "foo.example.com", endpoint.RecordTypeCNAME,
|
||||||
"bar.example.com", digitalOceanRecordTTL)
|
"bar.example.com", defaultTTL)
|
||||||
assert.Equal(t, &godo.DomainRecordEditRequest{
|
assert.Equal(t, &godo.DomainRecordEditRequest{
|
||||||
Type: endpoint.RecordTypeCNAME,
|
Type: endpoint.RecordTypeCNAME,
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Data: "bar.example.com.",
|
Data: "bar.example.com.",
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
}, r2)
|
}, r2)
|
||||||
|
|
||||||
// Ensure that CNAME records do not have an extra `.` appended if they already have a `.`
|
// Ensure that CNAME records do not have an extra `.` appended if they already have a `.`
|
||||||
r3 := makeDomainEditRequest("example.com", "foo.example.com", endpoint.RecordTypeCNAME,
|
r3 := makeDomainEditRequest("example.com", "foo.example.com", endpoint.RecordTypeCNAME,
|
||||||
"bar.example.com.", digitalOceanRecordTTL)
|
"bar.example.com.", defaultTTL)
|
||||||
assert.Equal(t, &godo.DomainRecordEditRequest{
|
assert.Equal(t, &godo.DomainRecordEditRequest{
|
||||||
Type: endpoint.RecordTypeCNAME,
|
Type: endpoint.RecordTypeCNAME,
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Data: "bar.example.com.",
|
Data: "bar.example.com.",
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
}, r3)
|
}, r3)
|
||||||
|
|
||||||
// Ensure that custom TTLs can be set
|
// Ensure that custom TTLs can be set
|
||||||
@ -350,24 +350,24 @@ func TestDigitalOceanMakeDomainEditRequest(t *testing.T) {
|
|||||||
|
|
||||||
// Ensure that MX records have `.` appended.
|
// Ensure that MX records have `.` appended.
|
||||||
r5 := makeDomainEditRequest("example.com", "foo.example.com", endpoint.RecordTypeMX,
|
r5 := makeDomainEditRequest("example.com", "foo.example.com", endpoint.RecordTypeMX,
|
||||||
"10 mx.example.com", digitalOceanRecordTTL)
|
"10 mx.example.com", defaultTTL)
|
||||||
assert.Equal(t, &godo.DomainRecordEditRequest{
|
assert.Equal(t, &godo.DomainRecordEditRequest{
|
||||||
Type: endpoint.RecordTypeMX,
|
Type: endpoint.RecordTypeMX,
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Data: "mx.example.com.",
|
Data: "mx.example.com.",
|
||||||
Priority: 10,
|
Priority: 10,
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
}, r5)
|
}, r5)
|
||||||
|
|
||||||
// Ensure that MX records do not have an extra `.` appended if they already have a `.`
|
// Ensure that MX records do not have an extra `.` appended if they already have a `.`
|
||||||
r6 := makeDomainEditRequest("example.com", "foo.example.com", endpoint.RecordTypeMX,
|
r6 := makeDomainEditRequest("example.com", "foo.example.com", endpoint.RecordTypeMX,
|
||||||
"10 mx.example.com.", digitalOceanRecordTTL)
|
"10 mx.example.com.", defaultTTL)
|
||||||
assert.Equal(t, &godo.DomainRecordEditRequest{
|
assert.Equal(t, &godo.DomainRecordEditRequest{
|
||||||
Type: endpoint.RecordTypeMX,
|
Type: endpoint.RecordTypeMX,
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Data: "mx.example.com.",
|
Data: "mx.example.com.",
|
||||||
Priority: 10,
|
Priority: 10,
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
}, r6)
|
}, r6)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,7 +420,7 @@ func TestDigitalOceanProcessCreateActions(t *testing.T) {
|
|||||||
Name: "foo",
|
Name: "foo",
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Data: "1.2.3.4",
|
Data: "1.2.3.4",
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -429,7 +429,7 @@ func TestDigitalOceanProcessCreateActions(t *testing.T) {
|
|||||||
Name: "@",
|
Name: "@",
|
||||||
Type: endpoint.RecordTypeCNAME,
|
Type: endpoint.RecordTypeCNAME,
|
||||||
Data: "foo.example.com.",
|
Data: "foo.example.com.",
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -439,7 +439,7 @@ func TestDigitalOceanProcessCreateActions(t *testing.T) {
|
|||||||
Type: endpoint.RecordTypeMX,
|
Type: endpoint.RecordTypeMX,
|
||||||
Priority: 10,
|
Priority: 10,
|
||||||
Data: "mx.example.com.",
|
Data: "mx.example.com.",
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -448,7 +448,7 @@ func TestDigitalOceanProcessCreateActions(t *testing.T) {
|
|||||||
Name: "@",
|
Name: "@",
|
||||||
Type: endpoint.RecordTypeTXT,
|
Type: endpoint.RecordTypeTXT,
|
||||||
Data: "SOME-TXT-TEXT",
|
Data: "SOME-TXT-TEXT",
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -466,21 +466,21 @@ func TestDigitalOceanProcessUpdateActions(t *testing.T) {
|
|||||||
Name: "foo",
|
Name: "foo",
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Data: "1.2.3.4",
|
Data: "1.2.3.4",
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: 2,
|
ID: 2,
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Data: "5.6.7.8",
|
Data: "5.6.7.8",
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: 3,
|
ID: 3,
|
||||||
Name: "@",
|
Name: "@",
|
||||||
Type: endpoint.RecordTypeCNAME,
|
Type: endpoint.RecordTypeCNAME,
|
||||||
Data: "foo.example.com.",
|
Data: "foo.example.com.",
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: 4,
|
ID: 4,
|
||||||
@ -488,7 +488,7 @@ func TestDigitalOceanProcessUpdateActions(t *testing.T) {
|
|||||||
Type: endpoint.RecordTypeMX,
|
Type: endpoint.RecordTypeMX,
|
||||||
Data: "mx1.example.com.",
|
Data: "mx1.example.com.",
|
||||||
Priority: 10,
|
Priority: 10,
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: 5,
|
ID: 5,
|
||||||
@ -496,14 +496,14 @@ func TestDigitalOceanProcessUpdateActions(t *testing.T) {
|
|||||||
Type: endpoint.RecordTypeMX,
|
Type: endpoint.RecordTypeMX,
|
||||||
Data: "mx2.example.com.",
|
Data: "mx2.example.com.",
|
||||||
Priority: 10,
|
Priority: 10,
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: 6,
|
ID: 6,
|
||||||
Name: "@",
|
Name: "@",
|
||||||
Type: endpoint.RecordTypeTXT,
|
Type: endpoint.RecordTypeTXT,
|
||||||
Data: "SOME_TXTX_TEXT",
|
Data: "SOME_TXTX_TEXT",
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -532,7 +532,7 @@ func TestDigitalOceanProcessUpdateActions(t *testing.T) {
|
|||||||
Name: "foo",
|
Name: "foo",
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Data: "10.11.12.13",
|
Data: "10.11.12.13",
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -541,7 +541,7 @@ func TestDigitalOceanProcessUpdateActions(t *testing.T) {
|
|||||||
Name: "@",
|
Name: "@",
|
||||||
Type: endpoint.RecordTypeCNAME,
|
Type: endpoint.RecordTypeCNAME,
|
||||||
Data: "bar.example.com.",
|
Data: "bar.example.com.",
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -551,7 +551,7 @@ func TestDigitalOceanProcessUpdateActions(t *testing.T) {
|
|||||||
Type: endpoint.RecordTypeMX,
|
Type: endpoint.RecordTypeMX,
|
||||||
Data: "mx3.example.com.",
|
Data: "mx3.example.com.",
|
||||||
Priority: 10,
|
Priority: 10,
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -560,7 +560,7 @@ func TestDigitalOceanProcessUpdateActions(t *testing.T) {
|
|||||||
Name: "@",
|
Name: "@",
|
||||||
Type: endpoint.RecordTypeTXT,
|
Type: endpoint.RecordTypeTXT,
|
||||||
Data: "ANOTHER-TXT",
|
Data: "ANOTHER-TXT",
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -609,7 +609,7 @@ func TestDigitalOceanProcessDeleteActions(t *testing.T) {
|
|||||||
Name: "foo",
|
Name: "foo",
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Data: "1.2.3.4",
|
Data: "1.2.3.4",
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
},
|
},
|
||||||
// This record will not be deleted because it represents a target not specified to be deleted.
|
// This record will not be deleted because it represents a target not specified to be deleted.
|
||||||
{
|
{
|
||||||
@ -617,14 +617,14 @@ func TestDigitalOceanProcessDeleteActions(t *testing.T) {
|
|||||||
Name: "foo",
|
Name: "foo",
|
||||||
Type: endpoint.RecordTypeA,
|
Type: endpoint.RecordTypeA,
|
||||||
Data: "5.6.7.8",
|
Data: "5.6.7.8",
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ID: 3,
|
ID: 3,
|
||||||
Name: "@",
|
Name: "@",
|
||||||
Type: endpoint.RecordTypeCNAME,
|
Type: endpoint.RecordTypeCNAME,
|
||||||
Data: "foo.example.com.",
|
Data: "foo.example.com.",
|
||||||
TTL: digitalOceanRecordTTL,
|
TTL: defaultTTL,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,13 @@ import (
|
|||||||
"sigs.k8s.io/external-dns/provider"
|
"sigs.k8s.io/external-dns/provider"
|
||||||
)
|
)
|
||||||
|
|
||||||
const dnsimpleRecordTTL = 3600 // Default TTL of 1 hour if not set (DNSimple's default)
|
const (
|
||||||
|
dnsimpleCreate = "CREATE"
|
||||||
|
dnsimpleDelete = "DELETE"
|
||||||
|
dnsimpleUpdate = "UPDATE"
|
||||||
|
|
||||||
|
defaultTTL = 3600 // Default TTL of 1 hour if not set (DNSimple's default)
|
||||||
|
)
|
||||||
|
|
||||||
type dnsimpleIdentityService struct {
|
type dnsimpleIdentityService struct {
|
||||||
service *dnsimple.IdentityService
|
service *dnsimple.IdentityService
|
||||||
@ -91,12 +97,6 @@ type dnsimpleChange struct {
|
|||||||
ResourceRecordSet dnsimple.ZoneRecord
|
ResourceRecordSet dnsimple.ZoneRecord
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
dnsimpleCreate = "CREATE"
|
|
||||||
dnsimpleDelete = "DELETE"
|
|
||||||
dnsimpleUpdate = "UPDATE"
|
|
||||||
)
|
|
||||||
|
|
||||||
// NewDnsimpleProvider initializes a new Dnsimple based provider
|
// NewDnsimpleProvider initializes a new Dnsimple based provider
|
||||||
func NewDnsimpleProvider(domainFilter endpoint.DomainFilter, zoneIDFilter provider.ZoneIDFilter, dryRun bool) (provider.Provider, error) {
|
func NewDnsimpleProvider(domainFilter endpoint.DomainFilter, zoneIDFilter provider.ZoneIDFilter, dryRun bool) (provider.Provider, error) {
|
||||||
oauthToken := os.Getenv("DNSIMPLE_OAUTH")
|
oauthToken := os.Getenv("DNSIMPLE_OAUTH")
|
||||||
@ -149,7 +149,7 @@ func ZonesFromZoneString(zonestring string) map[string]dnsimple.Zone {
|
|||||||
return zones
|
return zones
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a list of filtered Zones
|
// Zones Return a list of filtered Zones
|
||||||
func (p *dnsimpleProvider) Zones(ctx context.Context) (map[string]dnsimple.Zone, error) {
|
func (p *dnsimpleProvider) Zones(ctx context.Context) (map[string]dnsimple.Zone, error) {
|
||||||
zones := make(map[string]dnsimple.Zone)
|
zones := make(map[string]dnsimple.Zone)
|
||||||
|
|
||||||
@ -231,7 +231,7 @@ func (p *dnsimpleProvider) Records(ctx context.Context) (endpoints []*endpoint.E
|
|||||||
|
|
||||||
// newDnsimpleChange initializes a new change to dns records
|
// newDnsimpleChange initializes a new change to dns records
|
||||||
func newDnsimpleChange(action string, e *endpoint.Endpoint) *dnsimpleChange {
|
func newDnsimpleChange(action string, e *endpoint.Endpoint) *dnsimpleChange {
|
||||||
ttl := dnsimpleRecordTTL
|
ttl := defaultTTL
|
||||||
if e.RecordTTL.IsConfigured() {
|
if e.RecordTTL.IsConfigured() {
|
||||||
ttl = int(e.RecordTTL)
|
ttl = int(e.RecordTTL)
|
||||||
}
|
}
|
||||||
|
@ -181,7 +181,7 @@ func (ep *ExoscaleProvider) ApplyChanges(ctx context.Context, changes *plan.Chan
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, epoint := range changes.UpdateOld {
|
for _, epoint := range changes.UpdateOld {
|
||||||
// Since Exoscale "Patches", we ignore UpdateOld
|
// Since Exoscale "Patches", we've ignored UpdateOld
|
||||||
// We leave this logging here for information
|
// We leave this logging here for information
|
||||||
log.Debugf("UPDATE-OLD (ignored) for epoint: %+v", epoint)
|
log.Debugf("UPDATE-OLD (ignored) for epoint: %+v", epoint)
|
||||||
}
|
}
|
||||||
@ -310,10 +310,10 @@ func (f *zoneFilter) EndpointZoneID(endpoint *endpoint.Endpoint, zones map[strin
|
|||||||
|
|
||||||
func merge(updateOld, updateNew []*endpoint.Endpoint) []*endpoint.Endpoint {
|
func merge(updateOld, updateNew []*endpoint.Endpoint) []*endpoint.Endpoint {
|
||||||
findMatch := func(template *endpoint.Endpoint) *endpoint.Endpoint {
|
findMatch := func(template *endpoint.Endpoint) *endpoint.Endpoint {
|
||||||
for _, new := range updateNew {
|
for _, record := range updateNew {
|
||||||
if template.DNSName == new.DNSName &&
|
if template.DNSName == record.DNSName &&
|
||||||
template.RecordType == new.RecordType {
|
template.RecordType == record.RecordType {
|
||||||
return new
|
return record
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -323,7 +323,7 @@ func merge(updateOld, updateNew []*endpoint.Endpoint) []*endpoint.Endpoint {
|
|||||||
for _, old := range updateOld {
|
for _, old := range updateOld {
|
||||||
matchingNew := findMatch(old)
|
matchingNew := findMatch(old)
|
||||||
if matchingNew == nil {
|
if matchingNew == nil {
|
||||||
// no match, shouldn't happen
|
// no match shouldn't happen
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ const (
|
|||||||
gandiCreate = "CREATE"
|
gandiCreate = "CREATE"
|
||||||
gandiDelete = "DELETE"
|
gandiDelete = "DELETE"
|
||||||
gandiUpdate = "UPDATE"
|
gandiUpdate = "UPDATE"
|
||||||
gandiTTL = 600
|
defaultTTL = 600
|
||||||
gandiLiveDNSProvider = "livedns"
|
gandiLiveDNSProvider = "livedns"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -255,7 +255,7 @@ func (p *GandiProvider) submitChanges(ctx context.Context, changes []*GandiChang
|
|||||||
|
|
||||||
func (p *GandiProvider) newGandiChanges(action string, endpoints []*endpoint.Endpoint) []*GandiChanges {
|
func (p *GandiProvider) newGandiChanges(action string, endpoints []*endpoint.Endpoint) []*GandiChanges {
|
||||||
changes := make([]*GandiChanges, 0, len(endpoints))
|
changes := make([]*GandiChanges, 0, len(endpoints))
|
||||||
ttl := gandiTTL
|
ttl := defaultTTL
|
||||||
for _, e := range endpoints {
|
for _, e := range endpoints {
|
||||||
if e.RecordTTL.IsConfigured() {
|
if e.RecordTTL.IsConfigured() {
|
||||||
ttl = int(e.RecordTTL)
|
ttl = int(e.RecordTTL)
|
||||||
|
@ -34,19 +34,18 @@ import (
|
|||||||
"sigs.k8s.io/external-dns/pkg/apis/externaldns"
|
"sigs.k8s.io/external-dns/pkg/apis/externaldns"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultTimeout api requests after 180s
|
const (
|
||||||
const DefaultTimeout = 180 * time.Second
|
ErrCodeQuotaExceeded = "QUOTA_EXCEEDED"
|
||||||
|
|
||||||
|
// DefaultTimeout api requests after
|
||||||
|
DefaultTimeout = 180 * time.Second
|
||||||
|
)
|
||||||
|
|
||||||
// Errors
|
// Errors
|
||||||
var (
|
var (
|
||||||
ErrAPIDown = errors.New("godaddy: the GoDaddy API is down")
|
ErrAPIDown = errors.New("godaddy: the GoDaddy API is down")
|
||||||
)
|
)
|
||||||
|
|
||||||
// error codes
|
|
||||||
const (
|
|
||||||
ErrCodeQuotaExceeded = "QUOTA_EXCEEDED"
|
|
||||||
)
|
|
||||||
|
|
||||||
// APIError error
|
// APIError error
|
||||||
type APIError struct {
|
type APIError struct {
|
||||||
Code string
|
Code string
|
||||||
|
@ -19,8 +19,8 @@ package godaddy
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@ -32,10 +32,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
gdMinimalTTL = 600
|
defaultTTL = 600
|
||||||
gdCreate = 0
|
gdCreate = 0
|
||||||
gdReplace = 1
|
gdReplace = 1
|
||||||
gdDelete = 2
|
gdDelete = 2
|
||||||
|
|
||||||
|
domainsURI = "/v1/domains?statuses=ACTIVE,PENDING_DNS_ACTIVE"
|
||||||
)
|
)
|
||||||
|
|
||||||
var actionNames = []string{
|
var actionNames = []string{
|
||||||
@ -44,11 +46,6 @@ var actionNames = []string{
|
|||||||
"delete",
|
"delete",
|
||||||
}
|
}
|
||||||
|
|
||||||
const domainsURI = "/v1/domains?statuses=ACTIVE,PENDING_DNS_ACTIVE"
|
|
||||||
|
|
||||||
// ErrRecordToMutateNotFound when ApplyChange has to update/delete and didn't found the record in the existing zone (Change with no record ID)
|
|
||||||
var ErrRecordToMutateNotFound = errors.New("record to mutate not found in current zone")
|
|
||||||
|
|
||||||
type gdClient interface {
|
type gdClient interface {
|
||||||
Patch(string, interface{}, interface{}) error
|
Patch(string, interface{}, interface{}) error
|
||||||
Post(string, interface{}, interface{}) error
|
Post(string, interface{}, interface{}) error
|
||||||
@ -147,7 +144,7 @@ func NewGoDaddyProvider(ctx context.Context, domainFilter endpoint.DomainFilter,
|
|||||||
return &GDProvider{
|
return &GDProvider{
|
||||||
client: client,
|
client: client,
|
||||||
domainFilter: domainFilter,
|
domainFilter: domainFilter,
|
||||||
ttl: maxOf(gdMinimalTTL, ttl),
|
ttl: maxOf(defaultTTL, ttl),
|
||||||
DryRun: dryRun,
|
DryRun: dryRun,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -294,14 +291,14 @@ func (p *GDProvider) groupByNameAndType(zoneRecords []gdRecords) []*endpoint.End
|
|||||||
recordName = strings.TrimPrefix(fmt.Sprintf("%s.%s", records[0].Name, zoneName), ".")
|
recordName = strings.TrimPrefix(fmt.Sprintf("%s.%s", records[0].Name, zoneName), ".")
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoint := endpoint.NewEndpointWithTTL(
|
ep := endpoint.NewEndpointWithTTL(
|
||||||
recordName,
|
recordName,
|
||||||
records[0].Type,
|
records[0].Type,
|
||||||
endpoint.TTL(records[0].TTL),
|
endpoint.TTL(records[0].TTL),
|
||||||
targets...,
|
targets...,
|
||||||
)
|
)
|
||||||
|
|
||||||
endpoints = append(endpoints, endpoint)
|
endpoints = append(endpoints, ep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,7 +353,7 @@ func (p *GDProvider) changeAllRecords(endpoints []gdEndpoint, zoneRecords []*gdR
|
|||||||
dnsName = "@"
|
dnsName = "@"
|
||||||
}
|
}
|
||||||
|
|
||||||
e.endpoint.RecordTTL = endpoint.TTL(maxOf(gdMinimalTTL, int64(e.endpoint.RecordTTL)))
|
e.endpoint.RecordTTL = endpoint.TTL(maxOf(defaultTTL, int64(e.endpoint.RecordTTL)))
|
||||||
|
|
||||||
if err := zoneRecord.applyEndpoint(e.action, p.client, *e.endpoint, dnsName, p.DryRun); err != nil {
|
if err := zoneRecord.applyEndpoint(e.action, p.client, *e.endpoint, dnsName, p.DryRun); err != nil {
|
||||||
log.Errorf("Unable to apply change %s on record %s type %s, %v", actionNames[e.action], dnsName, e.endpoint.RecordType, err)
|
log.Errorf("Unable to apply change %s on record %s type %s, %v", actionNames[e.action], dnsName, e.endpoint.RecordType, err)
|
||||||
@ -584,8 +581,8 @@ func countTargets(p *plan.Changes) int {
|
|||||||
count := 0
|
count := 0
|
||||||
|
|
||||||
for _, endpoints := range changes {
|
for _, endpoints := range changes {
|
||||||
for _, endpoint := range endpoints {
|
for _, ep := range endpoints {
|
||||||
count += len(endpoint.Targets)
|
count += len(ep.Targets)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -593,15 +590,7 @@ func countTargets(p *plan.Changes) int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func maxOf(vars ...int64) int64 {
|
func maxOf(vars ...int64) int64 {
|
||||||
max := vars[0]
|
return slices.Max(vars)
|
||||||
|
|
||||||
for _, i := range vars {
|
|
||||||
if max < i {
|
|
||||||
max = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return max
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func toString(obj interface{}) string {
|
func toString(obj interface{}) string {
|
||||||
|
@ -138,13 +138,13 @@ func TestGoDaddyZoneRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "godaddy",
|
Name: "godaddy",
|
||||||
Type: "NS",
|
Type: "NS",
|
||||||
TTL: gdMinimalTTL,
|
TTL: defaultTTL,
|
||||||
Data: "203.0.113.42",
|
Data: "203.0.113.42",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "godaddy",
|
Name: "godaddy",
|
||||||
Type: "A",
|
Type: "A",
|
||||||
TTL: gdMinimalTTL,
|
TTL: defaultTTL,
|
||||||
Data: "203.0.113.42",
|
Data: "203.0.113.42",
|
||||||
},
|
},
|
||||||
}, nil).Once()
|
}, nil).Once()
|
||||||
@ -164,13 +164,13 @@ func TestGoDaddyZoneRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "godaddy",
|
Name: "godaddy",
|
||||||
Type: "NS",
|
Type: "NS",
|
||||||
TTL: gdMinimalTTL,
|
TTL: defaultTTL,
|
||||||
Data: "203.0.113.42",
|
Data: "203.0.113.42",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "godaddy",
|
Name: "godaddy",
|
||||||
Type: "A",
|
Type: "A",
|
||||||
TTL: gdMinimalTTL,
|
TTL: defaultTTL,
|
||||||
Data: "203.0.113.42",
|
Data: "203.0.113.42",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -240,13 +240,13 @@ func TestGoDaddyRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "@",
|
Name: "@",
|
||||||
Type: "A",
|
Type: "A",
|
||||||
TTL: gdMinimalTTL,
|
TTL: defaultTTL,
|
||||||
Data: "203.0.113.42",
|
Data: "203.0.113.42",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "www",
|
Name: "www",
|
||||||
Type: "CNAME",
|
Type: "CNAME",
|
||||||
TTL: gdMinimalTTL,
|
TTL: defaultTTL,
|
||||||
Data: "example.org",
|
Data: "example.org",
|
||||||
},
|
},
|
||||||
}, nil).Once()
|
}, nil).Once()
|
||||||
@ -255,13 +255,13 @@ func TestGoDaddyRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "godaddy",
|
Name: "godaddy",
|
||||||
Type: "A",
|
Type: "A",
|
||||||
TTL: gdMinimalTTL,
|
TTL: defaultTTL,
|
||||||
Data: "203.0.113.42",
|
Data: "203.0.113.42",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "godaddy",
|
Name: "godaddy",
|
||||||
Type: "A",
|
Type: "A",
|
||||||
TTL: gdMinimalTTL,
|
TTL: defaultTTL,
|
||||||
Data: "203.0.113.43",
|
Data: "203.0.113.43",
|
||||||
},
|
},
|
||||||
}, nil).Once()
|
}, nil).Once()
|
||||||
@ -278,7 +278,7 @@ func TestGoDaddyRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
DNSName: "godaddy.example.net",
|
DNSName: "godaddy.example.net",
|
||||||
RecordType: "A",
|
RecordType: "A",
|
||||||
RecordTTL: gdMinimalTTL,
|
RecordTTL: defaultTTL,
|
||||||
Labels: endpoint.NewLabels(),
|
Labels: endpoint.NewLabels(),
|
||||||
Targets: []string{
|
Targets: []string{
|
||||||
"203.0.113.42",
|
"203.0.113.42",
|
||||||
@ -288,7 +288,7 @@ func TestGoDaddyRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
DNSName: "example.org",
|
DNSName: "example.org",
|
||||||
RecordType: "A",
|
RecordType: "A",
|
||||||
RecordTTL: gdMinimalTTL,
|
RecordTTL: defaultTTL,
|
||||||
Labels: endpoint.NewLabels(),
|
Labels: endpoint.NewLabels(),
|
||||||
Targets: []string{
|
Targets: []string{
|
||||||
"203.0.113.42",
|
"203.0.113.42",
|
||||||
@ -297,7 +297,7 @@ func TestGoDaddyRecords(t *testing.T) {
|
|||||||
{
|
{
|
||||||
DNSName: "www.example.org",
|
DNSName: "www.example.org",
|
||||||
RecordType: "CNAME",
|
RecordType: "CNAME",
|
||||||
RecordTTL: gdMinimalTTL,
|
RecordTTL: defaultTTL,
|
||||||
Labels: endpoint.NewLabels(),
|
Labels: endpoint.NewLabels(),
|
||||||
Targets: []string{
|
Targets: []string{
|
||||||
"example.org",
|
"example.org",
|
||||||
@ -327,7 +327,7 @@ func TestGoDaddyChange(t *testing.T) {
|
|||||||
{
|
{
|
||||||
DNSName: ".example.net",
|
DNSName: ".example.net",
|
||||||
RecordType: "A",
|
RecordType: "A",
|
||||||
RecordTTL: gdMinimalTTL,
|
RecordTTL: defaultTTL,
|
||||||
Targets: []string{
|
Targets: []string{
|
||||||
"203.0.113.42",
|
"203.0.113.42",
|
||||||
},
|
},
|
||||||
@ -356,7 +356,7 @@ func TestGoDaddyChange(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "godaddy",
|
Name: "godaddy",
|
||||||
Type: "A",
|
Type: "A",
|
||||||
TTL: gdMinimalTTL,
|
TTL: defaultTTL,
|
||||||
Data: "203.0.113.43",
|
Data: "203.0.113.43",
|
||||||
},
|
},
|
||||||
}, nil).Once()
|
}, nil).Once()
|
||||||
@ -366,7 +366,7 @@ func TestGoDaddyChange(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "@",
|
Name: "@",
|
||||||
Type: "A",
|
Type: "A",
|
||||||
TTL: gdMinimalTTL,
|
TTL: defaultTTL,
|
||||||
Data: "203.0.113.42",
|
Data: "203.0.113.42",
|
||||||
},
|
},
|
||||||
}).Return(nil, nil).Once()
|
}).Return(nil, nil).Once()
|
||||||
@ -398,7 +398,7 @@ func TestGoDaddyErrorResponse(t *testing.T) {
|
|||||||
{
|
{
|
||||||
DNSName: ".example.net",
|
DNSName: ".example.net",
|
||||||
RecordType: "A",
|
RecordType: "A",
|
||||||
RecordTTL: gdMinimalTTL,
|
RecordTTL: defaultTTL,
|
||||||
Targets: []string{
|
Targets: []string{
|
||||||
"203.0.113.42",
|
"203.0.113.42",
|
||||||
},
|
},
|
||||||
@ -427,7 +427,7 @@ func TestGoDaddyErrorResponse(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Name: "godaddy",
|
Name: "godaddy",
|
||||||
Type: "A",
|
Type: "A",
|
||||||
TTL: gdMinimalTTL,
|
TTL: defaultTTL,
|
||||||
Data: "203.0.113.43",
|
Data: "203.0.113.43",
|
||||||
},
|
},
|
||||||
}, nil).Once()
|
}, nil).Once()
|
||||||
|
@ -37,7 +37,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
googleRecordTTL = 300
|
defaultTTL = 300
|
||||||
)
|
)
|
||||||
|
|
||||||
type managedZonesCreateCallInterface interface {
|
type managedZonesCreateCallInterface interface {
|
||||||
@ -154,7 +154,7 @@ func NewGoogleProvider(ctx context.Context, project string, domainFilter endpoin
|
|||||||
|
|
||||||
zoneTypeFilter := provider.NewZoneTypeFilter(zoneVisibility)
|
zoneTypeFilter := provider.NewZoneTypeFilter(zoneVisibility)
|
||||||
|
|
||||||
provider := &GoogleProvider{
|
return &GoogleProvider{
|
||||||
project: project,
|
project: project,
|
||||||
dryRun: dryRun,
|
dryRun: dryRun,
|
||||||
batchChangeSize: batchChangeSize,
|
batchChangeSize: batchChangeSize,
|
||||||
@ -166,9 +166,7 @@ func NewGoogleProvider(ctx context.Context, project string, domainFilter endpoin
|
|||||||
managedZonesClient: managedZonesService{dnsClient.ManagedZones},
|
managedZonesClient: managedZonesService{dnsClient.ManagedZones},
|
||||||
changesClient: changesService{dnsClient.Changes},
|
changesClient: changesService{dnsClient.Changes},
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
}
|
}, nil
|
||||||
|
|
||||||
return provider, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zones returns the list of hosted zones.
|
// Zones returns the list of hosted zones.
|
||||||
@ -261,11 +259,11 @@ func (p *GoogleProvider) SupportedRecordType(recordType string) bool {
|
|||||||
|
|
||||||
// newFilteredRecords returns a collection of RecordSets based on the given endpoints and domainFilter.
|
// newFilteredRecords returns a collection of RecordSets based on the given endpoints and domainFilter.
|
||||||
func (p *GoogleProvider) newFilteredRecords(endpoints []*endpoint.Endpoint) []*dns.ResourceRecordSet {
|
func (p *GoogleProvider) newFilteredRecords(endpoints []*endpoint.Endpoint) []*dns.ResourceRecordSet {
|
||||||
records := []*dns.ResourceRecordSet{}
|
var records []*dns.ResourceRecordSet
|
||||||
|
|
||||||
for _, endpoint := range endpoints {
|
for _, ep := range endpoints {
|
||||||
if p.domainFilter.Match(endpoint.DNSName) {
|
if p.domainFilter.Match(ep.DNSName) {
|
||||||
records = append(records, newRecord(endpoint))
|
records = append(records, newRecord(ep))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,7 +312,7 @@ func (p *GoogleProvider) submitChange(ctx context.Context, change *dns.Change) e
|
|||||||
|
|
||||||
// batchChange separates a zone in multiple transaction.
|
// batchChange separates a zone in multiple transaction.
|
||||||
func batchChange(change *dns.Change, batchSize int) []*dns.Change {
|
func batchChange(change *dns.Change, batchSize int) []*dns.Change {
|
||||||
changes := []*dns.Change{}
|
var changes []*dns.Change
|
||||||
|
|
||||||
if batchSize == 0 {
|
if batchSize == 0 {
|
||||||
return append(changes, change)
|
return append(changes, change)
|
||||||
@ -452,7 +450,7 @@ func newRecord(ep *endpoint.Endpoint) *dns.ResourceRecordSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// no annotation results in a Ttl of 0, default to 300 for backwards-compatibility
|
// no annotation results in a Ttl of 0, default to 300 for backwards-compatibility
|
||||||
var ttl int64 = googleRecordTTL
|
var ttl int64 = defaultTTL
|
||||||
if ep.RecordTTL.IsConfigured() {
|
if ep.RecordTTL.IsConfigured() {
|
||||||
ttl = int64(ep.RecordTTL)
|
ttl = int64(ep.RecordTTL)
|
||||||
}
|
}
|
||||||
|
@ -279,12 +279,12 @@ func TestGoogleRecords(t *testing.T) {
|
|||||||
|
|
||||||
func TestGoogleRecordsFilter(t *testing.T) {
|
func TestGoogleRecordsFilter(t *testing.T) {
|
||||||
originalEndpoints := []*endpoint.Endpoint{
|
originalEndpoints := []*endpoint.Endpoint{
|
||||||
endpoint.NewEndpointWithTTL("update-test.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, googleRecordTTL, "8.8.8.8"),
|
endpoint.NewEndpointWithTTL("update-test.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, defaultTTL, "8.8.8.8"),
|
||||||
endpoint.NewEndpointWithTTL("delete-test.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, googleRecordTTL, "8.8.8.8"),
|
endpoint.NewEndpointWithTTL("delete-test.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, defaultTTL, "8.8.8.8"),
|
||||||
endpoint.NewEndpointWithTTL("update-test.zone-2.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, googleRecordTTL, "8.8.4.4"),
|
endpoint.NewEndpointWithTTL("update-test.zone-2.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, defaultTTL, "8.8.4.4"),
|
||||||
endpoint.NewEndpointWithTTL("delete-test.zone-2.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, googleRecordTTL, "8.8.4.4"),
|
endpoint.NewEndpointWithTTL("delete-test.zone-2.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, defaultTTL, "8.8.4.4"),
|
||||||
endpoint.NewEndpointWithTTL("update-test-cname.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeCNAME, googleRecordTTL, "bar.elb.amazonaws.com"),
|
endpoint.NewEndpointWithTTL("update-test-cname.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeCNAME, defaultTTL, "bar.elb.amazonaws.com"),
|
||||||
endpoint.NewEndpointWithTTL("delete-test-cname.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeCNAME, googleRecordTTL, "qux.elb.amazonaws.com"),
|
endpoint.NewEndpointWithTTL("delete-test-cname.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeCNAME, defaultTTL, "qux.elb.amazonaws.com"),
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := newGoogleProvider(
|
provider := newGoogleProvider(
|
||||||
@ -339,12 +339,12 @@ func TestGoogleApplyChanges(t *testing.T) {
|
|||||||
provider.NewZoneIDFilter([]string{""}),
|
provider.NewZoneIDFilter([]string{""}),
|
||||||
false,
|
false,
|
||||||
[]*endpoint.Endpoint{
|
[]*endpoint.Endpoint{
|
||||||
endpoint.NewEndpointWithTTL("update-test.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, googleRecordTTL, "8.8.8.8"),
|
endpoint.NewEndpointWithTTL("update-test.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, defaultTTL, "8.8.8.8"),
|
||||||
endpoint.NewEndpointWithTTL("delete-test.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, googleRecordTTL, "8.8.8.8"),
|
endpoint.NewEndpointWithTTL("delete-test.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, defaultTTL, "8.8.8.8"),
|
||||||
endpoint.NewEndpointWithTTL("update-test-ttl.zone-2.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, endpoint.TTL(10), "8.8.4.4"),
|
endpoint.NewEndpointWithTTL("update-test-ttl.zone-2.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, endpoint.TTL(10), "8.8.4.4"),
|
||||||
endpoint.NewEndpointWithTTL("delete-test.zone-2.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, googleRecordTTL, "8.8.4.4"),
|
endpoint.NewEndpointWithTTL("delete-test.zone-2.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, defaultTTL, "8.8.4.4"),
|
||||||
endpoint.NewEndpointWithTTL("update-test-cname.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeCNAME, googleRecordTTL, "bar.elb.amazonaws.com"),
|
endpoint.NewEndpointWithTTL("update-test-cname.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeCNAME, defaultTTL, "bar.elb.amazonaws.com"),
|
||||||
endpoint.NewEndpointWithTTL("delete-test-cname.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeCNAME, googleRecordTTL, "qux.elb.amazonaws.com"),
|
endpoint.NewEndpointWithTTL("delete-test-cname.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeCNAME, defaultTTL, "qux.elb.amazonaws.com"),
|
||||||
},
|
},
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@ -393,23 +393,23 @@ func TestGoogleApplyChanges(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
validateEndpoints(t, records, []*endpoint.Endpoint{
|
validateEndpoints(t, records, []*endpoint.Endpoint{
|
||||||
endpoint.NewEndpointWithTTL("create-test.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, googleRecordTTL, "8.8.8.8"),
|
endpoint.NewEndpointWithTTL("create-test.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, defaultTTL, "8.8.8.8"),
|
||||||
endpoint.NewEndpointWithTTL("update-test.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, googleRecordTTL, "1.2.3.4"),
|
endpoint.NewEndpointWithTTL("update-test.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, defaultTTL, "1.2.3.4"),
|
||||||
endpoint.NewEndpointWithTTL("create-test-ttl.zone-2.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, endpoint.TTL(15), "8.8.4.4"),
|
endpoint.NewEndpointWithTTL("create-test-ttl.zone-2.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, endpoint.TTL(15), "8.8.4.4"),
|
||||||
endpoint.NewEndpointWithTTL("update-test-ttl.zone-2.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, endpoint.TTL(25), "4.3.2.1"),
|
endpoint.NewEndpointWithTTL("update-test-ttl.zone-2.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, endpoint.TTL(25), "4.3.2.1"),
|
||||||
endpoint.NewEndpointWithTTL("create-test-cname.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeCNAME, googleRecordTTL, "foo.elb.amazonaws.com"),
|
endpoint.NewEndpointWithTTL("create-test-cname.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeCNAME, defaultTTL, "foo.elb.amazonaws.com"),
|
||||||
endpoint.NewEndpointWithTTL("update-test-cname.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeCNAME, googleRecordTTL, "baz.elb.amazonaws.com"),
|
endpoint.NewEndpointWithTTL("update-test-cname.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeCNAME, defaultTTL, "baz.elb.amazonaws.com"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGoogleApplyChangesDryRun(t *testing.T) {
|
func TestGoogleApplyChangesDryRun(t *testing.T) {
|
||||||
originalEndpoints := []*endpoint.Endpoint{
|
originalEndpoints := []*endpoint.Endpoint{
|
||||||
endpoint.NewEndpointWithTTL("update-test.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, googleRecordTTL, "8.8.8.8"),
|
endpoint.NewEndpointWithTTL("update-test.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, defaultTTL, "8.8.8.8"),
|
||||||
endpoint.NewEndpointWithTTL("delete-test.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, googleRecordTTL, "8.8.8.8"),
|
endpoint.NewEndpointWithTTL("delete-test.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, defaultTTL, "8.8.8.8"),
|
||||||
endpoint.NewEndpointWithTTL("update-test.zone-2.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, googleRecordTTL, "8.8.4.4"),
|
endpoint.NewEndpointWithTTL("update-test.zone-2.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, defaultTTL, "8.8.4.4"),
|
||||||
endpoint.NewEndpointWithTTL("delete-test.zone-2.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, googleRecordTTL, "8.8.4.4"),
|
endpoint.NewEndpointWithTTL("delete-test.zone-2.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeA, defaultTTL, "8.8.4.4"),
|
||||||
endpoint.NewEndpointWithTTL("update-test-cname.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeCNAME, googleRecordTTL, "bar.elb.amazonaws.com"),
|
endpoint.NewEndpointWithTTL("update-test-cname.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeCNAME, defaultTTL, "bar.elb.amazonaws.com"),
|
||||||
endpoint.NewEndpointWithTTL("delete-test-cname.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeCNAME, googleRecordTTL, "qux.elb.amazonaws.com"),
|
endpoint.NewEndpointWithTTL("delete-test-cname.zone-1.ext-dns-test-2.gcp.zalan.do", endpoint.RecordTypeCNAME, defaultTTL, "qux.elb.amazonaws.com"),
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := newGoogleProvider(t, endpoint.NewDomainFilter([]string{"ext-dns-test-2.gcp.zalan.do."}), provider.NewZoneIDFilter([]string{""}), true, originalEndpoints, nil, nil)
|
provider := newGoogleProvider(t, endpoint.NewDomainFilter([]string{"ext-dns-test-2.gcp.zalan.do."}), provider.NewZoneIDFilter([]string{""}), true, originalEndpoints, nil, nil)
|
||||||
|
@ -61,8 +61,8 @@ const (
|
|||||||
recordDelete = "DELETE"
|
recordDelete = "DELETE"
|
||||||
// recordUpdate is a ChangeAction enum value
|
// recordUpdate is a ChangeAction enum value
|
||||||
recordUpdate = "UPDATE"
|
recordUpdate = "UPDATE"
|
||||||
// defaultPublicRecordTTL 1 = automatic
|
// defaultTTL 1 = automatic
|
||||||
defaultPublicRecordTTL = 1
|
defaultTTL = 1
|
||||||
|
|
||||||
proxyFilter = "ibmcloud-proxied"
|
proxyFilter = "ibmcloud-proxied"
|
||||||
vpcFilter = "ibmcloud-vpc"
|
vpcFilter = "ibmcloud-vpc"
|
||||||
@ -244,7 +244,7 @@ func (c *ibmcloudConfig) Validate(authenticator core.Authenticator, domainFilter
|
|||||||
return service, isPrivate, fmt.Errorf("failed to initialize ibmcloud public zones client: %v", err)
|
return service, isPrivate, fmt.Errorf("failed to initialize ibmcloud public zones client: %v", err)
|
||||||
}
|
}
|
||||||
if c.Endpoint != "" {
|
if c.Endpoint != "" {
|
||||||
service.publicZonesService.SetServiceURL(c.Endpoint)
|
_ = service.publicZonesService.SetServiceURL(c.Endpoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
zonesResp, _, err := service.publicZonesService.ListZones(&zonesv1.ListZonesOptions{})
|
zonesResp, _, err := service.publicZonesService.ListZones(&zonesv1.ListZonesOptions{})
|
||||||
@ -277,7 +277,7 @@ func (c *ibmcloudConfig) Validate(authenticator core.Authenticator, domainFilter
|
|||||||
return service, isPrivate, fmt.Errorf("failed to initialize ibmcloud public records client: %v", err)
|
return service, isPrivate, fmt.Errorf("failed to initialize ibmcloud public records client: %v", err)
|
||||||
}
|
}
|
||||||
if c.Endpoint != "" {
|
if c.Endpoint != "" {
|
||||||
service.publicRecordsService.SetServiceURL(c.Endpoint)
|
_ = service.publicRecordsService.SetServiceURL(c.Endpoint)
|
||||||
}
|
}
|
||||||
case strings.Contains(crn.ServiceName, "dns-svcs"):
|
case strings.Contains(crn.ServiceName, "dns-svcs"):
|
||||||
isPrivate = true
|
isPrivate = true
|
||||||
@ -289,7 +289,7 @@ func (c *ibmcloudConfig) Validate(authenticator core.Authenticator, domainFilter
|
|||||||
return service, isPrivate, fmt.Errorf("failed to initialize ibmcloud private records client: %v", err)
|
return service, isPrivate, fmt.Errorf("failed to initialize ibmcloud private records client: %v", err)
|
||||||
}
|
}
|
||||||
if c.Endpoint != "" {
|
if c.Endpoint != "" {
|
||||||
service.privateDNSService.SetServiceURL(c.Endpoint)
|
_ = service.privateDNSService.SetServiceURL(c.Endpoint)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return service, isPrivate, fmt.Errorf("IBM Cloud instance crn is not provided or invalid dns crn : %s", c.CRN)
|
return service, isPrivate, fmt.Errorf("IBM Cloud instance crn is not provided or invalid dns crn : %s", c.CRN)
|
||||||
@ -322,7 +322,7 @@ func NewIBMCloudProvider(configFile string, domainFilter endpoint.DomainFilter,
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := &IBMCloudProvider{
|
return &IBMCloudProvider{
|
||||||
Client: client,
|
Client: client,
|
||||||
source: source,
|
source: source,
|
||||||
domainFilter: domainFilter,
|
domainFilter: domainFilter,
|
||||||
@ -331,8 +331,7 @@ func NewIBMCloudProvider(configFile string, domainFilter endpoint.DomainFilter,
|
|||||||
privateZone: isPrivate,
|
privateZone: isPrivate,
|
||||||
proxiedByDefault: proxiedByDefault,
|
proxiedByDefault: proxiedByDefault,
|
||||||
DryRun: dryRun,
|
DryRun: dryRun,
|
||||||
}
|
}, nil
|
||||||
return provider, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Records gets the current records.
|
// Records gets the current records.
|
||||||
@ -351,9 +350,9 @@ func (p *IBMCloudProvider) Records(ctx context.Context) (endpoints []*endpoint.E
|
|||||||
func (p *IBMCloudProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
|
func (p *IBMCloudProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
|
||||||
log.Debugln("applying change...")
|
log.Debugln("applying change...")
|
||||||
ibmcloudChanges := []*ibmcloudChange{}
|
ibmcloudChanges := []*ibmcloudChange{}
|
||||||
for _, endpoint := range changes.Create {
|
for _, et := range changes.Create {
|
||||||
for _, target := range endpoint.Targets {
|
for _, target := range et.Targets {
|
||||||
ibmcloudChanges = append(ibmcloudChanges, p.newIBMCloudChange(recordCreate, endpoint, target))
|
ibmcloudChanges = append(ibmcloudChanges, p.newIBMCloudChange(recordCreate, et, target))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,9 +375,9 @@ func (p *IBMCloudProvider) ApplyChanges(ctx context.Context, changes *plan.Chang
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, endpoint := range changes.Delete {
|
for _, et := range changes.Delete {
|
||||||
for _, target := range endpoint.Targets {
|
for _, target := range et.Targets {
|
||||||
ibmcloudChanges = append(ibmcloudChanges, p.newIBMCloudChange(recordDelete, endpoint, target))
|
ibmcloudChanges = append(ibmcloudChanges, p.newIBMCloudChange(recordDelete, et, target))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -680,15 +679,15 @@ func (p *IBMCloudProvider) privateRecords(ctx context.Context) ([]*endpoint.Endp
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// Filter VPC annoation for private zone active
|
// Filter VPC annoation for private zone active
|
||||||
for _, source := range sources {
|
for _, src := range sources {
|
||||||
vpc = checkVPCAnnotation(source)
|
vpc = checkVPCAnnotation(src)
|
||||||
if len(vpc) > 0 {
|
if len(vpc) > 0 {
|
||||||
log.Debugf("VPC found: %s", vpc)
|
log.Debugf("VPC found: %s", vpc)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints := []*endpoint.Endpoint{}
|
var endpoints []*endpoint.Endpoint
|
||||||
for _, zone := range zones {
|
for _, zone := range zones {
|
||||||
if len(vpc) > 0 && *zone.State == zoneStatePendingNetwork {
|
if len(vpc) > 0 && *zone.State == zoneStatePendingNetwork {
|
||||||
log.Debugf("active zone: %s", *zone.ID)
|
log.Debugf("active zone: %s", *zone.ID)
|
||||||
@ -730,7 +729,7 @@ GETRECORDS:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *IBMCloudProvider) groupPrivateRecords(records []dnssvcsv1.ResourceRecord) []*endpoint.Endpoint {
|
func (p *IBMCloudProvider) groupPrivateRecords(records []dnssvcsv1.ResourceRecord) []*endpoint.Endpoint {
|
||||||
endpoints := []*endpoint.Endpoint{}
|
var endpoints []*endpoint.Endpoint
|
||||||
// group supported records by name and type
|
// group supported records by name and type
|
||||||
groups := map[string][]dnssvcsv1.ResourceRecord{}
|
groups := map[string][]dnssvcsv1.ResourceRecord{}
|
||||||
for _, r := range records {
|
for _, r := range records {
|
||||||
@ -806,7 +805,7 @@ func (p *IBMCloudProvider) getPrivateRecordID(records []dnssvcsv1.ResourceRecord
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *IBMCloudProvider) newIBMCloudChange(action string, endpoint *endpoint.Endpoint, target string) *ibmcloudChange {
|
func (p *IBMCloudProvider) newIBMCloudChange(action string, endpoint *endpoint.Endpoint, target string) *ibmcloudChange {
|
||||||
ttl := defaultPublicRecordTTL
|
ttl := defaultTTL
|
||||||
proxied := shouldBeProxied(endpoint, p.proxiedByDefault)
|
proxied := shouldBeProxied(endpoint, p.proxiedByDefault)
|
||||||
|
|
||||||
if endpoint.RecordTTL.IsConfigured() {
|
if endpoint.RecordTTL.IsConfigured() {
|
||||||
@ -984,7 +983,7 @@ func checkVPCAnnotation(endpoint *endpoint.Endpoint) string {
|
|||||||
for _, v := range endpoint.ProviderSpecific {
|
for _, v := range endpoint.ProviderSpecific {
|
||||||
if v.Name == vpcFilter {
|
if v.Name == vpcFilter {
|
||||||
vpcCrn, err := crn.Parse(v.Value)
|
vpcCrn, err := crn.Parse(v.Value)
|
||||||
if vpcCrn.ResourceType != "vpc" || err != nil {
|
if err != nil || vpcCrn.ResourceType != "vpc" {
|
||||||
log.Errorf("Failed to parse vpc [%s]: %v", v.Value, err)
|
log.Errorf("Failed to parse vpc [%s]: %v", v.Value, err)
|
||||||
} else {
|
} else {
|
||||||
vpc = v.Value
|
vpc = v.Value
|
||||||
@ -995,6 +994,7 @@ func checkVPCAnnotation(endpoint *endpoint.Endpoint) string {
|
|||||||
return vpc
|
return vpc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: could be shared function
|
||||||
func isNil(i interface{}) bool {
|
func isNil(i interface{}) bool {
|
||||||
if i == nil {
|
if i == nil {
|
||||||
return true
|
return true
|
||||||
@ -1002,6 +1002,7 @@ func isNil(i interface{}) bool {
|
|||||||
switch reflect.TypeOf(i).Kind() {
|
switch reflect.TypeOf(i).Kind() {
|
||||||
case reflect.Ptr, reflect.Map, reflect.Array, reflect.Chan, reflect.Slice:
|
case reflect.Ptr, reflect.Map, reflect.Array, reflect.Chan, reflect.Slice:
|
||||||
return reflect.ValueOf(i).IsNil()
|
return reflect.ValueOf(i).IsNil()
|
||||||
|
default:
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
@ -96,15 +96,14 @@ func NewLinodeProvider(domainFilter endpoint.DomainFilter, dryRun bool) (*Linode
|
|||||||
linodeClient := linodego.NewClient(oauth2Client)
|
linodeClient := linodego.NewClient(oauth2Client)
|
||||||
linodeClient.SetUserAgent(fmt.Sprintf("%s linodego/%s", externaldns.UserAgent(), linodego.Version))
|
linodeClient.SetUserAgent(fmt.Sprintf("%s linodego/%s", externaldns.UserAgent(), linodego.Version))
|
||||||
|
|
||||||
provider := &LinodeProvider{
|
return &LinodeProvider{
|
||||||
Client: &linodeClient,
|
Client: &linodeClient,
|
||||||
domainFilter: domainFilter,
|
domainFilter: domainFilter,
|
||||||
DryRun: dryRun,
|
DryRun: dryRun,
|
||||||
}
|
}, nil
|
||||||
return provider, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zones returns the list of hosted zones.
|
// Zones return the list of hosted zones.
|
||||||
func (p *LinodeProvider) Zones(ctx context.Context) ([]linodego.Domain, error) {
|
func (p *LinodeProvider) Zones(ctx context.Context) ([]linodego.Domain, error) {
|
||||||
zones, err := p.fetchZones(ctx)
|
zones, err := p.fetchZones(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -40,8 +40,8 @@ const (
|
|||||||
ns1Delete = "DELETE"
|
ns1Delete = "DELETE"
|
||||||
// ns1Update is a ChangeAction enum value
|
// ns1Update is a ChangeAction enum value
|
||||||
ns1Update = "UPDATE"
|
ns1Update = "UPDATE"
|
||||||
// ns1DefaultTTL is the default ttl for ttls that are not set
|
// defaultTTL is the default ttl for ttls that are not set
|
||||||
ns1DefaultTTL = 10
|
defaultTTL = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
// NS1DomainClient is a subset of the NS1 API the the provider uses, to ease testing
|
// NS1DomainClient is a subset of the NS1 API the the provider uses, to ease testing
|
||||||
@ -136,13 +136,12 @@ func newNS1ProviderWithHTTPClient(config NS1Config, client *http.Client) (*NS1Pr
|
|||||||
|
|
||||||
apiClient := api.NewClient(client, clientArgs...)
|
apiClient := api.NewClient(client, clientArgs...)
|
||||||
|
|
||||||
provider := &NS1Provider{
|
return &NS1Provider{
|
||||||
client: NS1DomainService{apiClient},
|
client: NS1DomainService{apiClient},
|
||||||
domainFilter: config.DomainFilter,
|
domainFilter: config.DomainFilter,
|
||||||
zoneIDFilter: config.ZoneIDFilter,
|
zoneIDFilter: config.ZoneIDFilter,
|
||||||
minTTLSeconds: config.MinTTLSeconds,
|
minTTLSeconds: config.MinTTLSeconds,
|
||||||
}
|
}, nil
|
||||||
return provider, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Records returns the endpoints this provider knows about
|
// Records returns the endpoints this provider knows about
|
||||||
@ -184,7 +183,7 @@ func (p *NS1Provider) ns1BuildRecord(zoneName string, change *ns1Change) *dns.Re
|
|||||||
record.AddAnswer(dns.NewAnswer(strings.Split(v, " ")))
|
record.AddAnswer(dns.NewAnswer(strings.Split(v, " ")))
|
||||||
}
|
}
|
||||||
// set default ttl, but respect minTTLSeconds
|
// set default ttl, but respect minTTLSeconds
|
||||||
ttl := ns1DefaultTTL
|
ttl := defaultTTL
|
||||||
if p.minTTLSeconds > ttl {
|
if p.minTTLSeconds > ttl {
|
||||||
ttl = p.minTTLSeconds
|
ttl = p.minTTLSeconds
|
||||||
}
|
}
|
||||||
@ -257,7 +256,7 @@ func (p *NS1Provider) zonesFiltered() ([]*dns.Zone, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
toReturn := []*dns.Zone{}
|
var toReturn []*dns.Zone
|
||||||
|
|
||||||
for _, z := range zones {
|
for _, z := range zones {
|
||||||
if p.domainFilter.Match(z.Zone) && p.zoneIDFilter.Match(z.ID) {
|
if p.domainFilter.Match(z.Zone) && p.zoneIDFilter.Match(z.ID) {
|
||||||
@ -292,10 +291,10 @@ func (p *NS1Provider) ApplyChanges(ctx context.Context, changes *plan.Changes) e
|
|||||||
func newNS1Changes(action string, endpoints []*endpoint.Endpoint) []*ns1Change {
|
func newNS1Changes(action string, endpoints []*endpoint.Endpoint) []*ns1Change {
|
||||||
changes := make([]*ns1Change, 0, len(endpoints))
|
changes := make([]*ns1Change, 0, len(endpoints))
|
||||||
|
|
||||||
for _, endpoint := range endpoints {
|
for _, ep := range endpoints {
|
||||||
changes = append(changes, &ns1Change{
|
changes = append(changes, &ns1Change{
|
||||||
Action: action,
|
Action: action,
|
||||||
Endpoint: endpoint,
|
Endpoint: ep,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -18,16 +18,16 @@ package oci
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
yaml "github.com/goccy/go-yaml"
|
"github.com/goccy/go-yaml"
|
||||||
"github.com/oracle/oci-go-sdk/v65/common"
|
"github.com/oracle/oci-go-sdk/v65/common"
|
||||||
"github.com/oracle/oci-go-sdk/v65/common/auth"
|
"github.com/oracle/oci-go-sdk/v65/common/auth"
|
||||||
"github.com/oracle/oci-go-sdk/v65/dns"
|
"github.com/oracle/oci-go-sdk/v65/dns"
|
||||||
"github.com/pkg/errors"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"sigs.k8s.io/external-dns/endpoint"
|
"sigs.k8s.io/external-dns/endpoint"
|
||||||
@ -35,7 +35,7 @@ import (
|
|||||||
"sigs.k8s.io/external-dns/provider"
|
"sigs.k8s.io/external-dns/provider"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ociRecordTTL = 300
|
const defaultTTL = 300
|
||||||
|
|
||||||
// OCIAuthConfig holds connection parameters for the OCI API.
|
// OCIAuthConfig holds connection parameters for the OCI API.
|
||||||
type OCIAuthConfig struct {
|
type OCIAuthConfig struct {
|
||||||
@ -153,7 +153,7 @@ func (p *OCIProvider) zones(ctx context.Context) (map[string]dns.ZoneSummary, er
|
|||||||
}
|
}
|
||||||
zones := make(map[string]dns.ZoneSummary)
|
zones := make(map[string]dns.ZoneSummary)
|
||||||
scopes := []dns.GetZoneScopeEnum{dns.GetZoneScopeEnum(p.zoneScope)}
|
scopes := []dns.GetZoneScopeEnum{dns.GetZoneScopeEnum(p.zoneScope)}
|
||||||
// If zone scope is empty, list all zones types.
|
// If the zone scope is empty, list all zones types.
|
||||||
if p.zoneScope == "" {
|
if p.zoneScope == "" {
|
||||||
scopes = dns.GetGetZoneScopeEnumValues()
|
scopes = dns.GetGetZoneScopeEnumValues()
|
||||||
}
|
}
|
||||||
@ -186,13 +186,13 @@ func mergeEndpointsMultiTargets(endpoints []*endpoint.Endpoint) []*endpoint.Endp
|
|||||||
|
|
||||||
// Otherwise, create a new list of endpoints with the consolidated targets.
|
// Otherwise, create a new list of endpoints with the consolidated targets.
|
||||||
var mergedEndpoints []*endpoint.Endpoint
|
var mergedEndpoints []*endpoint.Endpoint
|
||||||
for _, endpoints := range endpointsByNameType {
|
for _, ep := range endpointsByNameType {
|
||||||
dnsName := endpoints[0].DNSName
|
dnsName := ep[0].DNSName
|
||||||
recordType := endpoints[0].RecordType
|
recordType := ep[0].RecordType
|
||||||
recordTTL := endpoints[0].RecordTTL
|
recordTTL := ep[0].RecordTTL
|
||||||
|
|
||||||
targets := make([]string, len(endpoints))
|
targets := make([]string, len(ep))
|
||||||
for i, e := range endpoints {
|
for i, e := range ep {
|
||||||
targets[i] = e.Targets[0]
|
targets[i] = e.Targets[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,7 +232,7 @@ func (p *OCIProvider) addPaginatedZones(ctx context.Context, zones map[string]dn
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *OCIProvider) newFilteredRecordOperations(endpoints []*endpoint.Endpoint, opType dns.RecordOperationOperationEnum) []dns.RecordOperation {
|
func (p *OCIProvider) newFilteredRecordOperations(endpoints []*endpoint.Endpoint, opType dns.RecordOperationOperationEnum) []dns.RecordOperation {
|
||||||
ops := []dns.RecordOperation{}
|
var ops []dns.RecordOperation
|
||||||
for _, ep := range endpoints {
|
for _, ep := range endpoints {
|
||||||
if ep == nil {
|
if ep == nil {
|
||||||
continue
|
continue
|
||||||
@ -261,7 +261,7 @@ func (p *OCIProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error)
|
|||||||
return nil, provider.NewSoftError(fmt.Errorf("getting zones: %w", err))
|
return nil, provider.NewSoftError(fmt.Errorf("getting zones: %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints := []*endpoint.Endpoint{}
|
var endpoints []*endpoint.Endpoint
|
||||||
for _, zone := range zones {
|
for _, zone := range zones {
|
||||||
var page *string
|
var page *string
|
||||||
for {
|
for {
|
||||||
@ -303,7 +303,7 @@ func (p *OCIProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error)
|
|||||||
func (p *OCIProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
|
func (p *OCIProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
|
||||||
log.Debugf("Processing changes: %+v", changes)
|
log.Debugf("Processing changes: %+v", changes)
|
||||||
|
|
||||||
ops := []dns.RecordOperation{}
|
var ops []dns.RecordOperation
|
||||||
ops = append(ops, p.newFilteredRecordOperations(changes.Create, dns.RecordOperationOperationAdd)...)
|
ops = append(ops, p.newFilteredRecordOperations(changes.Create, dns.RecordOperationOperationAdd)...)
|
||||||
|
|
||||||
ops = append(ops, p.newFilteredRecordOperations(changes.UpdateNew, dns.RecordOperationOperationAdd)...)
|
ops = append(ops, p.newFilteredRecordOperations(changes.UpdateNew, dns.RecordOperationOperationAdd)...)
|
||||||
@ -349,7 +349,7 @@ func (p *OCIProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) e
|
|||||||
|
|
||||||
// AdjustEndpoints modifies the endpoints as needed by the specific provider
|
// AdjustEndpoints modifies the endpoints as needed by the specific provider
|
||||||
func (p *OCIProvider) AdjustEndpoints(endpoints []*endpoint.Endpoint) ([]*endpoint.Endpoint, error) {
|
func (p *OCIProvider) AdjustEndpoints(endpoints []*endpoint.Endpoint) ([]*endpoint.Endpoint, error) {
|
||||||
adjustedEndpoints := []*endpoint.Endpoint{}
|
var adjustedEndpoints []*endpoint.Endpoint
|
||||||
for _, e := range endpoints {
|
for _, e := range endpoints {
|
||||||
// OCI DNS does not support the set-identifier attribute, so we remove it to avoid plan failure
|
// OCI DNS does not support the set-identifier attribute, so we remove it to avoid plan failure
|
||||||
if e.SetIdentifier != "" {
|
if e.SetIdentifier != "" {
|
||||||
@ -370,7 +370,7 @@ func newRecordOperation(ep *endpoint.Endpoint, opType dns.RecordOperationOperati
|
|||||||
}
|
}
|
||||||
rdata := strings.Join(targets, " ")
|
rdata := strings.Join(targets, " ")
|
||||||
|
|
||||||
ttl := ociRecordTTL
|
ttl := defaultTTL
|
||||||
if ep.RecordTTL.IsConfigured() {
|
if ep.RecordTTL.IsConfigured() {
|
||||||
ttl = int(ep.RecordTTL)
|
ttl = int(ep.RecordTTL)
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,8 @@ package oci
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@ -25,7 +27,6 @@ import (
|
|||||||
|
|
||||||
"github.com/oracle/oci-go-sdk/v65/common"
|
"github.com/oracle/oci-go-sdk/v65/common"
|
||||||
"github.com/oracle/oci-go-sdk/v65/dns"
|
"github.com/oracle/oci-go-sdk/v65/dns"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"sigs.k8s.io/external-dns/endpoint"
|
"sigs.k8s.io/external-dns/endpoint"
|
||||||
@ -93,12 +94,12 @@ func (c *mockOCIDNSClient) GetZoneRecords(ctx context.Context, request dns.GetZo
|
|||||||
Domain: common.String("foo.foo.com"),
|
Domain: common.String("foo.foo.com"),
|
||||||
Rdata: common.String("127.0.0.1"),
|
Rdata: common.String("127.0.0.1"),
|
||||||
Rtype: common.String(endpoint.RecordTypeA),
|
Rtype: common.String(endpoint.RecordTypeA),
|
||||||
Ttl: common.Int(ociRecordTTL),
|
Ttl: common.Int(defaultTTL),
|
||||||
}, {
|
}, {
|
||||||
Domain: common.String("foo.foo.com"),
|
Domain: common.String("foo.foo.com"),
|
||||||
Rdata: common.String("heritage=external-dns,external-dns/owner=default,external-dns/resource=service/default/my-svc"),
|
Rdata: common.String("heritage=external-dns,external-dns/owner=default,external-dns/resource=service/default/my-svc"),
|
||||||
Rtype: common.String(endpoint.RecordTypeTXT),
|
Rtype: common.String(endpoint.RecordTypeTXT),
|
||||||
Ttl: common.Int(ociRecordTTL),
|
Ttl: common.Int(defaultTTL),
|
||||||
}}
|
}}
|
||||||
response.OpcNextPage = common.String("1")
|
response.OpcNextPage = common.String("1")
|
||||||
} else {
|
} else {
|
||||||
@ -106,7 +107,7 @@ func (c *mockOCIDNSClient) GetZoneRecords(ctx context.Context, request dns.GetZo
|
|||||||
Domain: common.String("bar.foo.com"),
|
Domain: common.String("bar.foo.com"),
|
||||||
Rdata: common.String("bar.com."),
|
Rdata: common.String("bar.com."),
|
||||||
Rtype: common.String(endpoint.RecordTypeCNAME),
|
Rtype: common.String(endpoint.RecordTypeCNAME),
|
||||||
Ttl: common.Int(ociRecordTTL),
|
Ttl: common.Int(defaultTTL),
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
case "ocid1.dns-zone.oc1..502aeddba262b92fd13ed7874f6f1404":
|
case "ocid1.dns-zone.oc1..502aeddba262b92fd13ed7874f6f1404":
|
||||||
@ -115,7 +116,7 @@ func (c *mockOCIDNSClient) GetZoneRecords(ctx context.Context, request dns.GetZo
|
|||||||
Domain: common.String("foo.bar.com"),
|
Domain: common.String("foo.bar.com"),
|
||||||
Rdata: common.String("127.0.0.1"),
|
Rdata: common.String("127.0.0.1"),
|
||||||
Rtype: common.String(endpoint.RecordTypeA),
|
Rtype: common.String(endpoint.RecordTypeA),
|
||||||
Ttl: common.Int(ociRecordTTL),
|
Ttl: common.Int(defaultTTL),
|
||||||
}}
|
}}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -329,26 +330,26 @@ func TestOCIRecords(t *testing.T) {
|
|||||||
domainFilter: endpoint.NewDomainFilter([]string{""}),
|
domainFilter: endpoint.NewDomainFilter([]string{""}),
|
||||||
zoneIDFilter: provider.NewZoneIDFilter([]string{""}),
|
zoneIDFilter: provider.NewZoneIDFilter([]string{""}),
|
||||||
expected: []*endpoint.Endpoint{
|
expected: []*endpoint.Endpoint{
|
||||||
endpoint.NewEndpointWithTTL("foo.foo.com", endpoint.RecordTypeA, endpoint.TTL(ociRecordTTL), "127.0.0.1"),
|
endpoint.NewEndpointWithTTL("foo.foo.com", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "127.0.0.1"),
|
||||||
endpoint.NewEndpointWithTTL("foo.foo.com", endpoint.RecordTypeTXT, endpoint.TTL(ociRecordTTL), "heritage=external-dns,external-dns/owner=default,external-dns/resource=service/default/my-svc"),
|
endpoint.NewEndpointWithTTL("foo.foo.com", endpoint.RecordTypeTXT, endpoint.TTL(defaultTTL), "heritage=external-dns,external-dns/owner=default,external-dns/resource=service/default/my-svc"),
|
||||||
endpoint.NewEndpointWithTTL("bar.foo.com", endpoint.RecordTypeCNAME, endpoint.TTL(ociRecordTTL), "bar.com."),
|
endpoint.NewEndpointWithTTL("bar.foo.com", endpoint.RecordTypeCNAME, endpoint.TTL(defaultTTL), "bar.com."),
|
||||||
endpoint.NewEndpointWithTTL("foo.bar.com", endpoint.RecordTypeA, endpoint.TTL(ociRecordTTL), "127.0.0.1"),
|
endpoint.NewEndpointWithTTL("foo.bar.com", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "127.0.0.1"),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "DomainFilter_foo.com",
|
name: "DomainFilter_foo.com",
|
||||||
domainFilter: endpoint.NewDomainFilter([]string{"foo.com"}),
|
domainFilter: endpoint.NewDomainFilter([]string{"foo.com"}),
|
||||||
zoneIDFilter: provider.NewZoneIDFilter([]string{""}),
|
zoneIDFilter: provider.NewZoneIDFilter([]string{""}),
|
||||||
expected: []*endpoint.Endpoint{
|
expected: []*endpoint.Endpoint{
|
||||||
endpoint.NewEndpointWithTTL("foo.foo.com", endpoint.RecordTypeA, endpoint.TTL(ociRecordTTL), "127.0.0.1"),
|
endpoint.NewEndpointWithTTL("foo.foo.com", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "127.0.0.1"),
|
||||||
endpoint.NewEndpointWithTTL("foo.foo.com", endpoint.RecordTypeTXT, endpoint.TTL(ociRecordTTL), "heritage=external-dns,external-dns/owner=default,external-dns/resource=service/default/my-svc"),
|
endpoint.NewEndpointWithTTL("foo.foo.com", endpoint.RecordTypeTXT, endpoint.TTL(defaultTTL), "heritage=external-dns,external-dns/owner=default,external-dns/resource=service/default/my-svc"),
|
||||||
endpoint.NewEndpointWithTTL("bar.foo.com", endpoint.RecordTypeCNAME, endpoint.TTL(ociRecordTTL), "bar.com."),
|
endpoint.NewEndpointWithTTL("bar.foo.com", endpoint.RecordTypeCNAME, endpoint.TTL(defaultTTL), "bar.com."),
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "ZoneIDFilter_ocid1.dns-zone.oc1..502aeddba262b92fd13ed7874f6f1404",
|
name: "ZoneIDFilter_ocid1.dns-zone.oc1..502aeddba262b92fd13ed7874f6f1404",
|
||||||
domainFilter: endpoint.NewDomainFilter([]string{""}),
|
domainFilter: endpoint.NewDomainFilter([]string{""}),
|
||||||
zoneIDFilter: provider.NewZoneIDFilter([]string{"ocid1.dns-zone.oc1..502aeddba262b92fd13ed7874f6f1404"}),
|
zoneIDFilter: provider.NewZoneIDFilter([]string{"ocid1.dns-zone.oc1..502aeddba262b92fd13ed7874f6f1404"}),
|
||||||
expected: []*endpoint.Endpoint{
|
expected: []*endpoint.Endpoint{
|
||||||
endpoint.NewEndpointWithTTL("foo.bar.com", endpoint.RecordTypeA, endpoint.TTL(ociRecordTTL), "127.0.0.1"),
|
endpoint.NewEndpointWithTTL("foo.bar.com", endpoint.RecordTypeA, endpoint.TTL(defaultTTL), "127.0.0.1"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -375,7 +376,7 @@ func TestNewRecordOperation(t *testing.T) {
|
|||||||
ep: endpoint.NewEndpointWithTTL(
|
ep: endpoint.NewEndpointWithTTL(
|
||||||
"foo.foo.com",
|
"foo.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"127.0.0.1"),
|
"127.0.0.1"),
|
||||||
expected: dns.RecordOperation{
|
expected: dns.RecordOperation{
|
||||||
Domain: common.String("foo.foo.com"),
|
Domain: common.String("foo.foo.com"),
|
||||||
@ -390,7 +391,7 @@ func TestNewRecordOperation(t *testing.T) {
|
|||||||
ep: endpoint.NewEndpointWithTTL(
|
ep: endpoint.NewEndpointWithTTL(
|
||||||
"foo.foo.com",
|
"foo.foo.com",
|
||||||
endpoint.RecordTypeTXT,
|
endpoint.RecordTypeTXT,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/default/my-svc"),
|
"heritage=external-dns,external-dns/owner=default,external-dns/resource=service/default/my-svc"),
|
||||||
expected: dns.RecordOperation{
|
expected: dns.RecordOperation{
|
||||||
Domain: common.String("foo.foo.com"),
|
Domain: common.String("foo.foo.com"),
|
||||||
@ -405,7 +406,7 @@ func TestNewRecordOperation(t *testing.T) {
|
|||||||
ep: endpoint.NewEndpointWithTTL(
|
ep: endpoint.NewEndpointWithTTL(
|
||||||
"foo.foo.com",
|
"foo.foo.com",
|
||||||
endpoint.RecordTypeCNAME,
|
endpoint.RecordTypeCNAME,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"bar.com."),
|
"bar.com."),
|
||||||
expected: dns.RecordOperation{
|
expected: dns.RecordOperation{
|
||||||
Domain: common.String("foo.foo.com"),
|
Domain: common.String("foo.foo.com"),
|
||||||
@ -621,7 +622,7 @@ func (c *mutableMockOCIDNSClient) PatchZoneRecords(ctx context.Context, request
|
|||||||
case dns.RecordOperationOperationRemove:
|
case dns.RecordOperationOperationRemove:
|
||||||
delete(records, k)
|
delete(records, k)
|
||||||
default:
|
default:
|
||||||
err = errors.Errorf("unsupported operation %q", op.Operation)
|
err = fmt.Errorf("unsupported operation %q", op.Operation)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -640,12 +641,12 @@ func TestMutableMockOCIDNSClient(t *testing.T) {
|
|||||||
Domain: common.String("foo.foo.com"),
|
Domain: common.String("foo.foo.com"),
|
||||||
Rdata: common.String("127.0.0.1"),
|
Rdata: common.String("127.0.0.1"),
|
||||||
Rtype: common.String(endpoint.RecordTypeA),
|
Rtype: common.String(endpoint.RecordTypeA),
|
||||||
Ttl: common.Int(ociRecordTTL),
|
Ttl: common.Int(defaultTTL),
|
||||||
}, {
|
}, {
|
||||||
Domain: common.String("foo.foo.com"),
|
Domain: common.String("foo.foo.com"),
|
||||||
Rdata: common.String("heritage=external-dns,external-dns/owner=default,external-dns/resource=service/default/my-svc"),
|
Rdata: common.String("heritage=external-dns,external-dns/owner=default,external-dns/resource=service/default/my-svc"),
|
||||||
Rtype: common.String(endpoint.RecordTypeTXT),
|
Rtype: common.String(endpoint.RecordTypeTXT),
|
||||||
Ttl: common.Int(ociRecordTTL),
|
Ttl: common.Int(defaultTTL),
|
||||||
}},
|
}},
|
||||||
}
|
}
|
||||||
client := newMutableMockOCIDNSClient(zones, records)
|
client := newMutableMockOCIDNSClient(zones, records)
|
||||||
@ -732,14 +733,14 @@ func TestOCIApplyChanges(t *testing.T) {
|
|||||||
Create: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
Create: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"foo.foo.com",
|
"foo.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
)},
|
)},
|
||||||
},
|
},
|
||||||
expectedEndpoints: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
expectedEndpoints: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"foo.foo.com",
|
"foo.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
)},
|
)},
|
||||||
}, {
|
}, {
|
||||||
@ -753,26 +754,26 @@ func TestOCIApplyChanges(t *testing.T) {
|
|||||||
Domain: common.String("foo.foo.com"),
|
Domain: common.String("foo.foo.com"),
|
||||||
Rdata: common.String("127.0.0.1"),
|
Rdata: common.String("127.0.0.1"),
|
||||||
Rtype: common.String(endpoint.RecordTypeA),
|
Rtype: common.String(endpoint.RecordTypeA),
|
||||||
Ttl: common.Int(ociRecordTTL),
|
Ttl: common.Int(defaultTTL),
|
||||||
}, {
|
}, {
|
||||||
Domain: common.String("foo.foo.com"),
|
Domain: common.String("foo.foo.com"),
|
||||||
Rdata: common.String("heritage=external-dns,external-dns/owner=default,external-dns/resource=service/default/my-svc"),
|
Rdata: common.String("heritage=external-dns,external-dns/owner=default,external-dns/resource=service/default/my-svc"),
|
||||||
Rtype: common.String(endpoint.RecordTypeTXT),
|
Rtype: common.String(endpoint.RecordTypeTXT),
|
||||||
Ttl: common.Int(ociRecordTTL),
|
Ttl: common.Int(defaultTTL),
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
changes: &plan.Changes{
|
changes: &plan.Changes{
|
||||||
Delete: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
Delete: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"foo.foo.com",
|
"foo.foo.com",
|
||||||
endpoint.RecordTypeTXT,
|
endpoint.RecordTypeTXT,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
)},
|
)},
|
||||||
},
|
},
|
||||||
expectedEndpoints: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
expectedEndpoints: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"foo.foo.com",
|
"foo.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
)},
|
)},
|
||||||
}, {
|
}, {
|
||||||
@ -786,27 +787,27 @@ func TestOCIApplyChanges(t *testing.T) {
|
|||||||
Domain: common.String("foo.foo.com"),
|
Domain: common.String("foo.foo.com"),
|
||||||
Rdata: common.String("127.0.0.1"),
|
Rdata: common.String("127.0.0.1"),
|
||||||
Rtype: common.String(endpoint.RecordTypeA),
|
Rtype: common.String(endpoint.RecordTypeA),
|
||||||
Ttl: common.Int(ociRecordTTL),
|
Ttl: common.Int(defaultTTL),
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
changes: &plan.Changes{
|
changes: &plan.Changes{
|
||||||
UpdateOld: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
UpdateOld: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"foo.foo.com",
|
"foo.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
)},
|
)},
|
||||||
UpdateNew: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
UpdateNew: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"foo.foo.com",
|
"foo.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"10.0.0.1",
|
"10.0.0.1",
|
||||||
)},
|
)},
|
||||||
},
|
},
|
||||||
expectedEndpoints: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
expectedEndpoints: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"foo.foo.com",
|
"foo.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"10.0.0.1",
|
"10.0.0.1",
|
||||||
)},
|
)},
|
||||||
}, {
|
}, {
|
||||||
@ -820,14 +821,14 @@ func TestOCIApplyChanges(t *testing.T) {
|
|||||||
Domain: common.String("foo.foo.com"),
|
Domain: common.String("foo.foo.com"),
|
||||||
Rdata: common.String("127.0.0.1"),
|
Rdata: common.String("127.0.0.1"),
|
||||||
Rtype: common.String(endpoint.RecordTypeA),
|
Rtype: common.String(endpoint.RecordTypeA),
|
||||||
Ttl: common.Int(ociRecordTTL),
|
Ttl: common.Int(defaultTTL),
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
changes: &plan.Changes{
|
changes: &plan.Changes{
|
||||||
Delete: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
Delete: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"foo.foo.com",
|
"foo.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
)},
|
)},
|
||||||
},
|
},
|
||||||
@ -835,7 +836,7 @@ func TestOCIApplyChanges(t *testing.T) {
|
|||||||
expectedEndpoints: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
expectedEndpoints: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"foo.foo.com",
|
"foo.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
)},
|
)},
|
||||||
}, {
|
}, {
|
||||||
@ -849,42 +850,42 @@ func TestOCIApplyChanges(t *testing.T) {
|
|||||||
Domain: common.String("foo.foo.com"),
|
Domain: common.String("foo.foo.com"),
|
||||||
Rdata: common.String("127.0.0.1"),
|
Rdata: common.String("127.0.0.1"),
|
||||||
Rtype: common.String(endpoint.RecordTypeA),
|
Rtype: common.String(endpoint.RecordTypeA),
|
||||||
Ttl: common.Int(ociRecordTTL),
|
Ttl: common.Int(defaultTTL),
|
||||||
}, {
|
}, {
|
||||||
Domain: common.String("car.foo.com"),
|
Domain: common.String("car.foo.com"),
|
||||||
Rdata: common.String("bar.com."),
|
Rdata: common.String("bar.com."),
|
||||||
Rtype: common.String(endpoint.RecordTypeCNAME),
|
Rtype: common.String(endpoint.RecordTypeCNAME),
|
||||||
Ttl: common.Int(ociRecordTTL),
|
Ttl: common.Int(defaultTTL),
|
||||||
}, {
|
}, {
|
||||||
Domain: common.String("bar.foo.com"),
|
Domain: common.String("bar.foo.com"),
|
||||||
Rdata: common.String("baz.com."),
|
Rdata: common.String("baz.com."),
|
||||||
Rtype: common.String(endpoint.RecordTypeCNAME),
|
Rtype: common.String(endpoint.RecordTypeCNAME),
|
||||||
Ttl: common.Int(ociRecordTTL),
|
Ttl: common.Int(defaultTTL),
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
changes: &plan.Changes{
|
changes: &plan.Changes{
|
||||||
Delete: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
Delete: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"foo.foo.com",
|
"foo.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
)},
|
)},
|
||||||
UpdateOld: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
UpdateOld: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"car.foo.com",
|
"car.foo.com",
|
||||||
endpoint.RecordTypeCNAME,
|
endpoint.RecordTypeCNAME,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"baz.com.",
|
"baz.com.",
|
||||||
)},
|
)},
|
||||||
UpdateNew: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
UpdateNew: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"bar.foo.com",
|
"bar.foo.com",
|
||||||
endpoint.RecordTypeCNAME,
|
endpoint.RecordTypeCNAME,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"foo.bar.com.",
|
"foo.bar.com.",
|
||||||
)},
|
)},
|
||||||
Create: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
Create: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"baz.foo.com",
|
"baz.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"127.0.0.1",
|
"127.0.0.1",
|
||||||
)},
|
)},
|
||||||
},
|
},
|
||||||
@ -892,13 +893,13 @@ func TestOCIApplyChanges(t *testing.T) {
|
|||||||
endpoint.NewEndpointWithTTL(
|
endpoint.NewEndpointWithTTL(
|
||||||
"bar.foo.com",
|
"bar.foo.com",
|
||||||
endpoint.RecordTypeCNAME,
|
endpoint.RecordTypeCNAME,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"foo.bar.com.",
|
"foo.bar.com.",
|
||||||
),
|
),
|
||||||
endpoint.NewEndpointWithTTL(
|
endpoint.NewEndpointWithTTL(
|
||||||
"baz.foo.com",
|
"baz.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"127.0.0.1"),
|
"127.0.0.1"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -913,19 +914,19 @@ func TestOCIApplyChanges(t *testing.T) {
|
|||||||
Create: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
Create: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"foo.foo.com",
|
"foo.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"192.168.1.2",
|
"192.168.1.2",
|
||||||
), endpoint.NewEndpointWithTTL(
|
), endpoint.NewEndpointWithTTL(
|
||||||
"foo.foo.com",
|
"foo.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"192.168.2.5",
|
"192.168.2.5",
|
||||||
)},
|
)},
|
||||||
},
|
},
|
||||||
expectedEndpoints: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
expectedEndpoints: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"foo.foo.com",
|
"foo.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL), "192.168.1.2", "192.168.2.5",
|
endpoint.TTL(defaultTTL), "192.168.1.2", "192.168.2.5",
|
||||||
)},
|
)},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -939,26 +940,26 @@ func TestOCIApplyChanges(t *testing.T) {
|
|||||||
Domain: common.String("foo.foo.com"),
|
Domain: common.String("foo.foo.com"),
|
||||||
Rdata: common.String("192.168.1.2"),
|
Rdata: common.String("192.168.1.2"),
|
||||||
Rtype: common.String(endpoint.RecordTypeA),
|
Rtype: common.String(endpoint.RecordTypeA),
|
||||||
Ttl: common.Int(ociRecordTTL),
|
Ttl: common.Int(defaultTTL),
|
||||||
}, {
|
}, {
|
||||||
Domain: common.String("foo.foo.com"),
|
Domain: common.String("foo.foo.com"),
|
||||||
Rdata: common.String("192.168.2.5"),
|
Rdata: common.String("192.168.2.5"),
|
||||||
Rtype: common.String(endpoint.RecordTypeA),
|
Rtype: common.String(endpoint.RecordTypeA),
|
||||||
Ttl: common.Int(ociRecordTTL),
|
Ttl: common.Int(defaultTTL),
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
changes: &plan.Changes{
|
changes: &plan.Changes{
|
||||||
Delete: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
Delete: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"foo.foo.com",
|
"foo.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"192.168.1.2",
|
"192.168.1.2",
|
||||||
)},
|
)},
|
||||||
},
|
},
|
||||||
expectedEndpoints: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
expectedEndpoints: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"foo.foo.com",
|
"foo.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL), "192.168.2.5",
|
endpoint.TTL(defaultTTL), "192.168.2.5",
|
||||||
)},
|
)},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -972,27 +973,27 @@ func TestOCIApplyChanges(t *testing.T) {
|
|||||||
Domain: common.String("first.foo.com"),
|
Domain: common.String("first.foo.com"),
|
||||||
Rdata: common.String("10.77.4.5"),
|
Rdata: common.String("10.77.4.5"),
|
||||||
Rtype: common.String(endpoint.RecordTypeA),
|
Rtype: common.String(endpoint.RecordTypeA),
|
||||||
Ttl: common.Int(ociRecordTTL),
|
Ttl: common.Int(defaultTTL),
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
changes: &plan.Changes{
|
changes: &plan.Changes{
|
||||||
UpdateOld: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
UpdateOld: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"first.foo.com",
|
"first.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"10.77.4.5",
|
"10.77.4.5",
|
||||||
)},
|
)},
|
||||||
UpdateNew: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
UpdateNew: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"first.foo.com",
|
"first.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"10.77.6.10",
|
"10.77.6.10",
|
||||||
)},
|
)},
|
||||||
},
|
},
|
||||||
expectedEndpoints: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
expectedEndpoints: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"first.foo.com",
|
"first.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"10.77.6.10",
|
"10.77.6.10",
|
||||||
)},
|
)},
|
||||||
},
|
},
|
||||||
@ -1007,21 +1008,21 @@ func TestOCIApplyChanges(t *testing.T) {
|
|||||||
Domain: common.String("first.foo.com"),
|
Domain: common.String("first.foo.com"),
|
||||||
Rdata: common.String("10.77.4.5"),
|
Rdata: common.String("10.77.4.5"),
|
||||||
Rtype: common.String(endpoint.RecordTypeA),
|
Rtype: common.String(endpoint.RecordTypeA),
|
||||||
Ttl: common.Int(ociRecordTTL),
|
Ttl: common.Int(defaultTTL),
|
||||||
}},
|
}},
|
||||||
},
|
},
|
||||||
changes: &plan.Changes{
|
changes: &plan.Changes{
|
||||||
Create: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
Create: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"first.foo.com",
|
"first.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"10.77.6.10",
|
"10.77.6.10",
|
||||||
)},
|
)},
|
||||||
},
|
},
|
||||||
expectedEndpoints: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
expectedEndpoints: []*endpoint.Endpoint{endpoint.NewEndpointWithTTL(
|
||||||
"first.foo.com",
|
"first.foo.com",
|
||||||
endpoint.RecordTypeA,
|
endpoint.RecordTypeA,
|
||||||
endpoint.TTL(ociRecordTTL),
|
endpoint.TTL(defaultTTL),
|
||||||
"10.77.4.5", "10.77.6.10",
|
"10.77.4.5", "10.77.6.10",
|
||||||
)},
|
)},
|
||||||
},
|
},
|
||||||
|
@ -41,8 +41,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
ovhDefaultTTL = 0
|
defaultTTL = 0
|
||||||
ovhCreate = iota
|
ovhCreate = iota
|
||||||
ovhDelete
|
ovhDelete
|
||||||
ovhUpdate
|
ovhUpdate
|
||||||
)
|
)
|
||||||
@ -324,9 +324,9 @@ func (p *OVHProvider) change(ctx context.Context, change ovhChange) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return p.client.PutWithContext(ctx, fmt.Sprintf("/domain/zone/%s/record/%d", url.PathEscape(change.Zone), change.ID), change.ovhRecordFieldUpdate, nil)
|
return p.client.PutWithContext(ctx, fmt.Sprintf("/domain/zone/%s/record/%d", url.PathEscape(change.Zone), change.ID), change.ovhRecordFieldUpdate, nil)
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *OVHProvider) invalidateCache(zone string) {
|
func (p *OVHProvider) invalidateCache(zone string) {
|
||||||
@ -357,8 +357,8 @@ func (p *OVHProvider) zonesRecords(ctx context.Context) ([]string, []ovhRecord,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *OVHProvider) zones(ctx context.Context) ([]string, error) {
|
func (p *OVHProvider) zones(ctx context.Context) ([]string, error) {
|
||||||
zones := []string{}
|
var zones []string
|
||||||
filteredZones := []string{}
|
var filteredZones []string
|
||||||
|
|
||||||
p.apiRateLimiter.Take()
|
p.apiRateLimiter.Take()
|
||||||
if err := p.client.GetWithContext(ctx, "/domain/zone", &zones); err != nil {
|
if err := p.client.GetWithContext(ctx, "/domain/zone", &zones); err != nil {
|
||||||
@ -476,25 +476,25 @@ func ovhGroupByNameAndType(records []ovhRecord) []*endpoint.Endpoint {
|
|||||||
|
|
||||||
// create single endpoint with all the targets for each name/type
|
// create single endpoint with all the targets for each name/type
|
||||||
for _, records := range groups {
|
for _, records := range groups {
|
||||||
targets := []string{}
|
var targets []string
|
||||||
for _, record := range records {
|
for _, record := range records {
|
||||||
targets = append(targets, record.Target)
|
targets = append(targets, record.Target)
|
||||||
}
|
}
|
||||||
endpoint := endpoint.NewEndpointWithTTL(
|
ep := endpoint.NewEndpointWithTTL(
|
||||||
strings.TrimPrefix(records[0].SubDomain+"."+records[0].Zone, "."),
|
strings.TrimPrefix(records[0].SubDomain+"."+records[0].Zone, "."),
|
||||||
records[0].FieldType,
|
records[0].FieldType,
|
||||||
endpoint.TTL(records[0].TTL),
|
endpoint.TTL(records[0].TTL),
|
||||||
targets...,
|
targets...,
|
||||||
)
|
)
|
||||||
endpoints = append(endpoints, endpoint)
|
endpoints = append(endpoints, ep)
|
||||||
}
|
}
|
||||||
|
|
||||||
return endpoints
|
return endpoints
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p OVHProvider) newOvhChangeCreateDelete(action int, endpoints []*endpoint.Endpoint, zone string, existingRecords []ovhRecord) ([]ovhChange, []ovhRecord) {
|
func (p OVHProvider) newOvhChangeCreateDelete(action int, endpoints []*endpoint.Endpoint, zone string, existingRecords []ovhRecord) ([]ovhChange, []ovhRecord) {
|
||||||
ovhChanges := []ovhChange{}
|
var ovhChanges []ovhChange
|
||||||
toDeleteIds := []int{}
|
var toDeleteIds []int
|
||||||
|
|
||||||
for _, e := range endpoints {
|
for _, e := range endpoints {
|
||||||
for _, target := range e.Targets {
|
for _, target := range e.Targets {
|
||||||
@ -506,7 +506,7 @@ func (p OVHProvider) newOvhChangeCreateDelete(action int, endpoints []*endpoint.
|
|||||||
FieldType: e.RecordType,
|
FieldType: e.RecordType,
|
||||||
ovhRecordFieldUpdate: ovhRecordFieldUpdate{
|
ovhRecordFieldUpdate: ovhRecordFieldUpdate{
|
||||||
SubDomain: convertDNSNameIntoSubDomain(e.DNSName, zone),
|
SubDomain: convertDNSNameIntoSubDomain(e.DNSName, zone),
|
||||||
TTL: ovhDefaultTTL,
|
TTL: defaultTTL,
|
||||||
Target: target,
|
Target: target,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -579,13 +579,13 @@ func (p OVHProvider) newOvhChangeUpdate(endpointsOld []*endpoint.Endpoint, endpo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
changes := []ovhChange{}
|
var changes []ovhChange
|
||||||
|
|
||||||
for id := range oldEndpointByTypeAndName {
|
for id := range oldEndpointByTypeAndName {
|
||||||
oldRecords := slices.Clone(oldRecordsInZone[id])
|
oldRecords := slices.Clone(oldRecordsInZone[id])
|
||||||
endpointsNew := newEndpointByTypeAndName[id]
|
endpointsNew := newEndpointByTypeAndName[id]
|
||||||
|
|
||||||
toInsertTarget := []string{}
|
var toInsertTarget []string
|
||||||
|
|
||||||
for _, target := range endpointsNew.Targets {
|
for _, target := range endpointsNew.Targets {
|
||||||
var toDelete = -1
|
var toDelete = -1
|
||||||
@ -617,7 +617,7 @@ func (p OVHProvider) newOvhChangeUpdate(endpointsOld []*endpoint.Endpoint, endpo
|
|||||||
if endpointsNew.RecordTTL.IsConfigured() {
|
if endpointsNew.RecordTTL.IsConfigured() {
|
||||||
record.TTL = int64(endpointsNew.RecordTTL)
|
record.TTL = int64(endpointsNew.RecordTTL)
|
||||||
} else {
|
} else {
|
||||||
record.TTL = ovhDefaultTTL
|
record.TTL = defaultTTL
|
||||||
}
|
}
|
||||||
|
|
||||||
change := ovhChange{
|
change := ovhChange{
|
||||||
@ -634,7 +634,7 @@ func (p OVHProvider) newOvhChangeUpdate(endpointsOld []*endpoint.Endpoint, endpo
|
|||||||
|
|
||||||
if len(toInsertTarget) > 0 {
|
if len(toInsertTarget) > 0 {
|
||||||
for _, target := range toInsertTarget {
|
for _, target := range toInsertTarget {
|
||||||
recordTTL := int64(ovhDefaultTTL)
|
recordTTL := int64(defaultTTL)
|
||||||
if endpointsNew.RecordTTL.IsConfigured() {
|
if endpointsNew.RecordTTL.IsConfigured() {
|
||||||
recordTTL = int64(endpointsNew.RecordTTL)
|
recordTTL = int64(endpointsNew.RecordTTL)
|
||||||
}
|
}
|
||||||
@ -680,6 +680,8 @@ func (c *ovhChange) String() string {
|
|||||||
action = "update"
|
action = "update"
|
||||||
case ovhDelete:
|
case ovhDelete:
|
||||||
action = "delete"
|
action = "delete"
|
||||||
|
default:
|
||||||
|
action = "unknown"
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.ID != 0 {
|
if c.ID != 0 {
|
||||||
|
@ -371,8 +371,8 @@ func TestOvhNewChange(t *testing.T) {
|
|||||||
changes, _ := provider.newOvhChangeCreateDelete(ovhCreate, endpoints, "example.net", []ovhRecord{})
|
changes, _ := provider.newOvhChangeCreateDelete(ovhCreate, endpoints, "example.net", []ovhRecord{})
|
||||||
td.Cmp(t, changes, []ovhChange{
|
td.Cmp(t, changes, []ovhChange{
|
||||||
{Action: ovhCreate, ovhRecord: ovhRecord{Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "A", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "", TTL: 10, Target: "203.0.113.42"}}}},
|
{Action: ovhCreate, ovhRecord: ovhRecord{Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "A", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "", TTL: 10, Target: "203.0.113.42"}}}},
|
||||||
{Action: ovhCreate, ovhRecord: ovhRecord{Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "A", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "ovh", TTL: ovhDefaultTTL, Target: "203.0.113.43"}}}},
|
{Action: ovhCreate, ovhRecord: ovhRecord{Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "A", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "ovh", TTL: defaultTTL, Target: "203.0.113.43"}}}},
|
||||||
{Action: ovhCreate, ovhRecord: ovhRecord{Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "CNAME", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "ovh2", TTL: ovhDefaultTTL, Target: "ovh.example.net."}}}},
|
{Action: ovhCreate, ovhRecord: ovhRecord{Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "CNAME", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "ovh2", TTL: defaultTTL, Target: "ovh.example.net."}}}},
|
||||||
})
|
})
|
||||||
|
|
||||||
// Delete change
|
// Delete change
|
||||||
@ -386,9 +386,9 @@ func TestOvhNewChange(t *testing.T) {
|
|||||||
}
|
}
|
||||||
changes, _ = provider.newOvhChangeCreateDelete(ovhDelete, endpoints, "example.net", records)
|
changes, _ = provider.newOvhChangeCreateDelete(ovhDelete, endpoints, "example.net", records)
|
||||||
td.Cmp(t, changes, []ovhChange{
|
td.Cmp(t, changes, []ovhChange{
|
||||||
{Action: ovhDelete, ovhRecord: ovhRecord{ID: 42, Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "A", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "ovh", TTL: ovhDefaultTTL, Target: "203.0.113.42"}}}},
|
{Action: ovhDelete, ovhRecord: ovhRecord{ID: 42, Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "A", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "ovh", TTL: defaultTTL, Target: "203.0.113.42"}}}},
|
||||||
{Action: ovhDelete, ovhRecord: ovhRecord{ID: 43, Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "A", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "ovh", TTL: ovhDefaultTTL, Target: "203.0.113.42"}}}},
|
{Action: ovhDelete, ovhRecord: ovhRecord{ID: 43, Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "A", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "ovh", TTL: defaultTTL, Target: "203.0.113.42"}}}},
|
||||||
{Action: ovhDelete, ovhRecord: ovhRecord{ID: 44, Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "A", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "ovh", TTL: ovhDefaultTTL, Target: "203.0.113.42"}}}},
|
{Action: ovhDelete, ovhRecord: ovhRecord{ID: 44, Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "A", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "ovh", TTL: defaultTTL, Target: "203.0.113.42"}}}},
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create change with CNAME relative
|
// Create change with CNAME relative
|
||||||
@ -403,8 +403,8 @@ func TestOvhNewChange(t *testing.T) {
|
|||||||
changes, _ = provider.newOvhChangeCreateDelete(ovhCreate, endpoints, "example.net", []ovhRecord{})
|
changes, _ = provider.newOvhChangeCreateDelete(ovhCreate, endpoints, "example.net", []ovhRecord{})
|
||||||
td.Cmp(t, changes, []ovhChange{
|
td.Cmp(t, changes, []ovhChange{
|
||||||
{Action: ovhCreate, ovhRecord: ovhRecord{Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "A", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "", TTL: 10, Target: "203.0.113.42"}}}},
|
{Action: ovhCreate, ovhRecord: ovhRecord{Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "A", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "", TTL: 10, Target: "203.0.113.42"}}}},
|
||||||
{Action: ovhCreate, ovhRecord: ovhRecord{Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "A", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "ovh", TTL: ovhDefaultTTL, Target: "203.0.113.43"}}}},
|
{Action: ovhCreate, ovhRecord: ovhRecord{Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "A", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "ovh", TTL: defaultTTL, Target: "203.0.113.43"}}}},
|
||||||
{Action: ovhCreate, ovhRecord: ovhRecord{Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "CNAME", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "ovh2", TTL: ovhDefaultTTL, Target: "ovh"}}}},
|
{Action: ovhCreate, ovhRecord: ovhRecord{Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "CNAME", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "ovh2", TTL: defaultTTL, Target: "ovh"}}}},
|
||||||
})
|
})
|
||||||
|
|
||||||
// Test with CNAME when target has already final dot
|
// Test with CNAME when target has already final dot
|
||||||
@ -419,8 +419,8 @@ func TestOvhNewChange(t *testing.T) {
|
|||||||
changes, _ = provider.newOvhChangeCreateDelete(ovhCreate, endpoints, "example.net", []ovhRecord{})
|
changes, _ = provider.newOvhChangeCreateDelete(ovhCreate, endpoints, "example.net", []ovhRecord{})
|
||||||
td.Cmp(t, changes, []ovhChange{
|
td.Cmp(t, changes, []ovhChange{
|
||||||
{Action: ovhCreate, ovhRecord: ovhRecord{Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "A", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "", TTL: 10, Target: "203.0.113.42"}}}},
|
{Action: ovhCreate, ovhRecord: ovhRecord{Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "A", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "", TTL: 10, Target: "203.0.113.42"}}}},
|
||||||
{Action: ovhCreate, ovhRecord: ovhRecord{Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "A", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "ovh", TTL: ovhDefaultTTL, Target: "203.0.113.43"}}}},
|
{Action: ovhCreate, ovhRecord: ovhRecord{Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "A", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "ovh", TTL: defaultTTL, Target: "203.0.113.43"}}}},
|
||||||
{Action: ovhCreate, ovhRecord: ovhRecord{Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "CNAME", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "ovh2", TTL: ovhDefaultTTL, Target: "ovh.example.com."}}}},
|
{Action: ovhCreate, ovhRecord: ovhRecord{Zone: "example.net", ovhRecordFields: ovhRecordFields{FieldType: "CNAME", ovhRecordFieldUpdate: ovhRecordFieldUpdate{SubDomain: "ovh2", TTL: defaultTTL, Target: "ovh.example.com."}}}},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/netip"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -63,6 +64,7 @@ func newPiholeClientV6(cfg PiholeConfig) (piholeAPI, error) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
cl := instrumented_http.NewClient(httpClient, &instrumented_http.Callbacks{})
|
cl := instrumented_http.NewClient(httpClient, &instrumented_http.Callbacks{})
|
||||||
|
|
||||||
p := &piholeClientV6{
|
p := &piholeClientV6{
|
||||||
@ -114,6 +116,32 @@ func (p *piholeClientV6) getConfigValue(ctx context.Context, rtype string) ([]st
|
|||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isValidIPv4 checks if the given IP address is a valid IPv4 address.
|
||||||
|
* It returns true if the IP address is valid, false otherwise.
|
||||||
|
* If the IP address is in IPv6 format, it will return false.
|
||||||
|
*/
|
||||||
|
func isValidIPv4(ip string) bool {
|
||||||
|
addr, err := netip.ParseAddr(ip)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return addr.Is4()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* isValidIPv6 checks if the given IP address is a valid IPv6 address.
|
||||||
|
* It returns true if the IP address is valid, false otherwise.
|
||||||
|
* If the IP address is in IPv6 with dual format y:y:y:y:y:y:x.x.x.x. , it will return true.
|
||||||
|
*/
|
||||||
|
func isValidIPv6(ip string) bool {
|
||||||
|
addr, err := netip.ParseAddr(ip)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return addr.Is6()
|
||||||
|
}
|
||||||
|
|
||||||
func (p *piholeClientV6) listRecords(ctx context.Context, rtype string) ([]*endpoint.Endpoint, error) {
|
func (p *piholeClientV6) listRecords(ctx context.Context, rtype string) ([]*endpoint.Endpoint, error) {
|
||||||
out := make([]*endpoint.Endpoint, 0)
|
out := make([]*endpoint.Endpoint, 0)
|
||||||
results, err := p.getConfigValue(ctx, rtype)
|
results, err := p.getConfigValue(ctx, rtype)
|
||||||
@ -126,42 +154,39 @@ func (p *piholeClientV6) listRecords(ctx context.Context, rtype string) ([]*endp
|
|||||||
return r == ' ' || r == ','
|
return r == ' ' || r == ','
|
||||||
})
|
})
|
||||||
if len(recs) < 2 {
|
if len(recs) < 2 {
|
||||||
log.Warnf("skipping record %s: invalid format", rec)
|
log.Warnf("skipping record %s: invalid format received from PiHole", rec)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var DNSName, Target string
|
var DNSName, Target string
|
||||||
var Ttl endpoint.TTL = 0
|
var Ttl = endpoint.TTL(0)
|
||||||
// A/AAAA record format is target(IP) DNSName
|
// A/AAAA record format is target(IP) DNSName
|
||||||
DNSName, Target = recs[1], recs[0]
|
DNSName, Target = recs[1], recs[0]
|
||||||
|
|
||||||
switch rtype {
|
switch rtype {
|
||||||
case endpoint.RecordTypeA:
|
case endpoint.RecordTypeA:
|
||||||
if strings.Contains(Target, ":") {
|
//PiHole return A and AAAA records. Filter to only keep the A records
|
||||||
|
if !isValidIPv4(Target) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
case endpoint.RecordTypeAAAA:
|
case endpoint.RecordTypeAAAA:
|
||||||
if strings.Contains(Target, ".") {
|
//PiHole return A and AAAA records. Filter to only keep the AAAA records
|
||||||
|
if !isValidIPv6(Target) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
case endpoint.RecordTypeCNAME:
|
case endpoint.RecordTypeCNAME:
|
||||||
// CNAME format is DNSName,target
|
//PiHole return only CNAME records.
|
||||||
|
// CNAME format is DNSName,target, ttl?
|
||||||
DNSName, Target = recs[0], recs[1]
|
DNSName, Target = recs[0], recs[1]
|
||||||
if len(recs) == 3 { // TTL is present
|
if len(recs) == 3 { // TTL is present
|
||||||
// Parse string to int64 first
|
// Parse string to int64 first
|
||||||
if ttlInt, err := strconv.ParseInt(recs[2], 10, 64); err == nil {
|
if ttlInt, err := strconv.ParseInt(recs[2], 10, 64); err == nil {
|
||||||
Ttl = endpoint.TTL(ttlInt)
|
Ttl = endpoint.TTL(ttlInt)
|
||||||
} else {
|
} else {
|
||||||
log.Warnf("failed to parse TTL value '%s': %v; using a TTL of %d", recs[2], err, Ttl)
|
log.Warnf("failed to parse TTL value received from PiHole '%s': %v; using a TTL of %d", recs[2], err, Ttl)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out = append(out, &endpoint.Endpoint{
|
out = append(out, endpoint.NewEndpointWithTTL(DNSName, rtype, Ttl, Target))
|
||||||
DNSName: DNSName,
|
|
||||||
Targets: []string{Target},
|
|
||||||
RecordTTL: Ttl,
|
|
||||||
RecordType: rtype,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
@ -375,7 +400,13 @@ func (p *piholeClientV6) do(req *http.Request) ([]byte, error) {
|
|||||||
if err := json.Unmarshal(jRes, &apiError); err != nil {
|
if err := json.Unmarshal(jRes, &apiError); err != nil {
|
||||||
return nil, fmt.Errorf("failed to unmarshal error response: %w", err)
|
return nil, fmt.Errorf("failed to unmarshal error response: %w", err)
|
||||||
}
|
}
|
||||||
log.Debugf("Error on request %s", req.Body)
|
if log.IsLevelEnabled(log.DebugLevel) {
|
||||||
|
log.Debugf("Error on request %s", req.URL)
|
||||||
|
if req.Body != nil {
|
||||||
|
log.Debugf("Body of the request %s", req.Body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if res.StatusCode == http.StatusUnauthorized && p.token != "" {
|
if res.StatusCode == http.StatusUnauthorized && p.token != "" {
|
||||||
tryCount := 1
|
tryCount := 1
|
||||||
maxRetries := 3
|
maxRetries := 3
|
||||||
|
@ -29,6 +29,62 @@ import (
|
|||||||
"sigs.k8s.io/external-dns/endpoint"
|
"sigs.k8s.io/external-dns/endpoint"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestIsValidIPv4(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
ip string
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{"192.168.1.1", true},
|
||||||
|
{"255.255.255.255", true},
|
||||||
|
{"0.0.0.0", true},
|
||||||
|
{"", false},
|
||||||
|
{"256.256.256.256", false},
|
||||||
|
{"192.168.0.1/22", false},
|
||||||
|
{"192.168.1", false},
|
||||||
|
{"abc.def.ghi.jkl", false},
|
||||||
|
{"::ffff:192.168.20.3", false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.ip, func(t *testing.T) {
|
||||||
|
if got := isValidIPv4(test.ip); got != test.expected {
|
||||||
|
t.Errorf("isValidIPv4(%s) = %v; want %v", test.ip, got, test.expected)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestIsValidIPv6(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
ip string
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{"2001:0db8:85a3:0000:0000:8a2e:0370:7334", true},
|
||||||
|
{"2001:db8:85a3::8a2e:370:7334", true},
|
||||||
|
//IPV6 dual, the format is y:y:y:y:y:y:x.x.x.x.
|
||||||
|
{"::ffff:192.168.20.3", true},
|
||||||
|
{"::1", true},
|
||||||
|
{"::", true},
|
||||||
|
{"2001:db8::", true},
|
||||||
|
{"", false},
|
||||||
|
{":", false},
|
||||||
|
{"::ffff:", false},
|
||||||
|
{"192.168.20.3", false},
|
||||||
|
{"2001:db8:85a3:0:0:8a2e:370:7334:1234", false},
|
||||||
|
{"2001:db8:85a3::8a2e:370g:7334", false},
|
||||||
|
{"2001:db8:85a3::8a2e:370:7334::", false},
|
||||||
|
{"2001:db8:85a3::8a2e:370:7334::1", false},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.ip, func(t *testing.T) {
|
||||||
|
if got := isValidIPv6(test.ip); got != test.expected {
|
||||||
|
t.Errorf("isValidIPv6(%s) = %v; want %v", test.ip, got, test.expected)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func newTestServerV6(t *testing.T, hdlr http.HandlerFunc) *httptest.Server {
|
func newTestServerV6(t *testing.T, hdlr http.HandlerFunc) *httptest.Server {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
svr := httptest.NewServer(hdlr)
|
svr := httptest.NewServer(hdlr)
|
||||||
@ -137,7 +193,9 @@ func TestListRecordsV6(t *testing.T) {
|
|||||||
"192.168.178.34 service3.example.com",
|
"192.168.178.34 service3.example.com",
|
||||||
"fc00::1:192:168:1:1 service4.example.com",
|
"fc00::1:192:168:1:1 service4.example.com",
|
||||||
"fc00::1:192:168:1:2 service5.example.com",
|
"fc00::1:192:168:1:2 service5.example.com",
|
||||||
"fc00::1:192:168:1:3 service6.example.com"
|
"fc00::1:192:168:1:3 service6.example.com",
|
||||||
|
"::ffff:192.168.20.3 service7.example.com",
|
||||||
|
"192.168.20.3 service7.example.com"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -177,20 +235,22 @@ func TestListRecordsV6(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure A records were parsed correctly
|
||||||
|
expected := [][]string{
|
||||||
|
{"service1.example.com", "192.168.178.33"},
|
||||||
|
{"service2.example.com", "192.168.178.34"},
|
||||||
|
{"service3.example.com", "192.168.178.34"},
|
||||||
|
{"service7.example.com", "192.168.20.3"},
|
||||||
|
}
|
||||||
// Test retrieve A records unfiltered
|
// Test retrieve A records unfiltered
|
||||||
arecs, err := cl.listRecords(context.Background(), endpoint.RecordTypeA)
|
arecs, err := cl.listRecords(context.Background(), endpoint.RecordTypeA)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if len(arecs) != 3 {
|
if len(arecs) != len(expected) {
|
||||||
t.Fatal("Expected 3 A records returned, got:", len(arecs))
|
t.Fatalf("Expected %d A records returned, got: %d", len(expected), len(arecs))
|
||||||
}
|
|
||||||
// Ensure records were parsed correctly
|
|
||||||
expected := [][]string{
|
|
||||||
{"service1.example.com", "192.168.178.33"},
|
|
||||||
{"service2.example.com", "192.168.178.34"},
|
|
||||||
{"service3.example.com", "192.168.178.34"},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx, rec := range arecs {
|
for idx, rec := range arecs {
|
||||||
if rec.DNSName != expected[idx][0] {
|
if rec.DNSName != expected[idx][0] {
|
||||||
t.Error("Got invalid DNS Name:", rec.DNSName, "expected:", expected[idx][0])
|
t.Error("Got invalid DNS Name:", rec.DNSName, "expected:", expected[idx][0])
|
||||||
@ -200,20 +260,23 @@ func TestListRecordsV6(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure AAAA records were parsed correctly
|
||||||
|
expected = [][]string{
|
||||||
|
{"service4.example.com", "fc00::1:192:168:1:1"},
|
||||||
|
{"service5.example.com", "fc00::1:192:168:1:2"},
|
||||||
|
{"service6.example.com", "fc00::1:192:168:1:3"},
|
||||||
|
{"service7.example.com", "::ffff:192.168.20.3"},
|
||||||
|
}
|
||||||
// Test retrieve AAAA records unfiltered
|
// Test retrieve AAAA records unfiltered
|
||||||
arecs, err = cl.listRecords(context.Background(), endpoint.RecordTypeAAAA)
|
arecs, err = cl.listRecords(context.Background(), endpoint.RecordTypeAAAA)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if len(arecs) != 3 {
|
|
||||||
t.Fatal("Expected 3 AAAA records returned, got:", len(arecs))
|
if len(arecs) != len(expected) {
|
||||||
}
|
t.Fatalf("Expected %d AAAA records returned, got: %d", len(expected), len(arecs))
|
||||||
// Ensure records were parsed correctly
|
|
||||||
expected = [][]string{
|
|
||||||
{"service4.example.com", "fc00::1:192:168:1:1"},
|
|
||||||
{"service5.example.com", "fc00::1:192:168:1:2"},
|
|
||||||
{"service6.example.com", "fc00::1:192:168:1:3"},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx, rec := range arecs {
|
for idx, rec := range arecs {
|
||||||
if rec.DNSName != expected[idx][0] {
|
if rec.DNSName != expected[idx][0] {
|
||||||
t.Error("Got invalid DNS Name:", rec.DNSName, "expected:", expected[idx][0])
|
t.Error("Got invalid DNS Name:", rec.DNSName, "expected:", expected[idx][0])
|
||||||
@ -223,20 +286,22 @@ func TestListRecordsV6(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ensure CNAME records were parsed correctly
|
||||||
|
expected = [][]string{
|
||||||
|
{"source1.example.com", "target1.domain.com", "1000"},
|
||||||
|
{"source2.example.com", "target2.domain.com", "50"},
|
||||||
|
{"source3.example.com", "target3.domain.com"},
|
||||||
|
}
|
||||||
|
|
||||||
// Test retrieve CNAME records unfiltered
|
// Test retrieve CNAME records unfiltered
|
||||||
cnamerecs, err := cl.listRecords(context.Background(), endpoint.RecordTypeCNAME)
|
cnamerecs, err := cl.listRecords(context.Background(), endpoint.RecordTypeCNAME)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
if len(cnamerecs) != 3 {
|
if len(cnamerecs) != len(expected) {
|
||||||
t.Fatal("Expected 3 CAME records returned, got:", len(cnamerecs))
|
t.Fatalf("Expected %d CAME records returned, got: %d", len(expected), len(cnamerecs))
|
||||||
}
|
|
||||||
// Ensure records were parsed correctly
|
|
||||||
expected = [][]string{
|
|
||||||
{"source1.example.com", "target1.domain.com", "1000"},
|
|
||||||
{"source2.example.com", "target2.domain.com", "50"},
|
|
||||||
{"source3.example.com", "target3.domain.com"},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for idx, rec := range cnamerecs {
|
for idx, rec := range cnamerecs {
|
||||||
if rec.DNSName != expected[idx][0] {
|
if rec.DNSName != expected[idx][0] {
|
||||||
t.Error("Got invalid DNS Name:", rec.DNSName, "expected:", expected[idx][0])
|
t.Error("Got invalid DNS Name:", rec.DNSName, "expected:", expected[idx][0])
|
||||||
@ -261,6 +326,7 @@ func TestListRecordsV6(t *testing.T) {
|
|||||||
t.Fatal("Expected error for using unsupported record type")
|
t.Fatal("Expected error for using unsupported record type")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestErrorsV6(t *testing.T) {
|
func TestErrorsV6(t *testing.T) {
|
||||||
//Error test cases
|
//Error test cases
|
||||||
|
|
||||||
|
@ -45,29 +45,25 @@ type RecordChange struct {
|
|||||||
|
|
||||||
func NewPluralProvider(cluster, provider string) (*PluralProvider, error) {
|
func NewPluralProvider(cluster, provider string) (*PluralProvider, error) {
|
||||||
token := os.Getenv("PLURAL_ACCESS_TOKEN")
|
token := os.Getenv("PLURAL_ACCESS_TOKEN")
|
||||||
endpoint := os.Getenv("PLURAL_ENDPOINT")
|
|
||||||
|
|
||||||
if token == "" {
|
if token == "" {
|
||||||
return nil, fmt.Errorf("no plural access token provided, you must set the PLURAL_ACCESS_TOKEN env var")
|
return nil, fmt.Errorf("no plural access token provided, you must set the PLURAL_ACCESS_TOKEN env var")
|
||||||
}
|
}
|
||||||
|
|
||||||
config := &Config{
|
config := &Config{
|
||||||
Token: token,
|
Token: token,
|
||||||
Endpoint: endpoint,
|
Endpoint: os.Getenv("PLURAL_ENDPOINT"),
|
||||||
Cluster: cluster,
|
Cluster: cluster,
|
||||||
Provider: provider,
|
Provider: provider,
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := NewClient(config)
|
cl, err := NewClient(config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
prov := &PluralProvider{
|
return &PluralProvider{
|
||||||
Client: client,
|
Client: cl,
|
||||||
}
|
}, nil
|
||||||
|
|
||||||
return prov, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PluralProvider) Records(_ context.Context) (endpoints []*endpoint.Endpoint, err error) {
|
func (p *PluralProvider) Records(_ context.Context) (endpoints []*endpoint.Endpoint, err error) {
|
||||||
@ -89,8 +85,8 @@ func (p *PluralProvider) AdjustEndpoints(endpoints []*endpoint.Endpoint) ([]*end
|
|||||||
|
|
||||||
func (p *PluralProvider) ApplyChanges(_ context.Context, diffs *plan.Changes) error {
|
func (p *PluralProvider) ApplyChanges(_ context.Context, diffs *plan.Changes) error {
|
||||||
var changes []*RecordChange
|
var changes []*RecordChange
|
||||||
for _, endpoint := range diffs.Create {
|
for _, ep := range diffs.Create {
|
||||||
changes = append(changes, makeChange(CreateAction, endpoint.Targets, endpoint))
|
changes = append(changes, makeChange(CreateAction, ep.Targets, ep))
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, desired := range diffs.UpdateNew {
|
for _, desired := range diffs.UpdateNew {
|
||||||
|
@ -19,6 +19,7 @@ package rfc2136
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net"
|
"net"
|
||||||
@ -32,7 +33,6 @@ import (
|
|||||||
"github.com/bodgit/tsig/gss"
|
"github.com/bodgit/tsig/gss"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"sigs.k8s.io/external-dns/endpoint"
|
"sigs.k8s.io/external-dns/endpoint"
|
||||||
@ -116,7 +116,7 @@ type rfc2136Actions interface {
|
|||||||
func NewRfc2136Provider(hosts []string, port int, zoneNames []string, insecure bool, keyName string, secret string, secretAlg string, axfr bool, domainFilter endpoint.DomainFilter, dryRun bool, minTTL time.Duration, createPTR bool, gssTsig bool, krb5Username string, krb5Password string, krb5Realm string, batchChangeSize int, tlsConfig TLSConfig, loadBalancingStrategy string, actions rfc2136Actions) (provider.Provider, error) {
|
func NewRfc2136Provider(hosts []string, port int, zoneNames []string, insecure bool, keyName string, secret string, secretAlg string, axfr bool, domainFilter endpoint.DomainFilter, dryRun bool, minTTL time.Duration, createPTR bool, gssTsig bool, krb5Username string, krb5Password string, krb5Realm string, batchChangeSize int, tlsConfig TLSConfig, loadBalancingStrategy string, actions rfc2136Actions) (provider.Provider, error) {
|
||||||
secretAlgChecked, ok := tsigAlgs[secretAlg]
|
secretAlgChecked, ok := tsigAlgs[secretAlg]
|
||||||
if !ok && !insecure && !gssTsig {
|
if !ok && !insecure && !gssTsig {
|
||||||
return nil, errors.Errorf("%s is not supported TSIG algorithm", secretAlg)
|
return nil, fmt.Errorf("%s is not supported TSIG algorithm", secretAlg)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set zone to root if no set
|
// Set zone to root if no set
|
||||||
@ -307,7 +307,7 @@ func (r *rfc2136Provider) List() ([]dns.RR, error) {
|
|||||||
|
|
||||||
for e := range env {
|
for e := range env {
|
||||||
if e.Error != nil {
|
if e.Error != nil {
|
||||||
if e.Error == dns.ErrSoa {
|
if errors.Is(e.Error, dns.ErrSoa) {
|
||||||
log.Error("AXFR error: unexpected response received from the server")
|
log.Error("AXFR error: unexpected response received from the server")
|
||||||
} else {
|
} else {
|
||||||
log.Errorf("AXFR error: %v", e.Error)
|
log.Errorf("AXFR error: %v", e.Error)
|
||||||
@ -342,8 +342,6 @@ func (r *rfc2136Provider) RemoveReverseRecord(ip string, hostname string) error
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *rfc2136Provider) GenerateReverseRecord(ip string, hostname string) []*endpoint.Endpoint {
|
func (r *rfc2136Provider) GenerateReverseRecord(ip string, hostname string) []*endpoint.Endpoint {
|
||||||
// Find the zone for the PTR record
|
|
||||||
// zone := findMsgZone(&endpoint.Endpoint{DNSName: ip}, p.ptrZoneNames)
|
|
||||||
// Generate PTR notation record starting from the IP address
|
// Generate PTR notation record starting from the IP address
|
||||||
var records []*endpoint.Endpoint
|
var records []*endpoint.Endpoint
|
||||||
|
|
||||||
@ -364,7 +362,7 @@ func (r *rfc2136Provider) GenerateReverseRecord(ip string, hostname string) []*e
|
|||||||
func (r *rfc2136Provider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
|
func (r *rfc2136Provider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
|
||||||
log.Debugf("ApplyChanges (Create: %d, UpdateOld: %d, UpdateNew: %d, Delete: %d)", len(changes.Create), len(changes.UpdateOld), len(changes.UpdateNew), len(changes.Delete))
|
log.Debugf("ApplyChanges (Create: %d, UpdateOld: %d, UpdateNew: %d, Delete: %d)", len(changes.Create), len(changes.UpdateOld), len(changes.UpdateNew), len(changes.Delete))
|
||||||
|
|
||||||
var errors []error
|
var errs []error
|
||||||
|
|
||||||
for c, chunk := range chunkBy(changes.Create, r.batchChangeSize) {
|
for c, chunk := range chunkBy(changes.Create, r.batchChangeSize) {
|
||||||
log.Debugf("Processing batch %d of create changes", c)
|
log.Debugf("Processing batch %d of create changes", c)
|
||||||
@ -397,7 +395,7 @@ func (r *rfc2136Provider) ApplyChanges(ctx context.Context, changes *plan.Change
|
|||||||
if len(z.Ns) > 0 {
|
if len(z.Ns) > 0 {
|
||||||
if err := r.actions.SendMessage(z); err != nil {
|
if err := r.actions.SendMessage(z); err != nil {
|
||||||
log.Errorf("RFC2136 create record failed: %v", err)
|
log.Errorf("RFC2136 create record failed: %v", err)
|
||||||
errors = append(errors, err)
|
errs = append(errs, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -436,7 +434,7 @@ func (r *rfc2136Provider) ApplyChanges(ctx context.Context, changes *plan.Change
|
|||||||
if len(z.Ns) > 0 {
|
if len(z.Ns) > 0 {
|
||||||
if err := r.actions.SendMessage(z); err != nil {
|
if err := r.actions.SendMessage(z); err != nil {
|
||||||
log.Errorf("RFC2136 update record failed: %v", err)
|
log.Errorf("RFC2136 update record failed: %v", err)
|
||||||
errors = append(errors, err)
|
errs = append(errs, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -473,15 +471,15 @@ func (r *rfc2136Provider) ApplyChanges(ctx context.Context, changes *plan.Change
|
|||||||
if len(z.Ns) > 0 {
|
if len(z.Ns) > 0 {
|
||||||
if err := r.actions.SendMessage(z); err != nil {
|
if err := r.actions.SendMessage(z); err != nil {
|
||||||
log.Errorf("RFC2136 delete record failed: %v", err)
|
log.Errorf("RFC2136 delete record failed: %v", err)
|
||||||
errors = append(errors, err)
|
errs = append(errs, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(errors) > 0 {
|
if len(errs) > 0 {
|
||||||
return fmt.Errorf("RFC2136 had errors in one or more of its batches: %v", errors)
|
return fmt.Errorf("RFC2136 had errors in one or more of its batches: %v", errs)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -34,7 +34,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
scalewyRecordTTL uint32 = 300
|
defaultTTL uint32 = 300
|
||||||
scalewayDefaultPriority uint32 = 0
|
scalewayDefaultPriority uint32 = 0
|
||||||
scalewayPriorityKey string = "scw/priority"
|
scalewayPriorityKey string = "scw/priority"
|
||||||
)
|
)
|
||||||
@ -110,7 +110,7 @@ func (p *ScalewayProvider) AdjustEndpoints(endpoints []*endpoint.Endpoint) ([]*e
|
|||||||
for i := range endpoints {
|
for i := range endpoints {
|
||||||
eps[i] = endpoints[i]
|
eps[i] = endpoints[i]
|
||||||
if !eps[i].RecordTTL.IsConfigured() {
|
if !eps[i].RecordTTL.IsConfigured() {
|
||||||
eps[i].RecordTTL = endpoint.TTL(scalewyRecordTTL)
|
eps[i].RecordTTL = endpoint.TTL(defaultTTL)
|
||||||
}
|
}
|
||||||
if _, ok := eps[i].GetProviderSpecificProperty(scalewayPriorityKey); !ok {
|
if _, ok := eps[i].GetProviderSpecificProperty(scalewayPriorityKey); !ok {
|
||||||
eps[i] = eps[i].WithProviderSpecific(scalewayPriorityKey, fmt.Sprintf("%d", scalewayDefaultPriority))
|
eps[i] = eps[i].WithProviderSpecific(scalewayPriorityKey, fmt.Sprintf("%d", scalewayDefaultPriority))
|
||||||
@ -300,7 +300,7 @@ func getCompleteZoneName(zone *domain.DNSZone) string {
|
|||||||
|
|
||||||
func endpointToScalewayRecords(zoneName string, ep *endpoint.Endpoint) []*domain.Record {
|
func endpointToScalewayRecords(zoneName string, ep *endpoint.Endpoint) []*domain.Record {
|
||||||
// no annotation results in a TTL of 0, default to 300 for consistency with other providers
|
// no annotation results in a TTL of 0, default to 300 for consistency with other providers
|
||||||
ttl := scalewyRecordTTL
|
ttl := defaultTTL
|
||||||
if ep.RecordTTL.IsConfigured() {
|
if ep.RecordTTL.IsConfigured() {
|
||||||
ttl = uint32(ep.RecordTTL)
|
ttl = uint32(ep.RecordTTL)
|
||||||
}
|
}
|
||||||
|
@ -32,8 +32,6 @@ import (
|
|||||||
|
|
||||||
func NewMockTencentCloudProvider(domainFilter endpoint.DomainFilter, zoneIDFilter provider.ZoneIDFilter, zoneType string) *TencentCloudProvider {
|
func NewMockTencentCloudProvider(domainFilter endpoint.DomainFilter, zoneIDFilter provider.ZoneIDFilter, zoneType string) *TencentCloudProvider {
|
||||||
cfg := tencentCloudConfig{
|
cfg := tencentCloudConfig{
|
||||||
// SecretId: "",
|
|
||||||
// SecretKey: "",
|
|
||||||
RegionId: "ap-shanghai",
|
RegionId: "ap-shanghai",
|
||||||
VPCId: "vpc-abcdefg",
|
VPCId: "vpc-abcdefg",
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
// 60 seconds is the current minimal TTL for TransIP and will replace unconfigured
|
// 60 seconds is the current minimal TTL for TransIP and will replace unconfigured
|
||||||
// TTL's for Endpoints
|
// TTL's for Endpoints
|
||||||
transipMinimalValidTTL = 60
|
defaultTTL = 60
|
||||||
)
|
)
|
||||||
|
|
||||||
// TransIPProvider is an implementation of Provider for TransIP.
|
// TransIPProvider is an implementation of Provider for TransIP.
|
||||||
@ -336,11 +336,11 @@ func recordNameForEndpoint(ep *endpoint.Endpoint, zoneName string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getMinimalValidTTL returns max between given Endpoint's RecordTTL and
|
// getMinimalValidTTL returns max between given Endpoint's RecordTTL and
|
||||||
// transipMinimalValidTTL
|
// defaultTTL
|
||||||
func getMinimalValidTTL(ep *endpoint.Endpoint) int {
|
func getMinimalValidTTL(ep *endpoint.Endpoint) int {
|
||||||
// TTL cannot be lower than transipMinimalValidTTL
|
// TTL cannot be lower than defaultTTL
|
||||||
if ep.RecordTTL < transipMinimalValidTTL {
|
if ep.RecordTTL < defaultTTL {
|
||||||
return transipMinimalValidTTL
|
return defaultTTL
|
||||||
}
|
}
|
||||||
|
|
||||||
return int(ep.RecordTTL)
|
return int(ep.RecordTTL)
|
||||||
|
@ -94,15 +94,15 @@ func TestTransIPDnsEntriesAreEqual(t *testing.T) {
|
|||||||
func TestTransIPGetMinimalValidTTL(t *testing.T) {
|
func TestTransIPGetMinimalValidTTL(t *testing.T) {
|
||||||
// test with 'unconfigured' TTL
|
// test with 'unconfigured' TTL
|
||||||
ep := &endpoint.Endpoint{}
|
ep := &endpoint.Endpoint{}
|
||||||
assert.EqualValues(t, transipMinimalValidTTL, getMinimalValidTTL(ep))
|
assert.EqualValues(t, defaultTTL, getMinimalValidTTL(ep))
|
||||||
|
|
||||||
// test with lower than minimal ttl
|
// test with lower than minimal ttl
|
||||||
ep.RecordTTL = (transipMinimalValidTTL - 1)
|
ep.RecordTTL = (defaultTTL - 1)
|
||||||
assert.EqualValues(t, transipMinimalValidTTL, getMinimalValidTTL(ep))
|
assert.EqualValues(t, defaultTTL, getMinimalValidTTL(ep))
|
||||||
|
|
||||||
// test with higher than minimal ttl
|
// test with higher than minimal ttl
|
||||||
ep.RecordTTL = (transipMinimalValidTTL + 1)
|
ep.RecordTTL = (defaultTTL + 1)
|
||||||
assert.EqualValues(t, transipMinimalValidTTL+1, getMinimalValidTTL(ep))
|
assert.EqualValues(t, defaultTTL+1, getMinimalValidTTL(ep))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTransIPRecordNameForEndpoint(t *testing.T) {
|
func TestTransIPRecordNameForEndpoint(t *testing.T) {
|
||||||
|
@ -39,23 +39,20 @@ const (
|
|||||||
rdPoolOrder = "ROUND_ROBIN"
|
rdPoolOrder = "ROUND_ROBIN"
|
||||||
)
|
)
|
||||||
|
|
||||||
// global variables
|
|
||||||
var sbPoolRunProbes = true
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
sbPoolActOnProbes = true
|
sbPoolActOnProbes = true
|
||||||
ultradnsPoolType = "rdpool"
|
ultradnsPoolType = "rdpool"
|
||||||
accountName string
|
accountName string
|
||||||
|
sbPoolRunProbes = true
|
||||||
|
// Setting custom headers for ultradns api calls
|
||||||
|
customHeader = []udnssdk.CustomHeader{
|
||||||
|
{
|
||||||
|
Key: "UltraClient",
|
||||||
|
Value: "kube-client",
|
||||||
|
},
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// Setting custom headers for ultradns api calls
|
|
||||||
var customHeader = []udnssdk.CustomHeader{
|
|
||||||
{
|
|
||||||
Key: "UltraClient",
|
|
||||||
Value: "kube-client",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// UltraDNSProvider struct
|
// UltraDNSProvider struct
|
||||||
type UltraDNSProvider struct {
|
type UltraDNSProvider struct {
|
||||||
provider.BaseProvider
|
provider.BaseProvider
|
||||||
@ -128,13 +125,11 @@ func NewUltraDNSProvider(domainFilter endpoint.DomainFilter, dryRun bool) (*Ultr
|
|||||||
return nil, fmt.Errorf("connection cannot be established")
|
return nil, fmt.Errorf("connection cannot be established")
|
||||||
}
|
}
|
||||||
|
|
||||||
provider := &UltraDNSProvider{
|
return &UltraDNSProvider{
|
||||||
client: *client,
|
client: *client,
|
||||||
domainFilter: domainFilter,
|
domainFilter: domainFilter,
|
||||||
dryRun: dryRun,
|
dryRun: dryRun,
|
||||||
}
|
}, nil
|
||||||
|
|
||||||
return provider, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Zones returns list of hosted zones
|
// Zones returns list of hosted zones
|
||||||
@ -216,7 +211,7 @@ func (p *UltraDNSProvider) fetchRecords(ctx context.Context, k udnssdk.RRSetKey)
|
|||||||
maxerrs := 5
|
maxerrs := 5
|
||||||
waittime := 5 * time.Second
|
waittime := 5 * time.Second
|
||||||
|
|
||||||
rrsets := []udnssdk.RRSet{}
|
var rrsets []udnssdk.RRSet
|
||||||
errcnt := 0
|
errcnt := 0
|
||||||
offset := 0
|
offset := 0
|
||||||
limit := 1000
|
limit := 1000
|
||||||
|
@ -33,6 +33,9 @@ import (
|
|||||||
const (
|
const (
|
||||||
MediaTypeFormatAndVersion = "application/external.dns.webhook+json;version=1"
|
MediaTypeFormatAndVersion = "application/external.dns.webhook+json;version=1"
|
||||||
ContentTypeHeader = "Content-Type"
|
ContentTypeHeader = "Content-Type"
|
||||||
|
UrlAdjustEndpoints = "/adjustendpoints"
|
||||||
|
UrlApplyChanges = "/applychanges"
|
||||||
|
UrlRecords = "/records"
|
||||||
)
|
)
|
||||||
|
|
||||||
type WebhookServer struct {
|
type WebhookServer struct {
|
||||||
@ -82,7 +85,7 @@ func (p *WebhookServer) AdjustEndpointsHandler(w http.ResponseWriter, req *http.
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
pve := []*endpoint.Endpoint{}
|
var pve []*endpoint.Endpoint
|
||||||
if err := json.NewDecoder(req.Body).Decode(&pve); err != nil {
|
if err := json.NewDecoder(req.Body).Decode(&pve); err != nil {
|
||||||
log.Errorf("Failed to decode in adjustEndpointsHandler: %v", err)
|
log.Errorf("Failed to decode in adjustEndpointsHandler: %v", err)
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
@ -101,7 +104,7 @@ func (p *WebhookServer) AdjustEndpointsHandler(w http.ResponseWriter, req *http.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *WebhookServer) NegotiateHandler(w http.ResponseWriter, req *http.Request) {
|
func (p *WebhookServer) NegotiateHandler(w http.ResponseWriter, _ *http.Request) {
|
||||||
w.Header().Set(ContentTypeHeader, MediaTypeFormatAndVersion)
|
w.Header().Set(ContentTypeHeader, MediaTypeFormatAndVersion)
|
||||||
json.NewEncoder(w).Encode(p.Provider.GetDomainFilter())
|
json.NewEncoder(w).Encode(p.Provider.GetDomainFilter())
|
||||||
}
|
}
|
||||||
@ -121,8 +124,8 @@ func StartHTTPApi(provider provider.Provider, startedChan chan struct{}, readTim
|
|||||||
|
|
||||||
m := http.NewServeMux()
|
m := http.NewServeMux()
|
||||||
m.HandleFunc("/", p.NegotiateHandler)
|
m.HandleFunc("/", p.NegotiateHandler)
|
||||||
m.HandleFunc("/records", p.RecordsHandler)
|
m.HandleFunc(UrlRecords, p.RecordsHandler)
|
||||||
m.HandleFunc("/adjustendpoints", p.AdjustEndpointsHandler)
|
m.HandleFunc(UrlAdjustEndpoints, p.AdjustEndpointsHandler)
|
||||||
|
|
||||||
s := &http.Server{
|
s := &http.Server{
|
||||||
Addr: providerPort,
|
Addr: providerPort,
|
||||||
|
@ -24,9 +24,11 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"sigs.k8s.io/external-dns/endpoint"
|
"sigs.k8s.io/external-dns/endpoint"
|
||||||
"sigs.k8s.io/external-dns/plan"
|
"sigs.k8s.io/external-dns/plan"
|
||||||
@ -35,8 +37,9 @@ import (
|
|||||||
var records []*endpoint.Endpoint
|
var records []*endpoint.Endpoint
|
||||||
|
|
||||||
type FakeWebhookProvider struct {
|
type FakeWebhookProvider struct {
|
||||||
err error
|
err error
|
||||||
domainFilter endpoint.DomainFilter
|
domainFilter endpoint.DomainFilter
|
||||||
|
assertChanges func(*plan.Changes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p FakeWebhookProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error) {
|
func (p FakeWebhookProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error) {
|
||||||
@ -51,6 +54,9 @@ func (p FakeWebhookProvider) ApplyChanges(ctx context.Context, changes *plan.Cha
|
|||||||
return p.err
|
return p.err
|
||||||
}
|
}
|
||||||
records = append(records, changes.Create...)
|
records = append(records, changes.Create...)
|
||||||
|
if p.assertChanges != nil {
|
||||||
|
p.assertChanges(changes)
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +83,7 @@ func TestMain(m *testing.M) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRecordsHandlerRecords(t *testing.T) {
|
func TestRecordsHandlerRecords(t *testing.T) {
|
||||||
req := httptest.NewRequest(http.MethodGet, "/records", nil)
|
req := httptest.NewRequest(http.MethodGet, UrlRecords, nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
providerAPIServer := &WebhookServer{
|
providerAPIServer := &WebhookServer{
|
||||||
@ -99,7 +105,7 @@ func TestRecordsHandlerRecords(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRecordsHandlerRecordsWithErrors(t *testing.T) {
|
func TestRecordsHandlerRecordsWithErrors(t *testing.T) {
|
||||||
req := httptest.NewRequest(http.MethodGet, "/records", nil)
|
req := httptest.NewRequest(http.MethodGet, UrlRecords, nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
providerAPIServer := &WebhookServer{
|
providerAPIServer := &WebhookServer{
|
||||||
@ -139,7 +145,7 @@ func TestRecordsHandlerApplyChangesWithValidRequest(t *testing.T) {
|
|||||||
|
|
||||||
reader := bytes.NewReader(j)
|
reader := bytes.NewReader(j)
|
||||||
|
|
||||||
req := httptest.NewRequest(http.MethodPost, "/applychanges", reader)
|
req := httptest.NewRequest(http.MethodPost, UrlApplyChanges, reader)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
providerAPIServer := &WebhookServer{
|
providerAPIServer := &WebhookServer{
|
||||||
@ -165,7 +171,7 @@ func TestRecordsHandlerApplyChangesWithErrors(t *testing.T) {
|
|||||||
|
|
||||||
reader := bytes.NewReader(j)
|
reader := bytes.NewReader(j)
|
||||||
|
|
||||||
req := httptest.NewRequest(http.MethodPost, "/applychanges", reader)
|
req := httptest.NewRequest(http.MethodPost, UrlApplyChanges, reader)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
providerAPIServer := &WebhookServer{
|
providerAPIServer := &WebhookServer{
|
||||||
@ -179,7 +185,7 @@ func TestRecordsHandlerApplyChangesWithErrors(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestRecordsHandlerWithWrongHTTPMethod(t *testing.T) {
|
func TestRecordsHandlerWithWrongHTTPMethod(t *testing.T) {
|
||||||
req := httptest.NewRequest(http.MethodPut, "/records", nil)
|
req := httptest.NewRequest(http.MethodPut, UrlRecords, nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
providerAPIServer := &WebhookServer{
|
providerAPIServer := &WebhookServer{
|
||||||
@ -190,8 +196,43 @@ func TestRecordsHandlerWithWrongHTTPMethod(t *testing.T) {
|
|||||||
require.Equal(t, http.StatusBadRequest, res.StatusCode)
|
require.Equal(t, http.StatusBadRequest, res.StatusCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRecordsHandlerWithMixedCase(t *testing.T) {
|
||||||
|
input := `{"Create":[{"dnsName":"foo"}],"updateOld":[{"dnsName":"bar"}],"updateNew":[{"dnsName":"baz"}],"Delete":[{"dnsName":"qux"}]}`
|
||||||
|
req := httptest.NewRequest(http.MethodPost, UrlRecords, strings.NewReader(input))
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
records = []*endpoint.Endpoint{}
|
||||||
|
|
||||||
|
providerAPIServer := &WebhookServer{
|
||||||
|
Provider: &FakeWebhookProvider{
|
||||||
|
assertChanges: func(changes *plan.Changes) {
|
||||||
|
t.Helper()
|
||||||
|
require.Equal(t, []*endpoint.Endpoint{
|
||||||
|
{
|
||||||
|
DNSName: "foo",
|
||||||
|
},
|
||||||
|
}, changes.Create)
|
||||||
|
require.Equal(t, []*endpoint.Endpoint{
|
||||||
|
{
|
||||||
|
DNSName: "bar",
|
||||||
|
},
|
||||||
|
}, changes.UpdateOld)
|
||||||
|
require.Equal(t, []*endpoint.Endpoint{
|
||||||
|
{
|
||||||
|
DNSName: "qux",
|
||||||
|
},
|
||||||
|
}, changes.Delete)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
providerAPIServer.RecordsHandler(w, req)
|
||||||
|
res := w.Result()
|
||||||
|
require.Equal(t, http.StatusNoContent, res.StatusCode)
|
||||||
|
assert.Equal(t, 1, len(records))
|
||||||
|
}
|
||||||
|
|
||||||
func TestAdjustEndpointsHandlerWithInvalidRequest(t *testing.T) {
|
func TestAdjustEndpointsHandlerWithInvalidRequest(t *testing.T) {
|
||||||
req := httptest.NewRequest(http.MethodPost, "/adjustendpoints", nil)
|
req := httptest.NewRequest(http.MethodPost, UrlAdjustEndpoints, nil)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
providerAPIServer := &WebhookServer{
|
providerAPIServer := &WebhookServer{
|
||||||
@ -201,7 +242,7 @@ func TestAdjustEndpointsHandlerWithInvalidRequest(t *testing.T) {
|
|||||||
res := w.Result()
|
res := w.Result()
|
||||||
require.Equal(t, http.StatusBadRequest, res.StatusCode)
|
require.Equal(t, http.StatusBadRequest, res.StatusCode)
|
||||||
|
|
||||||
req = httptest.NewRequest(http.MethodGet, "/adjustendpoints", nil)
|
req = httptest.NewRequest(http.MethodGet, UrlAdjustEndpoints, nil)
|
||||||
|
|
||||||
providerAPIServer.AdjustEndpointsHandler(w, req)
|
providerAPIServer.AdjustEndpointsHandler(w, req)
|
||||||
res = w.Result()
|
res = w.Result()
|
||||||
@ -222,7 +263,7 @@ func TestAdjustEndpointsHandlerWithValidRequest(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
reader := bytes.NewReader(j)
|
reader := bytes.NewReader(j)
|
||||||
req := httptest.NewRequest(http.MethodPost, "/adjustendpoints", reader)
|
req := httptest.NewRequest(http.MethodPost, UrlAdjustEndpoints, reader)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
providerAPIServer := &WebhookServer{
|
providerAPIServer := &WebhookServer{
|
||||||
@ -248,7 +289,7 @@ func TestAdjustEndpointsHandlerWithError(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
reader := bytes.NewReader(j)
|
reader := bytes.NewReader(j)
|
||||||
req := httptest.NewRequest(http.MethodPost, "/adjustendpoints", reader)
|
req := httptest.NewRequest(http.MethodPost, UrlAdjustEndpoints, reader)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
providerAPIServer := &WebhookServer{
|
providerAPIServer := &WebhookServer{
|
||||||
|
@ -30,7 +30,7 @@ import (
|
|||||||
"sigs.k8s.io/external-dns/provider"
|
"sigs.k8s.io/external-dns/provider"
|
||||||
webhookapi "sigs.k8s.io/external-dns/provider/webhook/api"
|
webhookapi "sigs.k8s.io/external-dns/provider/webhook/api"
|
||||||
|
|
||||||
"github.com/cenkalti/backoff/v4"
|
"github.com/cenkalti/backoff/v5"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@ -113,45 +113,30 @@ func NewWebhookProvider(u string) (*WebhookProvider, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// negotiate API information
|
// negotiate API information
|
||||||
req, err := http.NewRequest("GET", u, nil)
|
req, err := http.NewRequest(http.MethodGet, u, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.Header.Set(acceptHeader, webhookapi.MediaTypeFormatAndVersion)
|
req.Header.Set(acceptHeader, webhookapi.MediaTypeFormatAndVersion)
|
||||||
|
|
||||||
client := &http.Client{}
|
client := &http.Client{}
|
||||||
var resp *http.Response
|
|
||||||
err = backoff.Retry(func() error {
|
|
||||||
resp, err = client.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
log.Debugf("Failed to connect to webhook: %v", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// we currently only use 200 as success, but considering okay all 2XX for future usage
|
|
||||||
if resp.StatusCode >= 300 && resp.StatusCode < 500 {
|
|
||||||
return backoff.Permanent(fmt.Errorf("status code < 500"))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}, backoff.WithMaxRetries(backoff.NewExponentialBackOff(), maxRetries))
|
|
||||||
|
|
||||||
|
resp, err := requestWithRetry(client, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to connect to webhook: %v", err)
|
return nil, fmt.Errorf("failed to connect to webhook: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
contentType := resp.Header.Get(webhookapi.ContentTypeHeader)
|
|
||||||
|
|
||||||
// read the serialized DomainFilter from the response body and set it in the webhook provider struct
|
// read the serialized DomainFilter from the response body and set it in the webhook provider struct
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
if ct := resp.Header.Get(webhookapi.ContentTypeHeader); ct != webhookapi.MediaTypeFormatAndVersion {
|
||||||
|
return nil, fmt.Errorf("wrong content type returned from server: %s", ct)
|
||||||
|
}
|
||||||
|
|
||||||
df := endpoint.DomainFilter{}
|
df := endpoint.DomainFilter{}
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&df); err != nil {
|
if err := json.NewDecoder(resp.Body).Decode(&df); err != nil {
|
||||||
return nil, fmt.Errorf("failed to unmarshal response body of DomainFilter: %v", err)
|
return nil, fmt.Errorf("failed to unmarshal response body of DomainFilter: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if contentType != webhookapi.MediaTypeFormatAndVersion {
|
|
||||||
return nil, fmt.Errorf("wrong content type returned from server: %s", contentType)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &WebhookProvider{
|
return &WebhookProvider{
|
||||||
client: client,
|
client: client,
|
||||||
remoteServerURL: parsedURL,
|
remoteServerURL: parsedURL,
|
||||||
@ -159,12 +144,28 @@ func NewWebhookProvider(u string) (*WebhookProvider, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func requestWithRetry(client *http.Client, req *http.Request) (*http.Response, error) {
|
||||||
|
resp, err := backoff.Retry(context.Background(), func() (*http.Response, error) {
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
log.Debugf("Failed to connect to webhook: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// we currently only use 200 as success, but considering okay all 2XX for future usage
|
||||||
|
if resp.StatusCode >= http.StatusMultipleChoices && resp.StatusCode < http.StatusInternalServerError {
|
||||||
|
return nil, backoff.Permanent(fmt.Errorf("status code < %d", http.StatusInternalServerError))
|
||||||
|
}
|
||||||
|
return resp, nil
|
||||||
|
}, backoff.WithMaxTries(maxRetries))
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
// Records will make a GET call to remoteServerURL/records and return the results
|
// Records will make a GET call to remoteServerURL/records and return the results
|
||||||
func (p WebhookProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error) {
|
func (p WebhookProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error) {
|
||||||
recordsRequestsGauge.Gauge.Inc()
|
recordsRequestsGauge.Gauge.Inc()
|
||||||
u := p.remoteServerURL.JoinPath("records").String()
|
u := p.remoteServerURL.JoinPath("records").String()
|
||||||
|
|
||||||
req, err := http.NewRequest("GET", u, nil)
|
req, err := http.NewRequest(http.MethodGet, u, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
recordsErrorsGauge.Gauge.Inc()
|
recordsErrorsGauge.Gauge.Inc()
|
||||||
log.Debugf("Failed to create request: %s", err.Error())
|
log.Debugf("Failed to create request: %s", err.Error())
|
||||||
@ -189,7 +190,7 @@ func (p WebhookProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, err
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints := []*endpoint.Endpoint{}
|
var endpoints []*endpoint.Endpoint
|
||||||
if err := json.NewDecoder(resp.Body).Decode(&endpoints); err != nil {
|
if err := json.NewDecoder(resp.Body).Decode(&endpoints); err != nil {
|
||||||
recordsErrorsGauge.Gauge.Inc()
|
recordsErrorsGauge.Gauge.Inc()
|
||||||
log.Debugf("Failed to decode response body: %s", err.Error())
|
log.Debugf("Failed to decode response body: %s", err.Error())
|
||||||
@ -199,9 +200,9 @@ func (p WebhookProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ApplyChanges will make a POST to remoteServerURL/records with the changes
|
// ApplyChanges will make a POST to remoteServerURL/records with the changes
|
||||||
func (p WebhookProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
|
func (p WebhookProvider) ApplyChanges(_ context.Context, changes *plan.Changes) error {
|
||||||
applyChangesRequestsGauge.Gauge.Inc()
|
applyChangesRequestsGauge.Gauge.Inc()
|
||||||
u := p.remoteServerURL.JoinPath("records").String()
|
u := p.remoteServerURL.JoinPath(webhookapi.UrlRecords).String()
|
||||||
|
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
if err := json.NewEncoder(b).Encode(changes); err != nil {
|
if err := json.NewEncoder(b).Encode(changes); err != nil {
|
||||||
@ -210,7 +211,7 @@ func (p WebhookProvider) ApplyChanges(ctx context.Context, changes *plan.Changes
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", u, b)
|
req, err := http.NewRequest(http.MethodPost, u, b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
applyChangesErrorsGauge.Gauge.Inc()
|
applyChangesErrorsGauge.Gauge.Inc()
|
||||||
log.Debugf("Failed to create request: %s", err.Error())
|
log.Debugf("Failed to create request: %s", err.Error())
|
||||||
@ -225,6 +226,7 @@ func (p WebhookProvider) ApplyChanges(ctx context.Context, changes *plan.Changes
|
|||||||
log.Debugf("Failed to perform request: %s", err.Error())
|
log.Debugf("Failed to perform request: %s", err.Error())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusNoContent {
|
if resp.StatusCode != http.StatusNoContent {
|
||||||
@ -240,12 +242,12 @@ func (p WebhookProvider) ApplyChanges(ctx context.Context, changes *plan.Changes
|
|||||||
}
|
}
|
||||||
|
|
||||||
// AdjustEndpoints will call the provider doing a POST on `/adjustendpoints` which will return a list of modified endpoints
|
// AdjustEndpoints will call the provider doing a POST on `/adjustendpoints` which will return a list of modified endpoints
|
||||||
// based on a provider specific requirement.
|
// based on a provider-specific requirement.
|
||||||
// This method returns an empty slice in case there is a technical error on the provider's side so that no endpoints will be considered.
|
// This method returns an empty slice in case there is a technical error on the provider's side so that no endpoints will be considered.
|
||||||
func (p WebhookProvider) AdjustEndpoints(e []*endpoint.Endpoint) ([]*endpoint.Endpoint, error) {
|
func (p WebhookProvider) AdjustEndpoints(e []*endpoint.Endpoint) ([]*endpoint.Endpoint, error) {
|
||||||
adjustEndpointsRequestsGauge.Gauge.Inc()
|
adjustEndpointsRequestsGauge.Gauge.Inc()
|
||||||
endpoints := []*endpoint.Endpoint{}
|
var endpoints []*endpoint.Endpoint
|
||||||
u, err := url.JoinPath(p.remoteServerURL.String(), "adjustendpoints")
|
u, err := url.JoinPath(p.remoteServerURL.String(), webhookapi.UrlAdjustEndpoints)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
adjustEndpointsErrorsGauge.Gauge.Inc()
|
adjustEndpointsErrorsGauge.Gauge.Inc()
|
||||||
log.Debugf("Failed to join path, %s", err)
|
log.Debugf("Failed to join path, %s", err)
|
||||||
@ -259,7 +261,7 @@ func (p WebhookProvider) AdjustEndpoints(e []*endpoint.Endpoint) ([]*endpoint.En
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", u, b)
|
req, err := http.NewRequest(http.MethodPost, u, b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
adjustEndpointsErrorsGauge.Gauge.Inc()
|
adjustEndpointsErrorsGauge.Gauge.Inc()
|
||||||
log.Debugf("Failed to create new HTTP request, %s", err)
|
log.Debugf("Failed to create new HTTP request, %s", err)
|
||||||
|
@ -22,8 +22,11 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"sigs.k8s.io/external-dns/endpoint"
|
"sigs.k8s.io/external-dns/endpoint"
|
||||||
"sigs.k8s.io/external-dns/plan"
|
"sigs.k8s.io/external-dns/plan"
|
||||||
@ -31,6 +34,55 @@ import (
|
|||||||
webhookapi "sigs.k8s.io/external-dns/provider/webhook/api"
|
webhookapi "sigs.k8s.io/external-dns/provider/webhook/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func TestNewWebhookProvider_InvalidURL(t *testing.T) {
|
||||||
|
_, err := NewWebhookProvider("://invalid-url")
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewWebhookProvider_HTTPRequestFailure(t *testing.T) {
|
||||||
|
_, err := NewWebhookProvider("http://nonexistent.url")
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewWebhookProvider_InvalidResponseBody(t *testing.T) {
|
||||||
|
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.Header().Set(webhookapi.ContentTypeHeader, webhookapi.MediaTypeFormatAndVersion)
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
w.Write([]byte("invalid-json")) // Invalid JSON
|
||||||
|
}))
|
||||||
|
defer svr.Close()
|
||||||
|
|
||||||
|
_, err := NewWebhookProvider(svr.URL)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "failed to unmarshal response body of DomainFilter")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewWebhookProvider_Non2XXStatusCode(t *testing.T) {
|
||||||
|
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
}))
|
||||||
|
defer svr.Close()
|
||||||
|
|
||||||
|
_, err := NewWebhookProvider(svr.URL)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "status code < 500")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewWebhookProvider_WrongContentTypeHeader(t *testing.T) {
|
||||||
|
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.URL.Path == "/" {
|
||||||
|
w.Header().Set(webhookapi.ContentTypeHeader, webhookapi.MediaTypeFormatAndVersion+"wrong")
|
||||||
|
_, _ = w.Write([]byte(`{}`))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
defer svr.Close()
|
||||||
|
|
||||||
|
_, err := NewWebhookProvider(svr.URL)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "wrong content type returned from server")
|
||||||
|
}
|
||||||
|
|
||||||
func TestInvalidDomainFilter(t *testing.T) {
|
func TestInvalidDomainFilter(t *testing.T) {
|
||||||
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.URL.Path == "/" {
|
if r.URL.Path == "/" {
|
||||||
@ -108,6 +160,68 @@ func TestRecordsWithErrors(t *testing.T) {
|
|||||||
require.ErrorIs(t, err, provider.SoftError)
|
require.ErrorIs(t, err, provider.SoftError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRecords_HTTPRequestErrorMissingHost0(t *testing.T) {
|
||||||
|
wpr := WebhookProvider{
|
||||||
|
remoteServerURL: &url.URL{Scheme: "http", Host: "example\\x00.com", Path: "\\x00"},
|
||||||
|
client: &http.Client{},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := wpr.Records(nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "invalid URL escape")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRecords_HTTPRequestErrorMissingHost(t *testing.T) {
|
||||||
|
wpr := WebhookProvider{
|
||||||
|
remoteServerURL: &url.URL{Host: "example.com", Path: "\\x00"},
|
||||||
|
client: &http.Client{},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := wpr.Records(nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "unsupported protocol scheme")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRecords_DecodeError(t *testing.T) {
|
||||||
|
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.URL.Path == webhookapi.UrlRecords {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
_, _ = w.Write([]byte("invalid-json")) // Simulate invalid JSON response
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
defer svr.Close()
|
||||||
|
|
||||||
|
parsedURL, _ := url.Parse(svr.URL)
|
||||||
|
p := WebhookProvider{
|
||||||
|
remoteServerURL: parsedURL,
|
||||||
|
client: &http.Client{},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := p.Records(context.Background())
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "invalid character 'i' looking for beginning of value")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRecords_NonOKStatusCode(t *testing.T) {
|
||||||
|
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusNetworkAuthenticationRequired)
|
||||||
|
return
|
||||||
|
}))
|
||||||
|
defer svr.Close()
|
||||||
|
|
||||||
|
parsedURL, _ := url.Parse(svr.URL)
|
||||||
|
|
||||||
|
p := WebhookProvider{
|
||||||
|
remoteServerURL: &url.URL{Scheme: parsedURL.Scheme, Host: parsedURL.Host},
|
||||||
|
client: &http.Client{},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := p.Records(nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "failed to get records with code 511")
|
||||||
|
}
|
||||||
|
|
||||||
func TestApplyChanges(t *testing.T) {
|
func TestApplyChanges(t *testing.T) {
|
||||||
successfulApplyChanges := true
|
successfulApplyChanges := true
|
||||||
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
@ -137,6 +251,49 @@ func TestApplyChanges(t *testing.T) {
|
|||||||
require.ErrorIs(t, err, provider.SoftError)
|
require.ErrorIs(t, err, provider.SoftError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestApplyChanges_HTTPNewRequestErrorWrongHost(t *testing.T) {
|
||||||
|
wpr := WebhookProvider{
|
||||||
|
remoteServerURL: &url.URL{Host: "exa\\x00mple.com"},
|
||||||
|
client: &http.Client{},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := wpr.ApplyChanges(context.Background(), nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "invalid URL escape")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApplyChanges_GetFailed(t *testing.T) {
|
||||||
|
p := WebhookProvider{
|
||||||
|
remoteServerURL: &url.URL{Host: "localhost"},
|
||||||
|
client: &http.Client{},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := p.ApplyChanges(context.TODO(), &plan.Changes{})
|
||||||
|
require.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "unsupported protocol scheme")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestApplyChanges_StatusCodeError(t *testing.T) {
|
||||||
|
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.URL.Path == "/" {
|
||||||
|
w.Header().Set(webhookapi.ContentTypeHeader, webhookapi.MediaTypeFormatAndVersion)
|
||||||
|
w.Write([]byte(`{}`))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
require.Equal(t, webhookapi.UrlRecords, r.URL.Path)
|
||||||
|
w.WriteHeader(http.StatusNetworkAuthenticationRequired)
|
||||||
|
}))
|
||||||
|
defer svr.Close()
|
||||||
|
|
||||||
|
p, err := NewWebhookProvider(svr.URL)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = p.ApplyChanges(context.TODO(), nil)
|
||||||
|
require.NotNil(t, err)
|
||||||
|
require.NotErrorIs(t, err, provider.SoftError)
|
||||||
|
assert.Contains(t, err.Error(), "failed to apply changes with code 511")
|
||||||
|
}
|
||||||
|
|
||||||
func TestAdjustEndpoints(t *testing.T) {
|
func TestAdjustEndpoints(t *testing.T) {
|
||||||
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
if r.URL.Path == "/" {
|
if r.URL.Path == "/" {
|
||||||
@ -144,7 +301,7 @@ func TestAdjustEndpoints(t *testing.T) {
|
|||||||
w.Write([]byte(`{}`))
|
w.Write([]byte(`{}`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
require.Equal(t, "/adjustendpoints", r.URL.Path)
|
require.Equal(t, webhookapi.UrlAdjustEndpoints, r.URL.Path)
|
||||||
|
|
||||||
var endpoints []*endpoint.Endpoint
|
var endpoints []*endpoint.Endpoint
|
||||||
defer r.Body.Close()
|
defer r.Body.Close()
|
||||||
@ -162,7 +319,6 @@ func TestAdjustEndpoints(t *testing.T) {
|
|||||||
}
|
}
|
||||||
j, _ := json.Marshal(endpoints)
|
j, _ := json.Marshal(endpoints)
|
||||||
w.Write(j)
|
w.Write(j)
|
||||||
|
|
||||||
}))
|
}))
|
||||||
defer svr.Close()
|
defer svr.Close()
|
||||||
|
|
||||||
@ -197,7 +353,7 @@ func TestAdjustendpointsWithError(t *testing.T) {
|
|||||||
w.Write([]byte(`{}`))
|
w.Write([]byte(`{}`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
require.Equal(t, "/adjustendpoints", r.URL.Path)
|
require.Equal(t, webhookapi.UrlAdjustEndpoints, r.URL.Path)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
}))
|
}))
|
||||||
defer svr.Close()
|
defer svr.Close()
|
||||||
@ -269,3 +425,108 @@ func TestApplyChangesWithProviderSpecificProperty(t *testing.T) {
|
|||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAdjustEndpoints_JoinPathError(t *testing.T) {
|
||||||
|
wpr := WebhookProvider{
|
||||||
|
remoteServerURL: &url.URL{Scheme: "http", Host: "example\\x00.com"},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := wpr.AdjustEndpoints(nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "invalid URL escape")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAdjustEndpoints_HTTPRequestErrorMissingHost(t *testing.T) {
|
||||||
|
wpr := WebhookProvider{
|
||||||
|
remoteServerURL: &url.URL{Host: "example.com", Path: "\\x00"},
|
||||||
|
client: &http.Client{},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := wpr.AdjustEndpoints(nil)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "unsupported protocol scheme") // Ensure the "BINGO" log is triggered
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAdjustEndpoints_NonOKStatusCode(t *testing.T) {
|
||||||
|
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusNetworkAuthenticationRequired)
|
||||||
|
return
|
||||||
|
}))
|
||||||
|
defer svr.Close()
|
||||||
|
|
||||||
|
parsedURL, _ := url.Parse(svr.URL)
|
||||||
|
|
||||||
|
p := WebhookProvider{
|
||||||
|
remoteServerURL: &url.URL{Scheme: parsedURL.Scheme, Host: parsedURL.Host},
|
||||||
|
client: &http.Client{},
|
||||||
|
}
|
||||||
|
|
||||||
|
endpoints := []*endpoint.Endpoint{
|
||||||
|
{
|
||||||
|
DNSName: "test.example.com",
|
||||||
|
RecordTTL: 10,
|
||||||
|
RecordType: "A",
|
||||||
|
Targets: endpoint.Targets{""},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := p.AdjustEndpoints(endpoints)
|
||||||
|
require.Error(t, err)
|
||||||
|
assert.Contains(t, err.Error(), "failed to AdjustEndpoints with code 511")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAdjustEndpoints_DecodeError(t *testing.T) {
|
||||||
|
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.URL.Path == webhookapi.UrlAdjustEndpoints {
|
||||||
|
w.Header().Set(webhookapi.ContentTypeHeader, webhookapi.MediaTypeFormatAndVersion)
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
_, _ = w.Write([]byte("invalid-json")) // Simulate invalid JSON response
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
defer svr.Close()
|
||||||
|
|
||||||
|
parsedURL, _ := url.Parse(svr.URL)
|
||||||
|
p := WebhookProvider{
|
||||||
|
remoteServerURL: parsedURL,
|
||||||
|
client: &http.Client{},
|
||||||
|
}
|
||||||
|
|
||||||
|
var endpoints []*endpoint.Endpoint
|
||||||
|
|
||||||
|
_, err := p.AdjustEndpoints(endpoints)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Contains(t, err.Error(), "invalid character 'i' looking for beginning of value")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRequestWithRetry_Success(t *testing.T) {
|
||||||
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusOK)
|
||||||
|
io.WriteString(w, "ok")
|
||||||
|
}))
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client := &http.Client{Timeout: 2 * time.Second}
|
||||||
|
req, err := http.NewRequest(http.MethodGet, server.URL, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
resp, err := requestWithRetry(client, req)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, resp)
|
||||||
|
require.Equal(t, http.StatusOK, resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRequestWithRetry_NonRetriableStatus(t *testing.T) {
|
||||||
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
}))
|
||||||
|
defer server.Close()
|
||||||
|
|
||||||
|
client := &http.Client{Timeout: 2 * time.Second}
|
||||||
|
req, err := http.NewRequest(http.MethodGet, server.URL, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
resp, err := requestWithRetry(client, req)
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Nil(t, resp)
|
||||||
|
}
|
||||||
|
@ -29,12 +29,34 @@ func (z ZoneIDName) Add(zoneID, zoneName string) {
|
|||||||
z[zoneID] = zoneName
|
z[zoneID] = zoneName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindZone identifies the most suitable DNS zone for a given hostname.
|
||||||
|
// It returns the zone ID and name that best match the hostname.
|
||||||
|
//
|
||||||
|
// The function processes the hostname by splitting it into labels and
|
||||||
|
// converting each label to its Unicode form using IDNA (Internationalized
|
||||||
|
// Domain Names for Applications) standards.
|
||||||
|
//
|
||||||
|
// Labels containing underscores ('_') are skipped during Unicode conversion.
|
||||||
|
// This is because underscores are often used in special DNS records (e.g.,
|
||||||
|
// SRV records as per RFC 2782, or TXT record for services) that are not
|
||||||
|
// IDNA-aware and cannot represent non-ASCII labels. Skipping these labels
|
||||||
|
// ensures compatibility with such use cases.
|
||||||
func (z ZoneIDName) FindZone(hostname string) (suitableZoneID, suitableZoneName string) {
|
func (z ZoneIDName) FindZone(hostname string) (suitableZoneID, suitableZoneName string) {
|
||||||
name, err := idna.Lookup.ToUnicode(hostname)
|
var name string
|
||||||
if err != nil {
|
domain_labels := strings.Split(hostname, ".")
|
||||||
log.Warnf("Failed to convert hostname '%s' to its Unicode form: %v", hostname, err)
|
for i, label := range domain_labels {
|
||||||
name = hostname
|
if strings.Contains(label, "_") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
convertedLabel, err := idna.Lookup.ToUnicode(label)
|
||||||
|
if err != nil {
|
||||||
|
log.Warnf("Failed to convert label '%s' of hostname '%s' to its Unicode form: %v", label, hostname, err)
|
||||||
|
convertedLabel = label
|
||||||
|
}
|
||||||
|
domain_labels[i] = convertedLabel
|
||||||
}
|
}
|
||||||
|
name = strings.Join(domain_labels, ".")
|
||||||
|
|
||||||
for zoneID, zoneName := range z {
|
for zoneID, zoneName := range z {
|
||||||
if name == zoneName || strings.HasSuffix(name, "."+zoneName) {
|
if name == zoneName || strings.HasSuffix(name, "."+zoneName) {
|
||||||
if suitableZoneName == "" || len(zoneName) > len(suitableZoneName) {
|
if suitableZoneName == "" || len(zoneName) > len(suitableZoneName) {
|
||||||
|
@ -30,11 +30,15 @@ func TestZoneIDName(t *testing.T) {
|
|||||||
z.Add("123456", "qux.baz")
|
z.Add("123456", "qux.baz")
|
||||||
z.Add("654321", "foo.qux.baz")
|
z.Add("654321", "foo.qux.baz")
|
||||||
z.Add("987654", "エイミー.みんな")
|
z.Add("987654", "エイミー.みんな")
|
||||||
|
z.Add("123123", "_metadata.example.com")
|
||||||
|
z.Add("456456", "_metadata.エイミー.みんな")
|
||||||
|
|
||||||
assert.Equal(t, ZoneIDName{
|
assert.Equal(t, ZoneIDName{
|
||||||
"123456": "qux.baz",
|
"123456": "qux.baz",
|
||||||
"654321": "foo.qux.baz",
|
"654321": "foo.qux.baz",
|
||||||
"987654": "エイミー.みんな",
|
"987654": "エイミー.みんな",
|
||||||
|
"123123": "_metadata.example.com",
|
||||||
|
"456456": "_metadata.エイミー.みんな",
|
||||||
}, z)
|
}, z)
|
||||||
|
|
||||||
// simple entry in a domain
|
// simple entry in a domain
|
||||||
@ -72,7 +76,8 @@ func TestZoneIDName(t *testing.T) {
|
|||||||
assert.Equal(t, "エイミー.みんな", zoneName)
|
assert.Equal(t, "エイミー.みんな", zoneName)
|
||||||
assert.Equal(t, "987654", zoneID)
|
assert.Equal(t, "987654", zoneID)
|
||||||
|
|
||||||
b := testutils.LogsToBuffer(log.WarnLevel, t)
|
hook := testutils.LogsUnderTestWithLogLevel(log.WarnLevel, t)
|
||||||
zoneID, zoneName = z.FindZone("???")
|
_, _ = z.FindZone("???")
|
||||||
assert.Contains(t, b.String(), "level=warning msg=\"Failed to convert hostname '???' to its Unicode form: idna: disallowed rune U+003F\"")
|
|
||||||
|
testutils.TestHelperLogContains("Failed to convert label '???' of hostname '???' to its Unicode form: idna: disallowed rune U+003F", hook, t)
|
||||||
}
|
}
|
||||||
|
@ -300,12 +300,12 @@ func (im *DynamoDBRegistry) ApplyChanges(ctx context.Context, changes *plan.Chan
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for i, endpoint := range filteredChanges.Create {
|
for i, ep := range filteredChanges.Create {
|
||||||
if endpoint.Key() == key {
|
if ep.Key() == key {
|
||||||
log.Infof("Skipping endpoint %v because owner does not match", endpoint)
|
log.Infof("Skipping endpoint %v because owner does not match", ep)
|
||||||
filteredChanges.Create = append(filteredChanges.Create[:i], filteredChanges.Create[i+1:]...)
|
filteredChanges.Create = append(filteredChanges.Create[:i], filteredChanges.Create[i+1:]...)
|
||||||
// The dynamodb insertion failed; remove from our cache.
|
// The dynamodb insertion failed; remove from our cache.
|
||||||
im.removeFromCache(endpoint)
|
im.removeFromCache(ep)
|
||||||
delete(im.labels, key)
|
delete(im.labels, key)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -466,7 +466,7 @@ func toDynamoLabels(labels endpoint.Labels) dynamodbtypes.AttributeValue {
|
|||||||
return &dynamodbtypes.AttributeValueMemberM{Value: labelMap}
|
return &dynamodbtypes.AttributeValueMemberM{Value: labelMap}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (im *DynamoDBRegistry) appendInsert(statements []dynamodbtypes.BatchStatementRequest, key endpoint.EndpointKey, new endpoint.Labels) []dynamodbtypes.BatchStatementRequest {
|
func (im *DynamoDBRegistry) appendInsert(statements []dynamodbtypes.BatchStatementRequest, key endpoint.EndpointKey, newL endpoint.Labels) []dynamodbtypes.BatchStatementRequest {
|
||||||
return append(statements, dynamodbtypes.BatchStatementRequest{
|
return append(statements, dynamodbtypes.BatchStatementRequest{
|
||||||
Statement: aws.String(fmt.Sprintf("INSERT INTO %q VALUE {'k':?, 'o':?, 'l':?}", im.table)),
|
Statement: aws.String(fmt.Sprintf("INSERT INTO %q VALUE {'k':?, 'o':?, 'l':?}", im.table)),
|
||||||
ConsistentRead: aws.Bool(true),
|
ConsistentRead: aws.Bool(true),
|
||||||
@ -475,16 +475,16 @@ func (im *DynamoDBRegistry) appendInsert(statements []dynamodbtypes.BatchStateme
|
|||||||
&dynamodbtypes.AttributeValueMemberS{
|
&dynamodbtypes.AttributeValueMemberS{
|
||||||
Value: im.ownerID,
|
Value: im.ownerID,
|
||||||
},
|
},
|
||||||
toDynamoLabels(new),
|
toDynamoLabels(newL),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (im *DynamoDBRegistry) appendUpdate(statements []dynamodbtypes.BatchStatementRequest, key endpoint.EndpointKey, old endpoint.Labels, new endpoint.Labels) []dynamodbtypes.BatchStatementRequest {
|
func (im *DynamoDBRegistry) appendUpdate(statements []dynamodbtypes.BatchStatementRequest, key endpoint.EndpointKey, old endpoint.Labels, newE endpoint.Labels) []dynamodbtypes.BatchStatementRequest {
|
||||||
if len(old) == len(new) {
|
if len(old) == len(newE) {
|
||||||
equal := true
|
equal := true
|
||||||
for k, v := range old {
|
for k, v := range old {
|
||||||
if newV, exists := new[k]; !exists || v != newV {
|
if newV, exists := newE[k]; !exists || v != newV {
|
||||||
equal = false
|
equal = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -497,7 +497,7 @@ func (im *DynamoDBRegistry) appendUpdate(statements []dynamodbtypes.BatchStateme
|
|||||||
return append(statements, dynamodbtypes.BatchStatementRequest{
|
return append(statements, dynamodbtypes.BatchStatementRequest{
|
||||||
Statement: aws.String(fmt.Sprintf("UPDATE %q SET \"l\"=? WHERE \"k\"=?", im.table)),
|
Statement: aws.String(fmt.Sprintf("UPDATE %q SET \"l\"=? WHERE \"k\"=?", im.table)),
|
||||||
Parameters: []dynamodbtypes.AttributeValue{
|
Parameters: []dynamodbtypes.AttributeValue{
|
||||||
toDynamoLabels(new),
|
toDynamoLabels(newE),
|
||||||
toDynamoKey(key),
|
toDynamoKey(key),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -1821,7 +1821,7 @@ func TestTXTRegistryRecordsWithEmptyTargets(t *testing.T) {
|
|||||||
})
|
})
|
||||||
|
|
||||||
r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, nil, false)
|
r, _ := NewTXTRegistry(p, "", "", "owner", time.Hour, "", []string{}, []string{}, false, nil, false)
|
||||||
b := testutils.LogsToBuffer(log.ErrorLevel, t)
|
hook := testutils.LogsUnderTestWithLogLevel(log.ErrorLevel, t)
|
||||||
records, err := r.Records(ctx)
|
records, err := r.Records(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
@ -1835,5 +1835,6 @@ func TestTXTRegistryRecordsWithEmptyTargets(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert.True(t, testutils.SameEndpoints(records, expectedRecords))
|
assert.True(t, testutils.SameEndpoints(records, expectedRecords))
|
||||||
assert.Contains(t, b.String(), "TXT record has no targets empty-targets.test-zone.example.org")
|
|
||||||
|
testutils.TestHelperLogContains("TXT record has no targets empty-targets.test-zone.example.org", hook, t)
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ function main() {
|
|||||||
helm_unittest
|
helm_unittest
|
||||||
;;
|
;;
|
||||||
--helm-template)
|
--helm-template)
|
||||||
helm_unittest
|
helm_template
|
||||||
;;
|
;;
|
||||||
-d|--diff)
|
-d|--diff)
|
||||||
diff_schema
|
diff_schema
|
||||||
|
@ -15,9 +15,9 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
# renovate: datasource=github-releases depName=kubernetes-sigs/controller-tools
|
# renovate: datasource=github-releases depName=kubernetes-sigs/controller-tools
|
||||||
CONTROLLER_TOOLS_GENERATOR_VERSION=v0.15.0
|
CONTROLLER_TOOLS_GENERATOR_VERSION=v0.17.2
|
||||||
# renovate: datasource=github-releases depName=golangci/golangci-lint
|
# renovate: datasource=github-releases depName=golangci/golangci-lint
|
||||||
GOLANG_CI_LINTER_VERSION=v2.0.2
|
GOLANG_CI_LINTER_VERSION=v2.1.6
|
||||||
|
|
||||||
# Execute
|
# Execute
|
||||||
# scripts/install-tools.sh
|
# scripts/install-tools.sh
|
||||||
|
@ -18,12 +18,12 @@ package source
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
ambassador "github.com/datawire/ambassador/pkg/api/getambassador.io/v2"
|
ambassador "github.com/datawire/ambassador/pkg/api/getambassador.io/v2"
|
||||||
"github.com/pkg/errors"
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
@ -97,7 +97,7 @@ func NewAmbassadorHostSource(
|
|||||||
|
|
||||||
uc, err := newUnstructuredConverter()
|
uc, err := newUnstructuredConverter()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrapf(err, "failed to setup Unstructured Converter")
|
return nil, fmt.Errorf("failed to setup Unstructured Converter: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ambassadorHostSource{
|
return &ambassadorHostSource{
|
||||||
@ -138,7 +138,7 @@ func (sc *ambassadorHostSource) Endpoints(ctx context.Context) ([]*endpoint.Endp
|
|||||||
// Filter Ambassador Hosts
|
// Filter Ambassador Hosts
|
||||||
ambassadorHosts, err = sc.filterByAnnotations(ambassadorHosts)
|
ambassadorHosts, err = sc.filterByAnnotations(ambassadorHosts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to filter Ambassador Hosts by annotation")
|
return nil, fmt.Errorf("failed to filter Ambassador Hosts by annotation: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var endpoints []*endpoint.Endpoint
|
var endpoints []*endpoint.Endpoint
|
||||||
@ -260,7 +260,7 @@ func parseAmbLoadBalancerService(service string) (namespace, name string, err er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we got here, this string is simply ill-formatted. Return an error.
|
// If we got here, this string is simply ill-formatted. Return an error.
|
||||||
return "", "", errors.New(fmt.Sprintf("invalid external-dns service: %s", service))
|
return "", "", fmt.Errorf("invalid external-dns service: %s", service)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (sc *ambassadorHostSource) AddEventHandler(ctx context.Context, handler func()) {
|
func (sc *ambassadorHostSource) AddEventHandler(ctx context.Context, handler func()) {
|
||||||
@ -311,9 +311,8 @@ func (sc *ambassadorHostSource) filterByAnnotations(ambassadorHosts []*ambassado
|
|||||||
// Return a filtered list of Ambassador Hosts
|
// Return a filtered list of Ambassador Hosts
|
||||||
filteredList := []*ambassador.Host{}
|
filteredList := []*ambassador.Host{}
|
||||||
for _, host := range ambassadorHosts {
|
for _, host := range ambassadorHosts {
|
||||||
annotations := labels.Set(host.Annotations)
|
|
||||||
// include Ambassador Host if its annotations match the annotation filter
|
// include Ambassador Host if its annotations match the annotation filter
|
||||||
if selector.Matches(annotations) {
|
if selector.Matches(labels.Set(host.Annotations)) {
|
||||||
filteredList = append(filteredList, host)
|
filteredList = append(filteredList, host)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,11 @@ func ProviderSpecificAnnotations(annotations map[string]string) (endpoint.Provid
|
|||||||
Name: CloudflareProxiedKey,
|
Name: CloudflareProxiedKey,
|
||||||
Value: v,
|
Value: v,
|
||||||
})
|
})
|
||||||
|
} else if strings.Contains(k, CloudflareRegionKey) {
|
||||||
|
providerSpecificAnnotations = append(providerSpecificAnnotations, endpoint.ProviderSpecificProperty{
|
||||||
|
Name: CloudflareRegionKey,
|
||||||
|
Value: v,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -125,6 +125,41 @@ func TestGetProviderSpecificCloudflareAnnotations(t *testing.T) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for _, tc := range []struct {
|
||||||
|
title string
|
||||||
|
annotations map[string]string
|
||||||
|
expectedKey string
|
||||||
|
expectedValue string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
title: "Cloudflare region key annotation is set correctly",
|
||||||
|
annotations: map[string]string{CloudflareRegionKey: "us"},
|
||||||
|
expectedKey: CloudflareRegionKey,
|
||||||
|
expectedValue: "us",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Cloudflare region key annotation among another annotations is set correctly",
|
||||||
|
annotations: map[string]string{
|
||||||
|
"random annotation 1": "random value 1",
|
||||||
|
CloudflareRegionKey: "us",
|
||||||
|
"random annotation 2": "random value 2",
|
||||||
|
},
|
||||||
|
expectedKey: CloudflareRegionKey,
|
||||||
|
expectedValue: "us",
|
||||||
|
},
|
||||||
|
} {
|
||||||
|
t.Run(tc.title, func(t *testing.T) {
|
||||||
|
providerSpecificAnnotations, _ := ProviderSpecificAnnotations(tc.annotations)
|
||||||
|
for _, providerSpecificAnnotation := range providerSpecificAnnotations {
|
||||||
|
if providerSpecificAnnotation.Name == tc.expectedKey {
|
||||||
|
assert.Equal(t, tc.expectedValue, providerSpecificAnnotation.Value)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.Errorf("Cloudflare provider specific annotation %s is not set correctly to %v", tc.expectedKey, tc.expectedValue)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
for _, tc := range []struct {
|
for _, tc := range []struct {
|
||||||
title string
|
title string
|
||||||
annotations map[string]string
|
annotations map[string]string
|
||||||
|
@ -18,11 +18,11 @@ package source
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
"text/template"
|
"text/template"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
projectcontour "github.com/projectcontour/contour/apis/projectcontour/v1"
|
projectcontour "github.com/projectcontour/contour/apis/projectcontour/v1"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
@ -33,6 +33,8 @@ import (
|
|||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
|
|
||||||
|
"sigs.k8s.io/external-dns/source/fqdn"
|
||||||
|
|
||||||
"sigs.k8s.io/external-dns/endpoint"
|
"sigs.k8s.io/external-dns/endpoint"
|
||||||
"sigs.k8s.io/external-dns/source/annotations"
|
"sigs.k8s.io/external-dns/source/annotations"
|
||||||
)
|
)
|
||||||
@ -61,7 +63,7 @@ func NewContourHTTPProxySource(
|
|||||||
combineFqdnAnnotation bool,
|
combineFqdnAnnotation bool,
|
||||||
ignoreHostnameAnnotation bool,
|
ignoreHostnameAnnotation bool,
|
||||||
) (Source, error) {
|
) (Source, error) {
|
||||||
tmpl, err := parseTemplate(fqdnTemplate)
|
tmpl, err := fqdn.ParseTemplate(fqdnTemplate)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -88,7 +90,7 @@ func NewContourHTTPProxySource(
|
|||||||
|
|
||||||
uc, err := NewUnstructuredConverter()
|
uc, err := NewUnstructuredConverter()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to setup Unstructured Converter")
|
return nil, fmt.Errorf("failed to setup Unstructured Converter: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &httpProxySource{
|
return &httpProxySource{
|
||||||
@ -122,14 +124,14 @@ func (sc *httpProxySource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint,
|
|||||||
hpConverted := &projectcontour.HTTPProxy{}
|
hpConverted := &projectcontour.HTTPProxy{}
|
||||||
err := sc.unstructuredConverter.scheme.Convert(unstructuredHP, hpConverted, nil)
|
err := sc.unstructuredConverter.scheme.Convert(unstructuredHP, hpConverted, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to convert to HTTPProxy")
|
return nil, fmt.Errorf("failed to convert to HTTPProxy: %w", err)
|
||||||
}
|
}
|
||||||
httpProxies = append(httpProxies, hpConverted)
|
httpProxies = append(httpProxies, hpConverted)
|
||||||
}
|
}
|
||||||
|
|
||||||
httpProxies, err = sc.filterByAnnotations(httpProxies)
|
httpProxies, err = sc.filterByAnnotations(httpProxies)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to filter HTTPProxies")
|
return nil, fmt.Errorf("failed to filter HTTPProxies: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
endpoints := []*endpoint.Endpoint{}
|
endpoints := []*endpoint.Endpoint{}
|
||||||
@ -145,14 +147,14 @@ func (sc *httpProxySource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint,
|
|||||||
|
|
||||||
hpEndpoints, err := sc.endpointsFromHTTPProxy(hp)
|
hpEndpoints, err := sc.endpointsFromHTTPProxy(hp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to get endpoints from HTTPProxy")
|
return nil, fmt.Errorf("failed to get endpoints from HTTPProxy: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply template if fqdn is missing on HTTPProxy
|
// apply template if fqdn is missing on HTTPProxy
|
||||||
if (sc.combineFQDNAnnotation || len(hpEndpoints) == 0) && sc.fqdnTemplate != nil {
|
if (sc.combineFQDNAnnotation || len(hpEndpoints) == 0) && sc.fqdnTemplate != nil {
|
||||||
tmplEndpoints, err := sc.endpointsFromTemplate(hp)
|
tmplEndpoints, err := sc.endpointsFromTemplate(hp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to get endpoints from template")
|
return nil, fmt.Errorf("failed to get endpoints from template: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if sc.combineFQDNAnnotation {
|
if sc.combineFQDNAnnotation {
|
||||||
|
@ -18,11 +18,11 @@ package source
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
fakeDynamic "k8s.io/client-go/dynamic/fake"
|
fakeDynamic "k8s.io/client-go/dynamic/fake"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
projectcontour "github.com/projectcontour/contour/apis/projectcontour/v1"
|
projectcontour "github.com/projectcontour/contour/apis/projectcontour/v1"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
@ -148,7 +148,7 @@ func (cs *crdSource) AddEventHandler(ctx context.Context, handler func()) {
|
|||||||
AddFunc: func(obj interface{}) {
|
AddFunc: func(obj interface{}) {
|
||||||
handler()
|
handler()
|
||||||
},
|
},
|
||||||
UpdateFunc: func(old interface{}, new interface{}) {
|
UpdateFunc: func(old interface{}, newI interface{}) {
|
||||||
handler()
|
handler()
|
||||||
},
|
},
|
||||||
DeleteFunc: func(obj interface{}) {
|
DeleteFunc: func(obj interface{}) {
|
||||||
@ -287,11 +287,8 @@ func (cs *crdSource) filterByAnnotations(dnsendpoints *endpoint.DNSEndpointList)
|
|||||||
filteredList := endpoint.DNSEndpointList{}
|
filteredList := endpoint.DNSEndpointList{}
|
||||||
|
|
||||||
for _, dnsendpoint := range dnsendpoints.Items {
|
for _, dnsendpoint := range dnsendpoints.Items {
|
||||||
// convert the dnsendpoint' annotations to an equivalent label selector
|
|
||||||
annotations := labels.Set(dnsendpoint.Annotations)
|
|
||||||
|
|
||||||
// include dnsendpoint if its annotations match the selector
|
// include dnsendpoint if its annotations match the selector
|
||||||
if selector.Matches(annotations) {
|
if selector.Matches(labels.Set(dnsendpoint.Annotations)) {
|
||||||
filteredList.Items = append(filteredList.Items, dnsendpoint)
|
filteredList.Items = append(filteredList.Items, dnsendpoint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,8 @@ import (
|
|||||||
"sigs.k8s.io/external-dns/endpoint"
|
"sigs.k8s.io/external-dns/endpoint"
|
||||||
)
|
)
|
||||||
|
|
||||||
func EndpointsForHostname(hostname string, targets endpoint.Targets, ttl endpoint.TTL, providerSpecific endpoint.ProviderSpecific, setIdentifier string, resource string) []*endpoint.Endpoint {
|
// endpointsForHostname returns the endpoint objects for each host-target combination.
|
||||||
|
func endpointsForHostname(hostname string, targets endpoint.Targets, ttl endpoint.TTL, providerSpecific endpoint.ProviderSpecific, setIdentifier string, resource string) []*endpoint.Endpoint {
|
||||||
var (
|
var (
|
||||||
endpoints []*endpoint.Endpoint
|
endpoints []*endpoint.Endpoint
|
||||||
aTargets endpoint.Targets
|
aTargets endpoint.Targets
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user