Skip to content

Commit

Permalink
Feature/issue 183 (#190)
Browse files Browse the repository at this point in the history
  • Loading branch information
ian-bartholomew authored Jan 7, 2023
1 parent c30e2ed commit b887e52
Show file tree
Hide file tree
Showing 11 changed files with 313 additions and 97 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/bats.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Disabling this for now, since its not working quite right on GitHub, and
# its not full needed now
#
# name: BATS tests
# on:
# pull_request:
# jobs:
# batsTests:
# name: Test Binary
# strategy:
# matrix:
# os: [ubuntu-latest, windows-latest, macos-12]
# runs-on: ubuntu-latest
# steps:
# - uses: actions/checkout@v3
# - uses: actions/setup-go@v3
# with:
# go-version: 1.17
# - uses: actions/setup-node@v3
# with:
# node-version: "18"
# - name: Install bats
# run: make install/bats
# - name: Install bats dependencies
# run: make install/bats/dependencies
# - name: Run tests
# run: make run/bats/tests
12 changes: 12 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ install: run/tests build
install/checks/spell-and-markdown:
yarn

.PHONY: install/bats
install/bats:
@yarn global add bats

.PHONY: install/bats/dependencies
install/bats/dependencies:
@./test/cli/install-deps.sh

.PHONY: run/checks/spell-and-markdown
run/checks/spell-and-markdown:
yarn check-trailing-whitespaces
Expand All @@ -40,3 +48,7 @@ run/checks/golangci-lint:
.PHONY: run/tests
run/tests:
go test -race -cover ./...

.PHONY: run/bats/tests
run/bats/tests:
find test/cli -type f -name "*.bats" ! -path "test/cli/test_helper/*" | xargs bats
4 changes: 3 additions & 1 deletion cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,16 @@
"Rollup",
"rval",
"server",
"sloctl",
"slos",
"stretchr",
"structs",
"tada",
"TSDB",
"unflatten",
"unflattens",
"unmarshals"
"unmarshals",
"usix"
],
"enabledLanguageIds": [
"asciidoc",
Expand Down
101 changes: 61 additions & 40 deletions internal/pkg/convert/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ func getN9CountMetrics(r v1.RatioMetric) (nobl9v1alpha.CountMetricsSpec, error)

// Disabling the lint for this since theres not a really good way of doing this without a big switch statement.
//
//nolint:cyclop,gocyclo
//nolint:cyclop
func getN9MetricSource(m v1.MetricSource) (nobl9v1alpha.MetricSpec, error) {
// Nobl9 supported metric sources.
supportedMetricSources := map[string]string{
Expand Down Expand Up @@ -537,48 +537,14 @@ func getN9MetricSource(m v1.MetricSource) (nobl9v1alpha.MetricSpec, error) {
namespace := m.MetricSourceSpec["namespace"]
metricName := m.MetricSourceSpec["metricName"]
region := m.MetricSourceSpec["region"]
stat := m.MetricSourceSpec["stat"]
dimensions := m.MetricSourceSpec["dimensions"]
sql := m.MetricSourceSpec["sql"]
json := m.MetricSourceSpec["json"]

// split the incoming dimensions string into a CloudWatchMetricDimension
var dims []nobl9v1alpha.CloudWatchMetricDimension
for _, sequence := range strings.Split(dimensions, ";") {
// for the cloudwatch dimensions, we expect them in a single set of kv pairs, with name and value as the two keys
// example: 'name:foo,value:"foo";name:bar,value:"bar"'
cwDim := nobl9v1alpha.CloudWatchMetricDimension{}
for _, dimMap := range strings.Split(sequence, ",") {
kv := strings.Split(dimMap, ":")
if len(kv) != 2 {
return nobl9v1alpha.MetricSpec{}, fmt.Errorf("invalid dimension: %s", dimMap)
}

key := strings.TrimSpace(kv[0])
val := strings.TrimSpace(kv[1])

if strings.ToLower(key) == "name" {
cwDim.Name = &val
}

if strings.ToLower(key) == "value" {
cwDim.Value = &val
}
}
dims = append(dims, cwDim)
}
cwm := getN9CloudWatchQuery(m.MetricSourceSpec)
cwm.Namespace = &namespace
cwm.MetricName = &metricName
cwm.Region = &region

// convert dimensions (which is a string) to []nobl9v1alpha.CloudWatchMetricDimension
ms = nobl9v1alpha.MetricSpec{
CloudWatch: &nobl9v1alpha.CloudWatchMetric{
Namespace: &namespace,
MetricName: &metricName,
Dimensions: dims,
Region: &region,
Stat: &stat,
SQL: &sql,
JSON: &json,
},
CloudWatch: &cwm,
}
case supportedMetricSources["Redshift"]:
query := m.MetricSourceSpec["query"]
Expand Down Expand Up @@ -720,6 +686,61 @@ func getN9MetricSource(m v1.MetricSource) (nobl9v1alpha.MetricSpec, error) {
return ms, nil
}

func getN9CloudWatchQuery(m map[string]string) nobl9v1alpha.CloudWatchMetric {
switch {
case m["sql"] != "":
val := m["sql"]
return nobl9v1alpha.CloudWatchMetric{
SQL: &val,
}
case m["json"] != "":
val := m["json"]
return nobl9v1alpha.CloudWatchMetric{
JSON: &val,
}
case m["dimensions"] != "":
val, _ := getN9CloudWatchDims(m["dimensions"])
stat := m["stat"]
return nobl9v1alpha.CloudWatchMetric{
Stat: &stat,
Dimensions: val,
}
}

return nobl9v1alpha.CloudWatchMetric{}
}

func getN9CloudWatchDims(dimensions string) ([]nobl9v1alpha.CloudWatchMetricDimension, error) {
// split the incoming dimensions string into a CloudWatchMetricDimension
dimsPieces := strings.Split(dimensions, ";")
dims := make([]nobl9v1alpha.CloudWatchMetricDimension, 0, len(dimsPieces))
for _, sequence := range dimsPieces {
// for the cloudwatch dimensions, we expect them in a single set of kv pairs, with name and value as the two keys
// example: 'name:foo,value:"foo";name:bar,value:"bar"'
cwDim := nobl9v1alpha.CloudWatchMetricDimension{}
for _, dimMap := range strings.Split(sequence, ",") {
kv := strings.Split(dimMap, ":")
if len(kv) != 2 {
return []nobl9v1alpha.CloudWatchMetricDimension{}, fmt.Errorf("invalid dimension: %s", dimMap)
}

key := strings.TrimSpace(kv[0])
val := strings.TrimSpace(kv[1])

if strings.ToLower(key) == "name" {
cwDim.Name = &val
}

if strings.ToLower(key) == "value" {
cwDim.Value = &val
}
}
dims = append(dims, cwDim)
}

return dims, nil
}

func getN9SLISpec(o v1.SLOSpec, parsed []manifest.OpenSLOKind) v1.SLISpec {
var s v1.SLISpec
// if o.IndicatorRef is not nil, then return the indicator from the parsed list
Expand Down
130 changes: 74 additions & 56 deletions internal/pkg/convert/convert_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,6 @@ func Test_getMetricSource(t *testing.T) {
"region": "myregion",
"stat": "mystat",
"dimensions": "name:mydimensions,value:myvalue;name:mydimensions2,value:myvalue2",
"sql": "myquery",
"json": "myjson",
},
},
want: `cloudWatch:
Expand All @@ -276,8 +274,6 @@ func Test_getMetricSource(t *testing.T) {
value: myvalue
- name: mydimensions2
value: myvalue2
sql: myquery
json: myjson
`,
},
{
Expand Down Expand Up @@ -455,54 +451,6 @@ func Test_getMetricSource(t *testing.T) {
}
}

// func Test_getN9Indicator(t *testing.T) {
// t.Parallel()
// t.Run("nil", func(t *testing.T) {
// t.Parallel()
// ind := getN9Indicator(nil, "foo")
// assert.Equal(t, "ChangeMe", ind.MetricSource.Name)
// })
// t.Run("unknown", func(t *testing.T) {
// t.Parallel()
// var s v1.SLIInline
// ind := getN9Indicator(&s, "foo")
// assert.Equal(t, "ChangeMe", ind.MetricSource.Name)
// })
// t.Run("Total MetricSource exists", func(t *testing.T) {
// t.Parallel()
// s := v1.SLIInline{
// Spec: v1.SLISpec{
// RatioMetric: &v1.RatioMetric{
// Total: v1.MetricSourceHolder{
// MetricSource: v1.MetricSource{
// MetricSourceRef: "baz",
// },
// },
// },
// },
// }
// ind := getN9Indicator(&s, "foo")
// assert.Equal(t, "baz", ind.MetricSource.Name)
// })
// t.Run("Only Good MetricSource exists", func(t *testing.T) {
// t.Parallel()
// // if total doesn't exists, use default behavior and generate ChangeMe indicator
// s := v1.SLIInline{
// Spec: v1.SLISpec{
// RatioMetric: &v1.RatioMetric{
// Good: &v1.MetricSourceHolder{
// MetricSource: v1.MetricSource{
// MetricSourceRef: "baz",
// },
// },
// },
// },
// }
// ind := getN9Indicator(&s, "foo")
// assert.Equal(t, "ChangeMe", ind.MetricSource.Name)
// })
// }

func Test_RemoveDuplicates(t *testing.T) {
t.Parallel()
tests := []struct {
Expand Down Expand Up @@ -914,8 +862,6 @@ spec:
dimensions:
- name: CanaryName
value: web-app
sql: ""
json: ""
op: gte
service: foo-slos
timeWindows:
Expand Down Expand Up @@ -964,8 +910,6 @@ spec:
dimensions:
- name: CanaryName
value: web-app
sql: ""
json: ""
op: gte
service: foo-slos
timeWindows:
Expand Down Expand Up @@ -1396,3 +1340,77 @@ func Test_getN9Thresholds(t *testing.T) {
})
}
}

func Test_getN9CloudWatchQuery(t *testing.T) {
t.Parallel()
type args struct {
m map[string]string
}
tests := []struct {
name string
args args
want nobl9v1alpha.CloudWatchMetric
}{
{
name: "has dimensions",
args: args{
m: map[string]string{
"namespace": "mynamespace",
"metricName": "mymetricname",
"region": "myregion",
"stat": "mystat",
"dimensions": "name:mydimensions,value:myvalue;name:mydimensions2,value:myvalue2",
},
},
want: nobl9v1alpha.CloudWatchMetric{
Stat: func() *string { i := "mystat"; return &i }(),
Dimensions: []nobl9v1alpha.CloudWatchMetricDimension{
{
Name: func() *string { i := "mydimensions"; return &i }(),
Value: func() *string { i := "myvalue"; return &i }(),
},
{
Name: func() *string { i := "mydimensions2"; return &i }(),
Value: func() *string { i := "myvalue2"; return &i }(),
},
},
},
},
{
name: "has json",
args: args{
m: map[string]string{
"namespace": "mynamespace",
"metricName": "mymetricname",
"region": "myregion",
"json": "{\"foo\": \"bar\"}",
},
},
want: nobl9v1alpha.CloudWatchMetric{
JSON: func() *string { i := "{\"foo\": \"bar\"}"; return &i }(),
},
},
{
name: "has SQL",
args: args{
m: map[string]string{
"namespace": "mynamespace",
"metricName": "mymetricname",
"region": "myregion",
"sql": "SELECT * FROM FOO",
},
},
want: nobl9v1alpha.CloudWatchMetric{
SQL: func() *string { i := "SELECT * FROM FOO"; return &i }(),
},
},
}
for _, tt := range tests {
tt := tt // https://gist.github.com/kunwardeep/80c2e9f3d3256c894898bae82d9f75d0
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got := getN9CloudWatchQuery(tt.args.m)
assert.Equal(t, tt.want, got)
})
}
}
24 changes: 24 additions & 0 deletions test/cli/base.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/usr/bin/env bats

setup() {
load 'test_helper/common-setup'
_common_setup
}

@test "oslo displays help with no arguments" {
run oslo
assert_equal $status 0
assert_output --partial "Usage"
}

@test "oslo has help option" {
run oslo --help
assert_equal $status 0
assert_output --partial "Usage"
}

@test "oslo has version option" {
run oslo --version
assert_equal $status 0
assert_output
}
Loading

0 comments on commit b887e52

Please sign in to comment.