Skip to content

Commit

Permalink
add casperlabs automated test using jest
Browse files Browse the repository at this point in the history
  • Loading branch information
A-Harby committed May 27, 2024
1 parent 51f43a7 commit 80a5397
Showing 1 changed file with 267 additions and 0 deletions.
267 changes: 267 additions & 0 deletions packages/grid_client/tests/modules/applications/casperlabs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
import axios from "axios";
import { setTimeout } from "timers/promises";

import { FilterOptions, GatewayNameModel, generateString, GridClient, MachinesModel, randomChoice } from "../../../src";
import { config, getClient } from "../../client_loader";
import { bytesToGB, generateInt, getOnlineNode, log, splitIP } from "../../utils";

jest.setTimeout(300000);

let gridClient: GridClient;
let deploymentName: string;

beforeAll(async () => {
gridClient = await getClient();
deploymentName = generateString(15);
gridClient.clientOptions.projectName = `casperlabs/${deploymentName}`;
gridClient._connect();
return gridClient;
});

//Private IP Regex
const ipRegex = /(^127\.)|(^10\.)|(^172\.1[6-9]\.)|(^172\.2[0-9]\.)|(^172\.3[0-1]\.)|(^192\.168\.)/;

test("TC2683 - Applications: Deploy Casperlabs", async () => {
/**********************************************
Test Suite: Grid3_Client_TS (Automated)
Test Cases: TC2683 - Applications: Deploy Casperlabs
Scenario:
- Generate Test Data/casperlabs Config/Gateway Config.
- Select a Node To Deploy the casperlabs on.
- Select a Gateway Node To Deploy the gateway on.
- Deploy the casperlabs solution.
- Assert that the generated data matches
the deployment details.
- Pass the IP of the Created casperlabs to the Gateway
Config.
- Deploy the Gateway.
- Assert that the generated data matches
the deployment details.
- Assert that the Gateway points at the IP
of the created casperlabs.
- Assert that the returned domain is working
and returns correct data.
**********************************************/

//Test Data
const name = "gw" + generateString(10).toLowerCase();
const tlsPassthrough = false;
let cpu = generateInt(1, 4);
let memory = generateInt(1, 6);
let rootfsSize = generateInt(0, 2);
let diskSize = generateInt(1, 20);
const networkName = generateString(15);
const vmName = generateString(15);
const diskName = generateString(15);
const mountPoint = "/data";
const publicIp = false;
const ipRangeClassA = "10." + generateInt(1, 255) + ".0.0/16";
const ipRangeClassB = "172." + generateInt(16, 31) + ".0.0/16";
const ipRangeClassC = "192.168.0.0/16";
const ipRange = randomChoice([ipRangeClassA, ipRangeClassB, ipRangeClassC]);
const metadata = "{'deploymentType': 'casperlabs'}";
const description = "test deploying Casperlabs via ts grid3 client";

//GatewayNode Selection
const gatewayNodes = await gridClient.capacity.filterNodes({
gateway: true,
farmId: 1,
availableFor: await gridClient.twins.get_my_twin_id(),
} as FilterOptions);
if (gatewayNodes.length == 0) throw new Error("no nodes available to complete this test");
const GatewayNode = gatewayNodes[generateInt(0, gatewayNodes.length - 1)];

//Node Selection
let nodes;
try {
nodes = await gridClient.capacity.filterNodes({
cru: cpu,
mru: memory,
sru: rootfsSize + diskSize,
farmId: 1,
availableFor: await gridClient.twins.get_my_twin_id(),
} as FilterOptions);
} catch (error) {
//Log the resources that were not found.
log("A Node was not found with the generated resources." + error);
log("Regenerating test data with lower resources....");

//Generate lower resources.
cpu = generateInt(1, cpu);
memory = generateInt(1, memory);
rootfsSize = generateInt(2, rootfsSize);
diskSize = generateInt(1, diskSize);

//Search for another node with lower resources.
nodes = await gridClient.capacity.filterNodes({
cru: cpu,
mru: memory,
sru: rootfsSize + diskSize,
farmId: 1,
availableFor: await gridClient.twins.get_my_twin_id(),
} as FilterOptions);
}
const nodeId = await getOnlineNode(nodes);
if (nodeId == -1) throw new Error("no nodes available to complete this test");
const domain = name + "." + GatewayNode.publicConfig.domain;

//VM Model
const vms: MachinesModel = {
name: deploymentName,
network: {
name: networkName,
ip_range: ipRange,
},
machines: [
{
name: vmName,
node_id: nodeId,
cpu: cpu,
memory: 1024 * memory,
rootfs_size: rootfsSize,
disks: [
{
name: diskName,
size: diskSize,
mountpoint: mountPoint,
},
],
flist: "https://hub.grid.tf/tf-official-apps/casperlabs-latest.flist",
entrypoint: "/sbin/zinit init",
public_ip: publicIp,
planetary: true,
mycelium: false,
env: {
SSH_KEY: config.ssh_key,
CASPERLABS_HOSTNAME: domain,
},
},
],
metadata: metadata,
description: description,
};
const res = await gridClient.machines.deploy(vms);
log(res);

//Contracts Assertions
expect(res.contracts.created).toHaveLength(1);
expect(res.contracts.updated).toHaveLength(0);
expect(res.contracts.deleted).toHaveLength(0);

const vmsList = await gridClient.machines.list();
log(vmsList);

//VM List Assertions
expect(vmsList.length).toBeGreaterThanOrEqual(1);
expect(vmsList).toContain(vms.name);

const result = await gridClient.machines.getObj(vms.name);
log(result);

//VM Assertions
expect(result[0].nodeId).toBe(nodeId);
expect(result[0].status).toBe("ok");
expect(result[0].flist).toBe(vms.machines[0].flist);
expect(result[0].entrypoint).toBe(vms.machines[0].entrypoint);
expect(result[0].mounts).toHaveLength(1);
expect(result[0].interfaces[0]["network"]).toBe(vms.network.name);
expect(result[0].interfaces[0]["ip"]).toContain(splitIP(vms.network.ip_range));
expect(result[0].interfaces[0]["ip"]).toMatch(ipRegex);
expect(result[0].capacity["cpu"]).toBe(cpu);
expect(result[0].capacity["memory"]).toBe(memory * 1024);
expect(result[0].planetary).toBeDefined();
expect(result[0].publicIP).toBeNull();
expect(result[0].description).toBe(description);
expect(result[0].mounts[0]["name"]).toBe(diskName);
expect(result[0].mounts[0]["size"]).toBe(bytesToGB(diskSize));
expect(result[0].mounts[0]["mountPoint"]).toBe(mountPoint);
expect(result[0].mounts[0]["state"]).toBe("ok");

const backends = ["http://[" + result[0].planetary + "]:80"];
log(backends);

//Name Gateway Model
const gw: GatewayNameModel = {
name: name,
node_id: GatewayNode.nodeId,
tls_passthrough: tlsPassthrough,
backends: backends,
};

const gatewayRes = await gridClient.gateway.deploy_name(gw);
log(gatewayRes);

//Contracts Assertions
expect(gatewayRes.contracts.created).toHaveLength(1);
expect(gatewayRes.contracts.updated).toHaveLength(0);
expect(gatewayRes.contracts.deleted).toHaveLength(0);
expect(gatewayRes.contracts.created[0].contractType.nodeContract.nodeId).toBe(GatewayNode.nodeId);

const gatewayResult = await gridClient.gateway.getObj(gw.name);
log(gatewayResult);

//Gateway Assertions
expect(gatewayResult[0].name).toBe(name);
expect(gatewayResult[0].status).toBe("ok");
expect(gatewayResult[0].type).toContain("name");
expect(gatewayResult[0].domain).toContain(name);
expect(gatewayResult[0].tls_passthrough).toBe(tlsPassthrough);
expect(gatewayResult[0].backends).toStrictEqual(backends);

const site = "https://" + gatewayResult[0].domain;
let reachable = false;

for (let i = 0; i < 3000; i++) {
axios
.get(site)
.then(() => {
log("gateway is reachable");
reachable = true;
})
.catch(() => {
log("gateway is not reachable");
});
if (reachable) {
break;
}
const wait = await setTimeout(5000, "Waiting for gateway to be ready");
log(wait);
}

if (reachable) {
axios.get(site).then(res => {
log(res.status);
log(res.statusText);
log(res.data);
expect(res.status).toBe(200);
expect(res.statusText).toBe("OK");
expect(res.data).toContain("Your Casper node is now running succesfully on the ThreeFold Grid.");
});
} else {
throw new Error("Gateway is unreachable after multiple retries");
}
});

afterEach(async () => {
const vmNames = await gridClient.machines.list();
for (const name of vmNames) {
const res = await gridClient.machines.delete({ name });
log(res);
expect(res.created).toHaveLength(0);
expect(res.updated).toHaveLength(0);
expect(res.deleted).toBeDefined();
}

const gwNames = await gridClient.gateway.list();
for (const name of gwNames) {
const res = await gridClient.gateway.delete_name({ name });
log(res);
expect(res.created).toHaveLength(0);
expect(res.updated).toHaveLength(0);
expect(res.deleted).toBeDefined();
}
});

afterAll(async () => {
return await gridClient.disconnect();
}, 130000);

0 comments on commit 80a5397

Please sign in to comment.