diff --git a/api/k8s/v1beta4/k8s_helpers.go b/api/k8s/v1beta4/k8s_helpers.go index 66ae31d87..4e122734a 100644 --- a/api/k8s/v1beta4/k8s_helpers.go +++ b/api/k8s/v1beta4/k8s_helpers.go @@ -47,3 +47,91 @@ func (s *API) WaitForCluster(req *WaitForClusterRequest) (*Cluster, error) { } return cluster.(*Cluster), nil } + +func (s *API) getNodesWhenReady(req *ListNodesRequest, expectedCount uint32) (bool, error) { + res, err := s.ListNodes(req, scw.WithAllPages()) + if err != nil { + return false, err + } + + // first check that we have the right nodes count + if res.TotalCount != expectedCount { + return false, nil + } + + // then check that each node has Ready status + for _, node := range res.Nodes { + if node.Status != NodeStatusReady { + return false, nil + } + } + + return true, nil +} + +// WaitForClusterNodesReadyRequest is used by WaitForClusterNodesReady method. +type WaitForClusterNodesReadyRequest struct { + ClusterID string + Region scw.Region + Timeout time.Duration +} + +// WaitForClusterNodesReady waits for the nodes of a cluster to be ready +func (s *API) WaitForClusterNodesReady(req *WaitForClusterNodesReadyRequest) error { + pools, err := s.ListPools(&ListPoolsRequest{ + ClusterID: req.ClusterID, + Region: req.Region, + }) + if err != nil { + return err + } + + for _, pool := range pools.Pools { + err = s.WaitForPoolNodesReady(&WaitForPoolNodesReadyRequest{ + PoolID: pool.ID, + Timeout: req.Timeout, + }) + + if err != nil { + return err + } + } + + return nil +} + +// WaitForPoolNodesReadyRequest is used by WaitForPoolNodesReady method. +type WaitForPoolNodesReadyRequest struct { + PoolID string + Timeout time.Duration +} + +// WaitForPoolNodesReady waits for the nodes of a pool to be ready +func (s *API) WaitForPoolNodesReady(req *WaitForPoolNodesReadyRequest) error { + pool, err := s.GetPool(&GetPoolRequest{ + PoolID: req.PoolID, + }) + if err != nil { + return err + } + + r := &ListNodesRequest{ + ClusterID: pool.ClusterID, + PoolID: &req.PoolID, + } + + _, err = async.WaitSync(&async.WaitSyncConfig{ + Get: func() (interface{}, bool, error) { + ok, err := s.getNodesWhenReady(r, pool.Size) + if err != nil { + return nil, ok, err + } + + return nil, ok, nil + }, + Timeout: req.Timeout, + IntervalStrategy: async.LinearIntervalStrategy(5 * time.Second), + }) + + return err +}