main.go (153 lines of code) (raw):

// 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 main import ( "fmt" "os" "runtime/debug" "strings" "time" "github.com/elastic/crd-ref-docs/config" "github.com/elastic/crd-ref-docs/processor" "github.com/elastic/crd-ref-docs/renderer" "github.com/spf13/cobra" "go.uber.org/zap" "go.uber.org/zap/zapcore" ) var args = config.Flags{} func main() { cmd := cobra.Command{ Use: "crd-ref-docs", Short: "Generate CRD reference documentation", SilenceUsage: true, SilenceErrors: true, Version: printVersion(), RunE: doRun, } cmd.SetVersionTemplate("{{ .Version }}\n") cmd.Flags().StringVar(&args.LogLevel, "log-level", "INFO", "Log level") cmd.Flags().StringVar(&args.Config, "config", "config.yaml", "Path to config file") cmd.Flags().StringVar(&args.SourcePath, "source-path", "", "Path to source directory containing CRDs") cmd.Flags().StringVar(&args.TemplatesDir, "templates-dir", "", "Path to the directory containing template files") cmd.Flags().StringVar(&args.Renderer, "renderer", "asciidoctor", "Renderer to use ('asciidoctor' or 'markdown')") cmd.Flags().StringVar(&args.OutputPath, "output-path", ".", "Path to output the rendered result") cmd.Flags().StringVar(&args.OutputMode, "output-mode", "single", "Output mode to generate a single file or one file per group ('group' or 'single')") cmd.Flags().IntVar(&args.MaxDepth, "max-depth", 10, "Maximum recursion level for type discovery") if err := cmd.Execute(); err != nil { os.Exit(1) } } func doRun(_ *cobra.Command, _ []string) error { initLogging(args.LogLevel) zap.S().Infow("Loading configuration", "path", args.Config) conf, err := config.Load(args) if err != nil { zap.S().Errorw("Failed to read config", "error", err) return err } r, err := renderer.New(conf) if err != nil { zap.S().Errorw("Failed to create renderer", "error", err) return err } startTime := time.Now() defer func() { zap.S().Infof("Execution time: %s", time.Since(startTime)) }() zap.S().Infow("Processing source directory", "directory", conf.SourcePath, "depth", conf.MaxDepth) gvd, err := processor.Process(conf) if err != nil { zap.S().Errorw("Failed to process source directory", "error", err) return err } zap.S().Infow("Rendering output", "path", conf.OutputPath) if err := r.Render(gvd); err != nil { zap.S().Errorw("Failed to render", "error", err) return err } zap.S().Info("CRD reference documentation generated") return nil } func initLogging(level string) { var logger *zap.Logger var err error errorPriority := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { return lvl >= zapcore.ErrorLevel }) minLogLevel := zapcore.InfoLevel switch strings.ToUpper(level) { case "DEBUG": minLogLevel = zapcore.DebugLevel case "INFO": minLogLevel = zapcore.InfoLevel case "WARN": minLogLevel = zapcore.WarnLevel case "ERROR": minLogLevel = zapcore.ErrorLevel } infoPriority := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { return lvl < zapcore.ErrorLevel && lvl >= minLogLevel }) consoleErrors := zapcore.Lock(os.Stderr) consoleInfo := zapcore.Lock(os.Stdout) encoderConf := zap.NewDevelopmentEncoderConfig() encoderConf.EncodeLevel = zapcore.CapitalColorLevelEncoder consoleEncoder := zapcore.NewConsoleEncoder(encoderConf) core := zapcore.NewTee( zapcore.NewCore(consoleEncoder, consoleErrors, errorPriority), zapcore.NewCore(consoleEncoder, consoleInfo, infoPriority), ) stackTraceEnabler := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { return lvl > zapcore.ErrorLevel }) logger = zap.New(core, zap.AddStacktrace(stackTraceEnabler)) if err != nil { zap.S().Fatalw("Failed to create logger", "error", err) } zap.ReplaceGlobals(logger.Named("crd-ref-docs")) zap.RedirectStdLog(logger.Named("stdlog")) } // Global build information variables defined via ldflags during release. var ( buildVersion string buildDate string buildCommit string ) // printVersion prints the version, git commit and build date using global variables defined via ldflags during release, // or using values ​​from debug.ReadBuildInfo(). func printVersion() string { return fmt.Sprintf("Version: %s\nGitCommit: %s\nBuildDate: %s\n", version(), commit(), date()) } func version() string { if buildVersion != "" { return buildVersion } bi, ok := debug.ReadBuildInfo() if ok && bi != nil && bi.Main.Version != "" { return bi.Main.Version } return "(unknown)" } func date() string { if buildDate != "" { return buildDate } bi, ok := debug.ReadBuildInfo() if ok { for _, setting := range bi.Settings { if setting.Key == "vcs.time" { return setting.Value } } } return "(unknown)" } func commit() string { if buildCommit != "" { return buildCommit } bi, ok := debug.ReadBuildInfo() if ok { for _, setting := range bi.Settings { if setting.Key == "vcs.revision" { return setting.Value } } } return "(unknown)" }