feature: databricks sync

This commit is contained in:
Scott Wilson
2025-02-10 18:38:27 -08:00
parent 4e48ab1eeb
commit 4de8888843
105 changed files with 1548 additions and 173 deletions
@@ -0,0 +1,72 @@
import { Controller, useFormContext, useWatch } from "react-hook-form";
import { SingleValue } from "react-select";
import { faCircleInfo } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { SecretSyncConnectionField } from "@app/components/secret-syncs/forms/SecretSyncConnectionField";
import { FilterableSelect, FormControl, Tooltip } from "@app/components/v2";
import {
TDatabricksSecretScope,
useDatabricksConnectionListSecretScopes
} from "@app/hooks/api/appConnections/databricks";
import { SecretSync } from "@app/hooks/api/secretSyncs";
import { TSecretSyncForm } from "../schemas";
export const DatabricksSyncFields = () => {
const { control, setValue } = useFormContext<
TSecretSyncForm & { destination: SecretSync.Databricks }
>();
const connectionId = useWatch({ name: "connection.id", control });
const { data: secretScopes = [], isPending: isSecretScopesPending } =
useDatabricksConnectionListSecretScopes(connectionId, {
enabled: Boolean(connectionId)
});
return (
<>
<SecretSyncConnectionField
onChange={() => {
setValue("destinationConfig.scope", "");
}}
/>
<Controller
name="destinationConfig.scope"
control={control}
render={({ field: { value, onChange }, fieldState: { error } }) => (
<FormControl
isError={Boolean(error)}
errorText={error?.message}
label="Secret Scope"
helperText={
<Tooltip
className="max-w-md"
content="Ensure that you've created the secret scope in the selected workspace, the service principal has been be assigned to the respective workspace and that your service principal has write permissions for the specified secret scope."
>
<div>
<span>Don&#39;t see the secret scope you&#39;re looking for?</span>{" "}
<FontAwesomeIcon icon={faCircleInfo} className="text-mineshaft-400" />
</div>
</Tooltip>
}
>
<FilterableSelect
isLoading={isSecretScopesPending && Boolean(connectionId)}
isDisabled={!connectionId}
value={secretScopes.find((scope) => scope.name === value) ?? null}
onChange={(option) =>
onChange((option as SingleValue<TDatabricksSecretScope>)?.name ?? null)
}
options={secretScopes}
placeholder="Select a secret scope..."
getOptionLabel={(option) => option.name}
getOptionValue={(option) => option.name}
/>
</FormControl>
)}
/>
</>
);
};
@@ -1,5 +1,6 @@
import { useFormContext } from "react-hook-form";
import { DatabricksSyncFields } from "@app/components/secret-syncs/forms/SecretSyncDestinationFields/DatabricksSyncFields";
import { SecretSync } from "@app/hooks/api/secretSyncs";
import { TSecretSyncForm } from "../schemas";
@@ -28,6 +29,8 @@ export const SecretSyncDestinationFields = () => {
return <AzureKeyVaultSyncFields />;
case SecretSync.AzureAppConfiguration:
return <AzureAppConfigurationSyncFields />;
case SecretSync.Databricks:
return <DatabricksSyncFields />;
default:
throw new Error(`Unhandled Destination Config Field: ${destination}`);
}
@@ -0,0 +1,12 @@
import { useFormContext } from "react-hook-form";
import { SecretSyncLabel } from "@app/components/secret-syncs";
import { TSecretSyncForm } from "@app/components/secret-syncs/forms/schemas";
import { SecretSync } from "@app/hooks/api/secretSyncs";
export const DatabricksSyncReviewFields = () => {
const { watch } = useFormContext<TSecretSyncForm & { destination: SecretSync.Databricks }>();
const scope = watch("destinationConfig.scope");
return <SecretSyncLabel label="Secret Scope">{scope}</SecretSyncLabel>;
};
@@ -4,6 +4,7 @@ import { useFormContext } from "react-hook-form";
import { SecretSyncLabel } from "@app/components/secret-syncs";
import { TSecretSyncForm } from "@app/components/secret-syncs/forms/schemas";
import { AwsSecretsManagerSyncReviewFields } from "@app/components/secret-syncs/forms/SecretSyncReviewFields/AwsSecretsManagerSyncReviewFields";
import { DatabricksSyncReviewFields } from "@app/components/secret-syncs/forms/SecretSyncReviewFields/DatabricksSyncReviewFields";
import { Badge } from "@app/components/v2";
import { SECRET_SYNC_INITIAL_SYNC_BEHAVIOR_MAP, SECRET_SYNC_MAP } from "@app/helpers/secretSyncs";
import { SecretSync } from "@app/hooks/api/secretSyncs";
@@ -54,6 +55,9 @@ export const SecretSyncReviewFields = () => {
case SecretSync.AzureAppConfiguration:
DestinationFieldsComponent = <AzureAppConfigurationSyncReviewFields />;
break;
case SecretSync.Databricks:
DestinationFieldsComponent = <DatabricksSyncReviewFields />;
break;
default:
throw new Error(`Unhandled Destination Review Fields: ${destination}`);
}
@@ -0,0 +1,10 @@
import { z } from "zod";
import { SecretSync } from "@app/hooks/api/secretSyncs";
export const DatabricksSyncDestinationSchema = z.object({
destination: z.literal(SecretSync.Databricks),
destinationConfig: z.object({
scope: z.string().trim().min(1, "Databricks scope required")
})
});
@@ -1,6 +1,7 @@
import { z } from "zod";
import { AwsSecretsManagerSyncDestinationSchema } from "@app/components/secret-syncs/forms/schemas/aws-secrets-manager-sync-destination-schema";
import { DatabricksSyncDestinationSchema } from "@app/components/secret-syncs/forms/schemas/databricks-sync-destination-schema";
import { GitHubSyncDestinationSchema } from "@app/components/secret-syncs/forms/schemas/github-sync-destination-schema";
import { SecretSyncInitialSyncBehavior } from "@app/hooks/api/secretSyncs";
import { slugSchema } from "@app/lib/schemas";
@@ -39,7 +40,8 @@ const SecretSyncUnionSchema = z.discriminatedUnion("destination", [
GitHubSyncDestinationSchema,
GcpSyncDestinationSchema,
AzureKeyVaultSyncDestinationSchema,
AzureAppConfigurationSyncDestinationSchema
AzureAppConfigurationSyncDestinationSchema,
DatabricksSyncDestinationSchema
]);
export const SecretSyncFormSchema = SecretSyncUnionSchema.and(BaseSecretSyncSchema);
+5 -1
View File
@@ -10,6 +10,7 @@ import {
GitHubConnectionMethod,
TAppConnection
} from "@app/hooks/api/appConnections/types";
import { DatabricksConnectionMethod } from "@app/hooks/api/appConnections/types/databricks-connection";
export const APP_CONNECTION_MAP: Record<AppConnection, { name: string; image: string }> = {
[AppConnection.AWS]: { name: "AWS", image: "Amazon Web Services.png" },
@@ -22,7 +23,8 @@ export const APP_CONNECTION_MAP: Record<AppConnection, { name: string; image: st
[AppConnection.AzureAppConfiguration]: {
name: "Azure App Configuration",
image: "Microsoft Azure.png"
}
},
[AppConnection.Databricks]: { name: "Databricks", image: "Databricks.png" }
};
export const getAppConnectionMethodDetails = (method: TAppConnection["method"]) => {
@@ -39,6 +41,8 @@ export const getAppConnectionMethodDetails = (method: TAppConnection["method"])
return { name: "Assume Role", icon: faUser };
case GcpConnectionMethod.ServiceAccountImpersonation:
return { name: "Service Account Impersonation", icon: faUser };
case DatabricksConnectionMethod.ServicePrincipal:
return { name: "Service Principal", icon: faUser };
default:
throw new Error(`Unhandled App Connection Method: ${method}`);
}
+6 -1
View File
@@ -14,6 +14,10 @@ export const SECRET_SYNC_MAP: Record<SecretSync, { name: string; image: string }
[SecretSync.AzureAppConfiguration]: {
name: "Azure App Configuration",
image: "Microsoft Azure.png"
},
[SecretSync.Databricks]: {
name: "Databricks",
image: "Databricks.png"
}
};
@@ -23,7 +27,8 @@ export const SECRET_SYNC_CONNECTION_MAP: Record<SecretSync, AppConnection> = {
[SecretSync.GitHub]: AppConnection.GitHub,
[SecretSync.GCPSecretManager]: AppConnection.GCP,
[SecretSync.AzureKeyVault]: AppConnection.AzureKeyVault,
[SecretSync.AzureAppConfiguration]: AppConnection.AzureAppConfiguration
[SecretSync.AzureAppConfiguration]: AppConnection.AzureAppConfiguration,
[SecretSync.Databricks]: AppConnection.Databricks
};
export const SECRET_SYNC_INITIAL_SYNC_BEHAVIOR_MAP: Record<
@@ -0,0 +1,2 @@
export * from "./queries";
export * from "./types";
@@ -0,0 +1,37 @@
import { useQuery, UseQueryOptions } from "@tanstack/react-query";
import { apiRequest } from "@app/config/request";
import { appConnectionKeys } from "@app/hooks/api/appConnections";
import { TDatabricksConnectionListSecretScopesResponse, TDatabricksSecretScope } from "./types";
const databricksConnectionKeys = {
all: [...appConnectionKeys.all, "databricks"] as const,
listSecretScopes: (connectionId: string) =>
[...databricksConnectionKeys.all, "workspace-scopes", connectionId] as const
};
export const useDatabricksConnectionListSecretScopes = (
connectionId: string,
options?: Omit<
UseQueryOptions<
TDatabricksSecretScope[],
unknown,
TDatabricksSecretScope[],
ReturnType<typeof databricksConnectionKeys.listSecretScopes>
>,
"queryKey" | "queryFn"
>
) => {
return useQuery({
queryKey: databricksConnectionKeys.listSecretScopes(connectionId),
queryFn: async () => {
const { data } = await apiRequest.get<TDatabricksConnectionListSecretScopesResponse>(
`/api/v1/app-connections/databricks/${connectionId}/secret-scopes`
);
return data.secretScopes;
},
...options
});
};
@@ -0,0 +1,7 @@
export type TDatabricksSecretScope = {
name: string;
};
export type TDatabricksConnectionListSecretScopesResponse = {
secretScopes: TDatabricksSecretScope[];
};
@@ -3,5 +3,6 @@ export enum AppConnection {
GitHub = "github",
GCP = "gcp",
AzureKeyVault = "azure-key-vault",
AzureAppConfiguration = "azure-app-configuration"
AzureAppConfiguration = "azure-app-configuration",
Databricks = "databricks"
}
@@ -30,7 +30,17 @@ export type TAzureAppConfigurationConnectionOption = TAppConnectionOptionBase &
oauthClientId?: string;
};
export type TAppConnectionOption = TAwsConnectionOption | TGitHubConnectionOption;
export type TDatabricksConnectionOption = TAppConnectionOptionBase & {
app: AppConnection.Databricks;
};
export type TAppConnectionOption =
| TAwsConnectionOption
| TGitHubConnectionOption
| TGcpConnectionOption
| TAzureAppConfigurationConnectionOption
| TAzureKeyVaultConnectionOption
| TDatabricksConnectionOption;
export type TAppConnectionOptionMap = {
[AppConnection.AWS]: TAwsConnectionOption;
@@ -38,4 +48,5 @@ export type TAppConnectionOptionMap = {
[AppConnection.GCP]: TGcpConnectionOption;
[AppConnection.AzureKeyVault]: TAzureKeyVaultConnectionOption;
[AppConnection.AzureAppConfiguration]: TAzureAppConfigurationConnectionOption;
[AppConnection.Databricks]: TDatabricksConnectionOption;
};
@@ -0,0 +1,15 @@
import { AppConnection } from "../enums";
import { TRootAppConnection } from "./root-connection";
export enum DatabricksConnectionMethod {
ServicePrincipal = "service-principal"
}
export type TDatabricksConnection = TRootAppConnection & { app: AppConnection.Databricks } & {
method: DatabricksConnectionMethod.ServicePrincipal;
credentials: {
workspaceUrl: string;
clientId: string;
clientSecret: string;
};
};
@@ -1,6 +1,7 @@
import { AppConnection } from "@app/hooks/api/appConnections/enums";
import { TAppConnectionOption } from "@app/hooks/api/appConnections/types/app-options";
import { TAwsConnection } from "@app/hooks/api/appConnections/types/aws-connection";
import { TDatabricksConnection } from "@app/hooks/api/appConnections/types/databricks-connection";
import { TGitHubConnection } from "@app/hooks/api/appConnections/types/github-connection";
import { TAzureAppConfigurationConnection } from "./azure-app-configuration-connection";
@@ -18,7 +19,8 @@ export type TAppConnection =
| TGitHubConnection
| TGcpConnection
| TAzureKeyVaultConnection
| TAzureAppConfigurationConnection;
| TAzureAppConfigurationConnection
| TDatabricksConnection;
export type TAvailableAppConnection = Pick<TAppConnection, "name" | "id">;
@@ -51,4 +53,5 @@ export type TAppConnectionMap = {
[AppConnection.GCP]: TGcpConnection;
[AppConnection.AzureKeyVault]: TAzureKeyVaultConnection;
[AppConnection.AzureAppConfiguration]: TAzureAppConfigurationConnection;
[AppConnection.Databricks]: TDatabricksConnection;
};
+2 -1
View File
@@ -4,7 +4,8 @@ export enum SecretSync {
GitHub = "github",
GCPSecretManager = "gcp-secret-manager",
AzureKeyVault = "azure-key-vault",
AzureAppConfiguration = "azure-app-configuration"
AzureAppConfiguration = "azure-app-configuration",
Databricks = "databricks"
}
export enum SecretSyncStatus {
@@ -0,0 +1,15 @@
import { AppConnection } from "@app/hooks/api/appConnections/enums";
import { SecretSync } from "@app/hooks/api/secretSyncs";
import { TRootSecretSync } from "@app/hooks/api/secretSyncs/types/root-sync";
export type TDatabricksSync = TRootSecretSync & {
destination: SecretSync.Databricks;
destinationConfig: {
scope: string;
};
connection: {
app: AppConnection.Databricks;
name: string;
id: string;
};
};
@@ -1,5 +1,6 @@
import { SecretSync, SecretSyncImportBehavior } from "@app/hooks/api/secretSyncs";
import { TAwsParameterStoreSync } from "@app/hooks/api/secretSyncs/types/aws-parameter-store-sync";
import { TDatabricksSync } from "@app/hooks/api/secretSyncs/types/databricks-sync";
import { TGitHubSync } from "@app/hooks/api/secretSyncs/types/github-sync";
import { DiscriminativePick } from "@app/types";
@@ -20,7 +21,8 @@ export type TSecretSync =
| TGitHubSync
| TGcpSync
| TAzureKeyVaultSync
| TAzureAppConfigurationSync;
| TAzureAppConfigurationSync
| TDatabricksSync;
export type TListSecretSyncs = { secretSyncs: TSecretSync[] };
@@ -12,6 +12,7 @@ import { AppConnectionHeader } from "../AppConnectionHeader";
import { AwsConnectionForm } from "./AwsConnectionForm";
import { AzureAppConfigurationConnectionForm } from "./AzureAppConfigurationConnectionForm";
import { AzureKeyVaultConnectionForm } from "./AzureKeyVaultConnectionForm";
import { DatabricksConnectionForm } from "./DatabricksConnectionForm";
import { GcpConnectionForm } from "./GcpConnectionForm";
import { GitHubConnectionForm } from "./GitHubConnectionForm";
@@ -59,6 +60,8 @@ const CreateForm = ({ app, onComplete }: CreateFormProps) => {
return <AzureKeyVaultConnectionForm />;
case AppConnection.AzureAppConfiguration:
return <AzureAppConfigurationConnectionForm />;
case AppConnection.Databricks:
return <DatabricksConnectionForm onSubmit={onSubmit} />;
default:
throw new Error(`Unhandled App ${app}`);
}
@@ -102,6 +105,8 @@ const UpdateForm = ({ appConnection, onComplete }: UpdateFormProps) => {
return <AzureKeyVaultConnectionForm appConnection={appConnection} />;
case AppConnection.AzureAppConfiguration:
return <AzureAppConfigurationConnectionForm appConnection={appConnection} />;
case AppConnection.Databricks:
return <DatabricksConnectionForm onSubmit={onSubmit} appConnection={appConnection} />;
default:
throw new Error(`Unhandled App ${(appConnection as TAppConnection).app}`);
}
@@ -0,0 +1,166 @@
import { Controller, FormProvider, useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import {
Button,
FormControl,
Input,
ModalClose,
SecretInput,
Select,
SelectItem
} from "@app/components/v2";
import { APP_CONNECTION_MAP, getAppConnectionMethodDetails } from "@app/helpers/appConnections";
import { AppConnection } from "@app/hooks/api/appConnections/enums";
import {
DatabricksConnectionMethod,
TDatabricksConnection
} from "@app/hooks/api/appConnections/types/databricks-connection";
import {
genericAppConnectionFieldsSchema,
GenericAppConnectionsFields
} from "./GenericAppConnectionFields";
type Props = {
appConnection?: TDatabricksConnection;
onSubmit: (formData: FormData) => void;
};
const rootSchema = genericAppConnectionFieldsSchema.extend({
app: z.literal(AppConnection.Databricks)
});
const formSchema = z.discriminatedUnion("method", [
rootSchema.extend({
method: z.literal(DatabricksConnectionMethod.ServicePrincipal),
credentials: z.object({
workspaceUrl: z.string().url().trim().min(1, "Workspace URL required"),
clientId: z.string().trim().min(1, "Client ID required"),
clientSecret: z.string().trim().min(1, "Client secret required")
})
})
]);
type FormData = z.infer<typeof formSchema>;
export const DatabricksConnectionForm = ({ appConnection, onSubmit }: Props) => {
const isUpdate = Boolean(appConnection);
const form = useForm<FormData>({
resolver: zodResolver(formSchema),
defaultValues: appConnection ?? {
app: AppConnection.Databricks,
method: DatabricksConnectionMethod.ServicePrincipal
}
});
const {
handleSubmit,
control,
formState: { isSubmitting, isDirty }
} = form;
return (
<FormProvider {...form}>
<form onSubmit={handleSubmit(onSubmit)}>
{!isUpdate && <GenericAppConnectionsFields />}
<Controller
name="method"
control={control}
render={({ field: { value, onChange }, fieldState: { error } }) => (
<FormControl
tooltipText={`The method you would like to use to connect with ${
APP_CONNECTION_MAP[AppConnection.Databricks].name
}. This field cannot be changed after creation.`}
errorText={error?.message}
isError={Boolean(error?.message)}
label="Method"
>
<Select
isDisabled={isUpdate}
value={value}
onValueChange={(val) => onChange(val)}
className="w-full border border-mineshaft-500"
position="popper"
dropdownContainerClassName="max-w-none"
>
{Object.values(DatabricksConnectionMethod).map((method) => {
return (
<SelectItem value={method} key={method}>
{getAppConnectionMethodDetails(method).name}
</SelectItem>
);
})}
</Select>
</FormControl>
)}
/>
<Controller
name="credentials.workspaceUrl"
control={control}
shouldUnregister
render={({ field, fieldState: { error } }) => (
<FormControl
errorText={error?.message}
isError={Boolean(error?.message)}
label="Workspace URL"
>
<Input {...field} placeholder="https://xxx-xxxxxxxx-xxx.cloud.databricks.com" />
</FormControl>
)}
/>
<Controller
name="credentials.clientId"
control={control}
shouldUnregister
render={({ field, fieldState: { error } }) => (
<FormControl
errorText={error?.message}
isError={Boolean(error?.message)}
label="Client ID"
>
<Input {...field} placeholder="05810c8f-c44d-4bd0-a327-aab6dd77719b" />
</FormControl>
)}
/>
<Controller
name="credentials.clientSecret"
control={control}
shouldUnregister
render={({ field: { value, onChange }, fieldState: { error } }) => (
<FormControl
errorText={error?.message}
isError={Boolean(error?.message)}
label="Client Secret"
>
<SecretInput
containerClassName="text-gray-400 group-focus-within:!border-primary-400/50 border border-mineshaft-500 bg-mineshaft-900 px-2.5 py-1.5"
value={value}
onChange={(e) => onChange(e.target.value)}
/>
</FormControl>
)}
/>
<div className="mt-8 flex items-center">
<Button
className="mr-4"
size="sm"
type="submit"
colorSchema="secondary"
isLoading={isSubmitting}
isDisabled={isSubmitting || !isDirty}
>
{isUpdate ? "Update Credentials" : "Connect to Databricks"}
</Button>
<ModalClose asChild>
<Button colorSchema="secondary" variant="plain">
Cancel
</Button>
</ModalClose>
</div>
</form>
</FormProvider>
);
};
@@ -23,7 +23,7 @@ export const AppConnectionsSelect = ({ onSelect }: Props) => {
}
return (
<div className="grid grid-cols-5 gap-2">
<div className="grid grid-cols-4 gap-2">
{appConnectionOptions?.map((option) => (
<button
type="button"
@@ -44,7 +44,7 @@ export const DeleteAppConnectionModal = ({ isOpen, onOpenChange, appConnection }
isOpen={isOpen}
onChange={onOpenChange}
title={`Are you sure want to delete ${name}?`}
deleteKey="confirm"
deleteKey={name}
onDeleteApproved={handleDeleteAppConnection}
/>
);
@@ -0,0 +1,14 @@
import { TDatabricksSync } from "@app/hooks/api/secretSyncs/types/databricks-sync";
import { getSecretSyncDestinationColValues } from "../helpers";
import { SecretSyncTableCell } from "../SecretSyncTableCell";
type Props = {
secretSync: TDatabricksSync;
};
export const DatabricksSyncDestinationCol = ({ secretSync }: Props) => {
const { primaryText } = getSecretSyncDestinationColValues(secretSync);
return <SecretSyncTableCell primaryText={primaryText} secondaryText="Secret Scope" />;
};
@@ -4,6 +4,7 @@ import { AwsParameterStoreSyncDestinationCol } from "./AwsParameterStoreSyncDest
import { AwsSecretsManagerSyncDestinationCol } from "./AwsSecretsManagerSyncDestinationCol";
import { AzureAppConfigurationDestinationSyncCol } from "./AzureAppConfigurationDestinationSyncCol";
import { AzureKeyVaultDestinationSyncCol } from "./AzureKeyVaultDestinationSyncCol";
import { DatabricksSyncDestinationCol } from "./DatabricksSyncDestinationCol";
import { GcpSyncDestinationCol } from "./GcpSyncDestinationCol";
import { GitHubSyncDestinationCol } from "./GitHubSyncDestinationCol";
@@ -25,7 +26,8 @@ export const SecretSyncDestinationCol = ({ secretSync }: Props) => {
return <AzureKeyVaultDestinationSyncCol secretSync={secretSync} />;
case SecretSync.AzureAppConfiguration:
return <AzureAppConfigurationDestinationSyncCol secretSync={secretSync} />;
case SecretSync.Databricks:
return <DatabricksSyncDestinationCol secretSync={secretSync} />;
default:
throw new Error(
`Unhandled Secret Sync Destination Col: ${(secretSync as TSecretSync).destination}`
@@ -56,6 +56,9 @@ export const getSecretSyncDestinationColValues = (secretSync: TSecretSync) => {
secondaryText = `Label - ${destinationConfig.label}`;
}
break;
case SecretSync.Databricks:
primaryText = destinationConfig.scope;
break;
default:
throw new Error(`Unhandled Destination Col Values ${destination}`);
}
@@ -0,0 +1,14 @@
import { SecretSyncLabel } from "@app/components/secret-syncs";
import { TDatabricksSync } from "@app/hooks/api/secretSyncs/types/databricks-sync";
type Props = {
secretSync: TDatabricksSync;
};
export const DatabricksSyncDestinationSection = ({ secretSync }: Props) => {
const {
destinationConfig: { scope }
} = secretSync;
return <SecretSyncLabel label="Secret Scope">{scope}</SecretSyncLabel>;
};
@@ -11,6 +11,7 @@ import { APP_CONNECTION_MAP } from "@app/helpers/appConnections";
import { SecretSync, TSecretSync } from "@app/hooks/api/secretSyncs";
import { AwsParameterStoreSyncDestinationSection } from "@app/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/AwsParameterStoreSyncDestinationSection";
import { AwsSecretsManagerSyncDestinationSection } from "@app/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/AwsSecretsManagerSyncDestinationSection";
import { DatabricksSyncDestinationSection } from "@app/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/DatabricksSyncDestinationSection";
import { GitHubSyncDestinationSection } from "@app/pages/secret-manager/SecretSyncDetailsByIDPage/components/SecretSyncDestinationSection/GitHubSyncDestinationSection";
import { AzureAppConfigurationSyncDestinationSection } from "./AzureAppConfigurationSyncDestinationSection";
@@ -49,7 +50,9 @@ export const SecretSyncDestinationSection = ({ secretSync, onEditDestination }:
<AzureAppConfigurationSyncDestinationSection secretSync={secretSync} />
);
break;
case SecretSync.Databricks:
DestinationComponents = <DatabricksSyncDestinationSection secretSync={secretSync} />;
break;
default:
throw new Error(`Unhandled Destination Section components: ${destination}`);
}