@@ -2,17 +2,21 @@ package services
22
33import (
44 "context"
5+ "encoding/json"
6+ "fmt"
57 "log/slog"
8+ "net/http"
9+ "strings"
610 "time"
711
812 "github.com/ca-gip/kubi/internal/utils"
913 cagipv1 "github.com/ca-gip/kubi/pkg/apis/cagip/v1"
1014 "github.com/ca-gip/kubi/pkg/generated/clientset/versioned"
1115 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1216 "k8s.io/apimachinery/pkg/util/wait"
17+ kubernetes "k8s.io/client-go/kubernetes"
1318 "k8s.io/client-go/rest"
1419 "k8s.io/client-go/tools/cache"
15- kubernetes "k8s.io/client-go/kubernetes"
1620)
1721
1822// Watch NetworkPolicyConfig, which is a config object for namespace network bubble
@@ -63,7 +67,6 @@ func projectUpdated(old interface{}, new interface{}) {
6367 createOrUpdateProjectResources (project )
6468}
6569
66-
6770func createOrUpdateProjectResources (project * cagipv1.Project ) {
6871
6972 if err := generateNamespace (project ); err != nil {
@@ -110,6 +113,19 @@ func projectDeleted(obj interface{}) {
110113}
111114
112115func deleteProjectResources (project * cagipv1.Project ) {
116+ //verify that project exists in other clusters
117+ err := checkProjectExistsInOtherClusters (project )
118+ if err != nil {
119+ slog .Error ("check KGB API failed" , "project" , project .Name , "error" , err )
120+ return
121+ }
122+ // Check if there are any pods in the namespace
123+ err = checkPodExistsInNamespace (project .Name )
124+ if err != nil {
125+ slog .Error ("pods still exist in namespace, cannot delete resources" , "namespace" , project .Name , "error" , err )
126+ return
127+ }
128+
113129 // Delete role bindings first
114130 if err := deleteRoleBindings (project .Name ); err != nil {
115131 slog .Error ("failed to delete role bindings" , "namespace" , project .Name , "error" , err )
@@ -149,6 +165,46 @@ func deleteProjectResources(project *cagipv1.Project) {
149165 }
150166}
151167
168+ func checkProjectExistsInOtherClusters (project * cagipv1.Project ) error {
169+ //call kgb api https://kgb-api.devops.caas.cagip.group.gca/api/v1/clusters for see if project exists in other clusters
170+ //call kgb api
171+ client := & http.Client {Timeout : 90 * time .Second }
172+ apiURL := fmt .Sprintf ("%s/api/v1/clusters" , utils .Config .KgbApiURL )
173+ resp , err := client .Get (apiURL )
174+ if err != nil {
175+ return err
176+ }
177+ if resp != nil {
178+ defer resp .Body .Close ()
179+ }
180+
181+ if resp .StatusCode != 200 {
182+ return fmt .Errorf ("unexpected status code for call KGB API: %d" , resp .StatusCode )
183+ }
184+
185+ var clusters []struct {
186+ Projects []string `json:"projects"`
187+ }
188+ if err := json .NewDecoder (resp .Body ).Decode (& clusters ); err != nil {
189+ return err
190+ }
191+
192+ var listExistClusters []string = []string {}
193+ var i int = 0
194+ for _ , cluster := range clusters {
195+ for _ , p := range cluster .Projects {
196+ if strings .Contains (p , project .Name ) {
197+ i ++
198+ listExistClusters = append (listExistClusters , p )
199+ }
200+ }
201+ }
202+ if i == 1 {
203+ return nil
204+ }
205+ return fmt .Errorf ("project %s exists in other clusters: %v" , project .Name , listExistClusters )
206+ }
207+
152208func deleteNamespace (namespaceName string ) error {
153209 kconfig , _ := rest .InClusterConfig ()
154210 clientSet , err := kubernetes .NewForConfig (kconfig )
@@ -189,6 +245,25 @@ func deleteRoleBindings(namespaceName string) error {
189245 // Delete all role bindings in the namespace that were created by Kubi
190246 return clientSet .RbacV1 ().RoleBindings (namespaceName ).DeleteCollection (context .TODO (), metav1.DeleteOptions {}, metav1.ListOptions {
191247 LabelSelector : "creator=kubi" ,
192- })
248+ })
193249}
194250
251+ // checkPodExistsInNamespace returns an error if there are any pods in the given namespace.
252+ func checkPodExistsInNamespace (namespace string ) error {
253+ kconfig , err := rest .InClusterConfig ()
254+ if err != nil {
255+ return err
256+ }
257+ clientSet , err := kubernetes .NewForConfig (kconfig )
258+ if err != nil {
259+ return err
260+ }
261+ pods , err := clientSet .CoreV1 ().Pods (namespace ).List (context .TODO (), metav1.ListOptions {})
262+ if err != nil {
263+ return err
264+ }
265+ if len (pods .Items ) > 0 {
266+ return fmt .Errorf ("there are still %d pods in namespace %s" , len (pods .Items ), namespace )
267+ }
268+ return nil
269+ }
0 commit comments