forked from kubernetes-retired/multi-tenancy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a unit test for config_controller.go
Add a unit test for config_controller.go to test the case that when a new type is added to HNCConfiguration singleton, the corresponding object reconciler can be created correctly. This PR also moves shared helper functions from each controller test files to a common file. Design doc: http://bit.ly/hnc-type-configuration Issue: kubernetes-retired#411
- Loading branch information
1 parent
0b38160
commit 8551f06
Showing
6 changed files
with
207 additions
and
111 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package controllers_test | ||
|
||
import ( | ||
"context" | ||
"time" | ||
|
||
"github.com/kubernetes-sigs/multi-tenancy/incubator/hnc/pkg/config" | ||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
var _ = Describe("HNCConfiguration", func() { | ||
ctx := context.Background() | ||
|
||
var ( | ||
fooName string | ||
barName string | ||
) | ||
|
||
BeforeEach(func() { | ||
fooName = createNS(ctx, "foo") | ||
barName = createNS(ctx, "bar") | ||
}) | ||
|
||
AfterEach(func() { | ||
// Change current singleton back to the default value. | ||
// Wait 1 second to make sure the latest version of the singleton has been successfully updated | ||
// by the client. | ||
time.Sleep(1 * time.Second) | ||
c := getHNCConfig(ctx) | ||
c.Spec = config.GetDefaultConfigSpec() | ||
updateHNCConfig(ctx, c) | ||
}) | ||
|
||
It("should propagate objects whose types have been added to HNCConfiguration", func() { | ||
setParent(ctx, barName, fooName) | ||
makeSecret(ctx, fooName, "foo-sec") | ||
|
||
// Wait 1 second to give "foo-sec" a chance to be propagated to bar, if it can be propagated. | ||
time.Sleep(1 * time.Second) | ||
// "foo-sec" is not propagated to bar because Secret hasn't been configured in HNCConfiguration. | ||
Eventually(hasSecret(ctx, barName, "foo-sec")).Should(BeFalse()) | ||
|
||
c := getHNCConfig(ctx) | ||
addSecretToHNCConfig(ctx, c) | ||
|
||
// "foo-sec" is now propagated to bar. | ||
Eventually(hasSecret(ctx, barName, "foo-sec")).Should(BeTrue()) | ||
Expect(secretInheritedFrom(ctx, barName, "foo-sec")).Should(Equal(fooName)) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package controllers_test | ||
|
||
import ( | ||
"context" | ||
"crypto/rand" | ||
"fmt" | ||
|
||
"github.com/kubernetes-sigs/multi-tenancy/incubator/hnc/pkg/config" | ||
. "github.com/onsi/gomega" | ||
corev1 "k8s.io/api/core/v1" | ||
"k8s.io/apimachinery/pkg/types" | ||
|
||
api "github.com/kubernetes-sigs/multi-tenancy/incubator/hnc/api/v1alpha1" | ||
) | ||
|
||
func setParent(ctx context.Context, nm string, pnm string) { | ||
hier := newOrGetHierarchy(ctx, nm) | ||
oldPNM := hier.Spec.Parent | ||
hier.Spec.Parent = pnm | ||
updateHierarchy(ctx, hier) | ||
if oldPNM != "" { | ||
EventuallyWithOffset(1, func() []string { | ||
pHier := getHierarchyWithOffset(1, ctx, oldPNM) | ||
return pHier.Status.Children | ||
}).ShouldNot(ContainElement(nm)) | ||
} | ||
if pnm != "" { | ||
EventuallyWithOffset(1, func() []string { | ||
pHier := getHierarchyWithOffset(1, ctx, pnm) | ||
return pHier.Status.Children | ||
}).Should(ContainElement(nm)) | ||
} | ||
} | ||
|
||
// createNSName generates random namespace names. Namespaces are never deleted in test-env because | ||
// the building Namespace controller (which finalizes namespaces) doesn't run; I searched Github and | ||
// found that everyone who was deleting namespaces was *also* very intentionally generating random | ||
// names, so I guess this problem is widespread. | ||
func createNSName(prefix string) string { | ||
suffix := make([]byte, 10) | ||
rand.Read(suffix) | ||
return fmt.Sprintf("%s-%x", prefix, suffix) | ||
} | ||
|
||
func newHNCConfig() *api.HNCConfiguration { | ||
hncConfig := &api.HNCConfiguration{} | ||
hncConfig.ObjectMeta.Name = api.HNCConfigSingleton | ||
hncConfig.Spec = config.GetDefaultConfigSpec() | ||
return hncConfig | ||
} | ||
|
||
func updateHNCConfig(ctx context.Context, c *api.HNCConfiguration) { | ||
if c.CreationTimestamp.IsZero() { | ||
ExpectWithOffset(1, k8sClient.Create(ctx, c)).Should(Succeed()) | ||
} else { | ||
ExpectWithOffset(1, k8sClient.Update(ctx, c)).Should(Succeed()) | ||
} | ||
} | ||
|
||
func getHNCConfig(ctx context.Context) *api.HNCConfiguration { | ||
return getHNCConfigWithOffset(1, ctx) | ||
} | ||
|
||
func getHNCConfigWithOffset(offset int, ctx context.Context) *api.HNCConfiguration { | ||
snm := types.NamespacedName{Name: api.HNCConfigSingleton} | ||
config := &api.HNCConfiguration{} | ||
EventuallyWithOffset(offset+1, func() error { | ||
return k8sClient.Get(ctx, snm, config) | ||
}).Should(Succeed()) | ||
return config | ||
} | ||
|
||
// createNSWithLabel has similar function to createNS with label as additional parameter | ||
func createNSWithLabel(ctx context.Context, prefix string, label map[string]string) string { | ||
nm := createNSName(prefix) | ||
|
||
// Create the namespace | ||
ns := &corev1.Namespace{} | ||
ns.SetLabels(label) | ||
ns.Name = nm | ||
Expect(k8sClient.Create(ctx, ns)).Should(Succeed()) | ||
return nm | ||
} | ||
|
||
// createNS is a convenience function to create a namespace and wait for its singleton to be | ||
// created. It's used in other tests in this package, but basically duplicates the code in this test | ||
// (it didn't originally). TODO: refactor. | ||
func createNS(ctx context.Context, prefix string) string { | ||
nm := createNSName(prefix) | ||
|
||
// Create the namespace | ||
ns := &corev1.Namespace{} | ||
ns.Name = nm | ||
Expect(k8sClient.Create(ctx, ns)).Should(Succeed()) | ||
return nm | ||
} | ||
|
||
func addSecretToHNCConfig(ctx context.Context, c *api.HNCConfiguration) { | ||
secSpec := api.TypeSynchronizationSpec{APIVersion: "v1", Kind: "Secret", Mode: api.Propagate} | ||
c.Spec.Types = append(c.Spec.Types, secSpec) | ||
updateHNCConfig(ctx, c) | ||
} | ||
|
||
func makeSecret(ctx context.Context, nsName, secretName string) { | ||
sec := &corev1.Secret{} | ||
sec.Name = secretName | ||
sec.Namespace = nsName | ||
ExpectWithOffset(1, k8sClient.Create(ctx, sec)).Should(Succeed()) | ||
} | ||
|
||
func hasSecret(ctx context.Context, nsName, secretName string) func() bool { | ||
// `Eventually` only works with a fn that doesn't take any args | ||
return func() bool { | ||
nnm := types.NamespacedName{Namespace: nsName, Name: secretName} | ||
sec := &corev1.Secret{} | ||
err := k8sClient.Get(ctx, nnm, sec) | ||
return err == nil | ||
} | ||
} | ||
|
||
func secretInheritedFrom(ctx context.Context, nsName, secretName string) string { | ||
nnm := types.NamespacedName{Namespace: nsName, Name: secretName} | ||
sec := &corev1.Secret{} | ||
if err := k8sClient.Get(ctx, nnm, sec); err != nil { | ||
// should have been caught above | ||
return err.Error() | ||
} | ||
if sec.ObjectMeta.Labels == nil { | ||
return "" | ||
} | ||
lif, _ := sec.ObjectMeta.Labels["hnc.x-k8s.io/inheritedFrom"] | ||
return lif | ||
} |