Skip to content

Commit af3ae29

Browse files
chore: account init before relay deployment (#1154)
Signed-off-by: Jeffrey Tang <[email protected]>
1 parent ab018a7 commit af3ae29

File tree

8 files changed

+133
-20
lines changed

8 files changed

+133
-20
lines changed

.github/workflows/flow-task-test.yaml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ jobs:
3838
example-task-file-test:
3939
timeout-minutes: 20
4040
runs-on: solo-linux-large
41+
strategy:
42+
matrix:
43+
type: ["NO_ACCOUNT_INIT", "ACCOUNT_INIT"]
4144
steps:
4245
- name: Harden Runner
4346
uses: step-security/harden-runner@c95a14d0e5bab51a9f56296a4eb0e416910cd350 # v2.10.3
@@ -53,6 +56,11 @@ jobs:
5356
node-version: 20
5457
cache: npm
5558

59+
- name: Setup Helm
60+
uses: azure/setup-helm@fe7b79cd5ee1e45176fcad797de68ecaf3ca4814 # v4.2.0
61+
with:
62+
version: "v3.12.3" # helm version
63+
5664
- name: Setup Kind
5765
uses: helm/kind-action@a1b0e391336a6ee6713a0583f8c6240d70863de3 # v1.12.0
5866
with:
@@ -63,9 +71,8 @@ jobs:
6371
verbosity: 3
6472
wait: 120s
6573

66-
- name: Run Example Task File Test
74+
- name: Run Example Task File Test with type ${{ matrix.type }}
6775
run: |
68-
task default-with-relay
69-
sleep 10
70-
.github/workflows/script/solo_smoke_test.sh
76+
task default
77+
.github/workflows/script/solo_smoke_test.sh ${{ matrix.type }}
7178
task clean

.github/workflows/script/helper.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ function create_test_account ()
1414

1515
# get private key of the account
1616
npm run solo-test -- account get -n solo-e2e --account-id ${OPERATOR_ID} --private-key > test.log
17-
export OPERATOR_KEY=$(grep "privateKey" test.log | awk '{print $2}' | sed 's/"//g'| sed 's/,//g')
17+
18+
# retrieve the field privateKey but not privateKeyRaw
19+
export OPERATOR_KEY=$(grep "privateKey" test.log | grep -v "privateKeyRaw" | awk '{print $2}' | sed 's/"//g'| sed 's/,//g')
1820
export CONTRACT_TEST_KEY_ONE=0x$(grep "privateKeyRaw" test.log | awk '{print $2}' | sed 's/"//g'| sed 's/,//g')
1921
echo "CONTRACT_TEST_KEY_ONE=${CONTRACT_TEST_KEY_ONE}"
2022
rm test.log

.github/workflows/script/solo_smoke_test.sh

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,48 @@ function start_sdk_test ()
8686
return $result
8787
}
8888

89+
function check_monitor_log()
90+
{
91+
# get the logs of mirror-monitor
92+
kubectl get pods -n solo-e2e | grep mirror-monitor | awk '{print $1}' | xargs kubectl logs -n solo-e2e > mirror-monitor.log
93+
94+
if grep -q "ERROR" mirror-monitor.log; then
95+
echo "mirror-monitor.log contains ERROR"
96+
exit 1
97+
fi
98+
99+
# any line contains "Scenario pinger published" should contain the string "Errors: {}"
100+
if grep -q "Scenario pinger published" mirror-monitor.log; then
101+
if grep -q "Errors: {}" mirror-monitor.log; then
102+
echo "mirror-monitor.log contains Scenario pinger published and Errors: {}"
103+
else
104+
echo "mirror-monitor.log contains Scenario pinger published but not Errors: {}"
105+
exit 1
106+
fi
107+
fi
108+
}
109+
110+
function check_importer_log()
111+
{
112+
kubectl get pods -n solo-e2e | grep mirror-importer | awk '{print $1}' | xargs kubectl logs -n solo-e2e > mirror-importer.log
113+
if grep -q "ERROR" mirror-importer.log; then
114+
echo "mirror-importer.log contains ERROR"
115+
exit 1
116+
fi
117+
}
118+
119+
# if first parameter equals to ACCOUNT_INIT,
120+
# then call solo account init before deploy mirror and relay node
121+
if [ "$1" == "ACCOUNT_INIT" ]; then
122+
echo "Call solo account init"
123+
npm run solo-test -- account init -n solo-e2e
124+
fi
125+
126+
task solo:mirror-node
127+
task solo:relay
128+
89129
echo "Change to parent directory"
130+
90131
cd ../
91132
create_test_account
92133
clone_smart_contract_repo
@@ -97,3 +138,8 @@ start_contract_test
97138
start_sdk_test
98139
echo "Sleep a while to wait background transactions to finish"
99140
sleep 30
141+
142+
echo "Run mirror node acceptance test"
143+
helm test mirror -n solo-e2e --timeout 10m
144+
check_monitor_log
145+
check_importer_log

