Skip to content
Closed
Changes from all commits
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
242 changes: 237 additions & 5 deletions test/e2e/work_api_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
testutils "go.goms.io/fleet/test/e2e/utils"
)

// TODO: enable this when join/leave logic is connected to work-api, join the Hub and Member for this test.
var _ = Describe("Work API Controller test", func() {

const (
Expand All @@ -46,7 +45,8 @@ var _ = Describe("Work API Controller test", func() {
"CreationTimestamp",
"Annotations",
"OwnerReferences",
"ManagedFields"),
"ManagedFields",
"Labels"),
}

appliedWorkCmpOptions = append(cmpOptions, cmpopts.IgnoreFields(workapi.AppliedResourceMeta{}, "UID"))
Expand All @@ -55,10 +55,16 @@ var _ = Describe("Work API Controller test", func() {
cmpopts.IgnoreFields(apiextensionsv1.CustomResourceDefinition{}, "Status"),
cmpopts.IgnoreFields(apiextensionsv1.CustomResourceDefinitionSpec{}, "Versions", "Conversion"))

namespaceCmpOptions = append(cmpOptions,
cmpopts.IgnoreFields(corev1.Namespace{}, "Spec", "Status"))

secretCmpOptions = append(cmpOptions,
cmpopts.IgnoreFields(corev1.Secret{}, "TypeMeta"),
)

serviceAccountCmpOptions = append(cmpOptions,
cmpopts.IgnoreFields(corev1.ServiceAccount{}, "TypeMeta", "Secrets"))

resourceNamespace *corev1.Namespace
)

Expand All @@ -73,9 +79,6 @@ var _ = Describe("Work API Controller test", func() {
},
}
testutils.CreateNamespace(*MemberCluster, resourceNamespace)

//Empties the works since they were garbage collected earlier.
works = []workapi.Work{}
})

