mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 09:25:06 +03:00
Disable disk management for HA projects (#49633)
## Context As per PR title, disables disk management for HA projects, which involves - Disabling "Increase disk size" CTAs in reports/database and the old disk config settings in database/settings - Disabling all input fields related to disk management in settings/infrastructure <img width="1076" height="857" alt="image" src="https://github.com/user-attachments/assets/bfbdfc36-8ae3-41ce-af12-c05b46e620f4" /> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added High Availability notices and restrictions throughout disk management settings. * Disabled disk size, IOPS, throughput, and autoscaling controls where High Availability limits changes. * Added explanatory tooltips for restricted disk-size actions. * Updated database observability controls to reflect High Availability restrictions. * **Accessibility** * Added an accessible label to the database observability refresh button. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
1 parent
df002b4018
commit
102d3d1df5
11 files changed
+85
-62
No files matched your search
@@ -150,6 +150,9 @@ export function DiskSection({
|
||||
<DocsButton href={`${DOCS_URL}/guides/platform/database-size`} />
|
||||
</PageSectionAside>
|
||||
</PageSectionMeta>
|
||||
|
||||
<HighAvailabilityDisabledSectionNotice title="Disk management is unavailable for High Availability projects" />
|
||||
|
||||
<PageSectionContent ref={settingsRef} className="flex flex-col gap-4 scroll-mt-24">
|
||||
{isAws && <DiskSpaceBar form={form} />}
|
||||
|
||||
@@ -255,7 +258,7 @@ export function AdvancedSection({
|
||||
<PageSectionContent className="flex flex-col gap-4">
|
||||
<Card ref={autoscaleSettingsRef} className="scroll-mt-24">
|
||||
<CardContent className="flex flex-col gap-y-8">
|
||||
<AutoScaleFields form={form} />
|
||||
<AutoScaleFields form={form} disableInput={disableDiskInputs && disableDiskSizeInput} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
|
||||
@@ -55,12 +55,12 @@ import { AddonVariantId } from '@/data/subscriptions/types'
|
||||
import { useResourceWarningsQuery } from '@/data/usage/resource-warnings-query'
|
||||
import { useCheckEntitlements } from '@/hooks/misc/useCheckEntitlements'
|
||||
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
||||
import { useHighAvailability } from '@/hooks/misc/useHighAvailability'
|
||||
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
|
||||
import {
|
||||
useIsAwsCloudProvider,
|
||||
useIsAwsK8sCloudProvider,
|
||||
useIsAwsNimbusCloudProvider,
|
||||
useIsHighAvailability,
|
||||
useSelectedProjectQuery,
|
||||
} from '@/hooks/misc/useSelectedProject'
|
||||
import { GB, PROJECT_STATUS } from '@/lib/constants'
|
||||
@@ -102,7 +102,7 @@ export function DiskManagementForm({
|
||||
const isAws = useIsAwsCloudProvider()
|
||||
const isAwsK8s = useIsAwsK8sCloudProvider()
|
||||
const isAwsNimbus = useIsAwsNimbusCloudProvider()
|
||||
const { isHighAvailability } = useHighAvailability()
|
||||
const isHighAvailability = useIsHighAvailability()
|
||||
|
||||
const { can: canUpdateDiskConfiguration, isSuccess: isPermissionsLoaded } =
|
||||
useAsyncCheckPermissions(PermissionAction.UPDATE, 'projects', {
|
||||
@@ -209,9 +209,10 @@ export function DiskManagementForm({
|
||||
const usedPercentage = (usedSize / totalSize) * 100
|
||||
|
||||
const disableIopsThroughputConfig =
|
||||
modifiedComputeSize &&
|
||||
!isSpendCapEnabled &&
|
||||
RESTRICTED_COMPUTE_FOR_THROUGHPUT_ON_GP3.includes(modifiedComputeSize)
|
||||
isHighAvailability ||
|
||||
(modifiedComputeSize &&
|
||||
!isSpendCapEnabled &&
|
||||
RESTRICTED_COMPUTE_FOR_THROUGHPUT_ON_GP3.includes(modifiedComputeSize))
|
||||
|
||||
const watchedTotalSize = useWatch({ control: form.control, name: 'totalSize' }) ?? 0
|
||||
const watchedStorageType = useWatch({ control: form.control, name: 'storageType' })
|
||||
@@ -231,10 +232,11 @@ export function DiskManagementForm({
|
||||
isRequestingChanges ||
|
||||
isPlanUpgradeRequired ||
|
||||
isWithinCooldownWindow ||
|
||||
isHighAvailability ||
|
||||
!canUpdateDiskConfiguration ||
|
||||
!isAws
|
||||
|
||||
const disableDiskInputs = disableDiskSizeInput || isSpendCapEnabled
|
||||
const disableDiskInputs = disableDiskSizeInput || isSpendCapEnabled || isHighAvailability
|
||||
|
||||
// Compute resizing is not supported for High Availability projects during Alpha
|
||||
const disableComputeInputs = isPlanUpgradeRequired || isHighAvailability
|
||||
|
||||
@@ -17,9 +17,10 @@ import { useDiskAutoscaleCustomConfigQuery } from '@/data/config/disk-autoscale-
|
||||
|
||||
type AutoScaleFieldProps = {
|
||||
form: UseFormReturn<DiskStorageSchemaType>
|
||||
disableInput?: boolean
|
||||
}
|
||||
|
||||
export const AutoScaleFields = ({ form }: AutoScaleFieldProps) => {
|
||||
export const AutoScaleFields = ({ form, disableInput = false }: AutoScaleFieldProps) => {
|
||||
const { ref: projectRef } = useParams()
|
||||
const {
|
||||
control,
|
||||
@@ -76,7 +77,7 @@ export const AutoScaleFields = ({ form }: AutoScaleFieldProps) => {
|
||||
id={field.name}
|
||||
type="number"
|
||||
value={field.value ?? undefined}
|
||||
disabled={isError}
|
||||
disabled={disableInput || isError}
|
||||
onChange={(e) => {
|
||||
setValue(
|
||||
'growthPercent',
|
||||
@@ -123,7 +124,7 @@ export const AutoScaleFields = ({ form }: AutoScaleFieldProps) => {
|
||||
id={field.name}
|
||||
type="number"
|
||||
value={field.value ?? undefined}
|
||||
disabled={isError}
|
||||
disabled={disableInput || isError}
|
||||
onChange={(e) => {
|
||||
setValue(
|
||||
'minIncrementGb',
|
||||
@@ -165,7 +166,7 @@ export const AutoScaleFields = ({ form }: AutoScaleFieldProps) => {
|
||||
id={field.name}
|
||||
type="number"
|
||||
value={field.value ?? undefined}
|
||||
disabled={isError}
|
||||
disabled={disableInput || isError}
|
||||
onChange={(e) => {
|
||||
setValue('maxSizeGb', e.target.value === '' ? null : e.target.valueAsNumber, {
|
||||
shouldDirty: true,
|
||||
|
||||
+1
@@ -40,6 +40,7 @@ vi.mock('@/hooks/misc/useSelectedProject', () => ({
|
||||
data: { ref: 'default', connectionString: 'postgres://localhost' },
|
||||
}),
|
||||
useIsOrioleDb: () => false,
|
||||
useIsHighAvailability: () => false,
|
||||
}))
|
||||
|
||||
vi.mock('common', async (importOriginal) => {
|
||||
|
||||
+1
@@ -15,6 +15,7 @@ vi.mock('@/hooks/misc/useSelectedProject', () => ({
|
||||
useSelectedProjectQuery: () => ({
|
||||
data: { ref: 'default', connectionString: 'postgres://localhost' },
|
||||
}),
|
||||
useIsHighAvailability: () => false,
|
||||
}))
|
||||
|
||||
vi.mock('@/hooks/useProtectedSchemas', () => ({
|
||||
|
||||
+1
@@ -45,6 +45,7 @@ vi.mock('@/hooks/misc/useHighAvailability', () => ({
|
||||
|
||||
vi.mock('@/hooks/misc/useSelectedProject', () => ({
|
||||
useSelectedProjectQuery: mockUseSelectedProjectQuery,
|
||||
useIsHighAvailability: () => mockUseHighAvailability().isHighAvailability ?? false,
|
||||
}))
|
||||
|
||||
vi.mock('@/data/database/max-connections-query', () => ({
|
||||
|
||||
@@ -2,7 +2,7 @@ import { PermissionAction } from '@supabase/shared-types/out/constants'
|
||||
import { useParams } from 'common'
|
||||
import { ExternalLink, Info } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import { SetStateAction } from 'react'
|
||||
import { parseAsBoolean, useQueryState } from 'nuqs'
|
||||
import { toast } from 'sonner'
|
||||
import { Alert, AlertDescription, AlertTitle, Button, InfoIcon } from 'ui'
|
||||
import {
|
||||
@@ -26,9 +26,9 @@ import { useIsFeatureEnabled } from '@/hooks/misc/useIsFeatureEnabled'
|
||||
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
|
||||
import {
|
||||
useIsAwsNimbusCloudProvider,
|
||||
useIsHighAvailability,
|
||||
useSelectedProjectQuery,
|
||||
} from '@/hooks/misc/useSelectedProject'
|
||||
import { useUrlState } from '@/hooks/ui/useUrlState'
|
||||
import { DOCS_URL } from '@/lib/constants'
|
||||
import { formatBytes } from '@/lib/helpers'
|
||||
|
||||
@@ -42,14 +42,13 @@ export const DiskSizeConfiguration = ({ disabled = false }: DiskSizeConfiguratio
|
||||
const { data: organization } = useSelectedOrganizationQuery()
|
||||
|
||||
const isAwsNimbus = useIsAwsNimbusCloudProvider()
|
||||
const isHighAvailability = useIsHighAvailability()
|
||||
const { reportsAll } = useIsFeatureEnabled(['reports:all'])
|
||||
|
||||
const [{ show_increase_disk_size_modal }, setUrlParams] = useUrlState()
|
||||
const showIncreaseDiskSizeModal = show_increase_disk_size_modal === 'true'
|
||||
const setShowIncreaseDiskSizeModal = (value: SetStateAction<boolean>) => {
|
||||
const show = typeof value === 'function' ? value(showIncreaseDiskSizeModal) : value
|
||||
setUrlParams({ show_increase_disk_size_modal: show ? 'true' : undefined })
|
||||
}
|
||||
const [showIncreaseDiskSizeModal, setShowIncreaseDiskSizeModal] = useQueryState(
|
||||
'show_increase_disk_size_modal',
|
||||
parseAsBoolean.withDefault(false)
|
||||
)
|
||||
|
||||
const { can: canUpdateDiskSizeConfig } = useAsyncCheckPermissions(
|
||||
PermissionAction.UPDATE,
|
||||
@@ -110,14 +109,16 @@ export const DiskSizeConfiguration = ({ disabled = false }: DiskSizeConfiguratio
|
||||
<ButtonTooltip
|
||||
variant="default"
|
||||
className="w-min ml-auto"
|
||||
disabled={!canUpdateDiskSizeConfig || disabled}
|
||||
disabled={!canUpdateDiskSizeConfig || isHighAvailability || disabled}
|
||||
onClick={() => setShowIncreaseDiskSizeModal(true)}
|
||||
tooltip={{
|
||||
content: {
|
||||
side: 'bottom',
|
||||
text: !canUpdateDiskSizeConfig
|
||||
? 'You need additional permissions to increase the disk size'
|
||||
: undefined,
|
||||
: isHighAvailability
|
||||
? 'Disk size management is unavailable for High Availability projects'
|
||||
: undefined,
|
||||
},
|
||||
}}
|
||||
>
|
||||
@@ -219,11 +220,13 @@ Read more about [disk management](${DOCS_URL}/guides/platform/database-size#disk
|
||||
</PageSectionContent>
|
||||
</PageSection>
|
||||
|
||||
<DiskSizeConfigurationModal
|
||||
visible={showIncreaseDiskSizeModal}
|
||||
loading={isUpdatingDiskSize}
|
||||
hideModal={setShowIncreaseDiskSizeModal}
|
||||
/>
|
||||
{!isHighAvailability && (
|
||||
<DiskSizeConfigurationModal
|
||||
visible={showIncreaseDiskSizeModal}
|
||||
loading={isUpdatingDiskSize}
|
||||
hideModal={setShowIncreaseDiskSizeModal}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import type { ReactNode } from 'react'
|
||||
import { Admonition } from 'ui-patterns/Admonition'
|
||||
|
||||
import { useHighAvailability } from '@/hooks/misc/useHighAvailability'
|
||||
import { useIsHighAvailability } from '@/hooks/misc/useSelectedProject'
|
||||
|
||||
const DEFAULT_TITLE = 'This feature is unavailable on High Availability projects'
|
||||
const DEFAULT_DESCRIPTION =
|
||||
@@ -16,7 +16,7 @@ export function HighAvailabilityDisabledSectionNotice({
|
||||
title = DEFAULT_TITLE,
|
||||
description = DEFAULT_DESCRIPTION,
|
||||
}: HighAvailabilityDisabledSectionNoticeProps) {
|
||||
const { isHighAvailability } = useHighAvailability()
|
||||
const isHighAvailability = useIsHighAvailability()
|
||||
|
||||
if (!isHighAvailability) return null
|
||||
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import { MULTIGRES_SCHEMA_NAME, resolveHighAvailability } from './useHighAvailability.constants'
|
||||
import { useSelectedProjectQuery } from './useSelectedProject'
|
||||
import { useIsHighAvailability, useSelectedProjectQuery } from './useSelectedProject'
|
||||
|
||||
export { MULTIGRES_SCHEMA_NAME, resolveHighAvailability }
|
||||
|
||||
export function useHighAvailability() {
|
||||
const { data: project, isPending } = useSelectedProjectQuery()
|
||||
|
||||
const isHighAvailability = resolveHighAvailability(project)
|
||||
const isHighAvailability = useIsHighAvailability()
|
||||
const { isPending } = useSelectedProjectQuery()
|
||||
|
||||
return {
|
||||
isHighAvailability,
|
||||
|
||||
@@ -54,6 +54,7 @@ export const useIsOrioleDbInAws = () => {
|
||||
return isOrioleDbInAws
|
||||
}
|
||||
|
||||
// [Joshen TODO] There's a duplicate method `resolveHighAvailability` in `useHighAvailability.constants`
|
||||
export const useIsHighAvailability = () => {
|
||||
const { data: project } = useSelectedProjectQuery()
|
||||
return project?.high_availability ?? false
|
||||
|
||||
@@ -43,7 +43,7 @@ import { useCheckEntitlements } from '@/hooks/misc/useCheckEntitlements'
|
||||
import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions'
|
||||
import { useRefreshHandler, useReportDateRange } from '@/hooks/misc/useReportDateRange'
|
||||
import { useSelectedOrganizationQuery } from '@/hooks/misc/useSelectedOrganization'
|
||||
import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
|
||||
import { useIsHighAvailability, useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
|
||||
import { DOCS_URL } from '@/lib/constants'
|
||||
import { formatBytes } from '@/lib/helpers'
|
||||
import { useDatabaseSelectorStateSnapshot } from '@/state/database-selector'
|
||||
@@ -74,6 +74,7 @@ const DatabaseUsage = () => {
|
||||
const { db, chart, ref } = useParams()
|
||||
const { data: project } = useSelectedProjectQuery()
|
||||
const { data: org } = useSelectedOrganizationQuery()
|
||||
const isHighAvailability = useIsHighAvailability()
|
||||
|
||||
const {
|
||||
selectedDateRange,
|
||||
@@ -240,6 +241,7 @@ const DatabaseUsage = () => {
|
||||
side="bottom"
|
||||
>
|
||||
<Button
|
||||
aria-label="Refresh report"
|
||||
variant="default"
|
||||
disabled={isRefreshing}
|
||||
icon={<RefreshCw className={isRefreshing ? 'animate-spin' : ''} />}
|
||||
@@ -369,21 +371,27 @@ const DatabaseUsage = () => {
|
||||
</div>
|
||||
|
||||
<div className="ml-auto">
|
||||
{project?.cloud_provider === 'AWS' ? (
|
||||
{/*
|
||||
[Joshen] TODO: Check if this check is still relevant
|
||||
The DiskSizeConfigurationModal is old and might be obsolete
|
||||
*/}
|
||||
{project?.cloud_provider === 'AWS' && !isHighAvailability ? (
|
||||
<Button asChild variant="default">
|
||||
<Link href={getInfrastructurePath(ref)}>Increase disk size</Link>
|
||||
</Button>
|
||||
) : (
|
||||
<ButtonTooltip
|
||||
variant="default"
|
||||
disabled={!canUpdateDiskSizeConfig}
|
||||
disabled={!canUpdateDiskSizeConfig || isHighAvailability}
|
||||
onClick={() => setshowIncreaseDiskSizeModal(true)}
|
||||
tooltip={{
|
||||
content: {
|
||||
side: 'bottom',
|
||||
text: !canUpdateDiskSizeConfig
|
||||
? 'You need additional permissions to increase the disk size'
|
||||
: undefined,
|
||||
: isHighAvailability
|
||||
? 'Disk size management is unavailable for High Availability projects'
|
||||
: undefined,
|
||||
},
|
||||
}}
|
||||
>
|
||||
@@ -432,32 +440,7 @@ const DatabaseUsage = () => {
|
||||
</div>
|
||||
)
|
||||
}}
|
||||
append={() => (
|
||||
<div className="px-6 pb-6">
|
||||
<Alert variant="default" className="mt-4">
|
||||
<AlertDescription>
|
||||
<div className="space-y-2">
|
||||
<p>
|
||||
New Supabase projects have a database size of ~40-60mb. This space includes
|
||||
pre-installed extensions, schemas, and default Postgres data. Additional
|
||||
database size is used when installing extensions, even if those extensions are
|
||||
inactive.
|
||||
</p>
|
||||
|
||||
<Button asChild variant="default" icon={<ExternalLink />}>
|
||||
<Link
|
||||
href={`${DOCS_URL}/guides/platform/database-size#disk-space-usage`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Read about database size
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
</div>
|
||||
)}
|
||||
append={renderDatabaseSizeAdditionalInfo}
|
||||
/>
|
||||
<DiskSizeConfigurationModal
|
||||
visible={showIncreaseDiskSizeModal}
|
||||
@@ -471,3 +454,31 @@ const DatabaseUsage = () => {
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const renderDatabaseSizeAdditionalInfo = () => {
|
||||
return (
|
||||
<div className="px-6 pb-6">
|
||||
<Alert variant="default" className="mt-4">
|
||||
<AlertDescription>
|
||||
<div className="space-y-2">
|
||||
<p>
|
||||
New Supabase projects have a database size of ~40-60mb. This space includes
|
||||
pre-installed extensions, schemas, and default Postgres data. Additional database size
|
||||
is used when installing extensions, even if those extensions are inactive.
|
||||
</p>
|
||||
|
||||
<Button asChild variant="default" icon={<ExternalLink />}>
|
||||
<Link
|
||||
href={`${DOCS_URL}/guides/platform/database-size#disk-space-usage`}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
Read about database size
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user