docs/content/User/StepByStepGuide.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
## Advanced User Guide
2+
23
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.
4+
35
### Setup Kubernetes cluster
46

57
#### Remote cluster
@@ -28,6 +30,7 @@ Then run the following command to set the kubectl context to the new cluster:
2830
```bash
2931
kind create cluster -n "${SOLO_CLUSTER_NAME}"
3032
```
33+
3134
Example output
3235

3336
```
@@ -48,7 +51,6 @@ Thanks for using kind! 😊
4851

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

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

78-
7980
### Step by Step Instructions
8081

8182
* Initialize `solo` directories:
@@ -136,13 +137,16 @@ Kubernetes Cluster : kind-solo
136137
✔ Generate gRPC TLS Keys
137138
✔ Finalize
138139
```
140+
139141
PEM key files are generated in `~/.solo/keys` directory.
142+
140143
```
141144
hedera-node1.crt hedera-node3.crt s-private-node1.pem s-public-node1.pem unused-gossip-pem
142145
hedera-node1.key hedera-node3.key s-private-node2.pem s-public-node2.pem unused-tls
143146
hedera-node2.crt hedera-node4.crt s-private-node3.pem s-public-node3.pem
144147
hedera-node2.key hedera-node4.key s-private-node4.pem s-public-node4.pem
145148
```
149+
146150
* Setup cluster with shared components
147151

148152
```

examples/address-book/README.md

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
# Yahcli Address Book Example
22

3-
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).
3+
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).
44

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

77
## Usage
88

9-
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.
9+
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.
10+
1011
```bash
1112
# try and detect if the port forward is already setup
1213
netstat -na | grep 50211
@@ -17,28 +18,35 @@ kubectl port-forward -n "${SOLO_NAMESPACE}" pod/network-node1-0 50211:50211
1718
```
1819

1920
To get the address book from the ledger, run the following command:
21+
2022
```bash
2123
cd <solo-root>/examples/address-book
2224
task get:ledger:addressbook
2325
```
24-
It will output the address book in JSON format to:
26+
27+
It will output the address book in JSON format to:
28+
2529
* `examples/address-book/localhost/sysfiles/addressBook.json`
2630
* `examples/address-book/localhost/sysfiles/nodeDetails.json`
2731

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

3034
Once the files are ready, you can upload them to the ledger by running the following command:
35+
3136
```bash
3237
cd <solo-root>/examples/address-book
3338
task update:ledger:addressbook
3439
```
3540

3641
To get the address book from the mirror node, run the following command:
42+
3743
```bash
3844
cd <solo-root>/examples/address-book
3945
task get:mirror:addressbook
4046
```
47+
4148
NOTE: Mirror Node may not pick up the changes automatically, it might require running some transactions through, example:
49+
4250
```bash
4351
cd <solo-root>
4452
npm run solo -- account create

