youtubebeat/vendor/github.com/elastic/beats/dev-tools/mage/config.go

156 lines
3.9 KiB
Go

// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package mage
import (
"io/ioutil"
"os"
"path/filepath"
"sort"
"strings"
"github.com/pkg/errors"
"gopkg.in/yaml.v2"
)
const moduleConfigTemplate = `
#========================== Modules configuration =============================
{{.BeatName}}.modules:
{{range $mod := .Modules}}
#{{$mod.Dashes}} {{$mod.Title | title}} Module {{$mod.Dashes}}
{{$mod.Config}}
{{- end}}
`
type moduleConfigTemplateData struct {
ID string
Title string
Dashes string
Config string
}
type moduleFieldsYmlData []struct {
Title string `json:"title"`
ShortConfig bool `json:"short_config"`
}
func readModuleFieldsYml(path string) (title string, useShort bool, err error) {
data, err := ioutil.ReadFile(path)
if err != nil {
return "", false, err
}
var fd moduleFieldsYmlData
if err = yaml.Unmarshal(data, &fd); err != nil {
return "", false, err
}
if len(fd) == 0 {
return "", false, errors.New("module not found in fields.yml")
}
return fd[0].Title, fd[0].ShortConfig, nil
}
// moduleDashes returns a string containing the correct number of dashes '-' to
// center the modules title in the middle of the line surrounded by an equal
// number of dashes on each side.
func moduleDashes(name string) string {
const (
lineLen = 80
headerLen = len("#")
titleSuffixLen = len(" Module ")
)
numDashes := lineLen - headerLen - titleSuffixLen - len(name)
numDashes /= 2
return strings.Repeat("-", numDashes)
}
// GenerateModuleReferenceConfig generates a reference config file and includes
// modules found from the given module dirs.
func GenerateModuleReferenceConfig(out string, moduleDirs ...string) error {
var moduleConfigs []moduleConfigTemplateData
for _, dir := range moduleDirs {
modules, err := ioutil.ReadDir(dir)
if err != nil {
return err
}
for _, modDirInfo := range modules {
if !modDirInfo.IsDir() {
continue
}
name := modDirInfo.Name()
// Get title from fields.yml.
title, _, err := readModuleFieldsYml(filepath.Join(dir, name, "_meta/fields.yml"))
if err != nil {
title = strings.Title(name)
}
// Prioritize config.reference.yml, but fallback to config.yml.
files := []string{
filepath.Join(dir, name, "_meta/config.reference.yml"),
filepath.Join(dir, name, "_meta/config.yml"),
}
var data []byte
for _, f := range files {
data, err = ioutil.ReadFile(f)
if err != nil {
if os.IsNotExist(err) {
continue
}
return err
}
break
}
if data == nil {
continue
}
moduleConfigs = append(moduleConfigs, moduleConfigTemplateData{
ID: name,
Title: title,
Dashes: moduleDashes(title),
Config: string(data),
})
}
}
// Sort them by their module dir name, but put system first.
sort.Slice(moduleConfigs, func(i, j int) bool {
// Bubble system to the top of the list.
if moduleConfigs[i].ID == "system" {
return true
} else if moduleConfigs[j].ID == "system" {
return false
}
return moduleConfigs[i].ID < moduleConfigs[j].ID
})
config := MustExpand(moduleConfigTemplate, map[string]interface{}{
"Modules": moduleConfigs,
})
return ioutil.WriteFile(out, []byte(config), 0644)
}