Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package fortio for openSUSE:Factory checked in at 2023-02-21 15:36:40 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/fortio (Old) and /work/SRC/openSUSE:Factory/.fortio.new.22824 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "fortio" Tue Feb 21 15:36:40 2023 rev:31 rq:1066975 version:1.51.0 Changes: -------- --- /work/SRC/openSUSE:Factory/fortio/fortio.changes 2023-02-18 17:12:51.855674968 +0100 +++ /work/SRC/openSUSE:Factory/.fortio.new.22824/fortio.changes 2023-02-21 15:36:59.172612564 +0100 @@ -1,0 +2,8 @@ +Tue Feb 21 09:25:46 UTC 2023 - ka...@b1-systems.de + +- Update to version 1.51.0: + * refactor to use fortio.org/cli and scli (#713) + * Bump fortio.org/dflag from 1.4.1 to 1.4.2 (#712) + * use Deprecated: for log and dflag + +------------------------------------------------------------------- Old: ---- fortio-1.50.1.tar.gz New: ---- fortio-1.51.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ fortio.spec ++++++ --- /var/tmp/diff_new_pack.zVlBzs/_old 2023-02-21 15:36:59.764615966 +0100 +++ /var/tmp/diff_new_pack.zVlBzs/_new 2023-02-21 15:36:59.772616012 +0100 @@ -19,7 +19,7 @@ %define __arch_install_post export NO_BRP_STRIP_DEBUG=true Name: fortio -Version: 1.50.1 +Version: 1.51.0 Release: 0 Summary: Load testing library, command line tool, advanced echo server and web UI License: Apache-2.0 ++++++ _service ++++++ --- /var/tmp/diff_new_pack.zVlBzs/_old 2023-02-21 15:36:59.812616242 +0100 +++ /var/tmp/diff_new_pack.zVlBzs/_new 2023-02-21 15:36:59.816616264 +0100 @@ -3,7 +3,7 @@ <param name="url">https://github.com/fortio/fortio</param> <param name="scm">git</param> <param name="exclude">.git</param> - <param name="revision">v1.50.1</param> + <param name="revision">v1.51.0</param> <param name="versionformat">@PARENT_TAG@</param> <param name="changesgenerate">enable</param> <param name="versionrewrite-pattern">v(.*)</param> @@ -17,7 +17,7 @@ <param name="compression">gz</param> </service> <service name="go_modules" mode="disabled"> - <param name="archive">fortio-1.50.1.tar.gz</param> + <param name="archive">fortio-1.51.0.tar.gz</param> </service> </services> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.zVlBzs/_old 2023-02-21 15:36:59.840616403 +0100 +++ /var/tmp/diff_new_pack.zVlBzs/_new 2023-02-21 15:36:59.844616426 +0100 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/fortio/fortio</param> - <param name="changesrevision">f7ca38b31431e8ae81e2ab343e6fef71dcdfae6c</param></service></servicedata> + <param name="changesrevision">2bd5ef4e0034f3789706f50f15dbf0e057615066</param></service></servicedata> (No newline at EOF) ++++++ fortio-1.50.1.tar.gz -> fortio-1.51.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.50.1/Dockerfile new/fortio-1.51.0/Dockerfile --- old/fortio-1.50.1/Dockerfile 2023-02-17 21:43:27.000000000 +0100 +++ new/fortio-1.51.0/Dockerfile 2023-02-20 20:15:32.000000000 +0100 @@ -26,4 +26,4 @@ WORKDIR /var/lib/fortio ENTRYPOINT ["/usr/bin/fortio"] # start the server mode (grpc ping on 8079, http echo and UI on 8080, redirector on 8081) by default -CMD ["server", "-config", "/etc/fortio"] +CMD ["server", "-config-dir", "/etc/fortio"] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.50.1/README.md new/fortio-1.51.0/README.md --- old/fortio-1.50.1/README.md 2023-02-17 21:43:27.000000000 +0100 +++ new/fortio-1.51.0/README.md 2023-02-20 20:15:32.000000000 +0100 @@ -31,9 +31,10 @@ A recent addition is the new `jrpc` JSON Remote Procedure Calls library package ([docs](https://pkg.go.dev/fortio.org/fortio/jrpc)). We also have moved some of the library to their own toplevel package, like: -- Dynamic flags: [fortio.org/dflag](https://github.com/fortio/dflag/#fortio-dynamic-flags-was-go-flagz) +- Dynamic flags: [fortio.org/dflag](https://github.com/fortio/dflag#fortio-dynamic-flags) - Logger: [fortio.org/log](https://github.com/fortio/log#log) - Version helper: [fortio.org/version](https://github.com/fortio/version#version) +- CLI helpers integrating the above to reduce toil making new tools [fortio.org/cli](https://github.com/fortio/cli#cli) and servers [fortio.org/scli](https://github.com/fortio/scli#scli) for arguments, flags, usage, dynamic config, etc... If you want to connect to fortio using https and fortio to provide real TLS certificates, or to multiplex grpc and regular http behind a single port, check out [Fortio Proxy](https://github.com/fortio/proxy#fortio-proxy). @@ -58,13 +59,13 @@ The [releases](https://github.com/fortio/fortio/releases) page has binaries for many OS/architecture combinations (see assets): ```shell -curl -L https://github.com/fortio/fortio/releases/download/v1.50.1/fortio-linux_amd64-1.50.1.tgz \ +curl -L https://github.com/fortio/fortio/releases/download/v1.51.0/fortio-linux_amd64-1.51.0.tgz \ | sudo tar -C / -xvzpf - # or the debian package -wget https://github.com/fortio/fortio/releases/download/v1.50.1/fortio_1.50.1_amd64.deb -dpkg -i fortio_1.50.1_amd64.deb +wget https://github.com/fortio/fortio/releases/download/v1.51.0/fortio_1.51.0_amd64.deb +dpkg -i fortio_1.51.0_amd64.deb # or the rpm -rpm -i https://github.com/fortio/fortio/releases/download/v1.50.1/fortio-1.50.1-1.x86_64.rpm +rpm -i https://github.com/fortio/fortio/releases/download/v1.51.0/fortio-1.51.0-1.x86_64.rpm # and more, see assets in release page ``` @@ -74,7 +75,7 @@ brew install fortio ``` -On Windows, download https://github.com/fortio/fortio/releases/download/v1.50.1/fortio_win_1.50.1.zip and extract `fortio.exe` to any location, then using the Windows Command Prompt: +On Windows, download https://github.com/fortio/fortio/releases/download/v1.51.0/fortio_win_1.51.0.zip and extract `fortio.exe` to any location, then using the Windows Command Prompt: ``` fortio.exe server ``` @@ -96,7 +97,8 @@ Likewise you can establish a single TCP (or unix domain or UDP (use `udp://` prefix)) connection using the `nc` command (like the standalone netcat package). You can run just the redirector with `redirect` or just the tcp echo with `tcp-echo`. If you saved JSON results (using the web UI or directly from the command line), you can browse and graph those results using the `report` command. -The `version` command will print version and build information, `fortio version -s` just the version. +The `version` command will print the short print versiob. `fortio buildinfo` will print the full +build information. Lastly, you can learn which flags are available using `help` command. Most important flags for http load generation: @@ -123,8 +125,8 @@ <details> <!-- use release/updateFlags.sh to update this section --> <pre> -ΦοÏÏίο 1.50.1 usage: - fortio command [flags] target +ΦοÏÏίο 1.51.0 usage: + fortio command [flags] target where command is one of: load (load testing), server (starts ui, rest api, http-echo, redirect, proxies, tcp-echo, udp-echo and grpc ping servers), tcp-echo (only the tcp-echo server), udp-echo (only udp-echo server), @@ -134,21 +136,21 @@ or version (prints the full version and build details). where target is a url (http load tests) or host:port (grpc health test), or tcp://host:port (tcp load test), or udp://host:port (udp load test). -flags are: +or 1 of the special arguments + fortio {help|version|buildinfo} +flags: -H key:value - Additional http header(s) or grpc metadata. Multiple key:value pairs -can be passed using multiple -H. + Additional http header(s) or grpc metadata. Multiple key:value pairs can be +passed using multiple -H. -L Follow redirects (implies -std-client) - do not use for load test -M value - Http multi proxy to run, e.g -M "localport1 baseDestURL1 baseDestURL2" --M ... + Http multi proxy to run, e.g -M "localport1 baseDestURL1 baseDestURL2" -M ... -P value - Tcp proxies to run, e.g -P "localport1 dest_host1:dest_port1" -P -"[::1]:0 www.google.com:443" ... + Tcp proxies to run, e.g -P "localport1 dest_host1:dest_port1" -P "[::1]:0 +www.google.com:443" ... -a Automatically save JSON result with filename based on labels & timestamp -abort-on code - Http code that if encountered aborts the run. e.g. 503 or -1 for socket -errors. + Http code that if encountered aborts the run. e.g. 503 or -1 for socket errors. -access-log-file path file path to log all requests to. Maybe have performance impacts -access-log-format format @@ -156,53 +158,54 @@ -allow-initial-errors Allow and don't abort on initial warmup errors -base-url URL - base URL used as prefix for data/index.tsv generation. (when empty, the -url from the first request is used) + base URL used as prefix for data/index.tsv generation. (when empty, the url from +the first request is used) -c int Number of connections/goroutine/threads (default 4) -cacert Path - Path to a custom CA certificate file to be used for the TLS client -connections, if empty, use https:// prefix for standard internet/system CAs + Path to a custom CA certificate file to be used for the TLS client connections, +if empty, use https:// prefix for standard internet/system CAs -calc-qps Calculate the qps based on number of requests (-n) and duration (-t) -cert Path Path to the certificate file to be used for client or server TLS -compression Enable http compression - -config path - Config directory path to watch for changes of dynamic flags (empty for -no watch) + -config-dir directory + Config directory to watch for dynamic flag changes + -config-port port + Config port to open for dynamic flag UI/api -connection-reuse min:max - Range min:max for the max number of connections to reuse for each -thread, default to unlimited. e.g. 10:30 means randomly choose a max connection -reuse threshold between 10 and 30 requests. + Range min:max for the max number of connections to reuse for each thread, default +to unlimited. e.g. 10:30 means randomly choose a max connection reuse threshold between +10 and 30 requests. -content-type string - Sets http content type. Setting this value switches the request method -from GET to POST. + Sets http content type. Setting this value switches the request method from GET +to POST. -curl Just fetch the content once -curl-stdout-headers - Restore pre 1.22 behavior where http headers of the fast client are -output to stdout in curl mode. now stderr by default. + Restore pre 1.22 behavior where http headers of the fast client are output to +stdout in curl mode. now stderr by default. -data-dir Directory Directory where JSON results are stored/read (default ".") -dns-method method - When a name resolves to multiple ip, which method to pick: cached-rr -for cached round robin, rnd for random, first for first answer (pre 1.30 -behavior), rr for round robin. (default cached-rr) + When a name resolves to multiple ip, which method to pick: cached-rr for cached +round robin, rnd for random, first for first answer (pre 1.30 behavior), rr for round +robin. (default cached-rr) -echo-debug-path URI - http echo server URI for debug, empty turns off that part (more secure) -(default "/debug") + http echo server URI for debug, empty turns off that part (more secure) (default +"/debug") -echo-server-default-params value - Default parameters/querystring to use if there isn't one provided -explicitly. E.g "status=404&delay=3s" + Default parameters/querystring to use if there isn't one provided explicitly. E.g +"status=404&delay=3s" -gomaxprocs int Setting for runtime.GOMAXPROCS, <1 doesn't change the default -grpc Use GRPC (health check by default, add -ping for ping) for load testing -grpc-max-streams uint - MaxConcurrentStreams for the grpc server. Default (0) is to leave the -option unset. + MaxConcurrentStreams for the grpc server. Default (0) is to leave the option +unset. -grpc-ping-delay duration grpc ping delay in response -grpc-port port @@ -212,20 +215,19 @@ -h2 Attempt to use http2.0 / h2 (instead of http 1.1) with stdclient and TLS -halfclose - When not keepalive, whether to half close the connection (only for fast -http) + When not keepalive, whether to half close the connection (only for fast http) -health grpc ping client mode: use health instead of ping -healthservice string which service string to pass to health check -http-port port - http echo server port. Can be in the form of host:port, ip:port, port -or /unix/domain/path or "disabled". (default "8080") + http echo server port. Can be in the form of host:port, ip:port, port or +/unix/domain/path or "disabled". (default "8080") -http1.0 Use http1.0 (instead of http 1.1) -httpbufferkb kbytes - Size of the buffer (max data size) for the optimized http client in -kbytes (default 128) + Size of the buffer (max data size) for the optimized http client in kbytes +(default 128) -httpccch Check for Connection: Close Header -https-insecure @@ -233,43 +235,40 @@ -jitter set to true to de-synchronize parallel clients' by 10% -json path - Json output to provided file path or '-' for stdout (empty = no json -output, unless -a is used) + Json output to provided file path or '-' for stdout (empty = no json output, +unless -a is used) -k Do not verify certs in https/tls/grpc connections -keepalive Keep connection alive (only for fast http 1.1) (default true) -key Path Path to the key file matching the -cert -labels string - Additional config data/labels to add to the resulting JSON, defaults to -target URL and hostname + Additional config data/labels to add to the resulting JSON, defaults to target +URL and hostname -log-errors Log http non 2xx/418 error codes as they occur (default true) -loglevel level - log level, one of [Debug Verbose Info Warning Error Critical Fatal] -(default Info) + log level, one of [Debug Verbose Info Warning Error Critical Fatal] (default Info) -max-echo-delay value - Maximum sleep time for delay= echo server parameter. dynamic flag. -(default 1.5s) + Maximum sleep time for delay= echo server parameter. dynamic flag. (default 1.5s) -maxpayloadsizekb Kbytes - MaxPayloadSize is the maximum size of payload to be generated by the -EchoHandler size= argument. In Kbytes. (default 256) + MaxPayloadSize is the maximum size of payload to be generated by the EchoHandler +size= argument. In Kbytes. (default 256) -multi-mirror-origin - Mirror the request url to the target for multi proxies (-M) (default -true) + Mirror the request url to the target for multi proxies (-M) (default true) -multi-serial-mode Multi server (-M) requests one at a time instead of parallel mode -n int - Run for exactly this number of calls instead of duration. Default (0) -is to use duration (-t). Default is 1 when used as grpc ping count. + Run for exactly this number of calls instead of duration. Default (0) is to use +duration (-t). Default is 1 when used as grpc ping count. -nc-dont-stop-on-eof in netcat (nc) mode, don't abort as soon as remote side closes -no-reresolve - Keep the initial DNS resolution and don't re-resolve when making new -connections (because of error or reuse limit reached) + Keep the initial DNS resolution and don't re-resolve when making new connections +(because of error or reuse limit reached) -nocatchup - set to exact fixed qps and prevent fortio from trying to catchup when -the target fails to keep up temporarily + set to exact fixed qps and prevent fortio from trying to catchup when the target +fails to keep up temporarily -offset duration Offset of the histogram data -p string @@ -277,41 +276,38 @@ -payload string Payload string to send along -payload-file path - File path to be use as payload (POST for http), replaces -payload when -set. + File path to be use as payload (POST for http), replaces -payload when set. -payload-size int - Additional random payload size, replaces -payload when set > 0, must be -smaller than -maxpayloadsizekb. Setting this switches http to POST. + Additional random payload size, replaces -payload when set > 0, must be smaller +than -maxpayloadsizekb. Setting this switches http to POST. -ping grpc load test: use ping instead of health -profile file write .cpu and .mem profiles to file -proxy-all-headers - Determines if only tracing or all headers (and cookies) are copied from -request on the fetch2 ui/server endpoint (default true) + Determines if only tracing or all headers (and cookies) are copied from request +on the fetch2 ui/server endpoint (default true) -qps float Queries Per Seconds or 0 for no wait/max qps (default 8) -quiet - Quiet mode: sets the loglevel to Error and reduces the output. + Quiet mode, sets loglevel to Error (quietly) to reduces the output -r float Resolution of the histogram lowest buckets in seconds (default 0.001) -redirect-port port - Redirect all incoming traffic to https URL (need ingress to work -properly). Can be in the form of host:port, ip:port, port or "disabled" to -disable the feature. (default "8081") + Redirect all incoming traffic to https URL (need ingress to work properly). Can +be in the form of host:port, ip:port, port or "disabled" to disable the feature. (default +"8081") -resolve IP Resolve host name to this IP -resolve-ip-type type - Resolve type: ip4 for ipv4, ip6 for ipv6 only, use ip for both (default -ip4) + Resolve type: ip4 for ipv4, ip6 for ipv6 only, use ip for both (default ip4) -runid int - Optional RunID to add to json result and auto save filename, to match -server mode + Optional RunID to add to json result and auto save filename, to match server mode -s int Number of streams per grpc connection (default 1) -sequential-warmup - http(s) runner warmup done in parallel instead of sequentially. When -set, restores pre 1.21 behavior + http(s) runner warmup done in parallel instead of sequentially. When set, +restores pre 1.21 behavior -server-idle-timeout value Default IdleTimeout for servers (default 30s) -static-dir path @@ -337,15 +333,15 @@ -udp-timeout duration Udp timeout (default 750ms) -ui-path URI - http server URI for UI, empty turns off that part (more secure) -(default "/fortio/") + http server URI for UI, empty turns off that part (more secure) (default +"/fortio/") -uniform set to true to de-synchronize parallel clients' requests uniformly -unix-socket path Unix domain socket path to use for physical connection -user user:password - User credentials for basic authentication (for http). Input data format -should be user:password + User credentials for basic authentication (for http). Input data format should be +user:password </pre> </details> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.50.1/Webtest.sh new/fortio-1.51.0/Webtest.sh --- old/fortio-1.50.1/Webtest.sh 2023-02-17 21:43:27.000000000 +0100 +++ new/fortio-1.51.0/Webtest.sh 2023-02-20 20:15:32.000000000 +0100 @@ -83,7 +83,7 @@ # Check we can connect, and run a grpc QPS test against ourselves through fetch $CURL "${BASE_FORTIO}fetch/localhost:8080$FORTIO_UI_PREFIX?url=localhost:8079&load=Start&qps=-1&json=on&n=100&runner=grpc" | grep '"SERVING": 100' # Check we get the logo (need to remove the CR from raw headers) -VERSION=$(docker exec $DOCKERNAME $FORTIO_BIN_PATH version -s) +VERSION=$(docker exec $DOCKERNAME $FORTIO_BIN_PATH version) LOGO_TYPE=$($CURL "${BASE_FORTIO}${VERSION}/static/img/${LOGO}" 2>&1 >/dev/null | grep -i Content-Type: | tr -d '\r'| awk '{print $2}') if [ "$LOGO_TYPE" != "image/svg+xml" ]; then echo "Unexpected content type for the logo: $LOGO_TYPE" @@ -104,7 +104,6 @@ fi # Check main, sync, browse pages -VERSION=$(docker exec $DOCKERNAME $FORTIO_BIN_PATH version -s) LOGOPATH="${VERSION}/static/img/${LOGO}" for p in "" browse sync; do # Check the page doesn't 404s diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.50.1/bincommon/commonflags.go new/fortio-1.51.0/bincommon/commonflags.go --- old/fortio-1.50.1/bincommon/commonflags.go 2023-02-17 21:43:27.000000000 +0100 +++ new/fortio-1.51.0/bincommon/commonflags.go 2023-02-20 20:15:32.000000000 +0100 @@ -21,19 +21,15 @@ import ( "context" "flag" - "fmt" - "io" "net/http" "os" "reflect" "strings" "fortio.org/dflag" - "fortio.org/dflag/dynloglevel" "fortio.org/fortio/fhttp" "fortio.org/fortio/fnet" "fortio.org/fortio/periodic" - "fortio.org/fortio/version" "fortio.org/log" ) @@ -54,16 +50,6 @@ // and otel access logger. type FortioHook func(*fhttp.HTTPOptions, *periodic.RunnerOptions) -// FlagsUsage prints end of the usage() (flags part + error message). -func FlagsUsage(w io.Writer, msgs ...interface{}) { - _, _ = fmt.Fprintf(w, "flags are:\n") - flag.CommandLine.SetOutput(w) - flag.PrintDefaults() - if len(msgs) > 0 { - _, _ = fmt.Fprintln(w, msgs...) - } -} - var ( compressionFlag = flag.Bool("compression", false, "Enable http compression") keepAliveFlag = flag.Bool("keepalive", true, "Keep connection alive (only for fast http 1.1)") @@ -81,8 +67,6 @@ followRedirectsFlag = flag.Bool("L", false, "Follow redirects (implies -std-client) - do not use for load test") userCredentialsFlag = flag.String("user", "", "User credentials for basic authentication (for http). Input data format"+ " should be `user:password`") - // QuietFlag is the value of -quiet. - QuietFlag = flag.Bool("quiet", false, "Quiet mode: sets the loglevel to Error and reduces the output.") contentTypeFlag = flag.String("content-type", "", "Sets http content type. Setting this value switches the request method from GET to POST.") // PayloadSizeFlag is the value of -payload-size. @@ -94,9 +78,6 @@ PayloadFileFlag = flag.String("payload-file", "", "File `path` to be use as payload (POST for http), replaces -payload when set.") // UnixDomainSocket to use instead of regular host:port. unixDomainSocketFlag = flag.String("unix-socket", "", "Unix domain socket `path` to use for physical connection") - // ConfigDirectoryFlag is where to watch for dynamic flag updates. - ConfigDirectoryFlag = flag.String("config", "", - "Config directory `path` to watch for changes of dynamic flags (empty for no watch)") // CertFlag is the flag for the path for the client custom certificate. CertFlag = flag.String("cert", "", "`Path` to the certificate file to be used for client or server TLS") // KeyFlag is the flag for the path for the key for the `cert`. @@ -126,7 +107,9 @@ ) // SharedMain is the common part of main from fortio_main and fcurl. -func SharedMain(usage func(io.Writer, ...interface{})) { +// It sets up the common flags, the rest of usage/argument/flag handling +// is now moved to the [fortio.org/cli] and [fortio.org/scli] packages. +func SharedMain() { flag.Var(&headersFlags, "H", "Additional http header(s) or grpc metadata. Multiple `key:value` pairs can be passed using multiple -H.") flag.IntVar(&fhttp.BufferSizeKb, "httpbufferkb", fhttp.BufferSizeKb, @@ -148,26 +131,7 @@ // MaxDelay is the maximum delay allowed for the echoserver responses. // It is a dynamic flag with default value of 1.5s so we can test the default 1s timeout in envoy. dflag.Flag("max-echo-delay", fhttp.MaxDelay) - // This sets up the logger's -loglevel as a dynamic flag. - dynloglevel.LoggerFlagSetup() - // Special case so `fcurl -version` and `--version` and `version` and ... work - if len(os.Args) < 2 { - return - } - firstArg := os.Args[1] - if strings.Contains(firstArg, "version") { - if len(os.Args) >= 3 && strings.Contains(os.Args[2], "s") { - // so `fortio version -s` is the short version; everything else is long/full - fmt.Println(version.Short()) - } else { - fmt.Print(version.Full()) - } - os.Exit(0) - } - if strings.Contains(firstArg, "help") || firstArg == "-h" { - usage(os.Stdout) - os.Exit(0) - } + // call [scli.ServerMain()] to complete the setup. } // FetchURL is fetching url content and exiting with 1 upon error. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.50.1/cli/fortio_main.go new/fortio-1.51.0/cli/fortio_main.go --- old/fortio-1.50.1/cli/fortio_main.go 2023-02-17 21:43:27.000000000 +0100 +++ new/fortio-1.51.0/cli/fortio_main.go 2023-02-20 20:15:32.000000000 +0100 @@ -24,14 +24,13 @@ "encoding/json" "flag" "fmt" - "io" "os" "path" "runtime" "strings" "time" - "fortio.org/dflag/configmap" + "fortio.org/cli" "fortio.org/fortio/bincommon" "fortio.org/fortio/fgrpc" "fortio.org/fortio/fhttp" @@ -43,6 +42,7 @@ "fortio.org/fortio/ui" "fortio.org/fortio/version" "fortio.org/log" + "fortio.org/scli" ) // -- Start of support for multiple proxies (-P) flags on cmd line. @@ -73,11 +73,9 @@ // -- End of -M support. -// Usage is fortio's main cli Usage to a writer. -func Usage(w io.Writer, msgs ...interface{}) { - _, _ = fmt.Fprintf(w, "ΦοÏÏίο %s usage:\n\t%s command [flags] target\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", - version.Short(), - os.Args[0], +// fortio's help/args message. +func helpArgsString() string { + return fmt.Sprintf("target\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s", "where command is one of: load (load testing), server (starts ui, rest api,", " http-echo, redirect, proxies, tcp-echo, udp-echo and grpc ping servers), ", " tcp-echo (only the tcp-echo server), udp-echo (only udp-echo server),", @@ -87,13 +85,6 @@ " or version (prints the full version and build details).", "where target is a url (http load tests) or host:port (grpc health test),", " or tcp://host:port (tcp load test), or udp://host:port (udp load test).") - bincommon.FlagsUsage(w, msgs...) -} - -// Prints usage and error messages with StdErr writer. -func usageErr(usage func(io.Writer, ...interface{}), msgs ...interface{}) { - usage(os.Stderr, msgs...) - os.Exit(1) } // Attention: every flag that is common to http client goes to bincommon/ @@ -191,42 +182,34 @@ // serverArgCheck always returns true after checking arguments length. // so it can be used with isServer = serverArgCheck() below. -func serverArgCheck(usage func(io.Writer, ...interface{})) bool { +func serverArgCheck() bool { if len(flag.Args()) != 0 { - usageErr(usage, "Error: too many arguments (typo in a flag?)") + cli.ErrUsage("Error: too many arguments (typo in a flag?)") } return true } -//nolint:funlen // well yes it's fairly long -func FortioMain(usage func(io.Writer, ...interface{}), hook bincommon.FortioHook) { +func FortioMain(hook bincommon.FortioHook) { flag.Var(&proxiesFlags, "P", "Tcp proxies to run, e.g -P \"localport1 dest_host1:dest_port1\" -P \"[::1]:0 www.google.com:443\" ...") flag.Var(&httpMultiFlags, "M", "Http multi proxy to run, e.g -M \"localport1 baseDestURL1 baseDestURL2\" -M ...") - bincommon.SharedMain(usage) - if len(os.Args) < 2 { - usageErr(usage, "Error: need at least 1 command parameter") - } - command := os.Args[1] - os.Args = append([]string{os.Args[0]}, os.Args[2:]...) - flag.Parse() - if *bincommon.HelpFlag { - usage(os.Stdout) - os.Exit(0) - } - if *bincommon.QuietFlag { - log.SetLogLevelQuiet(log.Error) - } - confDir := *bincommon.ConfigDirectoryFlag - if confDir != "" { - if _, err := configmap.Setup(flag.CommandLine, confDir); err != nil { - log.Critf("Unable to watch config/flag changes in %v: %v", confDir, err) - } - } + bincommon.SharedMain() + + // Use the new [fortio.org/cli] package to handle usage, arguments and flags parsing. + if cli.ProgramName == "" { + // fortiotel presets this. + cli.ProgramName = "ΦοÏÏίο" + } + cli.ArgsHelp = helpArgsString() + cli.CommandBeforeFlags = true + cli.MinArgs = 0 // because `fortio server`s don't take any args + cli.MaxArgs = 1 // for load, curl etc... subcommands. + scli.ServerMain() // will Exit if there were arguments/flags errors. + fnet.ChangeMaxPayloadSize(*newMaxPayloadSizeKb * fnet.KILOBYTE) percList, err := stats.ParsePercentiles(*percentilesFlag) if err != nil { - usageErr(usage, "Unable to extract percentiles from -p: ", err) + cli.ErrUsage("Unable to extract percentiles from -p: %v", err) } baseURL := strings.Trim(*baseURLFlag, " \t\n\r/") // remove trailing slash and other whitespace sync := strings.TrimSpace(*syncFlag) @@ -236,18 +219,18 @@ } } isServer := false - switch command { + switch cli.Command { case "curl": - fortioLoad(usage, true, nil, hook) + fortioLoad(true, nil, hook) case "nc": - fortioNC(usage) + fortioNC() case "load": - fortioLoad(usage, *curlFlag, percList, hook) + fortioLoad(*curlFlag, percList, hook) case "redirect": - isServer = serverArgCheck(usage) + isServer = serverArgCheck() fhttp.RedirectToHTTPS(*redirectFlag) case "report": - isServer = serverArgCheck(usage) + isServer = serverArgCheck() if *redirectFlag != disabled { fhttp.RedirectToHTTPS(*redirectFlag) } @@ -255,20 +238,20 @@ os.Exit(1) // error already logged } case "tcp-echo": - isServer = serverArgCheck(usage) + isServer = serverArgCheck() fnet.TCPEchoServer("tcp-echo", *tcpPortFlag) startProxies() case "udp-echo": - isServer = serverArgCheck(usage) + isServer = serverArgCheck() fnet.UDPEchoServer("udp-echo", *udpPortFlag, *udpAsyncFlag) startProxies() case "proxies": - isServer = serverArgCheck(usage) + isServer = serverArgCheck() if startProxies() == 0 { - usageErr(usage, "Error: fortio proxies command needs at least one -P / -M flag") + cli.ErrUsage("Error: fortio proxies command needs at least one -P / -M flag") } case "server": - isServer = serverArgCheck(usage) + isServer = serverArgCheck() if *tcpPortFlag != disabled { fnet.TCPEchoServer("tcp-echo", *tcpPortFlag) } @@ -288,14 +271,11 @@ } startProxies() case "grpcping": - grpcClient(usage) + grpcClient() default: - usageErr(usage, "Error: unknown command ", command) + cli.ErrUsage("Error: unknown command %q", cli.Command) } if isServer { - if confDir == "" { - log.Infof("Note: not using dynamic flag watching (use -config to set watch directory)") - } serverLoop(sync) } } @@ -345,10 +325,10 @@ return numProxies } -func fortioNC(usage func(io.Writer, ...interface{})) { +func fortioNC() { l := len(flag.Args()) if l != 1 && l != 2 { - usageErr(usage, "Error: fortio nc needs a host:port or host port destination") + cli.ErrUsage("Error: fortio nc needs a host:port or host port destination") } d := flag.Args()[0] if l == 2 { @@ -362,9 +342,9 @@ } //nolint:funlen, gocognit // maybe refactor/shorten later. -func fortioLoad(usage func(io.Writer, ...interface{}), justCurl bool, percList []float64, hook bincommon.FortioHook) { +func fortioLoad(justCurl bool, percList []float64, hook bincommon.FortioHook) { if len(flag.Args()) != 1 { - usageErr(usage, "Error: fortio load/curl needs a url or destination") + cli.ErrUsage("Error: fortio load/curl needs a url or destination") } httpOpts := bincommon.SharedHTTPOptions() if justCurl { @@ -381,7 +361,7 @@ qps := *qpsFlag // TODO possibly use translated <=0 to "max" from results/options normalization in periodic/ if *calcQPS { if *exactlyFlag == 0 || *durationFlag <= 0 { - usageErr(usage, "Error: can't use `-calc-qps` without also specifying `-n` and `-t`") + cli.ErrUsage("Error: can't use `-calc-qps` without also specifying `-n` and `-t`") } qps = float64(*exactlyFlag) / durationFlag.Seconds() log.LogVf("Calculated QPS to do %d request in %v: %f", *exactlyFlag, *durationFlag, qps) @@ -527,9 +507,9 @@ } } -func grpcClient(usage func(io.Writer, ...interface{})) { +func grpcClient() { if len(flag.Args()) != 1 { - usageErr(usage, "Error: fortio grpcping needs host argument in the form of host, host:port or ip:port") + cli.ErrUsage("Error: fortio grpcping needs host argument in the form of host, host:port or ip:port") } host := flag.Arg(0) count := int(*exactlyFlag) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.50.1/dflag/README.md new/fortio-1.51.0/dflag/README.md --- old/fortio-1.50.1/dflag/README.md 2023-02-17 21:43:27.000000000 +0100 +++ new/fortio-1.51.0/dflag/README.md 2023-02-20 20:15:32.000000000 +0100 @@ -1,2 +1,2 @@ -Fortio dflag has moved to [github.com/fortio/dflag](https://github.com/fortio/dflag#fortio-dynamic-flags-was-go-flagz) +Fortio dflag has moved to [github.com/fortio/dflag](https://github.com/fortio/dflag#fortio-dynamic-flags) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.50.1/dflag/dflag.go new/fortio-1.51.0/dflag/dflag.go --- old/fortio-1.50.1/dflag/dflag.go 1970-01-01 01:00:00.000000000 +0100 +++ new/fortio-1.51.0/dflag/dflag.go 2023-02-20 20:15:32.000000000 +0100 @@ -0,0 +1,2 @@ +// Deprecated: This package moved to [fortio.org/dflag]. +package dflag // import fortio.org/fortio/dflag diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.50.1/fcurl/fcurl.go new/fortio-1.51.0/fcurl/fcurl.go --- old/fortio-1.50.1/fcurl/fcurl.go 2023-02-17 21:43:27.000000000 +0100 +++ new/fortio-1.51.0/fcurl/fcurl.go 2023-02-20 20:15:32.000000000 +0100 @@ -17,34 +17,16 @@ // Do not add any external dependencies we want to keep fortio minimal. import ( - "flag" - "fmt" - "io" - "os" - + "fortio.org/cli" "fortio.org/fortio/bincommon" - "fortio.org/fortio/version" - "fortio.org/log" ) -// Prints usage. -func usage(w io.Writer, msgs ...interface{}) { - _, _ = fmt.Fprintf(w, "ΦοÏÏίο fortio-curl %s usage:\n\t%s [flags] url\n", - version.Short(), - os.Args[0]) - bincommon.FlagsUsage(w, msgs...) -} - func main() { - bincommon.SharedMain(usage) - if len(os.Args) < 2 { - usage(os.Stderr, "Error: need a url as parameter") - os.Exit(1) - } - flag.Parse() - if *bincommon.QuietFlag { - log.SetLogLevelQuiet(log.Error) - } + cli.ProgramName = "ΦοÏÏίο fortio-curl" + cli.ArgsHelp = "url" + cli.MinArgs = 1 + bincommon.SharedMain() + cli.Main() o := bincommon.SharedHTTPOptions() bincommon.FetchURL(o) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.50.1/go.mod new/fortio-1.51.0/go.mod --- old/fortio-1.50.1/go.mod 2023-02-17 21:43:27.000000000 +0100 +++ new/fortio-1.51.0/go.mod 2023-02-20 20:15:32.000000000 +0100 @@ -4,8 +4,10 @@ require ( fortio.org/assert v1.1.3 - fortio.org/dflag v1.4.1 + fortio.org/cli v1.1.0 + fortio.org/dflag v1.4.2 fortio.org/log v1.2.2 + fortio.org/scli v1.1.0 fortio.org/version v1.0.2 github.com/golang/protobuf v1.5.2 github.com/google/uuid v1.3.0 @@ -13,6 +15,15 @@ google.golang.org/grpc v1.53.0 ) +// Local dev of dependencies changes +// replace ( +// fortio.org/cli => ../cli +// fortio.org/dflag => ../dflag +// fortio.org/log => ../log +// fortio.org/scli => ../scli +// fortio.org/version => ../version +// ) + require ( github.com/fsnotify/fsnotify v1.6.0 // indirect golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb // indirect diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.50.1/go.sum new/fortio-1.51.0/go.sum --- old/fortio-1.50.1/go.sum 2023-02-17 21:43:27.000000000 +0100 +++ new/fortio-1.51.0/go.sum 2023-02-20 20:15:32.000000000 +0100 @@ -1,9 +1,13 @@ fortio.org/assert v1.1.3 h1:zXm8xiNiKvq2xG/YQ3sONAg3287XUuklKIDdjyD9pyg= fortio.org/assert v1.1.3/go.mod h1:039mG+/iYDPO8Ibx8TrNuJCm2T2SuhwRI3uL9nHTTls= -fortio.org/dflag v1.4.1 h1:WDhlHMh3yrQFrvspyN5YEyr8WATdKM2dUJlTxsjCDtI= -fortio.org/dflag v1.4.1/go.mod h1:pTEF7UEj6sHP9rj9gZG2GyhAGrrPJE4c6zOO7zB2yyI= +fortio.org/cli v1.1.0 h1:ATIxi7DgA7WAexUCF8p5a0qlGYk48ZgkwSEDrvwXeN4= +fortio.org/cli v1.1.0/go.mod h1:O3nVImKwJSvHKbMYWkqMbEagAXCS1xvSv1YbHwkKJjY= +fortio.org/dflag v1.4.2 h1:kkPNgmoGViSqh16Muf3BGt+qxPgsx+yfFGB/bpmiGqM= +fortio.org/dflag v1.4.2/go.mod h1:pTEF7UEj6sHP9rj9gZG2GyhAGrrPJE4c6zOO7zB2yyI= fortio.org/log v1.2.2 h1:vs42JjNwiqbMbacittZjJE9+oi72Za6aekML9gKmILg= fortio.org/log v1.2.2/go.mod h1:u/8/2lyczXq52aT5Nw6reD+3cR6m/EbS2jBiIYhgiTU= +fortio.org/scli v1.1.0 h1:vnnCH9tOnEtwJXLv9nytNvsXoAwBVktIh73mGackoX8= +fortio.org/scli v1.1.0/go.mod h1:MJOVM2MgZjvan3BFwfqwj36YNH4OLRgO5PUK9it2m0Y= fortio.org/version v1.0.2 h1:8NwxdX58aoeKx7T5xAPO0xlUu1Hpk42nRz5s6e6eKZ0= fortio.org/version v1.0.2/go.mod h1:2JQp9Ax+tm6QKiGuzR5nJY63kFeANcgrZ0osoQFDVm0= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.50.1/log/logger.go new/fortio-1.51.0/log/logger.go --- old/fortio-1.50.1/log/logger.go 2023-02-17 21:43:27.000000000 +0100 +++ new/fortio-1.51.0/log/logger.go 2023-02-20 20:15:32.000000000 +0100 @@ -12,6 +12,6 @@ // See the License for the specific language governing permissions and // limitations under the License. -// This package has moved to [fortio.org/log] (and [fortio.org/dflag/dynloglevel] +// Deprecated: package has moved to [fortio.org/log] (and [fortio.org/dflag/dynloglevel] // for the dynamic flag setup and the [fortio.org/dflag/dynloglevel.ChangeFlagsDefault] function). package log // import "fortio.org/fortio/log" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.50.1/main.go new/fortio-1.51.0/main.go --- old/fortio-1.50.1/main.go 2023-02-17 21:43:27.000000000 +0100 +++ new/fortio-1.51.0/main.go 2023-02-20 20:15:32.000000000 +0100 @@ -20,5 +20,5 @@ // like fortiotel (fortio with opentelemetry) func main() { - cli.FortioMain(cli.Usage, nil /* no hook needed */) + cli.FortioMain(nil /* no hook needed */) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.50.1/release/Dockerfile.in new/fortio-1.51.0/release/Dockerfile.in --- old/fortio-1.50.1/release/Dockerfile.in 2023-02-17 21:43:27.000000000 +0100 +++ new/fortio-1.51.0/release/Dockerfile.in 2023-02-20 20:15:32.000000000 +0100 @@ -24,7 +24,7 @@ make -C fortio official-build BUILD_DIR=/build GOARCH=${arch} OFFICIAL_DIR=/tmp/fortio_${arch}; \ done' -RUN cd fortio && /tmp/fortio_$(go env GOARCH)/fortio version -s > /tmp/version +RUN cd fortio && /tmp/fortio_$(go env GOARCH)/fortio version > /tmp/version WORKDIR /stage diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.50.1/release/updateFlags.sh new/fortio-1.51.0/release/updateFlags.sh --- old/fortio-1.50.1/release/updateFlags.sh 2023-02-17 21:43:27.000000000 +0100 +++ new/fortio-1.51.0/release/updateFlags.sh 2023-02-20 20:15:32.000000000 +0100 @@ -15,4 +15,4 @@ # # Extract fortio's help and rewrap it to 80 cols # TODO: do like fmt does to keep leading identation -go run . help | expand | fold -s | sed -e "s/ $//" -e "s/</\</" +go run . help | expand | fold -s -w 90 | sed -e "s/ $//" -e "s/</\</" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/fortio-1.50.1/ui/templates/main.html new/fortio-1.51.0/ui/templates/main.html --- old/fortio-1.50.1/ui/templates/main.html 2023-02-17 21:43:27.000000000 +0100 +++ new/fortio-1.51.0/ui/templates/main.html 2023-02-20 20:15:32.000000000 +0100 @@ -41,11 +41,11 @@ <div> Title/Labels: <input type="text" name="labels" size="40" value="Fortio" /> (empty to skip title)<br /> URL: <input type="text" name="url" size="80" value="http://{{.URLHostPort}}/echo?delay=250us:30,5ms:5&status=503:0.5,429:1.5" /> <br /> - QPS: <input type="text" name="qps" size="6" value="1000" /> + QPS: <input type="text" name="qps" size="6" value="100" /> Duration: <input id="duration" type="text" name="t" size="6" value="3s" /> or run until interrupted:<input type="checkbox" name="t" onchange="toggleDuration(this)" /> or run for exactly <input type="text" name="n" size="6" value="" /> calls. <br /> - Threads/Simultaneous connections: <input type="text" name="c" size="6" value="8" /> <br /> + Threads/Simultaneous connections: <input type="text" name="c" size="6" value="10" /> <br /> Connection reuse range: Min <input type="text" name="connection-reuse-range-min" size="6" value="" /> Max <input type="text" name="connection-reuse-range-max" size="6" value="" /> or Single value: <input type="text" name="connection-reuse-range-value" size="6" value="" /> <br /> @@ -61,7 +61,7 @@ Load using:<br /> tcp/udp/http: <input type="radio" name="runner" value="http/tcp/udp" checked/> (https insecure:<input type="checkbox" name="https-insecure" />, - standard go client instead of fastclient:<input type="checkbox" name="stdclient"/>, + standard go client instead of fastclient:<input type="checkbox" name="stdclient" checked/>, h2: <input type="checkbox" name="h2"/>, sequential warmup: <input type="checkbox" name="sequential-warmup"/>, resolve: <input type="text" name="resolve" size="12" value="" />) ++++++ vendor.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/fortio.org/cli/.gitignore new/vendor/fortio.org/cli/.gitignore --- old/vendor/fortio.org/cli/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/vendor/fortio.org/cli/.gitignore 2023-02-21 10:25:47.000000000 +0100 @@ -0,0 +1,15 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/fortio.org/cli/.golangci.yml new/vendor/fortio.org/cli/.golangci.yml --- old/vendor/fortio.org/cli/.golangci.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/vendor/fortio.org/cli/.golangci.yml 2023-02-21 10:25:47.000000000 +0100 @@ -0,0 +1,176 @@ +# Config for golanglint-ci + +# output configuration options + +# all available settings of specific linters +linters-settings: + gocritic: + disabled-checks: + - ifElseChain + dupl: + # tokens count to trigger issue, 150 by default + threshold: 100 + exhaustive: + # indicates that switch statements are to be considered exhaustive if a + # 'default' case is present, even if all enum members aren't listed in the + # switch + default-signifies-exhaustive: false + funlen: + lines: 140 + statements: 70 + gocognit: + # minimal code complexity to report, 30 by default (but we recommend 10-20) + min-complexity: 42 + nestif: + # minimal complexity of if statements to report, 5 by default + min-complexity: 4 + gocyclo: + # minimal code complexity to report, 30 by default (but we recommend 10-20) + min-complexity: 30 + godot: + # check all top-level comments, not only declarations + check-all: false + govet: + # report about shadowed variables + check-shadowing: true + # settings per analyzer + settings: + printf: # analyzer name, run `go tool vet help` to see all analyzers + funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Printf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).FErrf + enable-all: true + disable-all: false + depguard: + list-type: blacklist + include-go-root: false + packages: + - github.com/sirupsen/logrus + packages-with-error-message: + # specify an error message to output when a blacklisted package is used + - github.com/sirupsen/logrus: "logging is allowed only by fortio.log" + lll: + # max line length, lines longer will be reported. Default is 120. + # '\t' is counted as 1 character by default, and can be changed with the tab-width option + line-length: 132 + # tab width in spaces. Default to 1. + tab-width: 1 + misspell: + # Correct spellings using locale preferences for US or UK. + # Default is to use a neutral variety of English. + # Setting locale to US will correct the British spelling of 'colour' to 'color'. + locale: US + ignore-words: + - fortio + nakedret: + # make an issue if func has more lines of code than this setting and it has naked returns; default is 30 + max-func-lines: 30 + nolintlint: + require-specific: true + whitespace: + multi-if: false # Enforces newlines (or comments) after every multi-line if statement + multi-func: false # Enforces newlines (or comments) after every multi-line function signature + gofumpt: + # Choose whether or not to use the extra rules that are disabled + # by default + extra-rules: false + + +linters: + disable: + # bad ones: + - musttag + # Deprecated ones: + - scopelint + - golint + - interfacer + - maligned + - varcheck + - structcheck + - nosnakecase + - deadcode + # Weird/bad ones: + - wsl + - nlreturn + - gochecknoinits + - gochecknoglobals + - gomnd + - testpackage + - wrapcheck + - exhaustivestruct + - tagliatelle + - nonamedreturns + - varnamelen + - exhaustruct # seems like a good idea at first but actually a pain and go does have zero values for a reason. +# TODO consider putting these back, when they stop being bugged (ifshort, wastedassign,...) + - paralleltest + - thelper + - forbidigo + - ifshort + - wastedassign + - cyclop + - forcetypeassert + - ireturn + enable-all: true + disable-all: false + # Must not use fast: true in newer golangci-lint or it'll just skip a bunch of linter instead of doing caching like before (!) + fast: false + + +issues: + # Excluding configuration per-path, per-linter, per-text and per-source + exclude-rules: + # Exclude some linters from running on tests files. + - path: _test\.go + linters: + - gocyclo + - errcheck + - dupl + - gosec + - gochecknoinits + - gochecknoglobals + - forcetypeassert + - nosnakecase + - noctx + + # Exclude lll issues for long lines with go:generate + - linters: + - lll + source: "^//go:generate " + - linters: + - goerr113 + text: "do not define dynamic errors" + - linters: + - govet + text: "fieldalignment:" + - linters: + - godox + text: "TODO" + - linters: + - nosnakecase + text: "grpc_|_SERVING|O_" + + # Maximum issues count per one linter. Set to 0 to disable. Default is 50. + max-issues-per-linter: 0 + + # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. + max-same-issues: 0 + +severity: + # Default value is empty string. + # Set the default severity for issues. If severity rules are defined and the issues + # do not match or no severity is provided to the rule this will be the default + # severity applied. Severities should match the supported severity names of the + # selected out format. + # - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity + # - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#severity + # - Github: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message + default-severity: error + + # The default value is false. + # If set to true severity-rules regular expressions become case sensitive. + case-sensitive: false diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/fortio.org/cli/LICENSE new/vendor/fortio.org/cli/LICENSE --- old/vendor/fortio.org/cli/LICENSE 1970-01-01 01:00:00.000000000 +0100 +++ new/vendor/fortio.org/cli/LICENSE 2023-02-21 10:25:47.000000000 +0100 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/fortio.org/cli/README.md new/vendor/fortio.org/cli/README.md --- old/vendor/fortio.org/cli/README.md 1970-01-01 01:00:00.000000000 +0100 +++ new/vendor/fortio.org/cli/README.md 2023-02-21 10:25:47.000000000 +0100 @@ -0,0 +1,108 @@ +[](https://pkg.go.dev/fortio.org/cli) +[](https://goreportcard.com/report/fortio.org/cli) +[](https://github.com/fortio/cli/releases/) + +# cli +Reduce boiler plate needed on each new Golang main functions (Command Line Interface) for both tools and servers (use [fortio.org/scli ServerMain()](https://github.com/fortio/scli#scli) for server) + +It abstracts the repetitive parts of a `main()` command line tool, flag parsing, usage, etc... + +You can see real use example in a tool like [multicurl](https://github.com/fortio/multicurl) or a server like [proxy](https://github.com/fortio/proxy). + +It also supports (sub)commands style (where there is a word/command before the flags and remaining arguments, [fortio](https://github.com/fortio/fortio) uses that mode). + +## Tool Example +Client/Tool example (no dynamic flag url or config) [sampleTool](sampleTool/main.go) + +Code as simple as +```golang +import ( + "flag" + "os" + + "fortio.org/cli" + "fortio.org/log" +) + +func main() { + myFlag := flag.String("myflag", "default", "my flag") + cli.MinArgs = 2 + cli.MaxArgs = 4 + cli.Main() // Will have either called cli.ExitFunction or everything is valid + // Next line output won't show when passed -quiet + log.Infof("Info test, -myflag is %q", *myFlag) + log.Printf("Hello world, version %s, args %v", cli.ShortVersion, flag.Args()) +} +``` + +```bash +$ sampleTool a +sampleTool 1.0.0 usage: + sampleTool [flags] arg1 arg2 [arg3...arg4] +or 1 of the special arguments + sampleTool {help|version|buildinfo} +flags: + -loglevel level + log level, one of [Debug Verbose Info Warning Error Critical Fatal] (default Info) + -myflag string + my flag (default "default") + -quiet + Quiet mode, sets log level to warning +At least 2 arguments expected, got 1 +``` + +or normal case +```bash +$ sampleTool a b +15:42:17 I Info test, -myflag is "default" +15:42:17 Hello world, version dev, args [a b] +``` + +## Additional builtins + +### buildinfo + +e.g + +```bash +% go install github.com/fortio/multicurl@latest +go: downloading github.com/fortio/multicurl v1.10.1 +% multicurl buildinfo +1.10.1 h1:h9yM3XplwG7JWtVaSS0eJPiDmCJfnxvj3w+yoAMWMo4= go1.19.6 arm64 darwin +go go1.19.6 +path github.com/fortio/multicurl +mod github.com/fortio/multicurl v1.10.1 h1:h9yM3XplwG7JWtVaSS0eJPiDmCJfnxvj3w+yoAMWMo4= +dep fortio.org/cli v0.6.1 h1:V9L6ly4oz4fJjeQ5745FulIMsFAwFZvLPSUN+cKUrKk= +dep fortio.org/log v1.2.2 h1:vs42JjNwiqbMbacittZjJE9+oi72Za6aekML9gKmILg= +dep fortio.org/version v1.0.2 h1:8NwxdX58aoeKx7T5xAPO0xlUu1Hpk42nRz5s6e6eKZ0= +build -compiler=gc +build CGO_ENABLED=1 +build CGO_CFLAGS= +build CGO_CPPFLAGS= +build CGO_CXXFLAGS= +build CGO_LDFLAGS= +build GOARCH=arm64 +build GOOS=darwin +``` + +### help +```bash +% multicurl help +Fortio multicurl 1.10.1 usage: + multicurl [flags] url +or 1 of the special arguments + multicurl {help|version|buildinfo} +flags: +[...] + -loglevel level + log level, one of [Debug Verbose Info Warning Error Critical Fatal] (default Info) + -quiet + Quiet mode, sets log level to warning +``` + +### version +Short 'numeric' version (v skipped, useful for docker image tags etc) +```bash + % multicurl version +1.10.1 +``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/fortio.org/cli/cli.go new/vendor/fortio.org/cli/cli.go --- old/vendor/fortio.org/cli/cli.go 1970-01-01 01:00:00.000000000 +0100 +++ new/vendor/fortio.org/cli/cli.go 2023-02-21 10:25:47.000000000 +0100 @@ -0,0 +1,186 @@ +// Fortio CLI/Main utilities. +// +// (c) 2023 Fortio Authors +// See LICENSE + +// Package cli contains utilities for command line tools and server main()s +// to handle flags, arguments, version, logging ([fortio.org/log]), etc... +// Configure using the package variables (at minimum [MinArgs] unless your +// binary only accepts flags), setup additional [flag] before calling +// [Main] or [fortio.org/scli.ServerMain] for configmap and dynamic flags +// setup. +// Also supports (sub)commands style, see [CommandBeforeFlags] and [Command]. +package cli // import "fortio.org/cli" + +import ( + "flag" + "fmt" + "io" + "os" + "path/filepath" + "strings" + + "fortio.org/log" + "fortio.org/version" +) + +// Configuration for your Main() or ServerMain() function. +// These variables is how to setup the arguments, flags and usage parsing for [Main] and [ServerMain]. +// At minium set the MinArgs should be set. +var ( + // Out parameters: + // *Version will be filled automatically by the cli package, using [fortio.org/version.FromBuildInfo()]. + ShortVersion string // x.y.z from tag/install + LongVersion string // version plus go version plus OS/arch + FullVersion string // LongVersion plus build date and git sha + Command string // first argument, if [CommandBeforeFlags] is true. + // Following can/should be specified. + ProgramName string // Used at the beginning of Usage() + // Optional for programs using subcommand, command will be set in [Command]. + CommandBeforeFlags bool + // Cli usage/arguments example, ie "url1..." program name and "[flags]" will be added" + // can include \n for additional details in the Usage() before the flags are dumped. + ArgsHelp string + MinArgs int // Minimum number of arguments expected, not counting (optional) command. + MaxArgs int // Maximum number of arguments expected. 0 means same as MinArgs. -1 means no limit. + // If not set to true, will setup static loglevel flag and logger output for client tools. + ServerMode = false + // Override this to change the exit function (for testing), will be applied to log.Fatalf too. + ExitFunction = os.Exit + baseExe string +) + +func usage(w io.Writer, msg string, args ...any) { + cmd := "" + if CommandBeforeFlags { + cmd = "command " + } + _, _ = fmt.Fprintf(w, "%s %s usage:\n\t%s %s[flags]%s\nor 1 of the special arguments\n\t%s {help|version|buildinfo}\nflags:\n", + ProgramName, + ShortVersion, + baseExe, + cmd, + ArgsHelp, + os.Args[0], + ) + flag.CommandLine.SetOutput(w) + flag.PrintDefaults() + if msg != "" { + fmt.Fprintf(w, msg, args...) + fmt.Fprintln(w) + } +} + +// Main handles your commandline and flag parsing. Sets up flags first then call Main. +// For a server with dynamic flags, call ServerMain instead. +// Will either have called [ExitFunction] (defaults to [os.Exit]) +// or returned if all validations passed. +func Main() { + quietFlag := flag.Bool("quiet", false, + "Quiet mode, sets loglevel to Error (quietly) to reduces the output") + ShortVersion, LongVersion, FullVersion = version.FromBuildInfo() + log.Config.FatalExit = ExitFunction + baseExe = filepath.Base(os.Args[0]) + if ProgramName == "" { + ProgramName = baseExe + } + if MaxArgs == 0 { + MaxArgs = MinArgs + } + if ArgsHelp == "" { + for i := 1; i <= MinArgs; i++ { + ArgsHelp += fmt.Sprintf(" arg%d", i) + } + if MaxArgs < 0 { + ArgsHelp += " ..." + } else if MaxArgs > MinArgs { + ArgsHelp += fmt.Sprintf(" [arg%d...arg%d]", MinArgs+1, MaxArgs) + } + } + // Callers can pass that part of the help with or without leading space + if !strings.HasPrefix(ArgsHelp, " ") { + ArgsHelp = " " + ArgsHelp + } + if !ServerMode { + log.SetDefaultsForClientTools() + log.LoggerStaticFlagSetup("loglevel") + } + flag.CommandLine.Usage = func() { usage(os.Stderr, "") } // flag handling will exit 1 after calling usage, except for -h/-help + nArgs := len(os.Args) + if nArgs == 2 { + switch strings.ToLower(os.Args[1]) { + case "version": + fmt.Println(ShortVersion) + ExitFunction(0) + return // not typically reached, unless ExitFunction doesn't exit + case "buildinfo": + fmt.Print(FullVersion) + ExitFunction(0) + return // not typically reached, unless ExitFunction doesn't exit + case "help": + usage(os.Stdout, "") + ExitFunction(0) + return // not typically reached, unless ExitFunction doesn't exit + } + } + if CommandBeforeFlags { + if nArgs == 1 { + ErrUsage("Missing command argument") + return // not typically reached, unless ExitFunction doesn't exit + } + Command = os.Args[1] + os.Args = append([]string{os.Args[0]}, os.Args[2:]...) + } + flag.Parse() + nArgs = len(flag.Args()) + argsRange := (MinArgs != MaxArgs) + exactly := "Exactly" + if nArgs < MinArgs { + if argsRange { + exactly = "At least" + } + errArgCount(exactly, MinArgs, nArgs) + return // not typically reached, unless ExitFunction doesn't exit + } + if MaxArgs >= 0 && nArgs > MaxArgs { + if MaxArgs <= 0 { + ErrUsage("No arguments expected (except for version, buildinfo or help and -flags), got %d", nArgs) + return // not typically reached, unless ExitFunction doesn't exit + } + if argsRange { + exactly = "At most" + } + errArgCount(exactly, MaxArgs, nArgs) + return // not typically reached, unless ExitFunction doesn't exit + } + if *quietFlag { + log.SetLogLevelQuiet(log.Error) + } +} + +func errArgCount(prefix string, expected, actual int) { + ErrUsage("%s %d %s expected, got %d", prefix, expected, Plural(expected, "argument"), actual) +} + +// Show usage and error message on stderr and calls [ExitFunction] with code 1. +func ErrUsage(msg string, args ...any) { + usage(os.Stderr, msg, args...) + ExitFunction(1) +} + +// Plural adds an "s" to the noun if i is not 1. +func Plural(i int, noun string) string { + return PluralExt(i, noun, "s") +} + +// PluralExt returns the noun with an extension if i is not 1. +// Eg: +// +// PluralExt(1, "address", "es") // -> "address" +// PluralExt(3 /* or 0 */, "address", "es") // -> "addresses" +func PluralExt(i int, noun string, ext string) string { + if i == 1 { + return noun + } + return noun + ext +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/fortio.org/dflag/README.md new/vendor/fortio.org/dflag/README.md --- old/vendor/fortio.org/dflag/README.md 2023-02-18 09:07:00.000000000 +0100 +++ new/vendor/fortio.org/dflag/README.md 2023-02-21 10:25:47.000000000 +0100 @@ -1,21 +1,12 @@ [](https://codecov.io/github/fortio/dflag) - -This came from https://github.com/ldemailly/go-flagz, a fork of the code originally on https://github.com/mwitkow/go-flagz and https://github.com/improbable-eng/go-flagz with initial changes to get the go modules to work, reduce boiler plate needed for configmap watcher, avoid panic when there is extra whitespace, make the watcher work with regular files and relative paths and switched to standard golang flags. -And now further changes, simplification, etc... as part of fortio. -And then moved to a toplevel package in the fortio org. - -Thanks to [@mwitkow](https://github.com/mwitkow) for having created this originally. - -# Fortio Dynamic Flags (was Go FlagZ) - [](LICENSE) +# Fortio Dynamic Flags + Dynamic, thread-safe `flag` variables that can be modified at runtime through files, URL endpoint, or [Kubernetes](http://kubernetes.io) configmap changes. -For a similar project for JVM languages (Java, scala) see [java-flagz](https://github.com/mwitkow/java-flagz) - -Now rewritten and simplified and extended thanks to Go 1.18 generics (use versions prior to 1.33 if you want to use the older per type implementation) +See History section below. ## This sounds crazy. Why? @@ -32,7 +23,8 @@ ## Features * compatible with standard go `flag` package - * dynamic `flag` that are thread-safe and efficient, now also `Dyn[T]` generic: + * dynamic `flag` that are thread-safe and efficient + - `Dyn[T]` generic, or - `DynBool` - `DynInt64` - `DynFloat64` @@ -55,7 +47,6 @@ Declare a single `flag.FlagSet` in some public package (e.g. `common.SharedFlagSet`) that you'll use throughout your server or stick to `flag.CommandLine` default flagset for your binary. - ### Dynamic JSON flag with a validator and notifier ```go @@ -88,20 +79,36 @@ ``` All access to `featuresFlag`, which is a `[]string` flag, is synchronized across go-routines using `atomic` pointer swaps. + ## Library versus caller style +NEW: ```golang // In the library "libfoo" package -var MyConfig = dflag.New("default value", "explanation of what that is for").WithValidator(MyValidator) +var MyConfig = dflag.New("default value", "explanation of what that is for").WithValidator(myValidator) // In the caller/users, bind to an actual flag: dflag.Flag("foocfg", libfoo.MyConfig) // defines -foocfg flag ``` ## Complete example -See a [http server](examples/server_kube) complete example. +See a [http server](examples/server_kube) complete example or the [fortio.org/scli](https://github.com/fortio/scli#scli) package for easy reuse/configuration. + +## History + +This came from https://github.com/ldemailly/go-flagz, a fork of the code originally on https://github.com/mwitkow/go-flagz and https://github.com/improbable-eng/go-flagz with initial changes to get the go modules to work, reduce boiler plate needed for configmap watcher, avoid panic when there is extra whitespace, make the watcher work with regular files and relative paths and switched to standard golang flags. + +And further changes, simplification, etc... as part of fortio. + +Including rewrite and simplifications taking advantage of go 1.18 and newer generics support (use versions in fortio prior to 1.33 if you want to use the older per type implementation) + +And now moved to a toplevel package in the fortio org. + +For a similar project for JVM languages (Java, scala) see [java-flagz](https://github.com/mwitkow/java-flagz) + +Thanks to [@mwitkow](https://github.com/mwitkow) for having created this originally. -# Status +## Status This code is *production* quality. It's been running happily in production in its earlier incarnation at Improbable for years and now everywhere fortio runs. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/fortio.org/scli/.gitignore new/vendor/fortio.org/scli/.gitignore --- old/vendor/fortio.org/scli/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/vendor/fortio.org/scli/.gitignore 2023-02-21 10:25:47.000000000 +0100 @@ -0,0 +1,15 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/fortio.org/scli/.golangci.yml new/vendor/fortio.org/scli/.golangci.yml --- old/vendor/fortio.org/scli/.golangci.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/vendor/fortio.org/scli/.golangci.yml 2023-02-21 10:25:47.000000000 +0100 @@ -0,0 +1,176 @@ +# Config for golanglint-ci + +# output configuration options + +# all available settings of specific linters +linters-settings: + gocritic: + disabled-checks: + - ifElseChain + dupl: + # tokens count to trigger issue, 150 by default + threshold: 100 + exhaustive: + # indicates that switch statements are to be considered exhaustive if a + # 'default' case is present, even if all enum members aren't listed in the + # switch + default-signifies-exhaustive: false + funlen: + lines: 140 + statements: 70 + gocognit: + # minimal code complexity to report, 30 by default (but we recommend 10-20) + min-complexity: 42 + nestif: + # minimal complexity of if statements to report, 5 by default + min-complexity: 4 + gocyclo: + # minimal code complexity to report, 30 by default (but we recommend 10-20) + min-complexity: 30 + godot: + # check all top-level comments, not only declarations + check-all: false + govet: + # report about shadowed variables + check-shadowing: true + # settings per analyzer + settings: + printf: # analyzer name, run `go tool vet help` to see all analyzers + funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).Printf + - (github.com/golangci/golangci-lint/pkg/logutils.Log).FErrf + enable-all: true + disable-all: false + depguard: + list-type: blacklist + include-go-root: false + packages: + - github.com/sirupsen/logrus + packages-with-error-message: + # specify an error message to output when a blacklisted package is used + - github.com/sirupsen/logrus: "logging is allowed only by fortio.log" + lll: + # max line length, lines longer will be reported. Default is 120. + # '\t' is counted as 1 character by default, and can be changed with the tab-width option + line-length: 132 + # tab width in spaces. Default to 1. + tab-width: 1 + misspell: + # Correct spellings using locale preferences for US or UK. + # Default is to use a neutral variety of English. + # Setting locale to US will correct the British spelling of 'colour' to 'color'. + locale: US + ignore-words: + - fortio + nakedret: + # make an issue if func has more lines of code than this setting and it has naked returns; default is 30 + max-func-lines: 30 + nolintlint: + require-specific: true + whitespace: + multi-if: false # Enforces newlines (or comments) after every multi-line if statement + multi-func: false # Enforces newlines (or comments) after every multi-line function signature + gofumpt: + # Choose whether or not to use the extra rules that are disabled + # by default + extra-rules: false + + +linters: + disable: + # bad ones: + - musttag + # Deprecated ones: + - scopelint + - golint + - interfacer + - maligned + - varcheck + - structcheck + - nosnakecase + - deadcode + # Weird/bad ones: + - wsl + - nlreturn + - gochecknoinits + - gochecknoglobals + - gomnd + - testpackage + - wrapcheck + - exhaustivestruct + - tagliatelle + - nonamedreturns + - varnamelen + - exhaustruct # seems like a good idea at first but actually a pain and go does have zero values for a reason. +# TODO consider putting these back, when they stop being bugged (ifshort, wastedassign,...) + - paralleltest + - thelper + - forbidigo + - ifshort + - wastedassign + - cyclop + - forcetypeassert + - ireturn + enable-all: true + disable-all: false + # Must not use fast: true in newer golangci-lint or it'll just skip a bunch of linter instead of doing caching like before (!) + fast: false + + +issues: + # Excluding configuration per-path, per-linter, per-text and per-source + exclude-rules: + # Exclude some linters from running on tests files. + - path: _test\.go + linters: + - gocyclo + - errcheck + - dupl + - gosec + - gochecknoinits + - gochecknoglobals + - forcetypeassert + - nosnakecase + - noctx + + # Exclude lll issues for long lines with go:generate + - linters: + - lll + source: "^//go:generate " + - linters: + - goerr113 + text: "do not define dynamic errors" + - linters: + - govet + text: "fieldalignment:" + - linters: + - godox + text: "TODO" + - linters: + - nosnakecase + text: "grpc_|_SERVING|O_" + + # Maximum issues count per one linter. Set to 0 to disable. Default is 50. + max-issues-per-linter: 0 + + # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. + max-same-issues: 0 + +severity: + # Default value is empty string. + # Set the default severity for issues. If severity rules are defined and the issues + # do not match or no severity is provided to the rule this will be the default + # severity applied. Severities should match the supported severity names of the + # selected out format. + # - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity + # - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#severity + # - Github: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message + default-severity: error + + # The default value is false. + # If set to true severity-rules regular expressions become case sensitive. + case-sensitive: false diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/fortio.org/scli/LICENSE new/vendor/fortio.org/scli/LICENSE --- old/vendor/fortio.org/scli/LICENSE 1970-01-01 01:00:00.000000000 +0100 +++ new/vendor/fortio.org/scli/LICENSE 2023-02-21 10:25:47.000000000 +0100 @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/fortio.org/scli/README.md new/vendor/fortio.org/scli/README.md --- old/vendor/fortio.org/scli/README.md 1970-01-01 01:00:00.000000000 +0100 +++ new/vendor/fortio.org/scli/README.md 2023-02-21 10:25:47.000000000 +0100 @@ -0,0 +1,91 @@ +[](https://pkg.go.dev/fortio.org/scli) +[](https://goreportcard.com/report/fortio.org/scli) +[](https://github.com/fortio/scli/releases/) +# scli + +Extends [cli](https://github.com/fortio/cli#cli) to server `main()`s . + +In addition to flags, usage and help output, arguments validation, `scli` abstracts the repetitive parts of a `main()` to setup a config directory watch for [dynamic flags](https://github.com/fortio/dflag) (configmap in kubernetes cases) and configuration endpoint/UI/api. + +You can see real use example in a server like [proxy](https://github.com/fortio/proxy). + +## Server Example + +Server example [sampleServer](sampleServer/main.go) + +```bash +% go run . -config-dir ./config -config-port 8888 a b +15:45:20 I updater.go:47> Configmap flag value watching on ./config +15:45:20 I updater.go:156> updating loglevel to "verbose\n" +15:45:20 I logger.go:183> Log level is now 1 Verbose (was 2 Info) +15:45:20 I updater.go:97> Now watching . and config +15:45:20 I updater.go:162> Background thread watching config now running +15:45:20 Fortio 1.50.1 config server listening on tcp [::]:8888 +15:45:20 Starting sampleServer dev go1.19.6 arm64 darwin +# When visiting the UI +15:46:20 ListFlags: GET / HTTP/1.1 [::1]:52406 () "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" +``` + +With the flags ui on http://localhost:8888 + +<img width="716" alt="flags UI" src="https://user-images.githubusercontent.com/3664595/219904547-368a024e-1d6a-4301-a7a9-8882e37f5a90.png"> + +## Additional builtins +(coming from `cli`'s base module) + +### buildinfo + +e.g + +```bash +$ go install fortio.org/cli/sampleServer@latest +go: downloading fortio.org/cli v0.1.0 +$ sampleServer buildinfo +0.1.0 h1:M+coC8So/41xSyGiiJ/6RS+XhnshNUslZuaB6H8z9GI= go1.19.6 arm64 darwin +go go1.19.6 +path fortio.org/cli/sampleServer +mod fortio.org/cli v0.1.0 h1:M+coC8So/41xSyGiiJ/6RS+XhnshNUslZuaB6H8z9GI= +dep fortio.org/dflag v1.4.1 h1:WDhlHMh3yrQFrvspyN5YEyr8WATdKM2dUJlTxsjCDtI= +dep fortio.org/fortio v1.50.1 h1:5FSttAHQsyAsi3dzxDmSByfzDYByrWY/yw53bqOg+Kc= +dep fortio.org/log v1.2.2 h1:vs42JjNwiqbMbacittZjJE9+oi72Za6aekML9gKmILg= +dep fortio.org/version v1.0.2 h1:8NwxdX58aoeKx7T5xAPO0xlUu1Hpk42nRz5s6e6eKZ0= +dep github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +dep github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +dep golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb h1:PaBZQdo+iSDyHT053FjUCgZQ/9uqVwPOcl7KSWhKn6w= +dep golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +dep golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +dep golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +build -compiler=gc +build CGO_ENABLED=1 +build CGO_CFLAGS= +build CGO_CPPFLAGS= +build CGO_CXXFLAGS= +build CGO_LDFLAGS= +build GOARCH=arm64 +build GOOS=darwin +``` + +### help +```bash +$ sampleServer help +sampleServer 0.1.0 usage: + sampleServer [flags] arg1 arg2 [arg3...arg4] +or 1 of the special arguments + sampleServer {help|version|buildinfo} +flags: + -config-dir directory + Config directory to watch for dynamic flag changes + -config-port port + Config port to open for dynamic flag UI/api + -loglevel level + log level, one of [Debug Verbose Info Warning Error Critical Fatal] (default Info) + -quiet + Quiet mode, sets log level to warning +``` + +### version +Short 'numeric' version (v skipped, useful for docker image tags etc) +```bash +$ sampleServer version +0.1.1 +``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/fortio.org/scli/cli.go new/vendor/fortio.org/scli/cli.go --- old/vendor/fortio.org/scli/cli.go 1970-01-01 01:00:00.000000000 +0100 +++ new/vendor/fortio.org/scli/cli.go 2023-02-21 10:25:47.000000000 +0100 @@ -0,0 +1,55 @@ +// Fortio CLI/Main utilities. +// +// (c) 2023 Fortio Authors +// See LICENSE + +// Package scli extends [cli] for server main()s +// [ServerMain] allows the setup of a confimap/directory watch for flags +// and a config endpoint (uses [fortio.org/dflag]). +// Configure using the [cli] package variables (at minimum [MinArgs] unless your +// binary only accepts flags), setup additional [flag] before calling +// [ServerMain]. +package scli // import "fortio.org/scli" + +import ( + "flag" + + "fortio.org/cli" + "fortio.org/dflag/configmap" + "fortio.org/dflag/dynloglevel" + "fortio.org/dflag/endpoint" + "fortio.org/fortio/fhttp" + "fortio.org/log" +) + +// ServerMain extends [cli.Main] and returns true if a config port server has been started +// caller needs to select {} after their own code is ready. +// [cli.ExitFunction] will have been called (ie program will have exited exited) +// if there are usage errors (wrong number of arguments, bad flags etc...). +// It sets up (optional) config-dir to watch and listen on config-port for dynamic flag +// changes and UI/api. +func ServerMain() bool { + configDir := flag.String("config-dir", "", "Config `directory` to watch for dynamic flag changes") + configPort := flag.String("config-port", "", "Config `port` to open for dynamic flag UI/api") + dynloglevel.LoggerFlagSetup("loglevel") + cli.ServerMode = true + cli.Main() // will call ExitFunction() if there are usage errors + if *configDir != "" { + if _, err := configmap.Setup(flag.CommandLine, *configDir); err != nil { + log.Critf("Unable to watch config/flag changes in %v: %v", *configDir, err) + } + } + hasStartedServer := false + if *configPort != "" { + mux, addr := fhttp.HTTPServer("config", *configPort) // err already logged + if addr != nil { + hasStartedServer = true + setURL := "/set" + ep := endpoint.NewFlagsEndpoint(flag.CommandLine, setURL) + mux.HandleFunc("/", ep.ListFlags) + mux.HandleFunc(setURL, ep.SetFlag) + } + } + log.Infof("Starting %s %s", cli.ProgramName, cli.LongVersion) + return hasStartedServer +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/vendor/modules.txt new/vendor/modules.txt --- old/vendor/modules.txt 2023-02-18 09:07:00.000000000 +0100 +++ new/vendor/modules.txt 2023-02-21 10:25:47.000000000 +0100 @@ -1,7 +1,10 @@ # fortio.org/assert v1.1.3 ## explicit; go 1.18 fortio.org/assert -# fortio.org/dflag v1.4.1 +# fortio.org/cli v1.1.0 +## explicit; go 1.18 +fortio.org/cli +# fortio.org/dflag v1.4.2 ## explicit; go 1.19 fortio.org/dflag fortio.org/dflag/configmap @@ -10,6 +13,9 @@ # fortio.org/log v1.2.2 ## explicit; go 1.18 fortio.org/log +# fortio.org/scli v1.1.0 +## explicit; go 1.18 +fortio.org/scli # fortio.org/version v1.0.2 ## explicit; go 1.18 fortio.org/version