async fn rollout_status(mf: &Manifest, kube: &ShipKube, hash: &Option<String>) -> Result<RolloutResult> {
    match mf.workload {
        PrimaryWorkload::Deployment => {
            // Get root data from Deployment status
            let deploy = kube.get_deploy().await?;
            let d = DeploySummary::try_from(deploy)?;
            debug!("{}: {:?}", mf.name, d);
            // Wait for at least the minimum number...

            let mut acurate_progress = None; // accurate progress number
            let mut minimum = mf.min_replicas(); // minimum replicas we wait for
            if let Some(tpl_hash) = hash {
                // Infer from pinned ReplicaSet status (that was latest during apply)
                if let Some(rs) = kube.get_rs_by_template_hash(&tpl_hash).await? {
                    let r = ReplicaSetSummary::try_from(rs)?;
                    debug!("{}: {:?}", mf.name, r);
                    acurate_progress = Some(r.ready);
                    // rs might have scaled it up during rollout
                    minimum = std::cmp::max(minimum, r.replicas.try_into().unwrap_or(0));
                }
            }

            // Decide whether to stop polling - did the upgrade pass?
            let ok = if let Some(acc) = acurate_progress {
                // Replicaset is scaled to our minimum, and all ready
                // NB: k8s >= 1.15 we could use `d.new_replicas_available`
                // as a better required check
                acc == (minimum as i32)
            // NB: This last && enforces the progress downscaling at the end of fn
            } else {
                // FALLBACK (never seems to really happen): count from deployment only
                // Need to at least have as many ready as expected
                // ...it needs to have been scaled to the correct minimum
                // ...and, either we have the explicit progress done, or all unavailables are gone
                // The last condition (which increases waiting time) is necessary because:
                // deployment summary aggregates up the total number of ready pods
                // so we won't really know we're done or not unless we got the go-ahead
                // (i.e. d.new_replicas_available in k8s >= 1.15),
                // or all the unavailable pods have been killed (indicating total completeness)
                d.ready == d.replicas
                    && d.ready >= minimum as i32
                    && (d.new_replicas_available || d.unavailable <= 0)
            };

            //  What to tell our progress bar:
            let progress: i32 = match acurate_progress {
                // 99% case: the number from our accurately matched replicaset:
                Some(p) => p,

                // Otherwise estimate based on deployment.status data
                // Slightly weird data because of replicasets worth of data is here..
                // There might be more than one deployment in progress, all of which surge..
                None => std::cmp::max(0, d.ready - d.unavailable),
            };
            Ok(RolloutResult {
                progress: progress.try_into().expect("progress >= 0"),
                expected: minimum,
                message: d.message,
                ok,
            })
        }
        PrimaryWorkload::Statefulset => {
            let ss = kube.get_statefulset().await?;
            let s = StatefulSummary::try_from(ss)?;
            let minimum = mf.min_replicas();

            let ok = s.updated_replicas >= minimum as i32
                && s.updated_replicas == s.ready
                && s.update_revision == *hash;
            let message = if ok {
                None
            } else {
                Some("Statefulset update in progress".to_string())
            };

            // NB: Progress is slightly optimistic because updated_replicas increment
            // as soon as the old replica is replaced, not when it's ready.
            // (we can't use ready_replicas because that counts the sum of old + new)
            // But this is OK. If it gets to 3/3 then at least 2 rolled out successfully,
            // and the third was started. The only other way of getting around that
            // would be tracking the pods with the new hash directly..

            // Note that while progressbar is optimistic, it's not marked as ok (done)
            // until the new revision is changed over (when sts controller thinks it's done)
            // So this is a progressbar only inconsistency.
            Ok(RolloutResult {
                progress: std::cmp::max(0, s.updated_replicas)
                    .try_into()
                    .expect("sts.updated_replicas >= 0"),
                expected: minimum,
                message: message,
                ok,
            })
        }
    }
}
/// Check if a rollout has completed
Check if a rollout has completed
Check if a rollout has completed
async fn rollout_status(mf: &Manifest, kube: &ShipKube, hash: &Option<String>) -> Result<RolloutResult> {
    match mf.workload {
        PrimaryWorkload::Deployment => {
            // Get root data from Deployment status
            let deploy = kube.get_deploy().await?;
            let d = DeploySummary::try_from(deploy)?;
            debug!("{}: {:?}", mf.name, d);
            // Wait for at least the minimum number...
            let mut acurate_progress = None; // accurate progress number
            let mut minimum = mf.min_replicas(); // minimum replicas we wait for
            if let Some(tpl_hash) = hash {
                // Infer from pinned ReplicaSet status (that was latest during apply)
                if let Some(rs) = kube.get_rs_by_template_hash(&tpl_hash).await? {
                    let r = ReplicaSetSummary::try_from(rs)?;
                    debug!("{}: {:?}", mf.name, r);
                    acurate_progress = Some(r.ready);
                    // rs might have scaled it up during rollout
                    minimum = std::cmp::max(minimum, r.replicas.try_into().unwrap_or(0));
                }
            }
            // Decide whether to stop polling - did the upgrade pass?
            let ok = if let Some(acc) = acurate_progress {
                // Replicaset is scaled to our minimum, and all ready
                // NB: k8s >= 1.15 we could use `d.new_replicas_available`
                // as a better required check
                acc == (minimum as i32)
            // NB: This last && enforces the progress downscaling at the end of fn
            } else {
                // FALLBACK (never seems to really happen): count from deployment only
                // Need to at least have as many ready as expected
                // ...it needs to have been scaled to the correct minimum
                // ...and, either we have the explicit progress done, or all unavailables are gone
                // The last condition (which increases waiting time) is necessary because:
                // deployment summary aggregates up the total number of ready pods
                // so we won't really know we're done or not unless we got the go-ahead
                // (i.e. d.new_replicas_available in k8s >= 1.15),
                // or all the unavailable pods have been killed (indicating total completeness)
                d.ready == d.replicas
                    && d.ready >= minimum as i32
                    && (d.new_replicas_available || d.unavailable <= 0)
            };
            //  What to tell our progress bar:
            let progress: i32 = match acurate_progress {
                // 99% case: the number from our accurately matched replicaset:
                Some(p) => p,
                // Otherwise estimate based on deployment.status data
                // Slightly weird data because of replicasets worth of data is here..
                // There might be more than one deployment in progress, all of which surge..
                None => std::cmp::max(0, d.ready - d.unavailable),
            };
            Ok(RolloutResult {
                progress: progress.try_into().expect("progress >= 0"),
                expected: minimum,
                message: d.message,
                ok,
            })
        }
        PrimaryWorkload::Statefulset => {
            let ss = kube.get_statefulset().await?;
            let s = StatefulSummary::try_from(ss)?;
            let minimum = mf.min_replicas();
            let ok = s.updated_replicas >= minimum as i32
                && s.updated_replicas == s.ready
                && s.update_revision == *hash;
            let message = if ok {
                None
            } else {
                Some("Statefulset update in progress".to_string())
            };
            // NB: Progress is slightly optimistic because updated_replicas increment
            // as soon as the old replica is replaced, not when it's ready.
            // (we can't use ready_replicas because that counts the sum of old + new)
            // But this is OK. If it gets to 3/3 then at least 2 rolled out successfully,
            // and the third was started. The only other way of getting around that
            // would be tracking the pods with the new hash directly..
            // Note that while progressbar is optimistic, it's not marked as ok (done)
            // until the new revision is changed over (when sts controller thinks it's done)
            // So this is a progressbar only inconsistency.
            Ok(RolloutResult {
                progress: std::cmp::max(0, s.updated_replicas)
                    .try_into()
                    .expect("sts.updated_replicas >= 0"),
                expected: minimum,
                message: message,
                ok,
            })
        }
    }
}
async fn rollout_status ( mf : & Manifest , kube : & ShipKube , hash : & Option < String > ) -> Result < RolloutResult > { match mf . workload { PrimaryWorkload :: Deployment => { // Get root data from Deployment status let deploy = kube . get_deploy ( ) . await ? ; let d = DeploySummary :: try_from ( deploy ) ? ; debug ! ( " " mf name d ) ; // Wait for at least the minimum number... let mut acurate_progress = None ; // accurate progress number let mut minimum = mf . min_replicas ( ) ; // minimum replicas we wait for if let Some ( tpl_hash ) = hash { // Infer from pinned ReplicaSet status (that was latest during apply) if let Some ( rs ) = kube . get_rs_by_template_hash ( & tpl_hash ) . await ? { let r = ReplicaSetSummary :: try_from ( rs ) ? ; debug ! ( " " mf name r ) ; acurate_progress = Some ( r . ready ) ; // rs might have scaled it up during rollout minimum = std :: cmp :: max ( minimum , r . replicas . try_into ( ) . unwrap_or ( 0 ) ) ; } } // Decide whether to stop polling - did the upgrade pass? let ok = if let Some ( acc ) = acurate_progress { // Replicaset is scaled to our minimum, and all ready // NB: k8s >= 1.15 we could use `d.new_replicas_available` // as a better required check acc == ( minimum as i32 ) // NB: This last && enforces the progress downscaling at the end of fn } else { // FALLBACK (never seems to really happen): count from deployment only // Need to at least have as many ready as expected // ...it needs to have been scaled to the correct minimum // ...and, either we have the explicit progress done, or all unavailables are gone // The last condition (which increases waiting time) is necessary because: // deployment summary aggregates up the total number of ready pods // so we won't really know we're done or not unless we got the go-ahead // (i.e. d.new_replicas_available in k8s >= 1.15), // or all the unavailable pods have been killed (indicating total completeness) d . ready == d . replicas && d . ready >= minimum as i32 && ( d . new_replicas_available || d . unavailable <= 0 ) } ; //  What to tell our progress bar: let progress : i32 = match acurate_progress { // 99% case: the number from our accurately matched replicaset: Some ( p ) => p , // Otherwise estimate based on deployment.status data // Slightly weird data because of replicasets worth of data is here.. // There might be more than one deployment in progress, all of which surge.. None => std :: cmp :: max ( 0 , d . ready - d . unavailable ) , } ; Ok ( RolloutResult { progress : progress . try_into ( ) . expect ( " " ) , expected : minimum , message : d . message , ok , } ) } PrimaryWorkload :: Statefulset => { let ss = kube . get_statefulset ( ) . await ? ; let s = StatefulSummary :: try_from ( ss ) ? ; let minimum = mf . min_replicas ( ) ; let ok = s . updated_replicas >= minimum as i32 && s . updated_replicas == s . ready && s . update_revision == * hash ; let message = if ok { None } else { Some ( " " . to_string ( ) ) } ; // NB: Progress is slightly optimistic because updated_replicas increment // as soon as the old replica is replaced, not when it's ready. // (we can't use ready_replicas because that counts the sum of old + new) // But this is OK. If it gets to 3/3 then at least 2 rolled out successfully, // and the third was started. The only other way of getting around that // would be tracking the pods with the new hash directly.. // Note that while progressbar is optimistic, it's not marked as ok (done) // until the new revision is changed over (when sts controller thinks it's done) // So this is a progressbar only inconsistency. Ok ( RolloutResult { progress : std :: cmp :: max ( 0 , s . updated_replicas ) . try_into ( ) . expect ( " " ) , expected : minimum , message : message , ok , } ) } } }
Check if a rollout has completed
Check if a rollout has completed
mf
&Manifest
kube
&ShipKube
hash
&Option<String>
mf
&Manifest
kube
&ShipKube
hash
&Option<String>