• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kubernetes-sigs / external-dns / 13883501058

16 Mar 2025 12:45PM UTC coverage: 70.244% (-0.8%) from 71.038%
13883501058

Pull #5186

github

ivankatliarchuk
chore(source): code cleanup to reduce coupling

Signed-off-by: ivan katliarchuk <ivan.katliarchuk@gmail.com>
Pull Request #5186: WIP chore(source): code cleanup

39 of 237 new or added lines in 15 files covered. (16.46%)

1 existing line in 1 file now uncovered.

14131 of 20117 relevant lines covered (70.24%)

670.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/source/utils/utils.go
1
package utils
2

3
import (
4
        "fmt"
5
        "net/netip"
6
        "strconv"
7
        "strings"
8
        "time"
9

10
        log "github.com/sirupsen/logrus"
11
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12
        "k8s.io/apimachinery/pkg/labels"
13
        "sigs.k8s.io/external-dns/endpoint"
14
)
15

16
// TTLFromAnnotations TODO: copied from source.go. Refactor to avoid duplication.
17
// TTLFromAnnotations extracts the TTL from the annotations of the given resource.
NEW
18
func TTLFromAnnotations(annotations map[string]string, resource string) endpoint.TTL {
×
NEW
19
        ttlNotConfigured := endpoint.TTL(0)
×
NEW
20
        ttlAnnotation, exists := annotations[ttlAnnotationKey]
×
NEW
21
        if !exists {
×
NEW
22
                return ttlNotConfigured
×
NEW
23
        }
×
NEW
24
        ttlValue, err := parseTTL(ttlAnnotation)
×
NEW
25
        if err != nil {
×
NEW
26
                log.Warnf("%s: \"%v\" is not a valid TTL value: %v", resource, ttlAnnotation, err)
×
NEW
27
                return ttlNotConfigured
×
NEW
28
        }
×
NEW
29
        if ttlValue < ttlMinimum || ttlValue > ttlMaximum {
×
NEW
30
                log.Warnf("TTL value %q must be between [%d, %d]", ttlValue, ttlMinimum, ttlMaximum)
×
NEW
31
                return ttlNotConfigured
×
NEW
32
        }
×
NEW
33
        return endpoint.TTL(ttlValue)
×
34
}
35

36
// TODO: test
37
// TODO: copied from source.go. Refactor to avoid duplication.
38
// parseTTL parses TTL from string, returning duration in seconds.
39
// parseTTL supports both integers like "600" and durations based
40
// on Go Duration like "10m", hence "600" and "10m" represent the same value.
41
//
42
// Note: for durations like "1.5s" the fraction is omitted (resulting in 1 second
43
// for the example).
NEW
44
func parseTTL(s string) (ttlSeconds int64, err error) {
×
NEW
45
        ttlDuration, errDuration := time.ParseDuration(s)
×
NEW
46
        if errDuration != nil {
×
NEW
47
                ttlInt, err := strconv.ParseInt(s, 10, 64)
×
NEW
48
                if err != nil {
×
NEW
49
                        return 0, errDuration
×
NEW
50
                }
×
NEW
51
                return ttlInt, nil
×
52
        }
53

NEW
54
        return int64(ttlDuration.Seconds()), nil
×
55
}
56

NEW
57
func getAliasFromAnnotations(annotations map[string]string) bool {
×
NEW
58
        aliasAnnotation, exists := annotations[aliasAnnotationKey]
×
NEW
59
        return exists && aliasAnnotation == "true"
×
NEW
60
}
×
61

62
// suitableType returns the DNS resource record type suitable for the target.
63
// In this case type A/AAAA for IPs and type CNAME for everything else.
NEW
64
func suitableType(target string) string {
×
NEW
65
        netIP, err := netip.ParseAddr(target)
×
NEW
66
        if err == nil && netIP.Is4() {
×
NEW
67
                return endpoint.RecordTypeA
×
NEW
68
        } else if err == nil && netIP.Is6() {
×
NEW
69
                return endpoint.RecordTypeAAAA
×
NEW
70
        }
×
NEW
71
        return endpoint.RecordTypeCNAME
×
72
}
73

74
// TODO: test
NEW
75
func ParseIngress(ingress string) (namespace, name string, err error) {
×
NEW
76
        parts := strings.Split(ingress, "/")
×
NEW
77
        if len(parts) == 2 {
×
NEW
78
                namespace, name = parts[0], parts[1]
×
NEW
79
        } else if len(parts) == 1 {
×
NEW
80
                name = parts[0]
×
NEW
81
        } else {
×
NEW
82
                err = fmt.Errorf("invalid ingress name (name or namespace/name) found %q", ingress)
×
NEW
83
        }
×
84

NEW
85
        return
×
86
}
87

88
// TODO: test
NEW
89
func SelectorMatchesServiceSelector(selector, svcSelector map[string]string) bool {
×
NEW
90
        for k, v := range selector {
×
NEW
91
                if lbl, ok := svcSelector[k]; !ok || lbl != v {
×
NEW
92
                        return false
×
NEW
93
                }
×
94
        }
NEW
95
        return true
×
96
}
97

98
// TargetsFromTargetAnnotation gets endpoints from optional "target" annotation.
99
// Returns empty endpoints array if none are found.
NEW
100
func TargetsFromTargetAnnotation(annotations map[string]string) endpoint.Targets {
×
NEW
101
        var targets endpoint.Targets
×
NEW
102

×
NEW
103
        // Get the desired hostname of the ingress from the annotation.
×
NEW
104
        targetAnnotation, exists := annotations[targetAnnotationKey]
×
NEW
105
        if exists && targetAnnotation != "" {
×
NEW
106
                // splits the hostname annotation and removes the trailing periods
×
NEW
107
                targetsList := strings.Split(strings.Replace(targetAnnotation, " ", "", -1), ",")
×
NEW
108
                for _, targetHostname := range targetsList {
×
NEW
109
                        targetHostname = strings.TrimSuffix(targetHostname, ".")
×
NEW
110
                        targets = append(targets, targetHostname)
×
NEW
111
                }
×
112
        }
NEW
113
        return targets
×
114
}
115

116
// ParseAnnotationFilter parses an annotation filter string into a labels.Selector.
117
// Returns nil if the annotation filter is invalid.
NEW
118
func ParseAnnotationFilter(annotationFilter string) (labels.Selector, error) {
×
NEW
119
        labelSelector, err := metav1.ParseToLabelSelector(annotationFilter)
×
NEW
120
        if err != nil {
×
NEW
121
                return nil, err
×
NEW
122
        }
×
NEW
123
        selector, err := metav1.LabelSelectorAsSelector(labelSelector)
×
NEW
124
        if err != nil {
×
NEW
125
                return nil, err
×
NEW
126
        }
×
NEW
127
        return selector, nil
×
128
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc