jiri-test/internal/test/vkube.go: GC old buckets and namespaces
The vkube integration test normally cleans up after itself. However,
when the test is interrupted for any reason, the bucket and/or namespace
might be left behind.
With this change, buckets and namespaces that are older than 2 hours are
automatically deleted next time test runs.
Change-Id: Ic8c1831d95f6a2c796e94fef8c2f17e6b93289d2
diff --git a/jiri-test/internal/test/vkube.go b/jiri-test/internal/test/vkube.go
index 80fc1e2..a95adf2 100644
--- a/jiri-test/internal/test/vkube.go
+++ b/jiri-test/internal/test/vkube.go
@@ -5,16 +5,24 @@
package test
import (
+ "bytes"
"errors"
"fmt"
"os"
+ "strings"
+ "time"
"v.io/jiri"
"v.io/jiri/collect"
"v.io/x/devtools/internal/test"
)
-const projectEnvVar = "VKUBE_TEST_PROJECT"
+const (
+ projectEnvVar = "VKUBE_TEST_PROJECT"
+ bucketNamePrefix = "gs://vkube-test-"
+ namespaceNamePrefix = "namespace/vkube-test-"
+ timeFormat = "20060102-150405"
+)
func vanadiumVkubeIntegrationTest(jirix *jiri.X, testName string, opts ...Opt) (_ *test.Result, e error) {
project := os.Getenv(projectEnvVar)
@@ -22,15 +30,15 @@
return nil, newInternalError(fmt.Errorf("project not defined in %s environment variable", projectEnvVar), "Env")
}
s := jirix.NewSeq()
- if err := s.Last("kubectl", "cluster-info"); err != nil {
- return nil, newInternalError(errors.New("this test requires kubectl"), err.Error())
- }
- if err := s.Last("gsutil", "ls", "-p", project); err != nil {
- return nil, newInternalError(errors.New("this test requires gsutil"), err.Error())
- }
if err := s.Last("docker", "info"); err != nil {
return nil, newInternalError(errors.New("this test requires docker"), err.Error())
}
+ if err := cleanUpBuckets(jirix, project); err != nil {
+ return nil, newInternalError(errors.New("failed to clean up old buckets"), err.Error())
+ }
+ if err := cleanUpNamespaces(jirix); err != nil {
+ return nil, newInternalError(errors.New("failed to clean up old namespaces"), err.Error())
+ }
cleanup, err := initTest(jirix, testName, []string{"v23:base"})
if err != nil {
@@ -49,3 +57,65 @@
return &test.Result{Status: test.Passed}, nil
}
+
+func cleanUpBuckets(jirix *jiri.X, project string) error {
+ s := jirix.NewSeq()
+ var output bytes.Buffer
+ if err := s.Capture(&output, nil).Last("gsutil", "ls", "-p", project); err != nil {
+ return err
+ }
+ for _, b := range strings.Split(output.String(), "\n") {
+ if !strings.HasPrefix(b, bucketNamePrefix) {
+ continue
+ }
+ ts := strings.TrimPrefix(b, bucketNamePrefix)
+ if len(ts) < len(timeFormat) {
+ fmt.Fprintf(jirix.Stderr(), "failed to parse timestamp %s\n", ts)
+ continue
+ }
+ ts = ts[:len(timeFormat)]
+ t, err := time.Parse(timeFormat, ts)
+ if err != nil {
+ fmt.Fprintf(jirix.Stderr(), "failed to parse timestamp in %s\n", b)
+ continue
+ }
+ if time.Since(t) > 2*time.Hour {
+ fmt.Fprintf(jirix.Stdout(), "Deleting old bucket %q\n", b)
+ if err := s.Last("gsutil", "-m", "rm", "-r", b); err != nil {
+ fmt.Fprintf(jirix.Stderr(), "failed to delete bucket %q: %v\n", b, err)
+ }
+ }
+ }
+ return nil
+}
+
+func cleanUpNamespaces(jirix *jiri.X) error {
+ s := jirix.NewSeq()
+ var output bytes.Buffer
+ if err := s.Capture(&output, nil).Last("kubectl", "get", "namespace", "-o", "name"); err != nil {
+ return err
+ }
+ for _, ns := range strings.Split(output.String(), "\n") {
+ if !strings.HasPrefix(ns, namespaceNamePrefix) {
+ continue
+ }
+ ts := strings.TrimPrefix(ns, namespaceNamePrefix)
+ if len(ts) < len(timeFormat) {
+ fmt.Fprintf(jirix.Stderr(), "failed to parse timestamp %s\n", ts)
+ continue
+ }
+ ts = ts[:len(timeFormat)]
+ t, err := time.Parse(timeFormat, ts)
+ if err != nil {
+ fmt.Fprintf(jirix.Stderr(), "failed to parse timestamp in %s\n", ns)
+ continue
+ }
+ if time.Since(t) > 2*time.Hour {
+ fmt.Fprintf(jirix.Stdout(), "Deleting old namespace %q\n", ns)
+ if err := s.Last("kubectl", "delete", ns); err != nil {
+ fmt.Fprintf(jirix.Stderr(), "failed to delete %q: %v\n", ns, err)
+ }
+ }
+ }
+ return nil
+}