coredns.io/bin/sync.go

226 lines
4.9 KiB
Go

package main
import (
"bufio"
"bytes"
"flag"
"io/ioutil"
"log"
"os"
"path"
"strings"
"time"
"github.com/BurntSushi/toml"
)
const (
pageDir = "content/plugins/"
)
type page struct {
header meta
content string
}
type meta struct {
Title string `toml:"title"`
Description string `toml:"description"`
Weight int `toml:"weight"`
Tags []string `toml:"tags"`
Categories []string `toml:"categories"`
Date string `toml:"date"`
}
var (
pluginDir = flag.String("plugindir", ".coredns/plugin", "directory where to find coredns")
)
func main() {
flag.Parse()
// Current pages
pages, err := getPages(pageDir)
if err != nil {
log.Fatalf("Failed getting all page contents: %s", err)
}
// Incoming content
plugins, err := getContent(*pluginDir)
if err != nil {
log.Fatalf("Failed getting all plugin contents: %s", err)
}
neg, pos := compare(plugins, pages)
if neg == nil && pos == nil {
log.Printf("Nothing to update.")
}
// Remove any plugin files not present upstream
for _, p := range neg {
path := path.Join(pageDir, p)
err := os.Remove(path + ".md")
if err != nil {
log.Fatalf("Error deleting file file %s: %s", path, err)
}
log.Printf("Removed content file: %s", path+".md")
}
// Overwrite/create necessary content files with toml header
for _, p := range pos {
h := plugins[p].header
h.Date = time.Now().UTC().Format("2006-01-02T15:04:05.877581")
h.Tags = []string{"plugin", h.Title}
h.Categories = []string{"plugin"}
var buf bytes.Buffer
err := toml.NewEncoder(&buf).Encode(h)
if err != nil {
log.Fatalf("Error creating TOML header data: %s", err)
}
headerData := buf.String()
contentData := plugins[p].content
filePath := path.Join(pageDir, p)
fileContent := strings.Join([]string{"", headerData, contentData}, "+++\n")
err = ioutil.WriteFile(filePath+".md", []byte(fileContent), 0644)
if err != nil {
log.Fatalf("Error writing file: %s", err)
}
log.Printf("Wrote content changes %s to %s", path.Join(*pluginDir, p, "README.md"), filePath)
}
}
// Get current content pages from hugo content directory
// Returned map doesn't include header data as this isn't needed currently
func getPages(pageDir string) (pages map[string]page, err error) {
pages = make(map[string]page)
pd, err := ioutil.ReadDir(pageDir)
if err != nil {
return nil, err
}
for _, p := range pd {
if p.IsDir() {
continue
}
path := path.Join(pageDir, p.Name())
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
var content string
headerSeparator := 0
scanner := bufio.NewScanner(file)
for scanner.Scan() {
if headerSeparator == 2 {
content += scanner.Text() + "\n"
}
if scanner.Text() == "+++" {
headerSeparator++
}
}
pageData := page{content: content}
pages[strings.Replace(p.Name(), ".md", "", -1)] = pageData
}
return pages, nil
}
// Get latest content from coreDNS code directory
func getContent(pluginDir string) (plugins map[string]page, err error) {
plugins = make(map[string]page)
pl, err := ioutil.ReadDir(pluginDir)
if err != nil {
return nil, err
}
weight := 0
for _, p := range pl {
if !p.IsDir() {
continue
}
if getBlacklist()[p.Name()] {
continue
}
weight++
path := path.Join(pluginDir, p.Name(), "README.md")
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
var header meta
var content string
headerStarted := false
contentStarted := false
scanner := bufio.NewScanner(file)
for scanner.Scan() {
if contentStarted {
content += scanner.Text() + "\n"
}
if headerStarted && scanner.Text() != "" {
rawHeader := strings.Split(scanner.Text(), " - ")
title := strings.Replace(rawHeader[0], "*", "", -1)
header.Title = title
header.Description = strings.Join([]string{"*", title, "* ", rawHeader[1]}, "")
header.Weight = weight
headerStarted = false
contentStarted = true
}
if scanner.Text() == "## Name" {
headerStarted = true
}
}
pluginData := page{header: header, content: content}
plugins[p.Name()] = pluginData
}
return plugins, nil
}
// Compare current and incoming state
// Return a negative list to delete
// Return a positive list to create/overwrite
func compare(plugins map[string]page, pages map[string]page) (neg []string, pos []string) {
// Prepare list of pages to delete
for k := range pages {
if _, ok := plugins[k]; !ok {
neg = append(neg, k)
}
}
// Prepare list of pages to create
for k := range plugins {
// New pages to create
if _, ok := pages[k]; !ok {
pos = append(pos, k)
}
// Check necessity for an update
if plugins[k].content != pages[k].content {
pos = append(pos, k)
}
}
return neg, pos
}
// Return directory blacklist
func getBlacklist() map[string]bool {
var bl = map[string]bool{
"test": true,
"pkg": true,
"deprecated": true,
}
return bl
}