Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/private-networking-dequeue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@trigger.dev/core": patch
---

Add optional `hasPrivateLink` field to the dequeue message organization object for private networking support
6 changes: 6 additions & 0 deletions .server-changes/private-networking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
area: webapp
type: feature
---

Add private networking support via AWS PrivateLink. Includes BillingClient methods for managing private connections, org settings UI pages for connection management, and supervisor changes to apply `privatelink` pod labels for CiliumNetworkPolicy matching.
1 change: 1 addition & 0 deletions apps/supervisor/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ class ManagedSupervisor {
snapshotFriendlyId: message.snapshot.friendlyId,
placementTags: message.placementTags,
annotations: message.run.annotations,
hasPrivateLink: message.organization.hasPrivateLink,
});

// Disabled for now
Expand Down
9 changes: 8 additions & 1 deletion apps/supervisor/src/workloadManager/kubernetes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ export class KubernetesWorkloadManager implements WorkloadManager {
}

#getSharedLabels(opts: WorkloadManagerCreateOptions): Record<string, string> {
return {
const labels: Record<string, string> = {
env: opts.envId,
envtype: this.#envTypeToLabelValue(opts.envType),
org: opts.orgId,
Expand All @@ -352,6 +352,13 @@ export class KubernetesWorkloadManager implements WorkloadManager {
// and pool-level scheduling decisions; finer-grained source breakdowns live in run annotations.
scheduled: String(this.#isScheduledRun(opts)),
};

// Add privatelink label for CiliumNetworkPolicy matching
if (opts.hasPrivateLink) {
labels.privatelink = opts.orgId;
}

return labels;
}

#getResourceRequestsForMachine(preset: MachinePreset): ResourceQuantities {
Expand Down
2 changes: 2 additions & 0 deletions apps/supervisor/src/workloadManager/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,6 @@ export interface WorkloadManagerCreateOptions {
snapshotId: string;
snapshotFriendlyId: string;
annotations?: RunAnnotations;
// private networking
hasPrivateLink?: boolean;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
ChartBarIcon,
Cog8ToothIcon,
CreditCardIcon,
LockClosedIcon,
UserGroupIcon,
} from "@heroicons/react/20/solid";
import { ArrowLeftIcon } from "@heroicons/react/24/solid";
Expand All @@ -19,6 +20,7 @@ import {
rootPath,
v3BillingAlertsPath,
v3BillingPath,
v3PrivateConnectionsPath,
v3UsagePath,
} from "~/utils/pathBuilder";
import { LinkButton } from "../primitives/Buttons";
Expand Down Expand Up @@ -46,7 +48,7 @@ export function OrganizationSettingsSideMenu({
organization: MatchedOrganization;
buildInfo: BuildInfo;
}) {
const { isManagedCloud } = useFeatures();
const { isManagedCloud, hasPrivateConnections } = useFeatures();
const currentPlan = useCurrentPlan();
const isAdmin = useHasAdminAccess();
const showBuildInfo = isAdmin || !isManagedCloud;
Expand Down Expand Up @@ -103,6 +105,15 @@ export function OrganizationSettingsSideMenu({
/>
</>
)}
{hasPrivateConnections && (
<SideMenuItem
name="Private Connections"
icon={LockClosedIcon}
activeIconColor="text-purple-500"
to={v3PrivateConnectionsPath(organization)}
data-action="private-connections"
/>
)}
<SideMenuItem
name="Team"
icon={UserGroupIcon}
Expand Down
4 changes: 4 additions & 0 deletions apps/webapp/app/env.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1385,6 +1385,10 @@ const EnvironmentSchema = z
REALTIME_STREAMS_S2_WAIT_SECONDS: z.coerce.number().int().default(60),
REALTIME_STREAMS_DEFAULT_VERSION: z.enum(["v1", "v2"]).default("v1"),
WAIT_UNTIL_TIMEOUT_MS: z.coerce.number().int().default(600_000),

// Private connections
PRIVATE_CONNECTIONS_ENABLED: z.string().optional(),
PRIVATE_CONNECTIONS_AWS_ACCOUNT_IDS: z.string().optional(),
})
.and(GithubAppEnvSchema)
.and(S2EnvSchema);
Expand Down
10 changes: 10 additions & 0 deletions apps/webapp/app/features.server.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { env } from "./env.server";
import { requestUrl } from "./utils/requestUrl.server";

export type TriggerFeatures = {
isManagedCloud: boolean;
hasPrivateConnections: boolean;
};

function isManagedCloud(host: string): boolean {
Expand All @@ -13,9 +15,17 @@ function isManagedCloud(host: string): boolean {
);
}

function hasPrivateConnections(host: string): boolean {
if (env.PRIVATE_CONNECTIONS_ENABLED === "1") {
return isManagedCloud(host);
}
return false;
}

function featuresForHost(host: string): TriggerFeatures {
return {
isManagedCloud: isManagedCloud(host),
hasPrivateConnections: hasPrivateConnections(host),
};
}

Expand Down
2 changes: 1 addition & 1 deletion apps/webapp/app/hooks/useFeatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ import type { TriggerFeatures } from "~/features.server";
export function useFeatures(): TriggerFeatures {
const routeMatch = useTypedRouteLoaderData<typeof loader>("root");

return routeMatch?.features ?? { isManagedCloud: false };
return routeMatch?.features ?? { isManagedCloud: false, hasPrivateConnections: false };
}
Loading
Loading