mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 18:48:08 +00:00 
			
		
		
		
	Port: Telemetry For Lease Expiration Times (#10375)
* port lease metrics * go mod vendor * caught a bug
This commit is contained in:
		| @@ -30,6 +30,10 @@ func TestLoadConfigFileIntegerAndBooleanValuesJson(t *testing.T) { | |||||||
| 	testLoadConfigFileIntegerAndBooleanValuesJson(t) | 	testLoadConfigFileIntegerAndBooleanValuesJson(t) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestLoadConfigFileWithLeaseMetricTelemetry(t *testing.T) { | ||||||
|  | 	testLoadConfigFileLeaseMetrics(t) | ||||||
|  | } | ||||||
|  |  | ||||||
| func TestLoadConfigDir(t *testing.T) { | func TestLoadConfigDir(t *testing.T) { | ||||||
| 	testLoadConfigDir(t) | 	testLoadConfigDir(t) | ||||||
| } | } | ||||||
|   | |||||||
| @@ -62,14 +62,17 @@ func testLoadConfigFile_topLevel(t *testing.T, entropy *configutil.Entropy) { | |||||||
| 			}, | 			}, | ||||||
|  |  | ||||||
| 			Telemetry: &configutil.Telemetry{ | 			Telemetry: &configutil.Telemetry{ | ||||||
| 				StatsdAddr:              "bar", | 				StatsdAddr:                  "bar", | ||||||
| 				StatsiteAddr:            "foo", | 				StatsiteAddr:                "foo", | ||||||
| 				DisableHostname:         false, | 				DisableHostname:             false, | ||||||
| 				DogStatsDAddr:           "127.0.0.1:7254", | 				DogStatsDAddr:               "127.0.0.1:7254", | ||||||
| 				DogStatsDTags:           []string{"tag_1:val_1", "tag_2:val_2"}, | 				DogStatsDTags:               []string{"tag_1:val_1", "tag_2:val_2"}, | ||||||
| 				PrometheusRetentionTime: 30 * time.Second, | 				PrometheusRetentionTime:     30 * time.Second, | ||||||
| 				UsageGaugePeriod:        5 * time.Minute, | 				UsageGaugePeriod:            5 * time.Minute, | ||||||
| 				MaximumGaugeCardinality: 125, | 				MaximumGaugeCardinality:     125, | ||||||
|  | 				LeaseMetricsEpsilon:         time.Hour, | ||||||
|  | 				NumLeaseMetricsTimeBuckets:  168, | ||||||
|  | 				LeaseMetricsNameSpaceLabels: false, | ||||||
| 			}, | 			}, | ||||||
|  |  | ||||||
| 			DisableMlock: true, | 			DisableMlock: true, | ||||||
| @@ -192,6 +195,9 @@ func testLoadConfigFile_json2(t *testing.T, entropy *configutil.Entropy) { | |||||||
| 				CirconusBrokerID:                   "0", | 				CirconusBrokerID:                   "0", | ||||||
| 				CirconusBrokerSelectTag:            "dc:sfo", | 				CirconusBrokerSelectTag:            "dc:sfo", | ||||||
| 				PrometheusRetentionTime:            30 * time.Second, | 				PrometheusRetentionTime:            30 * time.Second, | ||||||
|  | 				LeaseMetricsEpsilon:                time.Hour, | ||||||
|  | 				NumLeaseMetricsTimeBuckets:         168, | ||||||
|  | 				LeaseMetricsNameSpaceLabels:        false, | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
|  |  | ||||||
| @@ -371,15 +377,18 @@ func testLoadConfigFile(t *testing.T) { | |||||||
| 			}, | 			}, | ||||||
|  |  | ||||||
| 			Telemetry: &configutil.Telemetry{ | 			Telemetry: &configutil.Telemetry{ | ||||||
| 				StatsdAddr:              "bar", | 				StatsdAddr:                  "bar", | ||||||
| 				StatsiteAddr:            "foo", | 				StatsiteAddr:                "foo", | ||||||
| 				DisableHostname:         false, | 				DisableHostname:             false, | ||||||
| 				UsageGaugePeriod:        5 * time.Minute, | 				UsageGaugePeriod:            5 * time.Minute, | ||||||
| 				MaximumGaugeCardinality: 100, | 				MaximumGaugeCardinality:     100, | ||||||
| 				DogStatsDAddr:           "127.0.0.1:7254", | 				DogStatsDAddr:               "127.0.0.1:7254", | ||||||
| 				DogStatsDTags:           []string{"tag_1:val_1", "tag_2:val_2"}, | 				DogStatsDTags:               []string{"tag_1:val_1", "tag_2:val_2"}, | ||||||
| 				PrometheusRetentionTime: configutil.PrometheusDefaultRetentionTime, | 				PrometheusRetentionTime:     configutil.PrometheusDefaultRetentionTime, | ||||||
| 				MetricsPrefix:           "myprefix", | 				MetricsPrefix:               "myprefix", | ||||||
|  | 				LeaseMetricsEpsilon:         time.Hour, | ||||||
|  | 				NumLeaseMetricsTimeBuckets:  168, | ||||||
|  | 				LeaseMetricsNameSpaceLabels: false, | ||||||
| 			}, | 			}, | ||||||
|  |  | ||||||
| 			DisableMlock: true, | 			DisableMlock: true, | ||||||
| @@ -477,6 +486,9 @@ func testLoadConfigFile_json(t *testing.T) { | |||||||
| 				CirconusBrokerID:                   "", | 				CirconusBrokerID:                   "", | ||||||
| 				CirconusBrokerSelectTag:            "", | 				CirconusBrokerSelectTag:            "", | ||||||
| 				PrometheusRetentionTime:            configutil.PrometheusDefaultRetentionTime, | 				PrometheusRetentionTime:            configutil.PrometheusDefaultRetentionTime, | ||||||
|  | 				LeaseMetricsEpsilon:                time.Hour, | ||||||
|  | 				NumLeaseMetricsTimeBuckets:         168, | ||||||
|  | 				LeaseMetricsNameSpaceLabels:        false, | ||||||
| 			}, | 			}, | ||||||
|  |  | ||||||
| 			PidFile:     "./pidfile", | 			PidFile:     "./pidfile", | ||||||
| @@ -540,12 +552,15 @@ func testLoadConfigDir(t *testing.T) { | |||||||
| 			}, | 			}, | ||||||
|  |  | ||||||
| 			Telemetry: &configutil.Telemetry{ | 			Telemetry: &configutil.Telemetry{ | ||||||
| 				StatsiteAddr:            "qux", | 				StatsiteAddr:                "qux", | ||||||
| 				StatsdAddr:              "baz", | 				StatsdAddr:                  "baz", | ||||||
| 				DisableHostname:         true, | 				DisableHostname:             true, | ||||||
| 				UsageGaugePeriod:        5 * time.Minute, | 				UsageGaugePeriod:            5 * time.Minute, | ||||||
| 				MaximumGaugeCardinality: 100, | 				MaximumGaugeCardinality:     100, | ||||||
| 				PrometheusRetentionTime: configutil.PrometheusDefaultRetentionTime, | 				PrometheusRetentionTime:     configutil.PrometheusDefaultRetentionTime, | ||||||
|  | 				LeaseMetricsEpsilon:         time.Hour, | ||||||
|  | 				NumLeaseMetricsTimeBuckets:  168, | ||||||
|  | 				LeaseMetricsNameSpaceLabels: false, | ||||||
| 			}, | 			}, | ||||||
| 			ClusterName: "testcluster", | 			ClusterName: "testcluster", | ||||||
| 		}, | 		}, | ||||||
| @@ -668,6 +683,9 @@ func testConfig_Sanitized(t *testing.T) { | |||||||
| 			"stackdriver_debug_logs":                 false, | 			"stackdriver_debug_logs":                 false, | ||||||
| 			"statsd_address":                         "bar", | 			"statsd_address":                         "bar", | ||||||
| 			"statsite_address":                       "", | 			"statsite_address":                       "", | ||||||
|  | 			"lease_metrics_epsilon":                  time.Hour, | ||||||
|  | 			"num_lease_metrics_buckets":              168, | ||||||
|  | 			"add_lease_metrics_namespace_labels":     false, | ||||||
| 		}, | 		}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| @@ -787,3 +805,93 @@ func testParseSeals(t *testing.T) { | |||||||
| 	} | 	} | ||||||
| 	require.Equal(t, config, expected) | 	require.Equal(t, config, expected) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func testLoadConfigFileLeaseMetrics(t *testing.T) { | ||||||
|  | 	config, err := LoadConfigFile("./test-fixtures/config5.hcl") | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatalf("err: %s", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	expected := &Config{ | ||||||
|  | 		SharedConfig: &configutil.SharedConfig{ | ||||||
|  | 			Listeners: []*configutil.Listener{ | ||||||
|  | 				{ | ||||||
|  | 					Type:    "tcp", | ||||||
|  | 					Address: "127.0.0.1:443", | ||||||
|  | 				}, | ||||||
|  | 			}, | ||||||
|  |  | ||||||
|  | 			Telemetry: &configutil.Telemetry{ | ||||||
|  | 				StatsdAddr:                  "bar", | ||||||
|  | 				StatsiteAddr:                "foo", | ||||||
|  | 				DisableHostname:             false, | ||||||
|  | 				UsageGaugePeriod:            5 * time.Minute, | ||||||
|  | 				MaximumGaugeCardinality:     100, | ||||||
|  | 				DogStatsDAddr:               "127.0.0.1:7254", | ||||||
|  | 				DogStatsDTags:               []string{"tag_1:val_1", "tag_2:val_2"}, | ||||||
|  | 				PrometheusRetentionTime:     configutil.PrometheusDefaultRetentionTime, | ||||||
|  | 				MetricsPrefix:               "myprefix", | ||||||
|  | 				LeaseMetricsEpsilon:         time.Hour, | ||||||
|  | 				NumLeaseMetricsTimeBuckets:  2, | ||||||
|  | 				LeaseMetricsNameSpaceLabels: true, | ||||||
|  | 			}, | ||||||
|  |  | ||||||
|  | 			DisableMlock: true, | ||||||
|  |  | ||||||
|  | 			Entropy: nil, | ||||||
|  |  | ||||||
|  | 			PidFile: "./pidfile", | ||||||
|  |  | ||||||
|  | 			ClusterName: "testcluster", | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		Storage: &Storage{ | ||||||
|  | 			Type:         "consul", | ||||||
|  | 			RedirectAddr: "foo", | ||||||
|  | 			Config: map[string]string{ | ||||||
|  | 				"foo": "bar", | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		HAStorage: &Storage{ | ||||||
|  | 			Type:         "consul", | ||||||
|  | 			RedirectAddr: "snafu", | ||||||
|  | 			Config: map[string]string{ | ||||||
|  | 				"bar": "baz", | ||||||
|  | 			}, | ||||||
|  | 			DisableClustering: true, | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		ServiceRegistration: &ServiceRegistration{ | ||||||
|  | 			Type: "consul", | ||||||
|  | 			Config: map[string]string{ | ||||||
|  | 				"foo": "bar", | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  |  | ||||||
|  | 		DisableCache:             true, | ||||||
|  | 		DisableCacheRaw:          true, | ||||||
|  | 		DisablePrintableCheckRaw: true, | ||||||
|  | 		DisablePrintableCheck:    true, | ||||||
|  | 		EnableUI:                 true, | ||||||
|  | 		EnableUIRaw:              true, | ||||||
|  |  | ||||||
|  | 		EnableRawEndpoint:    true, | ||||||
|  | 		EnableRawEndpointRaw: true, | ||||||
|  |  | ||||||
|  | 		DisableSealWrap:    true, | ||||||
|  | 		DisableSealWrapRaw: true, | ||||||
|  |  | ||||||
|  | 		MaxLeaseTTL:        10 * time.Hour, | ||||||
|  | 		MaxLeaseTTLRaw:     "10h", | ||||||
|  | 		DefaultLeaseTTL:    10 * time.Hour, | ||||||
|  | 		DefaultLeaseTTLRaw: "10h", | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	addExpectedEntConfig(expected, []string{}) | ||||||
|  |  | ||||||
|  | 	config.Listeners[0].RawConfig = nil | ||||||
|  | 	if diff := deep.Equal(config, expected); diff != nil { | ||||||
|  | 		t.Fatal(diff) | ||||||
|  | 	} | ||||||
|  | } | ||||||
|   | |||||||
							
								
								
									
										51
									
								
								command/server/test-fixtures/config5.hcl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								command/server/test-fixtures/config5.hcl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | |||||||
|  | disable_cache = true | ||||||
|  |  disable_mlock = true | ||||||
|  |  | ||||||
|  |  ui = true | ||||||
|  |  | ||||||
|  |  listener "tcp" { | ||||||
|  |      address = "127.0.0.1:443" | ||||||
|  |  	allow_stuff = true | ||||||
|  |  } | ||||||
|  |  | ||||||
|  |  backend "consul" { | ||||||
|  |      foo = "bar" | ||||||
|  |      advertise_addr = "foo" | ||||||
|  |  } | ||||||
|  |  | ||||||
|  |  ha_backend "consul" { | ||||||
|  |      bar = "baz" | ||||||
|  |      advertise_addr = "snafu" | ||||||
|  |      disable_clustering = "true" | ||||||
|  |  } | ||||||
|  |  | ||||||
|  |  service_registration "consul" { | ||||||
|  |      foo = "bar" | ||||||
|  |  } | ||||||
|  |  | ||||||
|  |  telemetry { | ||||||
|  |      statsd_address = "bar" | ||||||
|  |      usage_gauge_period = "5m" | ||||||
|  |      maximum_gauge_cardinality = 100 | ||||||
|  |  | ||||||
|  |      statsite_address = "foo" | ||||||
|  |      dogstatsd_addr = "127.0.0.1:7254" | ||||||
|  |      dogstatsd_tags = ["tag_1:val_1", "tag_2:val_2"] | ||||||
|  |      metrics_prefix = "myprefix" | ||||||
|  |  | ||||||
|  |      lease_metrics_epsilon = "1h" | ||||||
|  |      num_lease_metrics_buckets = 2 | ||||||
|  |      add_lease_metrics_namespace_labels = true  | ||||||
|  |  } | ||||||
|  |  | ||||||
|  |  sentinel { | ||||||
|  |      additional_enabled_modules = [] | ||||||
|  |  } | ||||||
|  |  | ||||||
|  |  max_lease_ttl = "10h" | ||||||
|  |  default_lease_ttl = "10h" | ||||||
|  |  cluster_name = "testcluster" | ||||||
|  |  pid_file = "./pidfile" | ||||||
|  |  raw_storage_endpoint = true | ||||||
|  |  disable_sealwrap = true | ||||||
|  |  disable_printable_check = true | ||||||
| @@ -37,3 +37,22 @@ func TTLBucket(ttl time.Duration) string { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func ExpiryBucket(expiryTime time.Time, leaseEpsilon time.Duration, rollingWindow time.Time, labelNS string, useNS bool) *LeaseExpiryLabel { | ||||||
|  | 	if !useNS { | ||||||
|  | 		labelNS = "" | ||||||
|  | 	} | ||||||
|  | 	leaseExpiryLabel := LeaseExpiryLabel{LabelNS: labelNS} | ||||||
|  |  | ||||||
|  | 	// calculate rolling window | ||||||
|  | 	if expiryTime.Before(rollingWindow) { | ||||||
|  | 		leaseExpiryLabel.LabelName = expiryTime.Round(leaseEpsilon).String() | ||||||
|  | 		return &leaseExpiryLabel | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type LeaseExpiryLabel = struct { | ||||||
|  | 	LabelName string | ||||||
|  | 	LabelNS   string | ||||||
|  | } | ||||||
|   | |||||||
| @@ -28,6 +28,15 @@ type ClusterMetricSink struct { | |||||||
|  |  | ||||||
| 	// Sink is the go-metrics instance to send to. | 	// Sink is the go-metrics instance to send to. | ||||||
| 	Sink metrics.MetricSink | 	Sink metrics.MetricSink | ||||||
|  |  | ||||||
|  | 	// Constants that are helpful for metrics within the metrics sink | ||||||
|  | 	TelemetryConsts TelemetryConstConfig | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type TelemetryConstConfig struct { | ||||||
|  | 	LeaseMetricsEpsilon         time.Duration | ||||||
|  | 	NumLeaseMetricsTimeBuckets  int | ||||||
|  | 	LeaseMetricsNameSpaceLabels bool | ||||||
| } | } | ||||||
|  |  | ||||||
| type Metrics interface { | type Metrics interface { | ||||||
| @@ -83,8 +92,9 @@ func BlackholeSink() *ClusterMetricSink { | |||||||
|  |  | ||||||
| func NewClusterMetricSink(clusterName string, sink metrics.MetricSink) *ClusterMetricSink { | func NewClusterMetricSink(clusterName string, sink metrics.MetricSink) *ClusterMetricSink { | ||||||
| 	cms := &ClusterMetricSink{ | 	cms := &ClusterMetricSink{ | ||||||
| 		ClusterName: atomic.Value{}, | 		ClusterName:     atomic.Value{}, | ||||||
| 		Sink:        sink, | 		Sink:            sink, | ||||||
|  | 		TelemetryConsts: TelemetryConstConfig{}, | ||||||
| 	} | 	} | ||||||
| 	cms.ClusterName.Store(clusterName) | 	cms.ClusterName.Store(clusterName) | ||||||
| 	return cms | 	return cms | ||||||
|   | |||||||
| @@ -214,6 +214,9 @@ func (c *SharedConfig) Sanitized() map[string]interface{} { | |||||||
| 			"stackdriver_location":                   c.Telemetry.StackdriverLocation, | 			"stackdriver_location":                   c.Telemetry.StackdriverLocation, | ||||||
| 			"stackdriver_namespace":                  c.Telemetry.StackdriverNamespace, | 			"stackdriver_namespace":                  c.Telemetry.StackdriverNamespace, | ||||||
| 			"stackdriver_debug_logs":                 c.Telemetry.StackdriverDebugLogs, | 			"stackdriver_debug_logs":                 c.Telemetry.StackdriverDebugLogs, | ||||||
|  | 			"lease_metrics_epsilon":                  c.Telemetry.LeaseMetricsEpsilon, | ||||||
|  | 			"num_lease_metrics_buckets":              c.Telemetry.NumLeaseMetricsTimeBuckets, | ||||||
|  | 			"add_lease_metrics_namespace_labels":     c.Telemetry.LeaseMetricsNameSpaceLabels, | ||||||
| 		} | 		} | ||||||
| 		result["telemetry"] = sanitizedTelemetry | 		result["telemetry"] = sanitizedTelemetry | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -24,9 +24,11 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| const ( | const ( | ||||||
| 	PrometheusDefaultRetentionTime = 24 * time.Hour | 	PrometheusDefaultRetentionTime    = 24 * time.Hour | ||||||
| 	UsageGaugeDefaultPeriod        = 10 * time.Minute | 	UsageGaugeDefaultPeriod           = 10 * time.Minute | ||||||
| 	MaximumGaugeCardinalityDefault = 500 | 	MaximumGaugeCardinalityDefault    = 500 | ||||||
|  | 	LeaseMetricsEpsilonDefault        = time.Hour | ||||||
|  | 	NumLeaseMetricsTimeBucketsDefault = 168 | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // Telemetry is the telemetry configuration for the server | // Telemetry is the telemetry configuration for the server | ||||||
| @@ -137,6 +139,16 @@ type Telemetry struct { | |||||||
| 	StackdriverNamespace string `hcl:"stackdriver_namespace"` | 	StackdriverNamespace string `hcl:"stackdriver_namespace"` | ||||||
| 	// StackdriverDebugLogs will write additional stackdriver related debug logs to stderr. | 	// StackdriverDebugLogs will write additional stackdriver related debug logs to stderr. | ||||||
| 	StackdriverDebugLogs bool `hcl:"stackdriver_debug_logs"` | 	StackdriverDebugLogs bool `hcl:"stackdriver_debug_logs"` | ||||||
|  |  | ||||||
|  | 	// How often metrics for lease expiry will be aggregated | ||||||
|  | 	LeaseMetricsEpsilon    time.Duration | ||||||
|  | 	LeaseMetricsEpsilonRaw interface{} `hcl:"lease_metrics_epsilon"` | ||||||
|  |  | ||||||
|  | 	// Number of buckets by time that will be used in lease aggregation | ||||||
|  | 	NumLeaseMetricsTimeBuckets int `hcl:"num_lease_metrics_buckets"` | ||||||
|  |  | ||||||
|  | 	// Whether or not telemetry should add labels for namespaces | ||||||
|  | 	LeaseMetricsNameSpaceLabels bool `hcl:"add_lease_metrics_namespace_labels"` | ||||||
| } | } | ||||||
|  |  | ||||||
| func (t *Telemetry) GoString() string { | func (t *Telemetry) GoString() string { | ||||||
| @@ -151,11 +163,6 @@ func parseTelemetry(result *SharedConfig, list *ast.ObjectList) error { | |||||||
| 	// Get our one item | 	// Get our one item | ||||||
| 	item := list.Items[0] | 	item := list.Items[0] | ||||||
|  |  | ||||||
| 	var t Telemetry |  | ||||||
| 	if err := hcl.DecodeObject(&t, item.Val); err != nil { |  | ||||||
| 		return multierror.Prefix(err, "telemetry:") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if result.Telemetry == nil { | 	if result.Telemetry == nil { | ||||||
| 		result.Telemetry = &Telemetry{} | 		result.Telemetry = &Telemetry{} | ||||||
| 	} | 	} | ||||||
| @@ -192,6 +199,24 @@ func parseTelemetry(result *SharedConfig, list *ast.ObjectList) error { | |||||||
| 		result.Telemetry.MaximumGaugeCardinality = MaximumGaugeCardinalityDefault | 		result.Telemetry.MaximumGaugeCardinality = MaximumGaugeCardinalityDefault | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	if result.Telemetry.LeaseMetricsEpsilonRaw != nil { | ||||||
|  | 		if result.Telemetry.LeaseMetricsEpsilonRaw == "none" { | ||||||
|  | 			result.Telemetry.LeaseMetricsEpsilonRaw = 0 | ||||||
|  | 		} else { | ||||||
|  | 			var err error | ||||||
|  | 			if result.Telemetry.LeaseMetricsEpsilon, err = parseutil.ParseDurationSecond(result.Telemetry.LeaseMetricsEpsilonRaw); err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 			result.Telemetry.LeaseMetricsEpsilonRaw = nil | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		result.Telemetry.LeaseMetricsEpsilon = LeaseMetricsEpsilonDefault | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if result.Telemetry.NumLeaseMetricsTimeBuckets == 0 { | ||||||
|  | 		result.Telemetry.NumLeaseMetricsTimeBuckets = NumLeaseMetricsTimeBucketsDefault | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -355,6 +380,9 @@ func SetupTelemetry(opts *SetupTelemetryOpts) (*metrics.InmemSink, *metricsutil. | |||||||
| 	wrapper := metricsutil.NewClusterMetricSink(opts.ClusterName, globalMetrics) | 	wrapper := metricsutil.NewClusterMetricSink(opts.ClusterName, globalMetrics) | ||||||
| 	wrapper.MaxGaugeCardinality = opts.Config.MaximumGaugeCardinality | 	wrapper.MaxGaugeCardinality = opts.Config.MaximumGaugeCardinality | ||||||
| 	wrapper.GaugeInterval = opts.Config.UsageGaugePeriod | 	wrapper.GaugeInterval = opts.Config.UsageGaugePeriod | ||||||
|  | 	wrapper.TelemetryConsts.LeaseMetricsEpsilon = opts.Config.LeaseMetricsEpsilon | ||||||
|  | 	wrapper.TelemetryConsts.LeaseMetricsNameSpaceLabels = opts.Config.LeaseMetricsNameSpaceLabels | ||||||
|  | 	wrapper.TelemetryConsts.NumLeaseMetricsTimeBuckets = opts.Config.NumLeaseMetricsTimeBuckets | ||||||
|  |  | ||||||
| 	return inm, wrapper, prometheusEnabled, nil | 	return inm, wrapper, prometheusEnabled, nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -116,6 +116,17 @@ func (c *Core) tokenGaugePolicyCollector(ctx context.Context) ([]metricsutil.Gau | |||||||
| 	return ts.gaugeCollectorByPolicy(ctx) | 	return ts.gaugeCollectorByPolicy(ctx) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (c *Core) leaseExpiryGaugeCollector(ctx context.Context) ([]metricsutil.GaugeLabelValues, error) { | ||||||
|  | 	c.stateLock.RLock() | ||||||
|  | 	e := c.expiration | ||||||
|  | 	metricsConsts := c.MetricSink().TelemetryConsts | ||||||
|  | 	c.stateLock.RUnlock() | ||||||
|  | 	if e == nil { | ||||||
|  | 		return []metricsutil.GaugeLabelValues{}, errors.New("nil expiration manager") | ||||||
|  | 	} | ||||||
|  | 	return e.leaseAggregationMetrics(ctx, metricsConsts) | ||||||
|  | } | ||||||
|  |  | ||||||
| func (c *Core) tokenGaugeMethodCollector(ctx context.Context) ([]metricsutil.GaugeLabelValues, error) { | func (c *Core) tokenGaugeMethodCollector(ctx context.Context) ([]metricsutil.GaugeLabelValues, error) { | ||||||
| 	c.stateLock.RLock() | 	c.stateLock.RLock() | ||||||
| 	ts := c.tokenStore | 	ts := c.tokenStore | ||||||
| @@ -164,6 +175,12 @@ func (c *Core) emitMetrics(stopCh chan struct{}) { | |||||||
| 			c.tokenGaugePolicyCollector, | 			c.tokenGaugePolicyCollector, | ||||||
| 			"", | 			"", | ||||||
| 		}, | 		}, | ||||||
|  | 		{ | ||||||
|  | 			[]string{"expire", "leases", "by_expiration"}, | ||||||
|  | 			[]metrics.Label{{"gauge", "leases_by_expiration"}}, | ||||||
|  | 			c.leaseExpiryGaugeCollector, | ||||||
|  | 			"", | ||||||
|  | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			[]string{"token", "count", "by_auth"}, | 			[]string{"token", "count", "by_auth"}, | ||||||
| 			[]metrics.Label{{"gauge", "token_by_auth"}}, | 			[]metrics.Label{{"gauge", "token_by_auth"}}, | ||||||
|   | |||||||
| @@ -17,6 +17,7 @@ import ( | |||||||
| 	"github.com/hashicorp/errwrap" | 	"github.com/hashicorp/errwrap" | ||||||
| 	log "github.com/hashicorp/go-hclog" | 	log "github.com/hashicorp/go-hclog" | ||||||
| 	multierror "github.com/hashicorp/go-multierror" | 	multierror "github.com/hashicorp/go-multierror" | ||||||
|  | 	"github.com/hashicorp/vault/helper/metricsutil" | ||||||
| 	"github.com/hashicorp/vault/helper/namespace" | 	"github.com/hashicorp/vault/helper/namespace" | ||||||
| 	"github.com/hashicorp/vault/sdk/framework" | 	"github.com/hashicorp/vault/sdk/framework" | ||||||
| 	"github.com/hashicorp/vault/sdk/helper/base62" | 	"github.com/hashicorp/vault/sdk/helper/base62" | ||||||
| @@ -1997,6 +1998,66 @@ func (m *ExpirationManager) emitMetrics() { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (m *ExpirationManager) leaseAggregationMetrics(ctx context.Context, consts metricsutil.TelemetryConstConfig) ([]metricsutil.GaugeLabelValues, error) { | ||||||
|  | 	expiryTimes := make(map[metricsutil.LeaseExpiryLabel]int) | ||||||
|  | 	leaseEpsilon := consts.LeaseMetricsEpsilon | ||||||
|  | 	nsLabel := consts.LeaseMetricsNameSpaceLabels | ||||||
|  |  | ||||||
|  | 	rollingWindow := time.Now().Add(time.Duration(consts.NumLeaseMetricsTimeBuckets) * leaseEpsilon) | ||||||
|  |  | ||||||
|  | 	err := m.walkLeases(func(entryID string, expireTime time.Time) bool { | ||||||
|  | 		select { | ||||||
|  | 		// Abort and return empty collection if it's taking too much time, nonblocking check. | ||||||
|  | 		case <-ctx.Done(): | ||||||
|  | 			return false | ||||||
|  | 		default: | ||||||
|  | 			if entryID == "" { | ||||||
|  | 				return true | ||||||
|  | 			} | ||||||
|  | 			_, nsID := namespace.SplitIDFromString(entryID) | ||||||
|  | 			if nsID == "" { | ||||||
|  | 				nsID = "root" // this is what metricsutil.NamespaceLabel does | ||||||
|  | 			} | ||||||
|  | 			label := metricsutil.ExpiryBucket(expireTime, leaseEpsilon, rollingWindow, nsID, nsLabel) | ||||||
|  | 			if label != nil { | ||||||
|  | 				expiryTimes[*label] += 1 | ||||||
|  | 			} | ||||||
|  | 			return true | ||||||
|  | 		} | ||||||
|  | 	}) | ||||||
|  |  | ||||||
|  | 	if err != nil { | ||||||
|  | 		return []metricsutil.GaugeLabelValues{}, suppressRestoreModeError(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// If collection was cancelled, return an empty array. | ||||||
|  | 	select { | ||||||
|  | 	case <-ctx.Done(): | ||||||
|  | 		return []metricsutil.GaugeLabelValues{}, nil | ||||||
|  | 	default: | ||||||
|  | 		break | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	flattenedResults := make([]metricsutil.GaugeLabelValues, 0, len(expiryTimes)) | ||||||
|  |  | ||||||
|  | 	for bucket, count := range expiryTimes { | ||||||
|  | 		if nsLabel { | ||||||
|  | 			flattenedResults = append(flattenedResults, | ||||||
|  | 				metricsutil.GaugeLabelValues{ | ||||||
|  | 					Labels: []metrics.Label{{"expiring", bucket.LabelName}, {"namespace", bucket.LabelNS}}, | ||||||
|  | 					Value:  float32(count), | ||||||
|  | 				}) | ||||||
|  | 		} else { | ||||||
|  | 			flattenedResults = append(flattenedResults, | ||||||
|  | 				metricsutil.GaugeLabelValues{ | ||||||
|  | 					Labels: []metrics.Label{{"expiring", bucket.LabelName}}, | ||||||
|  | 					Value:  float32(count), | ||||||
|  | 				}) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return flattenedResults, nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // Callback function type to walk tokens referenced in the expiration | // Callback function type to walk tokens referenced in the expiration | ||||||
| // manager. Don't want to use leaseEntry here because it's an unexported | // manager. Don't want to use leaseEntry here because it's an unexported | ||||||
| // type (though most likely we would only call this from within the "vault" core package.) | // type (though most likely we would only call this from within the "vault" core package.) | ||||||
| @@ -2031,6 +2092,30 @@ func (m *ExpirationManager) WalkTokens(walkFn ExpirationWalkFunction) error { | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // leaseWalkFunction can only be used by the core package. | ||||||
|  | type leaseWalkFunction = func(leaseID string, expireTime time.Time) bool | ||||||
|  |  | ||||||
|  | func (m *ExpirationManager) walkLeases(walkFn leaseWalkFunction) error { | ||||||
|  | 	if m.inRestoreMode() { | ||||||
|  | 		return ErrInRestoreMode | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	callback := func(key, value interface{}) bool { | ||||||
|  | 		p := value.(pendingInfo) | ||||||
|  | 		if p.cachedLeaseInfo == nil { | ||||||
|  | 			return true | ||||||
|  | 		} | ||||||
|  | 		lease := p.cachedLeaseInfo | ||||||
|  | 		expireTime := lease.ExpireTime | ||||||
|  | 		return walkFn(key.(string), expireTime) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	m.pending.Range(callback) | ||||||
|  | 	m.nonexpiring.Range(callback) | ||||||
|  |  | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // leaseEntry is used to structure the values the expiration | // leaseEntry is used to structure the values the expiration | ||||||
| // manager stores. This is used to handle renew and revocation. | // manager stores. This is used to handle renew and revocation. | ||||||
| type leaseEntry struct { | type leaseEntry struct { | ||||||
|   | |||||||
| @@ -13,8 +13,10 @@ import ( | |||||||
| 	"testing" | 	"testing" | ||||||
| 	"time" | 	"time" | ||||||
|  |  | ||||||
|  | 	metrics "github.com/armon/go-metrics" | ||||||
| 	log "github.com/hashicorp/go-hclog" | 	log "github.com/hashicorp/go-hclog" | ||||||
| 	uuid "github.com/hashicorp/go-uuid" | 	uuid "github.com/hashicorp/go-uuid" | ||||||
|  | 	"github.com/hashicorp/vault/helper/metricsutil" | ||||||
| 	"github.com/hashicorp/vault/helper/namespace" | 	"github.com/hashicorp/vault/helper/namespace" | ||||||
| 	"github.com/hashicorp/vault/sdk/framework" | 	"github.com/hashicorp/vault/sdk/framework" | ||||||
| 	"github.com/hashicorp/vault/sdk/helper/logging" | 	"github.com/hashicorp/vault/sdk/helper/logging" | ||||||
| @@ -38,6 +40,186 @@ func mockBackendExpiration(t testing.TB, backend physical.Backend) (*Core, *Expi | |||||||
| 	return c, c.expiration | 	return c, c.expiration | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestExpiration_Metrics(t *testing.T) { | ||||||
|  | 	var err error | ||||||
|  |  | ||||||
|  | 	testCore := TestCore(t) | ||||||
|  | 	testCore.baseLogger = logger | ||||||
|  | 	testCore.logger = logger.Named("core") | ||||||
|  | 	testCoreUnsealed(t, testCore) | ||||||
|  |  | ||||||
|  | 	exp := testCore.expiration | ||||||
|  |  | ||||||
|  | 	if err := exp.Restore(nil); err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Set up a count function to calculate number of leases | ||||||
|  | 	count := 0 | ||||||
|  | 	countFunc := func(leaseID string) { | ||||||
|  | 		count++ | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Scan the storage with the count func set | ||||||
|  | 	if err = logical.ScanView(namespace.RootContext(nil), exp.idView, countFunc); err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Check that there are no leases to begin with | ||||||
|  | 	if count != 0 { | ||||||
|  | 		t.Fatalf("bad: lease count; expected:0 actual:%d", count) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for i := 0; i < 50; i++ { | ||||||
|  | 		le := &leaseEntry{ | ||||||
|  | 			LeaseID:    "lease" + fmt.Sprintf("%d", i), | ||||||
|  | 			Path:       "foo/bar/" + fmt.Sprintf("%d", i), | ||||||
|  | 			namespace:  namespace.RootNamespace, | ||||||
|  | 			IssueTime:  time.Now(), | ||||||
|  | 			ExpireTime: time.Now().Add(time.Hour), | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		otherNS := &namespace.Namespace{ | ||||||
|  | 			ID:   "nsid", | ||||||
|  | 			Path: "foo/bar", | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		otherNSle := &leaseEntry{ | ||||||
|  | 			LeaseID:    "lease" + fmt.Sprintf("%d", i) + "/blah.nsid", | ||||||
|  | 			Path:       "foo/bar/" + fmt.Sprintf("%d", i) + "/blah.nsid", | ||||||
|  | 			namespace:  otherNS, | ||||||
|  | 			IssueTime:  time.Now(), | ||||||
|  | 			ExpireTime: time.Now().Add(time.Hour), | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		exp.pendingLock.Lock() | ||||||
|  | 		if err := exp.persistEntry(namespace.RootContext(nil), le); err != nil { | ||||||
|  | 			exp.pendingLock.Unlock() | ||||||
|  | 			t.Fatalf("error persisting entry: %v", err) | ||||||
|  | 		} | ||||||
|  | 		exp.updatePendingInternal(le) | ||||||
|  |  | ||||||
|  | 		if err := exp.persistEntry(namespace.RootContext(nil), otherNSle); err != nil { | ||||||
|  | 			exp.pendingLock.Unlock() | ||||||
|  | 			t.Fatalf("error persisting entry: %v", err) | ||||||
|  | 		} | ||||||
|  | 		exp.updatePendingInternal(otherNSle) | ||||||
|  | 		exp.pendingLock.Unlock() | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	for i := 50; i < 250; i++ { | ||||||
|  | 		le := &leaseEntry{ | ||||||
|  | 			LeaseID:    "lease" + fmt.Sprintf("%d", i+1), | ||||||
|  | 			Path:       "foo/bar/" + fmt.Sprintf("%d", i+1), | ||||||
|  | 			namespace:  namespace.RootNamespace, | ||||||
|  | 			IssueTime:  time.Now(), | ||||||
|  | 			ExpireTime: time.Now().Add(2 * time.Hour), | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		exp.pendingLock.Lock() | ||||||
|  | 		if err := exp.persistEntry(namespace.RootContext(nil), le); err != nil { | ||||||
|  | 			exp.pendingLock.Unlock() | ||||||
|  | 			t.Fatalf("error persisting entry: %v", err) | ||||||
|  | 		} | ||||||
|  | 		exp.updatePendingInternal(le) | ||||||
|  | 		exp.pendingLock.Unlock() | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	count = 0 | ||||||
|  | 	if err = logical.ScanView(context.Background(), exp.idView, countFunc); err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var conf metricsutil.TelemetryConstConfig = metricsutil.TelemetryConstConfig{ | ||||||
|  | 		LeaseMetricsEpsilon:         time.Hour, | ||||||
|  | 		NumLeaseMetricsTimeBuckets:  2, | ||||||
|  | 		LeaseMetricsNameSpaceLabels: true, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	flattenedResults, err := exp.leaseAggregationMetrics(context.Background(), conf) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	if flattenedResults == nil { | ||||||
|  | 		t.Fatal("lease aggregation returns nil metrics") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	labelOneHour := metrics.Label{"expiring", time.Now().Add(time.Hour).Round(time.Hour).String()} | ||||||
|  | 	labelTwoHours := metrics.Label{"expiring", time.Now().Add(2 * time.Hour).Round(time.Hour).String()} | ||||||
|  | 	nsLabel := metrics.Label{"namespace", "root"} | ||||||
|  | 	nsLabelNonRoot := metrics.Label{"namespace", "nsid"} | ||||||
|  |  | ||||||
|  | 	foundLabelOne := false | ||||||
|  | 	foundLabelTwo := false | ||||||
|  | 	foundLabelThree := false | ||||||
|  |  | ||||||
|  | 	for _, labelVal := range flattenedResults { | ||||||
|  | 		retNsLabel := labelVal.Labels[1] | ||||||
|  | 		retTimeLabel := labelVal.Labels[0] | ||||||
|  | 		if nsLabel == retNsLabel { | ||||||
|  | 			if labelVal.Value == 50 { | ||||||
|  | 				if retTimeLabel == labelOneHour { | ||||||
|  | 					foundLabelOne = true | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			if labelVal.Value == 200 { | ||||||
|  | 				if retTimeLabel == labelTwoHours { | ||||||
|  | 					foundLabelTwo = true | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} else if retNsLabel == nsLabelNonRoot { | ||||||
|  | 			if labelVal.Value == 50 { | ||||||
|  | 				if retTimeLabel == labelOneHour { | ||||||
|  | 					foundLabelThree = true | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if !foundLabelOne || !foundLabelTwo || !foundLabelThree { | ||||||
|  | 		t.Errorf("One of the labels is missing") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// test the same leases while ignoring namespaces so the 2 different namespaces get aggregated | ||||||
|  | 	conf = metricsutil.TelemetryConstConfig{ | ||||||
|  | 		LeaseMetricsEpsilon:         time.Hour, | ||||||
|  | 		NumLeaseMetricsTimeBuckets:  2, | ||||||
|  | 		LeaseMetricsNameSpaceLabels: false, | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	flattenedResults, err = exp.leaseAggregationMetrics(context.Background(), conf) | ||||||
|  | 	if err != nil { | ||||||
|  | 		t.Fatal(err) | ||||||
|  | 	} | ||||||
|  | 	if flattenedResults == nil { | ||||||
|  | 		t.Fatal("lease aggregation returns nil metrics") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	foundLabelOne = false | ||||||
|  | 	foundLabelTwo = false | ||||||
|  |  | ||||||
|  | 	for _, labelVal := range flattenedResults { | ||||||
|  | 		if len(labelVal.Labels) != 1 { | ||||||
|  | 			t.Errorf("Namespace label is returned when explicitly not requested.") | ||||||
|  | 		} | ||||||
|  | 		retTimeLabel := labelVal.Labels[0] | ||||||
|  | 		if labelVal.Value == 100 { | ||||||
|  | 			if retTimeLabel == labelOneHour { | ||||||
|  | 				foundLabelOne = true | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if labelVal.Value == 200 { | ||||||
|  | 			if retTimeLabel == labelTwoHours { | ||||||
|  | 				foundLabelTwo = true | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	if !foundLabelOne || !foundLabelTwo { | ||||||
|  | 		t.Errorf("One of the labels is missing") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
|  |  | ||||||
| func TestExpiration_Tidy(t *testing.T) { | func TestExpiration_Tidy(t *testing.T) { | ||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										110
									
								
								vendor/github.com/hashicorp/vault/api/client.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										110
									
								
								vendor/github.com/hashicorp/vault/api/client.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -475,6 +475,9 @@ func (c *Client) SetAddress(addr string) error { | |||||||
| 		return errwrap.Wrapf("failed to set address: {{err}}", err) | 		return errwrap.Wrapf("failed to set address: {{err}}", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	c.config.modifyLock.Lock() | ||||||
|  | 	c.config.Address = addr | ||||||
|  | 	c.config.modifyLock.Unlock() | ||||||
| 	c.addr = parsedAddr | 	c.addr = parsedAddr | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
| @@ -492,57 +495,111 @@ func (c *Client) Address() string { | |||||||
| // rateLimit and burst are specified according to https://godoc.org/golang.org/x/time/rate#NewLimiter | // rateLimit and burst are specified according to https://godoc.org/golang.org/x/time/rate#NewLimiter | ||||||
| func (c *Client) SetLimiter(rateLimit float64, burst int) { | func (c *Client) SetLimiter(rateLimit float64, burst int) { | ||||||
| 	c.modifyLock.RLock() | 	c.modifyLock.RLock() | ||||||
|  | 	defer c.modifyLock.RUnlock() | ||||||
| 	c.config.modifyLock.Lock() | 	c.config.modifyLock.Lock() | ||||||
| 	defer c.config.modifyLock.Unlock() | 	defer c.config.modifyLock.Unlock() | ||||||
| 	c.modifyLock.RUnlock() |  | ||||||
|  |  | ||||||
| 	c.config.Limiter = rate.NewLimiter(rate.Limit(rateLimit), burst) | 	c.config.Limiter = rate.NewLimiter(rate.Limit(rateLimit), burst) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (c *Client) Limiter() *rate.Limiter { | ||||||
|  | 	c.modifyLock.RLock() | ||||||
|  | 	defer c.modifyLock.RUnlock() | ||||||
|  | 	c.config.modifyLock.RLock() | ||||||
|  | 	defer c.config.modifyLock.RUnlock() | ||||||
|  |  | ||||||
|  | 	return c.config.Limiter | ||||||
|  | } | ||||||
|  |  | ||||||
| // SetMaxRetries sets the number of retries that will be used in the case of certain errors | // SetMaxRetries sets the number of retries that will be used in the case of certain errors | ||||||
| func (c *Client) SetMaxRetries(retries int) { | func (c *Client) SetMaxRetries(retries int) { | ||||||
| 	c.modifyLock.RLock() | 	c.modifyLock.RLock() | ||||||
|  | 	defer c.modifyLock.RUnlock() | ||||||
| 	c.config.modifyLock.Lock() | 	c.config.modifyLock.Lock() | ||||||
| 	defer c.config.modifyLock.Unlock() | 	defer c.config.modifyLock.Unlock() | ||||||
| 	c.modifyLock.RUnlock() |  | ||||||
|  |  | ||||||
| 	c.config.MaxRetries = retries | 	c.config.MaxRetries = retries | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (c *Client) MaxRetries() int { | ||||||
|  | 	c.modifyLock.RLock() | ||||||
|  | 	defer c.modifyLock.RUnlock() | ||||||
|  | 	c.config.modifyLock.RLock() | ||||||
|  | 	defer c.config.modifyLock.RUnlock() | ||||||
|  |  | ||||||
|  | 	return c.config.MaxRetries | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *Client) SetSRVLookup(srv bool) { | ||||||
|  | 	c.modifyLock.RLock() | ||||||
|  | 	defer c.modifyLock.RUnlock() | ||||||
|  | 	c.config.modifyLock.Lock() | ||||||
|  | 	defer c.config.modifyLock.Unlock() | ||||||
|  |  | ||||||
|  | 	c.config.SRVLookup = srv | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *Client) SRVLookup() bool { | ||||||
|  | 	c.modifyLock.RLock() | ||||||
|  | 	defer c.modifyLock.RUnlock() | ||||||
|  | 	c.config.modifyLock.RLock() | ||||||
|  | 	defer c.config.modifyLock.RUnlock() | ||||||
|  |  | ||||||
|  | 	return c.config.SRVLookup | ||||||
|  | } | ||||||
|  |  | ||||||
| // SetCheckRetry sets the CheckRetry function to be used for future requests. | // SetCheckRetry sets the CheckRetry function to be used for future requests. | ||||||
| func (c *Client) SetCheckRetry(checkRetry retryablehttp.CheckRetry) { | func (c *Client) SetCheckRetry(checkRetry retryablehttp.CheckRetry) { | ||||||
| 	c.modifyLock.RLock() | 	c.modifyLock.RLock() | ||||||
|  | 	defer c.modifyLock.RUnlock() | ||||||
| 	c.config.modifyLock.Lock() | 	c.config.modifyLock.Lock() | ||||||
| 	defer c.config.modifyLock.Unlock() | 	defer c.config.modifyLock.Unlock() | ||||||
| 	c.modifyLock.RUnlock() |  | ||||||
|  |  | ||||||
| 	c.config.CheckRetry = checkRetry | 	c.config.CheckRetry = checkRetry | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (c *Client) CheckRetry() retryablehttp.CheckRetry { | ||||||
|  | 	c.modifyLock.RLock() | ||||||
|  | 	defer c.modifyLock.RUnlock() | ||||||
|  | 	c.config.modifyLock.RLock() | ||||||
|  | 	defer c.config.modifyLock.RUnlock() | ||||||
|  |  | ||||||
|  | 	return c.config.CheckRetry | ||||||
|  | } | ||||||
|  |  | ||||||
| // SetClientTimeout sets the client request timeout | // SetClientTimeout sets the client request timeout | ||||||
| func (c *Client) SetClientTimeout(timeout time.Duration) { | func (c *Client) SetClientTimeout(timeout time.Duration) { | ||||||
| 	c.modifyLock.RLock() | 	c.modifyLock.RLock() | ||||||
|  | 	defer c.modifyLock.RUnlock() | ||||||
| 	c.config.modifyLock.Lock() | 	c.config.modifyLock.Lock() | ||||||
| 	defer c.config.modifyLock.Unlock() | 	defer c.config.modifyLock.Unlock() | ||||||
| 	c.modifyLock.RUnlock() |  | ||||||
|  |  | ||||||
| 	c.config.Timeout = timeout | 	c.config.Timeout = timeout | ||||||
| } | } | ||||||
|  |  | ||||||
| func (c *Client) OutputCurlString() bool { | func (c *Client) ClientTimeout() time.Duration { | ||||||
| 	c.modifyLock.RLock() | 	c.modifyLock.RLock() | ||||||
|  | 	defer c.modifyLock.RUnlock() | ||||||
|  | 	c.config.modifyLock.RLock() | ||||||
|  | 	defer c.config.modifyLock.RUnlock() | ||||||
|  |  | ||||||
|  | 	return c.config.Timeout | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (c *Client) OutputCurlString() bool { | ||||||
|  | 	c.modifyLock.RLock() | ||||||
|  | 	defer c.modifyLock.RUnlock() | ||||||
| 	c.config.modifyLock.RLock() | 	c.config.modifyLock.RLock() | ||||||
| 	defer c.config.modifyLock.RUnlock() | 	defer c.config.modifyLock.RUnlock() | ||||||
| 	c.modifyLock.RUnlock() |  | ||||||
|  |  | ||||||
| 	return c.config.OutputCurlString | 	return c.config.OutputCurlString | ||||||
| } | } | ||||||
|  |  | ||||||
| func (c *Client) SetOutputCurlString(curl bool) { | func (c *Client) SetOutputCurlString(curl bool) { | ||||||
| 	c.modifyLock.RLock() | 	c.modifyLock.RLock() | ||||||
|  | 	defer c.modifyLock.RUnlock() | ||||||
| 	c.config.modifyLock.Lock() | 	c.config.modifyLock.Lock() | ||||||
| 	defer c.config.modifyLock.Unlock() | 	defer c.config.modifyLock.Unlock() | ||||||
| 	c.modifyLock.RUnlock() |  | ||||||
|  |  | ||||||
| 	c.config.OutputCurlString = curl | 	c.config.OutputCurlString = curl | ||||||
| } | } | ||||||
| @@ -552,7 +609,6 @@ func (c *Client) SetOutputCurlString(curl bool) { | |||||||
| func (c *Client) CurrentWrappingLookupFunc() WrappingLookupFunc { | func (c *Client) CurrentWrappingLookupFunc() WrappingLookupFunc { | ||||||
| 	c.modifyLock.RLock() | 	c.modifyLock.RLock() | ||||||
| 	defer c.modifyLock.RUnlock() | 	defer c.modifyLock.RUnlock() | ||||||
|  |  | ||||||
| 	return c.wrappingLookupFunc | 	return c.wrappingLookupFunc | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -561,7 +617,6 @@ func (c *Client) CurrentWrappingLookupFunc() WrappingLookupFunc { | |||||||
| func (c *Client) SetWrappingLookupFunc(lookupFunc WrappingLookupFunc) { | func (c *Client) SetWrappingLookupFunc(lookupFunc WrappingLookupFunc) { | ||||||
| 	c.modifyLock.Lock() | 	c.modifyLock.Lock() | ||||||
| 	defer c.modifyLock.Unlock() | 	defer c.modifyLock.Unlock() | ||||||
|  |  | ||||||
| 	c.wrappingLookupFunc = lookupFunc | 	c.wrappingLookupFunc = lookupFunc | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -570,7 +625,6 @@ func (c *Client) SetWrappingLookupFunc(lookupFunc WrappingLookupFunc) { | |||||||
| func (c *Client) SetMFACreds(creds []string) { | func (c *Client) SetMFACreds(creds []string) { | ||||||
| 	c.modifyLock.Lock() | 	c.modifyLock.Lock() | ||||||
| 	defer c.modifyLock.Unlock() | 	defer c.modifyLock.Unlock() | ||||||
|  |  | ||||||
| 	c.mfaCreds = creds | 	c.mfaCreds = creds | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -595,7 +649,6 @@ func (c *Client) setNamespace(namespace string) { | |||||||
| func (c *Client) Token() string { | func (c *Client) Token() string { | ||||||
| 	c.modifyLock.RLock() | 	c.modifyLock.RLock() | ||||||
| 	defer c.modifyLock.RUnlock() | 	defer c.modifyLock.RUnlock() | ||||||
|  |  | ||||||
| 	return c.token | 	return c.token | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -604,7 +657,6 @@ func (c *Client) Token() string { | |||||||
| func (c *Client) SetToken(v string) { | func (c *Client) SetToken(v string) { | ||||||
| 	c.modifyLock.Lock() | 	c.modifyLock.Lock() | ||||||
| 	defer c.modifyLock.Unlock() | 	defer c.modifyLock.Unlock() | ||||||
|  |  | ||||||
| 	c.token = v | 	c.token = v | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -612,7 +664,6 @@ func (c *Client) SetToken(v string) { | |||||||
| func (c *Client) ClearToken() { | func (c *Client) ClearToken() { | ||||||
| 	c.modifyLock.Lock() | 	c.modifyLock.Lock() | ||||||
| 	defer c.modifyLock.Unlock() | 	defer c.modifyLock.Unlock() | ||||||
|  |  | ||||||
| 	c.token = "" | 	c.token = "" | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -655,9 +706,9 @@ func (c *Client) SetHeaders(headers http.Header) { | |||||||
| // SetBackoff sets the backoff function to be used for future requests. | // SetBackoff sets the backoff function to be used for future requests. | ||||||
| func (c *Client) SetBackoff(backoff retryablehttp.Backoff) { | func (c *Client) SetBackoff(backoff retryablehttp.Backoff) { | ||||||
| 	c.modifyLock.RLock() | 	c.modifyLock.RLock() | ||||||
|  | 	defer c.modifyLock.RUnlock() | ||||||
| 	c.config.modifyLock.Lock() | 	c.config.modifyLock.Lock() | ||||||
| 	defer c.config.modifyLock.Unlock() | 	defer c.config.modifyLock.Unlock() | ||||||
| 	c.modifyLock.RUnlock() |  | ||||||
|  |  | ||||||
| 	c.config.Backoff = backoff | 	c.config.Backoff = backoff | ||||||
| } | } | ||||||
| @@ -672,22 +723,30 @@ func (c *Client) SetBackoff(backoff retryablehttp.Backoff) { | |||||||
| // behavior, must currently then be set as desired on the new client. | // behavior, must currently then be set as desired on the new client. | ||||||
| func (c *Client) Clone() (*Client, error) { | func (c *Client) Clone() (*Client, error) { | ||||||
| 	c.modifyLock.RLock() | 	c.modifyLock.RLock() | ||||||
| 	c.config.modifyLock.RLock() | 	defer c.modifyLock.RUnlock() | ||||||
|  |  | ||||||
| 	config := c.config | 	config := c.config | ||||||
| 	c.modifyLock.RUnlock() | 	config.modifyLock.RLock() | ||||||
|  | 	defer config.modifyLock.RUnlock() | ||||||
|  |  | ||||||
| 	newConfig := &Config{ | 	newConfig := &Config{ | ||||||
| 		Address:    config.Address, | 		Address:          config.Address, | ||||||
| 		HttpClient: config.HttpClient, | 		HttpClient:       config.HttpClient, | ||||||
| 		MaxRetries: config.MaxRetries, | 		MaxRetries:       config.MaxRetries, | ||||||
| 		Timeout:    config.Timeout, | 		Timeout:          config.Timeout, | ||||||
| 		Backoff:    config.Backoff, | 		Backoff:          config.Backoff, | ||||||
| 		CheckRetry: config.CheckRetry, | 		CheckRetry:       config.CheckRetry, | ||||||
| 		Limiter:    config.Limiter, | 		Limiter:          config.Limiter, | ||||||
|  | 		OutputCurlString: config.OutputCurlString, | ||||||
|  | 		AgentAddress:     config.AgentAddress, | ||||||
|  | 		SRVLookup:        config.SRVLookup, | ||||||
|  | 	} | ||||||
|  | 	client, err := NewClient(newConfig) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	config.modifyLock.RUnlock() |  | ||||||
|  |  | ||||||
| 	return NewClient(newConfig) | 	return client, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| // SetPolicyOverride sets whether requests should be sent with the policy | // SetPolicyOverride sets whether requests should be sent with the policy | ||||||
| @@ -696,7 +755,6 @@ func (c *Client) Clone() (*Client, error) { | |||||||
| func (c *Client) SetPolicyOverride(override bool) { | func (c *Client) SetPolicyOverride(override bool) { | ||||||
| 	c.modifyLock.Lock() | 	c.modifyLock.Lock() | ||||||
| 	defer c.modifyLock.Unlock() | 	defer c.modifyLock.Unlock() | ||||||
|  |  | ||||||
| 	c.policyOverride = override | 	c.policyOverride = override | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Hridoy Roy
					Hridoy Roy