From d88354d9fe8705e2a35304a2d5243cf5da11cee6 Mon Sep 17 00:00:00 2001 From: Samir Faci Date: Thu, 17 Oct 2024 17:04:01 -0400 Subject: [PATCH] Minor refactoring and adding a test --- cli/backup/alerting_contacts.go | 14 +++-- internal/service/alerting.go | 60 ++++++++++++++----- internal/service/contracts.go | 2 +- internal/service/dashboards.go | 8 ++- internal/service/libraryelements.go | 5 +- internal/service/mocks/AlertingApi.go | 22 +++++-- internal/service/mocks/AuthenticationApi.go | 2 +- .../service/mocks/ConnectionPermissions.go | 2 +- internal/service/mocks/ConnectionsApi.go | 2 +- .../service/mocks/DashboardPermissionsApi.go | 2 +- internal/service/mocks/DashboardsApi.go | 2 +- internal/service/mocks/FoldersApi.go | 2 +- internal/service/mocks/GrafanaService.go | 22 +++++-- internal/service/mocks/LibraryElementsApi.go | 2 +- internal/service/mocks/LicenseApi.go | 2 +- internal/service/mocks/NewClientOpts.go | 2 +- internal/service/mocks/OrgPreferencesApi.go | 2 +- internal/service/mocks/OrganizationsApi.go | 2 +- internal/service/mocks/ServerInfoApi.go | 2 +- internal/service/mocks/ServiceAccountApi.go | 2 +- internal/service/mocks/Storage.go | 2 +- internal/service/mocks/TeamsApi.go | 2 +- internal/service/mocks/TokenApi.go | 2 +- internal/service/mocks/UsersApi.go | 2 +- internal/service/mocks/organizationCrudApi.go | 2 +- .../service/mocks/organizationToolsApi.go | 2 +- .../service/mocks/organizationUserCrudApi.go | 2 +- internal/service/serviceaccounts.go | 7 ++- internal/service/user.go | 7 ++- internal/tools/generics_tooling.go | 4 -- internal/tools/ptr/ptr.go | 5 ++ test/alerting_contacts_test.go | 46 ++++++++++++++ test/dashboard_integration_test.go | 7 ++- test/data/org_main-org/alerting/contacts.json | 51 +++++----------- 34 files changed, 194 insertions(+), 106 deletions(-) create mode 100644 internal/tools/ptr/ptr.go create mode 100644 test/alerting_contacts_test.go diff --git a/cli/backup/alerting_contacts.go b/cli/backup/alerting_contacts.go index aba9c93f..317e4b4e 100644 --- a/cli/backup/alerting_contacts.go +++ b/cli/backup/alerting_contacts.go @@ -3,6 +3,7 @@ package backup import ( "context" "encoding/json" + "log" "log/slog" "github.com/bep/simplecobra" @@ -44,10 +45,15 @@ func newListContactPointsCmd() simplecobra.Commander { }, RunFunc: func(ctx context.Context, cd *simplecobra.Commandeer, rootCmd *support.RootCommand, args []string) error { rootCmd.TableObj.AppendHeader(table.Row{"uid", "name", "slug", "type", "provenance", "settings"}) - contactPoints := rootCmd.GrafanaSvc().ListContactPoints() + contactPoints, err := rootCmd.GrafanaSvc().ListContactPoints() slog.Info("Listing contact points for context", slog.String("Organization", GetOrganizationName()), slog.String("context", GetContext())) + slog.Warn("GDG does not manage the 'email receiver' entity. It has a very odd behavior compared to all " + + "other entities. If you need to manage email contacts, please create a new contact. GDG will ignore the default contact.") + if err != nil { + log.Fatal("unable to retrieve Orgs contact points", slog.Any("err", err)) + } if len(contactPoints) == 0 { slog.Info("No contact points found") } else { @@ -99,7 +105,7 @@ func newUploadContactPointsCmd() simplecobra.Commander { cmd.Aliases = []string{"u"} }, RunFunc: func(ctx context.Context, cd *simplecobra.Commandeer, rootCmd *support.RootCommand, args []string) error { - removedItems, err := rootCmd.GrafanaSvc().UploadContactPoints() + newItems, err := rootCmd.GrafanaSvc().UploadContactPoints() slog.Info("Upload contact points for context", slog.String("Organization", GetOrganizationName()), slog.String("context", GetContext())) @@ -108,11 +114,11 @@ func newUploadContactPointsCmd() simplecobra.Commander { } else { slog.Info("contact points successfully uploaded") rootCmd.TableObj.AppendHeader(table.Row{"name"}) - for _, item := range removedItems { + for _, item := range newItems { rootCmd.TableObj.AppendRow(table.Row{item}) } - rootCmd.Render(cd.CobraCommand, removedItems) + rootCmd.Render(cd.CobraCommand, newItems) } return nil }, diff --git a/internal/service/alerting.go b/internal/service/alerting.go index b7d19aa4..b722efee 100644 --- a/internal/service/alerting.go +++ b/internal/service/alerting.go @@ -6,19 +6,31 @@ import ( "log" "log/slog" + "github.com/samber/lo" + + "github.com/esnet/gdg/internal/tools/ptr" + "github.com/esnet/gdg/internal/config" - "github.com/esnet/gdg/internal/tools" "github.com/grafana/grafana-openapi-client-go/client/provisioning" "github.com/grafana/grafana-openapi-client-go/models" ) -func (s *DashNGoImpl) ListContactPoints() []*models.EmbeddedContactPoint { +const ( + emailReceiver = "email receiver" +) + +func (s *DashNGoImpl) ListContactPoints() ([]*models.EmbeddedContactPoint, error) { p := provisioning.NewGetContactpointsParams() result, err := s.GetClient().Provisioning.GetContactpoints(p) if err != nil { - log.Fatalf("unable to retrieve contact points, err:%s", err.Error()) + return nil, err } - return result.GetPayload() + slog.Warn("removing any contacts with no uid such as 'email receiver' that cannot be managed by GDG") + data := lo.Filter(result.GetPayload(), func(item *models.EmbeddedContactPoint, index int) bool { + return item.UID != "" + }) + + return data, nil } func (s *DashNGoImpl) DownloadContactPoints() (string, error) { @@ -27,16 +39,21 @@ func (s *DashNGoImpl) DownloadContactPoints() (string, error) { err error ) p := provisioning.NewGetContactpointsExportParams() - p.Download = tools.PtrOf(true) - p.Decrypt = tools.PtrOf(true) - p.Format = tools.PtrOf("json") + p.Download = ptr.Of(true) + p.Decrypt = ptr.Of(true) + p.Format = ptr.Of("json") data, err := s.GetClient().Provisioning.GetContactpointsExport(p) if err != nil { log.Fatalf("unable to retrieve Contact Points, err: %s", err.Error()) } + // filter default contactPoints + payload := data.GetPayload() + payload.ContactPoints = lo.Filter(payload.ContactPoints, func(item *models.ContactPointExport, index int) bool { + return item.Name != emailReceiver + }) dsPath := buildResourcePath("contacts", config.AlertingResource) - if dsPacked, err = json.MarshalIndent(data.GetPayload(), "", " "); err != nil { + if dsPacked, err = json.MarshalIndent(payload.ContactPoints, "", " "); err != nil { return "", fmt.Errorf("unable to serialize data to JSON. %w", err) } if err = s.storage.WriteFile(dsPath, dsPacked); err != nil { @@ -52,8 +69,11 @@ func (s *DashNGoImpl) UploadContactPoints() ([]string, error) { rawDS []byte result []string ) - data := new(models.AlertingFileExport) - currentContacts := s.ListContactPoints() + var data []models.ContactPointExport + currentContacts, err := s.ListContactPoints() + if err != nil { + return nil, err + } m := make(map[string]*models.EmbeddedContactPoint) for ndx, i := range currentContacts { m[i.UID] = currentContacts[ndx] @@ -63,11 +83,15 @@ func (s *DashNGoImpl) UploadContactPoints() ([]string, error) { if rawDS, err = s.storage.ReadFile(fileLocation); err != nil { return nil, fmt.Errorf("failed to read file. file: %s, err: %w", fileLocation, err) } - if err = json.Unmarshal(rawDS, data); err != nil { + if err = json.Unmarshal(rawDS, &data); err != nil { return nil, fmt.Errorf("failed to unmarshall file, file:%s, err: %w", fileLocation, err) } - for _, i := range data.ContactPoints { + for _, i := range data { for _, r := range i.Receivers { + if r.UID == "" { + slog.Info("No valid UID found for record, skipping", slog.Any("type", r.Type)) + continue + } if _, ok := m[r.UID]; ok { // do update p := provisioning.NewPutContactpointParams() @@ -77,7 +101,7 @@ func (s *DashNGoImpl) UploadContactPoints() ([]string, error) { Name: i.Name, Provenance: "", Settings: r.Settings, - Type: tools.PtrOf(r.Type), + Type: ptr.Of(r.Type), UID: r.UID, } _, err := s.GetClient().Provisioning.PutContactpoint(p) @@ -95,9 +119,9 @@ func (s *DashNGoImpl) UploadContactPoints() ([]string, error) { UID: r.UID, Provenance: "", Settings: r.Settings, - Type: tools.PtrOf(r.Type), + Type: ptr.Of(r.Type), } - _, err := s.GetClient().Provisioning.PostContactpoints(p) + _, err = s.GetClient().Provisioning.PostContactpoints(p) if err != nil { slog.Error("failed to create contact point", slog.Any("uid", r.UID)) continue @@ -116,7 +140,11 @@ func (s *DashNGoImpl) ClearContactPoints() ([]string, error) { err error results []string ) - contacts := s.ListContactPoints() + contacts, err := s.ListContactPoints() + if err != nil { + return nil, err + } + for _, contact := range contacts { _, err = s.GetClient().Provisioning.DeleteContactpoints(contact.UID) if err != nil { diff --git a/internal/service/contracts.go b/internal/service/contracts.go index 02e75167..9959378a 100644 --- a/internal/service/contracts.go +++ b/internal/service/contracts.go @@ -60,7 +60,7 @@ type DashboardsApi interface { } type AlertingApi interface { - ListContactPoints() []*models.EmbeddedContactPoint + ListContactPoints() ([]*models.EmbeddedContactPoint, error) DownloadContactPoints() (string, error) ClearContactPoints() ([]string, error) UploadContactPoints() ([]string, error) diff --git a/internal/service/dashboards.go b/internal/service/dashboards.go index b8f2258e..b0108b70 100644 --- a/internal/service/dashboards.go +++ b/internal/service/dashboards.go @@ -12,6 +12,8 @@ import ( "sort" "strings" + "github.com/esnet/gdg/internal/tools/ptr" + "github.com/esnet/gdg/internal/config" "github.com/esnet/gdg/internal/service/filters" "github.com/esnet/gdg/internal/service/types" @@ -279,9 +281,9 @@ func (s *DashNGoImpl) ListDashboards(filterReq filters.Filter) []*models.Hit { if tag != "" { searchParams.Tag = []string{tag} } - searchParams.Limit = tools.PtrOf(limit) - searchParams.Page = tools.PtrOf(page) - searchParams.Type = tools.PtrOf(searchTypeDashboard) + searchParams.Limit = ptr.Of(limit) + searchParams.Page = ptr.Of(page) + searchParams.Type = ptr.Of(searchTypeDashboard) pageBoardLinks, err := s.GetClient().Search.Search(searchParams) if err != nil { diff --git a/internal/service/libraryelements.go b/internal/service/libraryelements.go index 3d21821a..279dc356 100644 --- a/internal/service/libraryelements.go +++ b/internal/service/libraryelements.go @@ -8,9 +8,10 @@ import ( "log/slog" "strings" + "github.com/esnet/gdg/internal/tools/ptr" + "github.com/esnet/gdg/internal/config" "github.com/esnet/gdg/internal/service/filters" - "github.com/esnet/gdg/internal/tools" "github.com/gosimple/slug" "github.com/grafana/grafana-openapi-client-go/client/library_elements" "github.com/grafana/grafana-openapi-client-go/models" @@ -66,7 +67,7 @@ func (s *DashNGoImpl) ListLibraryElements(filter filters.Filter) []*models.Libra params := library_elements.NewGetLibraryElementsParams() params.FolderFilter = &folderList - params.Kind = tools.PtrOf(listLibraryPanels) + params.Kind = ptr.Of(listLibraryPanels) libraryElements, err := s.GetClient().LibraryElements.GetLibraryElements(params) if err != nil { log.Fatalf("Unable to list Library Elements %v", err) diff --git a/internal/service/mocks/AlertingApi.go b/internal/service/mocks/AlertingApi.go index 66f96425..03fcf134 100644 --- a/internal/service/mocks/AlertingApi.go +++ b/internal/service/mocks/AlertingApi.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks @@ -133,7 +133,7 @@ func (_c *AlertingApi_DownloadContactPoints_Call) RunAndReturn(run func() (strin } // ListContactPoints provides a mock function with given fields: -func (_m *AlertingApi) ListContactPoints() []*models.EmbeddedContactPoint { +func (_m *AlertingApi) ListContactPoints() ([]*models.EmbeddedContactPoint, error) { ret := _m.Called() if len(ret) == 0 { @@ -141,6 +141,10 @@ func (_m *AlertingApi) ListContactPoints() []*models.EmbeddedContactPoint { } var r0 []*models.EmbeddedContactPoint + var r1 error + if rf, ok := ret.Get(0).(func() ([]*models.EmbeddedContactPoint, error)); ok { + return rf() + } if rf, ok := ret.Get(0).(func() []*models.EmbeddedContactPoint); ok { r0 = rf() } else { @@ -149,7 +153,13 @@ func (_m *AlertingApi) ListContactPoints() []*models.EmbeddedContactPoint { } } - return r0 + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // AlertingApi_ListContactPoints_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListContactPoints' @@ -169,12 +179,12 @@ func (_c *AlertingApi_ListContactPoints_Call) Run(run func()) *AlertingApi_ListC return _c } -func (_c *AlertingApi_ListContactPoints_Call) Return(_a0 []*models.EmbeddedContactPoint) *AlertingApi_ListContactPoints_Call { - _c.Call.Return(_a0) +func (_c *AlertingApi_ListContactPoints_Call) Return(_a0 []*models.EmbeddedContactPoint, _a1 error) *AlertingApi_ListContactPoints_Call { + _c.Call.Return(_a0, _a1) return _c } -func (_c *AlertingApi_ListContactPoints_Call) RunAndReturn(run func() []*models.EmbeddedContactPoint) *AlertingApi_ListContactPoints_Call { +func (_c *AlertingApi_ListContactPoints_Call) RunAndReturn(run func() ([]*models.EmbeddedContactPoint, error)) *AlertingApi_ListContactPoints_Call { _c.Call.Return(run) return _c } diff --git a/internal/service/mocks/AuthenticationApi.go b/internal/service/mocks/AuthenticationApi.go index 236566ac..8f44c16c 100644 --- a/internal/service/mocks/AuthenticationApi.go +++ b/internal/service/mocks/AuthenticationApi.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/ConnectionPermissions.go b/internal/service/mocks/ConnectionPermissions.go index 4bde69a3..42eda9f1 100644 --- a/internal/service/mocks/ConnectionPermissions.go +++ b/internal/service/mocks/ConnectionPermissions.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/ConnectionsApi.go b/internal/service/mocks/ConnectionsApi.go index 3e47bf88..902da856 100644 --- a/internal/service/mocks/ConnectionsApi.go +++ b/internal/service/mocks/ConnectionsApi.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/DashboardPermissionsApi.go b/internal/service/mocks/DashboardPermissionsApi.go index 00f850ed..35394628 100644 --- a/internal/service/mocks/DashboardPermissionsApi.go +++ b/internal/service/mocks/DashboardPermissionsApi.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/DashboardsApi.go b/internal/service/mocks/DashboardsApi.go index cf378b21..56aba452 100644 --- a/internal/service/mocks/DashboardsApi.go +++ b/internal/service/mocks/DashboardsApi.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/FoldersApi.go b/internal/service/mocks/FoldersApi.go index ce209436..5c68ab09 100644 --- a/internal/service/mocks/FoldersApi.go +++ b/internal/service/mocks/FoldersApi.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/GrafanaService.go b/internal/service/mocks/GrafanaService.go index cddfc814..c2145961 100644 --- a/internal/service/mocks/GrafanaService.go +++ b/internal/service/mocks/GrafanaService.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks @@ -1962,7 +1962,7 @@ func (_c *GrafanaService_ListConnections_Call) RunAndReturn(run func(filters.Fil } // ListContactPoints provides a mock function with given fields: -func (_m *GrafanaService) ListContactPoints() []*models.EmbeddedContactPoint { +func (_m *GrafanaService) ListContactPoints() ([]*models.EmbeddedContactPoint, error) { ret := _m.Called() if len(ret) == 0 { @@ -1970,6 +1970,10 @@ func (_m *GrafanaService) ListContactPoints() []*models.EmbeddedContactPoint { } var r0 []*models.EmbeddedContactPoint + var r1 error + if rf, ok := ret.Get(0).(func() ([]*models.EmbeddedContactPoint, error)); ok { + return rf() + } if rf, ok := ret.Get(0).(func() []*models.EmbeddedContactPoint); ok { r0 = rf() } else { @@ -1978,7 +1982,13 @@ func (_m *GrafanaService) ListContactPoints() []*models.EmbeddedContactPoint { } } - return r0 + if rf, ok := ret.Get(1).(func() error); ok { + r1 = rf() + } else { + r1 = ret.Error(1) + } + + return r0, r1 } // GrafanaService_ListContactPoints_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListContactPoints' @@ -1998,12 +2008,12 @@ func (_c *GrafanaService_ListContactPoints_Call) Run(run func()) *GrafanaService return _c } -func (_c *GrafanaService_ListContactPoints_Call) Return(_a0 []*models.EmbeddedContactPoint) *GrafanaService_ListContactPoints_Call { - _c.Call.Return(_a0) +func (_c *GrafanaService_ListContactPoints_Call) Return(_a0 []*models.EmbeddedContactPoint, _a1 error) *GrafanaService_ListContactPoints_Call { + _c.Call.Return(_a0, _a1) return _c } -func (_c *GrafanaService_ListContactPoints_Call) RunAndReturn(run func() []*models.EmbeddedContactPoint) *GrafanaService_ListContactPoints_Call { +func (_c *GrafanaService_ListContactPoints_Call) RunAndReturn(run func() ([]*models.EmbeddedContactPoint, error)) *GrafanaService_ListContactPoints_Call { _c.Call.Return(run) return _c } diff --git a/internal/service/mocks/LibraryElementsApi.go b/internal/service/mocks/LibraryElementsApi.go index 30caac58..24f6a1f4 100644 --- a/internal/service/mocks/LibraryElementsApi.go +++ b/internal/service/mocks/LibraryElementsApi.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/LicenseApi.go b/internal/service/mocks/LicenseApi.go index d68af936..15c75abf 100644 --- a/internal/service/mocks/LicenseApi.go +++ b/internal/service/mocks/LicenseApi.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/NewClientOpts.go b/internal/service/mocks/NewClientOpts.go index 1fe8ae07..1ad7b91d 100644 --- a/internal/service/mocks/NewClientOpts.go +++ b/internal/service/mocks/NewClientOpts.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/OrgPreferencesApi.go b/internal/service/mocks/OrgPreferencesApi.go index f5360ad1..042108ac 100644 --- a/internal/service/mocks/OrgPreferencesApi.go +++ b/internal/service/mocks/OrgPreferencesApi.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/OrganizationsApi.go b/internal/service/mocks/OrganizationsApi.go index 2186437b..a2043311 100644 --- a/internal/service/mocks/OrganizationsApi.go +++ b/internal/service/mocks/OrganizationsApi.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/ServerInfoApi.go b/internal/service/mocks/ServerInfoApi.go index b4e0ffde..18ea0952 100644 --- a/internal/service/mocks/ServerInfoApi.go +++ b/internal/service/mocks/ServerInfoApi.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/ServiceAccountApi.go b/internal/service/mocks/ServiceAccountApi.go index f7621575..733e9e2c 100644 --- a/internal/service/mocks/ServiceAccountApi.go +++ b/internal/service/mocks/ServiceAccountApi.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/Storage.go b/internal/service/mocks/Storage.go index ee524f0b..e4d23ac7 100644 --- a/internal/service/mocks/Storage.go +++ b/internal/service/mocks/Storage.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/TeamsApi.go b/internal/service/mocks/TeamsApi.go index 7b309d76..858c737e 100644 --- a/internal/service/mocks/TeamsApi.go +++ b/internal/service/mocks/TeamsApi.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/TokenApi.go b/internal/service/mocks/TokenApi.go index aa424f85..880a21b1 100644 --- a/internal/service/mocks/TokenApi.go +++ b/internal/service/mocks/TokenApi.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/UsersApi.go b/internal/service/mocks/UsersApi.go index 7eb583b7..66500b84 100644 --- a/internal/service/mocks/UsersApi.go +++ b/internal/service/mocks/UsersApi.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/organizationCrudApi.go b/internal/service/mocks/organizationCrudApi.go index ba3cbf9e..c7a3f25f 100644 --- a/internal/service/mocks/organizationCrudApi.go +++ b/internal/service/mocks/organizationCrudApi.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/organizationToolsApi.go b/internal/service/mocks/organizationToolsApi.go index 1c926192..81404acf 100644 --- a/internal/service/mocks/organizationToolsApi.go +++ b/internal/service/mocks/organizationToolsApi.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/mocks/organizationUserCrudApi.go b/internal/service/mocks/organizationUserCrudApi.go index dd9e78c6..ea92eaff 100644 --- a/internal/service/mocks/organizationUserCrudApi.go +++ b/internal/service/mocks/organizationUserCrudApi.go @@ -1,4 +1,4 @@ -// Code generated by mockery v2.42.0. DO NOT EDIT. +// Code generated by mockery v2.44.1. DO NOT EDIT. package mocks diff --git a/internal/service/serviceaccounts.go b/internal/service/serviceaccounts.go index 43a95e9f..b83c30fb 100644 --- a/internal/service/serviceaccounts.go +++ b/internal/service/serviceaccounts.go @@ -5,9 +5,10 @@ import ( "log" "log/slog" + "github.com/esnet/gdg/internal/tools/ptr" + "github.com/esnet/gdg/internal/types" - "github.com/esnet/gdg/internal/tools" "github.com/grafana/grafana-openapi-client-go/client/service_accounts" "github.com/grafana/grafana-openapi-client-go/models" "github.com/samber/lo" @@ -44,8 +45,8 @@ func (s *DashNGoImpl) CreateServiceAccountToken(serviceAccountId int64, name str func (s *DashNGoImpl) ListServiceAccounts() []*types.ServiceAccountDTOWithTokens { p := service_accounts.NewSearchOrgServiceAccountsWithPagingParams() - p.Disabled = tools.PtrOf(false) - p.Perpage = tools.PtrOf(int64(5000)) + p.Disabled = ptr.Of(false) + p.Perpage = ptr.Of(int64(5000)) resp, err := s.GetClient().ServiceAccounts.SearchOrgServiceAccountsWithPaging(p) if err != nil { diff --git a/internal/service/user.go b/internal/service/user.go index f90ddfdc..1b7e1e6c 100644 --- a/internal/service/user.go +++ b/internal/service/user.go @@ -10,9 +10,10 @@ import ( "sort" "strings" + "github.com/esnet/gdg/internal/tools/ptr" + "github.com/esnet/gdg/internal/config" "github.com/esnet/gdg/internal/service/filters" - "github.com/esnet/gdg/internal/tools" "github.com/esnet/gdg/internal/types" "github.com/gosimple/slug" "github.com/grafana/grafana-openapi-client-go/client/admin_users" @@ -164,8 +165,8 @@ func (s *DashNGoImpl) ListUsers(filter filters.Filter) []*models.UserSearchHitDT } var filteredUsers []*models.UserSearchHitDTO params := users.NewSearchUsersParams() - params.Page = tools.PtrOf(int64(1)) - params.Perpage = tools.PtrOf(int64(5000)) + params.Page = ptr.Of(int64(1)) + params.Perpage = ptr.Of(int64(5000)) usersList, err := s.GetClient().Users.SearchUsers(params) if err != nil { log.Fatal(err.Error()) diff --git a/internal/tools/generics_tooling.go b/internal/tools/generics_tooling.go index 4db316db..2d259867 100644 --- a/internal/tools/generics_tooling.go +++ b/internal/tools/generics_tooling.go @@ -6,10 +6,6 @@ import ( "os" ) -func PtrOf[T any](value T) *T { - return &value -} - func DeepCopy[T any](value T) (*T, error) { origJSON, err := json.Marshal(value) if err != nil { diff --git a/internal/tools/ptr/ptr.go b/internal/tools/ptr/ptr.go new file mode 100644 index 00000000..c36b2a2d --- /dev/null +++ b/internal/tools/ptr/ptr.go @@ -0,0 +1,5 @@ +package ptr + +func Of[T any](value T) *T { + return &value +} diff --git a/test/alerting_contacts_test.go b/test/alerting_contacts_test.go new file mode 100644 index 00000000..24f6419b --- /dev/null +++ b/test/alerting_contacts_test.go @@ -0,0 +1,46 @@ +package test + +import ( + "bytes" + "log/slog" + "os" + "slices" + "testing" + + "github.com/esnet/gdg/pkg/test_tooling" + "github.com/stretchr/testify/assert" +) + +func TestContactsCrud(t *testing.T) { + apiClient, _, _, cleanup := test_tooling.InitTest(t, nil, nil) + defer func() { + err := cleanup() + if err != nil { + slog.Warn("Unable to clean up after alerting contacts crud tests") + } + }() + contactPoints, err := apiClient.ListContactPoints() + assert.NoError(t, err) + assert.Equal(t, len(contactPoints), 0, "Validate initial contact list is empty") + contacts, err := apiClient.UploadContactPoints() + assert.NoError(t, err) + assert.Equal(t, len(contacts), 2) + assert.True(t, slices.Contains(contacts, "discord")) + assert.True(t, slices.Contains(contacts, "email receiver")) + contactPoints, err = apiClient.ListContactPoints() + assert.NoError(t, err) + assert.Equal(t, len(contactPoints), 3) + _ = contactPoints + data, err := apiClient.DownloadContactPoints() + assert.NoError(t, err) + assert.Equal(t, "test/data/org_main-org/alerting/contacts.json", data) + rawData, err := os.ReadFile(data) + assert.NoError(t, err) + assert.True(t, bytes.Contains(rawData, []byte("discord"))) + assert.True(t, bytes.Contains(rawData, []byte("email receiver"))) + contacts, err = apiClient.ClearContactPoints() + assert.NoError(t, err) + assert.Equal(t, len(contacts), 2) + + _ = contacts +} diff --git a/test/dashboard_integration_test.go b/test/dashboard_integration_test.go index 9a828f0e..2b7ec8eb 100644 --- a/test/dashboard_integration_test.go +++ b/test/dashboard_integration_test.go @@ -8,7 +8,8 @@ import ( "strings" "testing" - "github.com/esnet/gdg/internal/tools" + "github.com/esnet/gdg/internal/tools/ptr" + "github.com/esnet/gdg/internal/types" "github.com/esnet/gdg/pkg/test_tooling/containers" "github.com/samber/lo" @@ -266,7 +267,7 @@ func TestDashboardPermissionsCrud(t *testing.T) { // Get current Permissions currentPerms, err := apiClient.ListDashboardPermissions(nil) assert.Equal(t, len(currentPerms), 16) - entry := tools.PtrOf(lo.FirstOrEmpty(lo.Filter(currentPerms, func(item types.DashboardAndPermissions, index int) bool { + entry := ptr.Of(lo.FirstOrEmpty(lo.Filter(currentPerms, func(item types.DashboardAndPermissions, index int) bool { return item.Dashboard.Title == "Bandwidth Dashboard" }))) assert.NotNil(t, entry) @@ -282,7 +283,7 @@ func TestDashboardPermissionsCrud(t *testing.T) { assert.Equal(t, len(addPerms), 16) currentPerms, err = apiClient.ListDashboardPermissions(nil) entry = nil - entry = tools.PtrOf(lo.FirstOrEmpty(lo.Filter(currentPerms, func(item types.DashboardAndPermissions, index int) bool { + entry = ptr.Of(lo.FirstOrEmpty(lo.Filter(currentPerms, func(item types.DashboardAndPermissions, index int) bool { return item.Dashboard.Title == "Bandwidth Dashboard" }))) assert.NotNil(t, entry) diff --git a/test/data/org_main-org/alerting/contacts.json b/test/data/org_main-org/alerting/contacts.json index b550af41..2bc299a4 100644 --- a/test/data/org_main-org/alerting/contacts.json +++ b/test/data/org_main-org/alerting/contacts.json @@ -1,35 +1,16 @@ -{ - "apiVersion": 1, - "contactPoints": [ - { - "name": "discord", - "orgId": 4, - "receivers": [ - { - "settings": { - "url": "https://www.discord.com?q=woot", - "use_discord_username": false - }, - "type": "discord", - "uid": "fdxmqkyb5gl4xb" - } - ] - }, - { - "name": "email receiver", - "orgId": 4, - "receivers": [ - { - "settings": { - "addresses": "\u003cexample@email.com\u003e" - }, - "type": "email", - "uid": "edxmyx0pdyo74a" - } - ] - } - ], - "groups": null, - "muteTimes": null, - "policies": null -} +[ + { + "name": "discord", + "orgId": 1, + "receivers": [ + { + "settings": { + "url": "https://www.discord.com?q=woot", + "use_discord_username": false + }, + "type": "discord", + "uid": "fdxmqkyb5gl4xb" + } + ] + } +] \ No newline at end of file