Skip to content

Commit 3d91617

Browse files
authored
fix: do checksum check after downloading platform zip file (#125)
Signed-off-by: Lenin Mehedy <[email protected]>
1 parent 8fd976b commit 3d91617

File tree

6 files changed

+78
-69
lines changed

6 files changed

+78
-69
lines changed

resources/extract-jar.sh

Lines changed: 0 additions & 16 deletions
This file was deleted.

resources/extract-platform.sh

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/bash
2+
# This script fetch the build.zip file and checksum file from builds.hedera.com and then extract it into HapiApp2 directory
3+
# Usage extract-platform <release-version>
4+
# e.g. extract-platform v0.42.5
5+
6+
readonly tag="${1}"
7+
if [ -z "${tag}" ]; then
8+
echo "Release tag is required (e.g. v0.42.5)";
9+
exit 1
10+
fi
11+
12+
readonly HAPI_DIR=/opt/hgcapp/services-hedera/HapiApp2.0
13+
readonly HEDERA_USER_HOME_DIR=/home/hedera
14+
readonly HEDERA_BUILDS_URL='https://builds.hedera.com'
15+
readonly RELEASE_DIR="$(awk -F'.' '{print $1"."$2}' <<< "${tag}")"
16+
readonly BUILD_ZIP_FILE="${HEDERA_USER_HOME_DIR}/build-${tag}.zip"
17+
readonly BUILD_ZIP_URL="${HEDERA_BUILDS_URL}/node/software/${RELEASE_DIR}/build-${tag}.zip"
18+
readonly CHECKSUM_FILE="${HEDERA_USER_HOME_DIR}/build-${tag}.sha384"
19+
readonly CHECKSUM_URL="${HEDERA_BUILDS_URL}/node/software/${RELEASE_DIR}/build-${tag}.sha384"
20+
21+
# download
22+
echo "Downloading ${BUILD_ZIP_URL}"
23+
[ -f "${BUILD_ZIP_FILE}" ] || curl -sSf "${BUILD_ZIP_URL}" -o "${BUILD_ZIP_FILE}"
24+
[ $? == 0 ] || exit 1
25+
echo "Downloading ${CHECKSUM_URL}"
26+
[ -f "${CHECKSUM_FILE}" ] || curl -sSf "${CHECKSUM_URL}" -o "${CHECKSUM_FILE}"
27+
[ $? == 0 ] || exit 1
28+
readonly sum="$(openssl dgst -sha384 "${BUILD_ZIP_FILE}" | awk '{print $2}')"
29+
readonly expected_sum="$(awk '{print $1}' < "${CHECKSUM_FILE}")"
30+
if [ "${sum}" != "${expected_sum}" ]; then
31+
echo "SHA sum of ${BUILD_ZIP_FILE} does not match. Aborting."
32+
exit 1
33+
fi
34+
35+
# extract
36+
echo "Extracting ${BUILD_ZIP_FILE}"
37+
[[ -d "${HAPI_DIR}" ]] || mkdir -p "${HAPI_DIR}"
38+
cd "${HAPI_DIR}" && jar xvf "${BUILD_ZIP_FILE}"
39+
[ $? == 0 ] || exit 1

src/commands/node.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ export class NodeCommand extends BaseCommand {
357357

358358
// set up the sub-tasks
359359
return task.newListr(subTasks, {
360-
concurrent: false, // parallel uploading of the zip file seems to be unreliable, so we just upload in sequence
360+
concurrent: true, // since we download in the container directly, we want this to be in parallel across all nodes
361361
rendererOptions: {
362362
collapseSubtasks: false
363363
}

src/core/k8.mjs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import net from 'net'
2020
import os from 'os'
2121
import path from 'path'
2222
import { flags } from '../commands/index.mjs'
23-
import { FullstackTestingError, MissingArgumentError } from './errors.mjs'
23+
import { FullstackTestingError, IllegalArgumentError, MissingArgumentError } from './errors.mjs'
2424
import * as sb from 'stream-buffers'
2525
import * as tar from 'tar'
2626
import { v4 as uuid4 } from 'uuid'
@@ -472,7 +472,10 @@ export class K8 {
472472

473473
// zip the source file
474474
const tmpFile = this._tempFileFor(srcFile)
475-
await tar.c({ file: tmpFile, cwd: srcDir }, [srcFile])
475+
await tar.c({
476+
file: tmpFile,
477+
cwd: srcDir
478+
}, [srcFile])
476479

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

618622
const self = this
619623
return new Promise((resolve, reject) => {

src/core/platform_installer.mjs

Lines changed: 7 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -100,50 +100,24 @@ export class PlatformInstaller {
100100
}
101101

102102
/**
103-
* Fetch platform code into the container
104-
*
105-
* It uses curl to fetch the platform code directly inside the /home/hedera directory.
106-
*
103+
* Fetch and extract platform code into the container
107104
* @param podName pod name
108105
* @param tag platform release tag
109106
* @return {Promise<boolean|undefined>}
110107
*/
108+
111109
async fetchPlatform (podName, tag) {
112110
if (!podName) throw new MissingArgumentError('podName is required')
113111
if (!tag) throw new MissingArgumentError('tag is required')
114112

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

126-
async extractPlatform (podName, buildZipSrc) {
127-
if (!podName) throw new MissingArgumentError('podName is required')
128-
if (!buildZipSrc) throw new MissingArgumentError('buildZipSrc is required')
129-
130-
const buildZipFileName = path.basename(buildZipSrc)
131-
const buildZip = path.join(constants.HEDERA_USER_HOME_DIR, buildZipFileName) // inside the container
132-
const extractScriptName = 'extract-jar.sh'
133-
const extractScriptSrc = path.join(constants.RESOURCES_DIR, extractScriptName)
134-
const extractScript = path.join(constants.HEDERA_USER_HOME_DIR, extractScriptName) // inside the container
135-
136-
this.logger.debug(`Extracting platform code in pod ${podName}`, {
137-
extractScript,
138-
buildZip,
139-
dest: constants.HEDERA_HAPI_PATH
140-
})
141-
142-
try {
143-
await this.copyFiles(podName, [extractScriptSrc], constants.HEDERA_USER_HOME_DIR)
118+
const extractScript = path.join(constants.HEDERA_USER_HOME_DIR, scriptName) // inside the container
144119
await this.k8.execContainer(podName, constants.ROOT_CONTAINER, `chmod +x ${extractScript}`)
145-
await this.k8.execContainer(podName, constants.ROOT_CONTAINER, [extractScript, buildZip, constants.HEDERA_HAPI_PATH])
146-
120+
await this.k8.execContainer(podName, constants.ROOT_CONTAINER, [extractScript, tag])
147121
return true
148122
} catch (e) {
149123
throw new FullstackTestingError(`failed to extract platform code in this pod '${podName}': ${e.message}`, e)

test/e2e/core/platform_installer_e2e.test.mjs

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
*/
1717
import { beforeAll, describe, expect, it } from '@jest/globals'
1818
import {
19-
PackageDownloader,
2019
PlatformInstaller,
2120
constants,
2221
Templates,
@@ -33,7 +32,6 @@ describe('PackageInstallerE2E', () => {
3332
const configManager = new ConfigManager(testLogger)
3433
const k8 = new K8(configManager, testLogger)
3534
const installer = new PlatformInstaller(testLogger, k8)
36-
const downloader = new PackageDownloader(testLogger)
3735
const testCacheDir = getTestCacheDir()
3836
const podName = 'network-node0-0'
3937
const packageVersion = 'v0.42.5'
@@ -58,28 +56,38 @@ describe('PackageInstallerE2E', () => {
5856
})
5957
})
6058

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

69-
// do not delete the cache dir
70-
}, 200000)
68+
try {
69+
await installer.fetchPlatform('INVALID', packageVersion)
70+
} catch (e) {
71+
expect(e.message
72+
.includes('failed to extract platform code in this pod'))
73+
.toBeTruthy()
74+
}
75+
}, 20000)
7176

72-
it('should succeed with valid tag and pod', async () => {
77+
it('should fail with invalid tag', async () => {
7378
expect.assertions(1)
7479
try {
75-
await expect(installer.fetchPlatform(podName, packageVersion)).resolves.toBeTruthy()
76-
const outputs = await k8.execContainer(podName, constants.ROOT_CONTAINER, `ls -la ${constants.HEDERA_HAPI_PATH}`)
77-
testLogger.showUser(outputs)
80+
await installer.fetchPlatform(podName, 'INVALID')
7881
} catch (e) {
79-
console.error(e)
80-
expect(e).toBeNull()
82+
expect(e.message.includes('curl: (22) The requested URL returned error: 404')).toBeTruthy()
8183
}
8284
}, 20000)
85+
86+
it('should succeed with valid tag and pod', async () => {
87+
await expect(installer.fetchPlatform(podName, packageVersion)).resolves.toBeTruthy()
88+
const outputs = await k8.execContainer(podName, constants.ROOT_CONTAINER, `ls -la ${constants.HEDERA_HAPI_PATH}`)
89+
testLogger.showUser(outputs)
90+
}, 60000)
8391
})
8492

8593
describe('prepareConfigTxt', () => {

0 commit comments

Comments
 (0)