Deployment and lifecycle management for Nix
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

client-go: add cobra for subcommands

+86 -35
+3
.gitignore
··· 39 39 data/ 40 40 .nixos-test-history 41 41 .bootstrap.token 42 + 43 + # go bin 44 + /sower
+71 -33
client-go/main.go
··· 1 1 package main 2 2 3 3 import ( 4 + _ "embed" 4 5 "fmt" 5 6 "net/url" 6 7 "os" ··· 15 16 "github.com/rs/zerolog" 16 17 "github.com/rs/zerolog/log" 17 18 19 + "github.com/spf13/cobra" 18 20 flag "github.com/spf13/pflag" 19 21 ) 22 + 23 + var version string 20 24 21 25 type config struct { 22 26 endpoint url.URL 23 27 } 24 28 25 - var conf = koanf.Conf{} 26 - 27 - var kConfig = koanf.NewWithConf(conf) 28 - 29 29 func main() { 30 30 log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) 31 31 32 - flags := flag.NewFlagSet("config", flag.ExitOnError) 33 - flags.Usage = func() { 34 - fmt.Println(flags.FlagUsages()) 35 - os.Exit(0) 32 + var config *config 33 + 34 + var rootCmd = &cobra.Command{ 35 + Use: "sower", 36 + Short: "sower client", 37 + PersistentPreRunE: func(cmd *cobra.Command, args []string) error { 38 + var err error 39 + 40 + // load the configuration for every subcommand 41 + config, err = initRootConfig(cmd.Flags()) 42 + if err != nil { 43 + log.Error().Err(err).Msg("failed loading configuration") 44 + return err 45 + } 46 + 47 + return nil 48 + }, 36 49 } 37 - // TODO fix default config path 38 - flags.StringSlice("config", []string{"./dev-client.toml"}, "path to one or more toml config files") 39 - flags.String("bootstrap-token-file", "", "bootstrap token") 40 - // TODO fix default name and seed_type 41 - flags.String("name", "", "seed name") 42 - flags.String("type", "", "seed type") 43 - flags.Bool("debug", false, "enable debug logging") 44 - flags.Parse(os.Args[1:]) 50 + rootCmd.PersistentFlags().Bool("debug", false, "enable debug logging") 51 + rootCmd.PersistentFlags().StringSlice("config", []string{"./dev-client.toml"}, "path to toml config file, repeatable") 52 + 53 + var versionCmd = &cobra.Command{ 54 + Use: "version", 55 + Short: "Print the version", 56 + Run: func(cmd *cobra.Command, args []string) { 57 + if version == "" { 58 + fmt.Println("dev") 59 + } else { 60 + fmt.Println(version) 61 + } 62 + }, 63 + } 64 + rootCmd.AddCommand(versionCmd) 65 + 66 + var daemonCmd = &cobra.Command{ 67 + Use: "daemon", 68 + Short: "Run the daemon", 69 + Run: func(cmd *cobra.Command, args []string) { 70 + run(config) 71 + }, 72 + } 73 + rootCmd.AddCommand(daemonCmd) 74 + 75 + if err := rootCmd.Execute(); err != nil { 76 + fmt.Println(err) 77 + os.Exit(1) 78 + } 79 + } 80 + 81 + func initRootConfig(flags *flag.FlagSet) (*config, error) { 82 + var conf = koanf.Conf{} 83 + var kConfig = koanf.NewWithConf(conf) 45 84 46 85 // load config files 47 86 configFiles, _ := flags.GetStringSlice("config") 48 87 for _, c := range configFiles { 49 88 if err := kConfig.Load(file.Provider(c), toml.Parser()); err != nil { 50 - log.Error().Err(err).Msg("error loading config file") 51 - os.Exit(1) 89 + return &config{}, fmt.Errorf("error loading config file") 52 90 } 53 91 } 54 92 55 93 // load cli args 56 94 if err := kConfig.Load(posflag.Provider(flags, ".", kConfig), nil); err != nil { 57 - log.Error().Err(err).Msg("error parsing arguments") 58 - os.Exit(1) 95 + return &config{}, fmt.Errorf("error parsing arguments") 59 96 } 60 97 61 98 zerolog.SetGlobalLevel(zerolog.InfoLevel) 62 - if kConfig.Bool("debug") { 99 + debug, err := flags.GetBool("debug") 100 + if err != nil { 101 + return &config{}, fmt.Errorf("Failed to parse debug: %v", err) 102 + } 103 + if debug { 63 104 zerolog.SetGlobalLevel(zerolog.DebugLevel) 64 105 } 65 106 66 107 if kConfig.String("bootstrap-token-file") == "" { 67 - log.Error().Msg("Missing required bootstrap-token") 68 - os.Exit(1) 108 + return &config{}, fmt.Errorf("Missing required bootstrap-token") 69 109 } 70 110 bootstrapToken, err := readSecret(kConfig.String("bootstrap-token-file")) 71 111 if err != nil { 72 - log.Error().Msgf("failed to read secret, %v", err) 73 - os.Exit(1) 112 + return &config{}, fmt.Errorf("failed to read secret, %v", err) 74 113 } 75 114 token, err := signToken(bootstrapToken, kConfig.String("name"), kConfig.String("type")) 76 115 if err != nil { 77 - log.Error().Msgf("failed to sign jwt, %v", err) 78 - os.Exit(1) 116 + return &config{}, fmt.Errorf("failed to sign jwt, %v", err) 79 117 } 80 118 81 119 endpoint, err := url.Parse(fmt.Sprintf("%s/client?token=%s", kConfig.String("url"), token)) 82 120 if err != nil { 83 - log.Error().Msgf("failed to parse URL, %v", err) 84 - os.Exit(1) 121 + return &config{}, fmt.Errorf("failed to parse URL, %v", err) 85 122 } 86 123 87 - config := config{ 124 + config := &config{ 88 125 endpoint: *endpoint, 89 126 } 90 127 91 - run(config) 128 + log.Debug().Any("config", config).Msg("") 129 + 130 + return config, nil 92 131 } 93 132 94 - func run(config config) { 133 + func run(config *config) { 95 134 log.Info().Msg("Starting") 96 - log.Debug().Any("config", config).Msg("") 97 135 98 136 socket := phx.NewSocket(&config.endpoint) 99 137 zerologLogger := logger{}
+2
go.mod
··· 10 10 github.com/knadh/koanf/v2 v2.1.1 11 11 github.com/nshafer/phx v0.2.2 12 12 github.com/rs/zerolog v1.33.0 13 + github.com/spf13/cobra v1.8.1 13 14 github.com/spf13/pflag v1.0.5 14 15 ) 15 16 ··· 17 18 github.com/fsnotify/fsnotify v1.7.0 // indirect 18 19 github.com/go-viper/mapstructure/v2 v2.0.0-alpha.1 // indirect 19 20 github.com/gorilla/websocket v1.5.0 // indirect 21 + github.com/inconshreveable/mousetrap v1.1.0 // indirect 20 22 github.com/knadh/koanf/maps v0.1.1 // indirect 21 23 github.com/mattn/go-colorable v0.1.13 // indirect 22 24 github.com/mattn/go-isatty v0.0.19 // indirect
+6
go.sum
··· 1 1 github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 2 + github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 2 3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 3 4 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 4 5 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= ··· 11 12 github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= 12 13 github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= 13 14 github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 15 + github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= 16 + github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 14 17 github.com/knadh/koanf/maps v0.1.1 h1:G5TjmUh2D7G2YWf5SQQqSiHRJEjaicvU0KpypqB3NIs= 15 18 github.com/knadh/koanf/maps v0.1.1/go.mod h1:npD/QZY3V6ghQDdcQzl1W4ICNVTkohC8E73eI2xW4yI= 16 19 github.com/knadh/koanf/parsers/toml/v2 v2.1.0 h1:EUdIKIeezfDj6e1ABDhIjhbURUpyrP1HToqW6tz8R0I= ··· 40 43 github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= 41 44 github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= 42 45 github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= 46 + github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 47 + github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= 48 + github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= 43 49 github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 44 50 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 45 51 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+4 -2
nix/client-go-package.nix
··· 1 1 { lib, buildGoModule }: 2 - buildGoModule { 2 + buildGoModule rec { 3 3 pname = "sower-client"; 4 4 version = builtins.readFile ../VERSION; 5 5 ··· 16 16 17 17 CGO_ENABLED = 0; 18 18 19 + ldflags = [ "-X main.version=${version}" ]; 20 + 19 21 postInstall = '' 20 22 mv $out/bin/client-go $out/bin/sower 21 23 ''; 22 24 23 - vendorHash = "sha256-ZaS8x9ktEbDC8xDKL4Gb13hQl19lDjqepbqSpC8MIv8="; 25 + vendorHash = "sha256-7658me4SpEoO66Y16Qy3/ue6/AJTuwb2T1mS2OQGB64="; 24 26 }