Skip to content

Commit

Permalink
Merge pull request #47 from icon-community/feat/dive-exec
Browse files Browse the repository at this point in the history
feat: DIVE integration for enhanced sandbox management
  • Loading branch information
coconut-bunch authored Oct 14, 2023
2 parents 3f1e289 + 9bfa36c commit cf7954d
Show file tree
Hide file tree
Showing 14 changed files with 706 additions and 236 deletions.
407 changes: 324 additions & 83 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"@types/node": "^14.11.2",
"@types/prompts": "^2.0.14",
"@types/signale": "^1.4.4",
"@types/tar-fs": "^2.0.2",
"gts": "^3.1.1",
"pkg": "^5.8.0",
"prettier": "^2.8.0",
Expand Down Expand Up @@ -70,7 +71,8 @@
"prompts": "^2.4.2",
"shelljs": "^0.8.5",
"signale": "^1.4.0",
"tar": "^6.1.15"
"tar": "^6.1.15",
"tar-fs": "^3.0.4"
},
"npm": {
"versionArgs": [
Expand Down
1 change: 0 additions & 1 deletion src/compile/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export const mountAndCompile = (projectPath: string, args: any, cb: any) => {

mountAndRunCommandInContainer(
container,
projectPath,
args,
command,
cb,
Expand Down
108 changes: 103 additions & 5 deletions src/core/dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import * as zlib from 'zlib';
var tar = require('tar');
import signale from 'signale';

import { DROGON_CONFIG_FOLDER, KURTOSIS_RELEASES_VERSION, DIVE_RELEASES_VERSION, DIVE_CLI, DIVE_CLI_REPO, KURTOSIS_CLI, KURTOSIS_CLI_REPO } from '../constants';
import { DROGON_CONFIG_FOLDER, KURTOSIS_RELEASES_VERSION, DIVE_RELEASES_VERSION, DIVE_CLI, DIVE_CLI_REPO, KURTOSIS_CLI, KURTOSIS_CLI_REPO, DROGON_IMAGE } from '../constants';
import { getContainerIdsFromNamePattern, getDIVEContainerId, getKurtosisContainerIds, mountAndRunCommandInContainerAsync, runAContainerInBackground, stopContainerWithName } from '../helpers/docker';
import { getContainerNameForProject } from '../helpers';

async function downloadAndExtractLatestRelease(repo: string, toolName: string, version: string): Promise<void> {

Expand Down Expand Up @@ -42,7 +44,7 @@ async function downloadAndExtractLatestRelease(repo: string, toolName: string, v
signale.success(`Downloaded ${toolName}!`);
}

const ensureCLI =async (toolName: string, repo: string, version: string): Promise<void> => {
const ensureCLI = async (toolName: string, repo: string, version: string): Promise<void> => {
const result = shell.which(`${DROGON_CONFIG_FOLDER}/${toolName}`);

if (!result) {
Expand All @@ -52,15 +54,15 @@ const ensureCLI =async (toolName: string, repo: string, version: string): Promis
}

const ensureKurtosisCli = () => ensureCLI(KURTOSIS_CLI, KURTOSIS_CLI_REPO, KURTOSIS_RELEASES_VERSION);
const ensureDIVECli = () => ensureCLI(DIVE_CLI,DIVE_CLI_REPO ,DIVE_RELEASES_VERSION);
const ensureDIVECli = () => ensureCLI(DIVE_CLI, DIVE_CLI_REPO, DIVE_RELEASES_VERSION);

const ensureDrogonConfigFolder = async () => {
if (!fs.existsSync(DROGON_CONFIG_FOLDER)) {
fs.mkdirSync(DROGON_CONFIG_FOLDER);
}
}

const unzipTarGz = async(source: string, destination: string): Promise<void> => {
const unzipTarGz = async (source: string, destination: string): Promise<void> => {
return new Promise((resolve, reject) => {
fs.createReadStream(source)
.pipe(zlib.createGunzip())
Expand All @@ -70,8 +72,104 @@ const unzipTarGz = async(source: string, destination: string): Promise<void> =>
});
}

const ensureKurtosisStopped = async () => {
shell.exec(`${DROGON_CONFIG_FOLDER}/kurtosis engine clean`, { silent: true });
shell.exec(`${DROGON_CONFIG_FOLDER}/kurtosis engine stop`, { silent: true });
const kurtosis_containers = await getKurtosisContainerIds()
if(kurtosis_containers != null && kurtosis_containers.length > 0){
for(const container_id of kurtosis_containers){
await stopContainerWithName(container_id)
}
}
}
const ensureKurtosisRunning = () => {
shell.exec(`${DROGON_CONFIG_FOLDER}/kurtosis engine start`, { silent: true });
}
const ensureDiveStopped = async () => {
shell.exec(`${DROGON_CONFIG_FOLDER}/dive clean`, { silent: true });
const container_id = await getDIVEContainerId()
if (container_id != null) {
await stopContainerWithName(container_id)
}
}
const ensureDiveRunning = async () => {
const container_id = await getDIVEContainerId()
if(container_id == null){
shell.exec(`${DROGON_CONFIG_FOLDER}/dive chain icon`, { silent: false })
}
}
const ensureGradleInDIVEContainer = async () => {
const container_id = await getDIVEContainerId()
if (container_id == null) {
throw new Error("DIVE container not found");
}
const command = `mkdir -p /gradle && \
wget -O gradle-5.5.1-all.zip https://services.gradle.org/distributions/gradle-5.5.1-all.zip && \
unzip gradle-5.5.1-all.zip && \
mv gradle-5.5.1 /gradle`
try {
await mountAndRunCommandInContainerAsync(container_id, [], command, true);
} catch (error) {
console.error("Command failed with exit code:", error);
throw error
}

export { ensureKurtosisCli, ensureDIVECli, ensureDrogonConfigFolder, ensureKurtosisRunning };
}
const getGradeDaemeonContainerId = async (projectPath: string) => {
const container_name = getContainerNameForProject(
projectPath,
DROGON_IMAGE,
'drogon'
);
const container = await getContainerIdsFromNamePattern(container_name)
if (container == null || container.length == 0) {
return null
}
return container[0]
}
const ensureGradleDaemonIsRunning = async (projectPath: string, args:any) => {
const container = await getGradeDaemeonContainerId(projectPath)
if (container == null) {
await ensureGradleDaemon(projectPath, args)
}
}

const ensureGradleDaemon = async (projectPath: string, args: any) => {
const command = 'tail -f /dev/null';
await runAContainerInBackground(
projectPath,
DROGON_IMAGE,
args,
command,
'drogon'
)

}
const stopGradleDaemon = async (projectPath: string, args: any) => {
const container = await getGradeDaemeonContainerId(projectPath)
if (container == null) {
return
}
const command = 'gradle --stop';
signale.pending('Stopping Drogon daemon');
try {
await mountAndRunCommandInContainerAsync(container, [], command, true);
await stopContainerWithName(container);
} catch (error) {
console.error("Command failed with exit code:", error);
throw error
}
}
export {
ensureKurtosisCli,
ensureDIVECli,
ensureDiveRunning,
ensureDiveStopped,
ensureDrogonConfigFolder,
ensureKurtosisStopped,
ensureKurtosisRunning,
ensureGradleInDIVEContainer,
getGradeDaemeonContainerId,
ensureGradleDaemonIsRunning,
stopGradleDaemon
};
22 changes: 4 additions & 18 deletions src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
checkIfFileExists,
ensureCWDDrogonProject,
panic,
ProgressBar,
safeexit,
} from '../helpers';
import {
Expand All @@ -14,8 +13,8 @@ import {
mountAndRunCommand,
pullImage,
} from '../helpers/docker';
import { ensureKurtosisCli, ensureDIVECli, ensureDrogonConfigFolder } from './dependencies';
import {DROGON_CONFIG_FOLDER, DROGON_IMAGE, ICON_TEMPLATES_REPO} from '../constants';
import { ensureKurtosisCli, ensureDIVECli, ensureDrogonConfigFolder, ensureKurtosisRunning } from './dependencies';
import {DROGON_IMAGE, ICON_TEMPLATES_REPO} from '../constants';
import {mainBuildGradle, gradleSettings, gitignore} from './contents';
import {Config} from './config';
import {runTackle, scaffoldProject} from './scaffold';
Expand All @@ -34,28 +33,15 @@ export const install = async () => {
await ensureDrogonConfigFolder();
await ensureKurtosisCli();
await ensureDIVECli()
// await fetch_drogon();
await initializeKurtosis();
await fetch_drogon();
await ensureKurtosisRunning();
// await fetch_score_image();

// progressBar.stopWithMessage('Drogon ready for use.');
// signale.success('Drogon ready for use.');
// process.exit();
};

export const initializeKurtosis = async () => {
const command = `${DROGON_CONFIG_FOLDER}/kurtosis engine start`
signale.pending('Initializing Kurtosis');
shell.exec(command, {async:true}, (code: any) => {
if (code !== 0) {
signale.error('Failed to initialize Kurtosis');
}
else {
signale.success('Initialized Kurtosis');
}
})
}

export const fetch_drogon = async () => {
const localImage = await localDrogonImageId(DROGON_IMAGE);
if (localImage) {
Expand Down
92 changes: 77 additions & 15 deletions src/deploy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ import {
listOptmizedContracts,
panic,
} from '../helpers';
import {mountAndRunCommandInContainer} from '../helpers/docker';
import {getDIVEContainerId, mountAndRunCommandInContainer, dockerInit} from '../helpers/docker';
import {DROGON_IMAGE} from '../constants';
import Wallet from '../core/keystore';
import chalk from 'chalk';
var shell = require('shelljs');

export const deployContracts = async (
projectPath: string,
Expand Down Expand Up @@ -65,48 +66,109 @@ export const deployContracts = async (
);
console.log(`Loaded wallet ${chalk.green(wallet.getAddress())}`);

await wallet.showBalances();
// await wallet.showBalances();

signale.pending('Deploying contracts');

const container = getContainerNameForProject(
projectPath,
DROGON_IMAGE,
'drogon'
);
// const container = getContainerNameForProject(
// projectPath,
// DROGON_IMAGE,
// 'drogon'
// );

const docker = dockerInit();
const containerId = await getDIVEContainerId();

if (!containerId) {
signale.fatal('DIVE container not found');
process.exit(1);
}

console.log("Discovered DIVE container: " + containerId)
const container = docker.getContainer(containerId);

const projects = await listAvailableContracts(projectPath);
const optimized = await listOptmizedContracts(projectPath);

const keys = Object.keys(projects);
const numProjects = keys.length;

let tasks: any = {};

for (var i = 0; i < numProjects; i++) {
let project = keys[i];
mountAndRunCommandInContainer(
container,
args,
"mkdir -p /goloop/app",
async (exitCode: any, output: string) => {
if (exitCode) {
signale.fatal('Failed to deploy contracts');
process.exit(exitCode);
} else {
}
},
true,
"/goloop/"
);

let j = 0
for(var i in optimized) {
console.log("Deploying optimized contract: " + i)
const path = optimized[i]

// Copy the optimized contract from host to container
signale.pending(`Copying optimized contract ${path} to container`)

// path without file name
const basePath = path.substring(0, path.lastIndexOf("/"))
const fileName = path.substring(path.lastIndexOf("/")+1)

console.log("Copying file " + fileName + " to /goloop/app/" + fileName)
console.log("Creating directory " + basePath)
let mkdir = `mkdir -p /goloop/app/${basePath}`

mountAndRunCommandInContainer(
container,
args,
mkdir,
async (exitCode: any, output: string) => {
if (exitCode) {
signale.fatal('Failed to deploy contracts');
process.exit(exitCode);
}
},
true
);

const basePath2 = path.split("/").slice(0, 2).join("/") + "/";

shell.exec(`docker cp ${projectPath}/${path} ${containerId}:/goloop/app/${path}`, { silent: false })
shell.exec(`docker cp ${projectPath}/${basePath2}/build.gradle ${containerId}:/goloop/app/${basePath2}/build.gradle`, { silent: false })
shell.exec(`docker cp ${projectPath}/build.gradle ${containerId}:/goloop/app/build.gradle`, { silent: false })
shell.exec(`docker cp ${projectPath}/settings.gradle ${containerId}:/goloop/app/settings.gradle`, { silent: false })

let command = `gradle src:${project}:${destination} -PkeystoreName=/goloop/app/${keystoreFile}`;
// Deploy the contract
let initialWalletBalance = 0
let project = keys[j];
j = j + 1
let command = `/gradle/gradle-5.5.1/bin/gradle src:${project}:${destination} -PkeystoreName=/goloop/app/${keystoreFile}`;

if (password) {
command += ` -PkeystorePass=${password}`;
}

let initialWalletBalance = await wallet.getBalance();

mountAndRunCommandInContainer(
container,
projectPath,
args,
command,
async (exitCode: any, output: string) => {
if (exitCode) {
signale.fatal('Failed to deploy contracts');
process.exit(exitCode);
} else {
signale.success(`Done deploying ${project} contract`);
signale.success(`Done deploying ${i} contract`);

let currentBalance = await wallet.getBalance();
tasks[project] = {
tasks[i] = {
current: currentBalance,
initial: initialWalletBalance,
};
Expand Down
1 change: 0 additions & 1 deletion src/deploy/optimize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ export const mountAndOptimize = (
);
mountAndRunCommandInContainer(
container,
projectPath,
args,
command,
cb,
Expand Down
1 change: 0 additions & 1 deletion src/goloop/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ export const runGoloopCmd = async (projectPath: any, command: any, cb: any) => {

await mountAndRunCommandInContainer(
container,
'/goloop/app',
[],
command,
(exitCode: any, output: string) => {
Expand Down
Loading

0 comments on commit cf7954d

Please sign in to comment.