Skip to content
Closed
Show file tree
Hide file tree
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
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,20 @@
errs = append(errs, field.Invalid(field.NewPath("spec"), cgm.Spec, fmt.Sprintf("cannot create membership as a ContactGroupMembershipRemoval %s already exists", existingRemovals.Items[0].Name)))
}

// Check that cgm namespace is the same as the contact namespace for contacts that are related
// to the resourcemanager.miloapis.com API group
if contact.Spec.SubjectRef != nil {
switch contact.Spec.SubjectRef.APIGroup {
case "resourcemanager.miloapis.com":
if cgm.Namespace != contact.Namespace {
errs = append(errs, field.Invalid(field.NewPath("spec"), cgm.Spec, "namespace must be the same as the contact namespace for contacts that are related to the resourcemanager.miloapis.com API group"))
}
default:
return nil, errors.NewInternalError(fmt.Errorf("server does not handle SubjectRef APIGroup %s", contact.Spec.SubjectRef.APIGroup))
}
}

if len(errs) > 0 {

Check warning on line 130 in internal/webhooks/notification/v1alpha1/contactgroupmembership_webhook.go

View check run for this annotation

JoggrBot / Joggr

internal/webhooks/notification/v1alpha1/contactgroupmembership_webhook.go#L117-L130

"docs/api/notification.md" is outdated: Webhook added requiring namespace match for contacts with resourcemanager.miloapis.com APIGroup; documentation for ContactGroupMembership and ContactGroupMembershipRemoval does not reflect this required constraint.
return nil, errors.NewInvalid(notificationv1alpha1.SchemeGroupVersion.WithKind("ContactGroupMembership").GroupKind(), cgm.Name, errs)
}
return nil, nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,45 @@ func TestContactGroupMembershipValidator(t *testing.T) {
expectError: true,
errorContains: "not found",
},
"subjectref same namespace": {
newObj: &notificationv1alpha1.ContactGroupMembership{
ObjectMeta: metav1.ObjectMeta{Name: "m6", Namespace: "default"},
Spec: notificationv1alpha1.ContactGroupMembershipSpec{
ContactRef: notificationv1alpha1.ContactReference{Name: "c-sub", Namespace: "default"},
ContactGroupRef: notificationv1alpha1.ContactGroupReference{Name: "g-sub", Namespace: "default"},
},
},
seedObjects: []client.Object{
&notificationv1alpha1.Contact{
ObjectMeta: metav1.ObjectMeta{Name: "c-sub", Namespace: "default"},
Spec: notificationv1alpha1.ContactSpec{
SubjectRef: &notificationv1alpha1.SubjectReference{APIGroup: "resourcemanager.miloapis.com", Kind: "Project", Name: "proj1"},
},
},
&notificationv1alpha1.ContactGroup{ObjectMeta: metav1.ObjectMeta{Name: "g-sub", Namespace: "default"}},
},
expectError: false,
},
"subjectref namespace mismatch": {
newObj: &notificationv1alpha1.ContactGroupMembership{
ObjectMeta: metav1.ObjectMeta{Name: "m7", Namespace: "other"},
Spec: notificationv1alpha1.ContactGroupMembershipSpec{
ContactRef: notificationv1alpha1.ContactReference{Name: "c-sub", Namespace: "default"},
ContactGroupRef: notificationv1alpha1.ContactGroupReference{Name: "g-sub", Namespace: "other"},
},
},
seedObjects: []client.Object{
&notificationv1alpha1.Contact{
ObjectMeta: metav1.ObjectMeta{Name: "c-sub", Namespace: "default"},
Spec: notificationv1alpha1.ContactSpec{
SubjectRef: &notificationv1alpha1.SubjectReference{APIGroup: "resourcemanager.miloapis.com", Kind: "Project", Name: "proj1"},
},
},
&notificationv1alpha1.ContactGroup{ObjectMeta: metav1.ObjectMeta{Name: "g-sub", Namespace: "other"}},
},
expectError: true,
errorContains: "namespace must be the same",
},
}