AfterEach(func() {
Expand Down Expand Up @@ -360,6 +363,235 @@ var _ = Describe("Work API Controller test", func() {
Expect(retrievedSecret.ObjectMeta.Annotations[specHashAnnotation]).ToNot(BeEmpty(),
"SpecHash Annotation does not exist for resource %s", secret.Name)
})

It("Manifests with dependencies within different work objects should successfully apply", func() {

workNameForNamespace := testutils.RandomWorkName(5)
workNameForServiceAccount := testutils.RandomWorkName(6)

testNamespace := corev1.Namespace{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Namespace",
},
ObjectMeta: metav1.ObjectMeta{
Name: "test-namespace",
},
}
// Ns abbreviated to avoid duplicate wording
nsNamespaceType := types.NamespacedName{
Name: testNamespace.Name,
}

testServiceAccount := corev1.ServiceAccount{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ServiceAccount",
},
ObjectMeta: metav1.ObjectMeta{
Name: "test-service-account",
Namespace: testNamespace.Name,
},
}
serviceAccountNamespaceType := types.NamespacedName{
Name: testServiceAccount.Name,
Namespace: testNamespace.Name,
}

namespaceTypeForNamespace := types.NamespacedName{Name: workNameForNamespace, Namespace: workNamespace.Name}
namespaceTypeForServiceAccount := types.NamespacedName{Name: workNameForServiceAccount, Namespace: workNamespace.Name}

manifestNamespace := testutils.AddManifests([]runtime.Object{&testNamespace}, []workapi.Manifest{})
manifestServiceAccount := testutils.AddManifests([]runtime.Object{&testServiceAccount}, []workapi.Manifest{})

workForNamespace := testutils.CreateWork(ctx, *HubCluster, workNameForNamespace, workNamespace.Name, manifestNamespace)
workForServiceAccount := testutils.CreateWork(ctx, *HubCluster, workNameForServiceAccount, workNamespace.Name, manifestServiceAccount)

By(fmt.Sprintf("Applied Condition should be set to True for Work %s and %s", namespaceTypeForNamespace, namespaceTypeForServiceAccount))

wantAppliedCondition := []metav1.Condition{
{
Type: conditionTypeApplied,
Status: metav1.ConditionTrue,
Reason: "appliedWorkComplete",
},
}

receivedWorkForNamespace := workapi.Work{}
receivedWorkForServiceAccount := workapi.Work{}

Eventually(func() string {
if err := HubCluster.KubeClient.Get(ctx, namespaceTypeForNamespace, &receivedWorkForNamespace); err != nil {
return err.Error()
}

return cmp.Diff(wantAppliedCondition, receivedWorkForNamespace.Status.Conditions, cmpOptions...)
}, testutils.PollTimeout, testutils.PollInterval).Should(BeEmpty(),
"Validate WorkStatus for work %s mismatch (-want, +got):", workForNamespace)

Eventually(func() string {
if err := HubCluster.KubeClient.Get(ctx, namespaceTypeForServiceAccount, &receivedWorkForServiceAccount); err != nil {
return err.Error()
}

return cmp.Diff(wantAppliedCondition, receivedWorkForServiceAccount.Status.Conditions, cmpOptions...)
}, testutils.PollTimeout, testutils.PollInterval).Should(BeEmpty(),
"Validate WorkStatus for work %s mismatch (-want, +got):", workForServiceAccount)

By(fmt.Sprintf("Manifest Condiitons on Work Objects %s and %s should be applied", namespaceTypeForNamespace, namespaceTypeForServiceAccount))
wantNamespaceManifestCondition := []workapi.ManifestCondition{
{
Conditions: []metav1.Condition{
{
Type: conditionTypeApplied,
Status: metav1.ConditionTrue,
Reason: "appliedManifestUpdated",
},
},
Identifier: workapi.ResourceIdentifier{
Group: testNamespace.GroupVersionKind().Group,
Version: testNamespace.GroupVersionKind().Version,
Kind: testNamespace.GroupVersionKind().Kind,
Namespace: testNamespace.Namespace,
Name: testNamespace.Name,
Resource: "namespaces",
},
},
}
wantServiceAccountManifestCondition := []workapi.ManifestCondition{
{
Conditions: []metav1.Condition{
{
Type: conditionTypeApplied,
Status: metav1.ConditionTrue,
Reason: "appliedManifestUpdated",
},
},
Identifier: workapi.ResourceIdentifier{
Group: testServiceAccount.GroupVersionKind().Group,
Version: testServiceAccount.GroupVersionKind().Version,
Kind: testServiceAccount.GroupVersionKind().Kind,
Namespace: testServiceAccount.Namespace,
Name: testServiceAccount.Name,
Resource: "serviceaccounts",
},
},
}

Expect(cmp.Diff(wantNamespaceManifestCondition, receivedWorkForNamespace.Status.ManifestConditions, cmpOptions...)).Should(BeEmpty(),
"Manifest Condition not matching for work %s (-want, +got):", namespaceTypeForNamespace)

Expect(cmp.Diff(wantServiceAccountManifestCondition, receivedWorkForServiceAccount.Status.ManifestConditions, cmpOptions...)).Should(BeEmpty(),
"Manifest Condition not matching for work %s (-want, +got):", namespaceTypeForServiceAccount)

By(fmt.Sprintf("AppliedWorkStatus should contain the meta for the resource %s and %s", testNamespace.Name, testServiceAccount.Name))
appliedWorkForNamespace := workapi.AppliedWork{}
Expect(MemberCluster.KubeClient.Get(ctx, namespaceTypeForNamespace, &appliedWorkForNamespace)).Should(Succeed(),
"Retrieving AppliedWork %s failed", workNameForNamespace)

wantAppliedWorkConditionNamespace := workapi.AppliedtWorkStatus{
AppliedResources: []workapi.AppliedResourceMeta{
{
ResourceIdentifier: workapi.ResourceIdentifier{
Group: testNamespace.GroupVersionKind().Group,
Version: testNamespace.GroupVersionKind().Version,
Kind: testNamespace.GroupVersionKind().Kind,
Namespace: testNamespace.Namespace,
Name: testNamespace.Name,
Resource: "namespaces",
},
},
},
}

Expect(cmp.Diff(wantAppliedWorkConditionNamespace, appliedWorkForNamespace.Status, appliedWorkCmpOptions...)).Should(BeEmpty(),
"Validate AppliedResourceMeta mismatch for appliedWork %s (-want, +got):", appliedWorkForNamespace.Name)

appliedWorkForServiceAccount := workapi.AppliedWork{}
Expect(MemberCluster.KubeClient.Get(ctx, namespaceTypeForServiceAccount, &appliedWorkForServiceAccount)).Should(Succeed(),
"Retrieving AppliedWork %s failed", workNameForServiceAccount)

wantAppliedConditionServiceAccount := workapi.AppliedtWorkStatus{
AppliedResources: []workapi.AppliedResourceMeta{
{
ResourceIdentifier: workapi.ResourceIdentifier{
Group: testServiceAccount.GroupVersionKind().Group,
Version: testServiceAccount.GroupVersionKind().Version,
Kind: testServiceAccount.GroupVersionKind().Kind,
Namespace: testServiceAccount.Namespace,
Name: testServiceAccount.Name,
Resource: "serviceaccounts",
},
},
},
}

Expect(cmp.Diff(wantAppliedConditionServiceAccount, appliedWorkForServiceAccount.Status, appliedWorkCmpOptions...)).Should(BeEmpty(),
"Validate AppliedResourceMeta mismatch for appliedWork %s (-want, +got):", appliedWorkForServiceAccount.Name)

By(fmt.Sprintf("The resources %s and %s should both be created in the member cluster.", testNamespace.Name, testServiceAccount.Name))
retrievedNamespace := corev1.Namespace{}
Expect(MemberCluster.KubeClient.Get(ctx, nsNamespaceType, &retrievedNamespace)).Should(Succeed(),
"Failed in retrieving resource %s", testNamespace)
wantNamespace := corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: "test-namespace",
},
}

