github.com/teknogeek/dnscontrol/v2@v2.10.1-0.20200227202244-ae299b55ba42/build/generate/featureMatrix.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "html/template" 6 "io/ioutil" 7 "sort" 8 9 "github.com/StackExchange/dnscontrol/v2/providers" 10 _ "github.com/StackExchange/dnscontrol/v2/providers/_all" 11 ) 12 13 func generateFeatureMatrix() error { 14 allNames := map[string]bool{} 15 for n := range providers.RegistrarTypes { 16 allNames[n] = true 17 } 18 for n := range providers.DNSProviderTypes { 19 allNames[n] = true 20 } 21 providerTypes := []string{} 22 for n := range allNames { 23 providerTypes = append(providerTypes, n) 24 } 25 sort.Strings(providerTypes) 26 matrix := &FeatureMatrix{ 27 Providers: map[string]FeatureMap{}, 28 Features: []FeatureDef{ 29 {"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"}, 30 {"DNS Provider", "Can manage and serve DNS zones"}, 31 {"Registrar", "The provider has registrar capabilities to set nameservers for zones"}, 32 {"ALIAS", "Provider supports some kind of ALIAS, ANAME or flattened CNAME record type"}, 33 {"AUTODNSSEC", "Provider can automatically manage DNSSEC"}, 34 {"CAA", "Provider can manage CAA records"}, 35 {"PTR", "Provider supports adding PTR records for reverse lookup zones"}, 36 {"NAPTR", "Provider can manage NAPTR records"}, 37 {"SRV", "Driver has explicitly implemented SRV record management"}, 38 {"SSHFP", "Provider can manage SSHFP records"}, 39 {"TLSA", "Provider can manage TLSA records"}, 40 {"TXTMulti", "Provider can manage TXT records with multiple strings"}, 41 {"R53_ALIAS", "Provider supports Route 53 limited ALIAS"}, 42 43 {"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"}, 44 {"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"}, 45 {"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."}, 46 {"get-zones", "indicates the dnscontrol get-zones subcommand is implemented."}, 47 }, 48 } 49 for _, p := range providerTypes { 50 if p == "NONE" { 51 continue 52 } 53 fm := FeatureMap{} 54 notes := providers.Notes[p] 55 if notes == nil { 56 notes = providers.DocumentationNotes{} 57 } 58 setCap := func(name string, cap providers.Capability) { 59 if notes[cap] != nil { 60 fm[name] = notes[cap] 61 return 62 } 63 fm.SetSimple(name, true, func() bool { return providers.ProviderHasCapability(p, cap) }) 64 } 65 setDoc := func(name string, cap providers.Capability, defaultNo bool) { 66 if notes[cap] != nil { 67 fm[name] = notes[cap] 68 } else if defaultNo { 69 fm[name] = &providers.DocumentationNote{ 70 HasFeature: false, 71 } 72 } 73 } 74 setDoc("Official Support", providers.DocOfficiallySupported, true) 75 fm.SetSimple("DNS Provider", false, func() bool { return providers.DNSProviderTypes[p] != nil }) 76 fm.SetSimple("Registrar", false, func() bool { return providers.RegistrarTypes[p] != nil }) 77 setCap("ALIAS", providers.CanUseAlias) 78 setCap("AUTODNSSEC", providers.CanAutoDNSSEC) 79 setCap("CAA", providers.CanUseCAA) 80 setCap("NAPTR", providers.CanUseNAPTR) 81 setCap("PTR", providers.CanUsePTR) 82 setCap("R53_ALIAS", providers.CanUseRoute53Alias) 83 setCap("SRV", providers.CanUseSRV) 84 setCap("SSHFP", providers.CanUseSSHFP) 85 setCap("TLSA", providers.CanUseTLSA) 86 setCap("TXTMulti", providers.CanUseTXTMulti) 87 setCap("get-zones", providers.CanGetZones) 88 setDoc("dual host", providers.DocDualHost, false) 89 setDoc("create-domains", providers.DocCreateDomains, true) 90 91 // no purge is a freaky double negative 92 cap := providers.CantUseNOPURGE 93 if notes[cap] != nil { 94 fm["no_purge"] = notes[cap] 95 } else { 96 fm.SetSimple("no_purge", false, func() bool { return !providers.ProviderHasCapability(p, cap) }) 97 } 98 matrix.Providers[p] = fm 99 } 100 buf := &bytes.Buffer{} 101 err := tmpl.Execute(buf, matrix) 102 if err != nil { 103 return err 104 } 105 return ioutil.WriteFile("docs/_includes/matrix.html", buf.Bytes(), 0644) 106 } 107 108 // FeatureDef describes features. 109 type FeatureDef struct { 110 Name, Desc string 111 } 112 113 // FeatureMap maps provider names to compliance documentation. 114 type FeatureMap map[string]*providers.DocumentationNote 115 116 // SetSimple configures a provider's setting in fm. 117 func (fm FeatureMap) SetSimple(name string, unknownsAllowed bool, f func() bool) { 118 if f() { 119 fm[name] = &providers.DocumentationNote{HasFeature: true} 120 } else if !unknownsAllowed { 121 fm[name] = &providers.DocumentationNote{HasFeature: false} 122 } 123 } 124 125 // FeatureMatrix describes features and which providers support it. 126 type FeatureMatrix struct { 127 Features []FeatureDef 128 Providers map[string]FeatureMap 129 } 130 131 var tmpl = template.Must(template.New("").Funcs(template.FuncMap{ 132 "safe": func(s string) template.HTML { return template.HTML(s) }, 133 }).Parse(` 134 {% comment %} 135 Matrix generated by build/generate/featureMatrix.go. DO NOT HAND EDIT! 136 {% endcomment %}{{$providers := .Providers}} 137 <table class="table-header-rotated"> 138 <thead> 139 <tr> 140 <th></th> 141 {{range $key,$val := $providers}}<th class="rotate"><div><span>{{$key}}</span></div></th> 142 {{end -}} 143 </tr> 144 </thead> 145 <tbody> 146 {{range .Features}}{{$name := .Name}}<tr> 147 <th class="row-header" style="text-decoration: underline;" data-toggle="tooltip" data-container="body" data-placement="top" title="{{.Desc}}">{{$name}}</th> 148 {{range $pname, $features := $providers}}{{$f := index $features $name}}{{if $f -}} 149 <td class="{{if $f.HasFeature}}success{{else if $f.Unimplemented}}info{{else}}danger{{end}}" 150 {{- if $f.Comment}} data-toggle="tooltip" data-container="body" data-placement="top" title="{{$f.Comment}}"{{end}}> 151 {{if $f.Link}}<a href="{{$f.Link}}">{{end}}<i class="fa {{if and $f.Comment (not $f.Unimplemented)}}has-tooltip {{end}} 152 {{- 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}} 153 </td> 154 {{- else}}<td><i class="fa fa-minus dim"></i></td>{{end}} 155 {{end -}} 156 </tr> 157 {{end -}} 158 </tbody> 159 </table> 160 `))