@@ -104,6 +104,11 @@ func (cmd *DeployCmd) Run(ctx *Context) error {
104104 return nil
105105 }
106106
107+ // Wait for prerequisites that this module needs.
108+ if err := waitForModulePrereqs (ctx , module ); err != nil {
109+ return err
110+ }
111+
107112 if err := createSystemConfigFromSOS (ctx , system , module ); err != nil {
108113 return err
109114 }
@@ -1044,6 +1049,100 @@ func getExampleOverlay(ctx *Context, system *config.System, module string) (stri
10441049 return "" , nil
10451050}
10461051
1052+ // Modules that require cert-manager webhook to be ready before deploying.
1053+ var modulesCertManager = []string {
1054+ "lustre-fs-operator" ,
1055+ "dws" ,
1056+ "nnf-sos" ,
1057+ }
1058+
1059+ // Modules that require the DWS controller-manager to be ready before deploying,
1060+ // because they use DWS CRDs that have a conversion webhook served by DWS.
1061+ var modulesDWSController = []string {
1062+ "nnf-sos" ,
1063+ "nnf-dm" ,
1064+ }
1065+
1066+ // waitForModulePrereqs waits for prerequisite services that a module depends on.
1067+ func waitForModulePrereqs (ctx * Context , module string ) error {
1068+ if ctx .DryRun {
1069+ return nil
1070+ }
1071+
1072+ for _ , m := range modulesCertManager {
1073+ if m == module {
1074+ if err := waitForCertManagerWebhook (ctx ); err != nil {
1075+ return err
1076+ }
1077+ break
1078+ }
1079+ }
1080+
1081+ for _ , m := range modulesDWSController {
1082+ if m == module {
1083+ if err := waitForDWSControllerManager (ctx ); err != nil {
1084+ return err
1085+ }
1086+ break
1087+ }
1088+ }
1089+
1090+ return nil
1091+ }
1092+
1093+ // waitForCertManagerWebhook waits for the cert-manager webhook to be ready and
1094+ // functional. Modules that create cert-manager Certificate or Issuer resources
1095+ // need this webhook to be operational.
1096+ func waitForCertManagerWebhook (ctx * Context ) error {
1097+ fmt .Println (" Waiting for cert-manager webhook..." )
1098+ cmd := exec .Command ("kubectl" , "wait" , "deploy" , "-n" , "cert-manager" ,
1099+ "--timeout=180s" , "cert-manager-webhook" ,
1100+ "--for" , "jsonpath={.status.availableReplicas}=1" )
1101+ if _ , err := runCommand (ctx , cmd ); err != nil {
1102+ return fmt .Errorf ("cert-manager webhook deployment not ready: %w" , err )
1103+ }
1104+
1105+ // The deployment being available doesn't guarantee the webhook is
1106+ // functional. Verify by attempting a server-side dry-run of an Issuer.
1107+ fmt .Println (" Verifying cert-manager webhook is functional..." )
1108+ for attempts := 0 ; attempts < 60 ; attempts ++ {
1109+ cmd = exec .Command ("kubectl" , "apply" , "--dry-run=server" , "-f" , "-" )
1110+ cmd .Stdin = strings .NewReader (`apiVersion: cert-manager.io/v1
1111+ kind: Issuer
1112+ metadata:
1113+ name: deploy-dryrun-test
1114+ namespace: default
1115+ spec:
1116+ selfSigned: {}
1117+ ` )
1118+ if out , err := cmd .CombinedOutput (); err == nil {
1119+ _ = out
1120+ break
1121+ }
1122+ if attempts == 59 {
1123+ return fmt .Errorf ("cert-manager webhook not functional after 120s" )
1124+ }
1125+ time .Sleep (2 * time .Second )
1126+ }
1127+
1128+ return nil
1129+ }
1130+
1131+ // waitForDWSControllerManager waits for the DWS controller-manager to be fully
1132+ // ready. The DWS controller-manager serves the CRD conversion webhook needed by
1133+ // modules that access DWS custom resources with multiple API versions.
1134+ func waitForDWSControllerManager (ctx * Context ) error {
1135+ fmt .Println (" Waiting for DWS controller-manager..." )
1136+ cmd := exec .Command ("kubectl" , "wait" , "deploy" , "-n" , "dws-system" ,
1137+ "--timeout=180s" , "dws-controller-manager" ,
1138+ "--for" , "jsonpath={.status.availableReplicas}=1" )
1139+ if _ , err := runCommand (ctx , cmd ); err != nil {
1140+ return fmt .Errorf ("DWS controller-manager not ready: %w" , err )
1141+ }
1142+
1143+ return nil
1144+ }
1145+
10471146func deployModule (ctx * Context , system * config.System , module string ) error {
10481147
10491148 cmd := exec .Command ("make" , "deploy" )
0 commit comments