Expect(cmp.Diff(wantNamespace, retrievedNamespace, namespaceCmpOptions...)).Should(BeEmpty(),
"Validate Namespace %s mismatch (-want, +got):", wantNamespace.Name)

retrievedServiceAccount := corev1.ServiceAccount{}
Expect(MemberCluster.KubeClient.Get(ctx, serviceAccountNamespaceType, &retrievedServiceAccount)).Should(Succeed(),
"Failed in retrieving resource %s", testServiceAccount)

wantServiceAccount := corev1.ServiceAccount{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ServiceAccount",
},
ObjectMeta: metav1.ObjectMeta{
Name: "test-service-account",
Namespace: testNamespace.Name,
},
}

Expect(cmp.Diff(wantServiceAccount, retrievedServiceAccount, serviceAccountCmpOptions...)).Should(BeEmpty(),
"Validate Service Account %s mismatch (-want, +got):", wantServiceAccount.Name)

By(fmt.Sprintf("Validating that the resource %s and %s is owned by the respective work", testNamespace.Name, testServiceAccount.Name))
wantOwnerForNamespace := []metav1.OwnerReference{
{
APIVersion: workapi.GroupVersion.String(),
Kind: workapi.AppliedWorkKind,
Name: appliedWorkForNamespace.GetName(),
UID: appliedWorkForNamespace.GetUID(),
},
}

wantOwnerForServiceAccount := []metav1.OwnerReference{
{
APIVersion: workapi.GroupVersion.String(),
Kind: workapi.AppliedWorkKind,
Name: appliedWorkForServiceAccount.GetName(),
UID: appliedWorkForServiceAccount.GetUID(),
},
}

Expect(cmp.Diff(wantOwnerForNamespace, retrievedNamespace.OwnerReferences, cmpOptions...)).Should(BeEmpty(),
"OwnerReference mismatch for resource %s (-want, +got):", testNamespace.Name)
Expect(cmp.Diff(wantOwnerForServiceAccount, retrievedServiceAccount.OwnerReferences, cmpOptions...)).Should(BeEmpty(),
"OwnerReference mismatch for resource %s (-want, +got):", testServiceAccount.Name)

// TODO: spec has isn't being created when resources such as namespace and service account is being created by the work-api. Possible bug?
//Expect(testNamespace.ObjectMeta.Annotations[specHashAnnotation]).ToNot(BeEmpty(),
// "SpecHash Annotation does not exist for resource %s", testNamespace.Name)
//Expect(testServiceAccount.ObjectMeta.Annotations[specHashAnnotation]).ToNot(BeEmpty(),
// "SpecHash Annotation does not exist for resource %s", testServiceAccount.Name)

})

It("Upon successful work creation of a CRD resource, manifest is applied, and resources are created", func() {
workName := testutils.RandomWorkName(5)

Expand Down