165 lines
5.4 KiB
Go
165 lines
5.4 KiB
Go
// Copyright The OpenTelemetry Authors
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package internal // import "go.opentelemetry.io/collector/cmd/builder/internal"
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/knadh/koanf/parsers/yaml"
|
|
"github.com/knadh/koanf/providers/env/v2"
|
|
"github.com/knadh/koanf/providers/file"
|
|
"github.com/knadh/koanf/v2"
|
|
"github.com/spf13/cobra"
|
|
flag "github.com/spf13/pflag"
|
|
"go.uber.org/multierr"
|
|
"go.uber.org/zap"
|
|
|
|
"go.opentelemetry.io/collector/cmd/builder/internal/builder"
|
|
"go.opentelemetry.io/collector/cmd/builder/internal/config"
|
|
)
|
|
|
|
const (
|
|
configFlag = "config"
|
|
skipGenerateFlag = "skip-generate"
|
|
skipCompilationFlag = "skip-compilation"
|
|
skipGetModulesFlag = "skip-get-modules"
|
|
skipStrictVersioningFlag = "skip-strict-versioning"
|
|
ldflagsFlag = "ldflags"
|
|
gcflagsFlag = "gcflags"
|
|
distributionOutputPathFlag = "output-path"
|
|
verboseFlag = "verbose"
|
|
)
|
|
|
|
// Command is the main entrypoint for this application
|
|
func Command() (*cobra.Command, error) {
|
|
cmd := &cobra.Command{
|
|
SilenceUsage: true, // Don't print usage on Run error.
|
|
SilenceErrors: true, // Don't print errors; main does it.
|
|
Use: "ocb",
|
|
Long: fmt.Sprintf("OpenTelemetry Collector Builder (%s)", version) + `
|
|
|
|
ocb generates a custom OpenTelemetry Collector binary using the
|
|
build configuration given by the "--config" argument. If no build
|
|
configuration is provided, ocb will generate a default Collector.
|
|
`,
|
|
Args: cobra.NoArgs,
|
|
RunE: func(cmd *cobra.Command, _ []string) error {
|
|
cfg, err := initConfig(cmd.Flags())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err = cfg.Validate(); err != nil {
|
|
return fmt.Errorf("invalid configuration: %w", err)
|
|
}
|
|
|
|
if err = cfg.SetGoPath(); err != nil {
|
|
return fmt.Errorf("go not found: %w", err)
|
|
}
|
|
|
|
if err = cfg.ParseModules(); err != nil {
|
|
return fmt.Errorf("invalid module configuration: %w", err)
|
|
}
|
|
|
|
return builder.GenerateAndCompile(cfg)
|
|
},
|
|
}
|
|
|
|
if err := initFlags(cmd.Flags()); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// version of this binary
|
|
cmd.AddCommand(versionCommand())
|
|
|
|
return cmd, nil
|
|
}
|
|
|
|
func initFlags(flags *flag.FlagSet) error {
|
|
flags.String(configFlag, "", "build configuration file")
|
|
// the distribution parameters, which we accept as CLI flags as well
|
|
flags.Bool(skipGenerateFlag, false, "Whether builder should skip generating go code (default false)")
|
|
flags.Bool(skipCompilationFlag, false, "Whether builder should only generate go code with no compile of the collector (default false)")
|
|
flags.Bool(skipGetModulesFlag, false, "Whether builder should skip updating go.mod and retrieve Go module list (default false)")
|
|
flags.Bool(skipStrictVersioningFlag, true, "Whether builder should skip strictly checking the calculated versions following dependency resolution")
|
|
flags.Bool(verboseFlag, false, "Whether builder should print verbose output (default false)")
|
|
flags.String(ldflagsFlag, "", `ldflags to include in the "go build" command`)
|
|
flags.String(gcflagsFlag, "", `gcflags to include in the "go build" command`)
|
|
flags.String(distributionOutputPathFlag, "", "Where to write the resulting files")
|
|
return flags.MarkDeprecated(distributionOutputPathFlag, "use config distribution::output_path")
|
|
}
|
|
|
|
func initConfig(flags *flag.FlagSet) (*builder.Config, error) {
|
|
cfg, err := builder.NewDefaultConfig()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
cfg.Logger.Info("OpenTelemetry Collector Builder", zap.String("version", version))
|
|
|
|
var provider koanf.Provider
|
|
cfgFile, _ := flags.GetString(configFlag)
|
|
if cfgFile != "" {
|
|
cfg.Logger.Info("Using config file", zap.String("path", cfgFile))
|
|
// load the config file
|
|
provider = file.Provider(cfgFile)
|
|
} else {
|
|
cfg.Logger.Info("Using default build configuration")
|
|
// or the default if the config isn't provided
|
|
provider = config.DefaultProvider()
|
|
}
|
|
|
|
k := koanf.New(".")
|
|
if err = k.Load(provider, yaml.Parser()); err != nil {
|
|
return nil, fmt.Errorf("failed to load configuration file: %w", err)
|
|
}
|
|
|
|
// handle env variables
|
|
if err = k.Load(env.Provider(".", env.Opt{}), nil); err != nil {
|
|
return nil, fmt.Errorf("failed to load environment variables: %w", err)
|
|
}
|
|
|
|
if err = k.UnmarshalWithConf("", cfg, koanf.UnmarshalConf{Tag: "mapstructure"}); err != nil {
|
|
return nil, fmt.Errorf("failed to unmarshal configuration: %w", err)
|
|
}
|
|
|
|
if err = applyFlags(flags, cfg); err != nil {
|
|
return nil, fmt.Errorf("failed to apply flags configuration: %w", err)
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|
|
|
|
func applyFlags(flags *flag.FlagSet, cfg *builder.Config) error {
|
|
var errs, err error
|
|
cfg.SkipGenerate, err = flags.GetBool(skipGenerateFlag)
|
|
errs = multierr.Append(errs, err)
|
|
cfg.SkipCompilation, err = flags.GetBool(skipCompilationFlag)
|
|
errs = multierr.Append(errs, err)
|
|
cfg.SkipGetModules, err = flags.GetBool(skipGetModulesFlag)
|
|
errs = multierr.Append(errs, err)
|
|
cfg.SkipStrictVersioning, err = flags.GetBool(skipStrictVersioningFlag)
|
|
errs = multierr.Append(errs, err)
|
|
|
|
if flags.Changed(ldflagsFlag) {
|
|
cfg.LDSet = true
|
|
cfg.LDFlags, err = flags.GetString(ldflagsFlag)
|
|
errs = multierr.Append(errs, err)
|
|
}
|
|
if flags.Changed(gcflagsFlag) {
|
|
cfg.GCSet = true
|
|
cfg.GCFlags, err = flags.GetString(gcflagsFlag)
|
|
errs = multierr.Append(errs, err)
|
|
}
|
|
|
|
cfg.Verbose, err = flags.GetBool(verboseFlag)
|
|
errs = multierr.Append(errs, err)
|
|
|
|
if flags.Changed(distributionOutputPathFlag) {
|
|
cfg.Distribution.OutputPath, err = flags.GetString(distributionOutputPathFlag)
|
|
errs = multierr.Append(errs, err)
|
|
}
|
|
|
|
return errs
|
|
}
|