@@ -20,17 +20,25 @@ import { Listr } from 'listr2'
20
20
import { FullstackTestingError , IllegalArgumentError , MissingArgumentError } from '../core/errors.mjs'
21
21
import { BaseCommand } from './base.mjs'
22
22
import * as flags from './flags.mjs'
23
- import { constants } from '../core/index.mjs'
23
+ import { constants , Templates } from '../core/index.mjs'
24
24
import * as prompts from './prompts.mjs'
25
25
import * as helpers from '../core/helpers.mjs'
26
26
import path from 'path'
27
+ import { validatePath } from '../core/helpers.mjs'
28
+ import fs from 'fs'
27
29
28
30
export class NetworkCommand extends BaseCommand {
29
31
constructor ( opts ) {
30
32
super ( opts )
31
33
34
+ if ( ! opts || ! opts . k8 ) throw new Error ( 'An instance of core/K8 is required' )
35
+ if ( ! opts || ! opts . keyManager ) throw new IllegalArgumentError ( 'An instance of core/KeyManager is required' , opts . keyManager )
36
+ if ( ! opts || ! opts . platformInstaller ) throw new IllegalArgumentError ( 'An instance of core/PlatformInstaller is required' , opts . platformInstaller )
32
37
if ( ! opts || ! opts . profileManager ) throw new MissingArgumentError ( 'An instance of core/ProfileManager is required' , opts . downloader )
33
38
39
+ this . k8 = opts . k8
40
+ this . keyManager = opts . keyManager
41
+ this . platformInstaller = opts . platformInstaller
34
42
this . profileManager = opts . profileManager
35
43
}
36
44
@@ -45,6 +53,7 @@ export class NetworkCommand extends BaseCommand {
45
53
flags . applicationEnv ,
46
54
flags . applicationProperties ,
47
55
flags . bootstrapProperties ,
56
+ flags . cacheDir ,
48
57
flags . chainId ,
49
58
flags . chartDirectory ,
50
59
flags . deployHederaExplorer ,
@@ -54,6 +63,7 @@ export class NetworkCommand extends BaseCommand {
54
63
flags . fstChartVersion ,
55
64
flags . hederaExplorerTlsHostName ,
56
65
flags . hederaExplorerTlsLoadBalancerIp ,
66
+ flags . keyFormat ,
57
67
flags . log4j2Xml ,
58
68
flags . namespace ,
59
69
flags . nodeIDs ,
@@ -143,10 +153,12 @@ export class NetworkCommand extends BaseCommand {
143
153
flags . applicationEnv ,
144
154
flags . applicationProperties ,
145
155
flags . bootstrapProperties ,
156
+ flags . cacheDir ,
146
157
flags . chainId ,
147
158
flags . deployHederaExplorer ,
148
159
flags . deployMirrorNode ,
149
160
flags . hederaExplorerTlsLoadBalancerIp ,
161
+ flags . keyFormat ,
150
162
flags . log4j2Xml ,
151
163
flags . persistentVolumeClaims ,
152
164
flags . profileName ,
@@ -160,6 +172,7 @@ export class NetworkCommand extends BaseCommand {
160
172
* @typedef {Object } NetworkDeployConfigClass
161
173
* -- flags --
162
174
* @property {string } applicationEnv
175
+ * @property {string } cacheDir
163
176
* @property {string } chartDirectory
164
177
* @property {boolean } deployHederaExplorer
165
178
* @property {boolean } deployMirrorNode
@@ -168,6 +181,7 @@ export class NetworkCommand extends BaseCommand {
168
181
* @property {string } fstChartVersion
169
182
* @property {string } hederaExplorerTlsHostName
170
183
* @property {string } hederaExplorerTlsLoadBalancerIp
184
+ * @property {string } keyFormat
171
185
* @property {string } namespace
172
186
* @property {string } nodeIDs
173
187
* @property {string } persistentVolumeClaims
@@ -176,8 +190,11 @@ export class NetworkCommand extends BaseCommand {
176
190
* @property {string } releaseTag
177
191
* @property {string } tlsClusterIssuerType
178
192
* -- extra args --
179
- * @property {string[] } nodeIds
180
193
* @property {string } chartPath
194
+ * @property {string } keysDir
195
+ * @property {string[] } nodeIds
196
+ * @property {string } stagingDir
197
+ * @property {string } stagingKeysDir
181
198
* @property {string } valuesArg
182
199
* -- methods --
183
200
* @property {getUnusedConfigs } getUnusedConfigs
@@ -189,7 +206,14 @@ export class NetworkCommand extends BaseCommand {
189
206
190
207
// create a config object for subsequent steps
191
208
const config = /** @type {NetworkDeployConfigClass } **/ this . getConfig ( NetworkCommand . DEPLOY_CONFIGS_NAME , NetworkCommand . DEPLOY_FLAGS_LIST ,
192
- [ 'nodeIds' , 'chartPath' , 'valuesArg' ] )
209
+ [
210
+ 'chartPath' ,
211
+ 'keysDir' ,
212
+ 'nodeIds' ,
213
+ 'stagingDir' ,
214
+ 'stagingKeysDir' ,
215
+ 'valuesArg'
216
+ ] )
193
217
194
218
config . nodeIds = helpers . parseNodeIds ( config . nodeIDs )
195
219
@@ -199,6 +223,28 @@ export class NetworkCommand extends BaseCommand {
199
223
200
224
config . valuesArg = await this . prepareValuesArg ( config )
201
225
226
+ // compute other config parameters
227
+ config . keysDir = path . join ( validatePath ( config . cacheDir ) , 'keys' )
228
+ config . stagingDir = Templates . renderStagingDir (
229
+ config . cacheDir ,
230
+ config . releaseTag
231
+ )
232
+ config . stagingKeysDir = path . join ( validatePath ( config . stagingDir ) , 'keys' )
233
+
234
+ if ( ! await this . k8 . hasNamespace ( config . namespace ) ) {
235
+ await this . k8 . createNamespace ( config . namespace )
236
+ }
237
+
238
+ // prepare staging keys directory
239
+ if ( ! fs . existsSync ( config . stagingKeysDir ) ) {
240
+ fs . mkdirSync ( config . stagingKeysDir , { recursive : true } )
241
+ }
242
+
243
+ // create cached keys dir if it does not exist yet
244
+ if ( ! fs . existsSync ( config . keysDir ) ) {
245
+ fs . mkdirSync ( config . keysDir )
246
+ }
247
+
202
248
this . logger . debug ( 'Prepared config' , {
203
249
config,
204
250
cachedConfig : this . configManager . config
@@ -221,7 +267,50 @@ export class NetworkCommand extends BaseCommand {
221
267
ctx . config = /** @type {NetworkDeployConfigClass } **/ await self . prepareConfig ( task , argv )
222
268
}
223
269
} ,
224
- // TODO create node keys and secrets
270
+ {
271
+ title : 'Prepare staging directory' ,
272
+ task : async ( ctx , parentTask ) => {
273
+ const subTasks = [
274
+ {
275
+ title : 'Copy Gossip keys to staging' ,
276
+ task : async ( ctx , _ ) => {
277
+ const config = /** @type {NetworkDeployConfigClass } **/ ctx . config
278
+
279
+ await this . keyManager . copyGossipKeysToStaging ( config . keyFormat , config . keysDir , config . stagingKeysDir , config . nodeIds )
280
+ }
281
+ } ,
282
+ {
283
+ title : 'Copy gRPC TLS keys to staging' ,
284
+ task : async ( ctx , _ ) => {
285
+ const config = /** @type {NetworkDeployConfigClass } **/ ctx . config
286
+ for ( const nodeId of config . nodeIds ) {
287
+ const tlsKeyFiles = self . keyManager . prepareTLSKeyFilePaths ( nodeId , config . keysDir )
288
+ await self . keyManager . copyNodeKeysToStaging ( tlsKeyFiles , config . stagingKeysDir )
289
+ }
290
+ }
291
+ }
292
+ ]
293
+
294
+ return parentTask . newListr ( subTasks , {
295
+ concurrent : false ,
296
+ rendererOptions : constants . LISTR_DEFAULT_RENDERER_OPTION
297
+ } )
298
+ }
299
+ } ,
300
+ {
301
+ title : 'Copy node keys to secrets' ,
302
+ task : async ( ctx , parentTask ) => {
303
+ const config = /** @type {NetworkDeployConfigClass } **/ ctx . config
304
+
305
+ const subTasks = self . platformInstaller . copyNodeKeys ( config . stagingDir , config . nodeIds , config . keyFormat )
306
+
307
+ // set up the sub-tasks
308
+ return parentTask . newListr ( subTasks , {
309
+ concurrent : true ,
310
+ rendererOptions : constants . LISTR_DEFAULT_RENDERER_OPTION
311
+ } )
312
+ }
313
+ } ,
225
314
{
226
315
title : `Install chart '${ constants . FULLSTACK_DEPLOYMENT_CHART } '` ,
227
316
task : async ( ctx , _ ) => {
0 commit comments