src/commands/flags.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,7 @@ export class Flags {
619619
name: 'operator-id',
620620
definition: {
621621
describe: 'Operator ID',
622-
defaultValue: constants.OPERATOR_ID,
622+
defaultValue: undefined,
623623
type: 'string',
624624
},
625625
prompt: async function promptOperatorId(task: ListrTaskWrapper<any, any, any>, input: any) {
@@ -640,7 +640,7 @@ export class Flags {
640640
name: 'operator-key',
641641
definition: {
642642
describe: 'Operator Key',
643-
defaultValue: constants.OPERATOR_KEY,
643+
defaultValue: undefined,
644644
type: 'string',
645645
},
646646
prompt: async function promptOperatorKey(task: ListrTaskWrapper<any, any, any>, input: any) {

src/commands/mirror_node.ts

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import * as fs from 'node:fs';
3333
import * as path from 'node:path';
3434
import type {Optional, SoloListrTask} from '../types/index.js';
3535
import type {Namespace} from '../core/config/remote/types.js';
36+
import * as Base64 from 'js-base64';
3637

3738
interface MirrorNodeDeployConfigClass {
3839
chartDirectory: string;
@@ -53,6 +54,8 @@ interface MirrorNodeDeployConfigClass {
5354
clusterSetupNamespace: string;
5455
soloChartVersion: string;
5556
pinger: boolean;
57+
operatorId: string;
58+
operatorKey: string;
5659
customMirrorNodeDatabaseValuePath: Optional<string>;
5760
storageType: constants.StorageType;
5861
storageAccessKey: string;
@@ -104,6 +107,8 @@ export class MirrorNodeCommand extends BaseCommand {
104107
flags.clusterSetupNamespace,
105108
flags.soloChartVersion,
106109
flags.customMirrorNodeDatabaseValuePath,
110+
flags.operatorId,
111+
flags.operatorKey,
107112
flags.storageType,
108113
flags.storageAccessKey,
109114
flags.storageSecrets,
@@ -234,6 +239,8 @@ export class MirrorNodeCommand extends BaseCommand {
234239
flags.valuesFile,
235240
flags.mirrorNodeVersion,
236241
flags.pinger,
242+
flags.operatorId,
243+
flags.operatorKey,
237244
flags.soloChartVersion,
238245
]);
239246

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

265+
await self.accountManager.loadNodeClient(ctx.config.namespace);
266+
258267
if (ctx.config.pinger) {
259268
const startAccId = constants.HEDERA_NODE_ACCOUNT_ID_START;
260269
const networkPods = await this.k8.getPodsByLabel(['solo.hedera.com/type=network-node']);
@@ -263,18 +272,36 @@ export class MirrorNodeCommand extends BaseCommand {
263272
const pod = networkPods[0];
264273
ctx.config.valuesArg += ` --set monitor.config.hedera.mirror.monitor.nodes.0.accountId=${startAccId}`;
265274
ctx.config.valuesArg += ` --set monitor.config.hedera.mirror.monitor.nodes.0.host=${pod.status.podIP}`;
266-
267-
ctx.config.valuesArg += ` --set monitor.config.hedera.mirror.monitor.operator.accountId=${constants.OPERATOR_ID}`;
268-
ctx.config.valuesArg += ` --set monitor.config.hedera.mirror.monitor.operator.privateKey=${constants.OPERATOR_KEY}`;
275+
ctx.config.valuesArg += ' --set monitor.config.hedera.mirror.monitor.nodes.0.nodeId=0';
276+
277+
const operatorId = ctx.config.operatorId || constants.OPERATOR_ID;
278+
ctx.config.valuesArg += ` --set monitor.config.hedera.mirror.monitor.operator.accountId=${operatorId}`;
279+
280+
if (ctx.config.operatorKey) {
281+
this.logger.info('Using provided operator key');
282+
ctx.config.valuesArg += ` --set monitor.config.hedera.mirror.monitor.operator.privateKey=${ctx.config.operatorKey}`;
283+
} else {
284+
try {
285+
const secrets = await this.k8.getSecretsByLabel([`solo.hedera.com/account-id=${operatorId}`]);
286+
if (secrets.length === 0) {
287+
this.logger.info(`No k8s secret found for operator account id ${operatorId}, use default one`);
288+
ctx.config.valuesArg += ` --set monitor.config.hedera.mirror.monitor.operator.privateKey=${constants.OPERATOR_KEY}`;
289+
} else {
290+
this.logger.info('Using operator key from k8s secret');
291+
const operatorKeyFromK8 = Base64.decode(secrets[0].data.privateKey);
292+
ctx.config.valuesArg += ` --set monitor.config.hedera.mirror.monitor.operator.privateKey=${operatorKeyFromK8}`;
293+
}
294+
} catch (e: Error | any) {
295+
throw new SoloError(`Error getting operator key: ${e.message}`, e);
296+
}
297+
}
269298
}
270299
}
271300

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

276-
await self.accountManager.loadNodeClient(ctx.config.namespace);
277-
278305
return ListrLease.newAcquireLeaseTask(lease, task);
279306
},
280307
},

src/commands/relay.ts

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {type Opts} from '../types/command_types.js';
2929
import {ListrLease} from '../core/lease/listr_lease.js';
3030
import {RelayComponent} from '../core/config/remote/components/relay_component.js';
3131
import {ComponentType} from '../core/config/remote/enumerations.js';
32+
import * as Base64 from 'js-base64';
3233

3334
export class RelayCommand extends BaseCommand {
3435
private readonly profileManager: ProfileManager;
@@ -105,12 +106,26 @@ export class RelayCommand extends BaseCommand {
105106
valuesArg += ` --set replicaCount=${replicaCount}`;
106107
}
107108

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

112112
if (operatorKey) {
113+
// use user provided operatorKey if available
113114
valuesArg += ` --set config.OPERATOR_KEY_MAIN=${operatorKey}`;
115+
} else {
116+
try {
117+
const secrets = await this.k8.getSecretsByLabel([`solo.hedera.com/account-id=${operatorIdUsing}`]);
118+
if (secrets.length === 0) {
119+
this.logger.info(`No k8s secret found for operator account id ${operatorIdUsing}, use default one`);
120+
valuesArg += ` --set config.OPERATOR_KEY_MAIN=${constants.OPERATOR_KEY}`;
121+
} else {
122+
this.logger.info('Using operator key from k8s secret');
123+
const operatorKeyFromK8 = Base64.decode(secrets[0].data.privateKey);
124+
valuesArg += ` --set config.OPERATOR_KEY_MAIN=${operatorKeyFromK8}`;
125+
}
126+
} catch (e: Error | any) {
127+
throw new SoloError(`Error getting operator key: ${e.message}`, e);
128+
}
114129
}
115130

116131
if (!nodeAliases) {
@@ -202,6 +217,8 @@ export class RelayCommand extends BaseCommand {
202217

203218
self.configManager.update(argv);
204219

220+
flags.disablePrompts([flags.operatorId, flags.operatorKey]);
221+
205222
await self.configManager.executePrompt(task, RelayCommand.DEPLOY_FLAGS_LIST);
206223

207224
// prompt if inputs are empty and set it in the context
@@ -231,6 +248,7 @@ export class RelayCommand extends BaseCommand {
231248
constants.JSON_RPC_RELAY_CHART,
232249
constants.JSON_RPC_RELAY_CHART,
233250
);
251+
await self.accountManager.loadNodeClient(ctx.config.namespace);
234252
config.valuesArg = await self.prepareValuesArg(
235253
config.valuesFile,
236254
config.nodeAliases,
@@ -298,6 +316,7 @@ export class RelayCommand extends BaseCommand {
298316
throw new SoloError('Error installing relays', e);
299317
} finally {
300318
await lease.release();
319+
await self.accountManager.close();
301320
}
302321

303322
return true;

0 commit comments

Comments
 (0)