...

Source file src/github.com/GoogleCloudPlatform/k8s-config-connector/pkg/lease/leaser/resource_leaser_integration_test.go

Documentation: github.com/GoogleCloudPlatform/k8s-config-connector/pkg/lease/leaser

     1  // Copyright 2022 Google LLC
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  //go:build integration
    16  // +build integration
    17  
    18  package leaser_test
    19  
    20  import (
    21  	"context"
    22  	"testing"
    23  
    24  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/k8s"
    25  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/krmtotf"
    26  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/lease/leaser"
    27  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/servicemapping/servicemappingloader"
    28  	testreconciler "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/controller/reconciler"
    29  	testkrmtotf "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/krmtotf"
    30  	"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/resourcefixture"
    31  	testvariable "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/resourcefixture/variable"
    32  	testrunner "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/test/runner"
    33  
    34  	"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
    35  	"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
    36  	"sigs.k8s.io/controller-runtime/pkg/client"
    37  	"sigs.k8s.io/controller-runtime/pkg/manager"
    38  )
    39  
    40  func TestObtainAndReleaseResourceLease(t *testing.T) {
    41  	shouldRun := func(fixture resourcefixture.ResourceFixture, mgr manager.Manager) bool {
    42  		// only need to test contention for a single resource since the logic will apply to all resources
    43  		return fixture.GVK.Kind == "BigQueryDataset" && fixture.Type == resourcefixture.Basic
    44  	}
    45  	testFunc := func(t *testing.T, testContext testrunner.TestContext, systemContext testrunner.SystemContext) {
    46  		u := testContext.CreateUnstruct
    47  		// create the resource with a no management conflict policy to prevent the controller from obtaining a lease on the resource
    48  		k8s.SetAnnotation(k8s.ManagementConflictPreventionPolicyFullyQualifiedAnnotation, k8s.ManagementConflictPreventionPolicyNone, u)
    49  		if err := systemContext.Manager.GetClient().Create(context.TODO(), u); err != nil {
    50  			t.Fatalf("error creating resource: %v", err)
    51  		}
    52  		resourceCleanup := systemContext.Reconciler.BuildCleanupFunc(testContext.CreateUnstruct, testreconciler.CleanupPolicyAlways)
    53  		defer resourceCleanup()
    54  		systemContext.Reconciler.Reconcile(u, testreconciler.ExpectedSuccessfulReconcileResultFor(systemContext.Reconciler, u), nil)
    55  		sm, err := systemContext.SMLoader.GetServiceMapping(u.GroupVersionKind().Group)
    56  		if err != nil {
    57  			t.Fatalf("error getting service mapping: %v", err)
    58  		}
    59  		krmResource1 := testkrmtotf.NewKRMResource(t, u, sm, systemContext.TFProvider)
    60  		krmResource2 := testkrmtotf.NewKRMResource(t, u, sm, systemContext.TFProvider)
    61  		krmResource2.SetNamespace(testvariable.NewUniqueId())
    62  		resourceLeaser := leaser.NewResourceLeaser(systemContext.TFProvider, systemContext.SMLoader, systemContext.Manager.GetClient())
    63  		liveState1 := testkrmtotf.FetchLiveState(t, krmResource1, systemContext.TFProvider, systemContext.Manager.GetClient(), systemContext.SMLoader)
    64  		// obtain a lease for the first namespace
    65  		liveLabels1 := krmtotf.GetLabelsFromState(krmResource1, liveState1)
    66  		if err := resourceLeaser.SoftObtain(context.TODO(), &krmResource1.Resource, liveLabels1); err != nil {
    67  			t.Fatalf("error obtaining lease on first namespace: %v", err)
    68  		}
    69  		apply(t, context.Background(), systemContext.TFProvider, systemContext.Manager.GetClient(), krmResource1, liveState1, systemContext.SMLoader)
    70  		// try to obtain a lease for the second namespace, verify this fails
    71  		liveState2 := testkrmtotf.FetchLiveState(t, krmResource2, systemContext.TFProvider, systemContext.Manager.GetClient(), systemContext.SMLoader)
    72  		liveLabels2 := krmtotf.GetLabelsFromState(krmResource2, liveState2)
    73  		if err := resourceLeaser.SoftObtain(context.TODO(), &krmResource2.Resource, liveLabels2); err == nil {
    74  			t.Fatal("expected error when obtaining lease for second namespace, instead got 'nil'")
    75  		}
    76  		// release the lease for the first namespace
    77  		if err := resourceLeaser.Release(context.TODO(), u); err != nil {
    78  			t.Fatalf("error releasing lease on first namespace: %v", err)
    79  		}
    80  		// now that the resource has been released, obtain a lease for the second namespace
    81  		liveState2 = testkrmtotf.FetchLiveState(t, krmResource2, systemContext.TFProvider, systemContext.Manager.GetClient(), systemContext.SMLoader)
    82  		liveLabels2 = krmtotf.GetLabelsFromState(krmResource2, liveState2)
    83  		if err := resourceLeaser.SoftObtain(context.TODO(), &krmResource2.Resource, liveLabels2); err != nil {
    84  			t.Fatalf("error obtaining lease for second namespace after it was released by the first: %v", err)
    85  		}
    86  	}
    87  	testrunner.RunAllWithDependenciesCreatedButNotObject(t, mgr, shouldRun, testFunc)
    88  }
    89  
    90  func apply(t *testing.T, ctx context.Context, provider *schema.Provider, kubeClient client.Client, resource *krmtotf.Resource, liveState *terraform.InstanceState, smLoader *servicemappingloader.ServiceMappingLoader) {
    91  	config, _, err := krmtotf.KRMResourceToTFResourceConfig(resource, kubeClient, smLoader)
    92  	if err != nil {
    93  		t.Fatalf("error converting resource to tf config: %v", err)
    94  	}
    95  	diff, err := resource.TFResource.Diff(ctx, liveState, config, provider.Meta())
    96  	if err != nil {
    97  		t.Fatalf("error diffing changes: %v", err)
    98  	}
    99  	if diff.Empty() {
   100  		t.Fatalf("unexpected empty diff")
   101  	}
   102  	_, diagnostics := resource.TFResource.Apply(ctx, liveState, diff, provider.Meta())
   103  	if err := krmtotf.NewErrorFromDiagnostics(diagnostics); err != nil {
   104  		t.Fatalf("error applying changes: %v", err)
   105  	}
   106  }
   107  

View as plain text