From 5ebf2d08f6d6e842540cd0a67ef0ea0240ef2b2d Mon Sep 17 00:00:00 2001 From: Sofia Papagiannaki <1632407+papagian@users.noreply.github.com> Date: Tue, 26 Mar 2024 12:32:56 +0200 Subject: [PATCH] Provisioning: Fix regression when dashboardProvisioner is accessed before being initialised (#85011) * Provisioning: Fix regression when dashboardProvisioner is accessed before being initialized * Set dashboard provisioner in the provider --- .../apis/dashboard/access/sql_dashboards.go | 3 +- pkg/services/provisioning/provisioning.go | 28 +++++++++++++------ .../provisioning/provisioning_test.go | 11 ++++---- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/pkg/registry/apis/dashboard/access/sql_dashboards.go b/pkg/registry/apis/dashboard/access/sql_dashboards.go index 4064a1fa7a3..a7dc2698706 100644 --- a/pkg/registry/apis/dashboard/access/sql_dashboards.go +++ b/pkg/registry/apis/dashboard/access/sql_dashboards.go @@ -322,8 +322,9 @@ func (a *dashboardSqlAccess) scanRow(rows *sql.Rows) (*dashboardRow, error) { if origin_name.Valid { ts := time.Unix(origin_ts.Int64, 0) + resolvedPath := a.provisioning.GetDashboardProvisionerResolvedPath(origin_name.String) originPath, err := filepath.Rel( - a.provisioning.GetDashboardProvisionerResolvedPath(origin_name.String), + resolvedPath, origin_path.String, ) if err != nil { diff --git a/pkg/services/provisioning/provisioning.go b/pkg/services/provisioning/provisioning.go index 14e3649a1f0..a0f60d0b2f6 100644 --- a/pkg/services/provisioning/provisioning.go +++ b/pkg/services/provisioning/provisioning.go @@ -74,9 +74,25 @@ func ProvideService( orgService: orgService, folderService: folderService, } + + err := s.setDashboardProvisioner() + if err != nil { + return nil, fmt.Errorf("%v: %w", "Failed to create provisioner", err) + } + return s, nil } +func (ps *ProvisioningServiceImpl) setDashboardProvisioner() error { + dashboardPath := filepath.Join(ps.Cfg.ProvisioningPath, "dashboards") + dashProvisioner, err := ps.newDashboardProvisioner(context.Background(), dashboardPath, ps.dashboardProvisioningService, ps.orgService, ps.dashboardService, ps.folderService) + if err != nil { + return fmt.Errorf("%v: %w", "Failed to create provisioner", err) + } + ps.dashboardProvisioner = dashProvisioner + return nil +} + type ProvisioningService interface { registry.BackgroundService RunInitProvisioners(ctx context.Context) error @@ -110,6 +126,7 @@ func newProvisioningServiceImpl( newDashboardProvisioner: newDashboardProvisioner, provisionDatasources: provisionDatasources, provisionPlugins: provisionPlugins, + Cfg: setting.NewCfg(), } } @@ -215,25 +232,18 @@ func (ps *ProvisioningServiceImpl) ProvisionPlugins(ctx context.Context) error { } func (ps *ProvisioningServiceImpl) ProvisionDashboards(ctx context.Context) error { - dashboardPath := filepath.Join(ps.Cfg.ProvisioningPath, "dashboards") - dashProvisioner, err := ps.newDashboardProvisioner(ctx, dashboardPath, ps.dashboardProvisioningService, ps.orgService, ps.dashboardService, ps.folderService) - if err != nil { - return fmt.Errorf("%v: %w", "Failed to create provisioner", err) - } - ps.mutex.Lock() defer ps.mutex.Unlock() ps.cancelPolling() - dashProvisioner.CleanUpOrphanedDashboards(ctx) + ps.dashboardProvisioner.CleanUpOrphanedDashboards(ctx) - err = dashProvisioner.Provision(ctx) + err := ps.dashboardProvisioner.Provision(ctx) if err != nil { // If we fail to provision with the new provisioner, the mutex will unlock and the polling will restart with the // old provisioner as we did not switch them yet. return fmt.Errorf("%v: %w", "Failed to provision dashboards", err) } - ps.dashboardProvisioner = dashProvisioner return nil } diff --git a/pkg/services/provisioning/provisioning_test.go b/pkg/services/provisioning/provisioning_test.go index 209732ce4b3..93691f7b12a 100644 --- a/pkg/services/provisioning/provisioning_test.go +++ b/pkg/services/provisioning/provisioning_test.go @@ -7,18 +7,18 @@ import ( "time" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" dashboardstore "github.com/grafana/grafana/pkg/services/dashboards" "github.com/grafana/grafana/pkg/services/folder" "github.com/grafana/grafana/pkg/services/org" "github.com/grafana/grafana/pkg/services/provisioning/dashboards" "github.com/grafana/grafana/pkg/services/provisioning/utils" - "github.com/grafana/grafana/pkg/setting" ) func TestProvisioningServiceImpl(t *testing.T) { t.Run("Restart dashboard provisioning and stop service", func(t *testing.T) { - serviceTest := setup() + serviceTest := setup(t) err := serviceTest.service.ProvisionDashboards(context.Background()) assert.Nil(t, err) serviceTest.startService() @@ -45,7 +45,7 @@ func TestProvisioningServiceImpl(t *testing.T) { }) t.Run("Failed reloading does not stop polling with old provisioned", func(t *testing.T) { - serviceTest := setup() + serviceTest := setup(t) err := serviceTest.service.ProvisionDashboards(context.Background()) assert.Nil(t, err) serviceTest.startService() @@ -83,7 +83,7 @@ type serviceTestStruct struct { service *ProvisioningServiceImpl } -func setup() *serviceTestStruct { +func setup(t *testing.T) *serviceTestStruct { serviceTest := &serviceTestStruct{} serviceTest.waitTimeout = time.Second @@ -102,7 +102,8 @@ func setup() *serviceTestStruct { nil, nil, ) - serviceTest.service.Cfg = setting.NewCfg() + err := serviceTest.service.setDashboardProvisioner() + require.NoError(t, err) ctx, cancel := context.WithCancel(context.Background()) serviceTest.cancel = cancel