Skip to content

Commit

Permalink
Merge pull request #37 from damsallem/main
Browse files Browse the repository at this point in the history
New way to resolve namespaces from MetaData
  • Loading branch information
damsallem committed Feb 16, 2024
2 parents a07b7d0 + b40027d commit a030629
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 12 deletions.
4 changes: 4 additions & 0 deletions configs/aerospike_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ client_config:
### Probe discovery configuration ###
# The key to discover Aerospike's namespaces through service discovery
# Set it to "" to instead discover namespaces automatically via the info command
# DEPRECATED since 02/19/2024
namespace_meta_key: "aerospike-namespaces"
# The key prefix to discover Aerospike's namespaces through service discovery
# old "namespace_meta_key" has been DEPRECATED because of 512 bytes limitation of the value in consul.
namespace_meta_key_prefix: "aerospike-monitoring-"
### Probe configuration ###
monitoring_set: monitoring
latency_key_prefix: monitoring_latency_
Expand Down
2 changes: 2 additions & 0 deletions pkg/aerospike/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ type AerospikeEndpointConfig struct {
TLSHostnameMetaKey string `yaml:"tls_hostname_meta_key,omitempty"`
// Probe configuration
NamespaceMetaKey string `yaml:"namespace_meta_key,omitempty"`
NamespaceMetaKeyPrefix string `yaml:"namespace_meta_key_prefix,omitempty"`
MonitoringSet string `yaml:"monitoring_set,omitempty"`
LatencyKeyPrefix string `yaml:"latency_key_prefix,omitempty"`
DurabilityKeyPrefix string `yaml:"durability_key_prefix,omitempty"`
Expand All @@ -63,6 +64,7 @@ var (
TLSTag: "tls",
TLSHostnameMetaKey: "tls-hostname",
NamespaceMetaKey: "",
NamespaceMetaKeyPrefix: "",
MonitoringSet: "monitoring",
LatencyKeyPrefix: "monitoring_latency_",
DurabilityKeyPrefix: "monitoring_durability_",
Expand Down
45 changes: 38 additions & 7 deletions pkg/aerospike/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package aerospike
import (
"fmt"
"os"
"strconv"
"strings"

as "github.com/aerospike/aerospike-client-go/v5"
Expand Down Expand Up @@ -47,7 +48,7 @@ func (conf *AerospikeProbeConfig) generateNamespacedEndpointsFromEntry(logger lo
clusterName = entry.Address
}

namespaces := conf.getNamespacesFromEntry(entry)
namespaces := conf.getNamespacesFromEntry(logger, entry)

var endpoints []*AerospikeEndpoint
for namespace := range namespaces {
Expand Down Expand Up @@ -75,15 +76,45 @@ func (conf *AerospikeProbeConfig) generateNamespacedEndpointsFromEntry(logger lo
return endpoints, nil
}

func (conf AerospikeProbeConfig) getNamespacesFromEntry(entry discovery.ServiceEntry) map[string]struct{} {
func (conf AerospikeProbeConfig) getNamespacesFromEntry(logger log.Logger, entry discovery.ServiceEntry) map[string]struct{} {
namespaces := make(map[string]struct{})
nsString, ok := entry.Meta[conf.AerospikeEndpointConfig.NamespaceMetaKey]
if ok {
nsFromDiscovery := strings.Split(nsString, ";")
for _, ns := range nsFromDiscovery {
namespaces[ns] = struct{}{}
fallback := false

// Correct way to get namespaces.
for metaKey, metaValue := range entry.Meta {
if !strings.HasPrefix(metaKey, conf.AerospikeEndpointConfig.NamespaceMetaKeyPrefix) {
continue
}
ready, err := strconv.ParseBool(metaValue)
// if the value of the NamespaceMetaKeyPrefix MetaData is not a boolean then fallback to the old method
if err != nil {
level.Error(logger).Log("msg", fmt.Sprintf("Fail to parse boolean value from MetaData %s. Fallbacking to deprecated method.", metaKey), "err", err)
fallback = true
break
}
// if ready is at false, then iterate to the next MetaData and try to resolve other namespaces
if !ready {
continue
}
ns := strings.Split(metaKey, "-")[2] // MetaKey is like : "aerospike-monitoring-closeststore"
namespaces[ns] = struct{}{}
}

// DEPRECATED way to get namespaces in case of fallback required or empty namespaces with the new method
if fallback || len(namespaces) == 0 {
nsString, ok := entry.Meta[conf.AerospikeEndpointConfig.NamespaceMetaKey]
if ok {
// Clear namespaces for any previously found entry from the old method
for k := range namespaces {
delete(namespaces, k)
}
nsFromDiscovery := strings.Split(nsString, ";")
for _, ns := range nsFromDiscovery {
namespaces[ns] = struct{}{}
}
}
}

return namespaces
}

Expand Down
110 changes: 110 additions & 0 deletions pkg/aerospike/discovery_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package aerospike

import (
"errors"
"reflect"
"testing"
"time"

"github.com/criteo/blackbox-prober/pkg/discovery"
"github.com/criteo/blackbox-prober/pkg/topology"
"github.com/go-kit/log"
)

type testEndpoint struct {
topology.DummyEndpoint
deadline time.Time
CheckCallCount int
RefreshCallCount int
}

func (te *testEndpoint) Refresh() error {
te.RefreshCallCount += 1
if te.RefreshCallCount%2 == 0 {
return errors.New("fake err")
}
return nil
}

func TestGetNamespacesFromEntry(t *testing.T) {
entry_newValid := discovery.ServiceEntry{
Meta: map[string]string{
"aerospike-monitoring-test1": "true",
"aerospike-monitoring-test2": "true",
"aerospike-monitoring-test3": "false",
},
}
expected_newValid := map[string]struct{}{
"test1": struct{}{},
"test2": struct{}{},
}

entry_oldValid := discovery.ServiceEntry{
Meta: map[string]string{
"aerospike-namespaces": "test1;test2;test3",
},
}
expected_oldValid := map[string]struct{}{
"test1": struct{}{},
"test2": struct{}{},
"test3": struct{}{},
}

entry_noFallback := discovery.ServiceEntry{
Meta: map[string]string{
"aerospike-namespaces": "test3",
"aerospike-monitoring-test1": "true",
"aerospike-monitoring-test2": "false",
"aerospike-monitoring-test3": "true",
},
}
expected_noFallback := map[string]struct{}{
"test1": struct{}{},
"test3": struct{}{},
}

entry_fallback := discovery.ServiceEntry{
Meta: map[string]string{
"aerospike-namespaces": "test3",
"aerospike-monitoring-test1": "true",
"aerospike-monitoring-test2": "foo",
"aerospike-monitoring-test3": "false",
},
}
expected_fallback := map[string]struct{}{
"test3": struct{}{},
}

entry_empty := discovery.ServiceEntry{
Meta: map[string]string{},
}
expected_empty := map[string]struct{}{}

// Minimum config for getNamespacesFromEntry tests
config := AerospikeProbeConfig{}
config.AerospikeEndpointConfig = AerospikeEndpointConfig{
NamespaceMetaKey: "aerospike-namespaces",
NamespaceMetaKeyPrefix: "aerospike-monitoring-",
}

namespaces := config.getNamespacesFromEntry(log.NewNopLogger(), entry_newValid)
if !reflect.DeepEqual(namespaces, expected_newValid) {
t.Errorf("getNamespacesFromEntry didn't return expected value for entry 'entry_newValid'.")
}
namespaces = config.getNamespacesFromEntry(log.NewNopLogger(), entry_oldValid)
if !reflect.DeepEqual(namespaces, expected_oldValid) {
t.Errorf("getNamespacesFromEntry didn't return expected value for entry 'entry_oldValid'.")
}
namespaces = config.getNamespacesFromEntry(log.NewNopLogger(), entry_noFallback)
if !reflect.DeepEqual(namespaces, expected_noFallback) {
t.Errorf("getNamespacesFromEntry didn't return expected value for entry 'entry_noFallback'.")
}
namespaces = config.getNamespacesFromEntry(log.NewNopLogger(), entry_fallback)
if !reflect.DeepEqual(namespaces, expected_fallback) {
t.Errorf("getNamespacesFromEntry didn't return expected value for entry 'entry_fallback'.")
}
namespaces = config.getNamespacesFromEntry(log.NewNopLogger(), entry_empty)
if !reflect.DeepEqual(namespaces, expected_empty) {
t.Errorf("getNamespacesFromEntry didn't return expected value for entry 'entry_empty'.")
}
}
20 changes: 15 additions & 5 deletions probes/aerospike/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,28 @@

## Namespace discovery

The probe is not discovering namespaces automatically. The `namespace_meta_key`
The probe is not discovering namespaces automatically. The `namespace_meta_key_prefix`
needs to be defined on the cluster's consul services for the probe to discover them
The probe will not do any checking without at least one namespace specified.

Example:
`namespace_meta_key` per default is set to `aerospike-namespaces`. The value
is a set of namespace name separated by a semicolon `;`.
`namespace_meta_key_prefix` per default is set to `aerospike-monitoring-`.

Example: advertising "foo" and "bar" namespace
For advertising "foo" and "bar" namespace

`aerospike-namespaces: "foo;bar"`
`aerospike-monitoring-foo: true`
`aerospike-monitoring-bar: true`

If any of these MetaData entries are not present of does not define a bool value
then it will fallback to the old method of namespace discovery:
`namespace_meta_key` which contains namespaces separated by `;`

Example:
`namespace_meta_key` per default is set to `aerospike-namespaces`.

For advertising "foo" and "bar" namespace

`aerospike-namespaces: foo;bar`

## Latency checks executed at cluster level

Expand Down

0 comments on commit a030629

Please sign in to comment.