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

feat: [PC-13433]: add get Adjustment Events #228

Merged
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
826f51e
feature: [PC-13433]: add get Adjustment Events
piotrkazulak Oct 7, 2024
4769205
remove unused filepath property
piotrkazulak Oct 8, 2024
98505f6
add some better error handling
piotrkazulak Oct 8, 2024
a16bfe7
brek long line into two shorter
piotrkazulak Oct 8, 2024
82ae285
Merge branch 'main' into PC-13433-sloctl-new-command-for-getdeleteupd…
piotrkazulak Oct 8, 2024
5eea234
Merge branch 'main' into PC-13433-sloctl-new-command-for-getdeleteupd…
piotrkazulak Oct 10, 2024
5ad4ac1
chore: Fix e2e tests (#229)
dawidwisn Oct 10, 2024
86b7b17
chore: Update dependency cspell to v8.15.1 (#230)
renovate[bot] Oct 11, 2024
a4ca1a4
chore: Update dependency yaml to v2.6.0 (#231)
renovate[bot] Oct 13, 2024
c9258ff
refactor
piotrkazulak Oct 14, 2024
4bba482
fix commands that do not need sdk clint setup (verriosn and context)
piotrkazulak Oct 14, 2024
53be1a2
[wip] handle errors
piotrkazulak Oct 14, 2024
392d76e
Merge remote-tracking branch 'origin/main' into PC-13433-sloctl-new-c…
piotrkazulak Oct 15, 2024
734ceea
managEment
piotrkazulak Oct 15, 2024
d604dbb
errors Errorf -> New
piotrkazulak Oct 15, 2024
8ea256d
error hangling for sdk errors
piotrkazulak Oct 15, 2024
91661a9
Add some better desciption for adjustments commands
piotrkazulak Oct 16, 2024
323c864
set nobl9-go version to RC
piotrkazulak Oct 16, 2024
8f92d04
brake down long desciption into shorter lines
piotrkazulak Oct 16, 2024
e878069
remove comment and add break line before return
piotrkazulak Oct 17, 2024
50caf10
Merge branch 'main' into PC-13433-sloctl-new-command-for-getdeleteupd…
piotrkazulak Oct 18, 2024
3f4657a
project -> sloProject
piotrkazulak Oct 18, 2024
ec8dcaf
DoRequest with body
piotrkazulak Oct 18, 2024
8841763
CR suggestion and refactor
piotrkazulak Oct 25, 2024
89107a7
CR suggestion and refactor part #2
piotrkazulak Oct 25, 2024
b761f94
one more
piotrkazulak Oct 25, 2024
a0feb14
chore: switch to new error structure (APIErrors)
piotrkazulak Oct 29, 2024
33041d1
Merge branch 'main' into PC-13433-sloctl-new-command-for-getdeleteupd…
piotrkazulak Oct 29, 2024
fa861b6
remove unnecessary embed import
piotrkazulak Nov 4, 2024
366cd23
wip: add adjustments bat
piotrkazulak Nov 5, 2024
6d28125
Merge branch 'main' into PC-13433-sloctl-new-command-for-getdeleteupd…
piotrkazulak Nov 5, 2024
6dcff0a
add delete
piotrkazulak Nov 8, 2024
3d13b32
add update
piotrkazulak Nov 8, 2024
0e30e1d
add e2e tests for update and delete
piotrkazulak Nov 8, 2024
d278e6c
cr changes
piotrkazulak Nov 13, 2024
b59ec5d
gopkg.in/yaml.v3 -> goccy/go-yaml
piotrkazulak Nov 13, 2024
ad22a73
go mod update
piotrkazulak Nov 13, 2024
682fe71
Update internal/budgetadjustments/events/inputreader.go
piotrkazulak Nov 13, 2024
dabd834
fix the replay confilct
piotrkazulak Nov 13, 2024
5901742
clean the filepath
piotrkazulak Nov 13, 2024
780daf4
fix the makefile
piotrkazulak Nov 13, 2024
9e6e977
clean up after removing dry run
piotrkazulak Nov 13, 2024
bd231c1
goccy -> nobl9/go-yaml
piotrkazulak Nov 13, 2024
eca1a90
rearange events update/delete examples
piotrkazulak Nov 13, 2024
3dd0b37
use yaml.YAMLToJSON for inputs
piotrkazulak Nov 13, 2024
714adfa
reuse file for stdin examples
piotrkazulak Nov 13, 2024
16e71de
chore: [PC-14714] - specify api version after api group name in path
piotrkazulak Nov 14, 2024
971aaf0
clarifying in the description that new commands concerns only past ev…
piotrkazulak Dec 3, 2024
7dd9487
Merge branch 'main' into PC-13433-sloctl-new-command-for-getdeleteupd…
piotrkazulak Dec 4, 2024
e8f7815
Merge remote-tracking branch 'origin/main' into HEAD
piotrkazulak Dec 6, 2024
e361b15
Merge branch 'main' into PC-13433-sloctl-new-command-for-getdeleteupd…
piotrkazulak Dec 9, 2024
916c927
bump version for release
piotrkazulak Dec 10, 2024
f6792b4
bump sdk version
piotrkazulak Dec 11, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions internal/budgetadjustments/examples/get_example.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Get Adjustment Events for 'sample-adjustment-name' from 2024-09-23T00:45:00 UTC to 2024-09-23T20:46:00 UTC.
sloctl budgetadjustments get --adjustment-name=sample-adjustment-name --from=2024-09-23T00:45:00Z --to=2024-09-23T20:46:00Z


# Get Adjustment Events for 'sample-adjustment-name' from 2024-09-23T00:45:00 UTC to 2024-09-23T20:46:00 UTC
# only for one slo with sloName and project filters.
sloctl budgetadjustments get \
--adjustment-name=sample-adjustment-name \
--from=2024-09-23T00:45:00Z \
--to=2024-09-23T20:46:00Z \
--project=sample-project-name \
--slo-name=sample-slo-name
96 changes: 96 additions & 0 deletions internal/budgetadjustments/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package budgetadjustments

import (
"time"

"github.com/spf13/cobra"

"github.com/nobl9/sloctl/internal/csv"
)

const (
flagAdjustment = "adjustment-name"
flagFrom = "from"
flagTo = "to"
flagProject = "project"
flagSloName = "slo-name"
)

func mustRegisterOutputFormatFlags(
cmd *cobra.Command,
outputFormat, fieldSeparator, recordSeparator *string,
) {
cmd.PersistentFlags().StringVarP(outputFormat, "output", "o", "yaml",
`Output format: one of yaml|json|csv.`)

cmd.PersistentFlags().StringVarP(fieldSeparator, csv.FieldSeparatorFlag, "",
csv.DefaultFieldSeparator, "Field Separator for CSV.")

cmd.PersistentFlags().StringVarP(recordSeparator, csv.RecordSeparatorFlag, "",
csv.DefaultRecordSeparator, "Record Separator for CSV.")

if err := cmd.PersistentFlags().MarkHidden(csv.RecordSeparatorFlag); err != nil {
panic(err)
}
}

func mustRegisterAdjustmentFlag(cmd *cobra.Command, storeIn *string) {
cmd.Flags().StringVar(storeIn, flagAdjustment, "", "Name of the Adjustment.")
if err := cmd.MarkFlagRequired(flagAdjustment); err != nil {
panic(err)
}
}

func registerProjectFlag(cmd *cobra.Command, storeIn *string) {
cmd.Flags().StringVarP(storeIn, flagProject, "", "",
"Name of the project. Required when sloName is defined.")
}

func registerSloNameFlag(cmd *cobra.Command, storeIn *string) {
cmd.Flags().StringVarP(storeIn, flagSloName, "", "",
"Name of the SLO. Required when sloName is defined.")
}

type TimeValue struct{ time.Time }

const (
timeLayout = time.RFC3339
timeLayoutString = "RFC3339"
)

func (t *TimeValue) String() string {
if t.IsZero() {
return ""
}
return t.Format(timeLayout)
}

func (t *TimeValue) Set(s string) (err error) {
t.Time, err = time.Parse(timeLayout, s)
return
}

func (t *TimeValue) Type() string {
return "time"
}

func mustRegisterFromFlag(
cmd *cobra.Command,
storeIn *TimeValue,
) {
cmd.Flags().
Var(storeIn, flagFrom, "Specifies the start date and time for the data range (in UTC).")
if err := cmd.MarkFlagRequired(flagFrom); err != nil {
panic(err)
}
}

func mustRegisterToFlag(
cmd *cobra.Command,
storeIn *TimeValue,
) {
cmd.Flags().Var(storeIn, flagTo, "Specifies the end date and time for the data range (in UTC).")
if err := cmd.MarkFlagRequired(flagTo); err != nil {
panic(err)
}
}
131 changes: 131 additions & 0 deletions internal/budgetadjustments/get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package budgetadjustments

import (
_ "embed"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"os"
"time"

"github.com/nobl9/nobl9-go/sdk"
"github.com/pkg/errors"
"github.com/spf13/cobra"

"github.com/nobl9/sloctl/internal/printer"
)

type GetCmd struct {
client *sdk.Client
outputFormat string
fieldSeparator string
recordSeparator string
out io.Writer
adjustment string
from, to TimeValue
project, sloName string
}

type SLO struct {
Project string `json:"project" validate:"required"`
Name string `json:"name" validate:"required"`
}

type Event struct {
EventStart time.Time `json:"eventStart"`
EventEnd time.Time `json:"eventEnd"`
Slos []SLO `json:"slos"`
}

//go:embed examples/get_example.sh
var example string

func NewGetCmd(client *sdk.Client) *cobra.Command {
get := &GetCmd{out: os.Stdout}

cmd := &cobra.Command{
Use: "get",
Short: "Return a list of events for given Adjustment with related SLOs.",
Long: "This endpoint only return past and ongoing events (events that are already started)." +
"Please see Editing budget adjustments." +
"Maximum 500 events can be returned." +
"Optional filtering for specific SLO (only one). If SLO is defined we will return only events" +
" for that SLO and the result will also include other SLOs that this events have. Sorted by eventStart.",
Example: example,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
get.client = client
project, _ := cmd.Flags().GetString(flagProject)
sloName, _ := cmd.Flags().GetString(flagSloName)
if project != "" {
if err := cmd.MarkFlagRequired(flagSloName); err != nil {
panic(err)
}
}
if sloName != "" {
if err := cmd.MarkFlagRequired(flagProject); err != nil {
panic(err)
}
}
},
RunE: func(cmd *cobra.Command, args []string) error { return get.run(cmd) },
}

mustRegisterOutputFormatFlags(cmd, &get.outputFormat, &get.fieldSeparator, &get.recordSeparator)
mustRegisterAdjustmentFlag(cmd, &get.adjustment)
registerProjectFlag(cmd, &get.project)
registerSloNameFlag(cmd, &get.sloName)
mustRegisterFromFlag(cmd, &get.from)
mustRegisterToFlag(cmd, &get.to)

return cmd
}

func (g *GetCmd) run(cmd *cobra.Command) error {
values := url.Values{"from": {g.from.String()}, "to": {g.to.String()}}
if g.sloName != "" {
values.Add("sloName", g.sloName)
}
if g.project != "" {
values.Add("project", g.project)
}

resBody, err := doRequest(
g.client,
cmd.Context(),
http.MethodGet,
fmt.Sprintf("%s/%s/events", budgetAdjustmentAPI, g.adjustment),
values,
)
if err != nil {
return errors.Wrap(err, "failed to get")
}

var events []Event
if err := json.Unmarshal(resBody, &events); err != nil {
return errors.Wrap(err, "failed parse response")
}

if err := g.printObjects(events); err != nil {
return errors.Wrap(err, "failed to print objects")
}

return nil
}

func (g *GetCmd) printObjects(objects interface{}) error {
p, err := printer.New(
g.out,
printer.Format(g.outputFormat),
g.fieldSeparator,
g.recordSeparator,
)
if err != nil {
return err
}
if err = p.Print(objects); err != nil {
return err
}
return nil
}
35 changes: 35 additions & 0 deletions internal/budgetadjustments/request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package budgetadjustments

import (
"context"
_ "embed"
"io"
"net/url"

"github.com/nobl9/nobl9-go/sdk"
"github.com/pkg/errors"
)

const budgetAdjustmentAPI = "/v1/budgetadjustments"

func doRequest(
client *sdk.Client,
ctx context.Context,
method, endpoint string,
values url.Values,
) ([]byte, error) {
req, err := client.CreateRequest(ctx, method, endpoint, nil, values, nil)
if err != nil {
return nil, err
}
resp, err := client.HTTP.Do(req)
if err != nil {
return nil, err
}
defer func() { _ = resp.Body.Close() }()
if resp.StatusCode >= 300 {
data, _ := io.ReadAll(resp.Body)
return nil, errors.Errorf("bad response (status: %d): %s", resp.StatusCode, string(data))
}
return io.ReadAll(resp.Body)
}
19 changes: 19 additions & 0 deletions internal/budgetadjustments/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package budgetadjustments

import (
_ "embed"
"fmt"

"github.com/nobl9/nobl9-go/sdk"
"github.com/spf13/cobra"
)

func NewRootCmd(client *sdk.Client) *cobra.Command {
cmd := &cobra.Command{
Use: "budgetadjustments",
Short: "Manage budgetadjustment.",
}
cmd.PersistentFlags().BoolP("help", "h", false, fmt.Sprintf("Help for %s.", cmd.Name()))
cmd.AddCommand(NewGetCmd(client))
return cmd
}
6 changes: 4 additions & 2 deletions internal/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import (
"os"
"runtime"

"github.com/spf13/cobra"

v1alphaParser "github.com/nobl9/nobl9-go/manifest/v1alpha/parser"
"github.com/nobl9/nobl9-go/sdk"
"github.com/spf13/cobra"

"github.com/nobl9/sloctl/internal/budgetadjustments"
)

const programName = "sloctl"
Expand Down Expand Up @@ -54,6 +55,7 @@ For every command more detailed help is available.`,
rootCmd.AddCommand(root.NewConfigCmd())
rootCmd.AddCommand(root.NewReplayCmd())
rootCmd.AddCommand(root.NewAwsIamIds())
rootCmd.AddCommand(budgetadjustments.NewRootCmd(root.GetClient()))
return rootCmd
}

Expand Down
Loading