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);