@@ -9,6 +9,7 @@ import path from 'path';
99import TOML , { Section } from '@ltd/j-toml' ;
1010import cockpit from 'cockpit' ;
1111import { fsinfo } from 'cockpit/fsinfo' ;
12+ import { LongRunningProcess } from 'long-running-process' ;
1213import { v4 as uuidv4 } from 'uuid' ;
1314
1415// We have to work around RTK query here, since it doesn't like splitting
@@ -19,17 +20,21 @@ import { v4 as uuidv4 } from 'uuid';
1920// bit so that the `cockpitApi` doesn't become a monolith.
2021import { contentSourcesApi } from './contentSourcesApi' ;
2122import {
23+ ComposeStatus ,
24+ composeStatus ,
2225 datastreamDistroLookup ,
2326 getBlueprintsPath ,
2427 getCloudConfigs ,
25- mapToOnpremRequest ,
2628 paginate ,
2729 readComposes ,
30+ updateComposeStatus ,
2831} from './helpers' ;
2932import type {
3033 CockpitCreateBlueprintApiArg ,
3134 CockpitCreateBlueprintRequest ,
3235 CockpitUpdateBlueprintApiArg ,
36+ GetCockpitComposeStatusApiResponse ,
37+ ImageStatus ,
3338 UpdateWorkerConfigApiArg ,
3439 WorkerConfigFile ,
3540 WorkerConfigResponse ,
@@ -39,6 +44,7 @@ import {
3944 mapHostedToOnPrem ,
4045 mapOnPremToHosted ,
4146} from '../../Components/Blueprints/helpers/onPremToHostedBlueprintMapper' ;
47+ import { ARTIFACTS_DIR } from '../../constants' ;
4248import {
4349 BlueprintItem ,
4450 ComposeBlueprintApiArg ,
@@ -61,7 +67,6 @@ import {
6167 GetComposesApiArg ,
6268 GetComposesApiResponse ,
6369 GetComposeStatusApiArg ,
64- GetComposeStatusApiResponse ,
6570 GetOscapCustomizationsApiArg ,
6671 GetOscapCustomizationsApiResponse ,
6772 GetOscapProfilesApiArg ,
@@ -359,7 +364,7 @@ export const cockpitApi = contentSourcesApi.injectEndpoints({
359364 ComposeBlueprintApiResponse ,
360365 ComposeBlueprintApiArg
361366 > ( {
362- queryFn : async ( { id : filename } , _ , __ , baseQuery ) => {
367+ queryFn : async ( { id : filename } ) => {
363368 try {
364369 const blueprintsDir = await getBlueprintsPath ( ) ;
365370 const file = cockpit . file (
@@ -386,29 +391,63 @@ export const cockpitApi = contentSourcesApi.injectEndpoints({
386391 image_requests : [ ir ] ,
387392 } ;
388393
389- const composeResp = await baseQuery ( {
390- url : '/compose' ,
391- method : 'POST' ,
392- body : JSON . stringify (
393- // since this is the request that gets sent to the cloudapi
394- // backend, we need to modify it slightly
395- mapToOnpremRequest (
394+ const uuid = uuidv4 ( ) ;
395+ const composeDir = path . join ( blueprintsDir , filename , uuid ) ;
396+ await cockpit . spawn ( [ 'mkdir' , '-p' , composeDir ] , { } ) ;
397+
398+ const ibBpPath = path . join ( composeDir , 'bp.json' ) ;
399+ await cockpit
400+ . file ( ibBpPath )
401+ . replace (
402+ JSON . stringify (
396403 mapHostedToOnPrem ( blueprint as CreateBlueprintRequest ) ,
397- crcComposeRequest . distribution ,
398- [ ir ] ,
404+ null ,
405+ 2 ,
399406 ) ,
400- null ,
401- 2 ,
402- ) ,
403- headers : {
404- 'content-type' : 'application/json' ,
405- } ,
406- } ) ;
407+ ) ;
407408
409+ // save the blueprint request early, since any errors
410+ // in this function cause pretty big headaches with
411+ // the images table
408412 await cockpit
409- . file ( path . join ( blueprintsDir , filename , composeResp . data ?. id ) )
413+ . file ( path . join ( composeDir , 'request.json' ) )
410414 . replace ( JSON . stringify ( crcComposeRequest , null , 2 ) ) ;
411- composes . push ( { id : composeResp . data ?. id } ) ;
415+
416+ const user = await cockpit . user ( ) ;
417+ const cmd = [
418+ // the image build fails if we don't set
419+ // this for some reason
420+ `HOME=${ user . home } ` ,
421+ '/usr/bin/image-builder' ,
422+ 'build' ,
423+ '--with-buildlog' ,
424+ '--blueprint' ,
425+ ibBpPath ,
426+ '--output-dir' ,
427+ path . join ( ARTIFACTS_DIR , uuid ) ,
428+ '--output-name' ,
429+ uuid ,
430+ '--distro' ,
431+ crcComposeRequest . distribution ,
432+ ir . image_type ,
433+ ] ;
434+
435+ const process = new LongRunningProcess (
436+ `cockpit-image-builder-${ uuid } .service` ,
437+ updateComposeStatus ( composeDir ) ,
438+ ) ;
439+
440+ // this is a workaround because the process
441+ // can't be started when in `init` state
442+ process . state = 'stopped' ;
443+
444+ process . run ( [ 'bash' , '-ec' , cmd . join ( ' ' ) ] ) . catch ( async ( ) => {
445+ await cockpit
446+ . file ( path . join ( composeDir , 'result' ) )
447+ . replace ( ComposeStatus . FAILURE ) ;
448+ } ) ;
449+
450+ composes . push ( { id : uuid } ) ;
412451 }
413452
414453 return {
@@ -452,37 +491,47 @@ export const cockpitApi = contentSourcesApi.injectEndpoints({
452491 } ,
453492 } ) ,
454493 getComposeStatus : builder . query <
455- GetComposeStatusApiResponse ,
494+ GetCockpitComposeStatusApiResponse ,
456495 GetComposeStatusApiArg
457496 > ( {
458- queryFn : async ( queryArg , _ , __ , baseQuery ) => {
497+ queryFn : async ( queryArg ) => {
459498 try {
460- const resp = await baseQuery ( {
461- url : `/composes/${ queryArg . composeId } ` ,
462- method : 'GET' ,
463- } ) ;
464499 const blueprintsDir = await getBlueprintsPath ( ) ;
465500 const info = await fsinfo ( blueprintsDir , [ 'entries' ] , {
466501 superuser : 'try' ,
467502 } ) ;
468503 const entries = Object . entries ( info ?. entries || { } ) ;
469- for ( const bpEntry of entries ) {
504+ for await ( const bpEntry of entries ) {
505+ const bpComposes = await readComposes ( bpEntry [ 0 ] ) ;
506+ if ( ! bpComposes . some ( ( c ) => c . id === queryArg . composeId ) ) {
507+ continue ;
508+ }
509+
470510 const request = await cockpit
471- . file ( path . join ( blueprintsDir , bpEntry [ 0 ] , queryArg . composeId ) )
511+ . file (
512+ path . join (
513+ blueprintsDir ,
514+ bpEntry [ 0 ] ,
515+ queryArg . composeId ,
516+ 'request.json' ,
517+ ) ,
518+ )
472519 . read ( ) ;
520+
521+ const status = await composeStatus (
522+ queryArg . composeId ,
523+ path . join ( blueprintsDir , bpEntry [ 0 ] , queryArg . composeId ) ,
524+ ) ;
525+
473526 return {
474527 data : {
475- image_status : resp . data ?. image_status ,
528+ image_status : status as ImageStatus ,
476529 request : JSON . parse ( request ) ,
477530 } ,
478531 } ;
479532 }
480- return {
481- data : {
482- image_status : '' ,
483- request : { } ,
484- } ,
485- } ;
533+
534+ throw new Error ( 'Compose not found' ) ;
486535 } catch ( error ) {
487536 return { error } ;
488537 }
0 commit comments