add all files from Hong
This commit is contained in:
40
cmds/coredhcp-generator/README.md
Normal file
40
cmds/coredhcp-generator/README.md
Normal file
@@ -0,0 +1,40 @@
|
||||
## CoreDHCP Generator
|
||||
|
||||
`coredhcp-generator` is a tool used to build CoreDHCP with the plugins you want.
|
||||
|
||||
Why is it even needed? Go is a compiled language with no dynamic loading
|
||||
support. In order to load a plugin, it has to be compiled in. We are happy to
|
||||
provide a standard [main.go](/cmds/coredhcp/main.go), and at the same time we
|
||||
don't want to include plugins that not everyone would use, otherwise the binary
|
||||
size would grow without control.
|
||||
|
||||
You can use `coredhcp-generator` to generate a `main.go` that includes all the
|
||||
plugins you wish. Just use it as follows:
|
||||
|
||||
```
|
||||
$ ./coredhcp-generator --from core-plugins.txt
|
||||
2019/11/21 23:32:04 Generating output file '/tmp/coredhcp547019106/coredhcp.go' with 7 plugin(s):
|
||||
2019/11/21 23:32:04 1) github.com/coredhcp/coredhcp/plugins/file
|
||||
2019/11/21 23:32:04 2) github.com/coredhcp/coredhcp/plugins/lease_time
|
||||
2019/11/21 23:32:04 3) github.com/coredhcp/coredhcp/plugins/netmask
|
||||
2019/11/21 23:32:04 4) github.com/coredhcp/coredhcp/plugins/range
|
||||
2019/11/21 23:32:04 5) github.com/coredhcp/coredhcp/plugins/router
|
||||
2019/11/21 23:32:04 6) github.com/coredhcp/coredhcp/plugins/server_id
|
||||
2019/11/21 23:32:04 7) github.com/coredhcp/coredhcp/plugins/dns
|
||||
2019/11/21 23:32:04 Generated file '/tmp/coredhcp547019106/coredhcp.go'. You can build it by running 'go build' in the output directory.
|
||||
```
|
||||
|
||||
You can also specify the plugin list on the command line, or mix it with
|
||||
`--from`:
|
||||
```
|
||||
$ ./coredhcp-generator --from core-plugins.txt \
|
||||
github.com/coredhcp/plugins/redis
|
||||
```
|
||||
|
||||
Notice that it created a file called `coredhcp.go` in a temporary directory. You
|
||||
can now `go build` that file and have your own custom CoreDHCP.
|
||||
|
||||
## Bugs
|
||||
|
||||
CoreDHCP uses Go versioned modules. The generated file does not do that yet. We
|
||||
will add this feature soon.
|
||||
15
cmds/coredhcp-generator/core-plugins.txt
Normal file
15
cmds/coredhcp-generator/core-plugins.txt
Normal file
@@ -0,0 +1,15 @@
|
||||
github.com/coredhcp/coredhcp/plugins/autoconfigure
|
||||
github.com/coredhcp/coredhcp/plugins/dns
|
||||
github.com/coredhcp/coredhcp/plugins/file
|
||||
github.com/coredhcp/coredhcp/plugins/ipv6only
|
||||
github.com/coredhcp/coredhcp/plugins/leasetime
|
||||
github.com/coredhcp/coredhcp/plugins/mtu
|
||||
github.com/coredhcp/coredhcp/plugins/netmask
|
||||
github.com/coredhcp/coredhcp/plugins/nbp
|
||||
github.com/coredhcp/coredhcp/plugins/prefix
|
||||
github.com/coredhcp/coredhcp/plugins/range
|
||||
github.com/coredhcp/coredhcp/plugins/router
|
||||
github.com/coredhcp/coredhcp/plugins/serverid
|
||||
github.com/coredhcp/coredhcp/plugins/searchdomains
|
||||
github.com/coredhcp/coredhcp/plugins/sleep
|
||||
github.com/coredhcp/coredhcp/plugins/staticroute
|
||||
104
cmds/coredhcp-generator/coredhcp.go.template
Normal file
104
cmds/coredhcp-generator/coredhcp.go.template
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright 2018-present the CoreDHCP Authors. All rights reserved
|
||||
// This source code is licensed under the MIT license found in the
|
||||
// LICENSE file in the root directory of this source tree.
|
||||
|
||||
{{/* This file is the template source. The following comment obviously doesn't apply here */ -}}
|
||||
// This is a generated file, edits should be made in the corresponding source file
|
||||
// And this file regenerated using `coredhcp-generator --from core-plugins.txt`
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/coredhcp/coredhcp/config"
|
||||
"github.com/coredhcp/coredhcp/logger"
|
||||
"github.com/coredhcp/coredhcp/server"
|
||||
|
||||
"github.com/coredhcp/coredhcp/plugins"
|
||||
{{- range $plugin := .}}
|
||||
{{- /* We import all plugins as pl_<pluginname> to avoid conflicts with reserved keywords */}}
|
||||
{{importname $plugin}} "{{$plugin}}"
|
||||
{{- end}}
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
flag "github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var (
|
||||
flagLogFile = flag.StringP("logfile", "l", "", "Name of the log file to append to. Default: stdout/stderr only")
|
||||
flagLogNoStdout = flag.BoolP("nostdout", "N", false, "Disable logging to stdout/stderr")
|
||||
flagLogLevel = flag.StringP("loglevel", "L", "info", fmt.Sprintf("Log level. One of %v", getLogLevels()))
|
||||
flagConfig = flag.StringP("conf", "c", "", "Use this configuration file instead of the default location")
|
||||
flagPlugins = flag.BoolP("plugins", "P", false, "list plugins")
|
||||
)
|
||||
|
||||
var logLevels = map[string]func(*logrus.Logger){
|
||||
"none": func(l *logrus.Logger) { l.SetOutput(io.Discard) },
|
||||
"debug": func(l *logrus.Logger) { l.SetLevel(logrus.DebugLevel) },
|
||||
"info": func(l *logrus.Logger) { l.SetLevel(logrus.InfoLevel) },
|
||||
"warning": func(l *logrus.Logger) { l.SetLevel(logrus.WarnLevel) },
|
||||
"error": func(l *logrus.Logger) { l.SetLevel(logrus.ErrorLevel) },
|
||||
"fatal": func(l *logrus.Logger) { l.SetLevel(logrus.FatalLevel) },
|
||||
}
|
||||
|
||||
func getLogLevels() []string {
|
||||
var levels []string
|
||||
for k := range logLevels {
|
||||
levels = append(levels, k)
|
||||
}
|
||||
return levels
|
||||
}
|
||||
|
||||
var desiredPlugins = []*plugins.Plugin{
|
||||
{{- range $plugin := .}}
|
||||
&{{importname $plugin}}.Plugin,
|
||||
{{- end}}
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
if *flagPlugins {
|
||||
for _, p := range desiredPlugins {
|
||||
fmt.Println(p.Name)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
log := logger.GetLogger("main")
|
||||
fn, ok := logLevels[*flagLogLevel]
|
||||
if !ok {
|
||||
log.Fatalf("Invalid log level '%s'. Valid log levels are %v", *flagLogLevel, getLogLevels())
|
||||
}
|
||||
fn(log.Logger)
|
||||
log.Infof("Setting log level to '%s'", *flagLogLevel)
|
||||
if *flagLogFile != "" {
|
||||
log.Infof("Logging to file %s", *flagLogFile)
|
||||
logger.WithFile(log, *flagLogFile)
|
||||
}
|
||||
if *flagLogNoStdout {
|
||||
log.Infof("Disabling logging to stdout/stderr")
|
||||
logger.WithNoStdOutErr(log)
|
||||
}
|
||||
config, err := config.Load(*flagConfig)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load configuration: %v", err)
|
||||
}
|
||||
// register plugins
|
||||
for _, plugin := range desiredPlugins {
|
||||
if err := plugins.RegisterPlugin(plugin); err != nil {
|
||||
log.Fatalf("Failed to register plugin '%s': %v", plugin.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
// start server
|
||||
srv, err := server.Start(config)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err := srv.Wait(); err != nil {
|
||||
log.Error(err)
|
||||
}
|
||||
}
|
||||
144
cmds/coredhcp-generator/main.go
Normal file
144
cmds/coredhcp-generator/main.go
Normal file
@@ -0,0 +1,144 @@
|
||||
// Copyright 2018-present the CoreDHCP Authors. All rights reserved
|
||||
// This source code is licensed under the MIT license found in the
|
||||
// LICENSE file in the root directory of this source tree.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
flag "github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultTemplateFile = "coredhcp.go.template"
|
||||
importBase = "github.com/coredhcp/coredhcp/"
|
||||
)
|
||||
|
||||
var (
|
||||
flagTemplate = flag.StringP("template", "t", defaultTemplateFile, "Template file name")
|
||||
flagOutfile = flag.StringP("outfile", "o", "", "Output file path")
|
||||
flagFromFile = flag.StringP("from", "f", "", "Optional file name to get the plugin list from, one import path per line")
|
||||
)
|
||||
|
||||
var funcMap = template.FuncMap{
|
||||
"importname": func(importPath string) (string, error) {
|
||||
parts := strings.Split(importPath, "/")
|
||||
if len(parts) < 1 {
|
||||
return "", fmt.Errorf("no components found in import path '%s'", importPath)
|
||||
}
|
||||
return "pl_" + parts[len(parts)-1], nil
|
||||
},
|
||||
}
|
||||
|
||||
func usage() {
|
||||
fmt.Fprintf(flag.CommandLine.Output(),
|
||||
"%s [-template tpl] [-outfile out] [-from pluginlist] [plugin [plugin...]]\n",
|
||||
os.Args[0],
|
||||
)
|
||||
flag.PrintDefaults()
|
||||
fmt.Fprintln(flag.CommandLine.Output(), ` plugin
|
||||
Plugin name to include, as go import path.
|
||||
Short names can be used for builtin coredhcp plugins (eg "serverid")`)
|
||||
}
|
||||
|
||||
func main() {
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
|
||||
data, err := os.ReadFile(*flagTemplate)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to read template file '%s': %v", *flagTemplate, err)
|
||||
}
|
||||
t, err := template.New("coredhcp").Funcs(funcMap).Parse(string(data))
|
||||
if err != nil {
|
||||
log.Fatalf("Template parsing failed: %v", err)
|
||||
}
|
||||
plugins := make(map[string]bool)
|
||||
for _, pl := range flag.Args() {
|
||||
pl := strings.TrimSpace(pl)
|
||||
if pl == "" {
|
||||
continue
|
||||
}
|
||||
if !strings.ContainsRune(pl, '/') {
|
||||
// A bare name was specified, not a full import path.
|
||||
// Coredhcp plugins aren't in the standard library, and it's unlikely someone
|
||||
// would put them at the base of $GOPATH/src.
|
||||
// Assume this is one of the builtin plugins. If needed, use the -from option
|
||||
// which always requires (and uses) exact paths
|
||||
|
||||
// XXX: we could also look into github.com/coredhcp/plugins
|
||||
pl = importBase + pl
|
||||
}
|
||||
plugins[pl] = true
|
||||
}
|
||||
if *flagFromFile != "" {
|
||||
// additional plugin names from a text file, one line per plugin import
|
||||
// path
|
||||
fd, err := os.Open(*flagFromFile)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to read file '%s': %v", *flagFromFile, err)
|
||||
}
|
||||
defer func() {
|
||||
if err := fd.Close(); err != nil {
|
||||
log.Printf("Error closing file '%s': %v", *flagFromFile, err)
|
||||
}
|
||||
}()
|
||||
sc := bufio.NewScanner(fd)
|
||||
for sc.Scan() {
|
||||
pl := strings.TrimSpace(sc.Text())
|
||||
if pl == "" {
|
||||
continue
|
||||
}
|
||||
plugins[pl] = true
|
||||
}
|
||||
if err := sc.Err(); err != nil {
|
||||
log.Fatalf("Error reading file '%s': %v", *flagFromFile, err)
|
||||
}
|
||||
}
|
||||
if len(plugins) == 0 {
|
||||
log.Fatalf("No plugin specified!")
|
||||
}
|
||||
outfile := *flagOutfile
|
||||
if outfile == "" {
|
||||
tmpdir, err := os.MkdirTemp("", "coredhcp")
|
||||
if err != nil {
|
||||
log.Fatalf("Cannot create temporary directory: %v", err)
|
||||
}
|
||||
outfile = path.Join(tmpdir, "coredhcp.go")
|
||||
}
|
||||
|
||||
log.Printf("Generating output file '%s' with %d plugin(s):", outfile, len(plugins))
|
||||
idx := 1
|
||||
for pl := range plugins {
|
||||
log.Printf("% 3d) %s", idx, pl)
|
||||
idx++
|
||||
}
|
||||
outFD, err := os.OpenFile(outfile, os.O_CREATE|os.O_WRONLY, 0644)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create output file '%s': %v", outfile, err)
|
||||
}
|
||||
defer func() {
|
||||
if err := outFD.Close(); err != nil {
|
||||
log.Printf("Error while closing file descriptor for '%s': %v", outfile, err)
|
||||
}
|
||||
}()
|
||||
// WARNING: no escaping of the provided strings is done
|
||||
pluginList := make([]string, 0, len(plugins))
|
||||
for pl := range plugins {
|
||||
pluginList = append(pluginList, pl)
|
||||
}
|
||||
sort.Strings(pluginList)
|
||||
if err := t.Execute(outFD, pluginList); err != nil {
|
||||
log.Fatalf("Template execution failed: %v", err)
|
||||
}
|
||||
log.Printf("Generated file '%s'. You can build it by running 'go build' in the output directory.", outfile)
|
||||
fmt.Println(path.Dir(outfile))
|
||||
}
|
||||
Reference in New Issue
Block a user