feat: Utils | add public and internal ingress routes

This commit is contained in:
2025-11-22 23:18:56 +05:00
parent 35c3c70b08
commit 4f5fbcf83a
8 changed files with 149 additions and 27 deletions

View File

@@ -1,4 +1,8 @@
export { CloudflareCertificate } from "./cert-manager"; export { CloudflareCertificate } from "./cert-manager";
export { OnePasswordSecret } from "./1password-secret"; export { OnePasswordSecret } from "./1password-secret";
export { IngressRoute, IngressRouteTcp } from "./traefik"; export {
PublicIngressRoute,
InternalIngressRoute,
IngressRouteTcp,
} from "./traefik";
export { LonghornPvc } from "./longhorn"; export { LonghornPvc } from "./longhorn";

View File

@@ -1,2 +1,2 @@
export { IngressRoute } from "./ingress"; export { PublicIngressRoute, InternalIngressRoute } from "./ingress";
export { IngressRouteTcp } from "./ingress-tcp"; export { IngressRouteTcp } from "./ingressTCP";

View File

@@ -0,0 +1,2 @@
export { PublicIngressRoute } from "./publicIngress";
export { InternalIngressRoute } from "./internalIngress";

View File

@@ -2,11 +2,12 @@ import { Construct } from "constructs";
import { Manifest } from "@cdktf/provider-kubernetes/lib/manifest"; import { Manifest } from "@cdktf/provider-kubernetes/lib/manifest";
import { KubernetesProvider } from "@cdktf/provider-kubernetes/lib/provider"; import { KubernetesProvider } from "@cdktf/provider-kubernetes/lib/provider";
import { CloudflareCertificate } from "../cert-manager"; import { CloudflareCertificate } from "../../cert-manager";
type IngressRouteOptions = { export type IngressRouteOptions = {
provider: KubernetesProvider; provider: KubernetesProvider;
namespace: string; namespace: string;
name: string;
/** Hostname for this route (e.g. npm.dogar.dev) */ /** Hostname for this route (e.g. npm.dogar.dev) */
host: string; host: string;
@@ -26,9 +27,6 @@ type IngressRouteOptions = {
/** Extra middlewares (traefik format: namespace/name) */ /** Extra middlewares (traefik format: namespace/name) */
middlewares?: string[]; middlewares?: string[];
/** Name override (otherwise auto) */
name?: string;
}; };
export class IngressRoute extends Construct { export class IngressRoute extends Construct {
@@ -37,7 +35,7 @@ export class IngressRoute extends Construct {
constructor(scope: Construct, id: string, opts: IngressRouteOptions) { constructor(scope: Construct, id: string, opts: IngressRouteOptions) {
super(scope, id); super(scope, id);
const name = opts.name ?? `route-${opts.host.replace(/\./g, "-")}`; const name = opts.name;
const path = opts.path ?? "/"; const path = opts.path ?? "/";
const entryPoints = opts.entryPoints ?? ["websecure"]; const entryPoints = opts.entryPoints ?? ["websecure"];

View File

@@ -0,0 +1,63 @@
import { Construct } from "constructs";
import { IngressRoute, IngressRouteOptions } from "./ingress";
import { DataTerraformRemoteStateS3 } from "cdktf";
import { DataKubernetesNamespaceV1 } from "@cdktf/provider-kubernetes/lib/data-kubernetes-namespace-v1";
type InternalIngressRouteOptions = Omit<
IngressRouteOptions,
"entryPoints" | "tlsSecretName" | "middlewares"
>;
export class InternalIngressRoute extends Construct {
constructor(scope: Construct, id: string, opts: InternalIngressRouteOptions) {
super(scope, id);
const r2Endpoint = `${process.env.ACCOUNT_ID!}.r2.cloudflarestorage.com`;
const coreServicesState = new DataTerraformRemoteStateS3(
this,
"core-services-state",
{
usePathStyle: true,
skipRegionValidation: true,
skipCredentialsValidation: true,
skipRequestingAccountId: true,
skipS3Checksum: true,
encrypt: true,
bucket: "terraform-state",
key: "core-services/terraform.tfstate",
endpoints: {
s3: `https://${r2Endpoint}`,
},
region: "auto",
accessKey: process.env.ACCESS_KEY,
secretKey: process.env.SECRET_KEY,
},
);
const namespaceName = coreServicesState.getString("namespace-output");
const namespaceResource = new DataKubernetesNamespaceV1(
this,
"core-services-namespace",
{
provider: opts.provider,
metadata: {
name: namespaceName,
},
},
);
const namespace = namespaceResource.metadata.name;
new IngressRoute(this, opts.name, {
provider: opts.provider,
namespace: opts.namespace,
host: opts.host,
path: opts.path ?? "/",
serviceName: opts.serviceName,
servicePort: opts.servicePort,
entryPoints: ["websecure"],
tlsSecretName: `${opts.name}-tls`,
middlewares: [`${namespace}/ip-allow-list`],
name: opts.name,
});
}
}

View File

@@ -0,0 +1,63 @@
import { Construct } from "constructs";
import { IngressRoute, IngressRouteOptions } from "./ingress";
import { DataTerraformRemoteStateS3 } from "cdktf";
import { DataKubernetesNamespaceV1 } from "@cdktf/provider-kubernetes/lib/data-kubernetes-namespace-v1";
type PublicIngressRouteOptions = Omit<
IngressRouteOptions,
"entryPoints" | "tlsSecretName" | "middlewares"
>;
export class PublicIngressRoute extends Construct {
constructor(scope: Construct, id: string, opts: PublicIngressRouteOptions) {
super(scope, id);
const r2Endpoint = `${process.env.ACCOUNT_ID!}.r2.cloudflarestorage.com`;
const coreServicesState = new DataTerraformRemoteStateS3(
this,
"core-services-state",
{
usePathStyle: true,
skipRegionValidation: true,
skipCredentialsValidation: true,
skipRequestingAccountId: true,
skipS3Checksum: true,
encrypt: true,
bucket: "terraform-state",
key: "core-services/terraform.tfstate",
endpoints: {
s3: `https://${r2Endpoint}`,
},
region: "auto",
accessKey: process.env.ACCESS_KEY,
secretKey: process.env.SECRET_KEY,
},
);
const namespaceName = coreServicesState.getString("namespace-output");
const namespaceResource = new DataKubernetesNamespaceV1(
this,
"core-services-namespace",
{
provider: opts.provider,
metadata: {
name: namespaceName,
},
},
);
const namespace = namespaceResource.metadata.name;
new IngressRoute(this, opts.name, {
provider: opts.provider,
namespace: opts.namespace,
host: opts.host,
path: opts.path ?? "/",
serviceName: opts.serviceName,
servicePort: opts.servicePort,
entryPoints: ["websecure"],
tlsSecretName: `${opts.name}-tls`,
middlewares: [`${namespace}/rate-limit`],
name: opts.name,
});
}
}

View File

@@ -0,0 +1 @@
export { IngressRouteTcp } from "./ingress-tcp";

View File

@@ -4,6 +4,13 @@ import { KubernetesProvider } from "@cdktf/provider-kubernetes/lib/provider";
type IngressRouteTcpOptions = { type IngressRouteTcpOptions = {
provider: KubernetesProvider; provider: KubernetesProvider;
name: string;
/**
* Match rule.
* Default is `HostSNI(\`*\`)` which is correct for most TCP services.
*/
match: string;
/** Namespace where the IngressRouteTCP will be created */ /** Namespace where the IngressRouteTCP will be created */
namespace: string; namespace: string;
@@ -16,15 +23,6 @@ type IngressRouteTcpOptions = {
/** Backend service port */ /** Backend service port */
servicePort: number; servicePort: number;
/**
* Match rule.
* Default is `HostSNI(\`*\`)` which is correct for most TCP services.
*/
match?: string;
/** Name override (CR name) */
name?: string;
}; };
export class IngressRouteTcp extends Construct { export class IngressRouteTcp extends Construct {
@@ -33,14 +31,7 @@ export class IngressRouteTcp extends Construct {
constructor(scope: Construct, id: string, opts: IngressRouteTcpOptions) { constructor(scope: Construct, id: string, opts: IngressRouteTcpOptions) {
super(scope, id); super(scope, id);
const name = const { name, match } = opts;
opts.name ??
`tcp-${opts.entryPoint}-${opts.serviceName}`.replace(
/[^a-zA-Z0-9-]/g,
"",
);
const matchRule = opts.match ?? "HostSNI(`*`)";
this.manifest = new Manifest(this, name, { this.manifest = new Manifest(this, name, {
provider: opts.provider, provider: opts.provider,
@@ -55,7 +46,7 @@ export class IngressRouteTcp extends Construct {
entryPoints: [opts.entryPoint], entryPoints: [opts.entryPoint],
routes: [ routes: [
{ {
match: matchRule, match,
services: [ services: [
{ {
name: opts.serviceName, name: opts.serviceName,