Skip to content

Commit

Permalink
chore: account init before relay deployment (#1154)
Browse files Browse the repository at this point in the history
Signed-off-by: Jeffrey Tang <[email protected]>
  • Loading branch information
JeffreyDallas authored Jan 17, 2025
1 parent ab018a7 commit af3ae29
Show file tree
Hide file tree
Showing 8 changed files with 133 additions and 20 deletions.
15 changes: 11 additions & 4 deletions .github/workflows/flow-task-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ jobs:
example-task-file-test:
timeout-minutes: 20
runs-on: solo-linux-large
strategy:
matrix:
type: ["NO_ACCOUNT_INIT", "ACCOUNT_INIT"]
steps:
- name: Harden Runner
uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
Expand All @@ -53,6 +56,11 @@ jobs:
node-version: 20
cache: npm

- name: Setup Helm
uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2.0
with:
version: "v3.12.3" # helm version

- name: Setup Kind
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
with:
Expand All @@ -63,9 +71,8 @@ jobs:
verbosity: 3
wait: 120s

- name: Run Example Task File Test
- name: Run Example Task File Test with type ${{ matrix.type }}
run: |
task default-with-relay
sleep 10
.github/workflows/script/solo_smoke_test.sh
task default
.github/workflows/script/solo_smoke_test.sh ${{ matrix.type }}
task clean
4 changes: 3 additions & 1 deletion .github/workflows/script/helper.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ function create_test_account ()

# get private key of the account
npm run solo-test -- account get -n solo-e2e --account-id ${OPERATOR_ID} --private-key > test.log
export OPERATOR_KEY=$(grep "privateKey" test.log | awk '{print $2}' | sed 's/"//g'| sed 's/,//g')

# retrieve the field privateKey but not privateKeyRaw
export OPERATOR_KEY=$(grep "privateKey" test.log | grep -v "privateKeyRaw" | awk '{print $2}' | sed 's/"//g'| sed 's/,//g')
export CONTRACT_TEST_KEY_ONE=0x$(grep "privateKeyRaw" test.log | awk '{print $2}' | sed 's/"//g'| sed 's/,//g')
echo "CONTRACT_TEST_KEY_ONE=${CONTRACT_TEST_KEY_ONE}"
rm test.log
Expand Down
46 changes: 46 additions & 0 deletions .github/workflows/script/solo_smoke_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,48 @@ function start_sdk_test ()
return $result
}

function check_monitor_log()
{
# get the logs of mirror-monitor
kubectl get pods -n solo-e2e | grep mirror-monitor | awk '{print $1}' | xargs kubectl logs -n solo-e2e > mirror-monitor.log

if grep -q "ERROR" mirror-monitor.log; then
echo "mirror-monitor.log contains ERROR"
exit 1
fi

# any line contains "Scenario pinger published" should contain the string "Errors: {}"
if grep -q "Scenario pinger published" mirror-monitor.log; then
if grep -q "Errors: {}" mirror-monitor.log; then
echo "mirror-monitor.log contains Scenario pinger published and Errors: {}"
else
echo "mirror-monitor.log contains Scenario pinger published but not Errors: {}"
exit 1
fi
fi
}

function check_importer_log()
{
kubectl get pods -n solo-e2e | grep mirror-importer | awk '{print $1}' | xargs kubectl logs -n solo-e2e > mirror-importer.log
if grep -q "ERROR" mirror-importer.log; then
echo "mirror-importer.log contains ERROR"
exit 1
fi
}

# if first parameter equals to ACCOUNT_INIT,
# then call solo account init before deploy mirror and relay node
if [ "$1" == "ACCOUNT_INIT" ]; then
echo "Call solo account init"
npm run solo-test -- account init -n solo-e2e
fi

task solo:mirror-node
task solo:relay

echo "Change to parent directory"

