Skip to content

Commit

Permalink
add delete PV
Browse files Browse the repository at this point in the history
  • Loading branch information
santinoncs committed Jan 15, 2024
1 parent ef655a0 commit 18d6af1
Show file tree
Hide file tree
Showing 7 changed files with 80 additions and 34 deletions.
40 changes: 29 additions & 11 deletions internal/app/processing.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@ package app

import (
"github.com/softonic/cloud-disks-cleaner/pkg/gcp"
"github.com/softonic/cloud-disks-cleaner/pkg/kubernetes"
"github.com/softonic/cloud-disks-cleaner/pkg/usage"
"google.golang.org/api/compute/v1"
"k8s.io/klog"
)

func ProcessUnusedDisks(gcpChecker usage.Checker, k8sChecker usage.Checker) ([]string, error) {
func ProcessUnusedDisks(gcpChecker usage.Checker, k8sChecker usage.Checker) ([]string, []string, error) {

disksToBeRemoved := []string{}
pvsToBeRemoved := []string{}

computeDisks, err := gcpChecker.ListResources()
if err != nil {
return nil, err
return nil, nil, err
}

for _, diskInterface := range computeDisks {
Expand All @@ -22,37 +24,53 @@ func ProcessUnusedDisks(gcpChecker usage.Checker, k8sChecker usage.Checker) ([]s
klog.Errorf("Error: expected item of type compute.Disk, got %T", diskInterface)
continue // skip to the next disk if there's a type mismatch
}
isNotUsedByAnyNode, err := gcpChecker.IsResourceUnused(disk.Name)
isNotUsedByAnyNode, _, err := gcpChecker.IsResourceUnused(disk.Name)
if err == nil && !isNotUsedByAnyNode {
continue
} else if err != nil {
klog.Errorf("Error checking usage of disk %s: %v", disk.Name, err)
return nil, err
return nil, nil, err
}

isUnused, err := k8sChecker.IsResourceUnused(disk.Name)
isUnused, pvName, err := k8sChecker.IsResourceUnused(disk.Name)
if err != nil {
klog.Errorf("Error checking usage of disk %s: %v", disk.Name, err)
continue // skip to the next disk if there's an error
}

if isUnused {
disksToBeRemoved = append(disksToBeRemoved, disk.Name)
pvsToBeRemoved = append(pvsToBeRemoved, pvName)
}

klog.Infof("list of pvs => %v", pvsToBeRemoved)

}
return disksToBeRemoved, nil
return disksToBeRemoved, pvsToBeRemoved, nil
}

func RemoveUnusedDisks(gcpDeleter *gcp.GCPDeleter, disks []string) {

for _, disk := range disks {
klog.Infof("Delete disk %s", disk)
err := gcpDeleter.DeleteResource("disk", disk)
if err != nil {
klog.Errorf("Failed to delete disk %s: %v", disk, err)
continue
}
/* err := gcpDeleter.DeleteResource("disk", disk)
if err != nil {
klog.Errorf("Failed to delete disk %s: %v", disk, err)
continue
} */
}

}

func RemoveUnusedPVs(k8sDeleter *kubernetes.K8sDeleter, pvs []string) {

for _, PV := range pvs {
klog.Infof("Delete PV %s", PV)

/* err := k8sDeleter.DeleteResource(PV)
if err != nil {
klog.Errorf("Failed to delete PV %s: %v", PV, err)
continue
} */
}
}
27 changes: 17 additions & 10 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ func main() {
}

// Initialize services
gcpChecker, gcpDeleter, k8sChecker, err := initializeServices(projectID, zone)
gcpChecker, gcpDeleter, k8sChecker, k8sDeleter, err := initializeServices(projectID, zone)
if err != nil {
errorhandling.HandleCriticalError(err)
}

// Execute the app
runApplication(gcpChecker, gcpDeleter, k8sChecker)
runApplication(gcpChecker, gcpDeleter, k8sChecker, k8sDeleter)

}

