Files
grafana/public/app/features/provisioning/GettingStarted/GettingStarted.tsx
T
Roberto Jiménez SánchezandClaude Sonnet 4.5 5bda17be3f Provisioning: Update provisioning docs to reflect kubernetesDashboards defaults to true (#115159)
Docs: Update provisioning docs to reflect kubernetesDashboards defaults to true

The kubernetesDashboards feature toggle now defaults to true, so users
don't need to explicitly enable it in their configuration. Updated
documentation and UI to reflect this:

- Removed kubernetesDashboards from configuration examples
- Added notes explaining it's enabled by default
- Clarified that users only need to take action if they've explicitly
  disabled it
- Kept validation checks to catch explicit disables

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-11 17:08:57 +01:00

203 lines
7.1 KiB
TypeScript

import { css } from '@emotion/css';
import { skipToken } from '@reduxjs/toolkit/query';
import { useState } from 'react';
import { GrafanaTheme2 } from '@grafana/data';
import { Trans, t } from '@grafana/i18n';
import { config } from '@grafana/runtime';
import { Alert, Stack, useStyles2 } from '@grafana/ui';
import { Repository, useGetFrontendSettingsQuery } from 'app/api/clients/provisioning/v0alpha1';
import provisioningSvg from '../img/provisioning.svg';
import { EnhancedFeatures } from './EnhancedFeatures';
import { FeaturesList } from './FeaturesList';
import { SetupModal } from './SetupModal';
import { getConfigurationStatus } from './features';
type SetupType = 'public-access' | 'required-features' | null;
// Configuration examples
const featureIni = `# In your custom.ini file
[feature_toggles]
provisioning = true
`;
const ngrokExample = `ngrok http 3000
Help shape K8s Bindings https://ngrok.com/new-features-update?ref=k8s
Session Status online
Account Roberto Jiménez Sánchez (Plan: Free)
Version 3.18.4
Region Europe (eu)
Latency 44ms
Web Interface http://127.0.0.1:4040
Forwarding https://d60d-83-33-235-27.ngrok-free.app -> http://localhost:3000
Connections ttl opn rt1 rt5 p50 p90
50 2 0.00 0.00 83.03 90.56
HTTP Requests
-------------
09:18:46.147 CET GET /favicon.ico 302 Found
09:18:46.402 CET GET /login`;
const rootUrlExample = `[server]
root_url = https://d60d-83-33-235-27.ngrok-free.app`;
const getModalContent = (setupType: SetupType) => {
switch (setupType) {
case 'public-access':
return {
title: t('provisioning.getting-started.modal-title-set-up-public-access', 'Set up public access'),
description: t(
'provisioning.getting-started.modal-description-public-access',
'Set up public access to your Grafana instance to enable GitHub integration'
),
steps: [
{
title: t('provisioning.getting-started.step-title-start-ngrok', 'Start ngrok for temporary public access'),
description: t(
'provisioning.getting-started.step-description-start-ngrok',
'Run this command to create a secure tunnel to your local Grafana:'
),
code: 'ngrok http 3000',
},
{
title: t('provisioning.getting-started.step-title-copy-url', 'Copy your public URL'),
description: t(
'provisioning.getting-started.step-description-copy-url',
'From the ngrok output, copy the https:// forwarding URL that looks like this:'
),
code: ngrokExample,
copyCode: false,
},
{
title: t(
'provisioning.getting-started.step-title-update-grafana-config',
'Update your Grafana configuration'
),
description: t(
'provisioning.getting-started.step-description-update-grafana-config',
'Add this to your custom.ini file, replacing the URL with your actual ngrok URL:'
),
code: rootUrlExample,
},
],
};
case 'required-features':
return {
title: t('provisioning.getting-started.modal-title-set-up-required-features', 'Set up required features'),
description: t(
'provisioning.getting-started.modal-description-required-features',
'Enable required Grafana features for provisioning'
),
steps: [
{
title: t(
'provisioning.getting-started.step-title-enable-feature-toggles',
'Enable Required Feature Toggles'
),
description: t(
'provisioning.getting-started.step-description-enable-feature-toggles',
'Add the provisioning feature toggle to your custom.ini file. Note: kubernetesDashboards is enabled by default, but if you have explicitly disabled it, you will need to enable it in your Grafana settings or remove the override from your configuration.'
),
code: featureIni,
},
],
};
default:
return {
title: '',
description: '',
steps: [],
};
}
};
interface Props {
items: Repository[];
}
export default function GettingStarted({ items }: Props) {
const styles = useStyles2(getStyles);
const settingsArg = config.featureToggles.provisioning ? undefined : skipToken;
const settingsQuery = useGetFrontendSettingsQuery(settingsArg, {
refetchOnMountOrArgChange: true,
});
const legacyStorage = settingsQuery.data?.legacyStorage;
const hasItems = Boolean(settingsQuery.data?.items?.length);
const { hasPublicAccess, hasImageRenderer, hasRequiredFeatures } = getConfigurationStatus();
const [showInstructionsModal, setShowModal] = useState(false);
const [setupType, setSetupType] = useState<SetupType>(null);
return (
<>
{legacyStorage && (
<Alert
severity="info"
title={t(
'provisioning.getting-started.title-setting-connection-could-cause-temporary-outage',
'Setting up this connection could cause a temporary outage'
)}
>
<Trans i18nKey="provisioning.getting-started.alert-temporary-outage">
When you connect your whole instance, dashboards will be unavailable while running the migration. We
recommend warning your users before starting the process.
</Trans>
</Alert>
)}
<Stack direction="column" gap={6} wrap="wrap">
<Stack gap={10} alignItems="center">
<div className={styles.imageContainer}>
{/* decorative img, use empty str to skip alt*/}
<img src={provisioningSvg} className={styles.image} alt="" />
</div>
<FeaturesList
hasRequiredFeatures={hasRequiredFeatures}
onSetupFeatures={() => {
setSetupType('required-features');
setShowModal(true);
}}
/>
</Stack>
{(!hasPublicAccess || !hasImageRenderer) && hasItems && (
<EnhancedFeatures
hasPublicAccess={hasPublicAccess}
hasImageRenderer={hasImageRenderer}
onSetupPublicAccess={() => {
setSetupType('public-access');
setShowModal(true);
}}
/>
)}
</Stack>
{showInstructionsModal && setupType && (
<SetupModal
{...getModalContent(setupType)}
isOpen={showInstructionsModal}
onDismiss={() => setShowModal(false)}
/>
)}
</>
);
}
function getStyles(theme: GrafanaTheme2) {
return {
imageContainer: css({
height: 350,
display: `flex`,
alignItems: `center`,
justifyContent: `center`,
}),
image: css({
borderRadius: theme.shape.radius.default,
width: '100%',
height: '100%',
}),
};
}