Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update the configureation and main fx code. #6

Merged
merged 3 commits into from
Sep 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,5 @@ go.work
xmidt-agent

internal/jwtxt/cmd/example/*

*.dot
72 changes: 71 additions & 1 deletion config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,79 @@

package main

import "github.com/xmidt-org/sallust"
import (
"fmt"
"os"

"github.com/goschtalt/goschtalt"
"github.com/xmidt-org/sallust"
"gopkg.in/dealancer/validate.v2"
)

type Config struct {
SpecialValue string
Logger sallust.Config
}

// Collect and process the configuration files and env vars and
// produce a configuration object.
func provideConfig(cli *CLI) (*goschtalt.Config, error) {
gs, err := goschtalt.New(
goschtalt.StdCfgLayout(applicationName, cli.Files...),
goschtalt.ConfigIs("two_words"),
goschtalt.DefaultUnmarshalOptions(
goschtalt.WithValidator(
goschtalt.ValidatorFunc(validate.Validate),
),
),

// Seed the program with the default, built-in configuration.
// Mark this as a default so it is ordered correctly.
goschtalt.AddValue("built-in", goschtalt.Root, defaultConfig,
goschtalt.AsDefault()),
)
if err != nil {
return nil, err
}

Check warning on line 39 in config.go

View check run for this annotation

Codecov / codecov/patch

config.go#L38-L39

Added lines #L38 - L39 were not covered by tests

if cli.Show {
// handleCLIShow handles the -s/--show option where the configuration is
// shown, then the program is exited.
//
// Exit with success because if the configuration is broken it will be
// very hard to debug where the problem originates. This way you can
// see the configuration and then run the service with the same
// configuration to see the error.

fmt.Fprintln(os.Stdout, gs.Explain().String())

out, err := gs.Marshal()
if err != nil {
fmt.Fprintln(os.Stderr, err)

Check warning on line 54 in config.go

View check run for this annotation

Codecov / codecov/patch

config.go#L54

Added line #L54 was not covered by tests
} else {
fmt.Fprintln(os.Stdout, "## Final Configuration\n---\n"+string(out))
}

os.Exit(0)
}

var tmp Config
err = gs.Unmarshal(goschtalt.Root, &tmp)
if err != nil {
fmt.Fprintln(os.Stderr, "There is a critical error in the configuration.")
fmt.Fprintln(os.Stderr, "Run with -s/--show to see the configuration.")
fmt.Fprintf(os.Stderr, "Error: %v\n", err)

// Exit here to prevent a very difficult to debug error from occurring.
os.Exit(0)
}

return gs, nil
}

// -----------------------------------------------------------------------------
// Keep the default configuration at the bottom of the file so it is easy to
// see what the default configuration is.
// -----------------------------------------------------------------------------

var defaultConfig = Config{}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ require (
github.com/xmidt-org/wrp-go/v3 v3.2.0
go.uber.org/fx v1.20.0
go.uber.org/zap v1.26.0
gopkg.in/dealancer/validate.v2 v2.1.0
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/goschtalt/approx v1.0.0 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/miekg/dns v1.1.56 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
Expand Down
14 changes: 14 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE
github.com/alecthomas/repr v0.1.0/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/foxcpp/go-mockdns v1.0.0 h1:7jBqxd3WDWwi/6WhDvacvH1XsN3rOLXyHM1uhvIx6FI=
Expand All @@ -30,6 +31,9 @@ github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/miekg/dns v1.1.25/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.56 h1:5imZaSeoRNvpM9SzWNhEcP9QliKiz20/dA2QabIGVnE=
github.com/miekg/dns v1.1.56/go.mod h1:cRm6Oo2C8TY9ZS/TqsSrseAcncm74lfK5G+ikN2SWWY=
Expand All @@ -41,6 +45,13 @@ github.com/psanford/memfs v0.0.0-20210214183328-a001468d78ef h1:NKxTG6GVGbfMXc2m
github.com/psanford/memfs v0.0.0-20210214183328-a001468d78ef/go.mod h1:tcaRap0jS3eifrEEllL6ZMd9dg8IlDpi2S1oARrQ+NI=
github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg=
github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
Expand Down Expand Up @@ -92,7 +103,10 @@ gonum.org/v1/gonum v0.13.0/go.mod h1:/WPYRckkfWrhWefxyYTfrTtQR0KH4iyHNuzxqXAKyAU
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/dealancer/validate.v2 v2.1.0 h1:XY95SZhVH1rBe8uwtnQEsOO79rv8GPwK+P3VWhQfJbA=
gopkg.in/dealancer/validate.v2 v2.1.0/go.mod h1:EipWMj8hVO2/dPXVlYRe9yKcgVd5OttpQDiM1/wZ0DE=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
5 changes: 5 additions & 0 deletions invalid.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# SPDX-FileCopyrightText: 2023 Comcast Cable Communications Management, LLC
# SPDX-License-Identifier: Apache-2.0
---
invalid:
invalid: invalid
114 changes: 38 additions & 76 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,28 @@
type CLI struct {
Dev bool `optional:"" short:"d" help:"Run in development mode."`
Show bool `optional:"" short:"s" help:"Show the configuration and exit."`
Graph string `optional:"" short:"g" help:"Output the dependency graph to the specified file."`
Files []string `optional:"" short:"f" help:"Specific configuration files or directories."`
}

// xmidiAgent is the main entry point for the program. It is responsible for
// setting up the dependency injection framework and invoking the program.
func xmidtAgent(args []string) error {
// xmidtAgent is the main entry point for the program. It is responsible for
// setting up the dependency injection framework and returning the app object.
func xmidtAgent(args []string) (*fx.App, error) {
var (
gscfg *goschtalt.Config

// Capture if the program is being run in dev mode so the extra stuff
// is output as requested.
dev devMode
// Capture the dependency tree in case we need to debug something.
g fx.DotGraph

// Capture if the program should gracefully exit early & without
// reporting an error via logging.
early earlyExit
// Capture the command line arguments.
cli *CLI
)

app := fx.New(
fx.Supply(cliArgs(args)),
fx.Supply(&early),
fx.Supply(&dev),
fx.Populate(&g),
fx.Populate(&gscfg),
fx.Populate(&cli),

fx.WithLogger(func(log *zap.Logger) fxevent.Logger {
return &fxevent.ZapLogger{Logger: log}
Expand All @@ -66,92 +66,58 @@
fx.Provide(
provideCLI,
provideLogger,

// Collect and process the configuration files and env vars and
// produce a configuration object.
func(cli *CLI) (*goschtalt.Config, error) {
return goschtalt.New(
goschtalt.StdCfgLayout(applicationName, cli.Files...),
goschtalt.ConfigIs("two_words"),

// Seed the program with the default, built-in configuration
goschtalt.AddValue("built-in", goschtalt.Root,
Config{
SpecialValue: "default",
},
goschtalt.AsDefault(), // Mark this as a default so it is ordered correctly
),
)
},
provideConfig,

goschtalt.UnmarshalFunc[sallust.Config]("logger", goschtalt.Optional()),
),

fx.Invoke(
handleCLIShow,
func(gs *goschtalt.Config) {
gscfg = gs
},
),
fx.Invoke(),
)

if dev {
defer func() {
fmt.Fprintln(os.Stderr, gscfg.Explain().String())
}()
if cli != nil && cli.Graph != "" {
_ = os.WriteFile(cli.Graph, []byte(g), 0600)
}

if err := app.Err(); err != nil || early {
return err
if err := app.Err(); err != nil {
return nil, err

Check warning on line 82 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L82

Added line #L82 was not covered by tests
}

app.Run()

return nil
return app, nil
}

func main() {
err := xmidtAgent(os.Args[1:])

app, err := xmidtAgent(os.Args[1:])

Check warning on line 89 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L89

Added line #L89 was not covered by tests
if err == nil {
app.Run()

Check warning on line 91 in main.go

View check run for this annotation

Codecov / codecov/patch

main.go#L91

Added line #L91 was not covered by tests
return
}

fmt.Fprintln(os.Stderr, err)
os.Exit(-1)
}

// Provides a named type so it's a bit easier to flow through & use in fx.
type earlyExit bool

// Provides a named type so it's a bit easier to flow through & use in fx.
type devMode bool

// Provides a named type so it's a bit easier to flow through & use in fx.
type cliArgs []string

// handleCLIShow handles the -s/--show option where the configuration is shown,
// then the program is exited.
func handleCLIShow(cli *CLI, cfg *goschtalt.Config, early *earlyExit) {
if !cli.Show {
return
}
// Handle the CLI processing and return the processed input.
func provideCLI(args cliArgs) (*CLI, error) {
return provideCLIWithOpts(args, false)
}

fmt.Fprintln(os.Stdout, cfg.Explain().String())
func provideCLIWithOpts(args cliArgs, testOpts bool) (*CLI, error) {
var cli CLI

out, err := cfg.Marshal()
if err != nil {
fmt.Fprintln(os.Stderr, err)
} else {
fmt.Fprintln(os.Stdout, "## Final Configuration\n---\n"+string(out))
}
// Create a no-op option to satisfy the kong.New() call.
var opt kong.Option = kong.OptionFunc(
func(*kong.Kong) error {
return nil
},
)

*early = earlyExit(true)
}
if testOpts {
opt = kong.Writers(nil, nil)
}

// Handle the CLI processing and return the processed input.
func provideCLI(args cliArgs, dev *devMode, early *earlyExit) (*CLI, error) {
var cli CLI
parser, err := kong.New(&cli,
kong.Name(applicationName),
kong.Description("The cpe agent for Xmidt service.\n"+
Expand All @@ -161,25 +127,21 @@
fmt.Sprintf("\tBuilt By: %s\n", builtBy),
),
kong.UsageOnError(),
opt,
)
if err != nil {
return nil, err
}

parser.Exit = func(i int) {
// Exit early on error, but we still need to return the CLI object
// otherwise fx will complain & hide the useful message we want to print.
*early = earlyExit(true)
if testOpts {
parser.Exit = func(_ int) { panic("exit") }
}

fmt.Printf("parser: %p\n", parser)
_, err = parser.Parse(args)
if err != nil {
parser.FatalIfErrorf(err)
}

// Mark the devMode state so the collector can be output
*dev = devMode(cli.Dev)
return &cli, nil
}

Expand Down
Loading