Skip to content

Commit

Permalink
fix: do checksum check after downloading platform zip file (#125)
Browse files Browse the repository at this point in the history
Signed-off-by: Lenin Mehedy <[email protected]>
  • Loading branch information
leninmehedy authored Mar 6, 2024
1 parent 8fd976b commit 3d91617
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 69 deletions.
16 changes: 0 additions & 16 deletions resources/extract-jar.sh

This file was deleted.

39 changes: 39 additions & 0 deletions resources/extract-platform.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#!/bin/bash
# This script fetch the build.zip file and checksum file from builds.hedera.com and then extract it into HapiApp2 directory
# Usage extract-platform <release-version>
# e.g. extract-platform v0.42.5

readonly tag="${1}"
if [ -z "${tag}" ]; then
echo "Release tag is required (e.g. v0.42.5)";
exit 1
fi

readonly HAPI_DIR=/opt/hgcapp/services-hedera/HapiApp2.0
readonly HEDERA_USER_HOME_DIR=/home/hedera
readonly HEDERA_BUILDS_URL='https://builds.hedera.com'
readonly RELEASE_DIR="$(awk -F'.' '{print $1"."$2}' <<< "${tag}")"
readonly BUILD_ZIP_FILE="${HEDERA_USER_HOME_DIR}/build-${tag}.zip"
readonly BUILD_ZIP_URL="${HEDERA_BUILDS_URL}/node/software/${RELEASE_DIR}/build-${tag}.zip"
readonly CHECKSUM_FILE="${HEDERA_USER_HOME_DIR}/build-${tag}.sha384"
readonly CHECKSUM_URL="${HEDERA_BUILDS_URL}/node/software/${RELEASE_DIR}/build-${tag}.sha384"

# download
echo "Downloading ${BUILD_ZIP_URL}"
[ -f "${BUILD_ZIP_FILE}" ] || curl -sSf "${BUILD_ZIP_URL}" -o "${BUILD_ZIP_FILE}"
[ $? == 0 ] || exit 1
echo "Downloading ${CHECKSUM_URL}"
[ -f "${CHECKSUM_FILE}" ] || curl -sSf "${CHECKSUM_URL}" -o "${CHECKSUM_FILE}"
[ $? == 0 ] || exit 1
readonly sum="$(openssl dgst -sha384 "${BUILD_ZIP_FILE}" | awk '{print $2}')"
readonly expected_sum="$(awk '{print $1}' < "${CHECKSUM_FILE}")"
if [ "${sum}" != "${expected_sum}" ]; then
echo "SHA sum of ${BUILD_ZIP_FILE} does not match. Aborting."
exit 1
fi

# extract
echo "Extracting ${BUILD_ZIP_FILE}"
[[ -d "${HAPI_DIR}" ]] || mkdir -p "${HAPI_DIR}"
cd "${HAPI_DIR}" && jar xvf "${BUILD_ZIP_FILE}"
[ $? == 0 ] || exit 1
2 changes: 1 addition & 1 deletion src/commands/node.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ export class NodeCommand extends BaseCommand {

// set up the sub-tasks
return task.newListr(subTasks, {
concurrent: false, // parallel uploading of the zip file seems to be unreliable, so we just upload in sequence
concurrent: true, // since we download in the container directly, we want this to be in parallel across all nodes
rendererOptions: {
collapseSubtasks: false
}
Expand Down
8 changes: 6 additions & 2 deletions src/core/k8.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import net from 'net'
import os from 'os'
import path from 'path'
import { flags } from '../commands/index.mjs'
import { FullstackTestingError, MissingArgumentError } from './errors.mjs'
import { FullstackTestingError, IllegalArgumentError, MissingArgumentError } from './errors.mjs'
import * as sb from 'stream-buffers'
import * as tar from 'tar'
import { v4 as uuid4 } from 'uuid'
Expand Down Expand Up @@ -472,7 +472,10 @@ export class K8 {

// zip the source file
const tmpFile = this._tempFileFor(srcFile)
await tar.c({ file: tmpFile, cwd: srcDir }, [srcFile])
await tar.c({
file: tmpFile,
cwd: srcDir
}, [srcFile])

const self = this
return new Promise((resolve, reject) => {
Expand Down Expand Up @@ -614,6 +617,7 @@ export class K8 {
if (!Array.isArray(command)) {
command = command.split(' ')
}
if (!await this.getPodByName(podName)) throw new IllegalArgumentError(`Invalid pod ${podName}`)

const self = this
return new Promise((resolve, reject) => {
Expand Down
40 changes: 7 additions & 33 deletions src/core/platform_installer.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -100,50 +100,24 @@ export class PlatformInstaller {
}

/**
* Fetch platform code into the container
*
* It uses curl to fetch the platform code directly inside the /home/hedera directory.
*
* Fetch and extract platform code into the container
* @param podName pod name
* @param tag platform release tag
* @return {Promise<boolean|undefined>}
*/

async fetchPlatform (podName, tag) {
if (!podName) throw new MissingArgumentError('podName is required')
if (!tag) throw new MissingArgumentError('tag is required')

try {
const releaseDir = Templates.prepareReleasePrefix(tag)
const packageURL = `${constants.HEDERA_BUILDS_URL}/node/software/${releaseDir}/build-${tag}.zip`
const buildZip = path.join(constants.HEDERA_USER_HOME_DIR, `build-${tag}.zip`)
await this.k8.execContainer(podName, constants.ROOT_CONTAINER, `curl -s ${packageURL} -o ${buildZip}`)
return this.extractPlatform(podName, buildZip)
} catch (e) {
throw new FullstackTestingError(`failed to copy platform code in to pod '${podName}': ${e.message}`, e)
}
}
const scriptName = 'extract-platform.sh'
const sourcePath = path.join(constants.RESOURCES_DIR, scriptName) // script source path
await this.copyFiles(podName, [sourcePath], constants.HEDERA_USER_HOME_DIR)

async extractPlatform (podName, buildZipSrc) {
if (!podName) throw new MissingArgumentError('podName is required')
if (!buildZipSrc) throw new MissingArgumentError('buildZipSrc is required')

const buildZipFileName = path.basename(buildZipSrc)
const buildZip = path.join(constants.HEDERA_USER_HOME_DIR, buildZipFileName) // inside the container
const extractScriptName = 'extract-jar.sh'
const extractScriptSrc = path.join(constants.RESOURCES_DIR, extractScriptName)
const extractScript = path.join(constants.HEDERA_USER_HOME_DIR, extractScriptName) // inside the container

this.logger.debug(`Extracting platform code in pod ${podName}`, {
extractScript,
buildZip,
dest: constants.HEDERA_HAPI_PATH
})

try {
await this.copyFiles(podName, [extractScriptSrc], constants.HEDERA_USER_HOME_DIR)
const extractScript = path.join(constants.HEDERA_USER_HOME_DIR, scriptName) // inside the container
await this.k8.execContainer(podName, constants.ROOT_CONTAINER, `chmod +x ${extractScript}`)
await this.k8.execContainer(podName, constants.ROOT_CONTAINER, [extractScript, buildZip, constants.HEDERA_HAPI_PATH])

await this.k8.execContainer(podName, constants.ROOT_CONTAINER, [extractScript, tag])
return true
} catch (e) {
throw new FullstackTestingError(`failed to extract platform code in this pod '${podName}': ${e.message}`, e)
Expand Down
42 changes: 25 additions & 17 deletions test/e2e/core/platform_installer_e2e.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
*/
import { beforeAll, describe, expect, it } from '@jest/globals'
import {
PackageDownloader,
PlatformInstaller,
constants,
Templates,
Expand All @@ -33,7 +32,6 @@ describe('PackageInstallerE2E', () => {
const configManager = new ConfigManager(testLogger)
const k8 = new K8(configManager, testLogger)
const installer = new PlatformInstaller(testLogger, k8)
const downloader = new PackageDownloader(testLogger)
const testCacheDir = getTestCacheDir()
const podName = 'network-node0-0'
const packageVersion = 'v0.42.5'
Expand All @@ -58,28 +56,38 @@ describe('PackageInstallerE2E', () => {
})
})

describe('copyPlatform', () => {
it('should succeed fetching platform release', async () => {
const releasePrefix = Templates.prepareReleasePrefix(packageVersion)
const destPath = `${testCacheDir}/${releasePrefix}/build-${packageVersion}.zip`
await expect(downloader.fetchPlatform(packageVersion, testCacheDir)).resolves.toBe(destPath)
expect(fs.existsSync(destPath)).toBeTruthy()
testLogger.showUser(destPath)
describe('fetchPlatform', () => {
it('should fail with invalid pod', async () => {
expect.assertions(2)
try {
await installer.fetchPlatform('', packageVersion)
} catch (e) {
expect(e.message.includes('podName is required')).toBeTruthy()
}

// do not delete the cache dir
}, 200000)
try {
await installer.fetchPlatform('INVALID', packageVersion)
} catch (e) {
expect(e.message
.includes('failed to extract platform code in this pod'))
.toBeTruthy()
}
}, 20000)

it('should succeed with valid tag and pod', async () => {
it('should fail with invalid tag', async () => {
expect.assertions(1)
try {
await expect(installer.fetchPlatform(podName, packageVersion)).resolves.toBeTruthy()
const outputs = await k8.execContainer(podName, constants.ROOT_CONTAINER, `ls -la ${constants.HEDERA_HAPI_PATH}`)
testLogger.showUser(outputs)
await installer.fetchPlatform(podName, 'INVALID')
} catch (e) {
console.error(e)
expect(e).toBeNull()
expect(e.message.includes('curl: (22) The requested URL returned error: 404')).toBeTruthy()
}
}, 20000)

it('should succeed with valid tag and pod', async () => {
await expect(installer.fetchPlatform(podName, packageVersion)).resolves.toBeTruthy()
const outputs = await k8.execContainer(podName, constants.ROOT_CONTAINER, `ls -la ${constants.HEDERA_HAPI_PATH}`)
testLogger.showUser(outputs)
}, 60000)
})

describe('prepareConfigTxt', () => {
Expand Down

0 comments on commit 3d91617

Please sign in to comment.