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 }