mirror of
https://github.com/VictoriaMetrics/VictoriaMetrics.git
synced 2024-11-21 14:44:00 +00:00
adds new Array Flags (#965)
* adds ArrayDuration and ArrayBool flags, makes sendTimeout and tlsInsecure configurable per remoteWrite url * added backward compatibility testcases for ArrayDuration and ArrayBool * fixes bool flag * fixes test cases
This commit is contained in:
parent
60fcac4878
commit
95c9b630cc
3 changed files with 233 additions and 7 deletions
|
@ -4,7 +4,6 @@ import (
|
|||
"bytes"
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
@ -21,11 +20,11 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
sendTimeout = flag.Duration("remoteWrite.sendTimeout", time.Minute, "Timeout for sending a single block of data to -remoteWrite.url")
|
||||
sendTimeout = flagutil.NewArrayDuration("remoteWrite.sendTimeout", "Timeout for sending a single block of data to -remoteWrite.url")
|
||||
proxyURL = flagutil.NewArray("remoteWrite.proxyURL", "Optional proxy URL for writing data to -remoteWrite.url. Supported proxies: http, https, socks5. "+
|
||||
"Example: -remoteWrite.proxyURL=socks5://proxy:1234")
|
||||
|
||||
tlsInsecureSkipVerify = flag.Bool("remoteWrite.tlsInsecureSkipVerify", false, "Whether to skip tls verification when connecting to -remoteWrite.url")
|
||||
tlsInsecureSkipVerify = flagutil.NewArrayBool("remoteWrite.tlsInsecureSkipVerify", "Whether to skip tls verification when connecting to -remoteWrite.url")
|
||||
tlsCertFile = flagutil.NewArray("remoteWrite.tlsCertFile", "Optional path to client-side TLS certificate file to use when connecting to -remoteWrite.url. "+
|
||||
"If multiple args are set, then they are applied independently for the corresponding -remoteWrite.url")
|
||||
tlsKeyFile = flagutil.NewArray("remoteWrite.tlsKeyFile", "Optional path to client-side TLS certificate key to use when connecting to -remoteWrite.url. "+
|
||||
|
@ -108,7 +107,7 @@ func newClient(argIdx int, remoteWriteURL, sanitizedURL string, fq *persistentqu
|
|||
fq: fq,
|
||||
hc: &http.Client{
|
||||
Transport: tr,
|
||||
Timeout: *sendTimeout,
|
||||
Timeout: sendTimeout.GetOptionalArgOrDefault(argIdx, time.Minute),
|
||||
},
|
||||
stopCh: make(chan struct{}),
|
||||
}
|
||||
|
@ -140,7 +139,7 @@ func getTLSConfig(argIdx int) (*tls.Config, error) {
|
|||
CertFile: tlsCertFile.GetOptionalArg(argIdx),
|
||||
KeyFile: tlsKeyFile.GetOptionalArg(argIdx),
|
||||
ServerName: tlsServerName.GetOptionalArg(argIdx),
|
||||
InsecureSkipVerify: *tlsInsecureSkipVerify,
|
||||
InsecureSkipVerify: tlsInsecureSkipVerify.GetOptionalArg(argIdx),
|
||||
}
|
||||
if c.CAFile == "" && c.CertFile == "" && c.KeyFile == "" && c.ServerName == "" && !c.InsecureSkipVerify {
|
||||
return nil, nil
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// NewArray returns new Array with the given name and description.
|
||||
|
@ -16,6 +17,24 @@ func NewArray(name, description string) *Array {
|
|||
return &a
|
||||
}
|
||||
|
||||
// NewArrayDuration returns new ArrayDuration with the given name and description.
|
||||
func NewArrayDuration(name, description string) *ArrayDuration {
|
||||
description += "\nSupports `array` of values separated by comma" +
|
||||
" or specified via multiple flags."
|
||||
var a ArrayDuration
|
||||
flag.Var(&a, name, description)
|
||||
return &a
|
||||
}
|
||||
|
||||
// NewArrayBool returns new ArrayBool with the given name and description.
|
||||
func NewArrayBool(name, description string) *ArrayBool {
|
||||
description += "\nSupports `array` of values separated by comma" +
|
||||
" or specified via multiple flags."
|
||||
var a ArrayBool
|
||||
flag.Var(&a, name, description)
|
||||
return &a
|
||||
}
|
||||
|
||||
// Array is a flag that holds an array of values.
|
||||
//
|
||||
// It may be set either by specifying multiple flags with the given name
|
||||
|
@ -124,3 +143,83 @@ func (a *Array) GetOptionalArg(argIdx int) string {
|
|||
}
|
||||
return x[argIdx]
|
||||
}
|
||||
|
||||
// ArrayBool is a flag that holds an array of booleans values.
|
||||
// have the same api as Array.
|
||||
type ArrayBool []bool
|
||||
|
||||
// IsBoolFlag implements flag.IsBoolFlag interface
|
||||
func (a *ArrayBool) IsBoolFlag() bool { return true }
|
||||
|
||||
// String implements flag.Value interface
|
||||
func (a *ArrayBool) String() string {
|
||||
formattedBools := make([]string, len(*a))
|
||||
for i, v := range *a {
|
||||
formattedBools[i] = strconv.FormatBool(v)
|
||||
}
|
||||
return strings.Join(formattedBools, ",")
|
||||
}
|
||||
|
||||
// Set implements flag.Value interface
|
||||
func (a *ArrayBool) Set(value string) error {
|
||||
values := parseArrayValues(value)
|
||||
for _, v := range values {
|
||||
b, err := strconv.ParseBool(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*a = append(*a, b)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetOptionalArg returns optional arg under the given argIdx.
|
||||
func (a *ArrayBool) GetOptionalArg(argIdx int) bool {
|
||||
x := *a
|
||||
if argIdx >= len(x) {
|
||||
if len(x) == 1 {
|
||||
return x[0]
|
||||
}
|
||||
return false
|
||||
}
|
||||
return x[argIdx]
|
||||
}
|
||||
|
||||
// ArrayDuration is a flag that holds an array of time.Duration values.
|
||||
// have the same api as Array.
|
||||
type ArrayDuration []time.Duration
|
||||
|
||||
// String implements flag.Value interface
|
||||
func (a *ArrayDuration) String() string {
|
||||
formattedBools := make([]string, len(*a))
|
||||
for i, v := range *a {
|
||||
formattedBools[i] = v.String()
|
||||
}
|
||||
return strings.Join(formattedBools, ",")
|
||||
}
|
||||
|
||||
// Set implements flag.Value interface
|
||||
func (a *ArrayDuration) Set(value string) error {
|
||||
values := parseArrayValues(value)
|
||||
for _, v := range values {
|
||||
b, err := time.ParseDuration(v)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*a = append(*a, b)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetOptionalArgOrDefault returns optional arg under the given argIdx,
|
||||
// or default value, if argIdx not found.
|
||||
func (a *ArrayDuration) GetOptionalArgOrDefault(argIdx int, defaultValue time.Duration) time.Duration {
|
||||
x := *a
|
||||
if argIdx >= len(x) {
|
||||
if len(x) == 1 {
|
||||
return x[0]
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
return x[argIdx]
|
||||
}
|
||||
|
|
|
@ -5,13 +5,21 @@ import (
|
|||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var fooFlag Array
|
||||
var (
|
||||
fooFlag Array
|
||||
fooFlagDuration ArrayDuration
|
||||
fooFlagBool ArrayBool
|
||||
)
|
||||
|
||||
func init() {
|
||||
os.Args = append(os.Args, "--fooFlag=foo", "--fooFlag=bar")
|
||||
os.Args = append(os.Args, "--fooFlag=foo", "--fooFlag=bar", "--fooFlagDuration=10s", "--fooFlagDuration=5m")
|
||||
os.Args = append(os.Args, "--fooFlagBool=true", "--fooFlagBool=false,true", "--fooFlagBool")
|
||||
flag.Var(&fooFlag, "fooFlag", "test")
|
||||
flag.Var(&fooFlagDuration, "fooFlagDuration", "test")
|
||||
flag.Var(&fooFlagBool, "fooFlagBool", "test")
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
@ -91,3 +99,123 @@ func TestArrayString(t *testing.T) {
|
|||
f(`", foo","b\"ar",`)
|
||||
f(`,"\nfoo\\",bar`)
|
||||
}
|
||||
|
||||
func TestArrayDuration(t *testing.T) {
|
||||
expected := map[time.Duration]struct{}{
|
||||
time.Second * 10: {},
|
||||
time.Minute * 5: {},
|
||||
}
|
||||
if len(expected) != len(fooFlagDuration) {
|
||||
t.Errorf("len array flag (%d) is not equal to %d", len(fooFlag), len(expected))
|
||||
}
|
||||
for _, i := range fooFlagDuration {
|
||||
if _, ok := expected[i]; !ok {
|
||||
t.Errorf("unexpected item in array %v", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestArrayDurationSet(t *testing.T) {
|
||||
f := func(s string, expectedValues []time.Duration) {
|
||||
t.Helper()
|
||||
var a ArrayDuration
|
||||
_ = a.Set(s)
|
||||
if !reflect.DeepEqual([]time.Duration(a), expectedValues) {
|
||||
t.Fatalf("unexpected values parsed;\ngot\n%q\nwant\n%q", a, expectedValues)
|
||||
}
|
||||
}
|
||||
f("", nil)
|
||||
f(`1m`, []time.Duration{time.Minute})
|
||||
f(`5m,1s,1h`, []time.Duration{time.Minute * 5, time.Second, time.Hour})
|
||||
}
|
||||
|
||||
func TestArrayDurationGetOptionalArg(t *testing.T) {
|
||||
f := func(s string, argIdx int, expectedValue time.Duration, defaultValue time.Duration) {
|
||||
t.Helper()
|
||||
var a ArrayDuration
|
||||
_ = a.Set(s)
|
||||
v := a.GetOptionalArgOrDefault(argIdx, defaultValue)
|
||||
if v != expectedValue {
|
||||
t.Fatalf("unexpected value; got %q; want %q", v, expectedValue)
|
||||
}
|
||||
}
|
||||
f("", 0, time.Second, time.Second)
|
||||
f("", 1, time.Minute, time.Minute)
|
||||
f("10s,1m", 1, time.Minute, time.Minute)
|
||||
f("10s", 3, time.Second*10, time.Minute)
|
||||
}
|
||||
|
||||
func TestArrayDurationString(t *testing.T) {
|
||||
f := func(s string) {
|
||||
t.Helper()
|
||||
var a ArrayDuration
|
||||
_ = a.Set(s)
|
||||
result := a.String()
|
||||
if result != s {
|
||||
t.Fatalf("unexpected string;\ngot\n%s\nwant\n%s", result, s)
|
||||
}
|
||||
}
|
||||
f("")
|
||||
f("10s,1m0s")
|
||||
f("5m0s,1s")
|
||||
}
|
||||
|
||||
func TestArrayBool(t *testing.T) {
|
||||
expected := []bool{
|
||||
true, false, true, true,
|
||||
}
|
||||
if len(expected) != len(fooFlagBool) {
|
||||
t.Errorf("len array flag (%d) is not equal to %d", len(fooFlag), len(expected))
|
||||
}
|
||||
for i, v := range fooFlagBool {
|
||||
if v != expected[i] {
|
||||
t.Errorf("unexpected item in array index=%v,value=%v,want=%v", i, v, expected[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestArrayBoolSet(t *testing.T) {
|
||||
f := func(s string, expectedValues []bool) {
|
||||
t.Helper()
|
||||
var a ArrayBool
|
||||
_ = a.Set(s)
|
||||
if !reflect.DeepEqual([]bool(a), expectedValues) {
|
||||
t.Fatalf("unexpected values parsed;\ngot\n%v\nwant\n%v", a, expectedValues)
|
||||
}
|
||||
}
|
||||
f("", nil)
|
||||
f(`true`, []bool{true})
|
||||
f(`false,True,False`, []bool{false, true, false})
|
||||
}
|
||||
|
||||
func TestArrayBoolGetOptionalArg(t *testing.T) {
|
||||
f := func(s string, argIdx int, expectedValue bool) {
|
||||
t.Helper()
|
||||
var a ArrayBool
|
||||
_ = a.Set(s)
|
||||
v := a.GetOptionalArg(argIdx)
|
||||
if v != expectedValue {
|
||||
t.Fatalf("unexpected value; got %v; want %v", v, expectedValue)
|
||||
}
|
||||
}
|
||||
f("", 0, false)
|
||||
f("", 1, false)
|
||||
f("true,true,false", 1, true)
|
||||
f("true", 2, true)
|
||||
}
|
||||
|
||||
func TestArrayBoolString(t *testing.T) {
|
||||
f := func(s string) {
|
||||
t.Helper()
|
||||
var a ArrayBool
|
||||
_ = a.Set(s)
|
||||
result := a.String()
|
||||
if result != s {
|
||||
t.Fatalf("unexpected string;\ngot\n%s\nwant\n%s", result, s)
|
||||
}
|
||||
}
|
||||
f("")
|
||||
f("true")
|
||||
f("true,false")
|
||||
f("false,true")
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue