1
0
mirror of https://github.com/go-acme/lego.git synced 2025-01-03 07:19:39 +02:00

chore: adds a new generator to create dns_provider.go (#2305)

This commit is contained in:
Ludovic Fernandez 2024-10-14 13:14:05 +02:00 committed by GitHub
parent 895a953590
commit d6c1ed9138
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 306 additions and 152 deletions

View File

@ -1,5 +1,45 @@
run:
timeout: 10m
linters:
enable-all: true
disable:
- gomnd # deprecated
- cyclop # duplicate of gocyclo
- sqlclosecheck # not relevant (SQL)
- rowserrcheck # not relevant (SQL)
- execinquery # not relevant (SQL)
- lll
- gosec
- dupl # not relevant
- prealloc # too many false-positive
- bodyclose # too many false-positive
- mnd
- testpackage # not relevant
- tparallel # not relevant
- paralleltest # not relevant
- nestif # too many false-positive
- wrapcheck
- err113 # not relevant
- nlreturn # not relevant
- wsl # not relevant
- exhaustive # not relevant
- exhaustruct # not relevant
- makezero # not relevant
- forbidigo
- varnamelen # not relevant
- nilnil # not relevant
- ireturn # not relevant
- contextcheck # too many false-positive
- tenv # we already have a test "framework" to handle env vars
- noctx
- forcetypeassert
- tagliatelle
- errname
- errchkjson
- nonamedreturns
- musttag # false-positive https://github.com/junk1tm/musttag/issues/17
- gosmopolitan # not relevant
- exportloopref # Useless with go1.22
- canonicalheader # Can create side effects in the context of API clients
- usestdlibvars # false-positive https://github.com/sashamelentyev/usestdlibvars/issues/96
linters-settings:
govet:
@ -96,50 +136,18 @@ linters-settings:
sprintf1: true
strconcat: false
linters:
enable-all: true
disable:
- gomnd # deprecated
- cyclop # duplicate of gocyclo
- sqlclosecheck # not relevant (SQL)
- rowserrcheck # not relevant (SQL)
- execinquery # not relevant (SQL)
- lll
- gosec
- dupl # not relevant
- prealloc # too many false-positive
- bodyclose # too many false-positive
- mnd
- testpackage # not relevant
- tparallel # not relevant
- paralleltest # not relevant
- nestif # too many false-positive
- wrapcheck
- err113 # not relevant
- nlreturn # not relevant
- wsl # not relevant
- exhaustive # not relevant
- exhaustruct # not relevant
- makezero # not relevant
- forbidigo
- varnamelen # not relevant
- nilnil # not relevant
- ireturn # not relevant
- contextcheck # too many false-positive
- tenv # we already have a test "framework" to handle env vars
- noctx
- forcetypeassert
- tagliatelle
- errname
- errchkjson
- nonamedreturns
- musttag # false-positive https://github.com/junk1tm/musttag/issues/17
- gosmopolitan # not relevant
- exportloopref # Useless with go1.22
- canonicalheader # Can create side effects in the context of API clients
- usestdlibvars # false-positive https://github.com/sashamelentyev/usestdlibvars/issues/96
run:
timeout: 10m
output:
show-stats: true
sort-results: true
sort-order:
- linter
- file
issues:
exclude-generated: strict
exclude-use-default: false
max-issues-per-linter: 0
max-same-issues: 0
@ -160,86 +168,96 @@ issues:
- path: providers/dns/dns_providers.go
linters:
- gocyclo
- path: providers/dns/gcloud/googlecloud_test.go
text: 'string `(lego\.wtf|manhattan)` has (\d+) occurrences, make it a constant'
- path: providers/dns/zoneee/zoneee_test.go
text: 'string `(bar|foo)` has (\d+) occurrences, make it a constant'
- path: certcrypto/crypto.go
text: '(tlsFeatureExtensionOID|ocspMustStapleFeature) is a global variable'
linters:
- gochecknoglobals
- path: challenge/dns01/nameserver.go
text: '(defaultNameservers|recursiveNameservers|fqdnSoaCache|muFqdnSoaCache) is a global variable'
linters:
- gochecknoglobals
- path: challenge/dns01/nameserver_.+.go
text: 'dnsTimeout is a global variable'
linters:
- gochecknoglobals
- path: challenge/dns01/nameserver_test.go
text: 'findXByFqdnTestCases is a global variable'
linters:
- gochecknoglobals
- path: challenge/http01/domain_matcher.go
text: 'string `Host` has \d occurrences, make it a constant'
linters:
- goconst
- path: challenge/http01/domain_matcher.go
text: 'cyclomatic complexity \d+ of func `parseForwardedHeader` is high'
linters:
- gocyclo
- path: challenge/http01/domain_matcher.go
text: "Function 'parseForwardedHeader' has too many statements"
linters:
- funlen
- path: challenge/tlsalpn01/tls_alpn_challenge.go
text: 'idPeAcmeIdentifierV1 is a global variable'
linters:
- gochecknoglobals
- path: log/logger.go
text: 'Logger is a global variable'
linters:
- gochecknoglobals
- path: 'e2e/(dnschallenge/)?[\d\w]+_test.go'
text: load is a global variable
linters:
- gochecknoglobals
- path: 'providers/dns/([\d\w]+/)*[\d\w]+_test.go'
text: 'envTest is a global variable'
linters:
- gochecknoglobals
- path: 'providers/http/([\d\w]+/)*[\d\w]+_test.go'
text: 'envTest is a global variable'
linters:
- gochecknoglobals
- path: providers/dns/namecheap/namecheap_test.go
text: 'testCases is a global variable'
linters:
- gochecknoglobals
- path: providers/dns/acmedns/acmedns_test.go
text: 'egTestAccount is a global variable'
linters:
- gochecknoglobals
- path: providers/http/memcached/memcached_test.go
text: 'memcachedHosts is a global variable'
- path: providers/dns/sakuracloud/client_test.go
text: 'cyclomatic complexity 13 of func `(TestDNSProvider_cleanupTXTRecord_concurrent|TestDNSProvider_addTXTRecord_concurrent)` is high'
- path: providers/dns/dns_providers.go
text: "Function 'NewDNSChallengeProviderByName' has too many statements"
- path: cmd/flags.go
text: "Function 'CreateFlags' is too long"
- path: certificate/certificates.go
text: "Function 'GetOCSP' is too long"
- path: providers/dns/otc/client.go
text: "Function 'loginRequest' is too long"
- path: providers/dns/gandi/gandi.go
text: "Function 'Present' is too long"
linters:
- gochecknoglobals
- path: cmd/zz_gen_cmd_dnshelp.go
linters:
- gocyclo
- funlen
- path: providers/dns/checkdomain/internal/types.go
text: '`payed` is a misspelling of `paid`'
- path: providers/dns/namecheap/namecheap_test.go
text: 'cognitive complexity (\d+) of func `TestDNSProvider_getHosts` is high'
linters:
- misspell
- path: platform/tester/env_test.go
linters:
- thelper
- path: providers/dns/oraclecloud/oraclecloud_test.go
text: 'SA1019: x509.EncryptPEMBlock has been deprecated since Go 1.16'
- path: challenge/http01/domain_matcher.go
text: 'yodaStyleExpr'
- path: providers/dns/dns_providers.go
text: 'Function name: NewDNSChallengeProviderByName,'
linters:
- staticcheck
- path: providers/dns/sakuracloud/wrapper.go
text: 'mu is a global variable'
- path: providers/dns/hosttech/internal/client_test.go
text: 'Duplicate words \(0\) found'
linters:
- gochecknoglobals
- path: cmd/cmd_renew.go
text: 'cyclomatic complexity \d+ of func `(renewForDomains|renewForCSR)` is high'
linters:
- gocyclo
- path: providers/dns/cpanel/cpanel.go
text: 'cyclomatic complexity 13 of func `\(\*DNSProvider\)\.CleanUp` is high'
linters:
- gocyclo
# Those elements have been replaced by non-exposed structures.
- path: providers/dns/linode/linode_test.go
linters:
- staticcheck
text: "SA1019: linodego\\.(DomainsPagedResponse|DomainRecordsPagedResponse) is deprecated"
output:
sort-results: true
sort-order:
- linter
- file

View File

@ -14,7 +14,7 @@ import (
"github.com/urfave/cli/v2"
)
const outputFile = "../../../docs/data/zz_cli_help.toml"
const outputFile = "../../docs/data/zz_cli_help.toml"
const baseTemplate = `# THIS FILE IS AUTO-GENERATED. PLEASE DO NOT EDIT.

View File

@ -0,0 +1,76 @@
package descriptors
import (
"os"
"path/filepath"
"github.com/BurntSushi/toml"
)
type Providers struct {
Providers []Provider
}
type Provider struct {
Name string // Real name of the DNS provider
Code string // DNS code
Aliases []string // DNS code aliases (for compatibility/deprecation)
Since string // First lego version
URL string // DNS provider URL
Description string // Provider summary
Example string // CLI example
Configuration *Configuration // Environment variables
Links *Links // Links
Additional string // Extra documentation
GeneratedFrom string // Source file
}
type Configuration struct {
Credentials map[string]string
Additional map[string]string
}
type Links struct {
API string
GoClient string
}
// GetProviderInformation extract provider information from TOML description files.
func GetProviderInformation(root string) (*Providers, error) {
models := &Providers{}
err := filepath.Walk(filepath.Join(root, "providers", "dns"), walker(root, models))
if err != nil {
return nil, err
}
return models, nil
}
func walker(root string, prs *Providers) func(string, os.FileInfo, error) error {
return func(path string, _ os.FileInfo, err error) error {
if err != nil {
return err
}
if filepath.Ext(path) != ".toml" {
return nil
}
m := Provider{}
m.GeneratedFrom, err = filepath.Rel(root, path)
if err != nil {
return err
}
_, err = toml.DecodeFile(path, &m)
if err != nil {
return err
}
prs.Providers = append(prs.Providers, m)
return nil
}
}

View File

@ -16,14 +16,14 @@ import (
"strings"
"text/template"
"github.com/BurntSushi/toml"
"github.com/go-acme/lego/v4/internal/dns/descriptors"
)
const (
root = "../../"
dnsPackage = root + "providers/dns"
mdTemplate = root + "internal/dnsdocs/dns.md.tmpl"
cliTemplate = root + "internal/dnsdocs/dns.go.tmpl"
root = "../../../"
mdTemplate = root + "internal/dns/docs/dns.md.tmpl"
cliTemplate = root + "internal/dns/docs/dns.go.tmpl"
cliOutput = root + "cmd/zz_gen_cmd_dnshelp.go"
docOutput = root + "docs/content/dns"
readmePath = root + "README.md"
@ -34,41 +34,20 @@ const (
endLine = "<!-- END DNS PROVIDERS LIST -->"
)
type Model struct {
Name string // Real name of the DNS provider
Code string // DNS code
Since string // First lego version
URL string // DNS provider URL
Description string // Provider summary
Example string // CLI example
Configuration *Configuration // Environment variables
Links *Links // Links
Additional string // Extra documentation
GeneratedFrom string // Source file
}
type Configuration struct {
Credentials map[string]string
Additional map[string]string
}
type Links struct {
API string
GoClient string
}
type Providers struct {
Providers []Model
}
func main() {
models := &Providers{}
err := filepath.Walk(dnsPackage, walker(models))
models, err := descriptors.GetProviderInformation(root)
if err != nil {
log.Fatal(err)
}
for _, m := range models.Providers {
// generate documentation
err = generateDocumentation(m)
if err != nil {
log.Fatal(err)
}
}
// generate CLI help
err = generateCLIHelp(models)
if err != nil {
@ -84,36 +63,7 @@ func main() {
fmt.Printf("Documentation for %d DNS providers has been generated.\n", len(models.Providers)+1)
}
func walker(prs *Providers) func(string, os.FileInfo, error) error {
return func(path string, _ os.FileInfo, err error) error {
if err != nil {
return err
}
if filepath.Ext(path) == ".toml" {
m := Model{}
m.GeneratedFrom, err = filepath.Rel(root, path)
if err != nil {
return err
}
_, err := toml.DecodeFile(path, &m)
if err != nil {
return err
}
prs.Providers = append(prs.Providers, m)
// generate documentation
return generateDocumentation(m)
}
return nil
}
}
func generateDocumentation(m Model) error {
func generateDocumentation(m descriptors.Provider) error {
filename := filepath.Join(docOutput, "zz_gen_"+m.Code+".md")
file, err := os.Create(filename)
@ -121,10 +71,12 @@ func generateDocumentation(m Model) error {
return err
}
defer func() { _ = file.Close() }()
return template.Must(template.ParseFiles(mdTemplate)).Execute(file, m)
}
func generateCLIHelp(models *Providers) error {
func generateCLIHelp(models *descriptors.Providers) error {
filename := filepath.Clean(cliOutput)
file, err := os.Create(filename)
@ -132,6 +84,8 @@ func generateCLIHelp(models *Providers) error {
return err
}
defer func() { _ = file.Close() }()
tlt := template.New(filepath.Base(cliTemplate)).Funcs(map[string]interface{}{
"safe": func(src string) string {
return strings.ReplaceAll(src, "`", "'")
@ -154,7 +108,7 @@ func generateCLIHelp(models *Providers) error {
return err
}
func generateReadMe(models *Providers) error {
func generateReadMe(models *descriptors.Providers) error {
maximum, lines := extractTableData(models)
file, err := os.Open(readmePath)
@ -203,7 +157,7 @@ func generateReadMe(models *Providers) error {
return os.WriteFile(readmePath, buffer.Bytes(), 0o666)
}
func extractTableData(models *Providers) (int, [][]string) {
func extractTableData(models *descriptors.Providers) (int, [][]string) {
readmePattern := "[%s](https://go-acme.github.io/lego/dns/%s/)"
items := []string{fmt.Sprintf(readmePattern, "Manual", "manual")}

View File

@ -0,0 +1,27 @@
// Code generated by 'make generate-dns'; DO NOT EDIT.
package dns
import (
"fmt"
"github.com/go-acme/lego/v4/challenge"
"github.com/go-acme/lego/v4/challenge/dns01"
{{- range $provider := .Providers }}
"github.com/go-acme/lego/v4/providers/dns/{{ cleanName $provider.Code }}"
{{- end}}
)
// NewDNSChallengeProviderByName Factory for DNS providers.
func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
switch name {
case "manual":
return dns01.NewDNSProviderManual()
{{- range $provider := .Providers }}
case "{{ $provider.Code }}"{{range $alias := $provider.Aliases }},"{{ $alias }}"{{end}}:
return {{ cleanName $provider.Code }}.NewDNSProvider()
{{- end}}
default:
return nil, fmt.Errorf("unrecognized DNS provider: %s", name)
}
}

View File

@ -0,0 +1,73 @@
package main
//go:generate go run .
import (
"bytes"
"fmt"
"go/format"
"log"
"os"
"path/filepath"
"strings"
"text/template"
"github.com/go-acme/lego/v4/internal/dns/descriptors"
)
const (
root = "../../../"
srcTemplate = "internal/dns/providers/dns_providers.go.tmpl"
outputPath = "providers/dns/zz_gen_dns_providers.go"
)
func main() {
err := generate()
if err != nil {
log.Fatal(err)
}
}
func generate() error {
info, err := descriptors.GetProviderInformation(root)
if err != nil {
return err
}
file, err := os.Create(filepath.Join(root, outputPath))
if err != nil {
return err
}
defer func() { _ = file.Close() }()
tmplFile := filepath.Join(root, srcTemplate)
tlt := template.New(filepath.Base(tmplFile)).Funcs(map[string]interface{}{
"cleanName": func(src string) string {
return strings.ReplaceAll(src, "-", "")
},
})
b := &bytes.Buffer{}
err = template.Must(tlt.ParseFiles(tmplFile)).Execute(b, info)
if err != nil {
return err
}
// gofmt
source, err := format.Source(b.Bytes())
if err != nil {
return err
}
_, err = file.Write(source)
if err != nil {
return err
}
fmt.Printf("Switch mapping for %d DNS providers has been generated.\n", len(info.Providers)+1)
return nil
}

View File

@ -2,6 +2,7 @@ Name = "Joohoi's ACME-DNS"
Description = ''''''
URL = "https://github.com/joohoi/acme-dns"
Code = "acme-dns"
Aliases = ["acmedns"] # TODO(ldez): remove "-" in v5
Since = "v1.1.0"
Example = '''

View File

@ -2,6 +2,7 @@ Name = "Domeneshop"
Description = ''''''
URL = "https://domene.shop"
Code = "domeneshop"
Aliases = ["domainnameshop"]
Since = "v4.3.0"
Example = '''

View File

@ -4,6 +4,7 @@ Akamai edgedns supersedes FastDNS; implementing a DNS provider for solving the D
'''
URL = "https://www.akamai.com/us/en/products/security/edge-dns.jsp"
Code = "edgedns"
Aliases = ["fastdns"] # "fastdns" is for compatibility with v3, must be dropped in v5
Since = "v3.9.0"
Example = '''

View File

@ -2,6 +2,7 @@ Name = "Linode (v4)"
Description = ''''''
URL = "https://www.linode.com/"
Code = "linode"
Aliases = ["linodev4"] # "linodev4" is for compatibility with v3, must be dropped in v5
Since = "v1.1.0"
Example = '''

View File

@ -1,3 +1,5 @@
// Code generated by 'make generate-dns'; DO NOT EDIT.
package dns
import (
@ -148,7 +150,9 @@ import (
// NewDNSChallengeProviderByName Factory for DNS providers.
func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
switch name {
case "acme-dns": // TODO(ldez): remove "-" in v5
case "manual":
return dns01.NewDNSProviderManual()
case "acme-dns", "acmedns":
return acmedns.NewDNSProvider()
case "alidns":
return alidns.NewDNSProvider()
@ -156,14 +160,14 @@ func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
return allinkl.NewDNSProvider()
case "arvancloud":
return arvancloud.NewDNSProvider()
case "azure":
return azure.NewDNSProvider()
case "azuredns":
return azuredns.NewDNSProvider()
case "auroradns":
return auroradns.NewDNSProvider()
case "autodns":
return autodns.NewDNSProvider()
case "azure":
return azure.NewDNSProvider()
case "azuredns":
return azuredns.NewDNSProvider()
case "bindman":
return bindman.NewDNSProvider()
case "bluecat":
@ -224,7 +228,7 @@ func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
return dynu.NewDNSProvider()
case "easydns":
return easydns.NewDNSProvider()
case "edgedns", "fastdns": // "fastdns" is for compatibility with v3, must be dropped in v5
case "edgedns", "fastdns":
return edgedns.NewDNSProvider()
case "efficientip":
return efficientip.NewDNSProvider()
@ -294,7 +298,7 @@ func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
return lightsail.NewDNSProvider()
case "limacity":
return limacity.NewDNSProvider()
case "linode", "linodev4": // "linodev4" is for compatibility with v3, must be dropped in v5
case "linode", "linodev4":
return linode.NewDNSProvider()
case "liquidweb":
return liquidweb.NewDNSProvider()
@ -304,8 +308,6 @@ func NewDNSChallengeProviderByName(name string) (challenge.Provider, error) {
return luadns.NewDNSProvider()
case "mailinabox":
return mailinabox.NewDNSProvider()
case "manual":
return dns01.NewDNSProviderManual()
case "metaname":
return metaname.NewDNSProvider()
case "mijnhost":