Skip to content

Commit dd47e36

Browse files
committed
Handle meta-data commands that return multiple values.
1 parent 69d841f commit dd47e36

File tree

6 files changed

+53
-4
lines changed

6 files changed

+53
-4
lines changed

cmd/chirpstack-gateway-bridge/cmd/configfile.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,15 @@ marshaler="{{ .Integration.Marshaler }}"
418418
# Max. execution duration.
419419
max_execution_duration="{{ .MetaData.Dynamic.MaxExecutionDuration }}"
420420
421+
# Split delimiter.
422+
#
423+
# When the output of a command returns multiple lines, ChirpStack Gateway Bridge
424+
# assumes multiple values are returned. In this case it will split by the given delimiter
425+
# to obtain the key / value of each row. The key will be prefixed with the name of the
426+
# configured command.
427+
split_delimiter="{{ .MetaData.Dynamic.SplitDelimiter }}"
428+
429+
421430
# Commands to execute.
422431
#
423432
# The value of the stdout will be used as the key value (string).

cmd/chirpstack-gateway-bridge/cmd/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ func init() {
6767

6868
viper.SetDefault("integration.mqtt.auth.azure_iot_hub.sas_token_expiration", 24*time.Hour)
6969

70+
viper.SetDefault("meta_data.dynamic.split_delimiter", "=")
7071
viper.SetDefault("meta_data.dynamic.execution_interval", time.Minute)
7172
viper.SetDefault("meta_data.dynamic.max_execution_duration", time.Second)
7273

docs/content/install/config.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,15 @@ marshaler="protobuf"
446446
# Max. execution duration.
447447
max_execution_duration="1s"
448448

449+
# Split delimiter.
450+
#
451+
# When the output of a command returns multiple lines, ChirpStack Gateway Bridge
452+
# assumes multiple values are returned. In this case it will split by the given delimiter
453+
# to obtain the key / value of each row. The key will be prefixed with the name of the
454+
# configured command.
455+
split_delimiter="="
456+
457+
449458
# Commands to execute.
450459
#
451460
# The value of the stdout will be used as the key value (string).

internal/config/config.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,14 @@ type Config struct {
110110
EndpointEnabled bool `mapstructure:"endpoint_enabled"`
111111
Bind string `mapstructure:"bind"`
112112
} `mapstructure:"prometheus"`
113-
} `mapstructure:"metrics"`
113+
} `mapstructure:"metrics"`
114114

115115
MetaData struct {
116116
Static map[string]string `mapstructure:"static"`
117117
Dynamic struct {
118118
ExecutionInterval time.Duration `mapstructure:"execution_interval"`
119119
MaxExecutionDuration time.Duration `mapstructure:"max_execution_duration"`
120+
SplitDelimiter string `mapstructure:"split_delimiter"`
120121
Commands map[string]string `mapstructure:"commands"`
121122
} `mapstructure:"dynamic"`
122123
} `mapstructure:"meta_data"`

internal/metadata/metadata.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ var (
2222
cmnds map[string]string
2323
cached map[string]string
2424

25-
interval time.Duration
26-
maxExecution time.Duration
25+
interval time.Duration
26+
maxExecution time.Duration
27+
splitDelimiter string
2728
)
2829

2930
// Setup configures the metadata package.
@@ -36,6 +37,7 @@ func Setup(conf config.Config) error {
3637

3738
interval = conf.MetaData.Dynamic.ExecutionInterval
3839
maxExecution = conf.MetaData.Dynamic.MaxExecutionDuration
40+
splitDelimiter = conf.MetaData.Dynamic.SplitDelimiter
3941

4042
go func() {
4143
for {
@@ -71,7 +73,23 @@ func runCommands() {
7173
continue
7274
}
7375

74-
newKV[k] = out
76+
if strings.Contains(out, "\n") {
77+
rows := strings.Split(out, "\n")
78+
for _, row := range rows {
79+
kv := strings.Split(row, splitDelimiter)
80+
if len(kv) != 2 {
81+
log.WithFields(log.Fields{
82+
"row": row,
83+
"split_delimiter": splitDelimiter,
84+
}).Warning("metadata: can not split output in key / value")
85+
} else {
86+
newKV[k+"_"+kv[0]] = kv[1]
87+
}
88+
}
89+
90+
} else {
91+
newKV[k] = out
92+
}
7593
}
7694

7795
mux.Lock()

internal/metadata/metadata_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,20 @@ func TestMetaData(t *testing.T) {
116116
"bar": "test2",
117117
},
118118
},
119+
{
120+
Name: "command returns multiple rows",
121+
Commands: map[string]string{
122+
"bar": `echo -e "foo=bar\nalice=bob"`,
123+
},
124+
Expected: map[string]string{
125+
"bar_foo": "bar",
126+
"bar_alice": "bob",
127+
},
128+
},
119129
}
120130

121131
maxExecution = time.Second
132+
splitDelimiter = "="
122133

123134
for _, tst := range tests {
124135
t.Run(tst.Name, func(t *testing.T) {

0 commit comments

Comments
 (0)