Skip to content

Commit 5517d67

Browse files
committed
add checks for existing projects and pods
1 parent 7875045 commit 5517d67

File tree

3 files changed

+81
-4
lines changed

3 files changed

+81
-4
lines changed

internal/services/project-operator.go

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,21 @@ package services
22

33
import (
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-
6770
func createOrUpdateProjectResources(project *cagipv1.Project) {
6871

6972
if err := generateNamespace(project); err != nil {
@@ -110,6 +113,19 @@ func projectDeleted(obj interface{}) {
110113
}
111114

112115
func 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+
152208
func 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+
}

internal/utils/config.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ func MakeConfig() (*types.Config, error) {
194194
PodSecurityAdmissionWarning: podSecurityAdmissionWarning,
195195
PodSecurityAdmissionAudit: podSecurityAdmissionAudit,
196196
Ldap: types.LdapConfig{
197-
UserBase: ldapUserBase,
197+
UserBase: ldapUserBase,
198198
EligibleGroupsParents: ldapEligibleGroupsParents,
199199
GroupBase: ldapGroupBase,
200200
AppMasterGroupBase: getEnv("LDAP_APP_GROUPBASE", ""),
@@ -234,6 +234,7 @@ func MakeConfig() (*types.Config, error) {
234234
Blacklist: strings.Split(getEnv("BLACKLIST", ""), ","),
235235
Whitelist: whitelist,
236236
BlackWhitelistNamespace: getEnv("BLACK_WHITELIST_NAMESPACE", "default"),
237+
KgbApiURL: getEnv("KGB_API_URL", "https://kgb-api.devops.caas.cagip.group.gca"),
237238
}, nil
238239
}
239240

pkg/types/types.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ type Config struct {
5454
Blacklist []string
5555
BlackWhitelistNamespace string
5656
Whitelist bool
57+
KgbApiURL string
5758
}
5859

5960
// Note: struct fields must be public in order for unmarshal to

0 commit comments

Comments
 (0)