Skip to content

Commit

Permalink
Add unit tests to ConfigMap and Secret
Browse files Browse the repository at this point in the history
Resolves VT-1387
  • Loading branch information
zugao authored and ccremer committed Aug 5, 2020
1 parent 289dde1 commit 40114b7
Show file tree
Hide file tree
Showing 13 changed files with 857 additions and 233 deletions.
69 changes: 3 additions & 66 deletions cmd/common.go
Expand Up @@ -9,7 +9,6 @@ import (
"github.com/appuio/seiso/pkg/openshift"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/thoas/go-funk"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand All @@ -24,21 +23,6 @@ func DeleteImages(imageTags []string, imageName string, namespace string) {
}
}

// DeleteResources deletes a list of ConfigMaps or secrets
func DeleteResources(resources []cfg.KubernetesResource, resourceSelectorFunc cfg.ResourceNamespaceSelector) {
for _, resource := range resources {
namespace := resource.GetNamespace()
kind := resource.GetKind()
name := resource.GetName()

log.Infof("Deleting %s %s/%s", kind, namespace, name)

if err := openshift.DeleteResource(name, resourceSelectorFunc); err != nil {
log.WithError(err).Errorf("Failed to delete %s %s/%s", kind, namespace, name)
}
}
}

// PrintImageTags prints the given image tags line by line. In batch mode, only the tag name is printed, otherwise default
// log with info level
func PrintImageTags(imageTags []string, imageName string, namespace string) {
Expand All @@ -55,17 +39,17 @@ func PrintImageTags(imageTags []string, imageName string, namespace string) {

// PrintResources prints the given resource line by line. In batch mode, only the resource is printed, otherwise default
// log with info level
func PrintResources(resources []cfg.KubernetesResource, namespace string) {
func PrintResources(resources []metav1.ObjectMeta, kind string) {
if len(resources) == 0 {
log.Info("Nothing found to be deleted.")
}
if config.Log.Batch {
for _, resource := range resources {
fmt.Println(resource.GetKind() + ": " + resource.GetName())
fmt.Println(kind + ": " + resource.GetName())
}
} else {
for _, resource := range resources {
log.Infof("Found %s candidate: %s/%s", resource.GetKind(), namespace, resource.GetName())
log.Infof("Found %s candidate: %s/%s", kind, resource.Namespace, resource.GetName())
}
}
}
Expand Down Expand Up @@ -100,53 +84,6 @@ func listImages() error {
return nil
}

func listConfigMaps() error {
namespace := config.Namespace
configMaps, err := openshift.ListConfigMaps(namespace, metav1.ListOptions{})
if err != nil {
return err
}

configMapNames, labels := getNamesAndLabels(configMaps)

log.WithFields(log.Fields{
"\n - namespace": namespace,
"\n - 🔓 configMaps": configMapNames,
"\n - 🎫 labels": labels,
}).Info("Please use labels to select ConfigMaps. The following ConfigMaps and Labels are available:")
return nil
}

func listSecrets() error {
namespace := config.Namespace
secrets, err := openshift.ListSecrets(namespace, metav1.ListOptions{})
if err != nil {
return err
}

secretNames, labels := getNamesAndLabels(secrets)
log.WithFields(log.Fields{
"\n - namespace": namespace,
"\n - 🔐 secrets": secretNames,
"\n - 🎫 labels": labels,
}).Info("Please use labels to select Secrets. The following Secrets and Labels are available:")
return nil
}

func getNamesAndLabels(resources []cfg.KubernetesResource) (resourceNames, labels []string) {
for _, resource := range resources {
resourceNames = append(resourceNames, resource.GetName())
for key, element := range resource.GetLabels() {
label := key + "=" + element
if !funk.ContainsString(labels, label) {
labels = append(labels, label)
}
}
}

return resourceNames, labels
}

//GetListOptions returns a ListOption object based on labels
func getListOptions(labels []string) metav1.ListOptions {
labelSelector := fmt.Sprintf(strings.Join(labels, ","))
Expand Down
59 changes: 33 additions & 26 deletions cmd/configmaps.go
Expand Up @@ -2,22 +2,18 @@ package cmd

import (
"fmt"

"github.com/appuio/seiso/cfg"
"github.com/appuio/seiso/pkg/cleanup"
"github.com/appuio/seiso/pkg/openshift"
"github.com/appuio/seiso/pkg/configmap"
"github.com/appuio/seiso/pkg/kubernetes"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
core "k8s.io/client-go/kubernetes/typed/core/v1"
)

const (
configMapCommandLongDescription = `Sometimes ConfigMaps are left unused in the Kubernetes cluster.
This command deletes ConfigMaps that are not being used anymore.`
)

var configMapLog *log.Entry

var (
// configMapCmd represents a cobra command to clean up unused ConfigMaps
configMapCmd = &cobra.Command{
Expand All @@ -29,11 +25,21 @@ var (
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
log.SetFormatter(&log.TextFormatter{DisableTimestamp: true})
if err := validateConfigMapCommandInput(args); err != nil {
if err := validateConfigMapCommandInput(); err != nil {
cmd.Usage()
return err
}
return executeConfigMapCleanupCommand(args)

coreClient, err := kubernetes.NewCoreV1Client()
if err != nil {
return fmt.Errorf("cannot initiate kubernetes core client")
}

configMapService := configmap.NewConfigMapsService(
coreClient.ConfigMaps(config.Namespace),
kubernetes.New(),
configmap.Configuration{Batch: config.Log.Batch})
return executeConfigMapCleanupCommand(configMapService)
},
}
)
Expand All @@ -50,50 +56,51 @@ func init() {
"Delete ConfigMaps that are older than the duration, e.g. [1y2mo3w4d5h6m7s]")
}

func validateConfigMapCommandInput(args []string) error {
func validateConfigMapCommandInput() error {

if _, err := parseCutOffDateTime(config.Resource.OlderThan); err != nil {
return fmt.Errorf("Could not parse older-than flag: %w", err)
}
return nil
}

func executeConfigMapCleanupCommand(args []string) error {
func executeConfigMapCleanupCommand(service configmap.Service) error {
c := config.Resource
namespace := config.Namespace
if len(config.Resource.Labels) == 0 {
if err := listConfigMaps(); err != nil {
configMaps, labels, err := service.ListNamesAndLabels()
if err != nil {
return err
}
log.WithFields(log.Fields{
"\n - namespace": namespace,
"\n - 🔐 configMaps": configMaps,
"\n - 🎫 labels": labels,
}).Info("Please use labels to select ConfigMaps. The following ConfigMaps and Labels are available:")
return nil
}

c := config.Resource
namespace := config.Namespace

log.WithField("namespace", namespace).Debug("Looking for ConfigMaps")

foundConfigMaps, err := openshift.ListConfigMaps(namespace, getListOptions(c.Labels))
foundConfigMaps, err := service.List(getListOptions(c.Labels))
if err != nil {
return fmt.Errorf("Could not retrieve ConfigMaps with labels '%s' for '%s': %w", c.Labels, namespace, err)
return fmt.Errorf("Could not retrieve config maps with labels '%s' for '%s': %w", c.Labels, namespace, err)
}

unusedConfigMaps, err := openshift.ListUnusedResources(namespace, foundConfigMaps)
unusedConfigMaps, err := service.GetUnused(namespace, foundConfigMaps)
if err != nil {
return fmt.Errorf("Could not retrieve unused ConfigMaps for '%s': %w", namespace, err)
return fmt.Errorf("Could not retrieve unused config maps for '%s': %w", namespace, err)
}

cutOffDateTime, _ := parseCutOffDateTime(c.OlderThan)
filteredConfigMaps := cleanup.FilterResourcesByTime(unusedConfigMaps, cutOffDateTime)
filteredConfigMaps = cleanup.FilterResourcesByMaxCount(filteredConfigMaps, config.History.Keep)
filteredConfigMaps := service.FilterByTime(unusedConfigMaps, cutOffDateTime)
filteredConfigMaps = service.FilterByMaxCount(filteredConfigMaps, config.History.Keep)

if config.Delete {
DeleteResources(
filteredConfigMaps,
func(client *core.CoreV1Client) cfg.CoreObjectInterface {
return client.ConfigMaps(namespace)
})
service.Delete(filteredConfigMaps)
} else {
log.Infof("Showing results for --keep=%d and --older-than=%s", config.History.Keep, c.OlderThan)
PrintResources(filteredConfigMaps, namespace)
service.Print(filteredConfigMaps)
}

return nil
Expand Down
55 changes: 32 additions & 23 deletions cmd/secrets.go
Expand Up @@ -2,13 +2,11 @@ package cmd

import (
"fmt"

"github.com/appuio/seiso/cfg"
"github.com/appuio/seiso/pkg/cleanup"
"github.com/appuio/seiso/pkg/openshift"
"github.com/appuio/seiso/pkg/kubernetes"
"github.com/appuio/seiso/pkg/secret"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
core "k8s.io/client-go/kubernetes/typed/core/v1"
)

const (
Expand All @@ -26,11 +24,21 @@ var (
Args: cobra.MaximumNArgs(1),
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
if err := validateSecretCommandInput(args); err != nil {
if err := validateSecretCommandInput(); err != nil {
cmd.Usage()
return err
}
return executeSecretCleanupCommand(args)

coreClient, err := kubernetes.NewCoreV1Client()
if err != nil {
return fmt.Errorf("cannot initiate kubernetes core client")
}

secretService := secret.NewSecretsService(
coreClient.Secrets(config.Namespace),
kubernetes.New(),
secret.Configuration{Batch: config.Log.Batch})
return executeSecretCleanupCommand(secretService)
},
}
)
Expand All @@ -47,50 +55,51 @@ func init() {
"Delete Secrets that are older than the duration, e.g. [1y2mo3w4d5h6m7s]")
}

func validateSecretCommandInput(args []string) error {

func validateSecretCommandInput() error {
if _, err := parseCutOffDateTime(config.Resource.OlderThan); err != nil {
return fmt.Errorf("Could not parse older-than flag: %w", err)
}
return nil
}

func executeSecretCleanupCommand(args []string) error {
func executeSecretCleanupCommand(service secret.Service) error {
c := config.Resource
namespace := config.Namespace
if len(config.Resource.Labels) == 0 {
if err := listSecrets(); err != nil {
secrets, labels, err := service.ListNamesAndLabels()
if err != nil {
return err
}
log.WithFields(log.Fields{
"\n - namespace": namespace,
"\n - 🔐 secrets": secrets,
"\n - 🎫 labels": labels,
}).Info("Please use labels to select Secrets. The following Secrets and Labels are available:")
return nil
}

c := config.Resource
namespace := config.Namespace

log.WithField("namespace", namespace).Debug("Looking for secrets")

foundSecrets, err := openshift.ListSecrets(namespace, getListOptions(c.Labels))
foundSecrets, err := service.List(getListOptions(c.Labels))
if err != nil {
return fmt.Errorf("Could not retrieve secrets with labels '%s' for '%s': %w", c.Labels, namespace, err)
}

unusedSecrets, err := openshift.ListUnusedResources(namespace, foundSecrets)
unusedSecrets, err := service.GetUnused(namespace, foundSecrets)
if err != nil {
return fmt.Errorf("Could not retrieve unused secrets for '%s': %w", namespace, err)
}

cutOffDateTime, _ := parseCutOffDateTime(c.OlderThan)
filteredSecrets := cleanup.FilterResourcesByTime(unusedSecrets, cutOffDateTime)
filteredSecrets = cleanup.FilterResourcesByMaxCount(filteredSecrets, config.History.Keep)

filteredSecrets := service.FilterByTime(unusedSecrets, cutOffDateTime)
filteredSecrets = service.FilterByMaxCount(filteredSecrets, config.History.Keep)

if config.Delete {
DeleteResources(
filteredSecrets,
func(client *core.CoreV1Client) cfg.CoreObjectInterface {
return client.Secrets(namespace)
})
service.Delete(filteredSecrets)
} else {
log.Infof("Showing results for --keep=%d and --older-than=%s", config.History.Keep, c.OlderThan)
PrintResources(filteredSecrets, namespace)
service.Print(filteredSecrets)
}

return nil
Expand Down
6 changes: 4 additions & 2 deletions go.mod
Expand Up @@ -4,6 +4,7 @@ go 1.14

require (
github.com/etdub/goparsetime v0.0.0-20160315173935-ea17b0ac3318 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/hashicorp/go-version v1.2.0
github.com/heroku/docker-registry-client v0.0.0-20190909225348-afc9e1acc3d5
github.com/imdario/mergo v0.3.8 // indirect
Expand All @@ -12,16 +13,17 @@ require (
github.com/knadh/koanf v0.10.0
github.com/openshift/api v3.9.1-0.20190322043348-8741ff068a47+incompatible
github.com/openshift/client-go v0.0.0-20180830153425-431ec9a26e50
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/sirupsen/logrus v1.4.2
github.com/spf13/cobra v0.0.6
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.5.1
github.com/thoas/go-funk v0.6.0
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/src-d/go-git.v4 v4.13.1
k8s.io/api v0.0.0-20180712090710-2d6f90ab1293 // indirect
k8s.io/api v0.0.0-20180712090710-2d6f90ab1293
k8s.io/apimachinery v0.0.0-20180621070125-103fd098999d
k8s.io/client-go v0.0.0-20180718001006-59698c7d9724
k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29 // indirect
)

0 comments on commit 40114b7

Please sign in to comment.