1
0
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:
Jeffrey Cafferata
2023-01-20 13:56:20 +01:00
committed by GitHub
parent f4388dd6ad
commit f912b15adc
188 changed files with 145405 additions and 4728 deletions

View File

@@ -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>&nbsp;</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>
`))

View File

@@ -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{}