@@ -20,10 +20,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
2020package cluster
2121
2222import (
23+ "context"
24+ "fmt"
2325 "slices"
2426
2527 "golang.org/x/exp/maps"
2628 "k8s.io/apimachinery/pkg/api/meta"
29+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
30+ "sigs.k8s.io/controller-runtime/pkg/client"
2731
2832 appsv1 "github.com/apecloud/kubeblocks/apis/apps/v1"
2933 "github.com/apecloud/kubeblocks/pkg/controller/graph"
@@ -41,7 +45,7 @@ func (t *clusterStatusTransformer) Transform(ctx graph.TransformContext, dag *gr
4145 graphCli , _ := transCtx .Client .(model.GraphClient )
4246
4347 defer func () { t .markClusterDagStatusAction (graphCli , dag , origCluster , cluster ) }()
44- if err := t .reconcileClusterStatus (cluster ); err != nil {
48+ if err := t .reconcileClusterStatus (transCtx . Context , transCtx . Client , cluster ); err != nil {
4549 return err
4650 }
4751 return nil
@@ -53,13 +57,12 @@ func (t *clusterStatusTransformer) markClusterDagStatusAction(graphCli model.Gra
5357 }
5458}
5559
56- func (t * clusterStatusTransformer ) reconcileClusterStatus (cluster * appsv1.Cluster ) error {
60+ func (t * clusterStatusTransformer ) reconcileClusterStatus (ctx context. Context , cli client. Reader , cluster * appsv1.Cluster ) error {
5761 if len (cluster .Status .Components ) == 0 && len (cluster .Status .Shardings ) == 0 {
5862 return nil
5963 }
60- oldPhase := t .reconcileClusterPhase (cluster )
61- t .syncClusterConditions (cluster , oldPhase )
62- return nil
64+ t .reconcileClusterPhase (cluster )
65+ return t .syncClusterConditions (ctx , cli , cluster )
6366}
6467
6568func (t * clusterStatusTransformer ) reconcileClusterPhase (cluster * appsv1.Cluster ) appsv1.ClusterPhase {
@@ -89,29 +92,99 @@ func (t *clusterStatusTransformer) reconcileClusterPhase(cluster *appsv1.Cluster
8992 return phase
9093}
9194
92- func (t * clusterStatusTransformer ) syncClusterConditions (cluster * appsv1. Cluster , oldPhase appsv1.ClusterPhase ) {
93- if cluster .Status .Phase == appsv1 .RunningClusterPhase && oldPhase != cluster . Status . Phase {
95+ func (t * clusterStatusTransformer ) syncClusterConditions (ctx context. Context , cli client. Reader , cluster * appsv1.Cluster ) error {
96+ if cluster .Status .Phase == appsv1 .RunningClusterPhase {
9497 meta .SetStatusCondition (& cluster .Status .Conditions , newClusterReadyCondition (cluster .Name ))
95- return
98+ } else {
99+ kindNames := map [string ][]string {}
100+ for kind , statusMap := range map [string ]map [string ]appsv1.ClusterComponentStatus {
101+ "component" : cluster .Status .Components ,
102+ "sharding" : t .shardingToCompStatus (cluster .Status .Shardings ),
103+ } {
104+ for name , status := range statusMap {
105+ if status .Phase == appsv1 .FailedComponentPhase {
106+ if _ , ok := kindNames [kind ]; ! ok {
107+ kindNames [kind ] = []string {}
108+ }
109+ kindNames [kind ] = append (kindNames [kind ], name )
110+ }
111+ }
112+ }
113+ if len (kindNames ) > 0 {
114+ meta .SetStatusCondition (& cluster .Status .Conditions , newClusterNotReadyCondition (cluster .Name , kindNames ))
115+ }
96116 }
97117
98- kindNames := map [string ][]string {}
99- for kind , statusMap := range map [string ]map [string ]appsv1.ClusterComponentStatus {
100- "component" : cluster .Status .Components ,
101- "sharding" : t .shardingToCompStatus (cluster .Status .Shardings ),
102- } {
103- for name , status := range statusMap {
104- if status .Phase == appsv1 .FailedComponentPhase {
105- if _ , ok := kindNames [kind ]; ! ok {
106- kindNames [kind ] = []string {}
118+ setAvailableCondition := func () error {
119+ comps , shardingComps , err := listClusterComponents (ctx , cli , cluster )
120+ if err != nil {
121+ return err
122+ }
123+ available := true
124+ aggregatedMessage := ""
125+ defer func () {
126+ var condition metav1.Condition
127+ if available {
128+ condition = metav1.Condition {
129+ Type : appsv1 .ConditionTypeAvailable ,
130+ Status : metav1 .ConditionTrue ,
131+ Message : "All components are available" ,
132+ Reason : "Available" ,
133+ }
134+ } else {
135+ condition = metav1.Condition {
136+ Type : appsv1 .ConditionTypeAvailable ,
137+ Status : metav1 .ConditionFalse ,
138+ Message : aggregatedMessage ,
139+ Reason : "Unavailable" ,
107140 }
108- kindNames [kind ] = append (kindNames [kind ], name )
109141 }
142+
143+ meta .SetStatusCondition (& cluster .Status .Conditions , condition )
144+ }()
145+
146+ if len (comps ) == 0 && len (shardingComps ) == 0 {
147+ available = false
148+ aggregatedMessage = "no component exists; "
149+ return nil
110150 }
151+
152+ for _ , comp := range comps {
153+ compCond := meta .FindStatusCondition (comp .Status .Conditions , appsv1 .ConditionTypeAvailable )
154+ if compCond != nil {
155+ if compCond .Status != metav1 .ConditionTrue {
156+ available = false
157+ message := fmt .Sprintf ("component %s is not available" , comp .Name )
158+ aggregatedMessage += message + "; "
159+ }
160+ } else {
161+ available = false
162+ message := fmt .Sprintf ("component %s has no available condition" , comp .Name )
163+ aggregatedMessage += message + "; "
164+ }
165+ }
166+
167+ for shardingName , comps := range shardingComps {
168+ for _ , comp := range comps {
169+ compCond := meta .FindStatusCondition (comp .Status .Conditions , appsv1 .ConditionTypeAvailable )
170+ if compCond != nil {
171+ if compCond .Status != metav1 .ConditionTrue {
172+ available = false
173+ message := fmt .Sprintf ("component %s of sharding %s is not available" , comp .Name , shardingName )
174+ aggregatedMessage += message + "; "
175+ }
176+ } else {
177+ available = false
178+ message := fmt .Sprintf ("component %s of sharding %s has no available condition" , comp .Name , shardingName )
179+ aggregatedMessage += message + "; "
180+ }
181+ }
182+ }
183+
184+ return nil
111185 }
112- if len (kindNames ) > 0 {
113- meta .SetStatusCondition (& cluster .Status .Conditions , newClusterNotReadyCondition (cluster .Name , kindNames ))
114- }
186+
187+ return setAvailableCondition ()
115188}
116189
117190func (t * clusterStatusTransformer ) shardingToCompStatus (shardingStatus map [string ]appsv1.ClusterShardingStatus ) map [string ]appsv1.ClusterComponentStatus {
0 commit comments