mirror of
https://github.com/kubernetes-sigs/external-dns.git
synced 2026-05-04 22:26:11 +02:00
Deployed 1a2d18f3 to v0.18.0 with MkDocs 1.5.3 and mike 2.0.0
This commit is contained in:
parent
87feca5cee
commit
71e164cca1
2968
v0.18.0/404.html
Normal file
2968
v0.18.0/404.html
Normal file
File diff suppressed because it is too large
Load Diff
3177
v0.18.0/CONTRIBUTING/index.html
Normal file
3177
v0.18.0/CONTRIBUTING/index.html
Normal file
File diff suppressed because it is too large
Load Diff
3219
v0.18.0/LICENSE/index.html
Normal file
3219
v0.18.0/LICENSE/index.html
Normal file
File diff suppressed because it is too large
Load Diff
265
v0.18.0/api/webhook.yaml
Normal file
265
v0.18.0/api/webhook.yaml
Normal file
@ -0,0 +1,265 @@
|
||||
---
|
||||
openapi: "3.0.0"
|
||||
info:
|
||||
version: v0.15.0
|
||||
title: External DNS Webhook Server
|
||||
description: >-
|
||||
Implements the external DNS webhook endpoints.
|
||||
contact:
|
||||
url: https://github.com/kubernetes-sigs/external-dns
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
tags:
|
||||
- name: initialization
|
||||
description: Endpoints for initial negotiation.
|
||||
- name: listing
|
||||
description: Endpoints to get listings of DNS records.
|
||||
- name: update
|
||||
description: Endpoints to update DNS records.
|
||||
servers:
|
||||
- url: http://localhost:8888
|
||||
description: Server url for a Kubernetes deployment.
|
||||
paths:
|
||||
/:
|
||||
get:
|
||||
summary: >-
|
||||
Initialisation and negotiates headers and returns domain
|
||||
filter.
|
||||
description: |
|
||||
Initialisation and negotiates headers and returns domain
|
||||
filter.
|
||||
operationId: negotiate
|
||||
tags: [initialization]
|
||||
responses:
|
||||
'200':
|
||||
description: |
|
||||
The list of domains this DNS provider serves.
|
||||
content:
|
||||
application/external.dns.webhook+json;version=1:
|
||||
schema:
|
||||
$ref: '#/components/schemas/filters'
|
||||
example:
|
||||
filters:
|
||||
- example.com
|
||||
'500':
|
||||
description: |
|
||||
Negotiation failed.
|
||||
|
||||
/records:
|
||||
get:
|
||||
summary: Returns the current records.
|
||||
description: |
|
||||
Get the current records from the DNS provider and return them.
|
||||
operationId: getRecords
|
||||
tags: [listing]
|
||||
responses:
|
||||
'200':
|
||||
description: |
|
||||
Provided the list of DNS records successfully.
|
||||
content:
|
||||
application/external.dns.webhook+json;version=1:
|
||||
schema:
|
||||
$ref: '#/components/schemas/endpoints'
|
||||
example:
|
||||
- dnsName: "test.example.com"
|
||||
recordTTL: 10
|
||||
recordType: 'A'
|
||||
targets:
|
||||
- "1.2.3.4"
|
||||
'500':
|
||||
description: |
|
||||
Failed to provide the list of DNS records.
|
||||
|
||||
post:
|
||||
summary: Applies the changes.
|
||||
description: |
|
||||
Set the records in the DNS provider based on those supplied here.
|
||||
operationId: setRecords
|
||||
tags: [update]
|
||||
requestBody:
|
||||
description: |
|
||||
This is the list of changes that need to be applied. There are
|
||||
four lists of endpoints. The `create` and `delete` lists are lists
|
||||
of records to create and delete respectively. The `updateOld` and
|
||||
`updateNew` lists are paired. For each entry there's the old version
|
||||
of the record and a new version of the record.
|
||||
required: true
|
||||
content:
|
||||
application/external.dns.webhook+json;version=1:
|
||||
schema:
|
||||
$ref: '#/components/schemas/changes'
|
||||
example:
|
||||
create:
|
||||
- dnsName: "test.example.com"
|
||||
recordTTL: 10
|
||||
recordType: 'A'
|
||||
responses:
|
||||
'204':
|
||||
description: |
|
||||
Changes were accepted.
|
||||
'500':
|
||||
description: |
|
||||
Changes were not accepted.
|
||||
|
||||
/adjustendpoints:
|
||||
post:
|
||||
summary: Executes the AdjustEndpoints method.
|
||||
description: |
|
||||
Adjusts the records in the provider based on those supplied here.
|
||||
operationId: adjustRecords
|
||||
tags: [update]
|
||||
requestBody:
|
||||
description: |
|
||||
This is the list of changes to be applied.
|
||||
required: true
|
||||
content:
|
||||
application/external.dns.webhook+json;version=1:
|
||||
schema:
|
||||
$ref: '#/components/schemas/endpoints'
|
||||
example:
|
||||
- dnsName: "test.example.com"
|
||||
recordTTL: 10
|
||||
recordType: 'A'
|
||||
targets:
|
||||
- "1.2.3.4"
|
||||
responses:
|
||||
'200':
|
||||
description: |
|
||||
Adjustments were accepted.
|
||||
content:
|
||||
application/external.dns.webhook+json;version=1:
|
||||
schema:
|
||||
$ref: '#/components/schemas/endpoints'
|
||||
example:
|
||||
- dnsName: "test.example.com"
|
||||
recordTTL: 0
|
||||
recordType: 'A'
|
||||
targets:
|
||||
- "1.2.3.4"
|
||||
'500':
|
||||
description: |
|
||||
Adjustments were not accepted.
|
||||
|
||||
components:
|
||||
schemas:
|
||||
filters:
|
||||
description: |
|
||||
external-dns will only create DNS records for host names (specified in ingress objects and services with the external-dns annotation) related to zones that match filters. They can set in external-dns deployment manifest.
|
||||
type: object
|
||||
properties:
|
||||
filters:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example: "foo.example.com"
|
||||
example:
|
||||
- ".example.com"
|
||||
example:
|
||||
filters:
|
||||
- ".example.com"
|
||||
- ".example.org"
|
||||
|
||||
endpoints:
|
||||
description: |
|
||||
This is a list of DNS records.
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/endpoint'
|
||||
example:
|
||||
- dnsName: foo.example.com
|
||||
recordType: A
|
||||
recordTTL: 60
|
||||
|
||||
endpoint:
|
||||
description: |
|
||||
This is a DNS record.
|
||||
type: object
|
||||
properties:
|
||||
dnsName:
|
||||
type: string
|
||||
example: "foo.example.org"
|
||||
targets:
|
||||
$ref: '#/components/schemas/targets'
|
||||
recordType:
|
||||
type: string
|
||||
example: "CNAME"
|
||||
setIdentifier:
|
||||
type: string
|
||||
example: "v1"
|
||||
recordTTL:
|
||||
type: integer
|
||||
format: int64
|
||||
example: 60
|
||||
labels:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
example: "foo"
|
||||
example:
|
||||
foo: bar
|
||||
providerSpecific:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/providerSpecificProperty'
|
||||
example:
|
||||
- name: foo
|
||||
value: bar
|
||||
example:
|
||||
dnsName: foo.example.com
|
||||
recordType: A
|
||||
recordTTL: 60
|
||||
|
||||
targets:
|
||||
description: |
|
||||
This is the list of targets that this DNS record points to.
|
||||
So for an A record it will be a list of IP addresses.
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
example: "::1"
|
||||
example:
|
||||
- "1.2.3.4"
|
||||
- "test.example.org"
|
||||
|
||||
providerSpecificProperty:
|
||||
description: |
|
||||
Allows provider to pass property specific to their implementation.
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
example: foo
|
||||
value:
|
||||
type: string
|
||||
example: bar
|
||||
example:
|
||||
name: foo
|
||||
value: bar
|
||||
|
||||
changes:
|
||||
description: |
|
||||
This is the list of changes send by `external-dns` that need to
|
||||
be applied. There are four lists of endpoints. The `create`
|
||||
and `delete` lists are lists of records to create and delete
|
||||
respectively. The `updateOld` and `updateNew` lists are paired.
|
||||
For each entry there's the old version of the record and a new
|
||||
version of the record.
|
||||
type: object
|
||||
properties:
|
||||
create:
|
||||
$ref: '#/components/schemas/endpoints'
|
||||
updateOld:
|
||||
$ref: '#/components/schemas/endpoints'
|
||||
updateNew:
|
||||
$ref: '#/components/schemas/endpoints'
|
||||
delete:
|
||||
$ref: '#/components/schemas/endpoints'
|
||||
example:
|
||||
create:
|
||||
- dnsName: foo.example.com
|
||||
recordType: A
|
||||
recordTTL: 60
|
||||
delete:
|
||||
- dnsName: foo.example.org
|
||||
recordType: CNAME
|
||||
17
v0.18.0/apis/api.go
Normal file
17
v0.18.0/apis/api.go
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
Copyright 2025 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 apis
|
||||
20
v0.18.0/apis/v1alpha1/api.go
Normal file
20
v0.18.0/apis/v1alpha1/api.go
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
Copyright 2017 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 v1alpha1 contains API Schema definitions for the externaldns.k8s.io v1alpha1 API group
|
||||
// +kubebuilder:object:generate=true
|
||||
// +groupName=externaldns.k8s.io
|
||||
package v1alpha1
|
||||
62
v0.18.0/apis/v1alpha1/dnsendpoint.go
Normal file
62
v0.18.0/apis/v1alpha1/dnsendpoint.go
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright 2017 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 v1alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"sigs.k8s.io/external-dns/endpoint"
|
||||
)
|
||||
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// DNSEndpoint is a contract that a user-specified CRD must implement to be used as a source for external-dns.
|
||||
// The user-specified CRD should also have the status sub-resource.
|
||||
// +k8s:openapi-gen=true
|
||||
// +groupName=externaldns.k8s.io
|
||||
// +kubebuilder:resource:path=dnsendpoints
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:metadata:annotations="api-approved.kubernetes.io=https://github.com/kubernetes-sigs/external-dns/pull/2007"
|
||||
// +versionName=v1alpha1
|
||||
type DNSEndpoint struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec DNSEndpointSpec `json:"spec,omitempty"`
|
||||
Status DNSEndpointStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// DNSEndpointList is a list of DNSEndpoint objects
|
||||
type DNSEndpointList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty"`
|
||||
Items []DNSEndpoint `json:"items"`
|
||||
}
|
||||
|
||||
// DNSEndpointSpec defines the desired state of DNSEndpoint
|
||||
type DNSEndpointSpec struct {
|
||||
Endpoints []*endpoint.Endpoint `json:"endpoints,omitempty"`
|
||||
}
|
||||
|
||||
// DNSEndpointStatus defines the observed state of DNSEndpoint
|
||||
type DNSEndpointStatus struct {
|
||||
// The generation observed by the external-dns controller.
|
||||
// +optional
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||
}
|
||||
40
v0.18.0/apis/v1alpha1/groupversion_info.go
Normal file
40
v0.18.0/apis/v1alpha1/groupversion_info.go
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
Copyright 2017 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 v1alpha1 contains API Schema definitions for the externaldns.k8s.io v1alpha1 API group
|
||||
// +kubebuilder:object:generate=true
|
||||
// +groupName=externaldns.k8s.io
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"sigs.k8s.io/controller-runtime/pkg/scheme"
|
||||
)
|
||||
|
||||
var (
|
||||
// GroupVersion is group version used to register these objects
|
||||
GroupVersion = schema.GroupVersion{Group: "externaldns.k8s.io", Version: "v1alpha1"}
|
||||
|
||||
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
|
||||
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
|
||||
|
||||
// AddToScheme adds the types in this group-version to the given scheme.
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
func init() {
|
||||
SchemeBuilder.Register(&DNSEndpoint{}, &DNSEndpointList{})
|
||||
}
|
||||
110
v0.18.0/apis/v1alpha1/zz_generated.deepcopy.go
Normal file
110
v0.18.0/apis/v1alpha1/zz_generated.deepcopy.go
Normal file
@ -0,0 +1,110 @@
|
||||
//go:build !ignore_autogenerated
|
||||
|
||||
// Code generated by controller-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
"sigs.k8s.io/external-dns/endpoint"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DNSEndpoint) DeepCopyInto(out *DNSEndpoint) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
out.Status = in.Status
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSEndpoint.
|
||||
func (in *DNSEndpoint) DeepCopy() *DNSEndpoint {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DNSEndpoint)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *DNSEndpoint) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DNSEndpointList) DeepCopyInto(out *DNSEndpointList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]DNSEndpoint, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSEndpointList.
|
||||
func (in *DNSEndpointList) DeepCopy() *DNSEndpointList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DNSEndpointList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *DNSEndpointList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DNSEndpointSpec) DeepCopyInto(out *DNSEndpointSpec) {
|
||||
*out = *in
|
||||
if in.Endpoints != nil {
|
||||
in, out := &in.Endpoints, &out.Endpoints
|
||||
*out = make([]*endpoint.Endpoint, len(*in))
|
||||
for i := range *in {
|
||||
if (*in)[i] != nil {
|
||||
in, out := &(*in)[i], &(*out)[i]
|
||||
*out = new(endpoint.Endpoint)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSEndpointSpec.
|
||||
func (in *DNSEndpointSpec) DeepCopy() *DNSEndpointSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DNSEndpointSpec)
|
||||
in.DeepCopyInto(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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
BIN
v0.18.0/assets/images/favicon.png
Normal file
BIN
v0.18.0/assets/images/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 KiB |
29
v0.18.0/assets/javascripts/bundle.1e8ae164.min.js
vendored
Normal file
29
v0.18.0/assets/javascripts/bundle.1e8ae164.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
7
v0.18.0/assets/javascripts/bundle.1e8ae164.min.js.map
Normal file
7
v0.18.0/assets/javascripts/bundle.1e8ae164.min.js.map
Normal file
File diff suppressed because one or more lines are too long
1
v0.18.0/assets/javascripts/lunr/min/lunr.ar.min.js
vendored
Normal file
1
v0.18.0/assets/javascripts/lunr/min/lunr.ar.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
v0.18.0/assets/javascripts/lunr/min/lunr.da.min.js
vendored
Normal file
18
v0.18.0/assets/javascripts/lunr/min/lunr.da.min.js
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
/*!
|
||||
* Lunr languages, `Danish` language
|
||||
* https://github.com/MihaiValentin/lunr-languages
|
||||
*
|
||||
* Copyright 2014, Mihai Valentin
|
||||
* http://www.mozilla.org/MPL/
|
||||
*/
|
||||
/*!
|
||||
* based on
|
||||
* Snowball JavaScript Library v0.3
|
||||
* http://code.google.com/p/urim/
|
||||
* http://snowball.tartarus.org/
|
||||
*
|
||||
* Copyright 2010, Oleg Mazko
|
||||
* http://www.mozilla.org/MPL/
|
||||
*/
|
||||
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.da=function(){this.pipeline.reset(),this.pipeline.add(e.da.trimmer,e.da.stopWordFilter,e.da.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.da.stemmer))},e.da.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.da.trimmer=e.trimmerSupport.generateTrimmer(e.da.wordCharacters),e.Pipeline.registerFunction(e.da.trimmer,"trimmer-da"),e.da.stemmer=function(){var r=e.stemmerSupport.Among,i=e.stemmerSupport.SnowballProgram,n=new function(){function e(){var e,r=f.cursor+3;if(d=f.limit,0<=r&&r<=f.limit){for(a=r;;){if(e=f.cursor,f.in_grouping(w,97,248)){f.cursor=e;break}if(f.cursor=e,e>=f.limit)return;f.cursor++}for(;!f.out_grouping(w,97,248);){if(f.cursor>=f.limit)return;f.cursor++}d=f.cursor,d<a&&(d=a)}}function n(){var e,r;if(f.cursor>=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(c,32),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del();break;case 2:f.in_grouping_b(p,97,229)&&f.slice_del()}}function t(){var e,r=f.limit-f.cursor;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.find_among_b(l,4)?(f.bra=f.cursor,f.limit_backward=e,f.cursor=f.limit-r,f.cursor>f.limit_backward&&(f.cursor--,f.bra=f.cursor,f.slice_del())):f.limit_backward=e)}function s(){var e,r,i,n=f.limit-f.cursor;if(f.ket=f.cursor,f.eq_s_b(2,"st")&&(f.bra=f.cursor,f.eq_s_b(2,"ig")&&f.slice_del()),f.cursor=f.limit-n,f.cursor>=d&&(r=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,e=f.find_among_b(m,5),f.limit_backward=r,e))switch(f.bra=f.cursor,e){case 1:f.slice_del(),i=f.limit-f.cursor,t(),f.cursor=f.limit-i;break;case 2:f.slice_from("løs")}}function o(){var e;f.cursor>=d&&(e=f.limit_backward,f.limit_backward=d,f.ket=f.cursor,f.out_grouping_b(w,97,248)?(f.bra=f.cursor,u=f.slice_to(u),f.limit_backward=e,f.eq_v_b(u)&&f.slice_del()):f.limit_backward=e)}var a,d,u,c=[new r("hed",-1,1),new r("ethed",0,1),new r("ered",-1,1),new r("e",-1,1),new r("erede",3,1),new r("ende",3,1),new r("erende",5,1),new r("ene",3,1),new r("erne",3,1),new r("ere",3,1),new r("en",-1,1),new r("heden",10,1),new r("eren",10,1),new r("er",-1,1),new r("heder",13,1),new r("erer",13,1),new r("s",-1,2),new r("heds",16,1),new r("es",16,1),new r("endes",18,1),new r("erendes",19,1),new r("enes",18,1),new r("ernes",18,1),new r("eres",18,1),new r("ens",16,1),new r("hedens",24,1),new r("erens",24,1),new r("ers",16,1),new r("ets",16,1),new r("erets",28,1),new r("et",-1,1),new r("eret",30,1)],l=[new r("gd",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("elig",1,1),new r("els",-1,1),new r("løst",-1,2)],w=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],p=[239,254,42,3,0,0,0,0,0,0,0,0,0,0,0,0,16],f=new i;this.setCurrent=function(e){f.setCurrent(e)},this.getCurrent=function(){return f.getCurrent()},this.stem=function(){var r=f.cursor;return e(),f.limit_backward=r,f.cursor=f.limit,n(),f.cursor=f.limit,t(),f.cursor=f.limit,s(),f.cursor=f.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return n.setCurrent(e),n.stem(),n.getCurrent()}):(n.setCurrent(e),n.stem(),n.getCurrent())}}(),e.Pipeline.registerFunction(e.da.stemmer,"stemmer-da"),e.da.stopWordFilter=e.generateStopWordFilter("ad af alle alt anden at blev blive bliver da de dem den denne der deres det dette dig din disse dog du efter eller en end er et for fra ham han hans har havde have hende hendes her hos hun hvad hvis hvor i ikke ind jeg jer jo kunne man mange med meget men mig min mine mit mod ned noget nogle nu når og også om op os over på selv sig sin sine sit skal skulle som sådan thi til ud under var vi vil ville vor være været".split(" ")),e.Pipeline.registerFunction(e.da.stopWordFilter,"stopWordFilter-da")}});
|
||||
18
v0.18.0/assets/javascripts/lunr/min/lunr.de.min.js
vendored
Normal file
18
v0.18.0/assets/javascripts/lunr/min/lunr.de.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
v0.18.0/assets/javascripts/lunr/min/lunr.du.min.js
vendored
Normal file
18
v0.18.0/assets/javascripts/lunr/min/lunr.du.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
v0.18.0/assets/javascripts/lunr/min/lunr.el.min.js
vendored
Normal file
1
v0.18.0/assets/javascripts/lunr/min/lunr.el.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
v0.18.0/assets/javascripts/lunr/min/lunr.es.min.js
vendored
Normal file
18
v0.18.0/assets/javascripts/lunr/min/lunr.es.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
v0.18.0/assets/javascripts/lunr/min/lunr.fi.min.js
vendored
Normal file
18
v0.18.0/assets/javascripts/lunr/min/lunr.fi.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
v0.18.0/assets/javascripts/lunr/min/lunr.fr.min.js
vendored
Normal file
18
v0.18.0/assets/javascripts/lunr/min/lunr.fr.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
v0.18.0/assets/javascripts/lunr/min/lunr.he.min.js
vendored
Normal file
1
v0.18.0/assets/javascripts/lunr/min/lunr.he.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
v0.18.0/assets/javascripts/lunr/min/lunr.hi.min.js
vendored
Normal file
1
v0.18.0/assets/javascripts/lunr/min/lunr.hi.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hi=function(){this.pipeline.reset(),this.pipeline.add(e.hi.trimmer,e.hi.stopWordFilter,e.hi.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.hi.stemmer))},e.hi.wordCharacters="ऀ-ःऄ-एऐ-टठ-यर-िी-ॏॐ-य़ॠ-९॰-ॿa-zA-Za-zA-Z0-90-9",e.hi.trimmer=e.trimmerSupport.generateTrimmer(e.hi.wordCharacters),e.Pipeline.registerFunction(e.hi.trimmer,"trimmer-hi"),e.hi.stopWordFilter=e.generateStopWordFilter("अत अपना अपनी अपने अभी अंदर आदि आप इत्यादि इन इनका इन्हीं इन्हें इन्हों इस इसका इसकी इसके इसमें इसी इसे उन उनका उनकी उनके उनको उन्हीं उन्हें उन्हों उस उसके उसी उसे एक एवं एस ऐसे और कई कर करता करते करना करने करें कहते कहा का काफ़ी कि कितना किन्हें किन्हों किया किर किस किसी किसे की कुछ कुल के को कोई कौन कौनसा गया घर जब जहाँ जा जितना जिन जिन्हें जिन्हों जिस जिसे जीधर जैसा जैसे जो तक तब तरह तिन तिन्हें तिन्हों तिस तिसे तो था थी थे दबारा दिया दुसरा दूसरे दो द्वारा न नके नहीं ना निहायत नीचे ने पर पहले पूरा पे फिर बनी बही बहुत बाद बाला बिलकुल भी भीतर मगर मानो मे में यदि यह यहाँ यही या यिह ये रखें रहा रहे ऱ्वासा लिए लिये लेकिन व वग़ैरह वर्ग वह वहाँ वहीं वाले वुह वे वो सकता सकते सबसे सभी साथ साबुत साभ सारा से सो संग ही हुआ हुई हुए है हैं हो होता होती होते होना होने".split(" ")),e.hi.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var r=e.wordcut;r.init(),e.hi.tokenizer=function(i){if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(r){return isLunr2?new e.Token(r.toLowerCase()):r.toLowerCase()});var t=i.toString().toLowerCase().replace(/^\s+/,"");return r.cut(t).split("|")},e.Pipeline.registerFunction(e.hi.stemmer,"stemmer-hi"),e.Pipeline.registerFunction(e.hi.stopWordFilter,"stopWordFilter-hi")}});
|
||||
18
v0.18.0/assets/javascripts/lunr/min/lunr.hu.min.js
vendored
Normal file
18
v0.18.0/assets/javascripts/lunr/min/lunr.hu.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
v0.18.0/assets/javascripts/lunr/min/lunr.hy.min.js
vendored
Normal file
1
v0.18.0/assets/javascripts/lunr/min/lunr.hy.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.hy=function(){this.pipeline.reset(),this.pipeline.add(e.hy.trimmer,e.hy.stopWordFilter)},e.hy.wordCharacters="[A-Za-z-֏ff-ﭏ]",e.hy.trimmer=e.trimmerSupport.generateTrimmer(e.hy.wordCharacters),e.Pipeline.registerFunction(e.hy.trimmer,"trimmer-hy"),e.hy.stopWordFilter=e.generateStopWordFilter("դու և եք էիր էիք հետո նաև նրանք որը վրա է որ պիտի են այս մեջ ն իր ու ի այդ որոնք այն կամ էր մի ես համար այլ իսկ էին ենք հետ ին թ էինք մենք նրա նա դուք եմ էի ըստ որպես ում".split(" ")),e.Pipeline.registerFunction(e.hy.stopWordFilter,"stopWordFilter-hy"),e.hy.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}(),e.Pipeline.registerFunction(e.hy.stemmer,"stemmer-hy")}});
|
||||
18
v0.18.0/assets/javascripts/lunr/min/lunr.it.min.js
vendored
Normal file
18
v0.18.0/assets/javascripts/lunr/min/lunr.it.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
v0.18.0/assets/javascripts/lunr/min/lunr.ja.min.js
vendored
Normal file
1
v0.18.0/assets/javascripts/lunr/min/lunr.ja.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.ja=function(){this.pipeline.reset(),this.pipeline.add(e.ja.trimmer,e.ja.stopWordFilter,e.ja.stemmer),r?this.tokenizer=e.ja.tokenizer:(e.tokenizer&&(e.tokenizer=e.ja.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.ja.tokenizer))};var t=new e.TinySegmenter;e.ja.tokenizer=function(i){var n,o,s,p,a,u,m,l,c,f;if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t.toLowerCase()):t.toLowerCase()});for(o=i.toString().toLowerCase().replace(/^\s+/,""),n=o.length-1;n>=0;n--)if(/\S/.test(o.charAt(n))){o=o.substring(0,n+1);break}for(a=[],s=o.length,c=0,l=0;c<=s;c++)if(u=o.charAt(c),m=c-l,u.match(/\s/)||c==s){if(m>0)for(p=t.segment(o.slice(l,c)).filter(function(e){return!!e}),f=l,n=0;n<p.length;n++)r?a.push(new e.Token(p[n],{position:[f,p[n].length],index:a.length})):a.push(p[n]),f+=p[n].length;l=c+1}return a},e.ja.stemmer=function(){return function(e){return e}}(),e.Pipeline.registerFunction(e.ja.stemmer,"stemmer-ja"),e.ja.wordCharacters="一二三四五六七八九十百千万億兆一-龠々〆ヵヶぁ-んァ-ヴーア-ン゙a-zA-Za-zA-Z0-90-9",e.ja.trimmer=e.trimmerSupport.generateTrimmer(e.ja.wordCharacters),e.Pipeline.registerFunction(e.ja.trimmer,"trimmer-ja"),e.ja.stopWordFilter=e.generateStopWordFilter("これ それ あれ この その あの ここ そこ あそこ こちら どこ だれ なに なん 何 私 貴方 貴方方 我々 私達 あの人 あのかた 彼女 彼 です あります おります います は が の に を で え から まで より も どの と し それで しかし".split(" ")),e.Pipeline.registerFunction(e.ja.stopWordFilter,"stopWordFilter-ja"),e.jp=e.ja,e.Pipeline.registerFunction(e.jp.stemmer,"stemmer-jp"),e.Pipeline.registerFunction(e.jp.trimmer,"trimmer-jp"),e.Pipeline.registerFunction(e.jp.stopWordFilter,"stopWordFilter-jp")}});
|
||||
1
v0.18.0/assets/javascripts/lunr/min/lunr.jp.min.js
vendored
Normal file
1
v0.18.0/assets/javascripts/lunr/min/lunr.jp.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
module.exports=require("./lunr.ja");
|
||||
1
v0.18.0/assets/javascripts/lunr/min/lunr.kn.min.js
vendored
Normal file
1
v0.18.0/assets/javascripts/lunr/min/lunr.kn.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.kn=function(){this.pipeline.reset(),this.pipeline.add(e.kn.trimmer,e.kn.stopWordFilter,e.kn.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.kn.stemmer))},e.kn.wordCharacters="ಀ-಄ಅ-ಔಕ-ಹಾ-ೌ಼-ಽೕ-ೖೝ-ೞೠ-ೡೢ-ೣ೦-೯ೱ-ೳ",e.kn.trimmer=e.trimmerSupport.generateTrimmer(e.kn.wordCharacters),e.Pipeline.registerFunction(e.kn.trimmer,"trimmer-kn"),e.kn.stopWordFilter=e.generateStopWordFilter("ಮತ್ತು ಈ ಒಂದು ರಲ್ಲಿ ಹಾಗೂ ಎಂದು ಅಥವಾ ಇದು ರ ಅವರು ಎಂಬ ಮೇಲೆ ಅವರ ತನ್ನ ಆದರೆ ತಮ್ಮ ನಂತರ ಮೂಲಕ ಹೆಚ್ಚು ನ ಆ ಕೆಲವು ಅನೇಕ ಎರಡು ಹಾಗು ಪ್ರಮುಖ ಇದನ್ನು ಇದರ ಸುಮಾರು ಅದರ ಅದು ಮೊದಲ ಬಗ್ಗೆ ನಲ್ಲಿ ರಂದು ಇತರ ಅತ್ಯಂತ ಹೆಚ್ಚಿನ ಸಹ ಸಾಮಾನ್ಯವಾಗಿ ನೇ ಹಲವಾರು ಹೊಸ ದಿ ಕಡಿಮೆ ಯಾವುದೇ ಹೊಂದಿದೆ ದೊಡ್ಡ ಅನ್ನು ಇವರು ಪ್ರಕಾರ ಇದೆ ಮಾತ್ರ ಕೂಡ ಇಲ್ಲಿ ಎಲ್ಲಾ ವಿವಿಧ ಅದನ್ನು ಹಲವು ರಿಂದ ಕೇವಲ ದ ದಕ್ಷಿಣ ಗೆ ಅವನ ಅತಿ ನೆಯ ಬಹಳ ಕೆಲಸ ಎಲ್ಲ ಪ್ರತಿ ಇತ್ಯಾದಿ ಇವು ಬೇರೆ ಹೀಗೆ ನಡುವೆ ಇದಕ್ಕೆ ಎಸ್ ಇವರ ಮೊದಲು ಶ್ರೀ ಮಾಡುವ ಇದರಲ್ಲಿ ರೀತಿಯ ಮಾಡಿದ ಕಾಲ ಅಲ್ಲಿ ಮಾಡಲು ಅದೇ ಈಗ ಅವು ಗಳು ಎ ಎಂಬುದು ಅವನು ಅಂದರೆ ಅವರಿಗೆ ಇರುವ ವಿಶೇಷ ಮುಂದೆ ಅವುಗಳ ಮುಂತಾದ ಮೂಲ ಬಿ ಮೀ ಒಂದೇ ಇನ್ನೂ ಹೆಚ್ಚಾಗಿ ಮಾಡಿ ಅವರನ್ನು ಇದೇ ಯ ರೀತಿಯಲ್ಲಿ ಜೊತೆ ಅದರಲ್ಲಿ ಮಾಡಿದರು ನಡೆದ ಆಗ ಮತ್ತೆ ಪೂರ್ವ ಆತ ಬಂದ ಯಾವ ಒಟ್ಟು ಇತರೆ ಹಿಂದೆ ಪ್ರಮಾಣದ ಗಳನ್ನು ಕುರಿತು ಯು ಆದ್ದರಿಂದ ಅಲ್ಲದೆ ನಗರದ ಮೇಲಿನ ಏಕೆಂದರೆ ರಷ್ಟು ಎಂಬುದನ್ನು ಬಾರಿ ಎಂದರೆ ಹಿಂದಿನ ಆದರೂ ಆದ ಸಂಬಂಧಿಸಿದ ಮತ್ತೊಂದು ಸಿ ಆತನ ".split(" ")),e.kn.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var r=e.wordcut;r.init(),e.kn.tokenizer=function(t){if(!arguments.length||null==t||void 0==t)return[];if(Array.isArray(t))return t.map(function(r){return isLunr2?new e.Token(r.toLowerCase()):r.toLowerCase()});var n=t.toString().toLowerCase().replace(/^\s+/,"");return r.cut(n).split("|")},e.Pipeline.registerFunction(e.kn.stemmer,"stemmer-kn"),e.Pipeline.registerFunction(e.kn.stopWordFilter,"stopWordFilter-kn")}});
|
||||
1
v0.18.0/assets/javascripts/lunr/min/lunr.ko.min.js
vendored
Normal file
1
v0.18.0/assets/javascripts/lunr/min/lunr.ko.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
v0.18.0/assets/javascripts/lunr/min/lunr.multi.min.js
vendored
Normal file
1
v0.18.0/assets/javascripts/lunr/min/lunr.multi.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(e.lunr)}(this,function(){return function(e){e.multiLanguage=function(){for(var t=Array.prototype.slice.call(arguments),i=t.join("-"),r="",n=[],s=[],p=0;p<t.length;++p)"en"==t[p]?(r+="\\w",n.unshift(e.stopWordFilter),n.push(e.stemmer),s.push(e.stemmer)):(r+=e[t[p]].wordCharacters,e[t[p]].stopWordFilter&&n.unshift(e[t[p]].stopWordFilter),e[t[p]].stemmer&&(n.push(e[t[p]].stemmer),s.push(e[t[p]].stemmer)));var o=e.trimmerSupport.generateTrimmer(r);return e.Pipeline.registerFunction(o,"lunr-multi-trimmer-"+i),n.unshift(o),function(){this.pipeline.reset(),this.pipeline.add.apply(this.pipeline,n),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add.apply(this.searchPipeline,s))}}}});
|
||||
18
v0.18.0/assets/javascripts/lunr/min/lunr.nl.min.js
vendored
Normal file
18
v0.18.0/assets/javascripts/lunr/min/lunr.nl.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
v0.18.0/assets/javascripts/lunr/min/lunr.no.min.js
vendored
Normal file
18
v0.18.0/assets/javascripts/lunr/min/lunr.no.min.js
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
/*!
|
||||
* Lunr languages, `Norwegian` language
|
||||
* https://github.com/MihaiValentin/lunr-languages
|
||||
*
|
||||
* Copyright 2014, Mihai Valentin
|
||||
* http://www.mozilla.org/MPL/
|
||||
*/
|
||||
/*!
|
||||
* based on
|
||||
* Snowball JavaScript Library v0.3
|
||||
* http://code.google.com/p/urim/
|
||||
* http://snowball.tartarus.org/
|
||||
*
|
||||
* Copyright 2010, Oleg Mazko
|
||||
* http://www.mozilla.org/MPL/
|
||||
*/
|
||||
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.no=function(){this.pipeline.reset(),this.pipeline.add(e.no.trimmer,e.no.stopWordFilter,e.no.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.no.stemmer))},e.no.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.no.trimmer=e.trimmerSupport.generateTrimmer(e.no.wordCharacters),e.Pipeline.registerFunction(e.no.trimmer,"trimmer-no"),e.no.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,i=new function(){function e(){var e,r=w.cursor+3;if(a=w.limit,0<=r||r<=w.limit){for(s=r;;){if(e=w.cursor,w.in_grouping(d,97,248)){w.cursor=e;break}if(e>=w.limit)return;w.cursor=e+1}for(;!w.out_grouping(d,97,248);){if(w.cursor>=w.limit)return;w.cursor++}a=w.cursor,a<s&&(a=s)}}function i(){var e,r,n;if(w.cursor>=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(m,29),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:n=w.limit-w.cursor,w.in_grouping_b(c,98,122)?w.slice_del():(w.cursor=w.limit-n,w.eq_s_b(1,"k")&&w.out_grouping_b(d,97,248)&&w.slice_del());break;case 3:w.slice_from("er")}}function t(){var e,r=w.limit-w.cursor;w.cursor>=a&&(e=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,w.find_among_b(u,2)?(w.bra=w.cursor,w.limit_backward=e,w.cursor=w.limit-r,w.cursor>w.limit_backward&&(w.cursor--,w.bra=w.cursor,w.slice_del())):w.limit_backward=e)}function o(){var e,r;w.cursor>=a&&(r=w.limit_backward,w.limit_backward=a,w.ket=w.cursor,e=w.find_among_b(l,11),e?(w.bra=w.cursor,w.limit_backward=r,1==e&&w.slice_del()):w.limit_backward=r)}var s,a,m=[new r("a",-1,1),new r("e",-1,1),new r("ede",1,1),new r("ande",1,1),new r("ende",1,1),new r("ane",1,1),new r("ene",1,1),new r("hetene",6,1),new r("erte",1,3),new r("en",-1,1),new r("heten",9,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",12,1),new r("s",-1,2),new r("as",14,1),new r("es",14,1),new r("edes",16,1),new r("endes",16,1),new r("enes",16,1),new r("hetenes",19,1),new r("ens",14,1),new r("hetens",21,1),new r("ers",14,1),new r("ets",14,1),new r("et",-1,1),new r("het",25,1),new r("ert",-1,3),new r("ast",-1,1)],u=[new r("dt",-1,-1),new r("vt",-1,-1)],l=[new r("leg",-1,1),new r("eleg",0,1),new r("ig",-1,1),new r("eig",2,1),new r("lig",2,1),new r("elig",4,1),new r("els",-1,1),new r("lov",-1,1),new r("elov",7,1),new r("slov",7,1),new r("hetslov",9,1)],d=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,48,0,128],c=[119,125,149,1],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,i(),w.cursor=w.limit,t(),w.cursor=w.limit,o(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return i.setCurrent(e),i.stem(),i.getCurrent()}):(i.setCurrent(e),i.stem(),i.getCurrent())}}(),e.Pipeline.registerFunction(e.no.stemmer,"stemmer-no"),e.no.stopWordFilter=e.generateStopWordFilter("alle at av bare begge ble blei bli blir blitt både båe da de deg dei deim deira deires dem den denne der dere deres det dette di din disse ditt du dykk dykkar då eg ein eit eitt eller elles en enn er et ett etter for fordi fra før ha hadde han hans har hennar henne hennes her hjå ho hoe honom hoss hossen hun hva hvem hver hvilke hvilken hvis hvor hvordan hvorfor i ikke ikkje ikkje ingen ingi inkje inn inni ja jeg kan kom korleis korso kun kunne kva kvar kvarhelst kven kvi kvifor man mange me med medan meg meget mellom men mi min mine mitt mot mykje ned no noe noen noka noko nokon nokor nokre nå når og også om opp oss over på samme seg selv si si sia sidan siden sin sine sitt sjøl skal skulle slik so som som somme somt så sånn til um upp ut uten var vart varte ved vere verte vi vil ville vore vors vort vår være være vært å".split(" ")),e.Pipeline.registerFunction(e.no.stopWordFilter,"stopWordFilter-no")}});
|
||||
18
v0.18.0/assets/javascripts/lunr/min/lunr.pt.min.js
vendored
Normal file
18
v0.18.0/assets/javascripts/lunr/min/lunr.pt.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
v0.18.0/assets/javascripts/lunr/min/lunr.ro.min.js
vendored
Normal file
18
v0.18.0/assets/javascripts/lunr/min/lunr.ro.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
18
v0.18.0/assets/javascripts/lunr/min/lunr.ru.min.js
vendored
Normal file
18
v0.18.0/assets/javascripts/lunr/min/lunr.ru.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
v0.18.0/assets/javascripts/lunr/min/lunr.sa.min.js
vendored
Normal file
1
v0.18.0/assets/javascripts/lunr/min/lunr.sa.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.sa=function(){this.pipeline.reset(),this.pipeline.add(e.sa.trimmer,e.sa.stopWordFilter,e.sa.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sa.stemmer))},e.sa.wordCharacters="ऀ-ःऄ-एऐ-टठ-यर-िी-ॏॐ-य़ॠ-९॰-ॿ꣠-꣱ꣲ-ꣷ꣸-ꣻ꣼-ꣽꣾ-ꣿᆰ0-ᆰ9",e.sa.trimmer=e.trimmerSupport.generateTrimmer(e.sa.wordCharacters),e.Pipeline.registerFunction(e.sa.trimmer,"trimmer-sa"),e.sa.stopWordFilter=e.generateStopWordFilter('तथा अयम् एकम् इत्यस्मिन् तथा तत् वा अयम् इत्यस्य ते आहूत उपरि तेषाम् किन्तु तेषाम् तदा इत्यनेन अधिकः इत्यस्य तत् केचन बहवः द्वि तथा महत्वपूर्णः अयम् अस्य विषये अयं अस्ति तत् प्रथमः विषये इत्युपरि इत्युपरि इतर अधिकतमः अधिकः अपि सामान्यतया ठ इतरेतर नूतनम् द न्यूनम् कश्चित् वा विशालः द सः अस्ति तदनुसारम् तत्र अस्ति केवलम् अपि अत्र सर्वे विविधाः तत् बहवः यतः इदानीम् द दक्षिण इत्यस्मै तस्य उपरि नथ अतीव कार्यम् सर्वे एकैकम् इत्यादि। एते सन्ति उत इत्थम् मध्ये एतदर्थं . स कस्य प्रथमः श्री. करोति अस्मिन् प्रकारः निर्मिता कालः तत्र कर्तुं समान अधुना ते सन्ति स एकः अस्ति सः अर्थात् तेषां कृते . स्थितम् विशेषः अग्रिम तेषाम् समान स्रोतः ख म समान इदानीमपि अधिकतया करोतु ते समान इत्यस्य वीथी सह यस्मिन् कृतवान् धृतः तदा पुनः पूर्वं सः आगतः किम् कुल इतर पुरा मात्रा स विषये उ अतएव अपि नगरस्य उपरि यतः प्रतिशतं कतरः कालः साधनानि भूत तथापि जात सम्बन्धि अन्यत् ग अतः अस्माकं स्वकीयाः अस्माकं इदानीं अन्तः इत्यादयः भवन्तः इत्यादयः एते एताः तस्य अस्य इदम् एते तेषां तेषां तेषां तान् तेषां तेषां तेषां समानः सः एकः च तादृशाः बहवः अन्ये च वदन्ति यत् कियत् कस्मै कस्मै यस्मै यस्मै यस्मै यस्मै न अतिनीचः किन्तु प्रथमं सम्पूर्णतया ततः चिरकालानन्तरं पुस्तकं सम्पूर्णतया अन्तः किन्तु अत्र वा इह इव श्रद्धाय अवशिष्यते परन्तु अन्ये वर्गाः सन्ति ते सन्ति शक्नुवन्ति सर्वे मिलित्वा सर्वे एकत्र"'.split(" ")),e.sa.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var r=e.wordcut;r.init(),e.sa.tokenizer=function(t){if(!arguments.length||null==t||void 0==t)return[];if(Array.isArray(t))return t.map(function(r){return isLunr2?new e.Token(r.toLowerCase()):r.toLowerCase()});var i=t.toString().toLowerCase().replace(/^\s+/,"");return r.cut(i).split("|")},e.Pipeline.registerFunction(e.sa.stemmer,"stemmer-sa"),e.Pipeline.registerFunction(e.sa.stopWordFilter,"stopWordFilter-sa")}});
|
||||
1
v0.18.0/assets/javascripts/lunr/min/lunr.stemmer.support.min.js
vendored
Normal file
1
v0.18.0/assets/javascripts/lunr/min/lunr.stemmer.support.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(r,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(r.lunr)}(this,function(){return function(r){r.stemmerSupport={Among:function(r,t,i,s){if(this.toCharArray=function(r){for(var t=r.length,i=new Array(t),s=0;s<t;s++)i[s]=r.charCodeAt(s);return i},!r&&""!=r||!t&&0!=t||!i)throw"Bad Among initialisation: s:"+r+", substring_i: "+t+", result: "+i;this.s_size=r.length,this.s=this.toCharArray(r),this.substring_i=t,this.result=i,this.method=s},SnowballProgram:function(){var r;return{bra:0,ket:0,limit:0,cursor:0,limit_backward:0,setCurrent:function(t){r=t,this.cursor=0,this.limit=t.length,this.limit_backward=0,this.bra=this.cursor,this.ket=this.limit},getCurrent:function(){var t=r;return r=null,t},in_grouping:function(t,i,s){if(this.cursor<this.limit){var e=r.charCodeAt(this.cursor);if(e<=s&&e>=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor++,!0}return!1},in_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e<=s&&e>=i&&(e-=i,t[e>>3]&1<<(7&e)))return this.cursor--,!0}return!1},out_grouping:function(t,i,s){if(this.cursor<this.limit){var e=r.charCodeAt(this.cursor);if(e>s||e<i)return this.cursor++,!0;if(e-=i,!(t[e>>3]&1<<(7&e)))return this.cursor++,!0}return!1},out_grouping_b:function(t,i,s){if(this.cursor>this.limit_backward){var e=r.charCodeAt(this.cursor-1);if(e>s||e<i)return this.cursor--,!0;if(e-=i,!(t[e>>3]&1<<(7&e)))return this.cursor--,!0}return!1},eq_s:function(t,i){if(this.limit-this.cursor<t)return!1;for(var s=0;s<t;s++)if(r.charCodeAt(this.cursor+s)!=i.charCodeAt(s))return!1;return this.cursor+=t,!0},eq_s_b:function(t,i){if(this.cursor-this.limit_backward<t)return!1;for(var s=0;s<t;s++)if(r.charCodeAt(this.cursor-t+s)!=i.charCodeAt(s))return!1;return this.cursor-=t,!0},find_among:function(t,i){for(var s=0,e=i,n=this.cursor,u=this.limit,o=0,h=0,c=!1;;){for(var a=s+(e-s>>1),f=0,l=o<h?o:h,_=t[a],m=l;m<_.s_size;m++){if(n+l==u){f=-1;break}if(f=r.charCodeAt(n+l)-_.s[m])break;l++}if(f<0?(e=a,h=l):(s=a,o=l),e-s<=1){if(s>0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n+_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n+_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},find_among_b:function(t,i){for(var s=0,e=i,n=this.cursor,u=this.limit_backward,o=0,h=0,c=!1;;){for(var a=s+(e-s>>1),f=0,l=o<h?o:h,_=t[a],m=_.s_size-1-l;m>=0;m--){if(n-l==u){f=-1;break}if(f=r.charCodeAt(n-1-l)-_.s[m])break;l++}if(f<0?(e=a,h=l):(s=a,o=l),e-s<=1){if(s>0||e==s||c)break;c=!0}}for(;;){var _=t[s];if(o>=_.s_size){if(this.cursor=n-_.s_size,!_.method)return _.result;var b=_.method();if(this.cursor=n-_.s_size,b)return _.result}if((s=_.substring_i)<0)return 0}},replace_s:function(t,i,s){var e=s.length-(i-t),n=r.substring(0,t),u=r.substring(i);return r=n+s+u,this.limit+=e,this.cursor>=i?this.cursor+=e:this.cursor>t&&(this.cursor=t),e},slice_check:function(){if(this.bra<0||this.bra>this.ket||this.ket>this.limit||this.limit>r.length)throw"faulty slice operation"},slice_from:function(r){this.slice_check(),this.replace_s(this.bra,this.ket,r)},slice_del:function(){this.slice_from("")},insert:function(r,t,i){var s=this.replace_s(r,t,i);r<=this.bra&&(this.bra+=s),r<=this.ket&&(this.ket+=s)},slice_to:function(){return this.slice_check(),r.substring(this.bra,this.ket)},eq_v_b:function(r){return this.eq_s_b(r.length,r)}}}},r.trimmerSupport={generateTrimmer:function(r){var t=new RegExp("^[^"+r+"]+"),i=new RegExp("[^"+r+"]+$");return function(r){return"function"==typeof r.update?r.update(function(r){return r.replace(t,"").replace(i,"")}):r.replace(t,"").replace(i,"")}}}}});
|
||||
18
v0.18.0/assets/javascripts/lunr/min/lunr.sv.min.js
vendored
Normal file
18
v0.18.0/assets/javascripts/lunr/min/lunr.sv.min.js
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
/*!
|
||||
* Lunr languages, `Swedish` language
|
||||
* https://github.com/MihaiValentin/lunr-languages
|
||||
*
|
||||
* Copyright 2014, Mihai Valentin
|
||||
* http://www.mozilla.org/MPL/
|
||||
*/
|
||||
/*!
|
||||
* based on
|
||||
* Snowball JavaScript Library v0.3
|
||||
* http://code.google.com/p/urim/
|
||||
* http://snowball.tartarus.org/
|
||||
*
|
||||
* Copyright 2010, Oleg Mazko
|
||||
* http://www.mozilla.org/MPL/
|
||||
*/
|
||||
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.sv=function(){this.pipeline.reset(),this.pipeline.add(e.sv.trimmer,e.sv.stopWordFilter,e.sv.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.sv.stemmer))},e.sv.wordCharacters="A-Za-zªºÀ-ÖØ-öø-ʸˠ-ˤᴀ-ᴥᴬ-ᵜᵢ-ᵥᵫ-ᵷᵹ-ᶾḀ-ỿⁱⁿₐ-ₜKÅℲⅎⅠ-ↈⱠ-ⱿꜢ-ꞇꞋ-ꞭꞰ-ꞷꟷ-ꟿꬰ-ꭚꭜ-ꭤff-stA-Za-z",e.sv.trimmer=e.trimmerSupport.generateTrimmer(e.sv.wordCharacters),e.Pipeline.registerFunction(e.sv.trimmer,"trimmer-sv"),e.sv.stemmer=function(){var r=e.stemmerSupport.Among,n=e.stemmerSupport.SnowballProgram,t=new function(){function e(){var e,r=w.cursor+3;if(o=w.limit,0<=r||r<=w.limit){for(a=r;;){if(e=w.cursor,w.in_grouping(l,97,246)){w.cursor=e;break}if(w.cursor=e,w.cursor>=w.limit)return;w.cursor++}for(;!w.out_grouping(l,97,246);){if(w.cursor>=w.limit)return;w.cursor++}o=w.cursor,o<a&&(o=a)}}function t(){var e,r=w.limit_backward;if(w.cursor>=o&&(w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(u,37),w.limit_backward=r,e))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.in_grouping_b(d,98,121)&&w.slice_del()}}function i(){var e=w.limit_backward;w.cursor>=o&&(w.limit_backward=o,w.cursor=w.limit,w.find_among_b(c,7)&&(w.cursor=w.limit,w.ket=w.cursor,w.cursor>w.limit_backward&&(w.bra=--w.cursor,w.slice_del())),w.limit_backward=e)}function s(){var e,r;if(w.cursor>=o){if(r=w.limit_backward,w.limit_backward=o,w.cursor=w.limit,w.ket=w.cursor,e=w.find_among_b(m,5))switch(w.bra=w.cursor,e){case 1:w.slice_del();break;case 2:w.slice_from("lös");break;case 3:w.slice_from("full")}w.limit_backward=r}}var a,o,u=[new r("a",-1,1),new r("arna",0,1),new r("erna",0,1),new r("heterna",2,1),new r("orna",0,1),new r("ad",-1,1),new r("e",-1,1),new r("ade",6,1),new r("ande",6,1),new r("arne",6,1),new r("are",6,1),new r("aste",6,1),new r("en",-1,1),new r("anden",12,1),new r("aren",12,1),new r("heten",12,1),new r("ern",-1,1),new r("ar",-1,1),new r("er",-1,1),new r("heter",18,1),new r("or",-1,1),new r("s",-1,2),new r("as",21,1),new r("arnas",22,1),new r("ernas",22,1),new r("ornas",22,1),new r("es",21,1),new r("ades",26,1),new r("andes",26,1),new r("ens",21,1),new r("arens",29,1),new r("hetens",29,1),new r("erns",21,1),new r("at",-1,1),new r("andet",-1,1),new r("het",-1,1),new r("ast",-1,1)],c=[new r("dd",-1,-1),new r("gd",-1,-1),new r("nn",-1,-1),new r("dt",-1,-1),new r("gt",-1,-1),new r("kt",-1,-1),new r("tt",-1,-1)],m=[new r("ig",-1,1),new r("lig",0,1),new r("els",-1,1),new r("fullt",-1,3),new r("löst",-1,2)],l=[17,65,16,1,0,0,0,0,0,0,0,0,0,0,0,0,24,0,32],d=[119,127,149],w=new n;this.setCurrent=function(e){w.setCurrent(e)},this.getCurrent=function(){return w.getCurrent()},this.stem=function(){var r=w.cursor;return e(),w.limit_backward=r,w.cursor=w.limit,t(),w.cursor=w.limit,i(),w.cursor=w.limit,s(),!0}};return function(e){return"function"==typeof e.update?e.update(function(e){return t.setCurrent(e),t.stem(),t.getCurrent()}):(t.setCurrent(e),t.stem(),t.getCurrent())}}(),e.Pipeline.registerFunction(e.sv.stemmer,"stemmer-sv"),e.sv.stopWordFilter=e.generateStopWordFilter("alla allt att av blev bli blir blivit de dem den denna deras dess dessa det detta dig din dina ditt du där då efter ej eller en er era ert ett från för ha hade han hans har henne hennes hon honom hur här i icke ingen inom inte jag ju kan kunde man med mellan men mig min mina mitt mot mycket ni nu när någon något några och om oss på samma sedan sig sin sina sitta själv skulle som så sådan sådana sådant till under upp ut utan vad var vara varför varit varje vars vart vem vi vid vilka vilkas vilken vilket vår våra vårt än är åt över".split(" ")),e.Pipeline.registerFunction(e.sv.stopWordFilter,"stopWordFilter-sv")}});
|
||||
1
v0.18.0/assets/javascripts/lunr/min/lunr.ta.min.js
vendored
Normal file
1
v0.18.0/assets/javascripts/lunr/min/lunr.ta.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.ta=function(){this.pipeline.reset(),this.pipeline.add(e.ta.trimmer,e.ta.stopWordFilter,e.ta.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.ta.stemmer))},e.ta.wordCharacters="-உஊ-ஏஐ-ஙச-ட-னப-யர-ஹ-ிீ-ொ-ௐ---௩௪-௯௰-௹௺-a-zA-Za-zA-Z0-90-9",e.ta.trimmer=e.trimmerSupport.generateTrimmer(e.ta.wordCharacters),e.Pipeline.registerFunction(e.ta.trimmer,"trimmer-ta"),e.ta.stopWordFilter=e.generateStopWordFilter("அங்கு அங்கே அது அதை அந்த அவர் அவர்கள் அவள் அவன் அவை ஆக ஆகவே ஆகையால் ஆதலால் ஆதலினால் ஆனாலும் ஆனால் இங்கு இங்கே இது இதை இந்த இப்படி இவர் இவர்கள் இவள் இவன் இவை இவ்வளவு உனக்கு உனது உன் உன்னால் எங்கு எங்கே எது எதை எந்த எப்படி எவர் எவர்கள் எவள் எவன் எவை எவ்வளவு எனக்கு எனது எனவே என் என்ன என்னால் ஏது ஏன் தனது தன்னால் தானே தான் நாங்கள் நாம் நான் நீ நீங்கள்".split(" ")),e.ta.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var t=e.wordcut;t.init(),e.ta.tokenizer=function(r){if(!arguments.length||null==r||void 0==r)return[];if(Array.isArray(r))return r.map(function(t){return isLunr2?new e.Token(t.toLowerCase()):t.toLowerCase()});var i=r.toString().toLowerCase().replace(/^\s+/,"");return t.cut(i).split("|")},e.Pipeline.registerFunction(e.ta.stemmer,"stemmer-ta"),e.Pipeline.registerFunction(e.ta.stopWordFilter,"stopWordFilter-ta")}});
|
||||
1
v0.18.0/assets/javascripts/lunr/min/lunr.te.min.js
vendored
Normal file
1
v0.18.0/assets/javascripts/lunr/min/lunr.te.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t():t()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.te=function(){this.pipeline.reset(),this.pipeline.add(e.te.trimmer,e.te.stopWordFilter,e.te.stemmer),this.searchPipeline&&(this.searchPipeline.reset(),this.searchPipeline.add(e.te.stemmer))},e.te.wordCharacters="ఀ-ఄఅ-ఔక-హా-ౌౕ-ౖౘ-ౚౠ-ౡౢ-ౣ౦-౯౸-౿఼ఽ్ౝ౷",e.te.trimmer=e.trimmerSupport.generateTrimmer(e.te.wordCharacters),e.Pipeline.registerFunction(e.te.trimmer,"trimmer-te"),e.te.stopWordFilter=e.generateStopWordFilter("అందరూ అందుబాటులో అడగండి అడగడం అడ్డంగా అనుగుణంగా అనుమతించు అనుమతిస్తుంది అయితే ఇప్పటికే ఉన్నారు ఎక్కడైనా ఎప్పుడు ఎవరైనా ఎవరో ఏ ఏదైనా ఏమైనప్పటికి ఒక ఒకరు కనిపిస్తాయి కాదు కూడా గా గురించి చుట్టూ చేయగలిగింది తగిన తర్వాత దాదాపు దూరంగా నిజంగా పై ప్రకారం ప్రక్కన మధ్య మరియు మరొక మళ్ళీ మాత్రమే మెచ్చుకో వద్ద వెంట వేరుగా వ్యతిరేకంగా సంబంధం".split(" ")),e.te.stemmer=function(){return function(e){return"function"==typeof e.update?e.update(function(e){return e}):e}}();var t=e.wordcut;t.init(),e.te.tokenizer=function(r){if(!arguments.length||null==r||void 0==r)return[];if(Array.isArray(r))return r.map(function(t){return isLunr2?new e.Token(t.toLowerCase()):t.toLowerCase()});var i=r.toString().toLowerCase().replace(/^\s+/,"");return t.cut(i).split("|")},e.Pipeline.registerFunction(e.te.stemmer,"stemmer-te"),e.Pipeline.registerFunction(e.te.stopWordFilter,"stopWordFilter-te")}});
|
||||
1
v0.18.0/assets/javascripts/lunr/min/lunr.th.min.js
vendored
Normal file
1
v0.18.0/assets/javascripts/lunr/min/lunr.th.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var r="2"==e.version[0];e.th=function(){this.pipeline.reset(),this.pipeline.add(e.th.trimmer),r?this.tokenizer=e.th.tokenizer:(e.tokenizer&&(e.tokenizer=e.th.tokenizer),this.tokenizerFn&&(this.tokenizerFn=e.th.tokenizer))},e.th.wordCharacters="[-]",e.th.trimmer=e.trimmerSupport.generateTrimmer(e.th.wordCharacters),e.Pipeline.registerFunction(e.th.trimmer,"trimmer-th");var t=e.wordcut;t.init(),e.th.tokenizer=function(i){if(!arguments.length||null==i||void 0==i)return[];if(Array.isArray(i))return i.map(function(t){return r?new e.Token(t):t});var n=i.toString().replace(/^\s+/,"");return t.cut(n).split("|")}}});
|
||||
18
v0.18.0/assets/javascripts/lunr/min/lunr.tr.min.js
vendored
Normal file
18
v0.18.0/assets/javascripts/lunr/min/lunr.tr.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
v0.18.0/assets/javascripts/lunr/min/lunr.vi.min.js
vendored
Normal file
1
v0.18.0/assets/javascripts/lunr/min/lunr.vi.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r():r()(e.lunr)}(this,function(){return function(e){if(void 0===e)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===e.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");e.vi=function(){this.pipeline.reset(),this.pipeline.add(e.vi.stopWordFilter,e.vi.trimmer)},e.vi.wordCharacters="[A-Za-ẓ̀͐́͑̉̃̓ÂâÊêÔôĂ-ăĐ-đƠ-ơƯ-ư]",e.vi.trimmer=e.trimmerSupport.generateTrimmer(e.vi.wordCharacters),e.Pipeline.registerFunction(e.vi.trimmer,"trimmer-vi"),e.vi.stopWordFilter=e.generateStopWordFilter("là cái nhưng mà".split(" "))}});
|
||||
1
v0.18.0/assets/javascripts/lunr/min/lunr.zh.min.js
vendored
Normal file
1
v0.18.0/assets/javascripts/lunr/min/lunr.zh.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
!function(e,r){"function"==typeof define&&define.amd?define(r):"object"==typeof exports?module.exports=r(require("@node-rs/jieba")):r()(e.lunr)}(this,function(e){return function(r,t){if(void 0===r)throw new Error("Lunr is not present. Please include / require Lunr before this script.");if(void 0===r.stemmerSupport)throw new Error("Lunr stemmer support is not present. Please include / require Lunr stemmer support before this script.");var i="2"==r.version[0];r.zh=function(){this.pipeline.reset(),this.pipeline.add(r.zh.trimmer,r.zh.stopWordFilter,r.zh.stemmer),i?this.tokenizer=r.zh.tokenizer:(r.tokenizer&&(r.tokenizer=r.zh.tokenizer),this.tokenizerFn&&(this.tokenizerFn=r.zh.tokenizer))},r.zh.tokenizer=function(n){if(!arguments.length||null==n||void 0==n)return[];if(Array.isArray(n))return n.map(function(e){return i?new r.Token(e.toLowerCase()):e.toLowerCase()});t&&e.load(t);var o=n.toString().trim().toLowerCase(),s=[];e.cut(o,!0).forEach(function(e){s=s.concat(e.split(" "))}),s=s.filter(function(e){return!!e});var u=0;return s.map(function(e,t){if(i){var n=o.indexOf(e,u),s={};return s.position=[n,e.length],s.index=t,u=n,new r.Token(e,s)}return e})},r.zh.wordCharacters="\\w一-龥",r.zh.trimmer=r.trimmerSupport.generateTrimmer(r.zh.wordCharacters),r.Pipeline.registerFunction(r.zh.trimmer,"trimmer-zh"),r.zh.stemmer=function(){return function(e){return e}}(),r.Pipeline.registerFunction(r.zh.stemmer,"stemmer-zh"),r.zh.stopWordFilter=r.generateStopWordFilter("的 一 不 在 人 有 是 为 為 以 于 於 上 他 而 后 後 之 来 來 及 了 因 下 可 到 由 这 這 与 與 也 此 但 并 並 个 個 其 已 无 無 小 我 们 們 起 最 再 今 去 好 只 又 或 很 亦 某 把 那 你 乃 它 吧 被 比 别 趁 当 當 从 從 得 打 凡 儿 兒 尔 爾 该 該 各 给 給 跟 和 何 还 還 即 几 幾 既 看 据 據 距 靠 啦 另 么 麽 每 嘛 拿 哪 您 凭 憑 且 却 卻 让 讓 仍 啥 如 若 使 谁 誰 虽 雖 随 隨 同 所 她 哇 嗡 往 些 向 沿 哟 喲 用 咱 则 則 怎 曾 至 致 着 著 诸 諸 自".split(" ")),r.Pipeline.registerFunction(r.zh.stopWordFilter,"stopWordFilter-zh")}});
|
||||
206
v0.18.0/assets/javascripts/lunr/tinyseg.js
Normal file
206
v0.18.0/assets/javascripts/lunr/tinyseg.js
Normal file
@ -0,0 +1,206 @@
|
||||
/**
|
||||
* export the module via AMD, CommonJS or as a browser global
|
||||
* Export code from https://github.com/umdjs/umd/blob/master/returnExports.js
|
||||
*/
|
||||
;(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define(factory)
|
||||
} else if (typeof exports === 'object') {
|
||||
/**
|
||||
* Node. Does not work with strict CommonJS, but
|
||||
* only CommonJS-like environments that support module.exports,
|
||||
* like Node.
|
||||
*/
|
||||
module.exports = factory()
|
||||
} else {
|
||||
// Browser globals (root is window)
|
||||
factory()(root.lunr);
|
||||
}
|
||||
}(this, function () {
|
||||
/**
|
||||
* Just return a value to define the module export.
|
||||
* This example returns an object, but the module
|
||||
* can return a function as the exported value.
|
||||
*/
|
||||
|
||||
return function(lunr) {
|
||||
// TinySegmenter 0.1 -- Super compact Japanese tokenizer in Javascript
|
||||
// (c) 2008 Taku Kudo <taku@chasen.org>
|
||||
// TinySegmenter is freely distributable under the terms of a new BSD licence.
|
||||
// For details, see http://chasen.org/~taku/software/TinySegmenter/LICENCE.txt
|
||||
|
||||
function TinySegmenter() {
|
||||
var patterns = {
|
||||
"[一二三四五六七八九十百千万億兆]":"M",
|
||||
"[一-龠々〆ヵヶ]":"H",
|
||||
"[ぁ-ん]":"I",
|
||||
"[ァ-ヴーア-ン゙ー]":"K",
|
||||
"[a-zA-Za-zA-Z]":"A",
|
||||
"[0-90-9]":"N"
|
||||
}
|
||||
this.chartype_ = [];
|
||||
for (var i in patterns) {
|
||||
var regexp = new RegExp(i);
|
||||
this.chartype_.push([regexp, patterns[i]]);
|
||||
}
|
||||
|
||||
this.BIAS__ = -332
|
||||
this.BC1__ = {"HH":6,"II":2461,"KH":406,"OH":-1378};
|
||||
this.BC2__ = {"AA":-3267,"AI":2744,"AN":-878,"HH":-4070,"HM":-1711,"HN":4012,"HO":3761,"IA":1327,"IH":-1184,"II":-1332,"IK":1721,"IO":5492,"KI":3831,"KK":-8741,"MH":-3132,"MK":3334,"OO":-2920};
|
||||
this.BC3__ = {"HH":996,"HI":626,"HK":-721,"HN":-1307,"HO":-836,"IH":-301,"KK":2762,"MK":1079,"MM":4034,"OA":-1652,"OH":266};
|
||||
this.BP1__ = {"BB":295,"OB":304,"OO":-125,"UB":352};
|
||||
this.BP2__ = {"BO":60,"OO":-1762};
|
||||
this.BQ1__ = {"BHH":1150,"BHM":1521,"BII":-1158,"BIM":886,"BMH":1208,"BNH":449,"BOH":-91,"BOO":-2597,"OHI":451,"OIH":-296,"OKA":1851,"OKH":-1020,"OKK":904,"OOO":2965};
|
||||
this.BQ2__ = {"BHH":118,"BHI":-1159,"BHM":466,"BIH":-919,"BKK":-1720,"BKO":864,"OHH":-1139,"OHM":-181,"OIH":153,"UHI":-1146};
|
||||
this.BQ3__ = {"BHH":-792,"BHI":2664,"BII":-299,"BKI":419,"BMH":937,"BMM":8335,"BNN":998,"BOH":775,"OHH":2174,"OHM":439,"OII":280,"OKH":1798,"OKI":-793,"OKO":-2242,"OMH":-2402,"OOO":11699};
|
||||
this.BQ4__ = {"BHH":-3895,"BIH":3761,"BII":-4654,"BIK":1348,"BKK":-1806,"BMI":-3385,"BOO":-12396,"OAH":926,"OHH":266,"OHK":-2036,"ONN":-973};
|
||||
this.BW1__ = {",と":660,",同":727,"B1あ":1404,"B1同":542,"、と":660,"、同":727,"」と":1682,"あっ":1505,"いう":1743,"いっ":-2055,"いる":672,"うし":-4817,"うん":665,"から":3472,"がら":600,"こう":-790,"こと":2083,"こん":-1262,"さら":-4143,"さん":4573,"した":2641,"して":1104,"すで":-3399,"そこ":1977,"それ":-871,"たち":1122,"ため":601,"った":3463,"つい":-802,"てい":805,"てき":1249,"でき":1127,"です":3445,"では":844,"とい":-4915,"とみ":1922,"どこ":3887,"ない":5713,"なっ":3015,"など":7379,"なん":-1113,"にし":2468,"には":1498,"にも":1671,"に対":-912,"の一":-501,"の中":741,"ませ":2448,"まで":1711,"まま":2600,"まる":-2155,"やむ":-1947,"よっ":-2565,"れた":2369,"れで":-913,"をし":1860,"を見":731,"亡く":-1886,"京都":2558,"取り":-2784,"大き":-2604,"大阪":1497,"平方":-2314,"引き":-1336,"日本":-195,"本当":-2423,"毎日":-2113,"目指":-724,"B1あ":1404,"B1同":542,"」と":1682};
|
||||
this.BW2__ = {"..":-11822,"11":-669,"――":-5730,"−−":-13175,"いう":-1609,"うか":2490,"かし":-1350,"かも":-602,"から":-7194,"かれ":4612,"がい":853,"がら":-3198,"きた":1941,"くな":-1597,"こと":-8392,"この":-4193,"させ":4533,"され":13168,"さん":-3977,"しい":-1819,"しか":-545,"した":5078,"して":972,"しな":939,"その":-3744,"たい":-1253,"たた":-662,"ただ":-3857,"たち":-786,"たと":1224,"たは":-939,"った":4589,"って":1647,"っと":-2094,"てい":6144,"てき":3640,"てく":2551,"ては":-3110,"ても":-3065,"でい":2666,"でき":-1528,"でし":-3828,"です":-4761,"でも":-4203,"とい":1890,"とこ":-1746,"とと":-2279,"との":720,"とみ":5168,"とも":-3941,"ない":-2488,"なが":-1313,"など":-6509,"なの":2614,"なん":3099,"にお":-1615,"にし":2748,"にな":2454,"によ":-7236,"に対":-14943,"に従":-4688,"に関":-11388,"のか":2093,"ので":-7059,"のに":-6041,"のの":-6125,"はい":1073,"はが":-1033,"はず":-2532,"ばれ":1813,"まし":-1316,"まで":-6621,"まれ":5409,"めて":-3153,"もい":2230,"もの":-10713,"らか":-944,"らし":-1611,"らに":-1897,"りし":651,"りま":1620,"れた":4270,"れて":849,"れば":4114,"ろう":6067,"われ":7901,"を通":-11877,"んだ":728,"んな":-4115,"一人":602,"一方":-1375,"一日":970,"一部":-1051,"上が":-4479,"会社":-1116,"出て":2163,"分の":-7758,"同党":970,"同日":-913,"大阪":-2471,"委員":-1250,"少な":-1050,"年度":-8669,"年間":-1626,"府県":-2363,"手権":-1982,"新聞":-4066,"日新":-722,"日本":-7068,"日米":3372,"曜日":-601,"朝鮮":-2355,"本人":-2697,"東京":-1543,"然と":-1384,"社会":-1276,"立て":-990,"第に":-1612,"米国":-4268,"11":-669};
|
||||
this.BW3__ = {"あた":-2194,"あり":719,"ある":3846,"い.":-1185,"い。":-1185,"いい":5308,"いえ":2079,"いく":3029,"いた":2056,"いっ":1883,"いる":5600,"いわ":1527,"うち":1117,"うと":4798,"えと":1454,"か.":2857,"か。":2857,"かけ":-743,"かっ":-4098,"かに":-669,"から":6520,"かり":-2670,"が,":1816,"が、":1816,"がき":-4855,"がけ":-1127,"がっ":-913,"がら":-4977,"がり":-2064,"きた":1645,"けど":1374,"こと":7397,"この":1542,"ころ":-2757,"さい":-714,"さを":976,"し,":1557,"し、":1557,"しい":-3714,"した":3562,"して":1449,"しな":2608,"しま":1200,"す.":-1310,"す。":-1310,"する":6521,"ず,":3426,"ず、":3426,"ずに":841,"そう":428,"た.":8875,"た。":8875,"たい":-594,"たの":812,"たり":-1183,"たる":-853,"だ.":4098,"だ。":4098,"だっ":1004,"った":-4748,"って":300,"てい":6240,"てお":855,"ても":302,"です":1437,"でに":-1482,"では":2295,"とう":-1387,"とし":2266,"との":541,"とも":-3543,"どう":4664,"ない":1796,"なく":-903,"など":2135,"に,":-1021,"に、":-1021,"にし":1771,"にな":1906,"には":2644,"の,":-724,"の、":-724,"の子":-1000,"は,":1337,"は、":1337,"べき":2181,"まし":1113,"ます":6943,"まっ":-1549,"まで":6154,"まれ":-793,"らし":1479,"られ":6820,"るる":3818,"れ,":854,"れ、":854,"れた":1850,"れて":1375,"れば":-3246,"れる":1091,"われ":-605,"んだ":606,"んで":798,"カ月":990,"会議":860,"入り":1232,"大会":2217,"始め":1681,"市":965,"新聞":-5055,"日,":974,"日、":974,"社会":2024,"カ月":990};
|
||||
this.TC1__ = {"AAA":1093,"HHH":1029,"HHM":580,"HII":998,"HOH":-390,"HOM":-331,"IHI":1169,"IOH":-142,"IOI":-1015,"IOM":467,"MMH":187,"OOI":-1832};
|
||||
this.TC2__ = {"HHO":2088,"HII":-1023,"HMM":-1154,"IHI":-1965,"KKH":703,"OII":-2649};
|
||||
this.TC3__ = {"AAA":-294,"HHH":346,"HHI":-341,"HII":-1088,"HIK":731,"HOH":-1486,"IHH":128,"IHI":-3041,"IHO":-1935,"IIH":-825,"IIM":-1035,"IOI":-542,"KHH":-1216,"KKA":491,"KKH":-1217,"KOK":-1009,"MHH":-2694,"MHM":-457,"MHO":123,"MMH":-471,"NNH":-1689,"NNO":662,"OHO":-3393};
|
||||
this.TC4__ = {"HHH":-203,"HHI":1344,"HHK":365,"HHM":-122,"HHN":182,"HHO":669,"HIH":804,"HII":679,"HOH":446,"IHH":695,"IHO":-2324,"IIH":321,"III":1497,"IIO":656,"IOO":54,"KAK":4845,"KKA":3386,"KKK":3065,"MHH":-405,"MHI":201,"MMH":-241,"MMM":661,"MOM":841};
|
||||
this.TQ1__ = {"BHHH":-227,"BHHI":316,"BHIH":-132,"BIHH":60,"BIII":1595,"BNHH":-744,"BOHH":225,"BOOO":-908,"OAKK":482,"OHHH":281,"OHIH":249,"OIHI":200,"OIIH":-68};
|
||||
this.TQ2__ = {"BIHH":-1401,"BIII":-1033,"BKAK":-543,"BOOO":-5591};
|
||||
this.TQ3__ = {"BHHH":478,"BHHM":-1073,"BHIH":222,"BHII":-504,"BIIH":-116,"BIII":-105,"BMHI":-863,"BMHM":-464,"BOMH":620,"OHHH":346,"OHHI":1729,"OHII":997,"OHMH":481,"OIHH":623,"OIIH":1344,"OKAK":2792,"OKHH":587,"OKKA":679,"OOHH":110,"OOII":-685};
|
||||
this.TQ4__ = {"BHHH":-721,"BHHM":-3604,"BHII":-966,"BIIH":-607,"BIII":-2181,"OAAA":-2763,"OAKK":180,"OHHH":-294,"OHHI":2446,"OHHO":480,"OHIH":-1573,"OIHH":1935,"OIHI":-493,"OIIH":626,"OIII":-4007,"OKAK":-8156};
|
||||
this.TW1__ = {"につい":-4681,"東京都":2026};
|
||||
this.TW2__ = {"ある程":-2049,"いった":-1256,"ころが":-2434,"しょう":3873,"その後":-4430,"だって":-1049,"ていた":1833,"として":-4657,"ともに":-4517,"もので":1882,"一気に":-792,"初めて":-1512,"同時に":-8097,"大きな":-1255,"対して":-2721,"社会党":-3216};
|
||||
this.TW3__ = {"いただ":-1734,"してい":1314,"として":-4314,"につい":-5483,"にとっ":-5989,"に当た":-6247,"ので,":-727,"ので、":-727,"のもの":-600,"れから":-3752,"十二月":-2287};
|
||||
this.TW4__ = {"いう.":8576,"いう。":8576,"からな":-2348,"してい":2958,"たが,":1516,"たが、":1516,"ている":1538,"という":1349,"ました":5543,"ません":1097,"ようと":-4258,"よると":5865};
|
||||
this.UC1__ = {"A":484,"K":93,"M":645,"O":-505};
|
||||
this.UC2__ = {"A":819,"H":1059,"I":409,"M":3987,"N":5775,"O":646};
|
||||
this.UC3__ = {"A":-1370,"I":2311};
|
||||
this.UC4__ = {"A":-2643,"H":1809,"I":-1032,"K":-3450,"M":3565,"N":3876,"O":6646};
|
||||
this.UC5__ = {"H":313,"I":-1238,"K":-799,"M":539,"O":-831};
|
||||
this.UC6__ = {"H":-506,"I":-253,"K":87,"M":247,"O":-387};
|
||||
this.UP1__ = {"O":-214};
|
||||
this.UP2__ = {"B":69,"O":935};
|
||||
this.UP3__ = {"B":189};
|
||||
this.UQ1__ = {"BH":21,"BI":-12,"BK":-99,"BN":142,"BO":-56,"OH":-95,"OI":477,"OK":410,"OO":-2422};
|
||||
this.UQ2__ = {"BH":216,"BI":113,"OK":1759};
|
||||
this.UQ3__ = {"BA":-479,"BH":42,"BI":1913,"BK":-7198,"BM":3160,"BN":6427,"BO":14761,"OI":-827,"ON":-3212};
|
||||
this.UW1__ = {",":156,"、":156,"「":-463,"あ":-941,"う":-127,"が":-553,"き":121,"こ":505,"で":-201,"と":-547,"ど":-123,"に":-789,"の":-185,"は":-847,"も":-466,"や":-470,"よ":182,"ら":-292,"り":208,"れ":169,"を":-446,"ん":-137,"・":-135,"主":-402,"京":-268,"区":-912,"午":871,"国":-460,"大":561,"委":729,"市":-411,"日":-141,"理":361,"生":-408,"県":-386,"都":-718,"「":-463,"・":-135};
|
||||
this.UW2__ = {",":-829,"、":-829,"〇":892,"「":-645,"」":3145,"あ":-538,"い":505,"う":134,"お":-502,"か":1454,"が":-856,"く":-412,"こ":1141,"さ":878,"ざ":540,"し":1529,"す":-675,"せ":300,"そ":-1011,"た":188,"だ":1837,"つ":-949,"て":-291,"で":-268,"と":-981,"ど":1273,"な":1063,"に":-1764,"の":130,"は":-409,"ひ":-1273,"べ":1261,"ま":600,"も":-1263,"や":-402,"よ":1639,"り":-579,"る":-694,"れ":571,"を":-2516,"ん":2095,"ア":-587,"カ":306,"キ":568,"ッ":831,"三":-758,"不":-2150,"世":-302,"中":-968,"主":-861,"事":492,"人":-123,"会":978,"保":362,"入":548,"初":-3025,"副":-1566,"北":-3414,"区":-422,"大":-1769,"天":-865,"太":-483,"子":-1519,"学":760,"実":1023,"小":-2009,"市":-813,"年":-1060,"強":1067,"手":-1519,"揺":-1033,"政":1522,"文":-1355,"新":-1682,"日":-1815,"明":-1462,"最":-630,"朝":-1843,"本":-1650,"東":-931,"果":-665,"次":-2378,"民":-180,"気":-1740,"理":752,"発":529,"目":-1584,"相":-242,"県":-1165,"立":-763,"第":810,"米":509,"自":-1353,"行":838,"西":-744,"見":-3874,"調":1010,"議":1198,"込":3041,"開":1758,"間":-1257,"「":-645,"」":3145,"ッ":831,"ア":-587,"カ":306,"キ":568};
|
||||
this.UW3__ = {",":4889,"1":-800,"−":-1723,"、":4889,"々":-2311,"〇":5827,"」":2670,"〓":-3573,"あ":-2696,"い":1006,"う":2342,"え":1983,"お":-4864,"か":-1163,"が":3271,"く":1004,"け":388,"げ":401,"こ":-3552,"ご":-3116,"さ":-1058,"し":-395,"す":584,"せ":3685,"そ":-5228,"た":842,"ち":-521,"っ":-1444,"つ":-1081,"て":6167,"で":2318,"と":1691,"ど":-899,"な":-2788,"に":2745,"の":4056,"は":4555,"ひ":-2171,"ふ":-1798,"へ":1199,"ほ":-5516,"ま":-4384,"み":-120,"め":1205,"も":2323,"や":-788,"よ":-202,"ら":727,"り":649,"る":5905,"れ":2773,"わ":-1207,"を":6620,"ん":-518,"ア":551,"グ":1319,"ス":874,"ッ":-1350,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278,"・":-3794,"一":-1619,"下":-1759,"世":-2087,"両":3815,"中":653,"主":-758,"予":-1193,"二":974,"人":2742,"今":792,"他":1889,"以":-1368,"低":811,"何":4265,"作":-361,"保":-2439,"元":4858,"党":3593,"全":1574,"公":-3030,"六":755,"共":-1880,"円":5807,"再":3095,"分":457,"初":2475,"別":1129,"前":2286,"副":4437,"力":365,"動":-949,"務":-1872,"化":1327,"北":-1038,"区":4646,"千":-2309,"午":-783,"協":-1006,"口":483,"右":1233,"各":3588,"合":-241,"同":3906,"和":-837,"員":4513,"国":642,"型":1389,"場":1219,"外":-241,"妻":2016,"学":-1356,"安":-423,"実":-1008,"家":1078,"小":-513,"少":-3102,"州":1155,"市":3197,"平":-1804,"年":2416,"広":-1030,"府":1605,"度":1452,"建":-2352,"当":-3885,"得":1905,"思":-1291,"性":1822,"戸":-488,"指":-3973,"政":-2013,"教":-1479,"数":3222,"文":-1489,"新":1764,"日":2099,"旧":5792,"昨":-661,"時":-1248,"曜":-951,"最":-937,"月":4125,"期":360,"李":3094,"村":364,"東":-805,"核":5156,"森":2438,"業":484,"氏":2613,"民":-1694,"決":-1073,"法":1868,"海":-495,"無":979,"物":461,"特":-3850,"生":-273,"用":914,"町":1215,"的":7313,"直":-1835,"省":792,"県":6293,"知":-1528,"私":4231,"税":401,"立":-960,"第":1201,"米":7767,"系":3066,"約":3663,"級":1384,"統":-4229,"総":1163,"線":1255,"者":6457,"能":725,"自":-2869,"英":785,"見":1044,"調":-562,"財":-733,"費":1777,"車":1835,"軍":1375,"込":-1504,"通":-1136,"選":-681,"郎":1026,"郡":4404,"部":1200,"金":2163,"長":421,"開":-1432,"間":1302,"関":-1282,"雨":2009,"電":-1045,"非":2066,"駅":1620,"1":-800,"」":2670,"・":-3794,"ッ":-1350,"ア":551,"グ":1319,"ス":874,"ト":521,"ム":1109,"ル":1591,"ロ":2201,"ン":278};
|
||||
this.UW4__ = {",":3930,".":3508,"―":-4841,"、":3930,"。":3508,"〇":4999,"「":1895,"」":3798,"〓":-5156,"あ":4752,"い":-3435,"う":-640,"え":-2514,"お":2405,"か":530,"が":6006,"き":-4482,"ぎ":-3821,"く":-3788,"け":-4376,"げ":-4734,"こ":2255,"ご":1979,"さ":2864,"し":-843,"じ":-2506,"す":-731,"ず":1251,"せ":181,"そ":4091,"た":5034,"だ":5408,"ち":-3654,"っ":-5882,"つ":-1659,"て":3994,"で":7410,"と":4547,"な":5433,"に":6499,"ぬ":1853,"ね":1413,"の":7396,"は":8578,"ば":1940,"ひ":4249,"び":-4134,"ふ":1345,"へ":6665,"べ":-744,"ほ":1464,"ま":1051,"み":-2082,"む":-882,"め":-5046,"も":4169,"ゃ":-2666,"や":2795,"ょ":-1544,"よ":3351,"ら":-2922,"り":-9726,"る":-14896,"れ":-2613,"ろ":-4570,"わ":-1783,"を":13150,"ん":-2352,"カ":2145,"コ":1789,"セ":1287,"ッ":-724,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637,"・":-4371,"ー":-11870,"一":-2069,"中":2210,"予":782,"事":-190,"井":-1768,"人":1036,"以":544,"会":950,"体":-1286,"作":530,"側":4292,"先":601,"党":-2006,"共":-1212,"内":584,"円":788,"初":1347,"前":1623,"副":3879,"力":-302,"動":-740,"務":-2715,"化":776,"区":4517,"協":1013,"参":1555,"合":-1834,"和":-681,"員":-910,"器":-851,"回":1500,"国":-619,"園":-1200,"地":866,"場":-1410,"塁":-2094,"士":-1413,"多":1067,"大":571,"子":-4802,"学":-1397,"定":-1057,"寺":-809,"小":1910,"屋":-1328,"山":-1500,"島":-2056,"川":-2667,"市":2771,"年":374,"庁":-4556,"後":456,"性":553,"感":916,"所":-1566,"支":856,"改":787,"政":2182,"教":704,"文":522,"方":-856,"日":1798,"時":1829,"最":845,"月":-9066,"木":-485,"来":-442,"校":-360,"業":-1043,"氏":5388,"民":-2716,"気":-910,"沢":-939,"済":-543,"物":-735,"率":672,"球":-1267,"生":-1286,"産":-1101,"田":-2900,"町":1826,"的":2586,"目":922,"省":-3485,"県":2997,"空":-867,"立":-2112,"第":788,"米":2937,"系":786,"約":2171,"経":1146,"統":-1169,"総":940,"線":-994,"署":749,"者":2145,"能":-730,"般":-852,"行":-792,"規":792,"警":-1184,"議":-244,"谷":-1000,"賞":730,"車":-1481,"軍":1158,"輪":-1433,"込":-3370,"近":929,"道":-1291,"選":2596,"郎":-4866,"都":1192,"野":-1100,"銀":-2213,"長":357,"間":-2344,"院":-2297,"際":-2604,"電":-878,"領":-1659,"題":-792,"館":-1984,"首":1749,"高":2120,"「":1895,"」":3798,"・":-4371,"ッ":-724,"ー":-11870,"カ":2145,"コ":1789,"セ":1287,"ト":-403,"メ":-1635,"ラ":-881,"リ":-541,"ル":-856,"ン":-3637};
|
||||
this.UW5__ = {",":465,".":-299,"1":-514,"E2":-32768,"]":-2762,"、":465,"。":-299,"「":363,"あ":1655,"い":331,"う":-503,"え":1199,"お":527,"か":647,"が":-421,"き":1624,"ぎ":1971,"く":312,"げ":-983,"さ":-1537,"し":-1371,"す":-852,"だ":-1186,"ち":1093,"っ":52,"つ":921,"て":-18,"で":-850,"と":-127,"ど":1682,"な":-787,"に":-1224,"の":-635,"は":-578,"べ":1001,"み":502,"め":865,"ゃ":3350,"ょ":854,"り":-208,"る":429,"れ":504,"わ":419,"を":-1264,"ん":327,"イ":241,"ル":451,"ン":-343,"中":-871,"京":722,"会":-1153,"党":-654,"務":3519,"区":-901,"告":848,"員":2104,"大":-1296,"学":-548,"定":1785,"嵐":-1304,"市":-2991,"席":921,"年":1763,"思":872,"所":-814,"挙":1618,"新":-1682,"日":218,"月":-4353,"査":932,"格":1356,"機":-1508,"氏":-1347,"田":240,"町":-3912,"的":-3149,"相":1319,"省":-1052,"県":-4003,"研":-997,"社":-278,"空":-813,"統":1955,"者":-2233,"表":663,"語":-1073,"議":1219,"選":-1018,"郎":-368,"長":786,"間":1191,"題":2368,"館":-689,"1":-514,"E2":-32768,"「":363,"イ":241,"ル":451,"ン":-343};
|
||||
this.UW6__ = {",":227,".":808,"1":-270,"E1":306,"、":227,"。":808,"あ":-307,"う":189,"か":241,"が":-73,"く":-121,"こ":-200,"じ":1782,"す":383,"た":-428,"っ":573,"て":-1014,"で":101,"と":-105,"な":-253,"に":-149,"の":-417,"は":-236,"も":-206,"り":187,"る":-135,"を":195,"ル":-673,"ン":-496,"一":-277,"中":201,"件":-800,"会":624,"前":302,"区":1792,"員":-1212,"委":798,"学":-960,"市":887,"広":-695,"後":535,"業":-697,"相":753,"社":-507,"福":974,"空":-822,"者":1811,"連":463,"郎":1082,"1":-270,"E1":306,"ル":-673,"ン":-496};
|
||||
|
||||
return this;
|
||||
}
|
||||
TinySegmenter.prototype.ctype_ = function(str) {
|
||||
for (var i in this.chartype_) {
|
||||
if (str.match(this.chartype_[i][0])) {
|
||||
return this.chartype_[i][1];
|
||||
}
|
||||
}
|
||||
return "O";
|
||||
}
|
||||
|
||||
TinySegmenter.prototype.ts_ = function(v) {
|
||||
if (v) { return v; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
TinySegmenter.prototype.segment = function(input) {
|
||||
if (input == null || input == undefined || input == "") {
|
||||
return [];
|
||||
}
|
||||
var result = [];
|
||||
var seg = ["B3","B2","B1"];
|
||||
var ctype = ["O","O","O"];
|
||||
var o = input.split("");
|
||||
for (i = 0; i < o.length; ++i) {
|
||||
seg.push(o[i]);
|
||||
ctype.push(this.ctype_(o[i]))
|
||||
}
|
||||
seg.push("E1");
|
||||
seg.push("E2");
|
||||
seg.push("E3");
|
||||
ctype.push("O");
|
||||
ctype.push("O");
|
||||
ctype.push("O");
|
||||
var word = seg[3];
|
||||
var p1 = "U";
|
||||
var p2 = "U";
|
||||
var p3 = "U";
|
||||
for (var i = 4; i < seg.length - 3; ++i) {
|
||||
var score = this.BIAS__;
|
||||
var w1 = seg[i-3];
|
||||
var w2 = seg[i-2];
|
||||
var w3 = seg[i-1];
|
||||
var w4 = seg[i];
|
||||
var w5 = seg[i+1];
|
||||
var w6 = seg[i+2];
|
||||
var c1 = ctype[i-3];
|
||||
var c2 = ctype[i-2];
|
||||
var c3 = ctype[i-1];
|
||||
var c4 = ctype[i];
|
||||
var c5 = ctype[i+1];
|
||||
var c6 = ctype[i+2];
|
||||
score += this.ts_(this.UP1__[p1]);
|
||||
score += this.ts_(this.UP2__[p2]);
|
||||
score += this.ts_(this.UP3__[p3]);
|
||||
score += this.ts_(this.BP1__[p1 + p2]);
|
||||
score += this.ts_(this.BP2__[p2 + p3]);
|
||||
score += this.ts_(this.UW1__[w1]);
|
||||
score += this.ts_(this.UW2__[w2]);
|
||||
score += this.ts_(this.UW3__[w3]);
|
||||
score += this.ts_(this.UW4__[w4]);
|
||||
score += this.ts_(this.UW5__[w5]);
|
||||
score += this.ts_(this.UW6__[w6]);
|
||||
score += this.ts_(this.BW1__[w2 + w3]);
|
||||
score += this.ts_(this.BW2__[w3 + w4]);
|
||||
score += this.ts_(this.BW3__[w4 + w5]);
|
||||
score += this.ts_(this.TW1__[w1 + w2 + w3]);
|
||||
score += this.ts_(this.TW2__[w2 + w3 + w4]);
|
||||
score += this.ts_(this.TW3__[w3 + w4 + w5]);
|
||||
score += this.ts_(this.TW4__[w4 + w5 + w6]);
|
||||
score += this.ts_(this.UC1__[c1]);
|
||||
score += this.ts_(this.UC2__[c2]);
|
||||
score += this.ts_(this.UC3__[c3]);
|
||||
score += this.ts_(this.UC4__[c4]);
|
||||
score += this.ts_(this.UC5__[c5]);
|
||||
score += this.ts_(this.UC6__[c6]);
|
||||
score += this.ts_(this.BC1__[c2 + c3]);
|
||||
score += this.ts_(this.BC2__[c3 + c4]);
|
||||
score += this.ts_(this.BC3__[c4 + c5]);
|
||||
score += this.ts_(this.TC1__[c1 + c2 + c3]);
|
||||
score += this.ts_(this.TC2__[c2 + c3 + c4]);
|
||||
score += this.ts_(this.TC3__[c3 + c4 + c5]);
|
||||
score += this.ts_(this.TC4__[c4 + c5 + c6]);
|
||||
// score += this.ts_(this.TC5__[c4 + c5 + c6]);
|
||||
score += this.ts_(this.UQ1__[p1 + c1]);
|
||||
score += this.ts_(this.UQ2__[p2 + c2]);
|
||||
score += this.ts_(this.UQ3__[p3 + c3]);
|
||||
score += this.ts_(this.BQ1__[p2 + c2 + c3]);
|
||||
score += this.ts_(this.BQ2__[p2 + c3 + c4]);
|
||||
score += this.ts_(this.BQ3__[p3 + c2 + c3]);
|
||||
score += this.ts_(this.BQ4__[p3 + c3 + c4]);
|
||||
score += this.ts_(this.TQ1__[p2 + c1 + c2 + c3]);
|
||||
score += this.ts_(this.TQ2__[p2 + c2 + c3 + c4]);
|
||||
score += this.ts_(this.TQ3__[p3 + c1 + c2 + c3]);
|
||||
score += this.ts_(this.TQ4__[p3 + c2 + c3 + c4]);
|
||||
var p = "O";
|
||||
if (score > 0) {
|
||||
result.push(word);
|
||||
word = "";
|
||||
p = "B";
|
||||
}
|
||||
p1 = p2;
|
||||
p2 = p3;
|
||||
p3 = p;
|
||||
word += seg[i];
|
||||
}
|
||||
result.push(word);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
lunr.TinySegmenter = TinySegmenter;
|
||||
};
|
||||
|
||||
}));
|
||||
6708
v0.18.0/assets/javascripts/lunr/wordcut.js
Normal file
6708
v0.18.0/assets/javascripts/lunr/wordcut.js
Normal file
File diff suppressed because one or more lines are too long
42
v0.18.0/assets/javascripts/workers/search.b8dbb3d2.min.js
vendored
Normal file
42
v0.18.0/assets/javascripts/workers/search.b8dbb3d2.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
v0.18.0/assets/stylesheets/main.bcfcd587.min.css
vendored
Normal file
1
v0.18.0/assets/stylesheets/main.bcfcd587.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
v0.18.0/assets/stylesheets/main.bcfcd587.min.css.map
Normal file
1
v0.18.0/assets/stylesheets/main.bcfcd587.min.css.map
Normal file
File diff suppressed because one or more lines are too long
1
v0.18.0/assets/stylesheets/palette.06af60db.min.css
vendored
Normal file
1
v0.18.0/assets/stylesheets/palette.06af60db.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
1
v0.18.0/assets/stylesheets/palette.06af60db.min.css.map
Normal file
1
v0.18.0/assets/stylesheets/palette.06af60db.min.css.map
Normal file
@ -0,0 +1 @@
|
||||
{"version":3,"sources":["src/templates/assets/stylesheets/palette/_scheme.scss","../../../../src/templates/assets/stylesheets/palette.scss","src/templates/assets/stylesheets/palette/_accent.scss","src/templates/assets/stylesheets/palette/_primary.scss","src/templates/assets/stylesheets/utilities/_break.scss"],"names":[],"mappings":"AA2BA,cAGE,6BAME,sDAAA,CACA,6DAAA,CACA,+DAAA,CACA,gEAAA,CACA,mDAAA,CACA,6DAAA,CACA,+DAAA,CACA,gEAAA,CAGA,mDAAA,CACA,gDAAA,CAGA,0BAAA,CACA,mCAAA,CAGA,iCAAA,CACA,kCAAA,CACA,mCAAA,CACA,mCAAA,CACA,kCAAA,CACA,iCAAA,CACA,+CAAA,CACA,6DAAA,CACA,gEAAA,CACA,4DAAA,CACA,4DAAA,CACA,6DAAA,CAGA,6CAAA,CAGA,+CAAA,CAGA,uDAAA,CACA,6DAAA,CACA,2DAAA,CAGA,iCAAA,CAGA,yDAAA,CACA,iEAAA,CAGA,mDAAA,CACA,mDAAA,CAGA,qDAAA,CACA,uDAAA,CAGA,8DAAA,CAKA,8DAAA,CAKA,0DAAA,CAvEA,iBCeF,CD6DE,kHAEE,YC3DJ,CDkFE,yDACE,4BChFJ,CD+EE,2DACE,4BC7EJ,CD4EE,gEACE,4BC1EJ,CDyEE,2DACE,4BCvEJ,CDsEE,yDACE,4BCpEJ,CDmEE,0DACE,4BCjEJ,CDgEE,gEACE,4BC9DJ,CD6DE,0DACE,4BC3DJ,CD0DE,2OACE,4BC/CJ,CDsDA,+FAGE,iCCpDF,CACF,CC/CE,2BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCD2CN,CCrDE,4BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDkDN,CC5DE,8BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDyDN,CCnEE,mCACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDgEN,CC1EE,8BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDuEN,CCjFE,4BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCD8EN,CCxFE,kCACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDqFN,CC/FE,4BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCD4FN,CCtGE,4BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDmGN,CC7GE,6BACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCD0GN,CCpHE,mCACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDiHN,CC3HE,4BACE,4BAAA,CACA,2CAAA,CAIE,8BAAA,CACA,qCD2HN,CClIE,8BACE,4BAAA,CACA,2CAAA,CAIE,8BAAA,CACA,qCDkIN,CCzIE,6BACE,yBAAA,CACA,2CAAA,CAIE,8BAAA,CACA,qCDyIN,CChJE,8BACE,4BAAA,CACA,2CAAA,CAIE,8BAAA,CACA,qCDgJN,CCvJE,mCACE,4BAAA,CACA,2CAAA,CAOE,yBAAA,CACA,qCDoJN,CEzJE,4BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsJN,CEjKE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCF8JN,CEzKE,+BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsKN,CEjLE,oCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCF8KN,CEzLE,+BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsLN,CEjME,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCF8LN,CEzME,mCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsMN,CEjNE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCF8MN,CEzNE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsNN,CEjOE,8BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCF8NN,CEzOE,oCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsON,CEjPE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAIE,+BAAA,CACA,sCFiPN,CEzPE,+BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAIE,+BAAA,CACA,sCFyPN,CEjQE,8BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAIE,+BAAA,CACA,sCFiQN,CEzQE,+BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAIE,+BAAA,CACA,sCFyQN,CEjRE,oCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCF8QN,CEzRE,8BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCFsRN,CEjSE,6BACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCAAA,CAKA,4BF0RN,CE1SE,kCACE,6BAAA,CACA,oCAAA,CACA,mCAAA,CAOE,0BAAA,CACA,sCAAA,CAKA,4BFmSN,CEpRE,sEACE,4BFuRJ,CExRE,+DACE,4BF2RJ,CE5RE,iEACE,4BF+RJ,CEhSE,gEACE,4BFmSJ,CEpSE,iEACE,4BFuSJ,CE9RA,8BACE,mDAAA,CACA,4DAAA,CACA,0DAAA,CACA,oDAAA,CACA,2DAAA,CAGA,4BF+RF,CE5RE,yCACE,+BF8RJ,CE3RI,kDAEE,0CAAA,CACA,sCAAA,CAFA,mCF+RN,CG3MI,mCD1EA,+CACE,8CFwRJ,CErRI,qDACE,8CFuRN,CElRE,iEACE,mCFoRJ,CACF,CGtNI,sCDvDA,uCACE,oCFgRJ,CACF,CEvQA,8BACE,kDAAA,CACA,4DAAA,CACA,wDAAA,CACA,oDAAA,CACA,6DAAA,CAGA,4BFwQF,CErQE,yCACE,+BFuQJ,CEpQI,kDAEE,0CAAA,CACA,sCAAA,CAFA,mCFwQN,CEjQE,yCACE,6CFmQJ,CG5NI,0CDhCA,8CACE,gDF+PJ,CACF,CGjOI,0CDvBA,iFACE,6CF2PJ,CACF,CGzPI,sCDKA,uCACE,6CFuPJ,CACF","file":"palette.css"}
|
||||
6
v0.18.0/charts/OWNERS
Normal file
6
v0.18.0/charts/OWNERS
Normal file
@ -0,0 +1,6 @@
|
||||
labels:
|
||||
- chart
|
||||
approvers:
|
||||
- stevehipwell
|
||||
reviewers:
|
||||
- stevehipwell
|
||||
3039
v0.18.0/charts/external-dns/CHANGELOG/index.html
Normal file
3039
v0.18.0/charts/external-dns/CHANGELOG/index.html
Normal file
File diff suppressed because it is too large
Load Diff
23
v0.18.0/charts/external-dns/Chart.yaml
Normal file
23
v0.18.0/charts/external-dns/Chart.yaml
Normal file
@ -0,0 +1,23 @@
|
||||
apiVersion: v2
|
||||
name: external-dns
|
||||
description: ExternalDNS synchronizes exposed Kubernetes Services and Ingresses with DNS providers.
|
||||
type: application
|
||||
version: 1.17.0
|
||||
appVersion: 0.17.0
|
||||
keywords:
|
||||
- kubernetes
|
||||
- k8s
|
||||
- externaldns
|
||||
- external-dns
|
||||
- dns
|
||||
- service
|
||||
- ingress
|
||||
- gateway
|
||||
home: https://github.com/kubernetes-sigs/external-dns/
|
||||
icon: https://github.com/kubernetes-sigs/external-dns/raw/master/docs/img/external-dns.png
|
||||
sources:
|
||||
- https://github.com/kubernetes-sigs/external-dns/
|
||||
maintainers:
|
||||
- name: stevehipwell
|
||||
email: steve.hipwell@gmail.com
|
||||
annotations: {}
|
||||
94
v0.18.0/charts/external-dns/README.md.gotmpl
Normal file
94
v0.18.0/charts/external-dns/README.md.gotmpl
Normal file
@ -0,0 +1,94 @@
|
||||
{{ template "chart.header" . }}
|
||||
{{ template "chart.deprecationWarning" . }}
|
||||
|
||||
{{ template "chart.badgesSection" . }}
|
||||
|
||||
{{ template "chart.description" . }}
|
||||
|
||||
{{ template "chart.homepageLine" . }}
|
||||
|
||||
{{ template "chart.maintainersSection" . }}
|
||||
|
||||
{{ template "chart.sourcesSection" . }}
|
||||
|
||||
## Installing the Chart
|
||||
|
||||
Before you can install the chart you will need to add the `external-dns` repo to [Helm](https://helm.sh/).
|
||||
|
||||
```shell
|
||||
helm repo add external-dns https://kubernetes-sigs.github.io/external-dns/
|
||||
```
|
||||
|
||||
After you've installed the repo you can install the chart.
|
||||
|
||||
```shell
|
||||
helm upgrade --install {{ template "chart.name" . }} external-dns/{{ template "chart.name" . }} --version {{ template "chart.version" . }}
|
||||
```
|
||||
|
||||
## Providers
|
||||
|
||||
> Legacy support of setting `provider: <name>` is deprecated.
|
||||
|
||||
Configuring the _ExternalDNS_ provider should be done via the `provider.name` value with provider specific configuration being set via the `provider.<name>.<key>` values, where supported, and the `extraArgs` value.
|
||||
|
||||
See [documentation](https://kubernetes-sigs.github.io/external-dns/#new-providers) for more info on available providers and tutorials.
|
||||
|
||||
### Providers with Specific Configuration Support
|
||||
|
||||
| Provider | Supported |
|
||||
|------------------------|------------|
|
||||
| `webhook` | ✅ |
|
||||
|
||||
### Other Providers
|
||||
|
||||
For set up for a specific provider using the Helm chart, see the following links:
|
||||
|
||||
* [AWS](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/aws.md#using-helm-with-oidc)
|
||||
* [akamai-edgedns](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/akamai-edgedns.md#using-helm)
|
||||
* [cloudflare](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/cloudflare.md#using-helm)
|
||||
* [digitalocean](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/digitalocean.md#using-helm)
|
||||
* [godaddy](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/godaddy.md#using-helm)
|
||||
* [ns1](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/ns1.md#using-helm)
|
||||
* [plural](https://github.com/kubernetes-sigs/external-dns/blob/master/docs/tutorials/plural.md#using-helm)
|
||||
|
||||
## Namespaced Scoped Installation
|
||||
|
||||
external-dns supports running on a namespaced only scope, too.
|
||||
If `namespaced=true` is defined, the helm chart will setup `Roles` and `RoleBindings` instead `ClusterRoles` and `ClusterRoleBindings`.
|
||||
|
||||
### Limited Supported
|
||||
|
||||
Not all sources are supported in namespaced scope, since some sources depends on cluster-wide resources.
|
||||
For example: Source `node` isn't supported, since `kind: Node` has scope `Cluster`.
|
||||
Sources like `istio-virtualservice` only work, if all resources like `Gateway` and `VirtualService` are present in the same
|
||||
namespaces as `external-dns`.
|
||||
|
||||
The annotation `external-dns.alpha.kubernetes.io/endpoints-type: NodeExternalIP` is not supported.
|
||||
|
||||
If `namespaced` is set to `true`, please ensure that `sources` my only contains supported sources (Default: `service,ingress`).
|
||||
|
||||
### Support Matrix
|
||||
|
||||
| Source | Supported | Infos |
|
||||
|------------------------|------------|------------------------|
|
||||
| `ingress` | ✅ | |
|
||||
| `istio-gateway` | ✅ | |
|
||||
| `istio-virtualservice` | ✅ | |
|
||||
| `crd` | ✅ | |
|
||||
| `kong-tcpingress` | ✅ | |
|
||||
| `openshift-route` | ✅ | |
|
||||
| `skipper-routegroup` | ✅ | |
|
||||
| `gloo-proxy` | ✅ | |
|
||||
| `contour-httpproxy` | ✅ | |
|
||||
| `service` | ⚠️️ | NodePort not supported |
|
||||
| `node` | ❌ | |
|
||||
| `pod` | ❌ | |
|
||||
|
||||
|
||||
{{ template "chart.requirementsSection" . }}
|
||||
|
||||
{{ template "chart.valuesSection" . }}
|
||||
|
||||
----------------------------------------------
|
||||
|
||||
Autogenerated from chart metadata using [helm-docs](https://github.com/norwoodj/helm-docs/).
|
||||
44
v0.18.0/charts/external-dns/ci/ci-values.yaml
Normal file
44
v0.18.0/charts/external-dns/ci/ci-values.yaml
Normal file
@ -0,0 +1,44 @@
|
||||
labelFilter: foo=bar
|
||||
managedRecordTypes: []
|
||||
provider:
|
||||
name: inmemory
|
||||
affinity:
|
||||
podAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
topologyKey: "kubernetes.io/hostname"
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app.kubernetes.io/name
|
||||
operator: In
|
||||
values:
|
||||
- test
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
- topologyKey: "kubernetes.io/hostname"
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
topologyKey: "kubernetes.io/hostname"
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
- topologyKey: "kubernetes.io/hostname"
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app.kubernetes.io/name
|
||||
operator: In
|
||||
values:
|
||||
- test
|
||||
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 1
|
||||
topologyKey: "topology.kubernetes.io/zone"
|
||||
whenUnsatisfiable: "ScheduleAnyway"
|
||||
|
||||
serviceAccount:
|
||||
annotations:
|
||||
notTemplated/version: "v1.2.3"
|
||||
justValueTemplated/version: "{{ .Chart.Version }}"
|
||||
"{{ .Chart.Name }}/chart": "{{ .Chart.Version }}"
|
||||
booleanVersion: "true"
|
||||
number: "1"
|
||||
@ -0,0 +1,96 @@
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
api-approved.kubernetes.io: https://github.com/kubernetes-sigs/external-dns/pull/2007
|
||||
name: dnsendpoints.externaldns.k8s.io
|
||||
spec:
|
||||
group: externaldns.k8s.io
|
||||
names:
|
||||
kind: DNSEndpoint
|
||||
listKind: DNSEndpointList
|
||||
plural: dnsendpoints
|
||||
singular: dnsendpoint
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: |-
|
||||
DNSEndpoint is a contract that a user-specified CRD must implement to be used as a source for external-dns.
|
||||
The user-specified CRD should also have the status sub-resource.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: |-
|
||||
APIVersion defines the versioned schema of this representation of an object.
|
||||
Servers should convert recognized schemas to the latest internal value, and
|
||||
may reject unrecognized values.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
type: string
|
||||
kind:
|
||||
description: |-
|
||||
Kind is a string value representing the REST resource this object represents.
|
||||
Servers may infer this from the endpoint the client submits requests to.
|
||||
Cannot be updated.
|
||||
In CamelCase.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: DNSEndpointSpec defines the desired state of DNSEndpoint
|
||||
properties:
|
||||
endpoints:
|
||||
items:
|
||||
description: Endpoint is a high-level way of a connection between a service and an IP
|
||||
properties:
|
||||
dnsName:
|
||||
description: The hostname of the DNS record
|
||||
type: string
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: Labels stores labels defined for the Endpoint
|
||||
type: object
|
||||
providerSpecific:
|
||||
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: array
|
||||
recordTTL:
|
||||
description: TTL for the record
|
||||
format: int64
|
||||
type: integer
|
||||
recordType:
|
||||
description: RecordType type of record, e.g. CNAME, A, AAAA, SRV, TXT etc
|
||||
type: string
|
||||
setIdentifier:
|
||||
description: Identifier to distinguish multiple records with the same name and type (e.g. Route53 records with routing policies other than 'simple')
|
||||
type: string
|
||||
targets:
|
||||
description: The targets the DNS record points to
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
status:
|
||||
description: DNSEndpointStatus defines the observed state of DNSEndpoint
|
||||
properties:
|
||||
observedGeneration:
|
||||
description: The generation observed by the external-dns controller.
|
||||
format: int64
|
||||
type: integer
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
3835
v0.18.0/charts/external-dns/index.html
Normal file
3835
v0.18.0/charts/external-dns/index.html
Normal file
File diff suppressed because it is too large
Load Diff
19
v0.18.0/charts/external-dns/schema/values.yaml
Normal file
19
v0.18.0/charts/external-dns/schema/values.yaml
Normal file
@ -0,0 +1,19 @@
|
||||
# Custom values for schema creation.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your schema.
|
||||
resources:
|
||||
requests:
|
||||
cpu: 200m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: 200m
|
||||
memory: 128Mi
|
||||
|
||||
provider:
|
||||
webhook:
|
||||
requests:
|
||||
cpu: 200m
|
||||
memory: 128Mi
|
||||
limits:
|
||||
cpu: 300m
|
||||
memory: 200Mi
|
||||
18
v0.18.0/charts/external-dns/templates/NOTES.txt
Normal file
18
v0.18.0/charts/external-dns/templates/NOTES.txt
Normal file
@ -0,0 +1,18 @@
|
||||
***********************************************************************
|
||||
* External DNS *
|
||||
***********************************************************************
|
||||
Chart version: {{ .Chart.Version }}
|
||||
App version: {{ .Chart.AppVersion }}
|
||||
Image tag: {{ include "external-dns.image" . }}
|
||||
***********************************************************************
|
||||
|
||||
{{- if eq (typeOf .Values.provider) "string" }}
|
||||
🚧 DEPRECATIONS 🚧
|
||||
|
||||
The following features, functions, or methods are deprecated and no longer recommended for use.
|
||||
|
||||
{{/* The deprecation message for legacy 'provider: name'. */}}
|
||||
{{- if eq (typeOf .Values.provider) "string" -}}
|
||||
❗❗❗ DEPRECATED ❗❗❗ The legacy 'provider: <name>' configuration is in use. Support will be removed in future releases.
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
105
v0.18.0/charts/external-dns/templates/_helpers.tpl
Normal file
105
v0.18.0/charts/external-dns/templates/_helpers.tpl
Normal file
@ -0,0 +1,105 @@
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "external-dns.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "external-dns.fullname" -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "external-dns.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "external-dns.labels" -}}
|
||||
helm.sh/chart: {{ include "external-dns.chart" . }}
|
||||
{{ include "external-dns.selectorLabels" . }}
|
||||
{{- if .Chart.AppVersion }}
|
||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- with .Values.commonLabels }}
|
||||
{{ toYaml . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "external-dns.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "external-dns.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "external-dns.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
{{- default (include "external-dns.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else }}
|
||||
{{- default "default" .Values.serviceAccount.name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
The image to use
|
||||
*/}}
|
||||
{{- define "external-dns.image" -}}
|
||||
{{- printf "%s:%s" .Values.image.repository (default (printf "v%s" .Chart.AppVersion) .Values.image.tag) }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Provider name, Keeps backward compatibility on provider
|
||||
TODO: line eq (typeOf .Values.provider) "string" to be removed in future releases
|
||||
*/}}
|
||||
{{- define "external-dns.providerName" -}}
|
||||
{{- if eq (typeOf .Values.provider) "string" }}
|
||||
{{- .Values.provider }}
|
||||
{{- else }}
|
||||
{{- .Values.provider.name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
The image to use for optional webhook sidecar
|
||||
*/}}
|
||||
{{- define "external-dns.webhookImage" -}}
|
||||
{{- with .image }}
|
||||
{{- if or (empty .repository) (empty .tag) }}
|
||||
{{- fail "ERROR: webhook provider needs an image repository and a tag" }}
|
||||
{{- end }}
|
||||
{{- printf "%s:%s" .repository .tag }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
The pod affinity default label Selector
|
||||
*/}}
|
||||
{{- define "external-dns.labelSelector" -}}
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
{{ include "external-dns.selectorLabels" . | nindent 4 }}
|
||||
{{- end }}
|
||||
130
v0.18.0/charts/external-dns/templates/clusterrole.yaml
Normal file
130
v0.18.0/charts/external-dns/templates/clusterrole.yaml
Normal file
@ -0,0 +1,130 @@
|
||||
{{- if .Values.rbac.create -}}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: {{ .Values.namespaced | ternary "Role" "ClusterRole" }}
|
||||
metadata:
|
||||
name: {{ template "external-dns.fullname" . }}
|
||||
labels:
|
||||
{{- include "external-dns.labels" . | nindent 4 }}
|
||||
rules:
|
||||
{{- if and (not .Values.namespaced) (or (has "node" .Values.sources) (has "pod" .Values.sources) (has "service" .Values.sources) (has "contour-httpproxy" .Values.sources) (has "gloo-proxy" .Values.sources) (has "openshift-route" .Values.sources) (has "skipper-routegroup" .Values.sources)) }}
|
||||
- apiGroups: [""]
|
||||
resources: ["nodes"]
|
||||
verbs: ["list","watch"]
|
||||
{{- end }}
|
||||
{{- if or (has "pod" .Values.sources) (has "service" .Values.sources) (has "contour-httpproxy" .Values.sources) (has "gloo-proxy" .Values.sources) (has "openshift-route" .Values.sources) (has "skipper-routegroup" .Values.sources) }}
|
||||
- apiGroups: [""]
|
||||
resources: ["pods"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- if or (has "service" .Values.sources) (has "contour-httpproxy" .Values.sources) (has "gloo-proxy" .Values.sources) (has "istio-gateway" .Values.sources) (has "istio-virtualservice" .Values.sources) (has "openshift-route" .Values.sources) (has "skipper-routegroup" .Values.sources) }}
|
||||
- apiGroups: [""]
|
||||
resources: ["services"]
|
||||
verbs: ["get","watch","list"]
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- if or (has "ingress" .Values.sources) (has "istio-gateway" .Values.sources) (has "istio-virtualservice" .Values.sources) (has "contour-httpproxy" .Values.sources) (has "openshift-route" .Values.sources) (has "skipper-routegroup" .Values.sources) }}
|
||||
- apiGroups: ["extensions","networking.k8s.io"]
|
||||
resources: ["ingresses"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- if or (has "istio-gateway" .Values.sources) (has "istio-virtualservice" .Values.sources) }}
|
||||
- apiGroups: ["networking.istio.io"]
|
||||
resources: ["gateways"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
|
||||
{{- if has "istio-virtualservice" .Values.sources }}
|
||||
- apiGroups: ["networking.istio.io"]
|
||||
resources: ["virtualservices"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- if has "ambassador-host" .Values.sources }}
|
||||
- apiGroups: ["getambassador.io"]
|
||||
resources: ["hosts","ingresses"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- if has "contour-httpproxy" .Values.sources }}
|
||||
- apiGroups: ["projectcontour.io"]
|
||||
resources: ["httpproxies"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- if has "crd" .Values.sources }}
|
||||
- apiGroups: ["externaldns.k8s.io"]
|
||||
resources: ["dnsendpoints"]
|
||||
verbs: ["get","watch","list"]
|
||||
- apiGroups: ["externaldns.k8s.io"]
|
||||
resources: ["dnsendpoints/status"]
|
||||
verbs: ["*"]
|
||||
{{- end }}
|
||||
{{- if or (has "gateway-httproute" .Values.sources) (has "gateway-grpcroute" .Values.sources) (has "gateway-tlsroute" .Values.sources) (has "gateway-tcproute" .Values.sources) (has "gateway-udproute" .Values.sources) }}
|
||||
- apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["gateways"]
|
||||
verbs: ["get","watch","list"]
|
||||
- apiGroups: [""]
|
||||
resources: ["namespaces"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- if has "gateway-httproute" .Values.sources }}
|
||||
- apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["httproutes"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- if has "gateway-grpcroute" .Values.sources }}
|
||||
- apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["grpcroutes"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- if has "gateway-tlsroute" .Values.sources }}
|
||||
- apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["tlsroutes"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- if has "gateway-tcproute" .Values.sources }}
|
||||
- apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["tcproutes"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- if has "gateway-udproute" .Values.sources }}
|
||||
- apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["udproutes"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- if has "gloo-proxy" .Values.sources }}
|
||||
- apiGroups: ["gloo.solo.io","gateway.solo.io"]
|
||||
resources: ["proxies","virtualservices"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- if has "kong-tcpingress" .Values.sources }}
|
||||
- apiGroups: ["configuration.konghq.com"]
|
||||
resources: ["tcpingresses"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- if has "traefik-proxy" .Values.sources }}
|
||||
- apiGroups: ["traefik.containo.us", "traefik.io"]
|
||||
resources: ["ingressroutes", "ingressroutetcps", "ingressrouteudps"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- if has "openshift-route" .Values.sources }}
|
||||
- apiGroups: ["route.openshift.io"]
|
||||
resources: ["routes"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- if has "skipper-routegroup" .Values.sources }}
|
||||
- apiGroups: ["zalando.org"]
|
||||
resources: ["routegroups"]
|
||||
verbs: ["get","watch","list"]
|
||||
- apiGroups: ["zalando.org"]
|
||||
resources: ["routegroups/status"]
|
||||
verbs: ["patch","update"]
|
||||
{{- end }}
|
||||
{{- if or (has "f5-virtualserver" .Values.sources) (has "f5-transportserver" .Values.sources) }}
|
||||
- apiGroups: ["cis.f5.com"]
|
||||
resources: ["virtualservers", "transportservers"]
|
||||
verbs: ["get","watch","list"]
|
||||
{{- end }}
|
||||
{{- with .Values.rbac.additionalPermissions }}
|
||||
{{- toYaml . | nindent 2 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@ -0,0 +1,16 @@
|
||||
{{- if .Values.rbac.create -}}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: {{ .Values.namespaced | ternary "RoleBinding" "ClusterRoleBinding" }}
|
||||
metadata:
|
||||
name: {{ printf "%s-viewer" (include "external-dns.fullname" .) }}
|
||||
labels:
|
||||
{{- include "external-dns.labels" . | nindent 4 }}
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: {{ .Values.namespaced | ternary "Role" "ClusterRole" }}
|
||||
name: {{ template "external-dns.fullname" . }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ template "external-dns.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
{{- end }}
|
||||
295
v0.18.0/charts/external-dns/templates/deployment.yaml
Normal file
295
v0.18.0/charts/external-dns/templates/deployment.yaml
Normal file
@ -0,0 +1,295 @@
|
||||
{{- $defaultSelector := (include "external-dns.labelSelector" $ ) | fromYaml -}}
|
||||
{{- $providerName := tpl (include "external-dns.providerName" .) $ }}
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: {{ include "external-dns.fullname" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "external-dns.labels" . | nindent 4 }}
|
||||
{{- with .Values.deploymentAnnotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "external-dns.selectorLabels" . | nindent 6 }}
|
||||
strategy:
|
||||
{{- toYaml .Values.deploymentStrategy | nindent 4 }}
|
||||
{{- if not (has (quote .Values.revisionHistoryLimit) (list "" (quote ""))) }}
|
||||
revisionHistoryLimit: {{ .Values.revisionHistoryLimit | int64 }}
|
||||
{{- end }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "external-dns.selectorLabels" . | nindent 8 }}
|
||||
{{- with .Values.podLabels }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if or .Values.secretConfiguration.enabled .Values.podAnnotations }}
|
||||
annotations:
|
||||
{{- if .Values.secretConfiguration.enabled }}
|
||||
checksum/secret: {{ tpl (toYaml .Values.secretConfiguration.data) . | sha256sum }}
|
||||
{{- end }}
|
||||
{{- with .Values.podAnnotations }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if not (quote .Values.automountServiceAccountToken | empty) }}
|
||||
automountServiceAccountToken: {{ .Values.automountServiceAccountToken }}
|
||||
{{- end }}
|
||||
{{- with (default .Values.global.imagePullSecrets .Values.imagePullSecrets) }}
|
||||
imagePullSecrets:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
serviceAccountName: {{ include "external-dns.serviceAccountName" . }}
|
||||
{{- with .Values.shareProcessNamespace }}
|
||||
shareProcessNamespace: {{ . }}
|
||||
{{- end }}
|
||||
{{- with .Values.podSecurityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.priorityClassName }}
|
||||
priorityClassName: {{ . | quote }}
|
||||
{{- end }}
|
||||
{{- with .Values.terminationGracePeriodSeconds }}
|
||||
terminationGracePeriodSeconds: {{ . }}
|
||||
{{- end }}
|
||||
{{- with .Values.dnsPolicy }}
|
||||
dnsPolicy: {{ . }}
|
||||
{{- end }}
|
||||
{{- with .Values.dnsConfig }}
|
||||
dnsConfig:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.initContainers }}
|
||||
initContainers:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
containers:
|
||||
{{- with .Values.extraContainers }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
- name: external-dns
|
||||
{{- with .Values.securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
image: {{ include "external-dns.image" . }}
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
{{- with .Values.env }}
|
||||
env:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
args:
|
||||
- --log-level={{ .Values.logLevel }}
|
||||
- --log-format={{ .Values.logFormat }}
|
||||
- --interval={{ .Values.interval }}
|
||||
{{- if .Values.triggerLoopOnEvent }}
|
||||
- --events
|
||||
{{- end }}
|
||||
{{- range .Values.sources }}
|
||||
- --source={{ . }}
|
||||
{{- end }}
|
||||
- --policy={{ .Values.policy }}
|
||||
- --registry={{ .Values.registry }}
|
||||
{{- if .Values.txtOwnerId }}
|
||||
- --txt-owner-id={{ .Values.txtOwnerId }}
|
||||
{{- end }}
|
||||
{{- if and .Values.txtPrefix .Values.txtSuffix }}
|
||||
{{- fail (printf "'txtPrefix' and 'txtSuffix' are mutually exclusive") }}
|
||||
{{- end }}
|
||||
{{- if .Values.txtPrefix }}
|
||||
- --txt-prefix={{ .Values.txtPrefix }}
|
||||
{{- else if .Values.txtSuffix }}
|
||||
- --txt-suffix={{ .Values.txtSuffix }}
|
||||
{{- end }}
|
||||
{{- if .Values.namespaced }}
|
||||
- --namespace={{ .Release.Namespace }}
|
||||
{{- end }}
|
||||
{{- range .Values.domainFilters }}
|
||||
- --domain-filter={{ . }}
|
||||
{{- end }}
|
||||
{{- range .Values.excludeDomains }}
|
||||
- --exclude-domains={{ . }}
|
||||
{{- end }}
|
||||
{{- if .Values.labelFilter }}
|
||||
- --label-filter={{ .Values.labelFilter }}
|
||||
{{- end }}
|
||||
{{- range .Values.managedRecordTypes }}
|
||||
- --managed-record-types={{ . }}
|
||||
{{- end }}
|
||||
- --provider={{ $providerName }}
|
||||
{{- 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 . $ }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: http
|
||||
protocol: TCP
|
||||
containerPort: 7979
|
||||
livenessProbe:
|
||||
{{- toYaml .Values.livenessProbe | nindent 12 }}
|
||||
readinessProbe:
|
||||
{{- toYaml .Values.readinessProbe | nindent 12 }}
|
||||
{{- if or .Values.secretConfiguration.enabled .Values.extraVolumeMounts }}
|
||||
volumeMounts:
|
||||
{{- if .Values.secretConfiguration.enabled }}
|
||||
- name: secrets
|
||||
mountPath: {{ tpl .Values.secretConfiguration.mountPath $ }}
|
||||
{{- with .Values.secretConfiguration.subPath }}
|
||||
subPath: {{ tpl . $ }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .Values.extraVolumeMounts }}
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .Values.resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- if eq $providerName "webhook" }}
|
||||
{{- with .Values.provider.webhook }}
|
||||
- name: webhook
|
||||
image: {{ include "external-dns.webhookImage" . }}
|
||||
imagePullPolicy: {{ .image.pullPolicy }}
|
||||
{{- with .env }}
|
||||
env:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .args }}
|
||||
args:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- name: http-webhook
|
||||
protocol: TCP
|
||||
containerPort: 8080
|
||||
livenessProbe:
|
||||
{{- toYaml .livenessProbe | nindent 12 }}
|
||||
readinessProbe:
|
||||
{{- toYaml .readinessProbe | nindent 12 }}
|
||||
{{- if .extraVolumeMounts }}
|
||||
volumeMounts:
|
||||
{{- with .extraVolumeMounts }}
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .resources }}
|
||||
resources:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- with .securityContext }}
|
||||
securityContext:
|
||||
{{- toYaml . | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if or .Values.secretConfiguration.enabled .Values.extraVolumes }}
|
||||
volumes:
|
||||
{{- if .Values.secretConfiguration.enabled }}
|
||||
- name: secrets
|
||||
secret:
|
||||
secretName: {{ include "external-dns.fullname" . }}
|
||||
{{- end }}
|
||||
{{- with .Values.extraVolumes }}
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.affinity }}
|
||||
affinity:
|
||||
{{- with .nodeAffinity }}
|
||||
nodeAffinity:
|
||||
{{- toYaml . | nindent 10 }}
|
||||
{{- end }}
|
||||
{{- with .podAffinity }}
|
||||
podAffinity:
|
||||
{{- with .preferredDuringSchedulingIgnoredDuringExecution }}
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
{{- range . }}
|
||||
- podAffinityTerm:
|
||||
{{- if dig "podAffinityTerm" "labelSelector" nil . }}
|
||||
{{- toYaml .podAffinityTerm | nindent 16 }}
|
||||
{{- else }}
|
||||
{{- (merge $defaultSelector .podAffinityTerm) | toYaml | nindent 16 }}
|
||||
{{- end }}
|
||||
weight: {{ .weight }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .requiredDuringSchedulingIgnoredDuringExecution }}
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
{{- range . }}
|
||||
{{- if dig "labelSelector" nil . }}
|
||||
- {{ toYaml . | indent 16 | trim }}
|
||||
{{- else }}
|
||||
- {{ (merge $defaultSelector .) | toYaml | indent 16 | trim }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .podAntiAffinity }}
|
||||
podAntiAffinity:
|
||||
{{- with .preferredDuringSchedulingIgnoredDuringExecution }}
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
{{- range . }}
|
||||
- podAffinityTerm:
|
||||
{{- if dig "podAffinityTerm" "labelSelector" nil . }}
|
||||
{{- toYaml .podAffinityTerm | nindent 16 }}
|
||||
{{- else }}
|
||||
{{- (merge $defaultSelector .podAffinityTerm) | toYaml | nindent 16 }}
|
||||
{{- end }}
|
||||
weight: {{ .weight }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .requiredDuringSchedulingIgnoredDuringExecution }}
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
{{- range . }}
|
||||
{{- if dig "labelSelector" nil . }}
|
||||
- {{ toYaml . | indent 16 | trim }}
|
||||
{{- else }}
|
||||
- {{ (merge $defaultSelector .) | toYaml | indent 16 | trim }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .Values.topologySpreadConstraints }}
|
||||
topologySpreadConstraints:
|
||||
{{- range . }}
|
||||
- {{ toYaml . | nindent 10 | trim }}
|
||||
{{- if not (hasKey . "labelSelector") }}
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
{{- include "external-dns.selectorLabels" $ | nindent 12 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
13
v0.18.0/charts/external-dns/templates/secret.yaml
Normal file
13
v0.18.0/charts/external-dns/templates/secret.yaml
Normal file
@ -0,0 +1,13 @@
|
||||
{{- if .Values.secretConfiguration.enabled }}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ include "external-dns.fullname" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "external-dns.labels" . | nindent 4 }}
|
||||
data:
|
||||
{{- range $key, $value := .Values.secretConfiguration.data }}
|
||||
{{ $key }}: {{ tpl $value $ | b64enc | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
36
v0.18.0/charts/external-dns/templates/service.yaml
Normal file
36
v0.18.0/charts/external-dns/templates/service.yaml
Normal file
@ -0,0 +1,36 @@
|
||||
{{- $providerName := include "external-dns.providerName" . }}
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ include "external-dns.fullname" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "external-dns.labels" . | nindent 4 }}
|
||||
{{- with .Values.service.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- with .Values.service.ipFamilies }}
|
||||
ipFamilies:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- with .Values.service.ipFamilyPolicy }}
|
||||
ipFamilyPolicy: {{ . }}
|
||||
{{- end }}
|
||||
type: ClusterIP
|
||||
selector:
|
||||
{{- include "external-dns.selectorLabels" . | nindent 4 }}
|
||||
ports:
|
||||
- name: http
|
||||
port: {{ .Values.service.port }}
|
||||
targetPort: http
|
||||
protocol: TCP
|
||||
{{- if eq $providerName "webhook" }}
|
||||
{{- with .Values.provider.webhook.service }}
|
||||
- name: http-webhook
|
||||
port: {{ .port }}
|
||||
targetPort: http-webhook
|
||||
protocol: TCP
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
19
v0.18.0/charts/external-dns/templates/serviceaccount.yaml
Normal file
19
v0.18.0/charts/external-dns/templates/serviceaccount.yaml
Normal file
@ -0,0 +1,19 @@
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ include "external-dns.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
{{- include "external-dns.labels" . | nindent 4 }}
|
||||
{{- with .Values.serviceAccount.labels }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- with .Values.serviceAccount.annotations }}
|
||||
annotations:
|
||||
{{- range $k, $v := . }}
|
||||
{{- printf "%s: %s" (toYaml (tpl $k $)) (toYaml (tpl $v $)) | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
automountServiceAccountToken: {{ .Values.serviceAccount.automountServiceAccountToken }}
|
||||
{{- end }}
|
||||
86
v0.18.0/charts/external-dns/templates/servicemonitor.yaml
Normal file
86
v0.18.0/charts/external-dns/templates/servicemonitor.yaml
Normal file
@ -0,0 +1,86 @@
|
||||
{{- if .Values.serviceMonitor.enabled -}}
|
||||
{{- $providerName := include "external-dns.providerName" . }}
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
metadata:
|
||||
name: {{ include "external-dns.fullname" . }}
|
||||
namespace: {{ default .Release.Namespace .Values.serviceMonitor.namespace }}
|
||||
{{- with .Values.serviceMonitor.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
{{- include "external-dns.labels" . | nindent 4 }}
|
||||
{{- with .Values.serviceMonitor.additionalLabels }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
jobLabel: app.kubernetes.io/instance
|
||||
namespaceSelector:
|
||||
matchNames:
|
||||
- {{ .Release.Namespace }}
|
||||
selector:
|
||||
matchLabels:
|
||||
{{- include "external-dns.selectorLabels" . | nindent 6 }}
|
||||
endpoints:
|
||||
- port: http
|
||||
path: /metrics
|
||||
{{- with .Values.serviceMonitor.interval }}
|
||||
interval: {{ . }}
|
||||
{{- end }}
|
||||
{{- with .Values.serviceMonitor.scheme }}
|
||||
scheme: {{ . }}
|
||||
{{- end }}
|
||||
{{- with .Values.serviceMonitor.bearerTokenFile }}
|
||||
bearerTokenFile: {{ . }}
|
||||
{{- end }}
|
||||
{{- with .Values.serviceMonitor.tlsConfig }}
|
||||
tlsConfig:
|
||||
{{- toYaml .| nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.serviceMonitor.scrapeTimeout }}
|
||||
scrapeTimeout: {{ . }}
|
||||
{{- end }}
|
||||
{{- with .Values.serviceMonitor.metricRelabelings }}
|
||||
metricRelabelings:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.serviceMonitor.relabelings }}
|
||||
relabelings:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- if eq $providerName "webhook" }}
|
||||
{{- with .Values.provider.webhook.serviceMonitor }}
|
||||
- port: http-webhook
|
||||
path: /metrics
|
||||
{{- with .interval }}
|
||||
interval: {{ . }}
|
||||
{{- end }}
|
||||
{{- with .scheme }}
|
||||
scheme: {{ . }}
|
||||
{{- end }}
|
||||
{{- with .bearerTokenFile }}
|
||||
bearerTokenFile: {{ . }}
|
||||
{{- end }}
|
||||
{{- with .tlsConfig }}
|
||||
tlsConfig:
|
||||
{{- toYaml .| nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .scrapeTimeout }}
|
||||
scrapeTimeout: {{ . }}
|
||||
{{- end }}
|
||||
{{- with .metricRelabelings }}
|
||||
metricRelabelings:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- with .relabelings }}
|
||||
relabelings:
|
||||
{{- toYaml . | nindent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .Values.serviceMonitor.targetLabels }}
|
||||
targetLabels:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
29
v0.18.0/charts/external-dns/tests/common-metadata_test.yaml
Normal file
29
v0.18.0/charts/external-dns/tests/common-metadata_test.yaml
Normal file
@ -0,0 +1,29 @@
|
||||
suite: All resources contains metadata
|
||||
templates:
|
||||
- "*.yaml"
|
||||
release:
|
||||
name: external-dns
|
||||
chart:
|
||||
version: "1.15.0"
|
||||
appVersion: "0.15.0"
|
||||
tests:
|
||||
- it: "should contain labels metadata in each template"
|
||||
set:
|
||||
secretConfiguration:
|
||||
enabled: true
|
||||
mountPath: "/etc/kubernetes/"
|
||||
serviceMonitor:
|
||||
enabled: true
|
||||
asserts:
|
||||
- exists:
|
||||
path: metadata.labels
|
||||
- isNotEmpty:
|
||||
path: metadata.labels
|
||||
- equal:
|
||||
path: metadata.labels
|
||||
value:
|
||||
helm.sh/chart: external-dns-1.15.0
|
||||
app.kubernetes.io/name: external-dns
|
||||
app.kubernetes.io/instance: external-dns
|
||||
app.kubernetes.io/version: "0.15.0"
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
@ -0,0 +1,81 @@
|
||||
suite: Deployment configuration
|
||||
templates:
|
||||
- deployment.yaml
|
||||
release:
|
||||
namespace: default
|
||||
tests:
|
||||
- it: should provide expected defaults
|
||||
asserts:
|
||||
- isKind:
|
||||
of: Deployment
|
||||
- hasDocuments:
|
||||
count: 1
|
||||
- equal:
|
||||
path: spec.replicas
|
||||
value: 1
|
||||
- equal:
|
||||
path: spec.strategy.type
|
||||
value: Recreate
|
||||
- equal:
|
||||
path: metadata.namespace
|
||||
value: default
|
||||
- equal:
|
||||
path: spec.template.spec.automountServiceAccountToken
|
||||
value: true
|
||||
|
||||
- it: should provide expected defaults for securityContext
|
||||
asserts:
|
||||
- isSubset:
|
||||
path: spec.template.spec.containers[?(@.name == "external-dns")]
|
||||
content:
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
privileged: false
|
||||
readOnlyRootFilesystem: true
|
||||
runAsGroup: 65532
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65532
|
||||
|
||||
- it: should provide expected defaults for liveness and readiness
|
||||
asserts:
|
||||
- isSubset:
|
||||
path: spec.template.spec.containers[?(@.name == "external-dns")]
|
||||
content:
|
||||
readinessProbe:
|
||||
failureThreshold: 6
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 5
|
||||
livenessProbe:
|
||||
failureThreshold: 2
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
successThreshold: 1
|
||||
timeoutSeconds: 5
|
||||
|
||||
- it: should have service account set
|
||||
release:
|
||||
name: test
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.serviceAccountName
|
||||
value: test-external-dns
|
||||
|
||||
- it: should have not be able to change replicas when specified via values
|
||||
set:
|
||||
deployment:
|
||||
replicas: 3
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.replicas
|
||||
value: 1
|
||||
166
v0.18.0/charts/external-dns/tests/deployment-flags_test.yaml
Normal file
166
v0.18.0/charts/external-dns/tests/deployment-flags_test.yaml
Normal file
@ -0,0 +1,166 @@
|
||||
suite: Deployment flags configurations
|
||||
templates:
|
||||
- deployment.yaml
|
||||
release:
|
||||
namespace: default
|
||||
tests:
|
||||
- it: should provide expected default flags
|
||||
asserts:
|
||||
- exists :
|
||||
path: spec.template.spec.containers[?(@.name == "external-dns")]
|
||||
- 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
|
||||
|
||||
- it: should configure 'txtSuffix' when not empty with 'txtPrefix' empty
|
||||
set:
|
||||
txtPrefix: ""
|
||||
txtSuffix: "test-suffix"
|
||||
asserts:
|
||||
- exists :
|
||||
path: spec.template.spec.containers[?(@.name == "external-dns")]
|
||||
- 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
|
||||
- --txt-suffix=test-suffix
|
||||
- --provider=aws
|
||||
- notContains:
|
||||
path: spec.template.spec.containers[?(@.name == "external-dns")].args
|
||||
content: "--txt-prefix=test-prefix"
|
||||
- contains:
|
||||
path: spec.template.spec.containers[?(@.name == "external-dns")].args
|
||||
content: "--txt-suffix=test-suffix"
|
||||
|
||||
- it: should configure 'txtSuffix' when set and 'txtPrefix' is not present
|
||||
set:
|
||||
txtSuffix: "custom-suffix"
|
||||
asserts:
|
||||
- exists :
|
||||
path: spec.template.spec.containers[?(@.name == "external-dns")]
|
||||
- contains:
|
||||
path: spec.template.spec.containers[?(@.name == "external-dns")].args
|
||||
content: "--txt-suffix=custom-suffix"
|
||||
|
||||
- it: should be able configure multiple sources
|
||||
set:
|
||||
sources:
|
||||
- fake
|
||||
- crd
|
||||
asserts:
|
||||
- contains:
|
||||
path: spec.template.spec.containers[?(@.name == "external-dns")].args
|
||||
content: "--source=fake"
|
||||
- contains:
|
||||
path: spec.template.spec.containers[?(@.name == "external-dns")].args
|
||||
content: "--source=crd"
|
||||
|
||||
- it: should be able to configure in single namespace
|
||||
set:
|
||||
namespaced: true
|
||||
asserts:
|
||||
- contains:
|
||||
path: spec.template.spec.containers[?(@.name == "external-dns")].args
|
||||
content: "--namespace=default"
|
||||
|
||||
- it: should manage multiple zones with 'extraArgs'
|
||||
set:
|
||||
extraArgs:
|
||||
- --zone-id-filter=/hostedzone/Z00001
|
||||
- --zone-id-filter=/hostedzone/Z00002
|
||||
- --zone-id-filter=/hostedzone/Z00003
|
||||
- --zone-id-filter=/hostedzone/Z00004
|
||||
- --zone-id-filter=/hostedzone/Z00005
|
||||
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
|
||||
- --zone-id-filter=/hostedzone/Z00001
|
||||
- --zone-id-filter=/hostedzone/Z00002
|
||||
- --zone-id-filter=/hostedzone/Z00003
|
||||
- --zone-id-filter=/hostedzone/Z00004
|
||||
- --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
|
||||
set:
|
||||
txtPrefix: "test-prefix"
|
||||
txtSuffix: "test-suffix"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorMessage: "'txtPrefix' and 'txtSuffix' are mutually exclusive"
|
||||
@ -0,0 +1,118 @@
|
||||
suite: Deployment scheduling configuration
|
||||
templates:
|
||||
- deployment.yaml
|
||||
release:
|
||||
namespace: default
|
||||
tests:
|
||||
- it: should not provide defaults for affinities or tolerations
|
||||
asserts:
|
||||
- isKind:
|
||||
of: Deployment
|
||||
- notExists:
|
||||
path: spec.template.spec.tolerations
|
||||
- notExists:
|
||||
path: spec.template.spec.affinity
|
||||
|
||||
- it: should provide support for custom affinities
|
||||
set:
|
||||
affinity:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: topology.kubernetes.io/zone
|
||||
operator: In
|
||||
values:
|
||||
- zoneA
|
||||
- zoneB
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.affinity
|
||||
value:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: topology.kubernetes.io/zone
|
||||
operator: In
|
||||
values:
|
||||
- zoneA
|
||||
- zoneB
|
||||
|
||||
- it: should provide support for configuring node and pod affinities
|
||||
set:
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
- topologyKey: kubernetes.io/hostname
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- test-pod-scheduling-config
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: datadog-agent
|
||||
operator: In
|
||||
values:
|
||||
- standard
|
||||
- key: iam/scope
|
||||
operator: In
|
||||
values:
|
||||
- namespace
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.template.spec.affinity
|
||||
value:
|
||||
nodeAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: datadog-agent
|
||||
operator: In
|
||||
values:
|
||||
- standard
|
||||
- key: iam/scope
|
||||
operator: In
|
||||
values:
|
||||
- namespace
|
||||
podAntiAffinity:
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
- labelSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- test-pod-scheduling-config
|
||||
topologyKey: kubernetes.io/hostname
|
||||
|
||||
- it: should provide support for configuring tolerations
|
||||
set:
|
||||
tolerations:
|
||||
- key: "key1"
|
||||
operator: "Equal"
|
||||
value: "value1"
|
||||
effect: "NoSchedule"
|
||||
- key: iam/scope
|
||||
operator: Equal
|
||||
value: namespace
|
||||
effect: NoExecute
|
||||
asserts:
|
||||
- notExists:
|
||||
path: spec.template.spec.affinity
|
||||
- exists:
|
||||
path: spec.template.spec.tolerations
|
||||
- equal:
|
||||
path: spec.template.spec.tolerations
|
||||
value:
|
||||
- effect: NoSchedule
|
||||
key: key1
|
||||
operator: Equal
|
||||
value: value1
|
||||
- effect: NoExecute
|
||||
key: iam/scope
|
||||
operator: Equal
|
||||
value: namespace
|
||||
64
v0.18.0/charts/external-dns/tests/json-schema_test.yaml
Normal file
64
v0.18.0/charts/external-dns/tests/json-schema_test.yaml
Normal file
@ -0,0 +1,64 @@
|
||||
suite: Test json value schema validation
|
||||
templates:
|
||||
- templates/*
|
||||
release:
|
||||
name: notes
|
||||
namespace: apps-notes
|
||||
tests:
|
||||
- it: should not throw an error when legacy provider is a string
|
||||
set:
|
||||
provider: legacy
|
||||
asserts:
|
||||
- notFailedTemplate: {}
|
||||
|
||||
- it: should not throw an error when provider is an object
|
||||
set:
|
||||
provider:
|
||||
name: aws
|
||||
webhook: {}
|
||||
asserts:
|
||||
- notFailedTemplate: {}
|
||||
|
||||
- it: should not throw an error when 'enabled' value is provided
|
||||
set:
|
||||
enabled: true
|
||||
asserts:
|
||||
- notFailedTemplate: {}
|
||||
|
||||
- it: should throw an error when 'enabled' value is not a bool or nil
|
||||
set:
|
||||
enabled: "abrakadabra"
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorPattern: "Invalid type. Expected: [boolean,null], given: string"
|
||||
|
||||
- it: should fail if provider is null
|
||||
set:
|
||||
provider: null
|
||||
asserts:
|
||||
- failedTemplate:
|
||||
errorPattern: 'executing "external-dns.providerName" at <.Values.provider.name>: nil pointer evaluating interface {}.name'
|
||||
|
||||
- it: should not fail if provider block is empty
|
||||
set:
|
||||
provider: {}
|
||||
asserts:
|
||||
- notFailedTemplate: {}
|
||||
|
||||
- it: should not fail when labelFilter has condition
|
||||
set:
|
||||
labelFilter: "mydomain.io/enable-dns-record in (true)"
|
||||
asserts:
|
||||
- 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: {}
|
||||
@ -0,0 +1,26 @@
|
||||
suite: Test NOTES.txt deprecations
|
||||
templates:
|
||||
- templates/NOTES.txt
|
||||
release:
|
||||
name: notes
|
||||
namespace: apps-notes
|
||||
tests:
|
||||
- it: should output a deprecation message when legacy provider configuration is in use
|
||||
set:
|
||||
provider: legacy
|
||||
asserts:
|
||||
- matchRegexRaw:
|
||||
pattern: "🚧 DEPRECATIONS 🚧"
|
||||
- matchRegexRaw:
|
||||
pattern: |
|
||||
❗❗❗ DEPRECATED ❗❗❗\sThe legacy 'provider: <name>' configuration is in use. Support will be removed in future releases.
|
||||
|
||||
- it: should not output a deprecation message when supported provider configuration is in use
|
||||
set:
|
||||
provider:
|
||||
name: non-legacy-config
|
||||
asserts:
|
||||
- notMatchRegexRaw:
|
||||
pattern: "🚧 DEPRECATIONS 🚧"
|
||||
- notMatchRegexRaw:
|
||||
pattern: ❗❗❗ DEPRECATED ❗❗❗
|
||||
21
v0.18.0/charts/external-dns/tests/notes_test.yaml
Normal file
21
v0.18.0/charts/external-dns/tests/notes_test.yaml
Normal file
@ -0,0 +1,21 @@
|
||||
suite: NOTES.txt output
|
||||
templates:
|
||||
- NOTES.txt
|
||||
chart:
|
||||
appVersion: 0.15.0
|
||||
version: 1.15.0
|
||||
tests:
|
||||
- it: should display message
|
||||
set:
|
||||
rbac:
|
||||
namespaced: true
|
||||
asserts:
|
||||
- equalRaw:
|
||||
value: |
|
||||
***********************************************************************
|
||||
* External DNS *
|
||||
***********************************************************************
|
||||
Chart version: 1.15.0
|
||||
App version: 0.15.0
|
||||
Image tag: registry.k8s.io/external-dns/external-dns:v0.15.0
|
||||
***********************************************************************
|
||||
158
v0.18.0/charts/external-dns/tests/rbac_test.yaml
Normal file
158
v0.18.0/charts/external-dns/tests/rbac_test.yaml
Normal file
@ -0,0 +1,158 @@
|
||||
suite: RBAC configuration
|
||||
templates:
|
||||
- clusterrole.yaml
|
||||
- clusterrolebinding.yaml
|
||||
- serviceaccount.yaml
|
||||
release:
|
||||
name: rbac
|
||||
tests:
|
||||
- it: should create default RBAC related objects
|
||||
asserts:
|
||||
- isKind:
|
||||
of: ClusterRole
|
||||
template: clusterrole.yaml
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: rbac-external-dns
|
||||
template: clusterrole.yaml
|
||||
- isKind:
|
||||
of: ClusterRoleBinding
|
||||
template: clusterrolebinding.yaml
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: rbac-external-dns-viewer
|
||||
template: clusterrolebinding.yaml
|
||||
- isKind:
|
||||
of: ServiceAccount
|
||||
template: serviceaccount.yaml
|
||||
- equal:
|
||||
path: metadata.name
|
||||
value: rbac-external-dns
|
||||
template: serviceaccount.yaml
|
||||
|
||||
- it: should create default RBAC rules
|
||||
asserts:
|
||||
- template: clusterrole.yaml
|
||||
equal:
|
||||
path: rules
|
||||
value:
|
||||
- apiGroups: [""]
|
||||
resources: ["nodes"]
|
||||
verbs: ["list", "watch"]
|
||||
- apiGroups: [""]
|
||||
resources: ["pods"]
|
||||
verbs: ["get", "watch", "list"]
|
||||
- apiGroups: [""]
|
||||
resources: ["services"]
|
||||
verbs: ["get","watch","list"]
|
||||
- apiGroups: ["discovery.k8s.io"]
|
||||
resources: ["endpointslices"]
|
||||
verbs: ["get","watch","list"]
|
||||
- apiGroups: ["extensions","networking.k8s.io"]
|
||||
resources: ["ingresses"]
|
||||
verbs: ["get","watch","list"]
|
||||
|
||||
- it: should create default RBAC rules for 'ambassador-host'
|
||||
set:
|
||||
sources:
|
||||
- ambassador-host
|
||||
asserts:
|
||||
- template: clusterrole.yaml
|
||||
equal:
|
||||
path: rules
|
||||
value:
|
||||
- apiGroups: ["getambassador.io"]
|
||||
resources: ["hosts","ingresses"]
|
||||
verbs: ["get","watch","list"]
|
||||
|
||||
- it: should create default RBAC rules for 'crd' and 'traefik-proxy'
|
||||
set:
|
||||
sources:
|
||||
- crd
|
||||
- traefik-proxy
|
||||
asserts:
|
||||
- template: clusterrole.yaml
|
||||
equal:
|
||||
path: rules
|
||||
value:
|
||||
- apiGroups: ["externaldns.k8s.io"]
|
||||
resources: ["dnsendpoints"]
|
||||
verbs: ["get","watch","list"]
|
||||
- apiGroups: ["externaldns.k8s.io"]
|
||||
resources: ["dnsendpoints/status"]
|
||||
verbs: ["*"]
|
||||
- apiGroups: ["traefik.containo.us", "traefik.io"]
|
||||
resources: ["ingressroutes", "ingressroutetcps", "ingressrouteudps"]
|
||||
verbs: ["get","watch","list"]
|
||||
|
||||
- it: should create default RBAC rules for 'f5' when 'f5-virtualserver' is set
|
||||
set:
|
||||
sources:
|
||||
- f5-virtualserver
|
||||
asserts:
|
||||
- template: clusterrole.yaml
|
||||
equal:
|
||||
path: rules
|
||||
value:
|
||||
- apiGroups: ["cis.f5.com"]
|
||||
resources: ["virtualservers", "transportservers"]
|
||||
verbs: ["get","watch","list"]
|
||||
|
||||
- it: should create default RBAC rules for 'f5' when 'f5-transportserver' is set
|
||||
set:
|
||||
sources:
|
||||
- f5-transportserver
|
||||
asserts:
|
||||
- template: clusterrole.yaml
|
||||
equal:
|
||||
path: rules
|
||||
value:
|
||||
- apiGroups: ["cis.f5.com"]
|
||||
resources: ["virtualservers", "transportservers"]
|
||||
verbs: ["get","watch","list"]
|
||||
|
||||
- it: should create default RBAC rules for 'gateway-api' with source 'gateway-httproute'
|
||||
set:
|
||||
sources:
|
||||
- gateway-httproute
|
||||
asserts:
|
||||
- template: clusterrole.yaml
|
||||
equal:
|
||||
path: rules
|
||||
value:
|
||||
- apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["gateways"]
|
||||
verbs: ["get","watch","list"]
|
||||
- apiGroups: [""]
|
||||
resources: ["namespaces"]
|
||||
verbs: ["get","watch","list"]
|
||||
- apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["httproutes"]
|
||||
verbs: ["get","watch","list"]
|
||||
|
||||
- it: should create default RBAC rules for 'gateway-api' with sources 'tlsroute,tcproute,udproute'
|
||||
set:
|
||||
sources:
|
||||
- gateway-tlsroute
|
||||
- gateway-tcproute
|
||||
- gateway-udproute
|
||||
asserts:
|
||||
- template: clusterrole.yaml
|
||||
equal:
|
||||
path: rules
|
||||
value:
|
||||
- apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["gateways"]
|
||||
verbs: ["get","watch","list"]
|
||||
- apiGroups: [""]
|
||||
resources: ["namespaces"]
|
||||
verbs: ["get","watch","list"]
|
||||
- apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["tlsroutes"]
|
||||
verbs: ["get","watch","list"]
|
||||
- apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["tcproutes"]
|
||||
verbs: ["get","watch","list"]
|
||||
- apiGroups: ["gateway.networking.k8s.io"]
|
||||
resources: ["udproutes"]
|
||||
verbs: ["get","watch","list"]
|
||||
42
v0.18.0/charts/external-dns/tests/secret_test.yaml
Normal file
42
v0.18.0/charts/external-dns/tests/secret_test.yaml
Normal file
@ -0,0 +1,42 @@
|
||||
suite: Secret configuration
|
||||
templates:
|
||||
- "secret.yaml"
|
||||
- "deployment.yaml"
|
||||
tests:
|
||||
- it: should not provide secret by default
|
||||
template: "secret.yaml"
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
|
||||
- it: should configure Azure secret
|
||||
release:
|
||||
name: under-test
|
||||
set:
|
||||
secretConfiguration:
|
||||
enabled: true
|
||||
mountPath: "/etc/kubernetes/"
|
||||
data:
|
||||
azure.json: |
|
||||
{
|
||||
"tenantId": "00000000-0000-0000-0000-000000000000",
|
||||
"subscriptionId": "00000000-0000-0000-0000-000000000000",
|
||||
"resourceGroup": "networking",
|
||||
"useWorkloadIdentityExtension": true
|
||||
}
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 1
|
||||
- exists:
|
||||
path: data["azure.json"]
|
||||
template: "secret.yaml"
|
||||
- exists:
|
||||
path: spec.template.spec.volumes
|
||||
template: "deployment.yaml"
|
||||
- equal:
|
||||
path: spec.template.spec.volumes
|
||||
value:
|
||||
- name: secrets
|
||||
secret:
|
||||
secretName: under-test-external-dns
|
||||
template: "deployment.yaml"
|
||||
61
v0.18.0/charts/external-dns/tests/serviceaccount_test.yaml
Normal file
61
v0.18.0/charts/external-dns/tests/serviceaccount_test.yaml
Normal file
@ -0,0 +1,61 @@
|
||||
suite: ServiceAccount configuration
|
||||
templates:
|
||||
- serviceaccount.yaml
|
||||
release:
|
||||
namespace: default
|
||||
tests:
|
||||
- it: should provide a single service account by default
|
||||
asserts:
|
||||
- isKind:
|
||||
of: ServiceAccount
|
||||
- hasDocuments:
|
||||
count: 1
|
||||
- equal:
|
||||
path: automountServiceAccountToken
|
||||
value: true
|
||||
|
||||
- it: should provide a way to disable service account
|
||||
set:
|
||||
serviceAccount:
|
||||
create: false
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 0
|
||||
|
||||
- it: should support annotations without template variables
|
||||
set:
|
||||
serviceAccount:
|
||||
annotations:
|
||||
eks.amazonaws.com/role-arn: arn:aws:iam::123456789:role/external-dns-role
|
||||
eks.amazonaws.com/sts-regional-endpoints: "true"
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 1
|
||||
- equal:
|
||||
path: metadata.annotations
|
||||
value:
|
||||
eks.amazonaws.com/role-arn: arn:aws:iam::123456789:role/external-dns-role
|
||||
eks.amazonaws.com/sts-regional-endpoints: "true"
|
||||
|
||||
- it: should support annotations with template variables
|
||||
release:
|
||||
name: v1
|
||||
set:
|
||||
account: 9876-dynamic-account-id
|
||||
serviceAccount:
|
||||
annotations:
|
||||
eks.amazonaws.com/role-arn: arn:aws:iam::{{ .Values.account }}:role/external-dns-role
|
||||
eks.amazonaws.com/sts-regional-endpoints: "true"
|
||||
tags.k8s.io/service: service-{{ include "external-dns.fullname" . }}
|
||||
asserts:
|
||||
- hasDocuments:
|
||||
count: 1
|
||||
- equal:
|
||||
path: metadata.annotations
|
||||
value:
|
||||
eks.amazonaws.com/role-arn: arn:aws:iam::9876-dynamic-account-id:role/external-dns-role
|
||||
eks.amazonaws.com/sts-regional-endpoints: "true"
|
||||
tags.k8s.io/service: service-v1-external-dns
|
||||
- isType:
|
||||
path: metadata.annotations["eks.amazonaws.com/sts-regional-endpoints"]
|
||||
type: string
|
||||
863
v0.18.0/charts/external-dns/values.schema.json
Normal file
863
v0.18.0/charts/external-dns/values.schema.json
Normal file
@ -0,0 +1,863 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"affinity": {
|
||||
"description": "Affinity settings for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). If an explicit label selector is not provided for pod affinity or pod anti-affinity one will be created from the pod selector labels.",
|
||||
"type": "object"
|
||||
},
|
||||
"automountServiceAccountToken": {
|
||||
"description": "Set this to `false` to [opt out of API credential automounting](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#opt-out-of-api-credential-automounting) for the `Pod`.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"commonLabels": {
|
||||
"description": "Labels to add to all chart resources.",
|
||||
"type": "object"
|
||||
},
|
||||
"deploymentAnnotations": {
|
||||
"description": "Annotations to add to the `Deployment`.",
|
||||
"type": "object"
|
||||
},
|
||||
"deploymentStrategy": {
|
||||
"description": "[Deployment Strategy](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy).",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": [
|
||||
"string"
|
||||
],
|
||||
"enum": [
|
||||
"Recreate",
|
||||
"RollingUpdate"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"dnsConfig": {
|
||||
"description": "[DNS config](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config) for the pod, if not set the default will be used.",
|
||||
"type": [
|
||||
"object",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"dnsPolicy": {
|
||||
"description": "[DNS policy](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy) for the pod, if not set the default will be used.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"domainFilters": {
|
||||
"description": "Limit possible target zones by domain suffixes.",
|
||||
"type": "array"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "No effect - reserved for use in sub-charting",
|
||||
"type": [
|
||||
"boolean",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"env": {
|
||||
"description": "[Environment variables](https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/) for the `external-dns` container.",
|
||||
"type": "array"
|
||||
},
|
||||
"excludeDomains": {
|
||||
"description": "Intentionally exclude domains from being managed.",
|
||||
"type": "array"
|
||||
},
|
||||
"extraArgs": {
|
||||
"description": "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.",
|
||||
"type": [
|
||||
"array",
|
||||
"null",
|
||||
"object"
|
||||
],
|
||||
"uniqueItems": true,
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"extraContainers": {
|
||||
"description": "Extra containers to add to the `Deployment`.",
|
||||
"type": "object"
|
||||
},
|
||||
"extraVolumeMounts": {
|
||||
"description": "Extra [volume mounts](https://kubernetes.io/docs/concepts/storage/volumes/) for the `external-dns` container.",
|
||||
"type": "array"
|
||||
},
|
||||
"extraVolumes": {
|
||||
"description": "Extra [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) for the `Pod`.",
|
||||
"type": "array"
|
||||
},
|
||||
"fullnameOverride": {
|
||||
"description": "Override the full name of the chart.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"global": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"imagePullSecrets": {
|
||||
"description": "Global image pull secrets.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"image": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pullPolicy": {
|
||||
"description": "Image pull policy for the `external-dns` container.",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"IfNotPresent",
|
||||
"Always"
|
||||
]
|
||||
},
|
||||
"repository": {
|
||||
"description": "Image repository for the `external-dns` container.",
|
||||
"type": "string"
|
||||
},
|
||||
"tag": {
|
||||
"description": "Image tag for the `external-dns` container, this will default to `.Chart.AppVersion` if not set.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
"imagePullSecrets": {
|
||||
"description": "Image pull secrets.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object"
|
||||
}
|
||||
},
|
||||
"initContainers": {
|
||||
"description": "[Init containers](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/) to add to the `Pod` definition.",
|
||||
"type": "array"
|
||||
},
|
||||
"interval": {
|
||||
"description": "Interval for DNS updates.",
|
||||
"type": "string"
|
||||
},
|
||||
"labelFilter": {
|
||||
"description": "Filter resources queried for endpoints by label selector",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"livenessProbe": {
|
||||
"description": "[Liveness probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) configuration for the `external-dns` container.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"failureThreshold": {
|
||||
"type": "integer"
|
||||
},
|
||||
"httpGet": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"port": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"initialDelaySeconds": {
|
||||
"type": "integer"
|
||||
},
|
||||
"periodSeconds": {
|
||||
"type": "integer"
|
||||
},
|
||||
"successThreshold": {
|
||||
"type": "integer"
|
||||
},
|
||||
"timeoutSeconds": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"logFormat": {
|
||||
"description": "Log format.",
|
||||
"default": "text",
|
||||
"type": [
|
||||
"string"
|
||||
],
|
||||
"enum": [
|
||||
"text",
|
||||
"json"
|
||||
]
|
||||
},
|
||||
"logLevel": {
|
||||
"description": "Log level.",
|
||||
"default": "info",
|
||||
"type": [
|
||||
"string"
|
||||
],
|
||||
"enum": [
|
||||
"panic",
|
||||
"debug",
|
||||
"info",
|
||||
"warning",
|
||||
"error",
|
||||
"fatal"
|
||||
]
|
||||
},
|
||||
"managedRecordTypes": {
|
||||
"description": "Record types to manage (default: A, AAAA, CNAME)",
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"uniqueItems": true,
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"nameOverride": {
|
||||
"description": "Override the name of the chart.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"namespaced": {
|
||||
"description": "if `true`, _ExternalDNS_ will run in a namespaced scope (`Role`` and `Rolebinding`` will be namespaced too).",
|
||||
"type": "boolean"
|
||||
},
|
||||
"nodeSelector": {
|
||||
"description": "Node labels to match for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/).",
|
||||
"type": "object"
|
||||
},
|
||||
"podAnnotations": {
|
||||
"description": "Annotations to add to the `Pod`.",
|
||||
"type": "object"
|
||||
},
|
||||
"podLabels": {
|
||||
"description": "Labels to add to the `Pod`.",
|
||||
"type": "object"
|
||||
},
|
||||
"podSecurityContext": {
|
||||
"description": "[Pod security context](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#podsecuritycontext-v1-core), this supports full customisation.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"fsGroup": {
|
||||
"type": "integer"
|
||||
},
|
||||
"runAsNonRoot": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"seccompProfile": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"policy": {
|
||||
"description": "How DNS records are synchronized between sources and providers; available values are `sync` \u0026 `upsert-only`.",
|
||||
"default": "upsert-only",
|
||||
"type": [
|
||||
"string"
|
||||
],
|
||||
"enum": [
|
||||
"sync",
|
||||
"upsert-only"
|
||||
]
|
||||
},
|
||||
"priorityClassName": {
|
||||
"description": "Priority class name for the `Pod`.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"provider": {
|
||||
"type": [
|
||||
"object",
|
||||
"string"
|
||||
],
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "_ExternalDNS_ provider name; for the available providers and how to configure them see [README](https://github.com/kubernetes-sigs/external-dns/blob/master/charts/external-dns/README.md#providers).",
|
||||
"type": "string"
|
||||
},
|
||||
"webhook": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"args": {
|
||||
"description": "Extra arguments to provide for the `webhook` container.",
|
||||
"type": "array"
|
||||
},
|
||||
"env": {
|
||||
"description": "[Environment variables](https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/) for the `webhook` container.",
|
||||
"type": "array"
|
||||
},
|
||||
"extraVolumeMounts": {
|
||||
"description": "Extra [volume mounts](https://kubernetes.io/docs/concepts/storage/volumes/) for the `webhook` container.",
|
||||
"type": "array"
|
||||
},
|
||||
"image": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"pullPolicy": {
|
||||
"description": "Image pull policy for the `webhook` container.",
|
||||
"type": "string"
|
||||
},
|
||||
"repository": {
|
||||
"description": "Image repository for the `webhook` container.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"tag": {
|
||||
"description": "Image tag for the `webhook` container.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"limits": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"type": "string"
|
||||
},
|
||||
"memory": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"livenessProbe": {
|
||||
"description": "[Liveness probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) configuration for the `external-dns` container.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"failureThreshold": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"httpGet": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"port": {
|
||||
"type": [
|
||||
"integer",
|
||||
"string"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"initialDelaySeconds": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"periodSeconds": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"successThreshold": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"timeoutSeconds": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"readinessProbe": {
|
||||
"description": "[Readiness probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) configuration for the `webhook` container.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"failureThreshold": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"httpGet": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"port": {
|
||||
"type": [
|
||||
"integer",
|
||||
"string"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"initialDelaySeconds": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"periodSeconds": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"successThreshold": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"timeoutSeconds": {
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"requests": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"type": "string"
|
||||
},
|
||||
"memory": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"resources": {
|
||||
"description": "[Resources](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) for the `webhook` container.",
|
||||
"type": "object"
|
||||
},
|
||||
"securityContext": {
|
||||
"description": "[Pod security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) for the `webhook` container.",
|
||||
"type": "object"
|
||||
},
|
||||
"service": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"port": {
|
||||
"description": "Webhook exposed HTTP port for the service.",
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"serviceMonitor": {
|
||||
"description": "Optional [Service Monitor](https://prometheus-operator.dev/docs/operator/design/#servicemonitor) configuration for the `webhook` container.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"bearerTokenFile": {
|
||||
"type": "null"
|
||||
},
|
||||
"interval": {
|
||||
"type": "null"
|
||||
},
|
||||
"metricRelabelings": {
|
||||
"type": "array"
|
||||
},
|
||||
"relabelings": {
|
||||
"type": "array"
|
||||
},
|
||||
"scheme": {
|
||||
"type": "null"
|
||||
},
|
||||
"scrapeTimeout": {
|
||||
"type": "null"
|
||||
},
|
||||
"tlsConfig": {
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"rbac": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"additionalPermissions": {
|
||||
"description": "Additional rules to add to the `ClusterRole`.",
|
||||
"type": "array"
|
||||
},
|
||||
"create": {
|
||||
"description": "If `true`, create a `ClusterRole` \u0026 `ClusterRoleBinding` with access to the Kubernetes API.",
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
},
|
||||
"readinessProbe": {
|
||||
"description": "[Readiness probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) configuration for the `external-dns` container.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"failureThreshold": {
|
||||
"type": "integer"
|
||||
},
|
||||
"httpGet": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"path": {
|
||||
"type": "string"
|
||||
},
|
||||
"port": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"initialDelaySeconds": {
|
||||
"type": "integer"
|
||||
},
|
||||
"periodSeconds": {
|
||||
"type": "integer"
|
||||
},
|
||||
"successThreshold": {
|
||||
"type": "integer"
|
||||
},
|
||||
"timeoutSeconds": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"registry": {
|
||||
"description": "Specify the registry for storing ownership and labels. Valid values are `txt`, `aws-sd`, `dynamodb` \u0026 `noop`.",
|
||||
"default": "txt",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"txt",
|
||||
"aws-sd",
|
||||
"dynamodb",
|
||||
"noop"
|
||||
]
|
||||
},
|
||||
"resources": {
|
||||
"description": "[Resources](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) for the `external-dns` container.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"limits": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"type": "string"
|
||||
},
|
||||
"memory": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"requests": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"type": "string"
|
||||
},
|
||||
"memory": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"revisionHistoryLimit": {
|
||||
"description": "Specify the number of old `ReplicaSets` to retain to allow rollback of the `Deployment``.",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
],
|
||||
"minimum": 0
|
||||
},
|
||||
"secretConfiguration": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"data": {
|
||||
"description": "`Secret` data.",
|
||||
"type": "object"
|
||||
},
|
||||
"enabled": {
|
||||
"description": "If `true`, create a `Secret` to store sensitive provider configuration (**DEPRECATED**).",
|
||||
"type": "boolean"
|
||||
},
|
||||
"mountPath": {
|
||||
"description": "Mount path for the `Secret`, this can be templated.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"subPath": {
|
||||
"description": "Sub-path for mounting the `Secret`, this can be templated.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"securityContext": {
|
||||
"description": "[Security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) for the `external-dns` container.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"allowPrivilegeEscalation": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"capabilities": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"drop": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"privileged": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"readOnlyRootFilesystem": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"runAsGroup": {
|
||||
"type": "integer"
|
||||
},
|
||||
"runAsNonRoot": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"runAsUser": {
|
||||
"type": "integer"
|
||||
}
|
||||
}
|
||||
},
|
||||
"service": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"description": "Service annotations.",
|
||||
"type": "object"
|
||||
},
|
||||
"ipFamilies": {
|
||||
"description": "Service IP families (e.g. IPv4 and/or IPv6).",
|
||||
"type": [
|
||||
"array",
|
||||
"null"
|
||||
],
|
||||
"maxItems": 2,
|
||||
"minItems": 0,
|
||||
"uniqueItems": true,
|
||||
"items": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"IPv4",
|
||||
"IPv6"
|
||||
]
|
||||
}
|
||||
},
|
||||
"ipFamilyPolicy": {
|
||||
"description": "Service IP family policy.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
],
|
||||
"enum": [
|
||||
"SingleStack",
|
||||
"PreferDualStack",
|
||||
"RequireDualStack",
|
||||
null
|
||||
]
|
||||
},
|
||||
"port": {
|
||||
"description": "Service HTTP port.",
|
||||
"default": 7979,
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"serviceAccount": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"annotations": {
|
||||
"description": "Annotations to add to the service account. Templates are allowed in both the key and the value. Example: `example.com/annotation/{{ .Values.nameOverride }}: {{ .Values.nameOverride }}`",
|
||||
"type": "object"
|
||||
},
|
||||
"automountServiceAccountToken": {
|
||||
"description": "Set this to `false` to [opt out of API credential automounting](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#opt-out-of-api-credential-automounting) for the `ServiceAccount`.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"create": {
|
||||
"description": "If `true`, create a new `ServiceAccount`.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"labels": {
|
||||
"description": "Labels to add to the service account.",
|
||||
"type": "object"
|
||||
},
|
||||
"name": {
|
||||
"description": "If this is set and `serviceAccount.create` is `true` this will be used for the created `ServiceAccount` name, if set and `serviceAccount.create` is `false` then this will define an existing `ServiceAccount` to use.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"serviceMonitor": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"additionalLabels": {
|
||||
"description": "Additional labels for the `ServiceMonitor`.",
|
||||
"type": "object"
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Annotations to add to the `ServiceMonitor`.",
|
||||
"type": "object"
|
||||
},
|
||||
"bearerTokenFile": {
|
||||
"description": "Provide a bearer token file for the `ServiceMonitor`.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"enabled": {
|
||||
"description": "If `true`, create a `ServiceMonitor` resource to support the _Prometheus Operator_.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"interval": {
|
||||
"description": "If set override the _Prometheus_ default interval.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"metricRelabelings": {
|
||||
"description": "[Metric relabel configs](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs) to apply to samples before ingestion.",
|
||||
"type": "array"
|
||||
},
|
||||
"namespace": {
|
||||
"description": "If set create the `ServiceMonitor` in an alternate namespace.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"relabelings": {
|
||||
"description": "[Relabel configs](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config) to apply to samples before ingestion.",
|
||||
"type": "array"
|
||||
},
|
||||
"scheme": {
|
||||
"description": "If set overrides the _Prometheus_ default scheme.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"scrapeTimeout": {
|
||||
"description": "If set override the _Prometheus_ default scrape timeout.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"targetLabels": {
|
||||
"description": "Provide target labels for the `ServiceMonitor`.",
|
||||
"type": "array"
|
||||
},
|
||||
"tlsConfig": {
|
||||
"description": "Configure the `ServiceMonitor` [TLS config](https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#tlsconfig).",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"shareProcessNamespace": {
|
||||
"description": "If `true`, the `Pod` will have [process namespace sharing](https://kubernetes.io/docs/tasks/configure-pod-container/share-process-namespace/) enabled.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"sources": {
|
||||
"description": "_Kubernetes_ resources to monitor for DNS entries.",
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"terminationGracePeriodSeconds": {
|
||||
"description": "Termination grace period for the `Pod` in seconds.",
|
||||
"type": [
|
||||
"integer",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"tolerations": {
|
||||
"description": "Node taints which will be tolerated for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/).",
|
||||
"type": "array"
|
||||
},
|
||||
"topologySpreadConstraints": {
|
||||
"description": "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.",
|
||||
"type": "array"
|
||||
},
|
||||
"triggerLoopOnEvent": {
|
||||
"description": "If `true`, triggers run loop on create/update/delete events in addition of regular interval.",
|
||||
"type": "boolean"
|
||||
},
|
||||
"txtOwnerId": {
|
||||
"description": "Specify an identifier for this instance of _ExternalDNS_ when using a registry other than `noop`.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"txtPrefix": {
|
||||
"description": "Specify a prefix for the domain names of TXT records created for the `txt` registry. Mutually exclusive with `txtSuffix`.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
},
|
||||
"txtSuffix": {
|
||||
"description": "Specify a suffix for the domain names of TXT records created for the `txt` registry. Mutually exclusive with `txtPrefix`.",
|
||||
"type": [
|
||||
"string",
|
||||
"null"
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": true
|
||||
}
|
||||
313
v0.18.0/charts/external-dns/values.yaml
Normal file
313
v0.18.0/charts/external-dns/values.yaml
Normal file
@ -0,0 +1,313 @@
|
||||
# Default values for external-dns.
|
||||
# This is a YAML-formatted file.
|
||||
# Declare variables to be passed into your templates.
|
||||
|
||||
global:
|
||||
# -- Global image pull secrets.
|
||||
imagePullSecrets: [] # @schema item: object
|
||||
|
||||
image: # @schema additionalProperties: false
|
||||
# -- Image repository for the `external-dns` container.
|
||||
repository: registry.k8s.io/external-dns/external-dns
|
||||
# -- Image tag for the `external-dns` container, this will default to `.Chart.AppVersion` if not set.
|
||||
tag: # @schema type:[string, null]
|
||||
# -- Image pull policy for the `external-dns` container.
|
||||
pullPolicy: IfNotPresent # @schema enum:[IfNotPresent, Always];
|
||||
|
||||
# -- Image pull secrets.
|
||||
imagePullSecrets: [] # @schema item: object
|
||||
|
||||
# -- (string) Override the name of the chart.
|
||||
nameOverride: # @schema type:[string, null]; default: null
|
||||
|
||||
# -- (string) Override the full name of the chart.
|
||||
fullnameOverride: # @schema type:[string, null]; default: null
|
||||
|
||||
# -- Labels to add to all chart resources.
|
||||
commonLabels: {}
|
||||
|
||||
serviceAccount:
|
||||
# -- If `true`, create a new `ServiceAccount`.
|
||||
create: true
|
||||
# -- Labels to add to the service account.
|
||||
labels: {}
|
||||
# -- Annotations to add to the service account. Templates are allowed in both the key and the value. Example: `example.com/annotation/{{ .Values.nameOverride }}: {{ .Values.nameOverride }}`
|
||||
annotations: {}
|
||||
# -- (string) If this is set and `serviceAccount.create` is `true` this will be used for the created `ServiceAccount` name, if set and `serviceAccount.create` is `false` then this will define an existing `ServiceAccount` to use.
|
||||
name: # @schema type:[string, null]; default: null
|
||||
# -- Set this to `false` to [opt out of API credential automounting](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#opt-out-of-api-credential-automounting) for the `ServiceAccount`.
|
||||
automountServiceAccountToken: true
|
||||
|
||||
service:
|
||||
# -- Service annotations.
|
||||
annotations: {}
|
||||
# -- Service HTTP port.
|
||||
port: 7979 # @schema minimum:0; default:7979
|
||||
# -- Service IP families (e.g. IPv4 and/or IPv6).
|
||||
ipFamilies: [] # @schema type: [array, null]; item: string; itemEnum: ["IPv4", "IPv6"]; minItems:0; maxItems:2; uniqueItems: true;
|
||||
# - IPv4
|
||||
# - IPv6
|
||||
# -- Service IP family policy.
|
||||
ipFamilyPolicy: # @schema type: [string, null]; enum:[SingleStack, PreferDualStack, RequireDualStack, null];
|
||||
|
||||
rbac: # @schema additionalProperties: true
|
||||
# -- If `true`, create a `ClusterRole` & `ClusterRoleBinding` with access to the Kubernetes API.
|
||||
create: true
|
||||
# -- Additional rules to add to the `ClusterRole`.
|
||||
additionalPermissions: []
|
||||
|
||||
# -- Annotations to add to the `Deployment`.
|
||||
deploymentAnnotations: {}
|
||||
|
||||
# -- Extra containers to add to the `Deployment`.
|
||||
extraContainers: {}
|
||||
|
||||
# -- [Deployment Strategy](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy).
|
||||
deploymentStrategy: # @schema additionalProperties: true
|
||||
type: Recreate # @schema enum:[Recreate, RollingUpdate]; type:string; default: Recreate
|
||||
|
||||
# -- (int) Specify the number of old `ReplicaSets` to retain to allow rollback of the `Deployment``.
|
||||
revisionHistoryLimit: # @schema type:[integer, null];minimum:0
|
||||
|
||||
# -- Labels to add to the `Pod`.
|
||||
podLabels: {}
|
||||
|
||||
# -- Annotations to add to the `Pod`.
|
||||
podAnnotations: {}
|
||||
|
||||
# -- (bool) Set this to `false` to [opt out of API credential automounting](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#opt-out-of-api-credential-automounting) for the `Pod`.
|
||||
automountServiceAccountToken: true
|
||||
|
||||
# -- If `true`, the `Pod` will have [process namespace sharing](https://kubernetes.io/docs/tasks/configure-pod-container/share-process-namespace/) enabled.
|
||||
shareProcessNamespace: false
|
||||
|
||||
# -- [Pod security context](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#podsecuritycontext-v1-core), this supports full customisation.
|
||||
# @default -- See _values.yaml_
|
||||
podSecurityContext:
|
||||
runAsNonRoot: true
|
||||
fsGroup: 65534
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
|
||||
# -- (string) Priority class name for the `Pod`.
|
||||
priorityClassName: # @schema type:[string, null]; default: null
|
||||
|
||||
# -- (int) Termination grace period for the `Pod` in seconds.
|
||||
terminationGracePeriodSeconds: # @schema type:[integer, null]
|
||||
|
||||
# -- (string) [DNS policy](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-s-dns-policy) for the pod, if not set the default will be used.
|
||||
dnsPolicy: # @schema type:[string, null]; default: null
|
||||
|
||||
# -- (object) [DNS config](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#pod-dns-config) for the pod, if not set the default will be used.
|
||||
dnsConfig: # @schema type:[object, null]; default: null
|
||||
|
||||
# -- [Init containers](https://kubernetes.io/docs/concepts/workloads/pods/init-containers/) to add to the `Pod` definition.
|
||||
initContainers: []
|
||||
|
||||
# -- [Security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) for the `external-dns` container.
|
||||
# @default -- See _values.yaml_
|
||||
securityContext:
|
||||
privileged: false
|
||||
allowPrivilegeEscalation: false
|
||||
readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
runAsUser: 65532
|
||||
runAsGroup: 65532
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
|
||||
# -- [Environment variables](https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/) for the `external-dns` container.
|
||||
env: []
|
||||
|
||||
# -- [Liveness probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) configuration for the `external-dns` container.
|
||||
# @default -- See _values.yaml_
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 2
|
||||
successThreshold: 1
|
||||
|
||||
# -- [Readiness probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) configuration for the `external-dns` container.
|
||||
# @default -- See _values.yaml_
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 6
|
||||
successThreshold: 1
|
||||
|
||||
# -- Extra [volumes](https://kubernetes.io/docs/concepts/storage/volumes/) for the `Pod`.
|
||||
extraVolumes: []
|
||||
|
||||
# -- Extra [volume mounts](https://kubernetes.io/docs/concepts/storage/volumes/) for the `external-dns` container.
|
||||
extraVolumeMounts: []
|
||||
|
||||
# -- [Resources](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) for the `external-dns` container.
|
||||
resources: {}
|
||||
|
||||
# -- Node labels to match for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/).
|
||||
nodeSelector: {}
|
||||
|
||||
# -- Affinity settings for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/). If an explicit label selector is not provided for pod affinity or pod anti-affinity one will be created from the pod selector labels.
|
||||
affinity: {}
|
||||
|
||||
# -- 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: []
|
||||
|
||||
# -- Node taints which will be tolerated for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/).
|
||||
tolerations: []
|
||||
|
||||
serviceMonitor:
|
||||
# -- If `true`, create a `ServiceMonitor` resource to support the _Prometheus Operator_.
|
||||
enabled: false
|
||||
# -- Additional labels for the `ServiceMonitor`.
|
||||
additionalLabels: {}
|
||||
# -- Annotations to add to the `ServiceMonitor`.
|
||||
annotations: {}
|
||||
# -- (string) If set create the `ServiceMonitor` in an alternate namespace.
|
||||
namespace: # @schema type:[string, null]; default: null
|
||||
# -- (string) If set override the _Prometheus_ default interval.
|
||||
interval: # @schema type:[string, null]; default: null
|
||||
# -- (string) If set override the _Prometheus_ default scrape timeout.
|
||||
scrapeTimeout: # @schema type:[string, null]; default: null
|
||||
# -- (string) If set overrides the _Prometheus_ default scheme.
|
||||
scheme: # @schema type:[string, null]; default: null
|
||||
# -- Configure the `ServiceMonitor` [TLS config](https://github.com/coreos/prometheus-operator/blob/master/Documentation/api.md#tlsconfig).
|
||||
tlsConfig: {}
|
||||
# -- (string) Provide a bearer token file for the `ServiceMonitor`.
|
||||
bearerTokenFile: # @schema type:[string, null]; default: null
|
||||
# -- [Relabel configs](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#relabel_config) to apply to samples before ingestion.
|
||||
relabelings: []
|
||||
# -- [Metric relabel configs](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#metric_relabel_configs) to apply to samples before ingestion.
|
||||
metricRelabelings: []
|
||||
# -- Provide target labels for the `ServiceMonitor`.
|
||||
targetLabels: []
|
||||
|
||||
# -- Log level.
|
||||
logLevel: info # @schema enum:[panic, debug, info, warning, error, fatal]; type:string; default: "info"
|
||||
|
||||
# -- Log format.
|
||||
logFormat: text # @schema enum:["text", "json"]; type:string; default: "text"
|
||||
|
||||
# -- Interval for DNS updates.
|
||||
interval: 1m
|
||||
|
||||
# -- If `true`, triggers run loop on create/update/delete events in addition of regular interval.
|
||||
triggerLoopOnEvent: false
|
||||
|
||||
# -- if `true`, _ExternalDNS_ will run in a namespaced scope (`Role`` and `Rolebinding`` will be namespaced too).
|
||||
namespaced: false
|
||||
|
||||
# -- _Kubernetes_ resources to monitor for DNS entries.
|
||||
sources:
|
||||
- service
|
||||
- ingress
|
||||
|
||||
# -- How DNS records are synchronized between sources and providers; available values are `sync` & `upsert-only`.
|
||||
policy: upsert-only # @schema enum:[sync, upsert-only]; type:string; default: "upsert-only"
|
||||
|
||||
# -- Specify the registry for storing ownership and labels.
|
||||
# Valid values are `txt`, `aws-sd`, `dynamodb` & `noop`.
|
||||
registry: txt # @schema enum:[txt, aws-sd, dynamodb, noop]; default: "txt"
|
||||
# -- (string) Specify an identifier for this instance of _ExternalDNS_ when using a registry other than `noop`.
|
||||
txtOwnerId: # @schema type:[string, null]; default: null
|
||||
# -- (string) Specify a prefix for the domain names of TXT records created for the `txt` registry.
|
||||
# Mutually exclusive with `txtSuffix`.
|
||||
txtPrefix: # @schema type:[string, null]; default: null
|
||||
# -- (string) Specify a suffix for the domain names of TXT records created for the `txt` registry.
|
||||
# Mutually exclusive with `txtPrefix`.
|
||||
txtSuffix: # @schema type:[string, null]; default: null
|
||||
|
||||
# -- Limit possible target zones by domain suffixes.
|
||||
domainFilters: []
|
||||
|
||||
# -- Intentionally exclude domains from being managed.
|
||||
excludeDomains: []
|
||||
|
||||
# -- Filter resources queried for endpoints by label selector
|
||||
labelFilter: # @schema type: [string,null]; default: null
|
||||
|
||||
# -- Record types to manage (default: A, AAAA, CNAME)
|
||||
managedRecordTypes: [] # @schema type: [array, null]; item: string; uniqueItems: true;
|
||||
|
||||
provider: # @schema type: [object, string];
|
||||
# -- _ExternalDNS_ provider name; for the available providers and how to configure them see [README](https://github.com/kubernetes-sigs/external-dns/blob/master/charts/external-dns/README.md#providers).
|
||||
name: aws
|
||||
webhook:
|
||||
image:
|
||||
# -- (string) Image repository for the `webhook` container.
|
||||
repository: # @schema type:[string, null]; default: null
|
||||
# -- (string) Image tag for the `webhook` container.
|
||||
tag: # @schema type:[string, null]; default: null
|
||||
# -- Image pull policy for the `webhook` container.
|
||||
pullPolicy: IfNotPresent
|
||||
# -- [Environment variables](https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/) for the `webhook` container.
|
||||
env: []
|
||||
# -- Extra arguments to provide for the `webhook` container.
|
||||
args: []
|
||||
# -- Extra [volume mounts](https://kubernetes.io/docs/concepts/storage/volumes/) for the `webhook` container.
|
||||
extraVolumeMounts: []
|
||||
# -- [Resources](https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/) for the `webhook` container.
|
||||
resources: {}
|
||||
# -- [Pod security context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/#set-the-security-context-for-a-container) for the `webhook` container.
|
||||
# @default -- See _values.yaml_
|
||||
securityContext: {}
|
||||
# -- [Liveness probe](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) configuration for the `external-dns` container.
|
||||
# @default -- See _values.yaml_
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz # @schema type:[string, null]; default: null
|
||||
port: http-webhook # @schema type:[integer,string]; default: string
|
||||
initialDelaySeconds: 10 # @schema type:[integer, null]; default: null
|
||||
periodSeconds: 10 # @schema type:[integer, null]; default: null
|
||||
timeoutSeconds: 5 # @schema type:[integer, null]; default: null
|
||||
failureThreshold: 2 # @schema type:[integer, null]; default: null
|
||||
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.
|
||||
# @default -- See _values.yaml_
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz # @schema type:[string, null]; default: null
|
||||
port: http-webhook # @schema type:[integer,string]; default: string
|
||||
initialDelaySeconds: 5 # @schema type:[integer, null]; default: null
|
||||
periodSeconds: 10 # @schema type:[integer, null]; default: null
|
||||
timeoutSeconds: 5 # @schema type:[integer, null]; default: null
|
||||
failureThreshold: 6 # @schema type:[integer, null]; default: null
|
||||
successThreshold: 1 # @schema type:[integer, null]; default: null
|
||||
service:
|
||||
# -- Webhook exposed HTTP port for the service.
|
||||
port: 8080
|
||||
# -- Optional [Service Monitor](https://prometheus-operator.dev/docs/operator/design/#servicemonitor) configuration for the `webhook` container.
|
||||
# @default -- See _values.yaml_
|
||||
serviceMonitor:
|
||||
interval:
|
||||
scheme:
|
||||
tlsConfig: {}
|
||||
bearerTokenFile:
|
||||
scrapeTimeout:
|
||||
metricRelabelings: []
|
||||
relabelings: []
|
||||
|
||||
# -- 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.
|
||||
extraArgs: {} # @schema type: [array, null, object]; item: string; uniqueItems: true;
|
||||
|
||||
secretConfiguration:
|
||||
# -- If `true`, create a `Secret` to store sensitive provider configuration (**DEPRECATED**).
|
||||
enabled: false
|
||||
# -- Mount path for the `Secret`, this can be templated.
|
||||
mountPath: # @schema type:[string, null]; default: null
|
||||
# -- Sub-path for mounting the `Secret`, this can be templated.
|
||||
subPath: # @schema type:[string, null]; default: null
|
||||
# -- `Secret` data.
|
||||
data: {}
|
||||
|
||||
# -- (bool) No effect - reserved for use in sub-charting.
|
||||
enabled: # @schema type: [boolean, null]; description: No effect - reserved for use in sub-charting
|
||||
3036
v0.18.0/code-of-conduct/index.html
Normal file
3036
v0.18.0/code-of-conduct/index.html
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,97 @@
|
||||
apiVersion: apiextensions.k8s.io/v1
|
||||
kind: CustomResourceDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
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:
|
||||
group: externaldns.k8s.io
|
||||
names:
|
||||
kind: DNSEndpoint
|
||||
listKind: DNSEndpointList
|
||||
plural: dnsendpoints
|
||||
singular: dnsendpoint
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: |-
|
||||
DNSEndpoint is a contract that a user-specified CRD must implement to be used as a source for external-dns.
|
||||
The user-specified CRD should also have the status sub-resource.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: |-
|
||||
APIVersion defines the versioned schema of this representation of an object.
|
||||
Servers should convert recognized schemas to the latest internal value, and
|
||||
may reject unrecognized values.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
|
||||
type: string
|
||||
kind:
|
||||
description: |-
|
||||
Kind is a string value representing the REST resource this object represents.
|
||||
Servers may infer this from the endpoint the client submits requests to.
|
||||
Cannot be updated.
|
||||
In CamelCase.
|
||||
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
type: string
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: DNSEndpointSpec defines the desired state of DNSEndpoint
|
||||
properties:
|
||||
endpoints:
|
||||
items:
|
||||
description: Endpoint is a high-level way of a connection between a service and an IP
|
||||
properties:
|
||||
dnsName:
|
||||
description: The hostname of the DNS record
|
||||
type: string
|
||||
labels:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: Labels stores labels defined for the Endpoint
|
||||
type: object
|
||||
providerSpecific:
|
||||
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: array
|
||||
recordTTL:
|
||||
description: TTL for the record
|
||||
format: int64
|
||||
type: integer
|
||||
recordType:
|
||||
description: RecordType type of record, e.g. CNAME, A, AAAA, SRV, TXT etc
|
||||
type: string
|
||||
setIdentifier:
|
||||
description: Identifier to distinguish multiple records with the same name and type (e.g. Route53 records with routing policies other than 'simple')
|
||||
type: string
|
||||
targets:
|
||||
description: The targets the DNS record points to
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
type: array
|
||||
type: object
|
||||
status:
|
||||
description: DNSEndpointStatus defines the observed state of DNSEndpoint
|
||||
properties:
|
||||
observedGeneration:
|
||||
description: The generation observed by the external-dns controller.
|
||||
format: int64
|
||||
type: integer
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
storage: true
|
||||
subresources:
|
||||
status: {}
|
||||
377
v0.18.0/controller/controller.go
Normal file
377
v0.18.0/controller/controller.go
Normal file
@ -0,0 +1,377 @@
|
||||
/*
|
||||
Copyright 2017 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 controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"sigs.k8s.io/external-dns/endpoint"
|
||||
"sigs.k8s.io/external-dns/pkg/metrics"
|
||||
"sigs.k8s.io/external-dns/plan"
|
||||
"sigs.k8s.io/external-dns/provider"
|
||||
"sigs.k8s.io/external-dns/registry"
|
||||
"sigs.k8s.io/external-dns/source"
|
||||
)
|
||||
|
||||
var (
|
||||
registryErrorsTotal = metrics.NewCounterWithOpts(
|
||||
prometheus.CounterOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "registry",
|
||||
Name: "errors_total",
|
||||
Help: "Number of Registry errors.",
|
||||
},
|
||||
)
|
||||
sourceErrorsTotal = metrics.NewCounterWithOpts(
|
||||
prometheus.CounterOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "source",
|
||||
Name: "errors_total",
|
||||
Help: "Number of Source errors.",
|
||||
},
|
||||
)
|
||||
sourceEndpointsTotal = metrics.NewGaugeWithOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "source",
|
||||
Name: "endpoints_total",
|
||||
Help: "Number of Endpoints in all sources",
|
||||
},
|
||||
)
|
||||
registryEndpointsTotal = metrics.NewGaugeWithOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "registry",
|
||||
Name: "endpoints_total",
|
||||
Help: "Number of Endpoints in the registry",
|
||||
},
|
||||
)
|
||||
lastSyncTimestamp = metrics.NewGaugeWithOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "controller",
|
||||
Name: "last_sync_timestamp_seconds",
|
||||
Help: "Timestamp of last successful sync with the DNS provider",
|
||||
},
|
||||
)
|
||||
lastReconcileTimestamp = metrics.NewGaugeWithOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "controller",
|
||||
Name: "last_reconcile_timestamp_seconds",
|
||||
Help: "Timestamp of last attempted sync with the DNS provider",
|
||||
},
|
||||
)
|
||||
controllerNoChangesTotal = metrics.NewCounterWithOpts(
|
||||
prometheus.CounterOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "controller",
|
||||
Name: "no_op_runs_total",
|
||||
Help: "Number of reconcile loops ending up with no changes on the DNS provider side.",
|
||||
},
|
||||
)
|
||||
deprecatedRegistryErrors = metrics.NewCounterWithOpts(
|
||||
prometheus.CounterOpts{
|
||||
Subsystem: "registry",
|
||||
Name: "errors_total",
|
||||
Help: "Number of Registry errors.",
|
||||
},
|
||||
)
|
||||
deprecatedSourceErrors = metrics.NewCounterWithOpts(
|
||||
prometheus.CounterOpts{
|
||||
Subsystem: "source",
|
||||
Name: "errors_total",
|
||||
Help: "Number of Source errors.",
|
||||
},
|
||||
)
|
||||
|
||||
registryRecords = metrics.NewGaugedVectorOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "registry",
|
||||
Name: "records",
|
||||
Help: "Number of registry records partitioned by label name (vector).",
|
||||
},
|
||||
[]string{"record_type"},
|
||||
)
|
||||
|
||||
sourceRecords = metrics.NewGaugedVectorOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "source",
|
||||
Name: "records",
|
||||
Help: "Number of source records partitioned by label name (vector).",
|
||||
},
|
||||
[]string{"record_type"},
|
||||
)
|
||||
|
||||
verifiedRecords = metrics.NewGaugedVectorOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "controller",
|
||||
Name: "verified_records",
|
||||
Help: "Number of DNS records that exists both in source and registry (vector).",
|
||||
},
|
||||
[]string{"record_type"},
|
||||
)
|
||||
|
||||
consecutiveSoftErrors = metrics.NewGaugeWithOpts(
|
||||
prometheus.GaugeOpts{
|
||||
Namespace: "external_dns",
|
||||
Subsystem: "controller",
|
||||
Name: "consecutive_soft_errors",
|
||||
Help: "Number of consecutive soft errors in reconciliation loop.",
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
func init() {
|
||||
metrics.RegisterMetric.MustRegister(registryErrorsTotal)
|
||||
metrics.RegisterMetric.MustRegister(sourceErrorsTotal)
|
||||
metrics.RegisterMetric.MustRegister(sourceEndpointsTotal)
|
||||
metrics.RegisterMetric.MustRegister(registryEndpointsTotal)
|
||||
metrics.RegisterMetric.MustRegister(lastSyncTimestamp)
|
||||
metrics.RegisterMetric.MustRegister(lastReconcileTimestamp)
|
||||
metrics.RegisterMetric.MustRegister(deprecatedRegistryErrors)
|
||||
metrics.RegisterMetric.MustRegister(deprecatedSourceErrors)
|
||||
metrics.RegisterMetric.MustRegister(controllerNoChangesTotal)
|
||||
|
||||
metrics.RegisterMetric.MustRegister(registryRecords)
|
||||
metrics.RegisterMetric.MustRegister(sourceRecords)
|
||||
metrics.RegisterMetric.MustRegister(verifiedRecords)
|
||||
|
||||
metrics.RegisterMetric.MustRegister(consecutiveSoftErrors)
|
||||
}
|
||||
|
||||
// Controller is responsible for orchestrating the different components.
|
||||
// It works in the following way:
|
||||
// * Ask the DNS provider for the current list of endpoints.
|
||||
// * Ask the Source for the desired list of endpoints.
|
||||
// * Take both lists and calculate a Plan to move current towards the desired state.
|
||||
// * Tell the DNS provider to apply the changes calculated by the Plan.
|
||||
type Controller struct {
|
||||
Source source.Source
|
||||
Registry registry.Registry
|
||||
// The policy that defines which change to DNS records is allowed
|
||||
Policy plan.Policy
|
||||
// The interval between individual synchronizations
|
||||
Interval time.Duration
|
||||
// The DomainFilter defines which DNS records to keep or exclude
|
||||
DomainFilter endpoint.DomainFilterInterface
|
||||
// The nextRunAt used for throttling and batching reconciliation
|
||||
nextRunAt time.Time
|
||||
// The runAtMutex is for atomic updating of nextRunAt and lastRunAt
|
||||
runAtMutex sync.Mutex
|
||||
// The lastRunAt used for throttling and batching reconciliation
|
||||
lastRunAt time.Time
|
||||
// MangedRecordTypes are DNS record types that will be considered for management.
|
||||
ManagedRecordTypes []string
|
||||
// ExcludeRecordTypes are DNS record types that will be excluded from management.
|
||||
ExcludeRecordTypes []string
|
||||
// MinEventSyncInterval is used as a window for batching events
|
||||
MinEventSyncInterval time.Duration
|
||||
}
|
||||
|
||||
// RunOnce runs a single iteration of a reconciliation loop.
|
||||
func (c *Controller) RunOnce(ctx context.Context) error {
|
||||
lastReconcileTimestamp.Gauge.SetToCurrentTime()
|
||||
|
||||
c.runAtMutex.Lock()
|
||||
c.lastRunAt = time.Now()
|
||||
c.runAtMutex.Unlock()
|
||||
|
||||
regMetrics := newMetricsRecorder()
|
||||
|
||||
regRecords, err := c.Registry.Records(ctx)
|
||||
if err != nil {
|
||||
registryErrorsTotal.Counter.Inc()
|
||||
deprecatedRegistryErrors.Counter.Inc()
|
||||
return err
|
||||
}
|
||||
|
||||
registryEndpointsTotal.Gauge.Set(float64(len(regRecords)))
|
||||
|
||||
countAddressRecords(regMetrics, regRecords, registryRecords)
|
||||
|
||||
ctx = context.WithValue(ctx, provider.RecordsContextKey, regRecords)
|
||||
|
||||
sourceEndpoints, err := c.Source.Endpoints(ctx)
|
||||
if err != nil {
|
||||
sourceErrorsTotal.Counter.Inc()
|
||||
deprecatedSourceErrors.Counter.Inc()
|
||||
return err
|
||||
}
|
||||
|
||||
sourceEndpointsTotal.Gauge.Set(float64(len(sourceEndpoints)))
|
||||
|
||||
sourceMetrics := newMetricsRecorder()
|
||||
countAddressRecords(sourceMetrics, sourceEndpoints, sourceRecords)
|
||||
|
||||
vaMetrics := newMetricsRecorder()
|
||||
countMatchingAddressRecords(vaMetrics, sourceEndpoints, regRecords, verifiedRecords)
|
||||
|
||||
endpoints, err := c.Registry.AdjustEndpoints(sourceEndpoints)
|
||||
if err != nil {
|
||||
return fmt.Errorf("adjusting endpoints: %w", err)
|
||||
}
|
||||
registryFilter := c.Registry.GetDomainFilter()
|
||||
|
||||
plan := &plan.Plan{
|
||||
Policies: []plan.Policy{c.Policy},
|
||||
Current: regRecords,
|
||||
Desired: endpoints,
|
||||
DomainFilter: endpoint.MatchAllDomainFilters{c.DomainFilter, registryFilter},
|
||||
ManagedRecords: c.ManagedRecordTypes,
|
||||
ExcludeRecords: c.ExcludeRecordTypes,
|
||||
OwnerID: c.Registry.OwnerID(),
|
||||
}
|
||||
|
||||
plan = plan.Calculate()
|
||||
|
||||
if plan.Changes.HasChanges() {
|
||||
err = c.Registry.ApplyChanges(ctx, plan.Changes)
|
||||
if err != nil {
|
||||
registryErrorsTotal.Counter.Inc()
|
||||
deprecatedRegistryErrors.Counter.Inc()
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
controllerNoChangesTotal.Counter.Inc()
|
||||
log.Info("All records are already up to date")
|
||||
}
|
||||
|
||||
lastSyncTimestamp.Gauge.SetToCurrentTime()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func earliest(r time.Time, times ...time.Time) time.Time {
|
||||
for _, t := range times {
|
||||
if t.Before(r) {
|
||||
r = t
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func latest(r time.Time, times ...time.Time) time.Time {
|
||||
for _, t := range times {
|
||||
if t.After(r) {
|
||||
r = t
|
||||
}
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// Counts the intersections of records in endpoint and registry.
|
||||
func countMatchingAddressRecords(rec *metricsRecorder, endpoints []*endpoint.Endpoint, registryRecords []*endpoint.Endpoint, metric metrics.GaugeVecMetric) {
|
||||
recordsMap := make(map[string]map[string]struct{})
|
||||
for _, regRecord := range registryRecords {
|
||||
if _, found := recordsMap[regRecord.DNSName]; !found {
|
||||
recordsMap[regRecord.DNSName] = make(map[string]struct{})
|
||||
}
|
||||
recordsMap[regRecord.DNSName][regRecord.RecordType] = struct{}{}
|
||||
}
|
||||
|
||||
for _, sourceRecord := range endpoints {
|
||||
if _, found := recordsMap[sourceRecord.DNSName]; found {
|
||||
if _, ok := recordsMap[sourceRecord.DNSName][sourceRecord.RecordType]; ok {
|
||||
rec.recordEndpointType(sourceRecord.RecordType)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, rt := range endpoint.KnownRecordTypes {
|
||||
metric.SetWithLabels(rec.loadFloat64(rt), rt)
|
||||
}
|
||||
}
|
||||
|
||||
// countAddressRecords updates the metricsRecorder with the count of each record type
|
||||
// found in the provided endpoints slice, and sets the corresponding metrics for each
|
||||
// known DNS record type using the sourceRecords metric.
|
||||
func countAddressRecords(rec *metricsRecorder, endpoints []*endpoint.Endpoint, metric metrics.GaugeVecMetric) {
|
||||
// compute the number of records per type
|
||||
for _, endPoint := range endpoints {
|
||||
rec.recordEndpointType(endPoint.RecordType)
|
||||
}
|
||||
// set metrics for each record type
|
||||
for _, rt := range endpoint.KnownRecordTypes {
|
||||
metric.SetWithLabels(rec.loadFloat64(rt), rt)
|
||||
}
|
||||
}
|
||||
|
||||
// ScheduleRunOnce makes sure execution happens at most once per interval.
|
||||
func (c *Controller) ScheduleRunOnce(now time.Time) {
|
||||
c.runAtMutex.Lock()
|
||||
defer c.runAtMutex.Unlock()
|
||||
c.nextRunAt = latest(
|
||||
c.lastRunAt.Add(c.MinEventSyncInterval),
|
||||
earliest(
|
||||
now.Add(5*time.Second),
|
||||
c.nextRunAt,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
func (c *Controller) ShouldRunOnce(now time.Time) bool {
|
||||
c.runAtMutex.Lock()
|
||||
defer c.runAtMutex.Unlock()
|
||||
if now.Before(c.nextRunAt) {
|
||||
return false
|
||||
}
|
||||
c.nextRunAt = now.Add(c.Interval)
|
||||
return true
|
||||
}
|
||||
|
||||
// Run runs RunOnce in a loop with a delay until context is canceled
|
||||
func (c *Controller) Run(ctx context.Context) {
|
||||
ticker := time.NewTicker(time.Second)
|
||||
defer ticker.Stop()
|
||||
var softErrorCount int
|
||||
for {
|
||||
if c.ShouldRunOnce(time.Now()) {
|
||||
if err := c.RunOnce(ctx); err != nil {
|
||||
if errors.Is(err, provider.SoftError) {
|
||||
softErrorCount++
|
||||
consecutiveSoftErrors.Gauge.Set(float64(softErrorCount))
|
||||
log.Errorf("Failed to do run once: %v (consecutive soft errors: %d)", err, softErrorCount)
|
||||
} else {
|
||||
log.Fatalf("Failed to do run once: %v", err)
|
||||
}
|
||||
} else {
|
||||
if softErrorCount > 0 {
|
||||
log.Infof("Reconciliation succeeded after %d consecutive soft errors", softErrorCount)
|
||||
}
|
||||
softErrorCount = 0
|
||||
consecutiveSoftErrors.Gauge.Set(0)
|
||||
}
|
||||
}
|
||||
select {
|
||||
case <-ticker.C:
|
||||
case <-ctx.Done():
|
||||
log.Info("Terminating main controller loop")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
555
v0.18.0/controller/controller_test.go
Normal file
555
v0.18.0/controller/controller_test.go
Normal file
@ -0,0 +1,555 @@
|
||||
/*
|
||||
Copyright 2017 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 controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"reflect"
|
||||
"sort"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"sigs.k8s.io/external-dns/endpoint"
|
||||
"sigs.k8s.io/external-dns/internal/testutils"
|
||||
"sigs.k8s.io/external-dns/pkg/apis/externaldns"
|
||||
"sigs.k8s.io/external-dns/plan"
|
||||
"sigs.k8s.io/external-dns/provider"
|
||||
"sigs.k8s.io/external-dns/registry"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// mockProvider returns mock endpoints and validates changes.
|
||||
type mockProvider struct {
|
||||
provider.BaseProvider
|
||||
RecordsStore []*endpoint.Endpoint
|
||||
ExpectChanges *plan.Changes
|
||||
}
|
||||
|
||||
type filteredMockProvider struct {
|
||||
provider.BaseProvider
|
||||
domainFilter *endpoint.DomainFilter
|
||||
RecordsStore []*endpoint.Endpoint
|
||||
RecordsCallCount int
|
||||
ApplyChangesCalls []*plan.Changes
|
||||
}
|
||||
|
||||
type errorMockProvider struct {
|
||||
mockProvider
|
||||
}
|
||||
|
||||
func (p *filteredMockProvider) GetDomainFilter() endpoint.DomainFilterInterface {
|
||||
return p.domainFilter
|
||||
}
|
||||
|
||||
// Records returns the desired mock endpoints.
|
||||
func (p *filteredMockProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error) {
|
||||
p.RecordsCallCount++
|
||||
return p.RecordsStore, nil
|
||||
}
|
||||
|
||||
// ApplyChanges stores all calls for later check
|
||||
func (p *filteredMockProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
|
||||
p.ApplyChangesCalls = append(p.ApplyChangesCalls, changes)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Records returns the desired mock endpoints.
|
||||
func (p *mockProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error) {
|
||||
return p.RecordsStore, nil
|
||||
}
|
||||
|
||||
func (p *errorMockProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error) {
|
||||
return nil, errors.New("error for testing")
|
||||
}
|
||||
|
||||
// ApplyChanges validates that the passed in changes satisfy the assumptions.
|
||||
func (p *mockProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
|
||||
if err := verifyEndpoints(changes.Create, p.ExpectChanges.Create); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := verifyEndpoints(changes.UpdateNew, p.ExpectChanges.UpdateNew); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := verifyEndpoints(changes.UpdateOld, p.ExpectChanges.UpdateOld); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := verifyEndpoints(changes.Delete, p.ExpectChanges.Delete); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(ctx.Value(provider.RecordsContextKey), p.RecordsStore) {
|
||||
return errors.New("context is wrong")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func verifyEndpoints(actual, expected []*endpoint.Endpoint) error {
|
||||
if len(actual) != len(expected) {
|
||||
return errors.New("number of records is wrong")
|
||||
}
|
||||
sort.Slice(actual, func(i, j int) bool {
|
||||
return actual[i].DNSName < actual[j].DNSName
|
||||
})
|
||||
for i := range actual {
|
||||
if actual[i].DNSName != expected[i].DNSName || !actual[i].Targets.Same(expected[i].Targets) {
|
||||
return errors.New("record is wrong")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// newMockProvider creates a new mockProvider returning the given endpoints and validating the desired changes.
|
||||
func newMockProvider(endpoints []*endpoint.Endpoint, changes *plan.Changes) provider.Provider {
|
||||
dnsProvider := &mockProvider{
|
||||
RecordsStore: endpoints,
|
||||
ExpectChanges: changes,
|
||||
}
|
||||
|
||||
return dnsProvider
|
||||
}
|
||||
|
||||
func getTestSource() *testutils.MockSource {
|
||||
// Fake some desired endpoints coming from our source.
|
||||
source := new(testutils.MockSource)
|
||||
source.On("Endpoints").Return([]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "create-record",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
{
|
||||
DNSName: "update-record",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"8.8.4.4"},
|
||||
},
|
||||
{
|
||||
DNSName: "create-aaaa-record",
|
||||
RecordType: endpoint.RecordTypeAAAA,
|
||||
Targets: endpoint.Targets{"2001:DB8::1"},
|
||||
},
|
||||
{
|
||||
DNSName: "update-aaaa-record",
|
||||
RecordType: endpoint.RecordTypeAAAA,
|
||||
Targets: endpoint.Targets{"2001:DB8::2"},
|
||||
},
|
||||
}, nil)
|
||||
|
||||
return source
|
||||
}
|
||||
|
||||
func getTestConfig() *externaldns.Config {
|
||||
cfg := externaldns.NewConfig()
|
||||
cfg.ManagedDNSRecordTypes = []string{endpoint.RecordTypeA, endpoint.RecordTypeAAAA, endpoint.RecordTypeCNAME}
|
||||
return cfg
|
||||
}
|
||||
|
||||
func getTestProvider() provider.Provider {
|
||||
// Fake some existing records in our DNS provider and validate some desired changes.
|
||||
return newMockProvider(
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "update-record",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
{
|
||||
DNSName: "delete-record",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"4.3.2.1"},
|
||||
},
|
||||
{
|
||||
DNSName: "update-aaaa-record",
|
||||
RecordType: endpoint.RecordTypeAAAA,
|
||||
Targets: endpoint.Targets{"2001:DB8::3"},
|
||||
},
|
||||
{
|
||||
DNSName: "delete-aaaa-record",
|
||||
RecordType: endpoint.RecordTypeAAAA,
|
||||
Targets: endpoint.Targets{"2001:DB8::4"},
|
||||
},
|
||||
},
|
||||
&plan.Changes{
|
||||
Create: []*endpoint.Endpoint{
|
||||
{DNSName: "create-aaaa-record", RecordType: endpoint.RecordTypeAAAA, Targets: endpoint.Targets{"2001:DB8::1"}},
|
||||
{DNSName: "create-record", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"1.2.3.4"}},
|
||||
},
|
||||
UpdateNew: []*endpoint.Endpoint{
|
||||
{DNSName: "update-aaaa-record", RecordType: endpoint.RecordTypeAAAA, Targets: endpoint.Targets{"2001:DB8::2"}},
|
||||
{DNSName: "update-record", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"8.8.4.4"}},
|
||||
},
|
||||
UpdateOld: []*endpoint.Endpoint{
|
||||
{DNSName: "update-aaaa-record", RecordType: endpoint.RecordTypeAAAA, Targets: endpoint.Targets{"2001:DB8::3"}},
|
||||
{DNSName: "update-record", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"8.8.8.8"}},
|
||||
},
|
||||
Delete: []*endpoint.Endpoint{
|
||||
{DNSName: "delete-aaaa-record", RecordType: endpoint.RecordTypeAAAA, Targets: endpoint.Targets{"2001:DB8::4"}},
|
||||
{DNSName: "delete-record", RecordType: endpoint.RecordTypeA, Targets: endpoint.Targets{"4.3.2.1"}},
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// TestRunOnce tests that RunOnce correctly orchestrates the different components.
|
||||
func TestRunOnce(t *testing.T) {
|
||||
source := getTestSource()
|
||||
cfg := getTestConfig()
|
||||
provider := getTestProvider()
|
||||
|
||||
r, err := registry.NewNoopRegistry(provider)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Run our controller once to trigger the validation.
|
||||
ctrl := &Controller{
|
||||
Source: source,
|
||||
Registry: r,
|
||||
Policy: &plan.SyncPolicy{},
|
||||
ManagedRecordTypes: cfg.ManagedDNSRecordTypes,
|
||||
}
|
||||
|
||||
assert.NoError(t, ctrl.RunOnce(context.Background()))
|
||||
|
||||
// Validate that the mock source was called.
|
||||
source.AssertExpectations(t)
|
||||
// check the verified records
|
||||
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 1, verifiedRecords.Gauge, map[string]string{"record_type": "a"})
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 1, verifiedRecords.Gauge, map[string]string{"record_type": "aaaa"})
|
||||
}
|
||||
|
||||
// TestRun tests that Run correctly starts and stops
|
||||
func TestRun(t *testing.T) {
|
||||
source := getTestSource()
|
||||
cfg := getTestConfig()
|
||||
provider := getTestProvider()
|
||||
|
||||
r, err := registry.NewNoopRegistry(provider)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Run our controller once to trigger the validation.
|
||||
ctrl := &Controller{
|
||||
Source: source,
|
||||
Registry: r,
|
||||
Policy: &plan.SyncPolicy{},
|
||||
ManagedRecordTypes: cfg.ManagedDNSRecordTypes,
|
||||
}
|
||||
ctrl.nextRunAt = time.Now().Add(-time.Millisecond)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
stopped := make(chan struct{})
|
||||
go func() {
|
||||
ctrl.Run(ctx)
|
||||
close(stopped)
|
||||
}()
|
||||
time.Sleep(1500 * time.Millisecond)
|
||||
cancel() // start shutdown
|
||||
<-stopped
|
||||
|
||||
// Validate that the mock source was called.
|
||||
source.AssertExpectations(t)
|
||||
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 1, verifiedRecords.Gauge, map[string]string{"record_type": "a"})
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 1, verifiedRecords.Gauge, map[string]string{"record_type": "aaaa"})
|
||||
}
|
||||
|
||||
func TestShouldRunOnce(t *testing.T) {
|
||||
ctrl := &Controller{Interval: 10 * time.Minute, MinEventSyncInterval: 15 * time.Second}
|
||||
|
||||
now := time.Now()
|
||||
|
||||
// First run of Run loop should execute RunOnce
|
||||
assert.True(t, ctrl.ShouldRunOnce(now))
|
||||
assert.Equal(t, now.Add(10*time.Minute), ctrl.nextRunAt)
|
||||
|
||||
// Second run should not
|
||||
assert.False(t, ctrl.ShouldRunOnce(now))
|
||||
ctrl.lastRunAt = now
|
||||
|
||||
now = now.Add(10 * time.Second)
|
||||
// Changes happen in ingresses or services
|
||||
ctrl.ScheduleRunOnce(now)
|
||||
ctrl.ScheduleRunOnce(now)
|
||||
|
||||
// Because we batch changes, ShouldRunOnce returns False at first
|
||||
assert.False(t, ctrl.ShouldRunOnce(now))
|
||||
assert.False(t, ctrl.ShouldRunOnce(now.Add(100*time.Microsecond)))
|
||||
|
||||
// But after MinInterval we should run reconciliation
|
||||
now = now.Add(5 * time.Second)
|
||||
assert.True(t, ctrl.ShouldRunOnce(now))
|
||||
|
||||
// But just one time
|
||||
assert.False(t, ctrl.ShouldRunOnce(now))
|
||||
|
||||
// We should wait maximum possible time after last reconciliation started
|
||||
now = now.Add(10*time.Minute - time.Second)
|
||||
assert.False(t, ctrl.ShouldRunOnce(now))
|
||||
|
||||
// After exactly Interval it's OK again to reconcile
|
||||
now = now.Add(time.Second)
|
||||
assert.True(t, ctrl.ShouldRunOnce(now))
|
||||
|
||||
// But not two times
|
||||
assert.False(t, ctrl.ShouldRunOnce(now))
|
||||
|
||||
// Multiple ingresses or services changes, closer than MinInterval from each other
|
||||
ctrl.lastRunAt = now
|
||||
firstChangeTime := now
|
||||
secondChangeTime := firstChangeTime.Add(time.Second)
|
||||
// First change
|
||||
ctrl.ScheduleRunOnce(firstChangeTime)
|
||||
// Second change
|
||||
ctrl.ScheduleRunOnce(secondChangeTime)
|
||||
|
||||
// Executions should be spaced by at least MinEventSyncInterval
|
||||
assert.False(t, ctrl.ShouldRunOnce(now.Add(5*time.Second)))
|
||||
|
||||
// Should not postpone the reconciliation further than firstChangeTime + MinInterval
|
||||
now = now.Add(ctrl.MinEventSyncInterval)
|
||||
assert.True(t, ctrl.ShouldRunOnce(now))
|
||||
}
|
||||
|
||||
func testControllerFiltersDomains(t *testing.T, configuredEndpoints []*endpoint.Endpoint, domainFilter *endpoint.DomainFilter, providerEndpoints []*endpoint.Endpoint, expectedChanges []*plan.Changes) {
|
||||
t.Helper()
|
||||
cfg := externaldns.NewConfig()
|
||||
cfg.ManagedDNSRecordTypes = []string{endpoint.RecordTypeA, endpoint.RecordTypeAAAA, endpoint.RecordTypeCNAME}
|
||||
|
||||
source := new(testutils.MockSource)
|
||||
source.On("Endpoints").Return(configuredEndpoints, nil)
|
||||
|
||||
// Fake some existing records in our DNS provider and validate some desired changes.
|
||||
provider := &filteredMockProvider{
|
||||
RecordsStore: providerEndpoints,
|
||||
}
|
||||
r, err := registry.NewNoopRegistry(provider)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
ctrl := &Controller{
|
||||
Source: source,
|
||||
Registry: r,
|
||||
Policy: &plan.SyncPolicy{},
|
||||
DomainFilter: domainFilter,
|
||||
ManagedRecordTypes: cfg.ManagedDNSRecordTypes,
|
||||
}
|
||||
|
||||
assert.NoError(t, ctrl.RunOnce(context.Background()))
|
||||
assert.Equal(t, 1, provider.RecordsCallCount)
|
||||
require.Len(t, provider.ApplyChangesCalls, len(expectedChanges))
|
||||
for i, change := range expectedChanges {
|
||||
assert.Equal(t, *change, *provider.ApplyChangesCalls[i])
|
||||
}
|
||||
}
|
||||
|
||||
func TestControllerSkipsEmptyChanges(t *testing.T) {
|
||||
testControllerFiltersDomains(
|
||||
t,
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "create-record.other.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
{
|
||||
DNSName: "some-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
},
|
||||
endpoint.NewDomainFilter([]string{"used.tld"}),
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "some-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
},
|
||||
[]*plan.Changes{},
|
||||
)
|
||||
}
|
||||
|
||||
func TestWhenNoFilterControllerConsidersAllComain(t *testing.T) {
|
||||
testControllerFiltersDomains(
|
||||
t,
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "create-record.other.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
{
|
||||
DNSName: "some-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
},
|
||||
&endpoint.DomainFilter{},
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "some-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
},
|
||||
[]*plan.Changes{
|
||||
{
|
||||
Create: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "create-record.other.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func TestWhenMultipleControllerConsidersAllFilteredComain(t *testing.T) {
|
||||
testControllerFiltersDomains(
|
||||
t,
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "create-record.other.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
{
|
||||
DNSName: "some-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.1.1.1"},
|
||||
},
|
||||
{
|
||||
DNSName: "create-record.unused.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
},
|
||||
endpoint.NewDomainFilter([]string{"used.tld", "other.tld"}),
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "some-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
},
|
||||
[]*plan.Changes{
|
||||
{
|
||||
Create: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "create-record.other.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
},
|
||||
UpdateOld: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "some-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
Labels: endpoint.Labels{},
|
||||
},
|
||||
},
|
||||
UpdateNew: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "some-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.1.1.1"},
|
||||
Labels: endpoint.Labels{
|
||||
"owner": "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
type toggleRegistry struct {
|
||||
registry.NoopRegistry
|
||||
failCount int
|
||||
failCountMu sync.Mutex // protects failCount
|
||||
}
|
||||
|
||||
const toggleRegistryFailureCount = 3
|
||||
|
||||
func (r *toggleRegistry) Records(_ context.Context) ([]*endpoint.Endpoint, error) {
|
||||
r.failCountMu.Lock()
|
||||
defer r.failCountMu.Unlock()
|
||||
if r.failCount < toggleRegistryFailureCount {
|
||||
r.failCount++
|
||||
return nil, provider.SoftError
|
||||
}
|
||||
return []*endpoint.Endpoint{}, nil
|
||||
}
|
||||
|
||||
func (r *toggleRegistry) ApplyChanges(_ context.Context, changes *plan.Changes) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestToggleRegistry(t *testing.T) {
|
||||
source := getTestSource()
|
||||
cfg := getTestConfig()
|
||||
r := &toggleRegistry{}
|
||||
|
||||
interval := 10 * time.Millisecond
|
||||
ctrl := &Controller{
|
||||
Source: source,
|
||||
Registry: r,
|
||||
Policy: &plan.SyncPolicy{},
|
||||
ManagedRecordTypes: cfg.ManagedDNSRecordTypes,
|
||||
Interval: interval,
|
||||
}
|
||||
ctrl.nextRunAt = time.Now().Add(-time.Millisecond)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
stopped := make(chan struct{})
|
||||
go func() {
|
||||
ctrl.Run(ctx)
|
||||
close(stopped)
|
||||
}()
|
||||
|
||||
// Wait up to 1 minute for failCount to reach at least 3
|
||||
// The timeout serves as a safety net against infinite loops while being
|
||||
// sufficiently large to accommodate slow CI environments
|
||||
deadline := time.Now().Add(15 * time.Second)
|
||||
for {
|
||||
r.failCountMu.Lock()
|
||||
count := r.failCount
|
||||
r.failCountMu.Unlock()
|
||||
if count >= toggleRegistryFailureCount {
|
||||
break
|
||||
}
|
||||
if time.Now().After(deadline) {
|
||||
break
|
||||
}
|
||||
// Sleep for the controller interval to avoid busy waiting
|
||||
// since the controller won't run again until the interval passes
|
||||
time.Sleep(interval)
|
||||
}
|
||||
cancel()
|
||||
<-stopped
|
||||
|
||||
r.failCountMu.Lock()
|
||||
finalCount := r.failCount
|
||||
r.failCountMu.Unlock()
|
||||
assert.Equal(t, toggleRegistryFailureCount, finalCount, "failCount should be at least %d", toggleRegistryFailureCount)
|
||||
}
|
||||
470
v0.18.0/controller/execute.go
Normal file
470
v0.18.0/controller/execute.go
Normal file
@ -0,0 +1,470 @@
|
||||
/*
|
||||
Copyright 2025 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 controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
|
||||
"github.com/aws/aws-sdk-go-v2/service/route53"
|
||||
sd "github.com/aws/aws-sdk-go-v2/service/servicediscovery"
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
"sigs.k8s.io/external-dns/endpoint"
|
||||
"sigs.k8s.io/external-dns/pkg/apis/externaldns"
|
||||
"sigs.k8s.io/external-dns/pkg/apis/externaldns/validation"
|
||||
"sigs.k8s.io/external-dns/pkg/metrics"
|
||||
"sigs.k8s.io/external-dns/plan"
|
||||
"sigs.k8s.io/external-dns/provider"
|
||||
"sigs.k8s.io/external-dns/provider/akamai"
|
||||
"sigs.k8s.io/external-dns/provider/alibabacloud"
|
||||
"sigs.k8s.io/external-dns/provider/aws"
|
||||
"sigs.k8s.io/external-dns/provider/awssd"
|
||||
"sigs.k8s.io/external-dns/provider/azure"
|
||||
"sigs.k8s.io/external-dns/provider/civo"
|
||||
"sigs.k8s.io/external-dns/provider/cloudflare"
|
||||
"sigs.k8s.io/external-dns/provider/coredns"
|
||||
"sigs.k8s.io/external-dns/provider/digitalocean"
|
||||
"sigs.k8s.io/external-dns/provider/dnsimple"
|
||||
"sigs.k8s.io/external-dns/provider/exoscale"
|
||||
"sigs.k8s.io/external-dns/provider/gandi"
|
||||
"sigs.k8s.io/external-dns/provider/godaddy"
|
||||
"sigs.k8s.io/external-dns/provider/google"
|
||||
"sigs.k8s.io/external-dns/provider/inmemory"
|
||||
"sigs.k8s.io/external-dns/provider/linode"
|
||||
"sigs.k8s.io/external-dns/provider/ns1"
|
||||
"sigs.k8s.io/external-dns/provider/oci"
|
||||
"sigs.k8s.io/external-dns/provider/ovh"
|
||||
"sigs.k8s.io/external-dns/provider/pdns"
|
||||
"sigs.k8s.io/external-dns/provider/pihole"
|
||||
"sigs.k8s.io/external-dns/provider/plural"
|
||||
"sigs.k8s.io/external-dns/provider/rfc2136"
|
||||
"sigs.k8s.io/external-dns/provider/scaleway"
|
||||
"sigs.k8s.io/external-dns/provider/transip"
|
||||
"sigs.k8s.io/external-dns/provider/webhook"
|
||||
webhookapi "sigs.k8s.io/external-dns/provider/webhook/api"
|
||||
"sigs.k8s.io/external-dns/registry"
|
||||
"sigs.k8s.io/external-dns/source"
|
||||
)
|
||||
|
||||
func Execute() {
|
||||
cfg := externaldns.NewConfig()
|
||||
if err := cfg.ParseFlags(os.Args[1:]); err != nil {
|
||||
log.Fatalf("flag parsing error: %v", err)
|
||||
}
|
||||
log.Infof("config: %s", cfg)
|
||||
if err := validation.ValidateConfig(cfg); err != nil {
|
||||
log.Fatalf("config validation failed: %v", err)
|
||||
}
|
||||
|
||||
configureLogger(cfg)
|
||||
|
||||
if cfg.DryRun {
|
||||
log.Info("running in dry-run mode. No changes to DNS records will be made.")
|
||||
}
|
||||
|
||||
if log.GetLevel() < log.DebugLevel {
|
||||
// Klog V2 is used by k8s.io/apimachinery/pkg/labels and can throw (a lot) of irrelevant logs
|
||||
// See https://github.com/kubernetes-sigs/external-dns/issues/2348
|
||||
defer klog.ClearLogger()
|
||||
klog.SetLogger(logr.Discard())
|
||||
}
|
||||
|
||||
log.Info(externaldns.Banner())
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
|
||||
go serveMetrics(cfg.MetricsAddress)
|
||||
go handleSigterm(cancel)
|
||||
|
||||
endpointsSource, err := buildSource(ctx, cfg)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
domainFilter := createDomainFilter(cfg)
|
||||
|
||||
prvdr, err := buildProvider(ctx, cfg, domainFilter)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if cfg.WebhookServer {
|
||||
webhookapi.StartHTTPApi(prvdr, nil, cfg.WebhookProviderReadTimeout, cfg.WebhookProviderWriteTimeout, "127.0.0.1:8888")
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
ctrl, err := buildController(cfg, endpointsSource, prvdr, domainFilter)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if cfg.Once {
|
||||
err := ctrl.RunOnce(ctx)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if cfg.UpdateEvents {
|
||||
// Add RunOnce as the handler function that will be called when ingress/service sources have changed.
|
||||
// Note that k8s Informers will perform an initial list operation, which results in the handler
|
||||
// function initially being called for every Service/Ingress that exists
|
||||
ctrl.Source.AddEventHandler(ctx, func() { ctrl.ScheduleRunOnce(time.Now()) })
|
||||
}
|
||||
|
||||
ctrl.ScheduleRunOnce(time.Now())
|
||||
ctrl.Run(ctx)
|
||||
}
|
||||
|
||||
func buildProvider(
|
||||
ctx context.Context,
|
||||
cfg *externaldns.Config,
|
||||
domainFilter *endpoint.DomainFilter,
|
||||
) (provider.Provider, error) {
|
||||
var p provider.Provider
|
||||
var err error
|
||||
|
||||
zoneNameFilter := endpoint.NewDomainFilter(cfg.ZoneNameFilter)
|
||||
zoneIDFilter := provider.NewZoneIDFilter(cfg.ZoneIDFilter)
|
||||
zoneTypeFilter := provider.NewZoneTypeFilter(cfg.AWSZoneType)
|
||||
zoneTagFilter := provider.NewZoneTagFilter(cfg.AWSZoneTagFilter)
|
||||
|
||||
switch cfg.Provider {
|
||||
case "akamai":
|
||||
p, err = akamai.NewAkamaiProvider(
|
||||
akamai.AkamaiConfig{
|
||||
DomainFilter: domainFilter,
|
||||
ZoneIDFilter: zoneIDFilter,
|
||||
ServiceConsumerDomain: cfg.AkamaiServiceConsumerDomain,
|
||||
ClientToken: cfg.AkamaiClientToken,
|
||||
ClientSecret: cfg.AkamaiClientSecret,
|
||||
AccessToken: cfg.AkamaiAccessToken,
|
||||
EdgercPath: cfg.AkamaiEdgercPath,
|
||||
EdgercSection: cfg.AkamaiEdgercSection,
|
||||
DryRun: cfg.DryRun,
|
||||
}, nil)
|
||||
case "alibabacloud":
|
||||
p, err = alibabacloud.NewAlibabaCloudProvider(cfg.AlibabaCloudConfigFile, domainFilter, zoneIDFilter, cfg.AlibabaCloudZoneType, cfg.DryRun)
|
||||
case "aws":
|
||||
configs := aws.CreateV2Configs(cfg)
|
||||
clients := make(map[string]aws.Route53API, len(configs))
|
||||
for profile, config := range configs {
|
||||
clients[profile] = route53.NewFromConfig(config)
|
||||
}
|
||||
|
||||
p, err = aws.NewAWSProvider(
|
||||
aws.AWSConfig{
|
||||
DomainFilter: domainFilter,
|
||||
ZoneIDFilter: zoneIDFilter,
|
||||
ZoneTypeFilter: zoneTypeFilter,
|
||||
ZoneTagFilter: zoneTagFilter,
|
||||
ZoneMatchParent: cfg.AWSZoneMatchParent,
|
||||
BatchChangeSize: cfg.AWSBatchChangeSize,
|
||||
BatchChangeSizeBytes: cfg.AWSBatchChangeSizeBytes,
|
||||
BatchChangeSizeValues: cfg.AWSBatchChangeSizeValues,
|
||||
BatchChangeInterval: cfg.AWSBatchChangeInterval,
|
||||
EvaluateTargetHealth: cfg.AWSEvaluateTargetHealth,
|
||||
PreferCNAME: cfg.AWSPreferCNAME,
|
||||
DryRun: cfg.DryRun,
|
||||
ZoneCacheDuration: cfg.AWSZoneCacheDuration,
|
||||
},
|
||||
clients,
|
||||
)
|
||||
case "aws-sd":
|
||||
// Check that only compatible Registry is used with AWS-SD
|
||||
if cfg.Registry != "noop" && cfg.Registry != "aws-sd" {
|
||||
log.Infof("Registry \"%s\" cannot be used with AWS Cloud Map. Switching to \"aws-sd\".", cfg.Registry)
|
||||
cfg.Registry = "aws-sd"
|
||||
}
|
||||
p, err = awssd.NewAWSSDProvider(domainFilter, cfg.AWSZoneType, cfg.DryRun, cfg.AWSSDServiceCleanup, cfg.TXTOwnerID, cfg.AWSSDCreateTag, sd.NewFromConfig(aws.CreateDefaultV2Config(cfg)))
|
||||
case "azure-dns", "azure":
|
||||
p, err = azure.NewAzureProvider(cfg.AzureConfigFile, domainFilter, zoneNameFilter, zoneIDFilter, cfg.AzureSubscriptionID, cfg.AzureResourceGroup, cfg.AzureUserAssignedIdentityClientID, cfg.AzureActiveDirectoryAuthorityHost, cfg.AzureZonesCacheDuration, cfg.AzureMaxRetriesCount, cfg.DryRun)
|
||||
case "azure-private-dns":
|
||||
p, err = azure.NewAzurePrivateDNSProvider(cfg.AzureConfigFile, domainFilter, zoneNameFilter, zoneIDFilter, cfg.AzureSubscriptionID, cfg.AzureResourceGroup, cfg.AzureUserAssignedIdentityClientID, cfg.AzureActiveDirectoryAuthorityHost, cfg.AzureZonesCacheDuration, cfg.AzureMaxRetriesCount, cfg.DryRun)
|
||||
case "civo":
|
||||
p, err = civo.NewCivoProvider(domainFilter, cfg.DryRun)
|
||||
case "cloudflare":
|
||||
p, err = cloudflare.NewCloudFlareProvider(
|
||||
domainFilter,
|
||||
zoneIDFilter,
|
||||
cfg.CloudflareProxied,
|
||||
cfg.DryRun,
|
||||
cloudflare.RegionalServicesConfig{
|
||||
Enabled: cfg.CloudflareRegionalServices,
|
||||
RegionKey: cfg.CloudflareRegionKey,
|
||||
},
|
||||
cloudflare.CustomHostnamesConfig{
|
||||
Enabled: cfg.CloudflareCustomHostnames,
|
||||
MinTLSVersion: cfg.CloudflareCustomHostnamesMinTLSVersion,
|
||||
CertificateAuthority: cfg.CloudflareCustomHostnamesCertificateAuthority,
|
||||
},
|
||||
cloudflare.DNSRecordsConfig{
|
||||
PerPage: cfg.CloudflareDNSRecordsPerPage,
|
||||
Comment: cfg.CloudflareDNSRecordsComment,
|
||||
})
|
||||
case "google":
|
||||
p, err = google.NewGoogleProvider(ctx, cfg.GoogleProject, domainFilter, zoneIDFilter, cfg.GoogleBatchChangeSize, cfg.GoogleBatchChangeInterval, cfg.GoogleZoneVisibility, cfg.DryRun)
|
||||
case "digitalocean":
|
||||
p, err = digitalocean.NewDigitalOceanProvider(ctx, domainFilter, cfg.DryRun, cfg.DigitalOceanAPIPageSize)
|
||||
case "ovh":
|
||||
p, err = ovh.NewOVHProvider(ctx, domainFilter, cfg.OVHEndpoint, cfg.OVHApiRateLimit, cfg.OVHEnableCNAMERelative, cfg.DryRun)
|
||||
case "linode":
|
||||
p, err = linode.NewLinodeProvider(domainFilter, cfg.DryRun)
|
||||
case "dnsimple":
|
||||
p, err = dnsimple.NewDnsimpleProvider(domainFilter, zoneIDFilter, cfg.DryRun)
|
||||
case "coredns", "skydns":
|
||||
p, err = coredns.NewCoreDNSProvider(domainFilter, cfg.CoreDNSPrefix, cfg.DryRun)
|
||||
case "exoscale":
|
||||
p, err = exoscale.NewExoscaleProvider(
|
||||
cfg.ExoscaleAPIEnvironment,
|
||||
cfg.ExoscaleAPIZone,
|
||||
cfg.ExoscaleAPIKey,
|
||||
cfg.ExoscaleAPISecret,
|
||||
cfg.DryRun,
|
||||
exoscale.ExoscaleWithDomain(domainFilter),
|
||||
exoscale.ExoscaleWithLogging(),
|
||||
)
|
||||
case "inmemory":
|
||||
p, err = inmemory.NewInMemoryProvider(inmemory.InMemoryInitZones(cfg.InMemoryZones), inmemory.InMemoryWithDomain(domainFilter), inmemory.InMemoryWithLogging()), nil
|
||||
case "pdns":
|
||||
p, err = pdns.NewPDNSProvider(
|
||||
ctx,
|
||||
pdns.PDNSConfig{
|
||||
DomainFilter: domainFilter,
|
||||
DryRun: cfg.DryRun,
|
||||
Server: cfg.PDNSServer,
|
||||
ServerID: cfg.PDNSServerID,
|
||||
APIKey: cfg.PDNSAPIKey,
|
||||
TLSConfig: pdns.TLSConfig{
|
||||
SkipTLSVerify: cfg.PDNSSkipTLSVerify,
|
||||
CAFilePath: cfg.TLSCA,
|
||||
ClientCertFilePath: cfg.TLSClientCert,
|
||||
ClientCertKeyFilePath: cfg.TLSClientCertKey,
|
||||
},
|
||||
},
|
||||
)
|
||||
case "oci":
|
||||
var config *oci.OCIConfig
|
||||
// if the instance-principals flag was set, and a compartment OCID was provided, then ignore the
|
||||
// OCI config file, and provide a config that uses instance principal authentication.
|
||||
if cfg.OCIAuthInstancePrincipal {
|
||||
if len(cfg.OCICompartmentOCID) == 0 {
|
||||
err = fmt.Errorf("instance principal authentication requested, but no compartment OCID provided")
|
||||
} else {
|
||||
authConfig := oci.OCIAuthConfig{UseInstancePrincipal: true}
|
||||
config = &oci.OCIConfig{Auth: authConfig, CompartmentID: cfg.OCICompartmentOCID}
|
||||
}
|
||||
} else {
|
||||
config, err = oci.LoadOCIConfig(cfg.OCIConfigFile)
|
||||
}
|
||||
config.ZoneCacheDuration = cfg.OCIZoneCacheDuration
|
||||
if err == nil {
|
||||
p, err = oci.NewOCIProvider(*config, domainFilter, zoneIDFilter, cfg.OCIZoneScope, cfg.DryRun)
|
||||
}
|
||||
case "rfc2136":
|
||||
tlsConfig := rfc2136.TLSConfig{
|
||||
UseTLS: cfg.RFC2136UseTLS,
|
||||
SkipTLSVerify: cfg.RFC2136SkipTLSVerify,
|
||||
CAFilePath: cfg.TLSCA,
|
||||
ClientCertFilePath: cfg.TLSClientCert,
|
||||
ClientCertKeyFilePath: cfg.TLSClientCertKey,
|
||||
}
|
||||
p, err = rfc2136.NewRfc2136Provider(cfg.RFC2136Host, cfg.RFC2136Port, cfg.RFC2136Zone, cfg.RFC2136Insecure, cfg.RFC2136TSIGKeyName, cfg.RFC2136TSIGSecret, cfg.RFC2136TSIGSecretAlg, cfg.RFC2136TAXFR, domainFilter, cfg.DryRun, cfg.RFC2136MinTTL, cfg.RFC2136CreatePTR, cfg.RFC2136GSSTSIG, cfg.RFC2136KerberosUsername, cfg.RFC2136KerberosPassword, cfg.RFC2136KerberosRealm, cfg.RFC2136BatchChangeSize, tlsConfig, cfg.RFC2136LoadBalancingStrategy, nil)
|
||||
case "ns1":
|
||||
p, err = ns1.NewNS1Provider(
|
||||
ns1.NS1Config{
|
||||
DomainFilter: domainFilter,
|
||||
ZoneIDFilter: zoneIDFilter,
|
||||
NS1Endpoint: cfg.NS1Endpoint,
|
||||
NS1IgnoreSSL: cfg.NS1IgnoreSSL,
|
||||
DryRun: cfg.DryRun,
|
||||
MinTTLSeconds: cfg.NS1MinTTLSeconds,
|
||||
},
|
||||
)
|
||||
case "transip":
|
||||
p, err = transip.NewTransIPProvider(cfg.TransIPAccountName, cfg.TransIPPrivateKeyFile, domainFilter, cfg.DryRun)
|
||||
case "scaleway":
|
||||
p, err = scaleway.NewScalewayProvider(ctx, domainFilter, cfg.DryRun)
|
||||
case "godaddy":
|
||||
p, err = godaddy.NewGoDaddyProvider(ctx, domainFilter, cfg.GoDaddyTTL, cfg.GoDaddyAPIKey, cfg.GoDaddySecretKey, cfg.GoDaddyOTE, cfg.DryRun)
|
||||
case "gandi":
|
||||
p, err = gandi.NewGandiProvider(ctx, domainFilter, cfg.DryRun)
|
||||
case "pihole":
|
||||
p, err = pihole.NewPiholeProvider(
|
||||
pihole.PiholeConfig{
|
||||
Server: cfg.PiholeServer,
|
||||
Password: cfg.PiholePassword,
|
||||
TLSInsecureSkipVerify: cfg.PiholeTLSInsecureSkipVerify,
|
||||
DomainFilter: domainFilter,
|
||||
DryRun: cfg.DryRun,
|
||||
APIVersion: cfg.PiholeApiVersion,
|
||||
},
|
||||
)
|
||||
case "plural":
|
||||
p, err = plural.NewPluralProvider(cfg.PluralCluster, cfg.PluralProvider)
|
||||
case "webhook":
|
||||
p, err = webhook.NewWebhookProvider(cfg.WebhookProviderURL)
|
||||
default:
|
||||
err = fmt.Errorf("unknown dns provider: %s", cfg.Provider)
|
||||
}
|
||||
if p != nil && cfg.ProviderCacheTime > 0 {
|
||||
p = provider.NewCachedProvider(
|
||||
p,
|
||||
cfg.ProviderCacheTime,
|
||||
)
|
||||
}
|
||||
return p, err
|
||||
}
|
||||
|
||||
func buildController(cfg *externaldns.Config, src source.Source, p provider.Provider, filter *endpoint.DomainFilter) (*Controller, error) {
|
||||
policy, ok := plan.Policies[cfg.Policy]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unknown policy: %s", cfg.Policy)
|
||||
}
|
||||
reg, err := selectRegistry(cfg, p)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Controller{
|
||||
Source: src,
|
||||
Registry: reg,
|
||||
Policy: policy,
|
||||
Interval: cfg.Interval,
|
||||
DomainFilter: filter,
|
||||
ManagedRecordTypes: cfg.ManagedDNSRecordTypes,
|
||||
ExcludeRecordTypes: cfg.ExcludeDNSRecordTypes,
|
||||
MinEventSyncInterval: cfg.MinEventSyncInterval,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// This function configures the logger format and level based on the provided configuration.
|
||||
func configureLogger(cfg *externaldns.Config) {
|
||||
if cfg.LogFormat == "json" {
|
||||
log.SetFormatter(&log.JSONFormatter{})
|
||||
}
|
||||
ll, err := log.ParseLevel(cfg.LogLevel)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to parse log level: %v", err)
|
||||
}
|
||||
log.SetLevel(ll)
|
||||
}
|
||||
|
||||
// selectRegistry selects the appropriate registry implementation based on the configuration in cfg.
|
||||
// It initializes and returns a registry along with any error encountered during setup.
|
||||
// Supported registry types include: dynamodb, noop, txt, and aws-sd.
|
||||
func selectRegistry(cfg *externaldns.Config, p provider.Provider) (registry.Registry, error) {
|
||||
var r registry.Registry
|
||||
var err error
|
||||
switch cfg.Registry {
|
||||
case "dynamodb":
|
||||
var dynamodbOpts []func(*dynamodb.Options)
|
||||
if cfg.AWSDynamoDBRegion != "" {
|
||||
dynamodbOpts = []func(*dynamodb.Options){
|
||||
func(opts *dynamodb.Options) {
|
||||
opts.Region = cfg.AWSDynamoDBRegion
|
||||
},
|
||||
}
|
||||
}
|
||||
r, err = registry.NewDynamoDBRegistry(p, cfg.TXTOwnerID, dynamodb.NewFromConfig(aws.CreateDefaultV2Config(cfg), dynamodbOpts...), cfg.AWSDynamoDBTable, cfg.TXTPrefix, cfg.TXTSuffix, cfg.TXTWildcardReplacement, cfg.ManagedDNSRecordTypes, cfg.ExcludeDNSRecordTypes, []byte(cfg.TXTEncryptAESKey), cfg.TXTCacheInterval)
|
||||
case "noop":
|
||||
r, err = registry.NewNoopRegistry(p)
|
||||
case "txt":
|
||||
r, err = registry.NewTXTRegistry(p, cfg.TXTPrefix, cfg.TXTSuffix, cfg.TXTOwnerID, cfg.TXTCacheInterval, cfg.TXTWildcardReplacement, cfg.ManagedDNSRecordTypes, cfg.ExcludeDNSRecordTypes, cfg.TXTEncryptEnabled, []byte(cfg.TXTEncryptAESKey))
|
||||
case "aws-sd":
|
||||
r, err = registry.NewAWSSDRegistry(p, cfg.TXTOwnerID)
|
||||
default:
|
||||
log.Fatalf("unknown registry: %s", cfg.Registry)
|
||||
}
|
||||
return r, err
|
||||
}
|
||||
|
||||
// buildSource creates and configures the source(s) for endpoint discovery based on the provided configuration.
|
||||
// It initializes the source configuration, generates the required sources, and combines them into a single,
|
||||
// deduplicated source. Returns the combined source or an error if source creation fails.
|
||||
func buildSource(ctx context.Context, cfg *externaldns.Config) (source.Source, error) {
|
||||
sourceCfg := source.NewSourceConfig(cfg)
|
||||
sources, err := source.ByNames(ctx, &source.SingletonClientGenerator{
|
||||
KubeConfig: cfg.KubeConfig,
|
||||
APIServerURL: cfg.APIServerURL,
|
||||
RequestTimeout: func() time.Duration {
|
||||
if cfg.UpdateEvents {
|
||||
return 0
|
||||
}
|
||||
return cfg.RequestTimeout
|
||||
}(),
|
||||
}, cfg.Sources, sourceCfg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Combine multiple sources into a single, deduplicated source.
|
||||
combinedSource := source.NewDedupSource(source.NewMultiSource(sources, sourceCfg.DefaultTargets, sourceCfg.ForceDefaultTargets))
|
||||
// Filter targets
|
||||
targetFilter := endpoint.NewTargetNetFilterWithExclusions(cfg.TargetNetFilter, cfg.ExcludeTargetNets)
|
||||
combinedSource = source.NewNAT64Source(combinedSource, cfg.NAT64Networks)
|
||||
combinedSource = source.NewTargetFilterSource(combinedSource, targetFilter)
|
||||
return combinedSource, nil
|
||||
}
|
||||
|
||||
// RegexDomainFilter overrides DomainFilter
|
||||
func createDomainFilter(cfg *externaldns.Config) *endpoint.DomainFilter {
|
||||
if cfg.RegexDomainFilter != nil && cfg.RegexDomainFilter.String() != "" {
|
||||
return endpoint.NewRegexDomainFilter(cfg.RegexDomainFilter, cfg.RegexDomainExclusion)
|
||||
} else {
|
||||
return endpoint.NewDomainFilterWithExclusions(cfg.DomainFilter, cfg.ExcludeDomains)
|
||||
}
|
||||
}
|
||||
|
||||
// handleSigterm listens for a SIGTERM signal and triggers the provided cancel function
|
||||
// to gracefully terminate the application. It logs a message when the signal is received.
|
||||
func handleSigterm(cancel func()) {
|
||||
signals := make(chan os.Signal, 1)
|
||||
signal.Notify(signals, syscall.SIGTERM)
|
||||
<-signals
|
||||
log.Info("Received SIGTERM. Terminating...")
|
||||
cancel()
|
||||
}
|
||||
|
||||
// serveMetrics starts an HTTP server that serves health and metrics endpoints.
|
||||
// The /healthz endpoint returns a 200 OK status to indicate the service is healthy.
|
||||
// The /metrics endpoint serves Prometheus metrics.
|
||||
// The server listens on the specified address and logs debug information about the endpoints.
|
||||
func serveMetrics(address string) {
|
||||
http.HandleFunc("/healthz", func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
_, _ = w.Write([]byte("OK"))
|
||||
})
|
||||
|
||||
log.Debugf("serving 'healthz' on '%s/healthz'", address)
|
||||
log.Debugf("serving 'metrics' on '%s/metrics'", address)
|
||||
log.Debugf("registered '%d' metrics", len(metrics.RegisterMetric.Metrics))
|
||||
|
||||
http.Handle("/metrics", promhttp.Handler())
|
||||
|
||||
log.Fatal(http.ListenAndServe(address, nil))
|
||||
}
|
||||
497
v0.18.0/controller/execute_test.go
Normal file
497
v0.18.0/controller/execute_test.go
Normal file
@ -0,0 +1,497 @@
|
||||
/*
|
||||
Copyright 2025 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 controller
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"os/signal"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"sigs.k8s.io/external-dns/endpoint"
|
||||
"sigs.k8s.io/external-dns/pkg/apis/externaldns"
|
||||
"sigs.k8s.io/external-dns/plan"
|
||||
"sigs.k8s.io/external-dns/provider"
|
||||
)
|
||||
|
||||
func TestSelectRegistry(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
cfg *externaldns.Config
|
||||
provider provider.Provider
|
||||
wantErr bool
|
||||
wantType string
|
||||
}{
|
||||
{
|
||||
name: "DynamoDB registry",
|
||||
cfg: &externaldns.Config{
|
||||
Registry: "dynamodb",
|
||||
AWSDynamoDBRegion: "us-west-2",
|
||||
AWSDynamoDBTable: "test-table",
|
||||
TXTOwnerID: "owner-id",
|
||||
TXTWildcardReplacement: "wildcard",
|
||||
ManagedDNSRecordTypes: []string{"A", "CNAME"},
|
||||
ExcludeDNSRecordTypes: []string{"TXT"},
|
||||
TXTCacheInterval: 60,
|
||||
},
|
||||
provider: &MockProvider{},
|
||||
wantErr: false,
|
||||
wantType: "DynamoDBRegistry",
|
||||
},
|
||||
{
|
||||
name: "Noop registry",
|
||||
cfg: &externaldns.Config{
|
||||
Registry: "noop",
|
||||
},
|
||||
provider: &MockProvider{},
|
||||
wantErr: false,
|
||||
wantType: "NoopRegistry",
|
||||
},
|
||||
{
|
||||
name: "TXT registry",
|
||||
cfg: &externaldns.Config{
|
||||
Registry: "txt",
|
||||
TXTPrefix: "prefix",
|
||||
TXTOwnerID: "owner-id",
|
||||
TXTCacheInterval: 60,
|
||||
TXTWildcardReplacement: "wildcard",
|
||||
ManagedDNSRecordTypes: []string{"A", "CNAME"},
|
||||
ExcludeDNSRecordTypes: []string{"TXT"},
|
||||
},
|
||||
provider: &MockProvider{},
|
||||
wantErr: false,
|
||||
wantType: "TXTRegistry",
|
||||
},
|
||||
{
|
||||
name: "AWS-SD registry",
|
||||
cfg: &externaldns.Config{
|
||||
Registry: "aws-sd",
|
||||
TXTOwnerID: "owner-id",
|
||||
},
|
||||
provider: &MockProvider{},
|
||||
wantErr: false,
|
||||
wantType: "AWSSDRegistry",
|
||||
},
|
||||
{
|
||||
name: "Unknown registry",
|
||||
cfg: &externaldns.Config{
|
||||
Registry: "unknown",
|
||||
},
|
||||
provider: &MockProvider{},
|
||||
wantErr: true,
|
||||
wantType: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.wantErr {
|
||||
defer func() { log.StandardLogger().ExitFunc = nil }()
|
||||
b := new(bytes.Buffer)
|
||||
log.StandardLogger().ExitFunc = func(int) {}
|
||||
log.StandardLogger().SetOutput(b)
|
||||
|
||||
_, err := selectRegistry(tt.cfg, tt.provider)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, b.String(), "unknown registry: unknown")
|
||||
} else {
|
||||
reg, err := selectRegistry(tt.cfg, tt.provider)
|
||||
assert.NoError(t, err)
|
||||
assert.Contains(t, reflect.TypeOf(reg).String(), tt.wantType)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateDomainFilter(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
cfg *externaldns.Config
|
||||
expectedDomainFilter *endpoint.DomainFilter
|
||||
isConfigured bool
|
||||
}{
|
||||
{
|
||||
name: "RegexDomainFilter",
|
||||
cfg: &externaldns.Config{
|
||||
RegexDomainFilter: regexp.MustCompile(`example\.com`),
|
||||
RegexDomainExclusion: regexp.MustCompile(`excluded\.example\.com`),
|
||||
},
|
||||
expectedDomainFilter: endpoint.NewRegexDomainFilter(regexp.MustCompile(`example\.com`), regexp.MustCompile(`excluded\.example\.com`)),
|
||||
isConfigured: true,
|
||||
},
|
||||
{
|
||||
name: "RegexDomainWithoutExclusionFilter",
|
||||
cfg: &externaldns.Config{
|
||||
RegexDomainFilter: regexp.MustCompile(`example\.com`),
|
||||
},
|
||||
expectedDomainFilter: endpoint.NewRegexDomainFilter(regexp.MustCompile(`example\.com`), nil),
|
||||
isConfigured: true,
|
||||
},
|
||||
{
|
||||
name: "DomainFilterWithExclusions",
|
||||
cfg: &externaldns.Config{
|
||||
DomainFilter: []string{"example.com"},
|
||||
ExcludeDomains: []string{"excluded.example.com"},
|
||||
},
|
||||
expectedDomainFilter: endpoint.NewDomainFilterWithExclusions([]string{"example.com"}, []string{"excluded.example.com"}),
|
||||
isConfigured: true,
|
||||
},
|
||||
{
|
||||
name: "DomainFilterWithExclusionsOnly",
|
||||
cfg: &externaldns.Config{
|
||||
ExcludeDomains: []string{"excluded.example.com"},
|
||||
},
|
||||
expectedDomainFilter: endpoint.NewDomainFilterWithExclusions([]string{}, []string{"excluded.example.com"}),
|
||||
isConfigured: true,
|
||||
},
|
||||
{
|
||||
name: "EmptyDomainFilter",
|
||||
cfg: &externaldns.Config{
|
||||
DomainFilter: []string{},
|
||||
ExcludeDomains: []string{},
|
||||
},
|
||||
expectedDomainFilter: endpoint.NewDomainFilterWithExclusions([]string{}, []string{}),
|
||||
isConfigured: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
filter := createDomainFilter(tt.cfg)
|
||||
assert.Equal(t, tt.isConfigured, filter.IsConfigured())
|
||||
assert.Equal(t, tt.expectedDomainFilter, filter)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleSigterm(t *testing.T) {
|
||||
cancelCalled := make(chan bool, 1)
|
||||
cancel := func() {
|
||||
cancelCalled <- true
|
||||
}
|
||||
|
||||
var logOutput bytes.Buffer
|
||||
log.SetOutput(&logOutput)
|
||||
defer log.SetOutput(os.Stderr)
|
||||
|
||||
go handleSigterm(cancel)
|
||||
|
||||
// Simulate sending a SIGTERM signal
|
||||
sigChan := make(chan os.Signal, 1)
|
||||
signal.Notify(sigChan, syscall.SIGTERM)
|
||||
err := syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Wait for the cancel function to be called
|
||||
select {
|
||||
case <-cancelCalled:
|
||||
assert.Contains(t, logOutput.String(), "Received SIGTERM. Terminating...")
|
||||
case sig := <-sigChan:
|
||||
assert.Equal(t, syscall.SIGTERM, sig)
|
||||
case <-time.After(1 * time.Second):
|
||||
t.Fatal("cancel function was not called")
|
||||
}
|
||||
}
|
||||
|
||||
func getRandomPort() (int, error) {
|
||||
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
l, err := net.ListenTCP("tcp", addr)
|
||||
if err != nil {
|
||||
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)
|
||||
|
||||
resp, err = http.Get(fmt.Sprintf("http://%s/metrics", addresse))
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, http.StatusOK, resp.StatusCode)
|
||||
}
|
||||
|
||||
func TestConfigureLogger(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
cfg *externaldns.Config
|
||||
wantLevel log.Level
|
||||
wantJSON bool
|
||||
wantErr bool
|
||||
wantErrMsg string
|
||||
}{
|
||||
{
|
||||
name: "Default log format and level",
|
||||
cfg: &externaldns.Config{
|
||||
LogLevel: "info",
|
||||
LogFormat: "text",
|
||||
},
|
||||
wantLevel: log.InfoLevel,
|
||||
},
|
||||
{
|
||||
name: "JSON log format",
|
||||
cfg: &externaldns.Config{
|
||||
LogLevel: "debug",
|
||||
LogFormat: "json",
|
||||
},
|
||||
wantLevel: log.DebugLevel,
|
||||
wantJSON: true,
|
||||
},
|
||||
{
|
||||
name: "Invalid log level",
|
||||
cfg: &externaldns.Config{
|
||||
LogLevel: "invalid",
|
||||
LogFormat: "text",
|
||||
},
|
||||
wantLevel: log.InfoLevel,
|
||||
wantErr: true,
|
||||
wantErrMsg: "failed to parse log level",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.wantErr {
|
||||
defer func() { log.StandardLogger().ExitFunc = nil }()
|
||||
|
||||
b := new(bytes.Buffer)
|
||||
var captureLogFatal bool
|
||||
log.StandardLogger().ExitFunc = func(int) { captureLogFatal = true }
|
||||
log.StandardLogger().SetOutput(b)
|
||||
|
||||
configureLogger(tt.cfg)
|
||||
|
||||
assert.True(t, captureLogFatal)
|
||||
assert.Contains(t, b.String(), tt.wantErrMsg)
|
||||
} else {
|
||||
configureLogger(tt.cfg)
|
||||
assert.Equal(t, tt.wantLevel, log.GetLevel())
|
||||
|
||||
if tt.wantJSON {
|
||||
assert.IsType(t, &log.JSONFormatter{}, log.StandardLogger().Formatter)
|
||||
} else {
|
||||
assert.IsType(t, &log.TextFormatter{}, log.StandardLogger().Formatter)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildProvider(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
cfg *externaldns.Config
|
||||
expectedType string
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
name: "aws provider",
|
||||
cfg: &externaldns.Config{
|
||||
Provider: "aws",
|
||||
},
|
||||
expectedType: "*aws.AWSProvider",
|
||||
},
|
||||
{
|
||||
name: "rfc2136 provider",
|
||||
cfg: &externaldns.Config{
|
||||
Provider: "rfc2136",
|
||||
RFC2136TSIGSecretAlg: "hmac-sha256",
|
||||
},
|
||||
expectedType: "*rfc2136.rfc2136Provider",
|
||||
},
|
||||
{
|
||||
name: "gandi provider",
|
||||
cfg: &externaldns.Config{
|
||||
Provider: "gandi",
|
||||
},
|
||||
expectedError: "no environment variable GANDI_KEY or GANDI_PAT provided",
|
||||
},
|
||||
{
|
||||
name: "inmemory provider",
|
||||
cfg: &externaldns.Config{
|
||||
Provider: "inmemory",
|
||||
},
|
||||
expectedType: "*inmemory.InMemoryProvider",
|
||||
},
|
||||
{
|
||||
name: "inmemory cached provider",
|
||||
cfg: &externaldns.Config{
|
||||
Provider: "inmemory",
|
||||
ProviderCacheTime: 10 * time.Millisecond,
|
||||
},
|
||||
expectedType: "*provider.CachedProvider",
|
||||
},
|
||||
{
|
||||
name: "coredns provider",
|
||||
cfg: &externaldns.Config{
|
||||
Provider: "coredns",
|
||||
},
|
||||
expectedType: "coredns.coreDNSProvider",
|
||||
},
|
||||
{
|
||||
name: "pihole provider",
|
||||
cfg: &externaldns.Config{
|
||||
Provider: "pihole",
|
||||
PiholeApiVersion: "6",
|
||||
PiholeServer: "http://localhost:8080",
|
||||
},
|
||||
expectedType: "*pihole.PiholeProvider",
|
||||
},
|
||||
{
|
||||
name: "dnsimple provider",
|
||||
cfg: &externaldns.Config{
|
||||
Provider: "dnsimple",
|
||||
},
|
||||
expectedError: "no dnsimple oauth token provided",
|
||||
},
|
||||
{
|
||||
name: "unknown provider",
|
||||
cfg: &externaldns.Config{
|
||||
Provider: "unknown",
|
||||
},
|
||||
expectedError: "unknown dns provider: unknown",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
domainFilter := endpoint.NewDomainFilter([]string{"example.com"})
|
||||
|
||||
p, err := buildProvider(t.Context(), tt.cfg, domainFilter)
|
||||
|
||||
if tt.expectedError != "" {
|
||||
assert.Error(t, err)
|
||||
assert.EqualError(t, err, tt.expectedError)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, p)
|
||||
assert.Equal(t, tt.expectedType, reflect.TypeOf(p).String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildSource(t *testing.T) {
|
||||
svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNotImplemented)
|
||||
}))
|
||||
defer svr.Close()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
cfg *externaldns.Config
|
||||
expectedError bool
|
||||
}{
|
||||
{
|
||||
name: "Valid configuration with sources",
|
||||
cfg: &externaldns.Config{
|
||||
APIServerURL: svr.URL,
|
||||
Sources: []string{"fake"},
|
||||
RequestTimeout: 6 * time.Millisecond,
|
||||
},
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Empty sources configuration",
|
||||
cfg: &externaldns.Config{
|
||||
APIServerURL: svr.URL,
|
||||
Sources: []string{},
|
||||
RequestTimeout: 6 * time.Millisecond,
|
||||
},
|
||||
expectedError: false,
|
||||
},
|
||||
{
|
||||
name: "Update events enabled",
|
||||
cfg: &externaldns.Config{
|
||||
KubeConfig: "path-to-kubeconfig-not-exists",
|
||||
APIServerURL: svr.URL,
|
||||
Sources: []string{"ingress"},
|
||||
UpdateEvents: true,
|
||||
},
|
||||
expectedError: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
src, err := buildSource(t.Context(), tt.cfg)
|
||||
|
||||
if tt.expectedError {
|
||||
assert.Error(t, err)
|
||||
assert.Nil(t, src)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, src)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// mocks
|
||||
type MockProvider struct{}
|
||||
|
||||
func (m *MockProvider) Records(ctx context.Context) ([]*endpoint.Endpoint, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (p *MockProvider) ApplyChanges(ctx context.Context, changes *plan.Changes) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockProvider) AdjustEndpoints(endpoints []*endpoint.Endpoint) ([]*endpoint.Endpoint, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *MockProvider) GetDomainFilter() endpoint.DomainFilterInterface {
|
||||
return nil
|
||||
}
|
||||
54
v0.18.0/controller/metrics.go
Normal file
54
v0.18.0/controller/metrics.go
Normal file
@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright 2025 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 controller
|
||||
|
||||
import "sigs.k8s.io/external-dns/endpoint"
|
||||
|
||||
type metricsRecorder struct {
|
||||
counterPerEndpointType map[string]int
|
||||
}
|
||||
|
||||
func newMetricsRecorder() *metricsRecorder {
|
||||
return &metricsRecorder{
|
||||
counterPerEndpointType: map[string]int{
|
||||
endpoint.RecordTypeA: 0,
|
||||
endpoint.RecordTypeAAAA: 0,
|
||||
endpoint.RecordTypeCNAME: 0,
|
||||
endpoint.RecordTypeTXT: 0,
|
||||
endpoint.RecordTypeSRV: 0,
|
||||
endpoint.RecordTypeNS: 0,
|
||||
endpoint.RecordTypePTR: 0,
|
||||
endpoint.RecordTypeMX: 0,
|
||||
endpoint.RecordTypeNAPTR: 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (m *metricsRecorder) recordEndpointType(endpointType string) {
|
||||
m.counterPerEndpointType[endpointType]++
|
||||
}
|
||||
|
||||
func (m *metricsRecorder) getEndpointTypeCount(endpointType string) int {
|
||||
if count, ok := m.counterPerEndpointType[endpointType]; ok {
|
||||
return count
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (m *metricsRecorder) loadFloat64(endpointType string) float64 {
|
||||
return float64(m.getEndpointTypeCount(endpointType))
|
||||
}
|
||||
376
v0.18.0/controller/metrics_test.go
Normal file
376
v0.18.0/controller/metrics_test.go
Normal file
@ -0,0 +1,376 @@
|
||||
/*
|
||||
Copyright 2025 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 controller
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"sigs.k8s.io/external-dns/endpoint"
|
||||
"sigs.k8s.io/external-dns/internal/testutils"
|
||||
"sigs.k8s.io/external-dns/pkg/apis/externaldns"
|
||||
"sigs.k8s.io/external-dns/plan"
|
||||
"sigs.k8s.io/external-dns/registry"
|
||||
)
|
||||
|
||||
func TestRecordKnownEndpointType(t *testing.T) {
|
||||
mr := newMetricsRecorder()
|
||||
|
||||
// Recording a built-in type should start at 1 and increment
|
||||
mr.recordEndpointType(endpoint.RecordTypeA)
|
||||
assert.Equal(t, 1, mr.getEndpointTypeCount(endpoint.RecordTypeA))
|
||||
|
||||
mr.recordEndpointType(endpoint.RecordTypeA)
|
||||
assert.Equal(t, 2, mr.getEndpointTypeCount(endpoint.RecordTypeA))
|
||||
}
|
||||
|
||||
func TestRecordUnknownEndpointType(t *testing.T) {
|
||||
mr := newMetricsRecorder()
|
||||
const customType = "CUSTOM"
|
||||
|
||||
// Unknown types start at zero
|
||||
assert.Equal(t, 0, mr.getEndpointTypeCount(customType))
|
||||
|
||||
// First record sets to 1
|
||||
mr.recordEndpointType(customType)
|
||||
assert.Equal(t, 1, mr.getEndpointTypeCount(customType))
|
||||
|
||||
// Subsequent records increment
|
||||
mr.recordEndpointType(customType)
|
||||
assert.Equal(t, 2, mr.getEndpointTypeCount(customType))
|
||||
}
|
||||
|
||||
func TestLoadFloat64(t *testing.T) {
|
||||
mr := newMetricsRecorder()
|
||||
|
||||
// loadFloat64 should return the float64 representation of the count
|
||||
mr.recordEndpointType(endpoint.RecordTypeAAAA)
|
||||
assert.InDelta(t, float64(1), mr.loadFloat64(endpoint.RecordTypeAAAA), 0.0001)
|
||||
}
|
||||
|
||||
func TestVerifyARecords(t *testing.T) {
|
||||
testControllerFiltersDomains(
|
||||
t,
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "create-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
{
|
||||
DNSName: "some-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
},
|
||||
endpoint.NewDomainFilter([]string{"used.tld"}),
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "some-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
{
|
||||
DNSName: "create-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
},
|
||||
[]*plan.Changes{},
|
||||
)
|
||||
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 2, verifiedRecords.Gauge, map[string]string{"record_type": "a"})
|
||||
|
||||
testControllerFiltersDomains(
|
||||
t,
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "some-record.1.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
{
|
||||
DNSName: "some-record.2.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
{
|
||||
DNSName: "some-record.3.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"24.24.24.24"},
|
||||
},
|
||||
},
|
||||
endpoint.NewDomainFilter([]string{"used.tld"}),
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "some-record.1.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
{
|
||||
DNSName: "some-record.2.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
},
|
||||
[]*plan.Changes{{
|
||||
Create: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "some-record.3.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"24.24.24.24"},
|
||||
},
|
||||
},
|
||||
}},
|
||||
)
|
||||
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 2, verifiedRecords.Gauge, map[string]string{"record_type": "a"})
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 0, verifiedRecords.Gauge, map[string]string{"record_type": "aaaa"})
|
||||
}
|
||||
|
||||
func TestVerifyAAAARecords(t *testing.T) {
|
||||
testControllerFiltersDomains(
|
||||
t,
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "create-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeAAAA,
|
||||
Targets: endpoint.Targets{"2001:DB8::1"},
|
||||
},
|
||||
{
|
||||
DNSName: "some-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeAAAA,
|
||||
Targets: endpoint.Targets{"2001:DB8::2"},
|
||||
},
|
||||
},
|
||||
endpoint.NewDomainFilter([]string{"used.tld"}),
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "some-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeAAAA,
|
||||
Targets: endpoint.Targets{"2001:DB8::2"},
|
||||
},
|
||||
{
|
||||
DNSName: "create-record.used.tld",
|
||||
RecordType: endpoint.RecordTypeAAAA,
|
||||
Targets: endpoint.Targets{"2001:DB8::1"},
|
||||
},
|
||||
},
|
||||
[]*plan.Changes{},
|
||||
)
|
||||
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 2, verifiedRecords.Gauge, map[string]string{"record_type": "aaaa"})
|
||||
|
||||
testControllerFiltersDomains(
|
||||
t,
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "some-record.1.used.tld",
|
||||
RecordType: endpoint.RecordTypeAAAA,
|
||||
Targets: endpoint.Targets{"2001:DB8::1"},
|
||||
},
|
||||
{
|
||||
DNSName: "some-record.2.used.tld",
|
||||
RecordType: endpoint.RecordTypeAAAA,
|
||||
Targets: endpoint.Targets{"2001:DB8::2"},
|
||||
},
|
||||
{
|
||||
DNSName: "some-record.3.used.tld",
|
||||
RecordType: endpoint.RecordTypeAAAA,
|
||||
Targets: endpoint.Targets{"2001:DB8::3"},
|
||||
},
|
||||
},
|
||||
endpoint.NewDomainFilter([]string{"used.tld"}),
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "some-record.1.used.tld",
|
||||
RecordType: endpoint.RecordTypeAAAA,
|
||||
Targets: endpoint.Targets{"2001:DB8::1"},
|
||||
},
|
||||
{
|
||||
DNSName: "some-record.2.used.tld",
|
||||
RecordType: endpoint.RecordTypeAAAA,
|
||||
Targets: endpoint.Targets{"2001:DB8::2"},
|
||||
},
|
||||
},
|
||||
[]*plan.Changes{{
|
||||
Create: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "some-record.3.used.tld",
|
||||
RecordType: endpoint.RecordTypeAAAA,
|
||||
Targets: endpoint.Targets{"2001:DB8::3"},
|
||||
},
|
||||
},
|
||||
}},
|
||||
)
|
||||
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 0, verifiedRecords.Gauge, map[string]string{"record_type": "a"})
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 2, verifiedRecords.Gauge, map[string]string{"record_type": "aaaa"})
|
||||
}
|
||||
|
||||
func TestARecords(t *testing.T) {
|
||||
testControllerFiltersDomains(
|
||||
t,
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "record1.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
{
|
||||
DNSName: "record2.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
{
|
||||
DNSName: "_mysql-svc._tcp.mysql.used.tld",
|
||||
RecordType: endpoint.RecordTypeSRV,
|
||||
Targets: endpoint.Targets{"0 50 30007 mysql.used.tld"},
|
||||
},
|
||||
},
|
||||
endpoint.NewDomainFilter([]string{"used.tld"}),
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "record1.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"1.2.3.4"},
|
||||
},
|
||||
{
|
||||
DNSName: "_mysql-svc._tcp.mysql.used.tld",
|
||||
RecordType: endpoint.RecordTypeSRV,
|
||||
Targets: endpoint.Targets{"0 50 30007 mysql.used.tld"},
|
||||
},
|
||||
},
|
||||
[]*plan.Changes{{
|
||||
Create: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "record2.used.tld",
|
||||
RecordType: endpoint.RecordTypeA,
|
||||
Targets: endpoint.Targets{"8.8.8.8"},
|
||||
},
|
||||
},
|
||||
}},
|
||||
)
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 1, verifiedRecords.Gauge, map[string]string{"record_type": "a"})
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 0, verifiedRecords.Gauge, map[string]string{"record_type": "aaaa"})
|
||||
}
|
||||
|
||||
func TestAAAARecords(t *testing.T) {
|
||||
testControllerFiltersDomains(
|
||||
t,
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "record1.used.tld",
|
||||
RecordType: endpoint.RecordTypeAAAA,
|
||||
Targets: endpoint.Targets{"2001:DB8::1"},
|
||||
},
|
||||
{
|
||||
DNSName: "record2.used.tld",
|
||||
RecordType: endpoint.RecordTypeAAAA,
|
||||
Targets: endpoint.Targets{"2001:DB8::2"},
|
||||
},
|
||||
{
|
||||
DNSName: "_mysql-svc._tcp.mysql.used.tld",
|
||||
RecordType: endpoint.RecordTypeSRV,
|
||||
Targets: endpoint.Targets{"0 50 30007 mysql.used.tld"},
|
||||
},
|
||||
},
|
||||
endpoint.NewDomainFilter([]string{"used.tld"}),
|
||||
[]*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "record1.used.tld",
|
||||
RecordType: endpoint.RecordTypeAAAA,
|
||||
Targets: endpoint.Targets{"2001:DB8::1"},
|
||||
},
|
||||
{
|
||||
DNSName: "_mysql-svc._tcp.mysql.used.tld",
|
||||
RecordType: endpoint.RecordTypeSRV,
|
||||
Targets: endpoint.Targets{"0 50 30007 mysql.used.tld"},
|
||||
},
|
||||
},
|
||||
[]*plan.Changes{{
|
||||
Create: []*endpoint.Endpoint{
|
||||
{
|
||||
DNSName: "record2.used.tld",
|
||||
RecordType: endpoint.RecordTypeAAAA,
|
||||
Targets: endpoint.Targets{"2001:DB8::2"},
|
||||
},
|
||||
},
|
||||
}},
|
||||
)
|
||||
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 0, sourceRecords.Gauge, map[string]string{"record_type": "a"})
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 2, sourceRecords.Gauge, map[string]string{"record_type": "aaaa"})
|
||||
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 0, verifiedRecords.Gauge, map[string]string{"record_type": "a"})
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 1, verifiedRecords.Gauge, map[string]string{"record_type": "aaaa"})
|
||||
}
|
||||
|
||||
func TestGaugeMetricsWithMixedRecords(t *testing.T) {
|
||||
configuredEndpoints := testutils.GenerateTestEndpointsByType(map[string]int{
|
||||
endpoint.RecordTypeA: 534,
|
||||
endpoint.RecordTypeAAAA: 324,
|
||||
endpoint.RecordTypeCNAME: 2,
|
||||
endpoint.RecordTypeTXT: 56,
|
||||
endpoint.RecordTypeSRV: 11,
|
||||
endpoint.RecordTypeNS: 3,
|
||||
})
|
||||
|
||||
providerEndpoints := testutils.GenerateTestEndpointsByType(map[string]int{
|
||||
endpoint.RecordTypeA: 5334,
|
||||
endpoint.RecordTypeAAAA: 324,
|
||||
endpoint.RecordTypeCNAME: 23,
|
||||
endpoint.RecordTypeTXT: 6,
|
||||
endpoint.RecordTypeSRV: 25,
|
||||
endpoint.RecordTypeNS: 1,
|
||||
endpoint.RecordTypePTR: 43,
|
||||
})
|
||||
|
||||
cfg := externaldns.NewConfig()
|
||||
cfg.ManagedDNSRecordTypes = endpoint.KnownRecordTypes
|
||||
|
||||
source := new(testutils.MockSource)
|
||||
source.On("Endpoints").Return(configuredEndpoints, nil)
|
||||
|
||||
provider := &filteredMockProvider{
|
||||
RecordsStore: providerEndpoints,
|
||||
}
|
||||
r, err := registry.NewNoopRegistry(provider)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
ctrl := &Controller{
|
||||
Source: source,
|
||||
Registry: r,
|
||||
Policy: &plan.SyncPolicy{},
|
||||
DomainFilter: endpoint.NewDomainFilter([]string{}),
|
||||
ManagedRecordTypes: cfg.ManagedDNSRecordTypes,
|
||||
}
|
||||
|
||||
assert.NoError(t, ctrl.RunOnce(t.Context()))
|
||||
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 534, sourceRecords.Gauge, map[string]string{"record_type": "a"})
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 324, sourceRecords.Gauge, map[string]string{"record_type": "aaaa"})
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 0, sourceRecords.Gauge, map[string]string{"record_type": "cname"})
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 11, sourceRecords.Gauge, map[string]string{"record_type": "srv"})
|
||||
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 5334, registryRecords.Gauge, map[string]string{"record_type": "a"})
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 324, registryRecords.Gauge, map[string]string{"record_type": "aaaa"})
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 0, registryRecords.Gauge, map[string]string{"record_type": "mx"})
|
||||
testutils.TestHelperVerifyMetricsGaugeVectorWithLabels(t, 43, registryRecords.Gauge, map[string]string{"record_type": "ptr"})
|
||||
}
|
||||
3439
v0.18.0/docs/20190708-external-dns-incubator/index.html
Normal file
3439
v0.18.0/docs/20190708-external-dns-incubator/index.html
Normal file
File diff suppressed because it is too large
Load Diff
4
v0.18.0/docs/OWNERS
Normal file
4
v0.18.0/docs/OWNERS
Normal file
@ -0,0 +1,4 @@
|
||||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
labels:
|
||||
- docs
|
||||
3941
v0.18.0/docs/advanced/fqdn-templating/index.html
Normal file
3941
v0.18.0/docs/advanced/fqdn-templating/index.html
Normal file
File diff suppressed because it is too large
Load Diff
3105
v0.18.0/docs/advanced/nat64/index.html
Normal file
3105
v0.18.0/docs/advanced/nat64/index.html
Normal file
File diff suppressed because it is too large
Load Diff
3211
v0.18.0/docs/advanced/rate-limits/index.html
Normal file
3211
v0.18.0/docs/advanced/rate-limits/index.html
Normal file
File diff suppressed because it is too large
Load Diff
3784
v0.18.0/docs/advanced/ttl/index.html
Normal file
3784
v0.18.0/docs/advanced/ttl/index.html
Normal file
File diff suppressed because it is too large
Load Diff
3544
v0.18.0/docs/annotations/annotations/index.html
Normal file
3544
v0.18.0/docs/annotations/annotations/index.html
Normal file
File diff suppressed because it is too large
Load Diff
3095
v0.18.0/docs/contributing/chart/index.html
Normal file
3095
v0.18.0/docs/contributing/chart/index.html
Normal file
File diff suppressed because it is too large
Load Diff
3128
v0.18.0/docs/contributing/design/index.html
Normal file
3128
v0.18.0/docs/contributing/design/index.html
Normal file
File diff suppressed because it is too large
Load Diff
3608
v0.18.0/docs/contributing/dev-guide/index.html
Normal file
3608
v0.18.0/docs/contributing/dev-guide/index.html
Normal file
File diff suppressed because it is too large
Load Diff
3050
v0.18.0/docs/contributing/index.html
Normal file
3050
v0.18.0/docs/contributing/index.html
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user