github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/backend/remote-state/kubernetes/backend_test.go (about)

     1  package kubernetes
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"math/rand"
     7  	"os"
     8  	"sync"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/hashicorp/terraform/internal/backend"
    13  	"github.com/hashicorp/terraform/internal/states/statemgr"
    14  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    15  )
    16  
    17  const (
    18  	secretSuffix = "test-state"
    19  )
    20  
    21  var namespace string
    22  
    23  // verify that we are doing ACC tests or the k8s tests specifically
    24  func testACC(t *testing.T) {
    25  	skip := os.Getenv("TF_ACC") == "" && os.Getenv("TF_K8S_TEST") == ""
    26  	if skip {
    27  		t.Log("k8s backend tests require setting TF_ACC or TF_K8S_TEST")
    28  		t.Skip()
    29  	}
    30  
    31  	ns := os.Getenv("KUBE_NAMESPACE")
    32  
    33  	if ns != "" {
    34  		namespace = ns
    35  	} else {
    36  		namespace = "default"
    37  	}
    38  
    39  	cleanupK8sResources(t)
    40  }
    41  
    42  func TestBackend_impl(t *testing.T) {
    43  	var _ backend.Backend = new(Backend)
    44  }
    45  
    46  func TestBackend(t *testing.T) {
    47  	testACC(t)
    48  	defer cleanupK8sResources(t)
    49  
    50  	b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
    51  		"secret_suffix": secretSuffix,
    52  	}))
    53  
    54  	// Test
    55  	backend.TestBackendStates(t, b1)
    56  }
    57  
    58  func TestBackendLocks(t *testing.T) {
    59  	testACC(t)
    60  	defer cleanupK8sResources(t)
    61  
    62  	// Get the backend. We need two to test locking.
    63  	b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
    64  		"secret_suffix": secretSuffix,
    65  	}))
    66  
    67  	b2 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
    68  		"secret_suffix": secretSuffix,
    69  	}))
    70  
    71  	// Test
    72  	backend.TestBackendStateLocks(t, b1, b2)
    73  	backend.TestBackendStateForceUnlock(t, b1, b2)
    74  }
    75  
    76  func TestBackendLocksSoak(t *testing.T) {
    77  	testACC(t)
    78  	defer cleanupK8sResources(t)
    79  
    80  	clientCount := 100
    81  	lockAttempts := 100
    82  
    83  	lockers := []statemgr.Locker{}
    84  	for i := 0; i < clientCount; i++ {
    85  		b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
    86  			"secret_suffix": secretSuffix,
    87  		}))
    88  
    89  		s, err := b.StateMgr(backend.DefaultStateName)
    90  		if err != nil {
    91  			t.Fatalf("Error creating state manager: %v", err)
    92  		}
    93  
    94  		lockers = append(lockers, s.(statemgr.Locker))
    95  	}
    96  
    97  	wg := sync.WaitGroup{}
    98  	for i, l := range lockers {
    99  		wg.Add(1)
   100  		go func(locker statemgr.Locker, n int) {
   101  			defer wg.Done()
   102  
   103  			li := statemgr.NewLockInfo()
   104  			li.Operation = "test"
   105  			li.Who = fmt.Sprintf("client-%v", n)
   106  
   107  			for i := 0; i < lockAttempts; i++ {
   108  				id, err := locker.Lock(li)
   109  				if err != nil {
   110  					continue
   111  				}
   112  
   113  				// hold onto the lock for a little bit
   114  				time.Sleep(time.Duration(rand.Intn(10)) * time.Microsecond)
   115  
   116  				err = locker.Unlock(id)
   117  				if err != nil {
   118  					t.Errorf("failed to unlock: %v", err)
   119  				}
   120  			}
   121  		}(l, i)
   122  	}
   123  
   124  	wg.Wait()
   125  }
   126  
   127  func cleanupK8sResources(t *testing.T) {
   128  	ctx := context.Background()
   129  	// Get a backend to use the k8s client
   130  	b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
   131  		"secret_suffix": secretSuffix,
   132  	}))
   133  
   134  	b := b1.(*Backend)
   135  
   136  	sClient, err := b.KubernetesSecretClient()
   137  	if err != nil {
   138  		t.Fatal(err)
   139  	}
   140  
   141  	// Delete secrets
   142  	opts := metav1.ListOptions{LabelSelector: tfstateKey + "=true"}
   143  	secrets, err := sClient.List(ctx, opts)
   144  	if err != nil {
   145  		t.Fatal(err)
   146  	}
   147  
   148  	delProp := metav1.DeletePropagationBackground
   149  	delOps := metav1.DeleteOptions{PropagationPolicy: &delProp}
   150  	var errs []error
   151  
   152  	for _, secret := range secrets.Items {
   153  		labels := secret.GetLabels()
   154  		key, ok := labels[tfstateSecretSuffixKey]
   155  		if !ok {
   156  			continue
   157  		}
   158  
   159  		if key == secretSuffix {
   160  			err = sClient.Delete(ctx, secret.GetName(), delOps)
   161  			if err != nil {
   162  				errs = append(errs, err)
   163  			}
   164  		}
   165  	}
   166  
   167  	leaseClient, err := b.KubernetesLeaseClient()
   168  	if err != nil {
   169  		t.Fatal(err)
   170  	}
   171  
   172  	// Delete leases
   173  	leases, err := leaseClient.List(ctx, opts)
   174  	if err != nil {
   175  		t.Fatal(err)
   176  	}
   177  
   178  	for _, lease := range leases.Items {
   179  		labels := lease.GetLabels()
   180  		key, ok := labels[tfstateSecretSuffixKey]
   181  		if !ok {
   182  			continue
   183  		}
   184  
   185  		if key == secretSuffix {
   186  			err = leaseClient.Delete(ctx, lease.GetName(), delOps)
   187  			if err != nil {
   188  				errs = append(errs, err)
   189  			}
   190  		}
   191  	}
   192  
   193  	if len(errs) > 0 {
   194  		t.Fatal(errs)
   195  	}
   196  }