annotation with upper-case hostnames block further updates

Signed-off-by: Nick Jüttner <nick@juni.io>
This commit is contained in:
Nick Jüttner 2018-05-31 16:58:57 +02:00
parent 7e3363f110
commit efe46c429d
2 changed files with 52 additions and 11 deletions

View File

@ -17,7 +17,12 @@ limitations under the License.
package plan
import (
"fmt"
"regexp"
"strings"
"github.com/kubernetes-incubator/external-dns/endpoint"
log "github.com/sirupsen/logrus"
)
// Plan can convert a list of desired and current records to a series of create,
@ -77,17 +82,27 @@ type planTableRow struct {
}
func (t planTable) addCurrent(e *endpoint.Endpoint) {
if _, ok := t.rows[e.DNSName]; !ok {
t.rows[e.DNSName] = &planTableRow{}
dnsName, err := stripLowerName(e.DNSName)
if err != nil {
log.Errorf("Skipping endpoint %v", err)
return
}
t.rows[e.DNSName].current = e
if _, ok := t.rows[dnsName]; !ok {
t.rows[dnsName] = &planTableRow{}
}
t.rows[dnsName].current = e
}
func (t planTable) addCandidate(e *endpoint.Endpoint) {
if _, ok := t.rows[e.DNSName]; !ok {
t.rows[e.DNSName] = &planTableRow{}
dnsName, err := stripLowerName(e.DNSName)
if err != nil {
log.Errorf("Skipping endpoint %v", err)
return
}
t.rows[e.DNSName].candidates = append(t.rows[e.DNSName].candidates, e)
if _, ok := t.rows[dnsName]; !ok {
t.rows[dnsName] = &planTableRow{}
}
t.rows[dnsName].candidates = append(t.rows[dnsName].candidates, e)
}
// TODO: allows record type change, which might not be supported by all dns providers
@ -175,3 +190,16 @@ func shouldUpdateTTL(desired, current *endpoint.Endpoint) bool {
}
return desired.RecordTTL != current.RecordTTL
}
func stripLowerName(dnsName string) (string, error) {
dnsName = strings.ToLower(dnsName)
dnsName = strings.TrimSpace(dnsName)
reg, err := regexp.Compile(`^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$`)
if err != nil {
return "", err
}
if !reg.MatchString(dnsName) {
return "", fmt.Errorf("%s because dns record is invalid", dnsName)
}
return dnsName, nil
}

View File

@ -34,6 +34,8 @@ type PlanTestSuite struct {
bar127A *endpoint.Endpoint
bar127AWithTTL *endpoint.Endpoint
bar192A *endpoint.Endpoint
invalidV2Cname *endpoint.Endpoint
invalidWithTTL *endpoint.Endpoint
}
func (suite *PlanTestSuite) SetupTest() {
@ -102,6 +104,17 @@ func (suite *PlanTestSuite) SetupTest() {
endpoint.ResourceLabelKey: "ingress/default/bar-192",
},
}
suite.invalidV2Cname = &endpoint.Endpoint{
DNSName: "IamInvalid!",
Targets: endpoint.Targets{"v2"},
RecordType: "CNAME",
}
suite.invalidWithTTL = &endpoint.Endpoint{
DNSName: "5HW598OVOMBY!!!.cluster.juni.io",
Targets: endpoint.Targets{"127.0.0.1"},
RecordType: "A",
RecordTTL: 300,
}
}
func (suite *PlanTestSuite) TestSyncFirstRound() {
@ -147,7 +160,7 @@ func (suite *PlanTestSuite) TestSyncSecondRound() {
}
func (suite *PlanTestSuite) TestSyncSecondRoundMigration() {
current := []*endpoint.Endpoint{suite.fooV2CnameNoLabel}
current := []*endpoint.Endpoint{suite.fooV2CnameNoLabel, suite.invalidWithTTL}
desired := []*endpoint.Endpoint{suite.fooV2Cname, suite.fooV1Cname, suite.bar127A}
expectedCreate := []*endpoint.Endpoint{suite.bar127A}
expectedUpdateOld := []*endpoint.Endpoint{suite.fooV2CnameNoLabel}
@ -241,8 +254,8 @@ func (suite *PlanTestSuite) TestIdempotency() {
}
func (suite *PlanTestSuite) TestDifferentTypes() {
current := []*endpoint.Endpoint{suite.fooV1Cname}
desired := []*endpoint.Endpoint{suite.fooV2Cname, suite.fooA5}
current := []*endpoint.Endpoint{suite.fooV1Cname, suite.invalidV2Cname}
desired := []*endpoint.Endpoint{suite.fooV2Cname, suite.fooA5, suite.invalidV2Cname}
expectedCreate := []*endpoint.Endpoint{}
expectedUpdateOld := []*endpoint.Endpoint{suite.fooV1Cname}
expectedUpdateNew := []*endpoint.Endpoint{suite.fooA5}
@ -327,8 +340,8 @@ func (suite *PlanTestSuite) TestDuplicatedEndpointsForSameResourceReplace() {
//TODO: remove once multiple-target per endpoint is supported
func (suite *PlanTestSuite) TestDuplicatedEndpointsForSameResourceRetain() {
current := []*endpoint.Endpoint{suite.fooV1Cname, suite.bar192A}
desired := []*endpoint.Endpoint{suite.fooV1Cname, suite.fooV3CnameSameResource}
current := []*endpoint.Endpoint{suite.fooV1Cname, suite.bar192A, suite.invalidV2Cname}
desired := []*endpoint.Endpoint{suite.fooV1Cname, suite.fooV3CnameSameResource, suite.invalidV2Cname}
expectedCreate := []*endpoint.Endpoint{}
expectedUpdateOld := []*endpoint.Endpoint{}
expectedUpdateNew := []*endpoint.Endpoint{}