for name, tt := range tests {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,20 @@
errs = append(errs, field.Duplicate(field.NewPath("spec"), fmt.Sprintf("membership removal already exists in ContactGroupMembershipRemoval %s", existing.Items[0].Name)))
}

// Check that cgmr namespace is the same as the contact namespace for contacts that are related
// to the resourcemanager.miloapis.com API group
if contact.Spec.SubjectRef != nil {
switch contact.Spec.SubjectRef.APIGroup {
case "resourcemanager.miloapis.com":
if removal.Namespace != contact.Namespace {
errs = append(errs, field.Invalid(field.NewPath("spec"), removal.Spec, "namespace must be the same as the contact namespace for contacts that are related to the resourcemanager.miloapis.com API group"))
}
default:
return nil, errors.NewInternalError(fmt.Errorf("server does not handle SubjectRef APIGroup %s", contact.Spec.SubjectRef.APIGroup))
}
}

if len(errs) > 0 {

Check warning on line 101 in internal/webhooks/notification/v1alpha1/contactgroupmembershipremoval_webhook.go

View check run for this annotation

JoggrBot / Joggr

internal/webhooks/notification/v1alpha1/contactgroupmembershipremoval_webhook.go#L88-L101

"docs/api/notification.md" is outdated: ContactGroupMembershipRemoval adds similar namespace/SubjectRef validation not represented in related docs table schema or field descriptions, creating possible confusion.
return nil, errors.NewInvalid(notificationv1alpha1.SchemeGroupVersion.WithKind("ContactGroupMembershipRemoval").GroupKind(), removal.Name, errs)
}
return nil, nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,24 @@ func TestContactGroupMembershipRemovalValidator(t *testing.T) {
return &notificationv1alpha1.ContactGroup{ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: "default"}}
}

// makeContactWithSubject creates a Contact that includes a SubjectRef with the given apiGroup and namespace.
makeContactWithSubject := func(name, ns, apiGroup string) *notificationv1alpha1.Contact {
return &notificationv1alpha1.Contact{
ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: ns},
Spec: notificationv1alpha1.ContactSpec{
SubjectRef: &notificationv1alpha1.SubjectReference{
APIGroup: apiGroup,
Kind: "User",
Name: "demo", // value not relevant for validator logic
Namespace: ns,
},
FamilyName: "Doe",
GivenName: "John",
Email: "john.doe@example.com",
},
}
}

tests := map[string]struct {
newObj *notificationv1alpha1.ContactGroupMembershipRemoval
seedObjects []client.Object
Expand Down Expand Up @@ -85,6 +103,29 @@ func TestContactGroupMembershipRemovalValidator(t *testing.T) {
},
expectError: false,
},
"contact with resourcemanager apiGroup same namespace": {
newObj: makeRemoval("rm7", "c-res", "g1"),
seedObjects: []client.Object{makeContactWithSubject("c-res", "default", "resourcemanager.miloapis.com"), makeGroup("g1")},
expectError: false,
},
"contact with resourcemanager apiGroup different namespace": {
newObj: &notificationv1alpha1.ContactGroupMembershipRemoval{
ObjectMeta: metav1.ObjectMeta{Name: "rm8", Namespace: "other-ns"},
Spec: notificationv1alpha1.ContactGroupMembershipRemovalSpec{
ContactRef: notificationv1alpha1.ContactReference{Name: "c-res", Namespace: "default"},
ContactGroupRef: notificationv1alpha1.ContactGroupReference{Name: "g1", Namespace: "default"},
},
},
seedObjects: []client.Object{makeContactWithSubject("c-res", "default", "resourcemanager.miloapis.com"), makeGroup("g1")},
expectError: true,
errorContains: "namespace must be the same",
},
"contact with unsupported apiGroup": {
newObj: makeRemoval("rm9", "c-oth", "g1"),
seedObjects: []client.Object{makeContactWithSubject("c-oth", "default", "unsupported.group"), makeGroup("g1")},
expectError: true,
errorContains: "server does not handle subjectref apigroup",
},
}

for name, tt := range tests {
Expand Down
Loading