cd ../
create_test_account
clone_smart_contract_repo
Expand All @@ -97,3 +138,8 @@ start_contract_test
start_sdk_test
echo "Sleep a while to wait background transactions to finish"
sleep 30

echo "Run mirror node acceptance test"
helm test mirror -n solo-e2e --timeout 10m
check_monitor_log
check_importer_log
8 changes: 6 additions & 2 deletions docs/content/User/StepByStepGuide.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
## Advanced User Guide

For those who would like to have more control or need some customized setups, here are some step by step instructions of how to setup and deploy a solo network.

### Setup Kubernetes cluster

#### Remote cluster
Expand Down Expand Up @@ -28,6 +30,7 @@ Then run the following command to set the kubectl context to the new cluster:
```bash
kind create cluster -n "${SOLO_CLUSTER_NAME}"
```

Example output

```
Expand All @@ -48,7 +51,6 @@ Thanks for using kind! 😊

You may now view pods in your cluster using `k9s -A` as below:


```
Context: kind-solo <0> all <a> Attach <ctr… ____ __.________
Cluster: kind-solo <ctrl-d> Delete <l> | |/ _/ __ \______
Expand All @@ -75,7 +77,6 @@ You may now view pods in your cluster using `k9s -A` as below:
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
```


### Step by Step Instructions

* Initialize `solo` directories:
Expand Down Expand Up @@ -136,13 +137,16 @@ Kubernetes Cluster : kind-solo
✔ Generate gRPC TLS Keys
✔ Finalize
```

PEM key files are generated in `~/.solo/keys` directory.

```
hedera-node1.crt hedera-node3.crt s-private-node1.pem s-public-node1.pem unused-gossip-pem
hedera-node1.key hedera-node3.key s-private-node2.pem s-public-node2.pem unused-tls
hedera-node2.crt hedera-node4.crt s-private-node3.pem s-public-node3.pem
hedera-node2.key hedera-node4.key s-private-node4.pem s-public-node4.pem
```

* Setup cluster with shared components

