diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index d9d659696..6bdcae2ff 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -9,8 +9,12 @@ jobs: name: Markdown, Go and OAS runs-on: ubuntu-latest permissions: - contents: read # to fetch code (actions/checkout) + # Required: allow read access to the content for analysis. + contents: read + # For OAS check checks: write + # For go lang linter + pull-requests: read steps: - name: Check out code into the Go module directory @@ -40,11 +44,11 @@ jobs: # https://github.com/golangci/golangci-lint-action?tab=readme-ov-file#verify - name: Verify linter configuration and Lint go code - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@v7 with: verify: true args: --timeout=30m - version: v1.64 + version: v2.0 # Run Spectral - name: Lint OpenAPI spec diff --git a/.golangci.yml b/.golangci.yml index 69572734f..99b3dde04 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,69 +1,70 @@ -linters-settings: - exhaustive: - default-signifies-exhaustive: false - goimports: - local-prefixes: sigs.k8s.io/external-dns - misspell: - locale: US - revive: - ignore-generated-header: true - rules: - - name: confusing-naming - disabled: true - +version: "2" linters: - # please, do not use `enable-all`: it's deprecated and will be removed soon. - # inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint - disable-all: true + default: none enable: - dogsled - - gofmt - - goimports - goprintffuncname - govet - ineffassign - misspell - - rowserrcheck - - typecheck - - unconvert - - whitespace - revive - - unused - - gosimple + - rowserrcheck - staticcheck - -issues: - # Excluding configuration per-path, per-linter, per-text and per-source - exclude-files: - - endpoint/zz_generated.deepcopy.go - exclude-rules: - - path: _test\.go - linters: - - deadcode - - depguard - - dogsled - - gofmt - - goimports - - goprintffuncname - - gosimple - - govet - - ineffassign - - misspell - - nolintlint - - rowserrcheck - - staticcheck - - structcheck - - stylecheck - - typecheck - - unconvert - - unused - - varcheck - - whitespace - - path: source/ambassador_host.go - linters: [ typecheck ] - - path: source/contour_httpproxy.go - linters: [ typecheck ] - - path: source/f5_virtualserver.go - linters: [ typecheck ] - - path: source/kong_tcpingress.go - linters: [ typecheck ] + - unconvert + - unused + - whitespace + settings: + exhaustive: + default-signifies-exhaustive: false + misspell: + locale: US + revive: + rules: + - name: confusing-naming + disabled: true + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + rules: + - linters: + - deadcode + - depguard + - dogsled + - goprintffuncname + - govet + - ineffassign + - misspell + - nolintlint + - rowserrcheck + - staticcheck + - structcheck + - unconvert + - unused + - varcheck + - whitespace + path: _test\.go + paths: + - endpoint/zz_generated.deepcopy.go + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gofmt + - goimports + settings: + goimports: + local-prefixes: + - sigs.k8s.io/external-dns + exclusions: + generated: lax + paths: + - endpoint/zz_generated.deepcopy.go + - third_party$ + - builtin$ + - examples$ + - _test\.go diff --git a/Makefile b/Makefile index 9b2a4a6c6..8b0bd52fe 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ endif #? golangci-lint: Install golangci-lint tool golangci-lint: - @command -v golangci-lint > /dev/null || curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.64.5 + @command -v golangci-lint > /dev/null || curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.0.2 #? golangci-lint-verify: Verify golangci-lint configuration golangci-lint-verify: golangci-lint diff --git a/internal/gen/docs/flags/main.go b/internal/gen/docs/flags/main.go index 72238db79..dba89ee7d 100644 --- a/internal/gen/docs/flags/main.go +++ b/internal/gen/docs/flags/main.go @@ -55,7 +55,7 @@ func main() { flags := computeFlags() content, err := flags.generateMarkdownTable() if err != nil { - _ = fmt.Errorf("failed to generate markdown file '%s': %v\n", path, err.Error()) + _ = fmt.Errorf("failed to generate markdown file '%s': %v", path, err.Error()) } content = content + "\n" _ = utils.WriteToFile(path, content) diff --git a/pkg/rfc2317/arpa.go b/pkg/rfc2317/arpa.go index bd7cc88ef..f11bac100 100644 --- a/pkg/rfc2317/arpa.go +++ b/pkg/rfc2317/arpa.go @@ -72,17 +72,18 @@ func CidrToInAddr(cidr string) (string, error) { } // Handle IPv4 Class-full and IPv6: - if total == 32 { + switch total { + case 32: if bits%8 != 0 { return "", fmt.Errorf("IPv4 mask must be multiple of 8 bits") } toTrim = (total - bits) / 8 - } else if total == 128 { + case 128: if bits%4 != 0 { return "", fmt.Errorf("IPv6 mask must be multiple of 4 bits") } toTrim = (total - bits) / 4 - } else { + default: return "", fmt.Errorf("invalid address (not IPv4 or IPv6): %v", cidr) } diff --git a/provider/akamai/akamai.go b/provider/akamai/akamai.go index 290b423ae..bd36fd663 100644 --- a/provider/akamai/akamai.go +++ b/provider/akamai/akamai.go @@ -321,11 +321,12 @@ func newAkamaiRecordset(dnsName, recordType string, ttl int, targets []string) d // cleanTargets preps recordset rdata if necessary for EdgeDNS func cleanTargets(rtype string, targets ...string) []string { log.Debugf("Targets to clean: [%v]", targets) - if rtype == "CNAME" || rtype == "SRV" { + switch rtype { + case "CNAME", "SRV": for idx, target := range targets { targets[idx] = strings.TrimSuffix(target, ".") } - } else if rtype == "TXT" { + case "TXT": for idx, target := range targets { log.Debugf("TXT data to clean: [%s]", target) // need to embed text data in quotes. Make sure not piling on @@ -359,7 +360,7 @@ func trimTxtRdata(rdata []string, rtype string) []string { func ttlAsInt(src endpoint.TTL) int { var temp interface{} = int64(src) temp64 := temp.(int64) - var ttl int = edgeDNSRecordTTL + var ttl = edgeDNSRecordTTL if temp64 > 0 && temp64 <= int64(maxInt) { ttl = int(temp64) } diff --git a/provider/alibabacloud/alibaba_cloud.go b/provider/alibabacloud/alibaba_cloud.go index b89b83548..5183d443e 100644 --- a/provider/alibabacloud/alibaba_cloud.go +++ b/provider/alibabacloud/alibaba_cloud.go @@ -492,7 +492,7 @@ func (p *AlibabaCloudProvider) escapeTXTRecordValue(value string) string { func (p *AlibabaCloudProvider) unescapeTXTRecordValue(value string) string { if strings.HasPrefix(value, "heritage=") { - return fmt.Sprintf("\"%s\"", strings.Replace(value, ";", ",", -1)) + return fmt.Sprintf("\"%s\"", strings.ReplaceAll(value, ";", ",")) } return value } diff --git a/provider/cloudflare/cloudflare.go b/provider/cloudflare/cloudflare.go index db8a3c132..a163c4c7a 100644 --- a/provider/cloudflare/cloudflare.go +++ b/provider/cloudflare/cloudflare.go @@ -673,7 +673,7 @@ func (p *CloudFlareProvider) listDNSRecordsWithAutoPagination(ctx context.Contex records[newDNSRecordIndex(r)] = r } params.ResultInfo = resultInfo.Next() - if params.ResultInfo.Done() { + if params.Done() { break } } diff --git a/provider/gandi/gandi.go b/provider/gandi/gandi.go index bc06d862d..63b193f8f 100644 --- a/provider/gandi/gandi.go +++ b/provider/gandi/gandi.go @@ -54,7 +54,7 @@ type GandiProvider struct { func NewGandiProvider(ctx context.Context, domainFilter endpoint.DomainFilter, dryRun bool) (*GandiProvider, error) { key, ok_key := os.LookupEnv("GANDI_KEY") pat, ok_pat := os.LookupEnv("GANDI_PAT") - if !(ok_key || ok_pat) { + if !ok_key && !ok_pat { return nil, errors.New("no environment variable GANDI_KEY or GANDI_PAT provided") } if ok_key { diff --git a/provider/ovh/ovh.go b/provider/ovh/ovh.go index 22437697d..5b7eb8ee2 100644 --- a/provider/ovh/ovh.go +++ b/provider/ovh/ovh.go @@ -588,7 +588,7 @@ func (p OVHProvider) newOvhChangeUpdate(endpointsOld []*endpoint.Endpoint, endpo toInsertTarget := []string{} for _, target := range endpointsNew.Targets { - var toDelete int = -1 + var toDelete = -1 for i, record := range oldRecords { if target == record.Target { diff --git a/provider/plural/plural.go b/provider/plural/plural.go index a73c29059..9f5a77152 100644 --- a/provider/plural/plural.go +++ b/provider/plural/plural.go @@ -48,7 +48,7 @@ func NewPluralProvider(cluster, provider string) (*PluralProvider, error) { endpoint := os.Getenv("PLURAL_ENDPOINT") if token == "" { - return nil, fmt.Errorf("No plural access token provided, you must set the PLURAL_ACCESS_TOKEN env var") + return nil, fmt.Errorf("no plural access token provided, you must set the PLURAL_ACCESS_TOKEN env var") } config := &Config{ diff --git a/provider/provider.go b/provider/provider.go index 317a643ba..2fc03d281 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -30,7 +30,7 @@ import ( // SoftError is an error, that provider will only log as error instead // of fatal. It is meant for error propagation from providers to tell // that this is a transient error. -var SoftError error = errors.New("soft error") +var SoftError error = errors.New("soft error") //nolint:staticcheck // NewSoftErrorf creates a SoftError with formats according to a format specifier and returns the string as a func NewSoftErrorf(format string, a ...any) error { diff --git a/provider/tencentcloud/cloudapi/tencentapi.go b/provider/tencentcloud/cloudapi/tencentapi.go index 1c8338e07..7cc6e6d05 100644 --- a/provider/tencentcloud/cloudapi/tencentapi.go +++ b/provider/tencentcloud/cloudapi/tencentapi.go @@ -238,13 +238,14 @@ func (api *defaultTencentAPIService) ModifyRecord(request *dnspod.ModifyRecordRe func dealWithError(action Action, request string, err error) bool { log.Errorf("dealWithError %s/%s request: %s, error: %s.", action.Service, action.Name, request, err.Error()) if sdkError, ok := err.(*errors.TencentCloudSDKError); ok { - if sdkError.Code == "RequestLimitExceeded" { + switch sdkError.Code { + case "RequestLimitExceeded": return true - } else if sdkError.Code == "InternalError" || sdkError.Code == "ClientError.HttpStatusCodeError" { + case "InternalError", "ClientError.HttpStatusCodeError": return false - } else if sdkError.Code == "ClientError.NetworkError" { + case "ClientError.NetworkError": return false - } else if sdkError.Code == "AuthFailure.UnauthorizedOperation" || sdkError.Code == "UnauthorizedOperation.CamNoAuth" { + case "AuthFailure.UnauthorizedOperation", "UnauthorizedOperation.CamNoAuth": return false } return false diff --git a/provider/ultradns/ultradns.go b/provider/ultradns/ultradns.go index 6208f7a69..9303813c8 100644 --- a/provider/ultradns/ultradns.go +++ b/provider/ultradns/ultradns.go @@ -292,9 +292,10 @@ func (p *UltraDNSProvider) submitChanges(ctx context.Context, changes []*UltraDN for zoneName, changes := range zoneChanges { for _, change := range changes { - if change.ResourceRecordSetUltraDNS.RRType == "CNAME" { + switch change.ResourceRecordSetUltraDNS.RRType { + case "CNAME": cnameownerName = change.ResourceRecordSetUltraDNS.OwnerName - } else if change.ResourceRecordSetUltraDNS.RRType == "TXT" { + case "TXT": txtownerName = change.ResourceRecordSetUltraDNS.OwnerName } diff --git a/source/compatibility.go b/source/compatibility.go index 1953b76ca..d7f4351c8 100644 --- a/source/compatibility.go +++ b/source/compatibility.go @@ -89,7 +89,7 @@ func legacyEndpointsFromMoleculeService(svc *v1.Service) []*endpoint.Endpoint { return nil } - hostnameList := strings.Split(strings.Replace(hostnameAnnotation, " ", "", -1), ",") + hostnameList := strings.Split(strings.ReplaceAll(hostnameAnnotation, " ", ""), ",") for _, hostname := range hostnameList { // Create a corresponding endpoint for each configured external entrypoint. @@ -145,9 +145,9 @@ func legacyEndpointsFromDNSControllerNodePortService(svc *v1.Service, sc *servic var hostnameList []string if isExternal { - hostnameList = strings.Split(strings.Replace(hostnameAnnotation, " ", "", -1), ",") + hostnameList = strings.Split(strings.ReplaceAll(hostnameAnnotation, " ", ""), ",") } else { - hostnameList = strings.Split(strings.Replace(internalHostnameAnnotation, " ", "", -1), ",") + hostnameList = strings.Split(strings.ReplaceAll(internalHostnameAnnotation, " ", ""), ",") } for _, hostname := range hostnameList { @@ -186,10 +186,10 @@ func legacyEndpointsFromDNSControllerLoadBalancerService(svc *v1.Service) []*end var hostnameList []string if hasExternal { - hostnameList = append(hostnameList, strings.Split(strings.Replace(hostnameAnnotation, " ", "", -1), ",")...) + hostnameList = append(hostnameList, strings.Split(strings.ReplaceAll(hostnameAnnotation, " ", ""), ",")...) } if hasInternal { - hostnameList = append(hostnameList, strings.Split(strings.Replace(internalHostnameAnnotation, " ", "", -1), ",")...) + hostnameList = append(hostnameList, strings.Split(strings.ReplaceAll(internalHostnameAnnotation, " ", ""), ",")...) } for _, hostname := range hostnameList { diff --git a/source/crd.go b/source/crd.go index d15b176ed..70a724073 100644 --- a/source/crd.go +++ b/source/crd.go @@ -96,7 +96,7 @@ func NewCRDClientForAPIVersionKind(client kubernetes.Interface, kubeConfig, apiS scheme := runtime.NewScheme() addKnownTypes(scheme, groupVersion) - config.ContentConfig.GroupVersion = &groupVersion + config.GroupVersion = &groupVersion config.APIPath = "/apis" config.NegotiatedSerializer = serializer.WithoutConversionCodecFactory{CodecFactory: serializer.NewCodecFactory(scheme)} @@ -184,7 +184,7 @@ func (cs *crdSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error crdEndpoints := []*endpoint.Endpoint{} for _, ep := range dnsEndpoint.Spec.Endpoints { if (ep.RecordType == "CNAME" || ep.RecordType == "A" || ep.RecordType == "AAAA") && len(ep.Targets) < 1 { - log.Warnf("Endpoint %s with DNSName %s has an empty list of targets", dnsEndpoint.ObjectMeta.Name, ep.DNSName) + log.Warnf("Endpoint %s with DNSName %s has an empty list of targets", dnsEndpoint.Name, ep.DNSName) continue } @@ -200,7 +200,7 @@ func (cs *crdSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error } } if illegalTarget { - log.Warnf("Endpoint %s with DNSName %s has an illegal target. The subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com')", dnsEndpoint.ObjectMeta.Name, ep.DNSName) + log.Warnf("Endpoint %s with DNSName %s has an illegal target. The subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com')", dnsEndpoint.Name, ep.DNSName) continue } @@ -231,7 +231,7 @@ func (cs *crdSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error func (cs *crdSource) setResourceLabel(crd *endpoint.DNSEndpoint, endpoints []*endpoint.Endpoint) { for _, ep := range endpoints { - ep.Labels[endpoint.ResourceLabelKey] = fmt.Sprintf("crd/%s/%s", crd.ObjectMeta.Namespace, crd.ObjectMeta.Name) + ep.Labels[endpoint.ResourceLabelKey] = fmt.Sprintf("crd/%s/%s", crd.Namespace, crd.Name) } } diff --git a/source/pod.go b/source/pod.go index 85f7a83d0..3a34a985b 100644 --- a/source/pod.go +++ b/source/pod.go @@ -152,7 +152,7 @@ func (ps *podSource) Endpoints(ctx context.Context) ([]*endpoint.Endpoint, error } if ps.podSourceDomain != "" { - domain := pod.ObjectMeta.Name + "." + ps.podSourceDomain + domain := pod.Name + "." + ps.podSourceDomain if len(targets) == 0 { addToEndpointMap(endpointMap, domain, suitableType(pod.Status.PodIP), pod.Status.PodIP) } diff --git a/source/service.go b/source/service.go index 1e6ed212b..e0f38c69a 100644 --- a/source/service.go +++ b/source/service.go @@ -694,7 +694,7 @@ func (sc *serviceSource) extractNodePortEndpoints(svc *v1.Service, hostname stri // take the service name from the K8s Service object // it is safe to use since it is DNS compatible // see https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names - serviceName := svc.ObjectMeta.Name + serviceName := svc.Name // figure out the protocol protocol := strings.ToLower(string(port.Protocol)) diff --git a/source/skipper_routegroup.go b/source/skipper_routegroup.go index d47682ba7..943b98862 100644 --- a/source/skipper_routegroup.go +++ b/source/skipper_routegroup.go @@ -315,7 +315,7 @@ func (sc *routeGroupSource) endpointsFromTemplate(rg *routeGroup) ([]*endpoint.E var endpoints []*endpoint.Endpoint // splits the FQDN template and removes the trailing periods - hostnameList := strings.Split(strings.Replace(hostnames, " ", "", -1), ",") + hostnameList := strings.Split(strings.ReplaceAll(hostnames, " ", ""), ",") for _, hostname := range hostnameList { hostname = strings.TrimSuffix(hostname, ".") endpoints = append(endpoints, endpointsForHostname(hostname, targets, ttl, providerSpecific, setIdentifier, resource)...) diff --git a/source/source.go b/source/source.go index 2f84dc81c..4641c056a 100644 --- a/source/source.go +++ b/source/source.go @@ -179,7 +179,7 @@ func getInternalHostnamesFromAnnotations(annotations map[string]string) []string } func splitHostnameAnnotation(annotation string) []string { - return strings.Split(strings.Replace(annotation, " ", "", -1), ",") + return strings.Split(strings.ReplaceAll(annotation, " ", ""), ",") } func getAliasFromAnnotations(annotations map[string]string) bool { @@ -251,7 +251,7 @@ func getTargetsFromTargetAnnotation(annotations map[string]string) endpoint.Targ targetAnnotation, exists := annotations[targetAnnotationKey] if exists && targetAnnotation != "" { // splits the hostname annotation and removes the trailing periods - targetsList := strings.Split(strings.Replace(targetAnnotation, " ", "", -1), ",") + targetsList := strings.Split(strings.ReplaceAll(targetAnnotation, " ", ""), ",") for _, targetHostname := range targetsList { targetHostname = strings.TrimSuffix(targetHostname, ".") targets = append(targets, targetHostname)