Plugins: Enable catalog management link to gcom (#34673)

* click out to gcom when config enabled

* set to false

* fix styling for uninstall

* remove advertising config + simplify callout URL

* add entry to configuration.md

* update config name

* update lingo
This commit is contained in:
Will Browne 2021-05-27 12:45:06 +02:00 committed by GitHub
parent f76f426da3
commit c7b58fe186
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 67 additions and 29 deletions

View File

@ -885,6 +885,7 @@ app_tls_skip_verify_insecure = false
allow_loading_unsigned_plugins =
# Enable or disable installing plugins directly from within Grafana.
plugin_admin_enabled = false
plugin_admin_external_manage_enabled = false
plugin_catalog_url = https://grafana.com/grafana/plugins/
#################################### Grafana Image Renderer Plugin ##########################

View File

@ -871,6 +871,7 @@
;allow_loading_unsigned_plugins =
# Enable or disable installing plugins directly from within Grafana.
;plugin_admin_enabled = false
;plugin_admin_external_manage_enabled = false
;plugin_catalog_url = https://grafana.com/grafana/plugins/
#################################### Grafana Image Renderer Plugin ##########################

View File

@ -1473,11 +1473,13 @@ Enter a comma-separated list of plugin identifiers to identify plugins that are
### plugin_admin_enabled
Available to Grafana administrators only, the plugin admin app is set to `false` by default. Set it to `true` to enable the app.
For more information, refer to [Plugin catalog]({{< relref "../plugins/catalog.md" >}}).
### plugin_admin_external_manage_enabled
Set to `true` if you want to enable external management of plugins. Default is `false`. This is only applicable to Grafana Cloud users.
### plugin_catalog_url

View File

@ -76,6 +76,7 @@ export class GrafanaBootConfig implements GrafanaConfig {
};
pluginCatalogURL = 'https://grafana.com/grafana/plugins/';
pluginAdminEnabled = false;
pluginAdminExternalManageEnabled = false;
expressionsEnabled = false;
customTheme?: any;
awsAllowedAuthProviders: string[] = [];

View File

@ -242,15 +242,16 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i
"licenseUrl": hs.License.LicenseURL(c.SignedInUser),
"edition": hs.License.Edition(),
},
"featureToggles": hs.Cfg.FeatureToggles,
"rendererAvailable": hs.RenderService.IsAvailable(),
"http2Enabled": hs.Cfg.Protocol == setting.HTTP2Scheme,
"sentry": hs.Cfg.Sentry,
"pluginCatalogURL": hs.Cfg.PluginCatalogURL,
"pluginAdminEnabled": c.IsGrafanaAdmin && hs.Cfg.PluginAdminEnabled && hasPluginManagerApp,
"expressionsEnabled": hs.Cfg.ExpressionsEnabled,
"awsAllowedAuthProviders": hs.Cfg.AWSAllowedAuthProviders,
"awsAssumeRoleEnabled": hs.Cfg.AWSAssumeRoleEnabled,
"featureToggles": hs.Cfg.FeatureToggles,
"rendererAvailable": hs.RenderService.IsAvailable(),
"http2Enabled": hs.Cfg.Protocol == setting.HTTP2Scheme,
"sentry": hs.Cfg.Sentry,
"pluginCatalogURL": hs.Cfg.PluginCatalogURL,
"pluginAdminEnabled": c.IsGrafanaAdmin && hs.Cfg.PluginAdminEnabled && hasPluginManagerApp,
"pluginAdminExternalManageEnabled": hs.Cfg.PluginAdminExternalManageEnabled,
"expressionsEnabled": hs.Cfg.ExpressionsEnabled,
"awsAllowedAuthProviders": hs.Cfg.AWSAllowedAuthProviders,
"awsAssumeRoleEnabled": hs.Cfg.AWSAssumeRoleEnabled,
"azure": map[string]interface{}{
"cloud": hs.Cfg.Azure.Cloud,
"managedIdentityEnabled": hs.Cfg.Azure.ManagedIdentityEnabled,

View File

@ -253,15 +253,16 @@ type Cfg struct {
// CSPTemplate contains the Content Security Policy template.
CSPTemplate string
TempDataLifetime time.Duration
PluginsEnableAlpha bool
PluginsAppsSkipVerifyTLS bool
PluginSettings PluginSettings
PluginsAllowUnsigned []string
PluginCatalogURL string
PluginAdminEnabled bool
DisableSanitizeHtml bool
EnterpriseLicensePath string
TempDataLifetime time.Duration
PluginsEnableAlpha bool
PluginsAppsSkipVerifyTLS bool
PluginSettings PluginSettings
PluginsAllowUnsigned []string
PluginCatalogURL string
PluginAdminEnabled bool
PluginAdminExternalManageEnabled bool
DisableSanitizeHtml bool
EnterpriseLicensePath string
// Metrics
MetricsEndpointEnabled bool
@ -891,6 +892,7 @@ func (cfg *Cfg) Load(args *CommandLineArgs) error {
}
cfg.PluginCatalogURL = pluginsSection.Key("plugin_catalog_url").MustString("https://grafana.com/grafana/plugins/")
cfg.PluginAdminEnabled = pluginsSection.Key("plugin_admin_enabled").MustBool(false)
cfg.PluginAdminExternalManageEnabled = pluginsSection.Key("plugin_admin_external_manage_enabled").MustBool(false)
// Read and populate feature toggles list
featureTogglesSection := iniFile.Section("feature_toggles")

View File

@ -3,7 +3,7 @@ import { css } from '@emotion/css';
import { gt, satisfies } from 'semver';
import { config } from '@grafana/runtime';
import { Button, HorizontalGroup, Icon, useStyles2 } from '@grafana/ui';
import { Button, HorizontalGroup, Icon, LinkButton, useStyles2 } from '@grafana/ui';
import { AppEvents, GrafanaTheme2, OrgRole } from '@grafana/data';
import { Metadata, Plugin } from '../types';
@ -25,6 +25,8 @@ export const InstallControls = ({ localPlugin, remotePlugin }: Props) => {
const [shouldUpdate, setShouldUpdate] = useState(
remotePlugin?.version && localPlugin?.info.version && gt(remotePlugin?.version!, localPlugin?.info.version!)
);
const isExternallyManaged = config.pluginAdminExternalManageEnabled;
const externalManageLink = getExternalManageLink(remotePlugin);
const styles = useStyles2(getStyles);
@ -93,14 +95,32 @@ export const InstallControls = ({ localPlugin, remotePlugin }: Props) => {
if (isInstalled) {
return (
<HorizontalGroup height="auto">
{shouldUpdate && (
<Button disabled={loading || !hasPermission} onClick={onUpdate}>
{loading ? 'Updating' : 'Update'}
{shouldUpdate &&
(isExternallyManaged ? (
<LinkButton disabled={!hasPermission} href={externalManageLink} target="_blank" rel="noopener noreferrer">
{'Update via grafana.com'}
</LinkButton>
) : (
<Button disabled={loading || !hasPermission} onClick={onUpdate}>
{loading ? 'Updating' : 'Update'}
</Button>
))}
{isExternallyManaged ? (
<LinkButton
variant="destructive"
disabled={!hasPermission}
href={externalManageLink}
target="_blank"
rel="noopener noreferrer"
>
{'Uninstall via grafana.com'}
</LinkButton>
) : (
<Button variant="destructive" disabled={loading || !hasPermission} onClick={onUninstall}>
{loading && !shouldUpdate ? 'Uninstalling' : 'Uninstall'}
</Button>
)}
<Button variant="destructive" disabled={loading || !hasPermission} onClick={onUninstall}>
{loading && !shouldUpdate ? 'Uninstalling' : 'Uninstall'}
</Button>
{!hasPermission && <div className={styles.message}>You need admin privileges to manage this plugin.</div>}
</HorizontalGroup>
);
@ -117,14 +137,24 @@ export const InstallControls = ({ localPlugin, remotePlugin }: Props) => {
return (
<HorizontalGroup height="auto">
<Button disabled={loading || !hasPermission} onClick={onInstall}>
{loading ? 'Installing' : 'Install'}
</Button>
{isExternallyManaged ? (
<LinkButton disabled={!hasPermission} href={externalManageLink} target="_blank" rel="noopener noreferrer">
{'Install via grafana.com'}
</LinkButton>
) : (
<Button disabled={loading || !hasPermission} onClick={onInstall}>
{loading ? 'Installing' : 'Install'}
</Button>
)}
{!hasPermission && <div className={styles.message}>You need admin privileges to install this plugin.</div>}
</HorizontalGroup>
);
};
function getExternalManageLink(plugin: Plugin): string {
return `https://grafana.com/grafana/plugins/${plugin.slug}`;
}
export const getStyles = (theme: GrafanaTheme2) => {
return {
message: css`