Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backend/kubernetes: Add Kubernetes as a backend #19525

Merged
merged 4 commits into from
Jun 8, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
92 changes: 87 additions & 5 deletions backend/remote-state/kubernetes/backend_test.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package kubernetes

import (
"fmt"
"math/rand"
"os"
"sync"
"testing"
"time"

"github.com/hashicorp/terraform/backend"
"github.com/hashicorp/terraform/state"
"github.com/hashicorp/terraform/states/statemgr"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand All @@ -30,7 +36,7 @@ func testACC(t *testing.T) {
namespace = "default"
}

cleanupK8sSecrets(t)
cleanupK8sResources(t)
}

func TestBackend_impl(t *testing.T) {
Expand All @@ -39,7 +45,7 @@ func TestBackend_impl(t *testing.T) {

func TestBackend(t *testing.T) {
testACC(t)
defer cleanupK8sSecrets(t)
defer cleanupK8sResources(t)

b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
"secret_suffix": secretSuffix,
Expand All @@ -51,7 +57,7 @@ func TestBackend(t *testing.T) {

func TestBackendLocks(t *testing.T) {
testACC(t)
defer cleanupK8sSecrets(t)
defer cleanupK8sResources(t)

// Get the backend. We need two to test locking.
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
Expand All @@ -67,7 +73,57 @@ func TestBackendLocks(t *testing.T) {
backend.TestBackendStateForceUnlock(t, b1, b2)
}

func cleanupK8sSecrets(t *testing.T) {
func TestBackendLocksSoak(t *testing.T) {
testACC(t)
defer cleanupK8sResources(t)

clientCount := 1000
jrhouston marked this conversation as resolved.
Show resolved Hide resolved
lockCount := 0

lockers := []statemgr.Locker{}
for i := 0; i < clientCount; i++ {
b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
"secret_suffix": secretSuffix,
}))

s, err := b.StateMgr(backend.DefaultStateName)
if err != nil {
t.Fatalf("Error creating state manager: %v", err)
}

lockers = append(lockers, s.(statemgr.Locker))
}

wg := sync.WaitGroup{}
for i, l := range lockers {
wg.Add(1)
go func(locker statemgr.Locker, i int) {
r := rand.Intn(10)
time.Sleep(time.Duration(r) * time.Microsecond)
li := state.NewLockInfo()
li.Operation = "test"
li.Who = fmt.Sprintf("client-%v", i)
_, err := locker.Lock(li)
if err == nil {
t.Logf("[INFO] Client %v got the lock\r\n", i)
lockCount++
jrhouston marked this conversation as resolved.
Show resolved Hide resolved
}
wg.Done()
jrhouston marked this conversation as resolved.
Show resolved Hide resolved
}(l, i)
}

wg.Wait()

if lockCount > 1 {
jrhouston marked this conversation as resolved.
Show resolved Hide resolved
t.Fatalf("multiple backend clients were able to acquire a lock, count: %v", lockCount)
}

if lockCount == 0 {
t.Fatal("no clients were able to acquire a lock")
}
}

func cleanupK8sResources(t *testing.T) {
// Get a backend to use the k8s client
b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
"secret_suffix": secretSuffix,
Expand All @@ -80,7 +136,7 @@ func cleanupK8sSecrets(t *testing.T) {
t.Fatal(err)
}

// Get state secrets based off the tfstateKey label
// Delete secrets
opts := metav1.ListOptions{LabelSelector: tfstateKey + "=true"}
secrets, err := sClient.List(opts)
if err != nil {
Expand All @@ -106,6 +162,32 @@ func cleanupK8sSecrets(t *testing.T) {
}
}

leaseClient, err := b.KubernetesLeaseClient()
if err != nil {
t.Fatal(err)
}

// Delete leases
leases, err := leaseClient.List(opts)
if err != nil {
t.Fatal(err)
}

for _, lease := range leases.Items {
labels := lease.GetLabels()
key, ok := labels[tfstateSecretSuffixKey]
if !ok {
continue
}

if key == secretSuffix {
err = leaseClient.Delete(lease.GetName(), delOps)
if err != nil {
errs = append(errs, err)
}
}
}

if len(errs) > 0 {
t.Fatal(errs)
}
Expand Down
6 changes: 3 additions & 3 deletions backend/remote-state/kubernetes/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ func TestRemoteClient_impl(t *testing.T) {

func TestRemoteClient(t *testing.T) {
testACC(t)
defer cleanupK8sSecrets(t)
defer cleanupK8sResources(t)

b := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
"secret_suffix": secretSuffix,
Expand All @@ -31,7 +31,7 @@ func TestRemoteClient(t *testing.T) {

func TestRemoteClientLocks(t *testing.T) {
testACC(t)
defer cleanupK8sSecrets(t)
defer cleanupK8sResources(t)

b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
"secret_suffix": secretSuffix,
Expand All @@ -56,7 +56,7 @@ func TestRemoteClientLocks(t *testing.T) {

func TestForceUnlock(t *testing.T) {
testACC(t)
defer cleanupK8sSecrets(t)
defer cleanupK8sResources(t)

b1 := backend.TestBackendConfig(t, New(), backend.TestWrapConfig(map[string]interface{}{
"secret_suffix": secretSuffix,
Expand Down
Loading