Expand All @@ -63,7 +63,7 @@ func loadConfiguration() (projectID string, zone string, err error) {
return projectID, zone, nil
}

func initializeServices(projectID string, zone string) (usage.Checker, *gcp.GCPDeleter, usage.Checker, error) {
func initializeServices(projectID string, zone string) (usage.Checker, *gcp.GCPDeleter, usage.Checker, *kubernetes.K8sDeleter, error) {

ctx := context.Background()

Expand All @@ -75,12 +75,12 @@ func initializeServices(projectID string, zone string) (usage.Checker, *gcp.GCPD
gcpChecker, err := gcp.NewGCPChecker(computeService, projectID, zone)
if err != nil {
klog.Errorf("Failed to create GCP checker: %v", err)
return nil, nil, nil, err
return nil, nil, nil, nil, err
}

gcpDeleter, err := gcp.NewGCPDeleter(computeService, projectID, zone)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}

// k8s init
Expand All @@ -89,27 +89,34 @@ func initializeServices(projectID string, zone string) (usage.Checker, *gcp.GCPD

clientset, err := kubernetes.NewKubernetesService(false, kubeConfig)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}

k8sChecker, err := kubernetes.NewK8sChecker(clientset)
if err != nil {
//klog.Errorf("Failed to create k8s checker: %v", err)
return nil, nil, nil, err
return nil, nil, nil, nil, err
}

return gcpChecker, gcpDeleter, k8sChecker, nil
// Remove the unused variable declaration and assignment
k8sDeleter, err := kubernetes.NewK8sDeleter(clientset)
if err != nil {
return nil, nil, nil, nil, err
}

return gcpChecker, gcpDeleter, k8sChecker, k8sDeleter, nil

}

func runApplication(gcpChecker usage.Checker, gcpDeleter *gcp.GCPDeleter, k8sChecker usage.Checker) {
func runApplication(gcpChecker usage.Checker, gcpDeleter *gcp.GCPDeleter, k8sChecker usage.Checker, k8sDeleter *kubernetes.K8sDeleter) {
// app

disks, err := app.ProcessUnusedDisks(gcpChecker, k8sChecker)
disks, pvs, err := app.ProcessUnusedDisks(gcpChecker, k8sChecker)
if err != nil {
klog.Errorf("Failed to process unused disks: %v", err)
}

app.RemoveUnusedDisks(gcpDeleter, disks)
app.RemoveUnusedPVs(k8sDeleter, pvs)

}
6 changes: 3 additions & 3 deletions pkg/gcp/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@ func NewGCPChecker(service ComputeService, projectID string, zone string) (*GCPC
}, nil
}

func (c *GCPChecker) IsResourceUnused(resourceID string) (bool, error) {
func (c *GCPChecker) IsResourceUnused(resourceID string) (bool, string, error) {
ctx := context.Background()

disk, err := c.service.DisksGet(ctx, c.projectID, c.zone, resourceID)
if err != nil {
return false, err // Si hay un error, retorna false y el error.
return false, "", err // Si hay un error, retorna false y el error.
}

// Verifica si el disco está en uso.
// En este ejemplo, supondremos que un disco se considera en uso si tiene usuarios asociados.
isUnused := len(disk.Users) == 0

return isUnused, nil // Retorna el resultado de la verificación y nil para el error.
return isUnused, resourceID, nil // Retorna el resultado de la verificación y nil para el error.
}

func (c *GCPChecker) ListResources() ([]interface{}, error) {
Expand Down
18 changes: 9 additions & 9 deletions pkg/kubernetes/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,16 @@ func NewK8sChecker(clientset kubernetesService) (*K8sChecker, error) {
// se puede borrar
// Si existe el PV y el PVC al que está asociado tambien existe, aunque el estado sea Released
// no borraremos el disco, como medida de precaucion.
func (c *K8sChecker) IsResourceUnused(resourceID string) (bool, error) {
func (c *K8sChecker) IsResourceUnused(resourceID string) (bool, string, error) {
// En este caso, asumiremos que resourceID es el nombre del PersistentVolume en Kubernetes.
pv, err := c.getPVFromDisk(resourceID)
pv, err := c.GetPVFromDisk(resourceID)
if err != nil {
return false, err
return false, "", err
}

if pv == nil {
klog.Infof("PV was not found. Disk => %s", resourceID)
return true, nil
return true, "", nil
}

// Verifica si el PersistentVolume está en uso.
Expand All @@ -56,30 +56,30 @@ func (c *K8sChecker) IsResourceUnused(resourceID string) (bool, error) {
// El PVC no se encontró, por lo que el recurso no está siendo utilizado.
// Pero por seguridad no vamos a eliminar el disco. Quiza será utilizado en el futuro.
klog.Infof("The pvc bind to the disk: %s does not exists", resourceID)
return false, nil
return false, "", nil
}
return false, err
return false, "", err
}

isBound, err := c.isPVCBoundToPV(pv.Name, pvc.Namespace, pvc.Name)
if err != nil {
return false, err
return false, "", err
}

isUnused := !isBound // Invierte la lógica: si no está vinculado, entonces no está en uso.
if isUnused {
klog.Infof("PV was found, PVC was found, but pvc and pv are not binded. Disk => %s", resourceID)
}

return isUnused, nil // Retorna el resultado de la verificación y nil para el error.
return isUnused, pv.Name, nil // Retorna el resultado de la verificación y nil para el error.
}

func (c *K8sChecker) ListResources() ([]interface{}, error) {
// Retornar nil o una lista vacía, o tal vez un error que indique que esta operación no está soportada.
return nil, nil
}

func (c *K8sChecker) getPVFromDisk(diskName string) (*v1.PersistentVolume, error) {
func (c *K8sChecker) GetPVFromDisk(diskName string) (*v1.PersistentVolume, error) {
if c == nil {
return nil, errors.New("clientset is nil")
}
Expand Down
6 changes: 6 additions & 0 deletions pkg/kubernetes/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func NewKubernetesService(inCluster bool, k8sConfig string) (kubernetesService,
type kubernetesService interface {
PersistentVolumesList() (*v1.PersistentVolumeList, error)
PersistentVolumeClaimsGet(pvcName string, pvcNamespace string) (*v1.PersistentVolumeClaim, error)
PersistentVolumeDelete(persistentVolumeName string) error
}

type clientsetimpl struct {
Expand All @@ -49,3 +50,8 @@ func (c *clientsetimpl) PersistentVolumesList() (*v1.PersistentVolumeList, error
func (c *clientsetimpl) PersistentVolumeClaimsGet(pvcName string, pvcNamespace string) (*v1.PersistentVolumeClaim, error) {
return c.clientset.CoreV1().PersistentVolumeClaims(pvcNamespace).Get(pvcName, metav1.GetOptions{})
}

func (c *clientsetimpl) PersistentVolumeDelete(persistentVolumeName string) error {
err := c.clientset.CoreV1().PersistentVolumes().Delete(persistentVolumeName, &metav1.DeleteOptions{})
return err
}
15 changes: 15 additions & 0 deletions pkg/kubernetes/deleter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package kubernetes

type K8sDeleter struct {
clientset kubernetesService
}

func NewK8sDeleter(clientset kubernetesService) (*K8sDeleter, error) {
return &K8sDeleter{
clientset: clientset,
}, nil
}

func (d *K8sDeleter) DeleteResource(resourceID string) error {
return d.clientset.PersistentVolumeDelete(resourceID)
}
2 changes: 1 addition & 1 deletion pkg/usage/interface.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package usage

type Checker interface {
IsResourceUnused(resourceID string) (bool, error)
IsResourceUnused(resourceID string) (bool, string, error)
ListResources() ([]interface{}, error)
}

0 comments on commit 18d6af1

Please sign in to comment.