Skip to content

Commit 1c41f4d

Browse files
committed
feat: uri extraction
1 parent bd73cc5 commit 1c41f4d

File tree

2 files changed

+56
-23
lines changed

2 files changed

+56
-23
lines changed

infrastructure/evault-provisioner/src/index.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ interface ProvisionRequest {
1919

2020
interface ProvisionResponse {
2121
success: boolean;
22-
message: string;
23-
jobName?: string;
22+
uri?: string;
23+
message?: string;
2424
error?: string | unknown;
2525
}
2626

@@ -66,14 +66,12 @@ app.post(
6666

6767
const w3id = userId.id;
6868

69-
await provisionEVault(w3id, evaultId.id);
70-
const jobName = `evault-${w3id}`;
69+
const uri = await provisionEVault(w3id, evaultId.id);
7170

7271

7372
res.json({
7473
success: true,
75-
message: `Successfully provisioned evault for tenant ${w3id}`,
76-
jobName,
74+
uri,
7775
});
7876
} catch (error) {
7977
const axiosError = error as AxiosError;

infrastructure/evault-provisioner/src/templates/evault.nomad.ts

Lines changed: 52 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import sha256 from "sha256";
22
import * as k8s from '@kubernetes/client-node';
3+
import { execSync } from "child_process";
4+
import { json } from "express";
35

46
export function generatePassword(length = 16): string {
57
const chars =
@@ -87,24 +89,57 @@ export async function provisionEVault(w3id: string, eVaultId: string) {
8789

8890
await appsApi.createNamespacedDeployment({ body: deployment, namespace: namespaceName });
8991

90-
const serviceSpec = {
91-
metadata: { name: 'evault-service', namespace: namespaceName },
92-
spec: {
93-
type: 'NodePort',
94-
selector: { app: 'evault' },
95-
ports: [
96-
{
97-
port: 80,
98-
targetPort: containerPort,
99-
protocol: 'TCP'
100-
// No nodePort → let Kubernetes assign one dynamically
101-
}
102-
]
92+
await coreApi.createNamespacedService({
93+
namespace: namespaceName,
94+
body: {
95+
apiVersion: 'v1',
96+
kind: 'Service',
97+
metadata: { name: 'evault-service' },
98+
spec: {
99+
type: 'LoadBalancer',
100+
selector: { app: 'evault' },
101+
ports: [
102+
{
103+
port: 4000,
104+
targetPort: 4000
105+
}
106+
]
107+
}
103108
}
104-
};
109+
});
110+
111+
const svc = await coreApi.readNamespacedService({ name: 'evault-service', namespace: namespaceName });
112+
const spec = svc.spec;
113+
const status = svc.status;
105114

106-
await coreApi.createNamespacedService({ body: serviceSpec, namespace: namespaceName });
115+
// Check LoadBalancer first (cloud clusters)
116+
const ingress = status?.loadBalancer?.ingress?.[0];
117+
if (ingress?.ip || ingress?.hostname) {
118+
const host = ingress.ip || ingress.hostname;
119+
const port = spec?.ports?.[0]?.port;
120+
return `http://${host}:${port}`;
121+
}
122+
123+
// Fallback: NodePort + Node IP (local clusters or bare-metal)
124+
const nodePort = spec?.ports?.[0]?.nodePort;
125+
if (!nodePort) throw new Error('No LoadBalancer or NodePort found.');
126+
127+
// Try getting an external IP from the cluster nodes
128+
const nodes = await coreApi.listNode();
129+
console.log(JSON.stringify(nodes))
130+
const address = nodes?.items[0].status.addresses.find(
131+
(a) => a.type === 'ExternalIP' || a.type === 'InternalIP'
132+
)?.address;
107133

108-
const res = await coreApi.readNamespacedService({ name: 'evault-service', namespace: namespaceName });
109-
console.log(JSON.stringify(res))
134+
if (address) {
135+
return `http://${address}:${nodePort}`;
136+
}
137+
138+
// Local fallback: use minikube IP if available
139+
try {
140+
const minikubeIP = execSync('minikube ip').toString().trim();
141+
return `http://${minikubeIP}:${nodePort}`
142+
} catch (e) {
143+
throw new Error('Unable to determine service IP (no LoadBalancer, Node IP, or Minikube IP)');
144+
}
110145
}

0 commit comments

Comments
 (0)