@@ -36,6 +36,29 @@ type AppCompose = {
3636 event_log_version ?: number ;
3737} ;
3838
39+ /** Parses one `KEY=VALUE` annotation per line, refusing a key given twice. */
40+ function parseAnnotations ( text : string ) : Record < string , string > {
41+ const annotations = new Map < string , string > ( ) ;
42+ for ( const line of text . split ( '\n' ) . map ( ( l ) => l . trim ( ) ) . filter ( Boolean ) ) {
43+ const eq = line . indexOf ( '=' ) ;
44+ if ( eq <= 0 ) {
45+ throw new Error ( `Invalid annotation "${ line } ", expected KEY=VALUE` ) ;
46+ }
47+ const key = line . slice ( 0 , eq ) ;
48+ if ( annotations . has ( key ) ) {
49+ throw new Error ( `Annotation "${ key } " given twice` ) ;
50+ }
51+ annotations . set ( key , line . slice ( eq + 1 ) ) ;
52+ }
53+ return Object . fromEntries ( annotations ) ;
54+ }
55+
56+ function annotationsText ( annotations : Record < string , string > | null | undefined ) : string {
57+ return Object . entries ( annotations || { } )
58+ . map ( ( [ key , value ] ) => `${ key } =${ value } ` )
59+ . join ( '\n' ) ;
60+ }
61+
3962function initScriptList ( initScript : string | string [ ] | undefined ) : string [ ] {
4063 const scripts = Array . isArray ( initScript )
4164 ? [ ...initScript ]
@@ -167,6 +190,7 @@ type VmFormState = {
167190 disk_prealloc : string ;
168191 networks : NetworkFormEntry [ ] ;
169192 user_config : string ;
193+ annotations : string ;
170194 kms_urls : string [ ] ;
171195 gateway_urls : string [ ] ;
172196 stopped : boolean ;
@@ -259,6 +283,7 @@ function createVmFormState(preLaunchScript: string): VmFormState {
259283 disk_prealloc : '' ,
260284 networks : [ ] ,
261285 user_config : '' ,
286+ annotations : '' ,
262287 kms_urls : [ ] ,
263288 gateway_urls : [ ] ,
264289 stopped : false ,
@@ -630,6 +655,7 @@ type CreateVmPayloadSource = {
630655 kms_urls ?: string [ ] ;
631656 gateway_urls ?: string [ ] ;
632657 stopped ?: boolean ;
658+ annotations ?: Record < string , string > ;
633659 } ;
634660
635661 function buildCreateVmPayload ( source : CreateVmPayloadSource ) : VmmTypes . IVmConfiguration {
@@ -657,6 +683,7 @@ type CreateVmPayloadSource = {
657683 kms_urls : source . kms_urls ?. filter ( ( url ) => url && url . trim ( ) . length ) ?? [ ] ,
658684 gateway_urls : source . gateway_urls ?. filter ( ( url ) => url && url . trim ( ) . length ) ?? [ ] ,
659685 stopped : ! ! source . stopped ,
686+ annotations : source . annotations ?? { } ,
660687 } ;
661688 }
662689
@@ -1126,6 +1153,8 @@ type CreateVmPayloadSource = {
11261153 // and inheriting "full" unannounced costs the next deploy a full write of
11271154 // its disk before the VM boots.
11281155 vmForm . value . disk_prealloc = '' ;
1156+ // And a clone's annotations are parameters for that VM's host tooling.
1157+ vmForm . value . annotations = '' ;
11291158 vmForm . value . swapValue = 0 ;
11301159 vmForm . value . swapUnit = 'GB' ;
11311160 vmForm . value . swap_size = 0 ;
@@ -1265,6 +1294,7 @@ type CreateVmPayloadSource = {
12651294 kms_urls : vmForm . value . kms_urls ,
12661295 gateway_urls : vmForm . value . gateway_urls ,
12671296 stopped : vmForm . value . stopped ,
1297+ annotations : parseAnnotations ( vmForm . value . annotations ) ,
12681298 } ) ;
12691299
12701300 await vmmRpc . createVm ( payload ) ;
@@ -1420,6 +1450,7 @@ type CreateVmPayloadSource = {
14201450 no_tee : ! ! config . no_tee ,
14211451 simulated_tee : config . simulated_tee || '' ,
14221452 user_config : config . user_config || '' ,
1453+ annotations : annotationsText ( config . annotations ) ,
14231454 stopped : ! ! config . stopped ,
14241455 event_log_version : theVm . appCompose ?. event_log_version || 1 ,
14251456 } ;
0 commit comments