mirror of
https://github.com/StackExchange/dnscontrol.git
synced 2024-05-11 05:55:12 +00:00
DOCS: Migrated documentation website to Gitbook (#1809)
This commit is contained in:
committed by
GitHub
parent
f4388dd6ad
commit
f912b15adc
@@ -1,167 +1,281 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"html/template"
|
||||
"os"
|
||||
"sort"
|
||||
|
||||
"fmt"
|
||||
"github.com/StackExchange/dnscontrol/v3/providers"
|
||||
_ "github.com/StackExchange/dnscontrol/v3/providers/_all"
|
||||
"github.com/fbiville/markdown-table-formatter/pkg/markdown"
|
||||
"sort"
|
||||
)
|
||||
|
||||
func generateFeatureMatrix() error {
|
||||
allNames := map[string]bool{}
|
||||
for n := range providers.RegistrarTypes {
|
||||
allNames[n] = true
|
||||
matrix := matrixData()
|
||||
markdownTable, err := markdownTable(matrix)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for n := range providers.DNSProviderTypes {
|
||||
allNames[n] = true
|
||||
|
||||
fmt.Print(markdownTable)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func markdownTable(matrix *FeatureMatrix) (string, error) {
|
||||
var tableHeaders []string
|
||||
tableHeaders = append(tableHeaders, "Provider name")
|
||||
for _, featureName := range matrix.Features {
|
||||
tableHeaders = append(tableHeaders, featureName)
|
||||
}
|
||||
providerTypes := []string{}
|
||||
for n := range allNames {
|
||||
providerTypes = append(providerTypes, n)
|
||||
|
||||
var tableData [][]string
|
||||
for _, providerName := range allProviderNames() {
|
||||
featureMap := matrix.Providers[providerName]
|
||||
|
||||
var tableDataRow []string
|
||||
tableDataRow = append(tableDataRow, "`"+providerName+"`")
|
||||
for _, featureName := range matrix.Features {
|
||||
tableDataRow = append(tableDataRow, featureEmoji(featureMap, featureName))
|
||||
}
|
||||
tableData = append(tableData, tableDataRow)
|
||||
}
|
||||
sort.Strings(providerTypes)
|
||||
|
||||
var markdownTable, err = markdown.NewTableFormatterBuilder().
|
||||
Build(tableHeaders...).
|
||||
Format(tableData)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return markdownTable, nil
|
||||
}
|
||||
|
||||
func featureEmoji(
|
||||
featureMap FeatureMap,
|
||||
featureName string,
|
||||
) string {
|
||||
if featureMap[featureName] == nil {
|
||||
return "❔"
|
||||
}
|
||||
|
||||
if featureMap[featureName].HasFeature == true {
|
||||
return "✅"
|
||||
} else if featureMap[featureName].Unimplemented == true {
|
||||
return "❔"
|
||||
}
|
||||
return "❌"
|
||||
}
|
||||
|
||||
func matrixData() *FeatureMatrix {
|
||||
const (
|
||||
OfficialSupport = "Official Support"
|
||||
ProviderDnsProvider = "DNS Provider"
|
||||
ProviderRegistrar = "Registrar"
|
||||
DomainModifierAlias = "ALIAS"
|
||||
DomainModifierDnssec = "AUTODNSSEC"
|
||||
DomainModifierCaa = "CAA"
|
||||
DomainModifierPtr = "PTR"
|
||||
DomainModifierNaptr = "NAPTR"
|
||||
DomainModifierSoa = "SOA"
|
||||
DomainModifierSrv = "SRV"
|
||||
DomainModifierSshfp = "SSHFP"
|
||||
DomainModifierTlsa = "TLSA"
|
||||
DomainModifierDs = "DS"
|
||||
DualHost = "dual host"
|
||||
CreateDomains = "create-domains"
|
||||
NoPurge = "NO_PURGE"
|
||||
GetZones = "get-zones"
|
||||
)
|
||||
|
||||
matrix := &FeatureMatrix{
|
||||
Providers: map[string]FeatureMap{},
|
||||
Features: []FeatureDef{
|
||||
{"Official Support", "This means the provider is actively used at Stack Exchange, bugs are more likely to be fixed, and failing integration tests will block a release. See below for details"},
|
||||
{"DNS Provider", "Can manage and serve DNS zones"},
|
||||
{"Registrar", "The provider has registrar capabilities to set nameservers for zones"},
|
||||
{"ALIAS", "Provider supports some kind of ALIAS, ANAME or flattened CNAME record type"},
|
||||
{"AUTODNSSEC", "Provider can automatically manage DNSSEC"},
|
||||
{"CAA", "Provider can manage CAA records"},
|
||||
{"PTR", "Provider supports adding PTR records for reverse lookup zones"},
|
||||
{"NAPTR", "Provider can manage NAPTR records"},
|
||||
{"SOA", "Provider can manage SOA records"},
|
||||
{"SRV", "Driver has explicitly implemented SRV record management"},
|
||||
{"SSHFP", "Provider can manage SSHFP records"},
|
||||
{"TLSA", "Provider can manage TLSA records"},
|
||||
{"R53_ALIAS", "Provider supports Route 53 limited ALIAS"},
|
||||
{"AZURE_ALIAS", "Provider supports Azure DNS limited ALIAS"},
|
||||
{"DS", "Provider supports adding DS records"},
|
||||
{"AKAMAICDN", "Provider supports adding AKAMAICDN records"},
|
||||
|
||||
{"dual host", "This provider is recommended for use in 'dual hosting' scenarios. Usually this means the provider allows full control over the apex NS records"},
|
||||
{"create-domains", "This means the provider can automatically create domains that do not currently exist on your account. The 'dnscontrol create-domains' command will initialize any missing domains"},
|
||||
{"no_purge", "indicates you can use NO_PURGE macro to prevent deleting records not managed by dnscontrol. A few providers that generate the entire zone from scratch have a problem implementing this."},
|
||||
{"get-zones", "indicates the dnscontrol get-zones subcommand is implemented."},
|
||||
Features: []string{
|
||||
OfficialSupport,
|
||||
ProviderDnsProvider,
|
||||
ProviderRegistrar,
|
||||
DomainModifierAlias,
|
||||
DomainModifierDnssec,
|
||||
DomainModifierCaa,
|
||||
DomainModifierPtr,
|
||||
DomainModifierNaptr,
|
||||
DomainModifierSoa,
|
||||
DomainModifierSrv,
|
||||
DomainModifierSshfp,
|
||||
DomainModifierTlsa,
|
||||
DomainModifierDs,
|
||||
DualHost,
|
||||
CreateDomains,
|
||||
NoPurge,
|
||||
GetZones,
|
||||
},
|
||||
}
|
||||
for _, p := range providerTypes {
|
||||
if p == "NONE" {
|
||||
continue
|
||||
|
||||
for _, providerName := range allProviderNames() {
|
||||
featureMap := FeatureMap{}
|
||||
providerNotes := providers.Notes[providerName]
|
||||
if providerNotes == nil {
|
||||
providerNotes = providers.DocumentationNotes{}
|
||||
}
|
||||
fm := FeatureMap{}
|
||||
notes := providers.Notes[p]
|
||||
if notes == nil {
|
||||
notes = providers.DocumentationNotes{}
|
||||
}
|
||||
setCap := func(name string, cap providers.Capability) {
|
||||
if notes[cap] != nil {
|
||||
fm[name] = notes[cap]
|
||||
|
||||
setCapability := func(
|
||||
featureName string,
|
||||
capability providers.Capability,
|
||||
) {
|
||||
if providerNotes[capability] != nil {
|
||||
featureMap[featureName] = providerNotes[capability]
|
||||
return
|
||||
}
|
||||
fm.SetSimple(name, true, func() bool { return providers.ProviderHasCapability(p, cap) })
|
||||
featureMap.SetSimple(
|
||||
featureName,
|
||||
true,
|
||||
func() bool { return providers.ProviderHasCapability(providerName, capability) },
|
||||
)
|
||||
}
|
||||
setDoc := func(name string, cap providers.Capability, defaultNo bool) {
|
||||
if notes[cap] != nil {
|
||||
fm[name] = notes[cap]
|
||||
|
||||
setDocumentation := func(
|
||||
featureName string,
|
||||
capability providers.Capability,
|
||||
defaultNo bool,
|
||||
) {
|
||||
if providerNotes[capability] != nil {
|
||||
featureMap[featureName] = providerNotes[capability]
|
||||
} else if defaultNo {
|
||||
fm[name] = &providers.DocumentationNote{
|
||||
featureMap[featureName] = &providers.DocumentationNote{
|
||||
HasFeature: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
setDoc("Official Support", providers.DocOfficiallySupported, true)
|
||||
fm.SetSimple("DNS Provider", false, func() bool { return providers.DNSProviderTypes[p].Initializer != nil })
|
||||
fm.SetSimple("Registrar", false, func() bool { return providers.RegistrarTypes[p] != nil })
|
||||
setCap("AKAMAICDN", providers.CanUseAKAMAICDN)
|
||||
setCap("ALIAS", providers.CanUseAlias)
|
||||
setCap("AUTODNSSEC", providers.CanAutoDNSSEC)
|
||||
setCap("AZURE_ALIAS", providers.CanUseAzureAlias)
|
||||
setCap("CAA", providers.CanUseCAA)
|
||||
setCap("DS", providers.CanUseDS)
|
||||
setCap("NAPTR", providers.CanUseNAPTR)
|
||||
setCap("PTR", providers.CanUsePTR)
|
||||
setCap("R53_ALIAS", providers.CanUseRoute53Alias)
|
||||
setCap("SOA", providers.CanUseSOA)
|
||||
setCap("SRV", providers.CanUseSRV)
|
||||
setCap("SSHFP", providers.CanUseSSHFP)
|
||||
setCap("TLSA", providers.CanUseTLSA)
|
||||
setCap("get-zones", providers.CanGetZones)
|
||||
setDoc("create-domains", providers.DocCreateDomains, true)
|
||||
setDoc("dual host", providers.DocDualHost, false)
|
||||
|
||||
setDocumentation(
|
||||
OfficialSupport,
|
||||
providers.DocOfficiallySupported,
|
||||
true,
|
||||
)
|
||||
featureMap.SetSimple(
|
||||
ProviderDnsProvider,
|
||||
false,
|
||||
func() bool { return providers.DNSProviderTypes[providerName].Initializer != nil },
|
||||
)
|
||||
featureMap.SetSimple(
|
||||
ProviderRegistrar,
|
||||
false,
|
||||
func() bool { return providers.RegistrarTypes[providerName] != nil },
|
||||
)
|
||||
setCapability(
|
||||
DomainModifierAlias,
|
||||
providers.CanUseAlias,
|
||||
)
|
||||
setCapability(
|
||||
DomainModifierDnssec,
|
||||
providers.CanAutoDNSSEC,
|
||||
)
|
||||
setCapability(
|
||||
DomainModifierCaa,
|
||||
providers.CanUseCAA,
|
||||
)
|
||||
setCapability(
|
||||
DomainModifierDs,
|
||||
providers.CanUseDS,
|
||||
)
|
||||
setCapability(
|
||||
DomainModifierNaptr,
|
||||
providers.CanUseNAPTR,
|
||||
)
|
||||
setCapability(
|
||||
DomainModifierPtr,
|
||||
providers.CanUsePTR,
|
||||
)
|
||||
setCapability(
|
||||
DomainModifierSoa,
|
||||
providers.CanUseSOA,
|
||||
)
|
||||
setCapability(
|
||||
DomainModifierSrv,
|
||||
providers.CanUseSRV,
|
||||
)
|
||||
setCapability(
|
||||
DomainModifierSshfp,
|
||||
providers.CanUseSSHFP,
|
||||
)
|
||||
setCapability(
|
||||
DomainModifierTlsa,
|
||||
providers.CanUseTLSA,
|
||||
)
|
||||
setCapability(
|
||||
GetZones,
|
||||
providers.CanGetZones,
|
||||
)
|
||||
setDocumentation(
|
||||
CreateDomains,
|
||||
providers.DocCreateDomains,
|
||||
true,
|
||||
)
|
||||
setDocumentation(
|
||||
DualHost,
|
||||
providers.DocDualHost,
|
||||
false,
|
||||
)
|
||||
|
||||
// no purge is a freaky double negative
|
||||
cap := providers.CantUseNOPURGE
|
||||
if notes[cap] != nil {
|
||||
fm["no_purge"] = notes[cap]
|
||||
cantUseNOPURGE := providers.CantUseNOPURGE
|
||||
if providerNotes[cantUseNOPURGE] != nil {
|
||||
featureMap[NoPurge] = providerNotes[cantUseNOPURGE]
|
||||
} else {
|
||||
fm.SetSimple("no_purge", false, func() bool { return !providers.ProviderHasCapability(p, cap) })
|
||||
featureMap.SetSimple(
|
||||
NoPurge,
|
||||
false,
|
||||
func() bool { return !providers.ProviderHasCapability(providerName, cantUseNOPURGE) },
|
||||
)
|
||||
}
|
||||
matrix.Providers[p] = fm
|
||||
matrix.Providers[providerName] = featureMap
|
||||
}
|
||||
buf := &bytes.Buffer{}
|
||||
err := tmpl.Execute(buf, matrix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.WriteFile("docs/_includes/matrix.html", buf.Bytes(), 0644)
|
||||
return matrix
|
||||
}
|
||||
|
||||
// FeatureDef describes features.
|
||||
type FeatureDef struct {
|
||||
Name, Desc string
|
||||
func allProviderNames() []string {
|
||||
const ProviderNameNone = "NONE"
|
||||
|
||||
allProviderNames := map[string]bool{}
|
||||
for providerName := range providers.RegistrarTypes {
|
||||
if providerName == ProviderNameNone {
|
||||
continue
|
||||
}
|
||||
allProviderNames[providerName] = true
|
||||
}
|
||||
for providerName := range providers.DNSProviderTypes {
|
||||
if providerName == ProviderNameNone {
|
||||
continue
|
||||
}
|
||||
allProviderNames[providerName] = true
|
||||
}
|
||||
|
||||
var allProviderNamesAsString []string
|
||||
for providerName := range allProviderNames {
|
||||
allProviderNamesAsString = append(allProviderNamesAsString, providerName)
|
||||
}
|
||||
sort.Strings(allProviderNamesAsString)
|
||||
|
||||
return allProviderNamesAsString
|
||||
}
|
||||
|
||||
// FeatureMap maps provider names to compliance documentation.
|
||||
type FeatureMap map[string]*providers.DocumentationNote
|
||||
|
||||
// SetSimple configures a provider's setting in fm.
|
||||
func (fm FeatureMap) SetSimple(name string, unknownsAllowed bool, f func() bool) {
|
||||
// SetSimple configures a provider's setting in featureMap.
|
||||
func (featureMap FeatureMap) SetSimple(
|
||||
name string,
|
||||
unknownsAllowed bool,
|
||||
f func() bool,
|
||||
) {
|
||||
if f() {
|
||||
fm[name] = &providers.DocumentationNote{HasFeature: true}
|
||||
featureMap[name] = &providers.DocumentationNote{HasFeature: true}
|
||||
} else if !unknownsAllowed {
|
||||
fm[name] = &providers.DocumentationNote{HasFeature: false}
|
||||
featureMap[name] = &providers.DocumentationNote{HasFeature: false}
|
||||
}
|
||||
}
|
||||
|
||||
// FeatureMatrix describes features and which providers support it.
|
||||
type FeatureMatrix struct {
|
||||
Features []FeatureDef
|
||||
Features []string
|
||||
Providers map[string]FeatureMap
|
||||
}
|
||||
|
||||
var tmpl = template.Must(template.New("").Funcs(template.FuncMap{
|
||||
"safe": func(s string) template.HTML { return template.HTML(s) },
|
||||
}).Parse(`{% comment %}
|
||||
Matrix generated by build/generate/featureMatrix.go. DO NOT HAND EDIT!
|
||||
{% endcomment %}{{$providers := .Providers}}
|
||||
<figure class="full-width">
|
||||
<table class="table-header-rotated">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="row-header rotate"><div><span> </span></div></th>
|
||||
{{range $key,$val := $providers}}<th class="rotate"><div><span>{{$key}}</span></div></th>
|
||||
{{end -}}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .Features}}{{$name := .Name}}<tr>
|
||||
<th class="row-header" style="text-decoration: underline;" data-toggle="tooltip" data-container="body" data-placement="top" title="{{.Desc}}">{{$name}}</th>
|
||||
{{range $pname, $features := $providers}}{{$f := index $features $name}}{{if $f -}}
|
||||
<td class="{{if $f.HasFeature}}success{{else if $f.Unimplemented}}info{{else}}danger{{end}}"
|
||||
{{- if $f.Comment}} data-toggle="tooltip" data-container="body" data-placement="top" title="{{$f.Comment}}"{{end}}>
|
||||
{{if $f.Link}}<a href="{{$f.Link}}">{{end}}<i class="fa {{if and $f.Comment (not $f.Unimplemented)}}has-tooltip {{end}}
|
||||
{{- if $f.HasFeature}}fa-check text-success{{else if $f.Unimplemented}}fa-circle-o text-info{{else}}fa-times text-danger{{end}}" aria-hidden="true"></i>{{if $f.Link}}</a>{{end}}
|
||||
</td>
|
||||
{{- else}}<td><i class="fa fa-minus dim"></i></td>{{end}}
|
||||
{{end -}}
|
||||
</tr>
|
||||
{{end -}}
|
||||
</tbody>
|
||||
</table>
|
||||
</figure>
|
||||
`))
|
||||
|
@@ -54,7 +54,7 @@ var returnTypes = map[string]string{
|
||||
func generateFunctionTypes() (string, error) {
|
||||
funcs := []Function{}
|
||||
|
||||
srcRoot := join("docs", "_functions")
|
||||
srcRoot := join("docs", "functions")
|
||||
types, err := os.ReadDir(srcRoot)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -89,13 +89,13 @@ func generateFunctionTypes() (string, error) {
|
||||
}
|
||||
|
||||
body = body + "\n"
|
||||
body = strings.ReplaceAll(body, "{{site.github.url}}", "https://dnscontrol.org/")
|
||||
body = strings.ReplaceAll(body, "{% capture example %}", "")
|
||||
body = strings.ReplaceAll(body, "{% capture example2 %}", "")
|
||||
body = strings.ReplaceAll(body, "{% endcapture %}", "")
|
||||
body = strings.ReplaceAll(body, "{% include example.html content=example %}", "")
|
||||
body = strings.ReplaceAll(body, "{% include example.html content=example2 %}", "")
|
||||
body = strings.ReplaceAll(body, "](#", "](https://dnscontrol.org/js#")
|
||||
body = strings.ReplaceAll(body, "{% hint style=\"danger\" %}", "")
|
||||
body = strings.ReplaceAll(body, "{% hint style=\"info\" %}", "")
|
||||
body = strings.ReplaceAll(body, "{% hint style=\"success\" %}", "")
|
||||
body = strings.ReplaceAll(body, "{% hint style=\"warning\" %}", "")
|
||||
body = strings.ReplaceAll(body, "{% endhint %}", "")
|
||||
body = strings.ReplaceAll(body, "**NOTE**", "NOTE")
|
||||
body = strings.ReplaceAll(body, "**WARNING**", "WARNING")
|
||||
body = fixRuns(body)
|
||||
|
||||
paramNames := []string{}
|
||||
|
Reference in New Issue
Block a user