@miosa/sdk 1.2.3 → 1.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +41 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/resources/deployments.test.ts +73 -0
- package/src/resources/deployments.ts +58 -5
package/package.json
CHANGED
|
@@ -72,6 +72,12 @@ describe("Deployments", () => {
|
|
|
72
72
|
metadata: {
|
|
73
73
|
deployment_product: "docker_deploy",
|
|
74
74
|
runtime: { ip: "172.16.74.246", port: 23906 },
|
|
75
|
+
docker_deploy: {
|
|
76
|
+
app_id: "miosa-clinic-intake",
|
|
77
|
+
container_id: "container_123",
|
|
78
|
+
status: "running",
|
|
79
|
+
url: "http://127.0.0.1:23906",
|
|
80
|
+
},
|
|
75
81
|
},
|
|
76
82
|
},
|
|
77
83
|
};
|
|
@@ -114,8 +120,75 @@ describe("Deployments", () => {
|
|
|
114
120
|
"deployment_product",
|
|
115
121
|
"docker_deploy_host_id",
|
|
116
122
|
"docker_deploy_host_health",
|
|
123
|
+
"docker_deploy_app",
|
|
117
124
|
"runtime_route",
|
|
118
125
|
"public_url_probe",
|
|
119
126
|
]);
|
|
120
127
|
});
|
|
128
|
+
|
|
129
|
+
it("doctorDockerDeploy fails when route metadata does not point at the Docker container port", async () => {
|
|
130
|
+
mockGet.mockImplementation(async (path: string) => {
|
|
131
|
+
if (path === "/deployments/dep_123") {
|
|
132
|
+
return {
|
|
133
|
+
data: {
|
|
134
|
+
id: "dep_123",
|
|
135
|
+
tenant_id: "ten_123",
|
|
136
|
+
name: "Clinic Intake",
|
|
137
|
+
slug: "clinic-intake",
|
|
138
|
+
state: "running",
|
|
139
|
+
deployment_product: "docker_deploy",
|
|
140
|
+
docker_deploy_host_id: "ddh_123",
|
|
141
|
+
public_url: "https://clinic-intake.osa.miosa.app",
|
|
142
|
+
metadata: {
|
|
143
|
+
deployment_product: "docker_deploy",
|
|
144
|
+
runtime: { ip: "172.16.74.246", port: 8080 },
|
|
145
|
+
docker_deploy: {
|
|
146
|
+
app_id: "miosa-clinic-intake",
|
|
147
|
+
container_id: "container_123",
|
|
148
|
+
status: "running",
|
|
149
|
+
url: "http://127.0.0.1:23906",
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
},
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
if (path === "/docker-deploy/hosts/ddh_123") {
|
|
157
|
+
return {
|
|
158
|
+
data: {
|
|
159
|
+
id: "ddh_123",
|
|
160
|
+
tenant_id: "ten_123",
|
|
161
|
+
workspace_id: "ws_123",
|
|
162
|
+
status: "active",
|
|
163
|
+
size: "medium",
|
|
164
|
+
region: "us",
|
|
165
|
+
appliance_status: "healthy",
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
throw new Error(`unexpected path ${path}`);
|
|
171
|
+
});
|
|
172
|
+
vi.stubGlobal(
|
|
173
|
+
"fetch",
|
|
174
|
+
vi.fn().mockResolvedValue({ ok: true, status: 200 }),
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
const result = await new Deployments(makeHttp()).doctorDockerDeploy(
|
|
178
|
+
"dep_123",
|
|
179
|
+
{ probePath: "/health" },
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
expect(result.ok).toBe(false);
|
|
183
|
+
expect(result.checks).toEqual(
|
|
184
|
+
expect.arrayContaining([
|
|
185
|
+
expect.objectContaining({
|
|
186
|
+
name: "runtime_route",
|
|
187
|
+
ok: false,
|
|
188
|
+
message:
|
|
189
|
+
"Deployment route port 8080 does not match Docker container host port 23906.",
|
|
190
|
+
}),
|
|
191
|
+
]),
|
|
192
|
+
);
|
|
193
|
+
});
|
|
121
194
|
});
|
|
@@ -481,6 +481,25 @@ function dockerDeployHostId(deployment: DeploymentData): string | null {
|
|
|
481
481
|
);
|
|
482
482
|
}
|
|
483
483
|
|
|
484
|
+
function dockerDeployApp(deployment: DeploymentData): Record<string, unknown> | null {
|
|
485
|
+
const app = deployment.metadata?.["docker_deploy"];
|
|
486
|
+
if (!app || typeof app !== "object" || Array.isArray(app)) return null;
|
|
487
|
+
return app as Record<string, unknown>;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
function dockerDeployAppPort(app: Record<string, unknown> | null): number | null {
|
|
491
|
+
const url = app?.["url"];
|
|
492
|
+
if (typeof url !== "string") return null;
|
|
493
|
+
|
|
494
|
+
try {
|
|
495
|
+
const parsed = new URL(url);
|
|
496
|
+
const port = Number.parseInt(parsed.port, 10);
|
|
497
|
+
return Number.isInteger(port) ? port : null;
|
|
498
|
+
} catch {
|
|
499
|
+
return null;
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
|
|
484
503
|
function addDoctorCheck(
|
|
485
504
|
checks: DockerDeployDoctorCheck[],
|
|
486
505
|
name: string,
|
|
@@ -787,21 +806,55 @@ export class Deployments {
|
|
|
787
806
|
}
|
|
788
807
|
}
|
|
789
808
|
|
|
809
|
+
const app = dockerDeployApp(deployment);
|
|
810
|
+
const appPort = dockerDeployAppPort(app);
|
|
811
|
+
const appRunning = app?.["status"] === "running" && appPort !== null;
|
|
812
|
+
addDoctorCheck(
|
|
813
|
+
checks,
|
|
814
|
+
"docker_deploy_app",
|
|
815
|
+
appRunning,
|
|
816
|
+
appRunning
|
|
817
|
+
? "Docker Deploy app metadata points at a running container."
|
|
818
|
+
: "Deployment is missing running Docker Deploy app metadata.",
|
|
819
|
+
app
|
|
820
|
+
? {
|
|
821
|
+
app_id: app["app_id"],
|
|
822
|
+
container_id: app["container_id"],
|
|
823
|
+
status: app["status"],
|
|
824
|
+
url: app["url"],
|
|
825
|
+
expected_port: appPort,
|
|
826
|
+
}
|
|
827
|
+
: undefined,
|
|
828
|
+
);
|
|
829
|
+
|
|
790
830
|
const runtime = metadata["runtime"];
|
|
791
831
|
const hasRuntimeRoute =
|
|
792
832
|
typeof runtime === "object" &&
|
|
793
833
|
runtime !== null &&
|
|
794
834
|
typeof (runtime as Record<string, unknown>)["ip"] === "string" &&
|
|
795
835
|
typeof (runtime as Record<string, unknown>)["port"] === "number";
|
|
836
|
+
const runtimeRecord =
|
|
837
|
+
hasRuntimeRoute && typeof runtime === "object"
|
|
838
|
+
? (runtime as Record<string, unknown>)
|
|
839
|
+
: undefined;
|
|
840
|
+
const routeMatchesContainerPort =
|
|
841
|
+
hasRuntimeRoute &&
|
|
842
|
+
(appPort === null || runtimeRecord?.["port"] === appPort);
|
|
796
843
|
addDoctorCheck(
|
|
797
844
|
checks,
|
|
798
845
|
"runtime_route",
|
|
799
|
-
hasRuntimeRoute,
|
|
800
|
-
hasRuntimeRoute
|
|
801
|
-
? "Deployment
|
|
846
|
+
hasRuntimeRoute && routeMatchesContainerPort,
|
|
847
|
+
hasRuntimeRoute && routeMatchesContainerPort
|
|
848
|
+
? "Deployment route points at the Docker container host port."
|
|
849
|
+
: hasRuntimeRoute && appPort !== null
|
|
850
|
+
? `Deployment route port ${String(runtimeRecord?.["port"])} does not match Docker container host port ${appPort}.`
|
|
802
851
|
: "Deployment is missing appliance runtime route metadata.",
|
|
803
|
-
|
|
804
|
-
?
|
|
852
|
+
runtimeRecord
|
|
853
|
+
? {
|
|
854
|
+
...runtimeRecord,
|
|
855
|
+
expected_port: appPort,
|
|
856
|
+
docker_deploy_url: app?.["url"],
|
|
857
|
+
}
|
|
805
858
|
: undefined,
|
|
806
859
|
);
|
|
807
860
|
|