mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Plugins: Hide version information when plugin is managed (#88065)
* first pass * fixup * fix linter issues * fix API test * update naming * rework * update var name * empty check * prettier * fix test * fix lint
This commit is contained in:
parent
e2ee7f06eb
commit
1b3fa8c47f
@ -122,6 +122,7 @@ export class GrafanaBootConfig implements GrafanaConfig {
|
|||||||
pluginAdminEnabled = true;
|
pluginAdminEnabled = true;
|
||||||
pluginAdminExternalManageEnabled = false;
|
pluginAdminExternalManageEnabled = false;
|
||||||
pluginCatalogHiddenPlugins: string[] = [];
|
pluginCatalogHiddenPlugins: string[] = [];
|
||||||
|
pluginCatalogManagedPlugins: string[] = [];
|
||||||
pluginsCDNBaseURL = '';
|
pluginsCDNBaseURL = '';
|
||||||
expressionsEnabled = false;
|
expressionsEnabled = false;
|
||||||
customTheme?: undefined;
|
customTheme?: undefined;
|
||||||
|
@ -227,6 +227,7 @@ type FrontendSettingsDTO struct {
|
|||||||
PluginAdminEnabled bool `json:"pluginAdminEnabled"`
|
PluginAdminEnabled bool `json:"pluginAdminEnabled"`
|
||||||
PluginAdminExternalManageEnabled bool `json:"pluginAdminExternalManageEnabled"`
|
PluginAdminExternalManageEnabled bool `json:"pluginAdminExternalManageEnabled"`
|
||||||
PluginCatalogHiddenPlugins []string `json:"pluginCatalogHiddenPlugins"`
|
PluginCatalogHiddenPlugins []string `json:"pluginCatalogHiddenPlugins"`
|
||||||
|
PluginCatalogManagedPlugins []string `json:"pluginCatalogManagedPlugins"`
|
||||||
ExpressionsEnabled bool `json:"expressionsEnabled"`
|
ExpressionsEnabled bool `json:"expressionsEnabled"`
|
||||||
AwsAllowedAuthProviders []string `json:"awsAllowedAuthProviders"`
|
AwsAllowedAuthProviders []string `json:"awsAllowedAuthProviders"`
|
||||||
AwsAssumeRoleEnabled bool `json:"awsAssumeRoleEnabled"`
|
AwsAssumeRoleEnabled bool `json:"awsAssumeRoleEnabled"`
|
||||||
|
@ -266,6 +266,7 @@ func (hs *HTTPServer) getFrontendSettings(c *contextmodel.ReqContext) (*dtos.Fro
|
|||||||
PluginAdminEnabled: hs.Cfg.PluginAdminEnabled,
|
PluginAdminEnabled: hs.Cfg.PluginAdminEnabled,
|
||||||
PluginAdminExternalManageEnabled: hs.Cfg.PluginAdminEnabled && hs.Cfg.PluginAdminExternalManageEnabled,
|
PluginAdminExternalManageEnabled: hs.Cfg.PluginAdminEnabled && hs.Cfg.PluginAdminExternalManageEnabled,
|
||||||
PluginCatalogHiddenPlugins: hs.Cfg.PluginCatalogHiddenPlugins,
|
PluginCatalogHiddenPlugins: hs.Cfg.PluginCatalogHiddenPlugins,
|
||||||
|
PluginCatalogManagedPlugins: hs.managedPluginsService.ManagedPlugins(c.Req.Context()),
|
||||||
ExpressionsEnabled: hs.Cfg.ExpressionsEnabled,
|
ExpressionsEnabled: hs.Cfg.ExpressionsEnabled,
|
||||||
AwsAllowedAuthProviders: hs.Cfg.AWSAllowedAuthProviders,
|
AwsAllowedAuthProviders: hs.Cfg.AWSAllowedAuthProviders,
|
||||||
AwsAssumeRoleEnabled: hs.Cfg.AWSAssumeRoleEnabled,
|
AwsAssumeRoleEnabled: hs.Cfg.AWSAssumeRoleEnabled,
|
||||||
|
@ -23,6 +23,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/authn/authntest"
|
"github.com/grafana/grafana/pkg/services/authn/authntest"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
"github.com/grafana/grafana/pkg/services/licensing"
|
"github.com/grafana/grafana/pkg/services/licensing"
|
||||||
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/managedplugins"
|
||||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
||||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||||
"github.com/grafana/grafana/pkg/services/rendering"
|
"github.com/grafana/grafana/pkg/services/rendering"
|
||||||
@ -79,6 +80,7 @@ func setupTestEnvironment(t *testing.T, cfg *setting.Cfg, features featuremgmt.F
|
|||||||
}),
|
}),
|
||||||
namespacer: request.GetNamespaceMapper(cfg),
|
namespacer: request.GetNamespaceMapper(cfg),
|
||||||
SocialService: socialimpl.ProvideService(cfg, features, &usagestats.UsageStatsMock{}, supportbundlestest.NewFakeBundleService(), remotecache.NewFakeCacheStorage(), nil, &ssosettingstests.MockService{}),
|
SocialService: socialimpl.ProvideService(cfg, features, &usagestats.UsageStatsMock{}, supportbundlestest.NewFakeBundleService(), remotecache.NewFakeCacheStorage(), nil, &ssosettingstests.MockService{}),
|
||||||
|
managedPluginsService: managedplugins.NewNoop(),
|
||||||
}
|
}
|
||||||
|
|
||||||
m := web.New()
|
m := web.New()
|
||||||
|
@ -25,10 +25,6 @@ import (
|
|||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/services/anonymous"
|
|
||||||
grafanaapiserver "github.com/grafana/grafana/pkg/services/apiserver"
|
|
||||||
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/api/avatar"
|
"github.com/grafana/grafana/pkg/api/avatar"
|
||||||
"github.com/grafana/grafana/pkg/api/routing"
|
"github.com/grafana/grafana/pkg/api/routing"
|
||||||
httpstatic "github.com/grafana/grafana/pkg/api/static"
|
httpstatic "github.com/grafana/grafana/pkg/api/static"
|
||||||
@ -48,7 +44,10 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/plugins/pluginscdn"
|
"github.com/grafana/grafana/pkg/plugins/pluginscdn"
|
||||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||||
"github.com/grafana/grafana/pkg/services/annotations"
|
"github.com/grafana/grafana/pkg/services/annotations"
|
||||||
|
"github.com/grafana/grafana/pkg/services/anonymous"
|
||||||
"github.com/grafana/grafana/pkg/services/apikey"
|
"github.com/grafana/grafana/pkg/services/apikey"
|
||||||
|
grafanaapiserver "github.com/grafana/grafana/pkg/services/apiserver"
|
||||||
|
"github.com/grafana/grafana/pkg/services/apiserver/endpoints/request"
|
||||||
"github.com/grafana/grafana/pkg/services/auth"
|
"github.com/grafana/grafana/pkg/services/auth"
|
||||||
"github.com/grafana/grafana/pkg/services/authn"
|
"github.com/grafana/grafana/pkg/services/authn"
|
||||||
"github.com/grafana/grafana/pkg/services/cleanup"
|
"github.com/grafana/grafana/pkg/services/cleanup"
|
||||||
@ -78,6 +77,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/org"
|
"github.com/grafana/grafana/pkg/services/org"
|
||||||
"github.com/grafana/grafana/pkg/services/playlist"
|
"github.com/grafana/grafana/pkg/services/playlist"
|
||||||
"github.com/grafana/grafana/pkg/services/plugindashboards"
|
"github.com/grafana/grafana/pkg/services/plugindashboards"
|
||||||
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/managedplugins"
|
||||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext"
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext"
|
||||||
pluginSettings "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
pluginSettings "github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
||||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginstore"
|
||||||
@ -195,6 +195,7 @@ type HTTPServer struct {
|
|||||||
apiKeyService apikey.Service
|
apiKeyService apikey.Service
|
||||||
kvStore kvstore.KVStore
|
kvStore kvstore.KVStore
|
||||||
pluginsCDNService *pluginscdn.Service
|
pluginsCDNService *pluginscdn.Service
|
||||||
|
managedPluginsService managedplugins.Manager
|
||||||
|
|
||||||
userService user.Service
|
userService user.Service
|
||||||
tempUserService tempUser.Service
|
tempUserService tempUser.Service
|
||||||
@ -254,7 +255,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
|
|||||||
avatarCacheServer *avatar.AvatarCacheServer, preferenceService pref.Service,
|
avatarCacheServer *avatar.AvatarCacheServer, preferenceService pref.Service,
|
||||||
folderPermissionsService accesscontrol.FolderPermissionsService,
|
folderPermissionsService accesscontrol.FolderPermissionsService,
|
||||||
dashboardPermissionsService accesscontrol.DashboardPermissionsService, dashboardVersionService dashver.Service,
|
dashboardPermissionsService accesscontrol.DashboardPermissionsService, dashboardVersionService dashver.Service,
|
||||||
starService star.Service, csrfService csrf.Service,
|
starService star.Service, csrfService csrf.Service, managedPlugins managedplugins.Manager,
|
||||||
playlistService playlist.Service, apiKeyService apikey.Service, kvStore kvstore.KVStore,
|
playlistService playlist.Service, apiKeyService apikey.Service, kvStore kvstore.KVStore,
|
||||||
secretsMigrator secrets.Migrator, secretsPluginManager plugins.SecretsPluginManager, secretsService secrets.Service,
|
secretsMigrator secrets.Migrator, secretsPluginManager plugins.SecretsPluginManager, secretsService secrets.Service,
|
||||||
secretsPluginMigrator spm.SecretMigrationProvider, secretsStore secretsKV.SecretsKVStore,
|
secretsPluginMigrator spm.SecretMigrationProvider, secretsStore secretsKV.SecretsKVStore,
|
||||||
@ -359,6 +360,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi
|
|||||||
statsService: statsService,
|
statsService: statsService,
|
||||||
authnService: authnService,
|
authnService: authnService,
|
||||||
pluginsCDNService: pluginsCDNService,
|
pluginsCDNService: pluginsCDNService,
|
||||||
|
managedPluginsService: managedPlugins,
|
||||||
starApi: starApi,
|
starApi: starApi,
|
||||||
promRegister: promRegister,
|
promRegister: promRegister,
|
||||||
promGatherer: promGatherer,
|
promGatherer: promGatherer,
|
||||||
|
@ -12,12 +12,12 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
||||||
"github.com/prometheus/client_golang/prometheus"
|
"github.com/prometheus/client_golang/prometheus"
|
||||||
dto "github.com/prometheus/client_model/go"
|
dto "github.com/prometheus/client_model/go"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
"github.com/grafana/grafana-plugin-sdk-go/backend"
|
|
||||||
"github.com/grafana/grafana/pkg/api/dtos"
|
"github.com/grafana/grafana/pkg/api/dtos"
|
||||||
"github.com/grafana/grafana/pkg/infra/log"
|
"github.com/grafana/grafana/pkg/infra/log"
|
||||||
"github.com/grafana/grafana/pkg/infra/log/logtest"
|
"github.com/grafana/grafana/pkg/infra/log/logtest"
|
||||||
@ -39,6 +39,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||||
"github.com/grafana/grafana/pkg/services/org"
|
"github.com/grafana/grafana/pkg/services/org"
|
||||||
"github.com/grafana/grafana/pkg/services/org/orgtest"
|
"github.com/grafana/grafana/pkg/services/org/orgtest"
|
||||||
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/managedplugins"
|
||||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol"
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginaccesscontrol"
|
||||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs"
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginerrs"
|
||||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
|
||||||
@ -99,6 +100,7 @@ func Test_PluginsInstallAndUninstall(t *testing.T) {
|
|||||||
ID: pluginID,
|
ID: pluginID,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
hs.managedPluginsService = managedplugins.NewNoop()
|
||||||
|
|
||||||
expectedIdentity := &authn.Identity{
|
expectedIdentity := &authn.Identity{
|
||||||
OrgID: tc.permissionOrg,
|
OrgID: tc.permissionOrg,
|
||||||
@ -641,6 +643,7 @@ func Test_PluginsList_AccessControl(t *testing.T) {
|
|||||||
hs.PluginSettings = &pluginSettings
|
hs.PluginSettings = &pluginSettings
|
||||||
hs.pluginStore = pluginstore.New(pluginRegistry, &fakes.FakeLoader{})
|
hs.pluginStore = pluginstore.New(pluginRegistry, &fakes.FakeLoader{})
|
||||||
hs.pluginFileStore = filestore.ProvideService(pluginRegistry)
|
hs.pluginFileStore = filestore.ProvideService(pluginRegistry)
|
||||||
|
hs.managedPluginsService = managedplugins.NewNoop()
|
||||||
var err error
|
var err error
|
||||||
hs.pluginsUpdateChecker, err = updatechecker.ProvidePluginsService(hs.Cfg, nil, tracing.InitializeTracerForTest())
|
hs.pluginsUpdateChecker, err = updatechecker.ProvidePluginsService(hs.Cfg, nil, tracing.InitializeTracerForTest())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
19
pkg/services/pluginsintegration/managedplugins/managed.go
Normal file
19
pkg/services/pluginsintegration/managedplugins/managed.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
package managedplugins
|
||||||
|
|
||||||
|
import "context"
|
||||||
|
|
||||||
|
type Manager interface {
|
||||||
|
ManagedPlugins(ctx context.Context) []string
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ Manager = (*Noop)(nil)
|
||||||
|
|
||||||
|
type Noop struct{}
|
||||||
|
|
||||||
|
func NewNoop() *Noop {
|
||||||
|
return &Noop{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Noop) ManagedPlugins(_ context.Context) []string {
|
||||||
|
return []string{}
|
||||||
|
}
|
@ -41,6 +41,7 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/keystore"
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/keystore"
|
||||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/licensing"
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/licensing"
|
||||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/loader"
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/loader"
|
||||||
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/managedplugins"
|
||||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pipeline"
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/pipeline"
|
||||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginconfig"
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginconfig"
|
||||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext"
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/plugincontext"
|
||||||
@ -132,10 +133,12 @@ var WireExtensionSet = wire.NewSet(
|
|||||||
wire.Bind(new(plugins.BackendFactoryProvider), new(*provider.Service)),
|
wire.Bind(new(plugins.BackendFactoryProvider), new(*provider.Service)),
|
||||||
signature.ProvideOSSAuthorizer,
|
signature.ProvideOSSAuthorizer,
|
||||||
wire.Bind(new(plugins.PluginLoaderAuthorizer), new(*signature.UnsignedPluginAuthorizer)),
|
wire.Bind(new(plugins.PluginLoaderAuthorizer), new(*signature.UnsignedPluginAuthorizer)),
|
||||||
wire.Bind(new(finder.Finder), new(*finder.Local)),
|
|
||||||
finder.ProvideLocalFinder,
|
finder.ProvideLocalFinder,
|
||||||
|
wire.Bind(new(finder.Finder), new(*finder.Local)),
|
||||||
ProvideClientDecorator,
|
ProvideClientDecorator,
|
||||||
wire.Bind(new(plugins.Client), new(*client.Decorator)),
|
wire.Bind(new(plugins.Client), new(*client.Decorator)),
|
||||||
|
managedplugins.NewNoop,
|
||||||
|
wire.Bind(new(managedplugins.Manager), new(*managedplugins.Noop)),
|
||||||
)
|
)
|
||||||
|
|
||||||
func ProvideClientDecorator(
|
func ProvideClientDecorator(
|
||||||
|
@ -74,7 +74,6 @@ func ToGrafanaDTO(p *plugins.Plugin) Plugin {
|
|||||||
Module: p.Module,
|
Module: p.Module,
|
||||||
BaseURL: p.BaseURL,
|
BaseURL: p.BaseURL,
|
||||||
ExternalService: p.ExternalService,
|
ExternalService: p.ExternalService,
|
||||||
|
|
||||||
Angular: p.Angular,
|
Angular: p.Angular,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@ export default {
|
|||||||
isDisabled: false,
|
isDisabled: false,
|
||||||
isDeprecated: false,
|
isDeprecated: false,
|
||||||
isPublished: true,
|
isPublished: true,
|
||||||
|
isManaged: false,
|
||||||
name: 'Zabbix',
|
name: 'Zabbix',
|
||||||
orgName: 'Alexander Zobnin',
|
orgName: 'Alexander Zobnin',
|
||||||
popularity: 0.2093,
|
popularity: 0.2093,
|
||||||
|
@ -32,6 +32,7 @@ const plugin: CatalogPlugin = {
|
|||||||
isDisabled: false,
|
isDisabled: false,
|
||||||
isDeprecated: false,
|
isDeprecated: false,
|
||||||
isPublished: true,
|
isPublished: true,
|
||||||
|
isManaged: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('GetStartedWithDataSource', () => {
|
describe('GetStartedWithDataSource', () => {
|
||||||
|
@ -32,6 +32,7 @@ const plugin: CatalogPlugin = {
|
|||||||
isDisabled: false,
|
isDisabled: false,
|
||||||
isDeprecated: false,
|
isDeprecated: false,
|
||||||
isPublished: true,
|
isPublished: true,
|
||||||
|
isManaged: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
function setup(opts: { angularSupportEnabled: boolean; angularDetected: boolean }) {
|
function setup(opts: { angularSupportEnabled: boolean; angularDetected: boolean }) {
|
||||||
@ -242,4 +243,15 @@ describe('InstallControlsButton', () => {
|
|||||||
expect(button).toBeEnabled();
|
expect(button).toBeEnabled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('update button', () => {
|
||||||
|
it('should be hidden when plugin is managed', () => {
|
||||||
|
render(
|
||||||
|
<TestProvider>
|
||||||
|
<InstallControlsButton plugin={{ ...plugin, isManaged: true }} pluginStatus={PluginStatus.UPDATE} />
|
||||||
|
</TestProvider>
|
||||||
|
);
|
||||||
|
expect(screen.queryByText('Update')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -152,9 +152,11 @@ export function InstallControlsButton({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack alignItems="flex-start" width="auto" height="auto">
|
<Stack alignItems="flex-start" width="auto" height="auto">
|
||||||
|
{!plugin.isManaged && (
|
||||||
<Button disabled={disableUpdate} onClick={onUpdate}>
|
<Button disabled={disableUpdate} onClick={onUpdate}>
|
||||||
{isInstalling ? 'Updating' : 'Update'}
|
{isInstalling ? 'Updating' : 'Update'}
|
||||||
</Button>
|
</Button>
|
||||||
|
)}
|
||||||
<Button variant="destructive" disabled={isUninstalling} onClick={onUninstall}>
|
<Button variant="destructive" disabled={isUninstalling} onClick={onUninstall}>
|
||||||
{uninstallBtnText}
|
{uninstallBtnText}
|
||||||
</Button>
|
</Button>
|
||||||
|
@ -47,6 +47,7 @@ const getMockPlugin = (id: string): CatalogPlugin => {
|
|||||||
isDisabled: false,
|
isDisabled: false,
|
||||||
isDeprecated: false,
|
isDeprecated: false,
|
||||||
isPublished: true,
|
isPublished: true,
|
||||||
|
isManaged: false,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -57,6 +57,7 @@ describe('PluginListItem', () => {
|
|||||||
isDisabled: false,
|
isDisabled: false,
|
||||||
isDeprecated: false,
|
isDeprecated: false,
|
||||||
isPublished: true,
|
isPublished: true,
|
||||||
|
isManaged: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
/** As Grid */
|
/** As Grid */
|
||||||
|
@ -33,6 +33,7 @@ describe('PluginListItemBadges', () => {
|
|||||||
isDisabled: false,
|
isDisabled: false,
|
||||||
isDeprecated: false,
|
isDeprecated: false,
|
||||||
isPublished: true,
|
isPublished: true,
|
||||||
|
isManaged: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
@ -76,6 +77,13 @@ describe('PluginListItemBadges', () => {
|
|||||||
expect(screen.getByText(/update available/i)).toBeVisible();
|
expect(screen.getByText(/update available/i)).toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not render an upgrade badge (when plugin has an available update and is managed)', () => {
|
||||||
|
render(
|
||||||
|
<PluginListItemBadges plugin={{ ...plugin, hasUpdate: true, installedVersion: '0.0.9', isManaged: true }} />
|
||||||
|
);
|
||||||
|
expect(screen.queryByText(/update available/i)).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
it('renders an angular badge (when plugin is angular)', () => {
|
it('renders an angular badge (when plugin is angular)', () => {
|
||||||
render(<PluginListItemBadges plugin={{ ...plugin, angularDetected: true }} />);
|
render(<PluginListItemBadges plugin={{ ...plugin, angularDetected: true }} />);
|
||||||
expect(screen.getByText(/angular/i)).toBeVisible();
|
expect(screen.getByText(/angular/i)).toBeVisible();
|
||||||
|
@ -24,7 +24,7 @@ export function PluginListItemBadges({ plugin }: PluginBadgeType) {
|
|||||||
<Stack height="auto" wrap="wrap">
|
<Stack height="auto" wrap="wrap">
|
||||||
<PluginEnterpriseBadge plugin={plugin} />
|
<PluginEnterpriseBadge plugin={plugin} />
|
||||||
{plugin.isDisabled && <PluginDisabledBadge error={plugin.error} />}
|
{plugin.isDisabled && <PluginDisabledBadge error={plugin.error} />}
|
||||||
{hasUpdate && <PluginUpdateAvailableBadge plugin={plugin} />}
|
{hasUpdate && !plugin.isManaged && <PluginUpdateAvailableBadge plugin={plugin} />}
|
||||||
{plugin.angularDetected && <PluginAngularBadge />}
|
{plugin.angularDetected && <PluginAngularBadge />}
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
@ -36,7 +36,7 @@ export function PluginListItemBadges({ plugin }: PluginBadgeType) {
|
|||||||
{plugin.isDisabled && <PluginDisabledBadge error={plugin.error} />}
|
{plugin.isDisabled && <PluginDisabledBadge error={plugin.error} />}
|
||||||
{plugin.isDeprecated && <PluginDeprecatedBadge />}
|
{plugin.isDeprecated && <PluginDeprecatedBadge />}
|
||||||
{plugin.isInstalled && <PluginInstalledBadge />}
|
{plugin.isInstalled && <PluginInstalledBadge />}
|
||||||
{hasUpdate && <PluginUpdateAvailableBadge plugin={plugin} />}
|
{hasUpdate && !plugin.isManaged && <PluginUpdateAvailableBadge plugin={plugin} />}
|
||||||
{plugin.angularDetected && <PluginAngularBadge />}
|
{plugin.angularDetected && <PluginAngularBadge />}
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
@ -203,6 +203,7 @@ describe('Plugins/Helpers', () => {
|
|||||||
isInstalled: false,
|
isInstalled: false,
|
||||||
isDeprecated: false,
|
isDeprecated: false,
|
||||||
isPublished: true,
|
isPublished: true,
|
||||||
|
isManaged: false,
|
||||||
name: 'Zabbix',
|
name: 'Zabbix',
|
||||||
orgName: 'Alexander Zobnin',
|
orgName: 'Alexander Zobnin',
|
||||||
popularity: 0.2111,
|
popularity: 0.2111,
|
||||||
@ -280,6 +281,7 @@ describe('Plugins/Helpers', () => {
|
|||||||
isInstalled: true,
|
isInstalled: true,
|
||||||
isPublished: false,
|
isPublished: false,
|
||||||
isDeprecated: false,
|
isDeprecated: false,
|
||||||
|
isManaged: false,
|
||||||
name: 'Zabbix',
|
name: 'Zabbix',
|
||||||
orgName: 'Alexander Zobnin',
|
orgName: 'Alexander Zobnin',
|
||||||
popularity: 0,
|
popularity: 0,
|
||||||
@ -332,6 +334,7 @@ describe('Plugins/Helpers', () => {
|
|||||||
isInstalled: true,
|
isInstalled: true,
|
||||||
isPublished: true,
|
isPublished: true,
|
||||||
isDeprecated: false,
|
isDeprecated: false,
|
||||||
|
isManaged: false,
|
||||||
name: 'Zabbix',
|
name: 'Zabbix',
|
||||||
orgName: 'Alexander Zobnin',
|
orgName: 'Alexander Zobnin',
|
||||||
popularity: 0.2111,
|
popularity: 0.2111,
|
||||||
|
@ -142,6 +142,7 @@ export function mapRemoteToCatalog(plugin: RemotePlugin, error?: PluginError): C
|
|||||||
isPublished: true,
|
isPublished: true,
|
||||||
isInstalled: isDisabled,
|
isInstalled: isDisabled,
|
||||||
isDisabled: isDisabled,
|
isDisabled: isDisabled,
|
||||||
|
isManaged: isManagedPlugin(id),
|
||||||
isDeprecated: status === RemotePluginStatus.Deprecated,
|
isDeprecated: status === RemotePluginStatus.Deprecated,
|
||||||
isCore: plugin.internal,
|
isCore: plugin.internal,
|
||||||
isDev: false,
|
isDev: false,
|
||||||
@ -191,6 +192,7 @@ export function mapLocalToCatalog(plugin: LocalPlugin, error?: PluginError): Cat
|
|||||||
isDeprecated: false,
|
isDeprecated: false,
|
||||||
isDev: Boolean(dev),
|
isDev: Boolean(dev),
|
||||||
isEnterprise: false,
|
isEnterprise: false,
|
||||||
|
isManaged: isManagedPlugin(id),
|
||||||
type,
|
type,
|
||||||
error: error?.errorCode,
|
error: error?.errorCode,
|
||||||
accessControl: accessControl,
|
accessControl: accessControl,
|
||||||
@ -238,6 +240,7 @@ export function mapToCatalogPlugin(local?: LocalPlugin, remote?: RemotePlugin, e
|
|||||||
isDisabled: isDisabled,
|
isDisabled: isDisabled,
|
||||||
isDeprecated: remote?.status === RemotePluginStatus.Deprecated,
|
isDeprecated: remote?.status === RemotePluginStatus.Deprecated,
|
||||||
isPublished: true,
|
isPublished: true,
|
||||||
|
isManaged: isManagedPlugin(id),
|
||||||
// TODO<check if we would like to keep preferring the remote version>
|
// TODO<check if we would like to keep preferring the remote version>
|
||||||
name: remote?.name || local?.name || '',
|
name: remote?.name || local?.name || '',
|
||||||
// TODO<check if we would like to keep preferring the remote version>
|
// TODO<check if we would like to keep preferring the remote version>
|
||||||
@ -373,6 +376,12 @@ function isNotHiddenByConfig(id: string) {
|
|||||||
return !pluginCatalogHiddenPlugins.includes(id);
|
return !pluginCatalogHiddenPlugins.includes(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isManagedPlugin(id: string) {
|
||||||
|
const { pluginCatalogManagedPlugins }: { pluginCatalogManagedPlugins: string[] } = config;
|
||||||
|
|
||||||
|
return pluginCatalogManagedPlugins?.includes(id);
|
||||||
|
}
|
||||||
|
|
||||||
function isDisabledSecretsPlugin(type?: PluginType): boolean {
|
function isDisabledSecretsPlugin(type?: PluginType): boolean {
|
||||||
return type === PluginType.secretsmanager && !config.secretsManagerPluginEnabled;
|
return type === PluginType.secretsmanager && !config.secretsManagerPluginEnabled;
|
||||||
}
|
}
|
||||||
|
@ -25,11 +25,18 @@ export const usePluginInfo = (plugin?: CatalogPlugin): PageInfoItem[] => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (Boolean(version)) {
|
if (Boolean(version)) {
|
||||||
|
if (plugin.isManaged) {
|
||||||
|
info.push({
|
||||||
|
label: 'Version',
|
||||||
|
value: 'Managed by Grafana',
|
||||||
|
});
|
||||||
|
} else {
|
||||||
info.push({
|
info.push({
|
||||||
label: 'Version',
|
label: 'Version',
|
||||||
value: version,
|
value: version,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (Boolean(plugin.orgName)) {
|
if (Boolean(plugin.orgName)) {
|
||||||
info.push({
|
info.push({
|
||||||
|
@ -315,6 +315,17 @@ describe('Plugin details page', () => {
|
|||||||
expect(queryByRole('button', { name: /^install/i })).not.toBeInTheDocument();
|
expect(queryByRole('button', { name: /^install/i })).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not display an update button for a plugin that is managed', async () => {
|
||||||
|
const { queryByRole } = renderPluginDetails({ id, isInstalled: true, hasUpdate: true, isManaged: true });
|
||||||
|
|
||||||
|
// Does not display an "update" button
|
||||||
|
expect(await queryByRole('button', { name: /update/i })).not.toBeInTheDocument();
|
||||||
|
expect(queryByRole('button', { name: /uninstall/i })).toBeInTheDocument();
|
||||||
|
|
||||||
|
// Does not display "install" button
|
||||||
|
expect(queryByRole('button', { name: /^install/i })).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
it('should display an install button for enterprise plugins if license is valid', async () => {
|
it('should display an install button for enterprise plugins if license is valid', async () => {
|
||||||
config.licenseInfo.enabledFeatures = { 'enterprise.plugins': true };
|
config.licenseInfo.enabledFeatures = { 'enterprise.plugins': true };
|
||||||
|
|
||||||
|
@ -44,6 +44,7 @@ export interface CatalogPlugin extends WithAccessControlMetadata {
|
|||||||
isInstalled: boolean;
|
isInstalled: boolean;
|
||||||
isDisabled: boolean;
|
isDisabled: boolean;
|
||||||
isDeprecated: boolean;
|
isDeprecated: boolean;
|
||||||
|
isManaged: boolean; // Indicates that the plugin version is managed by Grafana
|
||||||
// `isPublished` is TRUE if the plugin is published to grafana.com
|
// `isPublished` is TRUE if the plugin is published to grafana.com
|
||||||
isPublished: boolean;
|
isPublished: boolean;
|
||||||
name: string;
|
name: string;
|
||||||
|
Loading…
Reference in New Issue
Block a user