Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: budgetadjutments events - handle multiple YAML documents in one file #294

2 changes: 1 addition & 1 deletion internal/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.10.1
0.11.3
32 changes: 17 additions & 15 deletions internal/budgetadjustments/events/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,24 +43,26 @@ func NewDeleteCmd(clientProvider sdkclient.SdkClientProvider) *cobra.Command {
}

func (g *DeleteCmd) run(cmd *cobra.Command) error {
data, err := readFile(g.filepath)
docs, err := getEventsStringsFromFile(g.filepath)
if err != nil {
return errors.Wrap(err, "failed to read input data")
}
body, err := yaml.YAMLToJSON(data)
if err != nil {
return errors.Wrap(err, "failed to convert input data to JSON")
return errors.Wrap(err, "failed to read events form file")
}

if _, err = DoRequest(
g.client,
cmd.Context(),
http.MethodPost,
fmt.Sprintf("%s/%s/events/delete", BudgetAdjustmentAPI, g.adjustment),
nil,
bytes.NewReader(body),
); err != nil {
return err
for _, doc := range docs {
jsonBytes, err := yaml.YAMLToJSON([]byte(doc))
if err != nil {
return errors.Wrap(err, "failed to convert input data to JSON")
}
if _, err = DoRequest(
g.client,
cmd.Context(),
http.MethodPost,
fmt.Sprintf("%s/%s/events/delete", BudgetAdjustmentAPI, g.adjustment),
nil,
bytes.NewReader(jsonBytes),
); err != nil {
return err
}
}

return nil
Expand Down
24 changes: 24 additions & 0 deletions internal/budgetadjustments/events/inputreader.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import (
"io"
"os"
"path/filepath"
"regexp"

"github.com/pkg/errors"
)

func readFile(path string) (data []byte, err error) {
Expand All @@ -13,3 +16,24 @@ func readFile(path string) (data []byte, err error) {
path = filepath.Clean(path)
return os.ReadFile(path) // #nosec G304
}

func getEventsStringsFromFile(path string) ([]string, error) {
data, err := readFile(path)
if err != nil {
return nil, errors.Wrap(err, "failed to read input data")
}
return splitYAMLDocs(data), nil
}

func splitYAMLDocs(data []byte) []string {
re := regexp.MustCompile("(?m)^---$\n?")
split := re.Split(string(data), -1)
docs := make([]string, 0, len(split))
for _, docStr := range split {
if len(docStr) < 1 {
continue
}
docs = append(docs, docStr)
}
return docs
}
160 changes: 160 additions & 0 deletions internal/budgetadjustments/events/inputreader_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
package events

import (
"reflect"
"strings"
"testing"
)

func TestSplitYAMLDocuments(t *testing.T) {
tests := []struct {
name string
input string
expected []string
}{
{
name: "Basic YAML Split",
input: `---
name: doc1
value: 1
---
name: doc2
value: 2
---
name: doc3
value: 3
`,
expected: []string{
"name: doc1\nvalue: 1",
"name: doc2\nvalue: 2",
"name: doc3\nvalue: 3",
},
},
{
name: "Basic YAML Split with additional separators",
input: `---
---
---
name: doc1
value: 1
---
---
name: doc2
value: 2
---
name: doc3
value: 3
---
---`,
expected: []string{
"name: doc1\nvalue: 1",
"name: doc2\nvalue: 2",
"name: doc3\nvalue: 3",
},
},
{
name: "YAML with Lists",
input: `---
list:
- item1
- item2
---
list:
- item3
- item4
`,
expected: []string{
"list:\n - item1\n - item2",
"list:\n - item3\n - item4",
},
},
{
name: "YAML with Nested Structures",
input: `---
parent:
child: value1
---
parent:
child: value2
`,
expected: []string{
"parent:\n child: value1",
"parent:\n child: value2",
},
},
{
name: "invalid YAML",
input: `---
foo bar
baz: bob
`,
expected: []string{"foo bar\nbaz: bob"},
},
{
name: "just YAML",
input: "YAML",
expected: []string{"YAML"},
},
{
name: "YAML with doc separators found in content",
input: `---
parent:
child: "foo---bar"
---
parent:
child: value2
---
----nt:
child: value3
----
---
---
---
`,
expected: []string{
"parent:\n child: \"foo---bar\"",
"parent:\n child: value2",
"----nt:\n child: value3\n----",
"---\n ---",
},
},
{
name: "YAML with correct event format",
input: `
- eventStart: 2024-12-04T06:37:00Z
eventEnd: 2024-12-04T06:59:00Z
slos:
- project: test-project
name: sample-slo-1-578b974d-8e27-43cf-85a3-7751a774f13d
update:
eventStart: 2024-12-04T06:37:00Z
eventEnd: 2024-12-04T06:59:00Z
`,
expected: []string{
`- eventStart: 2024-12-04T06:37:00Z
eventEnd: 2024-12-04T06:59:00Z
slos:
- project: test-project
name: sample-slo-1-578b974d-8e27-43cf-85a3-7751a774f13d
update:
eventStart: 2024-12-04T06:37:00Z
eventEnd: 2024-12-04T06:59:00Z`,
},
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := splitYAMLDocs([]byte(tt.input))

// Trim whitespace from results for better comparison
for i := range result {
result[i] = strings.TrimSpace(result[i])
}

if !reflect.DeepEqual(result, tt.expected) {
t.Errorf("Test %s failed. Expected %v, but got %v", tt.name, tt.expected, result)
}
})
}
}
34 changes: 18 additions & 16 deletions internal/budgetadjustments/events/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,25 +43,27 @@ func NewUpdateCmd(clientProvider sdkclient.SdkClientProvider) *cobra.Command {
}

func (g *UpdateCmd) run(cmd *cobra.Command) error {
data, err := readFile(g.filepath)
docs, err := getEventsStringsFromFile(g.filepath)
if err != nil {
return errors.Wrap(err, "failed to read input data")
}
body, err := yaml.YAMLToJSON(data)
if err != nil {
return errors.Wrap(err, "failed to convert input data to JSON")
return errors.Wrap(err, "failed to read events form file")
}

_, err = DoRequest(
g.client,
cmd.Context(),
http.MethodPut,
fmt.Sprintf("%s/%s/events/update", BudgetAdjustmentAPI, g.adjustment),
nil,
bytes.NewReader(body),
)
if err != nil {
return err
for _, doc := range docs {
jsonBytes, err := yaml.YAMLToJSON([]byte(doc))
if err != nil {
return errors.Wrap(err, "failed to convert input data to JSON")
}
_, err = DoRequest(
g.client,
cmd.Context(),
http.MethodPut,
fmt.Sprintf("%s/%s/events/update", BudgetAdjustmentAPI, g.adjustment),
nil,
bytes.NewReader(jsonBytes),
)
if err != nil {
return err
}
}

return nil
Expand Down
Loading