```
Expand Down
14 changes: 11 additions & 3 deletions examples/address-book/README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# Yahcli Address Book Example

This is an example of how to use Yahcli to pull the ledger and mirror node address book. And to update the ledger address book. It updates File 101 (the ledger address book file) and File 102 (the ledger node details file).
This is an example of how to use Yahcli to pull the ledger and mirror node address book. And to update the ledger address book. It updates File 101 (the ledger address book file) and File 102 (the ledger node details file).

NOTE: Mirror Node refers to File 102 as its address book.

## Usage

To get the address book from the ledger, this requires a port forward to be setup on port 50211 to consensus node with node ID = 0.
To get the address book from the ledger, this requires a port forward to be setup on port 50211 to consensus node with node ID = 0.

```bash
# try and detect if the port forward is already setup
netstat -na | grep 50211
Expand All @@ -17,28 +18,35 @@ kubectl port-forward -n "${SOLO_NAMESPACE}" pod/network-node1-0 50211:50211
```

To get the address book from the ledger, run the following command:

```bash
cd <solo-root>/examples/address-book
task get:ledger:addressbook
```
It will output the address book in JSON format to:

It will output the address book in JSON format to:

* `examples/address-book/localhost/sysfiles/addressBook.json`
* `examples/address-book/localhost/sysfiles/nodeDetails.json`

You can update the address book files with your favorite text editor.

Once the files are ready, you can upload them to the ledger by running the following command:

```bash
cd <solo-root>/examples/address-book
task update:ledger:addressbook
```

To get the address book from the mirror node, run the following command:

```bash
cd <solo-root>/examples/address-book
task get:mirror:addressbook
```

NOTE: Mirror Node may not pick up the changes automatically, it might require running some transactions through, example:

```bash
cd <solo-root>
npm run solo -- account create
Expand Down
4 changes: 2 additions & 2 deletions src/commands/flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,7 @@ export class Flags {
name: 'operator-id',
definition: {
describe: 'Operator ID',
defaultValue: constants.OPERATOR_ID,
defaultValue: undefined,
type: 'string',
},
prompt: async function promptOperatorId(task: ListrTaskWrapper<any, any, any>, input: any) {
Expand All @@ -640,7 +640,7 @@ export class Flags {
name: 'operator-key',
definition: {
describe: 'Operator Key',
defaultValue: constants.OPERATOR_KEY,
defaultValue: undefined,
type: 'string',
},
prompt: async function promptOperatorKey(task: ListrTaskWrapper<any, any, any>, input: any) {
Expand Down
37 changes: 32 additions & 5 deletions src/commands/mirror_node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import * as fs from 'node:fs';
import * as path from 'node:path';
import type {Optional, SoloListrTask} from '../types/index.js';
import type {Namespace} from '../core/config/remote/types.js';
import * as Base64 from 'js-base64';

interface MirrorNodeDeployConfigClass {
chartDirectory: string;
Expand All @@ -53,6 +54,8 @@ interface MirrorNodeDeployConfigClass {
clusterSetupNamespace: string;
soloChartVersion: string;
pinger: boolean;
operatorId: string;
operatorKey: string;
customMirrorNodeDatabaseValuePath: Optional<string>;
storageType: constants.StorageType;
storageAccessKey: string;
Expand Down Expand Up @@ -104,6 +107,8 @@ export class MirrorNodeCommand extends BaseCommand {
flags.clusterSetupNamespace,
flags.soloChartVersion,
flags.customMirrorNodeDatabaseValuePath,
flags.operatorId,
flags.operatorKey,
flags.storageType,
flags.storageAccessKey,
flags.storageSecrets,
Expand Down Expand Up @@ -234,6 +239,8 @@ export class MirrorNodeCommand extends BaseCommand {
flags.valuesFile,
flags.mirrorNodeVersion,
flags.pinger,
flags.operatorId,
flags.operatorKey,
flags.soloChartVersion,
]);

Expand All @@ -255,6 +262,8 @@ export class MirrorNodeCommand extends BaseCommand {
// user defined values later to override predefined values
ctx.config.valuesArg += await self.prepareValuesArg(ctx.config);

await self.accountManager.loadNodeClient(ctx.config.namespace);

if (ctx.config.pinger) {
const startAccId = constants.HEDERA_NODE_ACCOUNT_ID_START;
const networkPods = await this.k8.getPodsByLabel(['solo.hedera.com/type=network-node']);
Expand All @@ -263,18 +272,36 @@ export class MirrorNodeCommand extends BaseCommand {
const pod = networkPods[0];
ctx.config.valuesArg += ` --set monitor.config.hedera.mirror.monitor.nodes.0.accountId=${startAccId}`;
ctx.config.valuesArg += ` --set monitor.config.hedera.mirror.monitor.nodes.0.host=${pod.status.podIP}`;

ctx.config.valuesArg += ` --set monitor.config.hedera.mirror.monitor.operator.accountId=${constants.OPERATOR_ID}`;
ctx.config.valuesArg += ` --set monitor.config.hedera.mirror.monitor.operator.privateKey=${constants.OPERATOR_KEY}`;
ctx.config.valuesArg += ' --set monitor.config.hedera.mirror.monitor.nodes.0.nodeId=0';

const operatorId = ctx.config.operatorId || constants.OPERATOR_ID;
ctx.config.valuesArg += ` --set monitor.config.hedera.mirror.monitor.operator.accountId=${operatorId}`;

if (ctx.config.operatorKey) {
this.logger.info('Using provided operator key');
ctx.config.valuesArg += ` --set monitor.config.hedera.mirror.monitor.operator.privateKey=${ctx.config.operatorKey}`;
} else {
try {
const secrets = await this.k8.getSecretsByLabel([`solo.hedera.com/account-id=${operatorId}`]);
if (secrets.length === 0) {
this.logger.info(`No k8s secret found for operator account id ${operatorId}, use default one`);
ctx.config.valuesArg += ` --set monitor.config.hedera.mirror.monitor.operator.privateKey=${constants.OPERATOR_KEY}`;
} else {
this.logger.info('Using operator key from k8s secret');
const operatorKeyFromK8 = Base64.decode(secrets[0].data.privateKey);
ctx.config.valuesArg += ` --set monitor.config.hedera.mirror.monitor.operator.privateKey=${operatorKeyFromK8}`;
}
} catch (e: Error | any) {
throw new SoloError(`Error getting operator key: ${e.message}`, e);
}
}
}
}

if (!(await self.k8.hasNamespace(ctx.config.namespace))) {
throw new SoloError(`namespace ${ctx.config.namespace} does not exist`);
}

await self.accountManager.loadNodeClient(ctx.config.namespace);

return ListrLease.newAcquireLeaseTask(lease, task);
},
},
Expand Down
25 changes: 22 additions & 3 deletions src/commands/relay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import {type Opts} from '../types/command_types.js';
import {ListrLease} from '../core/lease/listr_lease.js';
import {RelayComponent} from '../core/config/remote/components/relay_component.js';
import {ComponentType} from '../core/config/remote/enumerations.js';
import * as Base64 from 'js-base64';

export class RelayCommand extends BaseCommand {
private readonly profileManager: ProfileManager;
Expand Down Expand Up @@ -105,12 +106,26 @@ export class RelayCommand extends BaseCommand {
valuesArg += ` --set replicaCount=${replicaCount}`;
}

if (operatorID) {
valuesArg += ` --set config.OPERATOR_ID_MAIN=${operatorID}`;
}
const operatorIdUsing = operatorID || constants.OPERATOR_ID;
valuesArg += ` --set config.OPERATOR_ID_MAIN=${operatorIdUsing}`;

if (operatorKey) {
// use user provided operatorKey if available
valuesArg += ` --set config.OPERATOR_KEY_MAIN=${operatorKey}`;
} else {
try {
const secrets = await this.k8.getSecretsByLabel([`solo.hedera.com/account-id=${operatorIdUsing}`]);
if (secrets.length === 0) {
this.logger.info(`No k8s secret found for operator account id ${operatorIdUsing}, use default one`);
valuesArg += ` --set config.OPERATOR_KEY_MAIN=${constants.OPERATOR_KEY}`;
} else {
this.logger.info('Using operator key from k8s secret');
const operatorKeyFromK8 = Base64.decode(secrets[0].data.privateKey);
valuesArg += ` --set config.OPERATOR_KEY_MAIN=${operatorKeyFromK8}`;
}
} catch (e: Error | any) {
throw new SoloError(`Error getting operator key: ${e.message}`, e);
}
}

if (!nodeAliases) {
Expand Down Expand Up @@ -202,6 +217,8 @@ export class RelayCommand extends BaseCommand {

self.configManager.update(argv);

flags.disablePrompts([flags.operatorId, flags.operatorKey]);

await self.configManager.executePrompt(task, RelayCommand.DEPLOY_FLAGS_LIST);

// prompt if inputs are empty and set it in the context
Expand Down Expand Up @@ -231,6 +248,7 @@ export class RelayCommand extends BaseCommand {
constants.JSON_RPC_RELAY_CHART,
constants.JSON_RPC_RELAY_CHART,
);
await self.accountManager.loadNodeClient(ctx.config.namespace);
config.valuesArg = await self.prepareValuesArg(
config.valuesFile,
config.nodeAliases,
Expand Down Expand Up @@ -298,6 +316,7 @@ export class RelayCommand extends BaseCommand {
throw new SoloError('Error installing relays', e);
} finally {
await lease.release();
await self.accountManager.close();
}

return true;
Expand Down

0 comments on commit af3ae29

Please sign in to comment.