Alerting: Migrate notification models to generated by grafnaa-app-sdk (#95430)
* create notifications module and generate models * switch template group to app models * switch time intervals to use app models * switch receiver to use app models * switch routing tree to use app models * move schema registration to resource packages * fix package names to match app * fix codeowners * fix UI to use metadata.name instead of uid * update dockerfile * move generated models to pkg * remove provenance from field selector * move client factories to test files * rename GenericClient to TypedClient
This commit is contained in:
@@ -15,11 +15,13 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/dynamic"
|
||||
|
||||
"github.com/grafana/grafana/pkg/apis/alerting_notifications/v0alpha1"
|
||||
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/resource/timeinterval/v0alpha1"
|
||||
"github.com/grafana/grafana/apps/alerting/notifications/pkg/apis/resource/timeinterval/v0alpha1/fakes"
|
||||
"github.com/grafana/grafana/pkg/bus"
|
||||
"github.com/grafana/grafana/pkg/generated/clientset/versioned"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol"
|
||||
"github.com/grafana/grafana/pkg/services/accesscontrol/acimpl"
|
||||
@@ -61,22 +63,20 @@ func TestIntegrationResourceIdentifier(t *testing.T) {
|
||||
|
||||
ctx := context.Background()
|
||||
helper := getTestHelper(t)
|
||||
adminK8sClient, err := versioned.NewForConfig(helper.Org1.Admin.NewRestConfig())
|
||||
require.NoError(t, err)
|
||||
client := adminK8sClient.NotificationsV0alpha1().TimeIntervals("default")
|
||||
client := newClient(t, helper.Org1.Admin)
|
||||
|
||||
newInterval := &v0alpha1.TimeInterval{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: v0alpha1.TimeIntervalSpec{
|
||||
Spec: v0alpha1.Spec{
|
||||
Name: "time-newInterval",
|
||||
TimeIntervals: v0alpha1.IntervalGenerator{}.GenerateMany(2),
|
||||
TimeIntervals: fakes.IntervalGenerator{}.GenerateMany(2),
|
||||
},
|
||||
}
|
||||
|
||||
t.Run("create should fail if object name is specified", func(t *testing.T) {
|
||||
interval := newInterval.DeepCopy()
|
||||
interval := newInterval.Copy().(*v0alpha1.TimeInterval)
|
||||
interval.Name = "time-newInterval"
|
||||
_, err := client.Create(ctx, interval, v1.CreateOptions{})
|
||||
require.Truef(t, errors.IsBadRequest(err), "Expected BadRequest but got %s", err)
|
||||
@@ -104,7 +104,7 @@ func TestIntegrationResourceIdentifier(t *testing.T) {
|
||||
if existingInterval == nil {
|
||||
t.Skip()
|
||||
}
|
||||
updated := existingInterval.DeepCopy()
|
||||
updated := existingInterval.Copy().(*v0alpha1.TimeInterval)
|
||||
updated.Spec.Name = "another-newInterval"
|
||||
actual, err := client.Update(ctx, updated, v1.UpdateOptions{})
|
||||
require.NoError(t, err)
|
||||
@@ -197,24 +197,18 @@ func TestIntegrationTimeIntervalAccessControl(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
admin := org1.Admin
|
||||
adminK8sClient, err := versioned.NewForConfig(admin.NewRestConfig())
|
||||
require.NoError(t, err)
|
||||
adminClient := adminK8sClient.NotificationsV0alpha1().TimeIntervals("default")
|
||||
adminClient := newClient(t, helper.Org1.Admin)
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(fmt.Sprintf("user '%s'", tc.user.Identity.GetLogin()), func(t *testing.T) {
|
||||
k8sClient, err := versioned.NewForConfig(tc.user.NewRestConfig())
|
||||
require.NoError(t, err)
|
||||
client := k8sClient.NotificationsV0alpha1().TimeIntervals("default")
|
||||
|
||||
client := newClient(t, tc.user)
|
||||
var expected = &v0alpha1.TimeInterval{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: v0alpha1.TimeIntervalSpec{
|
||||
Spec: v0alpha1.Spec{
|
||||
Name: fmt.Sprintf("time-interval-1-%s", tc.user.Identity.GetLogin()),
|
||||
TimeIntervals: v0alpha1.IntervalGenerator{}.GenerateMany(2),
|
||||
TimeIntervals: fakes.IntervalGenerator{}.GenerateMany(2),
|
||||
},
|
||||
}
|
||||
expected.SetProvenanceStatus("")
|
||||
@@ -280,8 +274,8 @@ func TestIntegrationTimeIntervalAccessControl(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
updatedExpected := expected.DeepCopy()
|
||||
updatedExpected.Spec.TimeIntervals = v0alpha1.IntervalGenerator{}.GenerateMany(2)
|
||||
updatedExpected := expected.Copy().(*v0alpha1.TimeInterval)
|
||||
updatedExpected.Spec.TimeIntervals = fakes.IntervalGenerator{}.GenerateMany(2)
|
||||
|
||||
d, err = json.Marshal(updatedExpected)
|
||||
require.NoError(t, err)
|
||||
@@ -294,7 +288,7 @@ func TestIntegrationTimeIntervalAccessControl(t *testing.T) {
|
||||
expected = updated
|
||||
|
||||
t.Run("should get NotFound if name does not exist", func(t *testing.T) {
|
||||
up := updatedExpected.DeepCopy()
|
||||
up := updatedExpected.Copy().(*v0alpha1.TimeInterval)
|
||||
up.Name = "notFound"
|
||||
_, err := client.Update(ctx, up, v1.UpdateOptions{})
|
||||
require.Truef(t, errors.IsNotFound(err), "Should get NotFound error but got: %s", err)
|
||||
@@ -306,7 +300,7 @@ func TestIntegrationTimeIntervalAccessControl(t *testing.T) {
|
||||
require.Truef(t, errors.IsForbidden(err), "should get Forbidden error but got %s", err)
|
||||
|
||||
t.Run("should get forbidden even if resource does not exist", func(t *testing.T) {
|
||||
up := updatedExpected.DeepCopy()
|
||||
up := updatedExpected.Copy().(*v0alpha1.TimeInterval)
|
||||
up.Name = "notFound"
|
||||
_, err := client.Update(ctx, up, v1.UpdateOptions{})
|
||||
require.Truef(t, errors.IsForbidden(err), "should get Forbidden error but got %s", err)
|
||||
@@ -361,9 +355,7 @@ func TestIntegrationTimeIntervalProvisioning(t *testing.T) {
|
||||
org := helper.Org1
|
||||
|
||||
admin := org.Admin
|
||||
adminK8sClient, err := versioned.NewForConfig(admin.NewRestConfig())
|
||||
require.NoError(t, err)
|
||||
adminClient := adminK8sClient.NotificationsV0alpha1().TimeIntervals("default")
|
||||
adminClient := newClient(t, helper.Org1.Admin)
|
||||
|
||||
env := helper.GetEnv()
|
||||
ac := acimpl.ProvideAccessControl(env.FeatureToggles, zanzana.NewNoopClient())
|
||||
@@ -374,9 +366,9 @@ func TestIntegrationTimeIntervalProvisioning(t *testing.T) {
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: v0alpha1.TimeIntervalSpec{
|
||||
Spec: v0alpha1.Spec{
|
||||
Name: "time-interval-1",
|
||||
TimeIntervals: v0alpha1.IntervalGenerator{}.GenerateMany(2),
|
||||
TimeIntervals: fakes.IntervalGenerator{}.GenerateMany(2),
|
||||
},
|
||||
}, v1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
@@ -394,8 +386,8 @@ func TestIntegrationTimeIntervalProvisioning(t *testing.T) {
|
||||
require.Equal(t, "API", got.GetProvenanceStatus())
|
||||
})
|
||||
t.Run("should not let update if provisioned", func(t *testing.T) {
|
||||
updated := created.DeepCopy()
|
||||
updated.Spec.TimeIntervals = v0alpha1.IntervalGenerator{}.GenerateMany(2)
|
||||
updated := created.Copy().(*v0alpha1.TimeInterval)
|
||||
updated.Spec.TimeIntervals = fakes.IntervalGenerator{}.GenerateMany(2)
|
||||
|
||||
_, err := adminClient.Update(ctx, updated, v1.UpdateOptions{})
|
||||
require.Truef(t, errors.IsForbidden(err), "should get Forbidden error but got %s", err)
|
||||
@@ -415,17 +407,15 @@ func TestIntegrationTimeIntervalOptimisticConcurrency(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
helper := getTestHelper(t)
|
||||
|
||||
adminK8sClient, err := versioned.NewForConfig(helper.Org1.Admin.NewRestConfig())
|
||||
require.NoError(t, err)
|
||||
adminClient := adminK8sClient.NotificationsV0alpha1().TimeIntervals("default")
|
||||
adminClient := newClient(t, helper.Org1.Admin)
|
||||
|
||||
interval := v0alpha1.TimeInterval{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: v0alpha1.TimeIntervalSpec{
|
||||
Spec: v0alpha1.Spec{
|
||||
Name: "time-interval",
|
||||
TimeIntervals: v0alpha1.IntervalGenerator{}.GenerateMany(2),
|
||||
TimeIntervals: fakes.IntervalGenerator{}.GenerateMany(2),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -435,23 +425,23 @@ func TestIntegrationTimeIntervalOptimisticConcurrency(t *testing.T) {
|
||||
require.NotEmpty(t, created.ResourceVersion)
|
||||
|
||||
t.Run("should forbid if version does not match", func(t *testing.T) {
|
||||
updated := created.DeepCopy()
|
||||
updated := created.Copy().(*v0alpha1.TimeInterval)
|
||||
updated.ResourceVersion = "test"
|
||||
_, err := adminClient.Update(ctx, updated, v1.UpdateOptions{})
|
||||
require.Truef(t, errors.IsConflict(err), "should get Forbidden error but got %s", err)
|
||||
})
|
||||
t.Run("should update if version matches", func(t *testing.T) {
|
||||
updated := created.DeepCopy()
|
||||
updated.Spec.TimeIntervals = v0alpha1.IntervalGenerator{}.GenerateMany(2)
|
||||
updated := created.Copy().(*v0alpha1.TimeInterval)
|
||||
updated.Spec.TimeIntervals = fakes.IntervalGenerator{}.GenerateMany(2)
|
||||
actualUpdated, err := adminClient.Update(ctx, updated, v1.UpdateOptions{})
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, updated.Spec, actualUpdated.Spec)
|
||||
require.NotEqual(t, updated.ResourceVersion, actualUpdated.ResourceVersion)
|
||||
})
|
||||
t.Run("should update if version is empty", func(t *testing.T) {
|
||||
updated := created.DeepCopy()
|
||||
updated := created.Copy().(*v0alpha1.TimeInterval)
|
||||
updated.ResourceVersion = ""
|
||||
updated.Spec.TimeIntervals = v0alpha1.IntervalGenerator{}.GenerateMany(2)
|
||||
updated.Spec.TimeIntervals = fakes.IntervalGenerator{}.GenerateMany(2)
|
||||
|
||||
actualUpdated, err := adminClient.Update(ctx, updated, v1.UpdateOptions{})
|
||||
require.NoError(t, err)
|
||||
@@ -501,17 +491,15 @@ func TestIntegrationTimeIntervalPatch(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
helper := getTestHelper(t)
|
||||
|
||||
adminK8sClient, err := versioned.NewForConfig(helper.Org1.Admin.NewRestConfig())
|
||||
require.NoError(t, err)
|
||||
adminClient := adminK8sClient.NotificationsV0alpha1().TimeIntervals("default")
|
||||
adminClient := newClient(t, helper.Org1.Admin)
|
||||
|
||||
interval := v0alpha1.TimeInterval{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: v0alpha1.TimeIntervalSpec{
|
||||
Spec: v0alpha1.Spec{
|
||||
Name: "time-interval",
|
||||
TimeIntervals: v0alpha1.IntervalGenerator{}.GenerateMany(2),
|
||||
TimeIntervals: fakes.IntervalGenerator{}.GenerateMany(2),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -534,7 +522,7 @@ func TestIntegrationTimeIntervalPatch(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("should patch with json patch", func(t *testing.T) {
|
||||
expected := v0alpha1.IntervalGenerator{}.Generate()
|
||||
expected := fakes.IntervalGenerator{}.Generate()
|
||||
|
||||
patch := []map[string]interface{}{
|
||||
{
|
||||
@@ -549,9 +537,11 @@ func TestIntegrationTimeIntervalPatch(t *testing.T) {
|
||||
|
||||
result, err := adminClient.Patch(ctx, current.Name, types.JSONPatchType, patchData, v1.PatchOptions{})
|
||||
require.NoError(t, err)
|
||||
expectedSpec := *current.Spec.DeepCopy()
|
||||
expectedSpec.TimeIntervals = []v0alpha1.Interval{
|
||||
expected,
|
||||
expectedSpec := v0alpha1.Spec{
|
||||
Name: current.Spec.Name,
|
||||
TimeIntervals: []v0alpha1.Interval{
|
||||
expected,
|
||||
},
|
||||
}
|
||||
require.EqualValues(t, expectedSpec, result.Spec)
|
||||
current = result
|
||||
@@ -566,29 +556,27 @@ func TestIntegrationTimeIntervalListSelector(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
helper := getTestHelper(t)
|
||||
|
||||
adminK8sClient, err := versioned.NewForConfig(helper.Org1.Admin.NewRestConfig())
|
||||
require.NoError(t, err)
|
||||
adminClient := adminK8sClient.NotificationsV0alpha1().TimeIntervals("default")
|
||||
adminClient := newClient(t, helper.Org1.Admin)
|
||||
|
||||
interval1 := &v0alpha1.TimeInterval{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: v0alpha1.TimeIntervalSpec{
|
||||
Spec: v0alpha1.Spec{
|
||||
Name: "test1",
|
||||
TimeIntervals: v0alpha1.IntervalGenerator{}.GenerateMany(2),
|
||||
TimeIntervals: fakes.IntervalGenerator{}.GenerateMany(2),
|
||||
},
|
||||
}
|
||||
interval1, err = adminClient.Create(ctx, interval1, v1.CreateOptions{})
|
||||
interval1, err := adminClient.Create(ctx, interval1, v1.CreateOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
interval2 := &v0alpha1.TimeInterval{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
},
|
||||
Spec: v0alpha1.TimeIntervalSpec{
|
||||
Spec: v0alpha1.Spec{
|
||||
Name: "test2",
|
||||
TimeIntervals: v0alpha1.IntervalGenerator{}.GenerateMany(2),
|
||||
TimeIntervals: fakes.IntervalGenerator{}.GenerateMany(2),
|
||||
},
|
||||
}
|
||||
interval2, err = adminClient.Create(ctx, interval2, v1.CreateOptions{})
|
||||
@@ -630,7 +618,7 @@ func TestIntegrationTimeIntervalListSelector(t *testing.T) {
|
||||
|
||||
t.Run("should filter by multiple filters", func(t *testing.T) {
|
||||
list, err := adminClient.List(ctx, v1.ListOptions{
|
||||
FieldSelector: fmt.Sprintf("metadata.name=%s,metadata.provenance=%s", interval2.Name, "API"),
|
||||
FieldSelector: fmt.Sprintf("metadata.name=%s,spec.name=%s", interval2.Name, interval2.Spec.Name),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Len(t, list.Items, 1)
|
||||
@@ -639,7 +627,7 @@ func TestIntegrationTimeIntervalListSelector(t *testing.T) {
|
||||
|
||||
t.Run("should be empty when filter does not match", func(t *testing.T) {
|
||||
list, err := adminClient.List(ctx, v1.ListOptions{
|
||||
FieldSelector: fmt.Sprintf("metadata.name=%s,metadata.provenance=%s", interval2.Name, "unknown"),
|
||||
FieldSelector: fmt.Sprintf("metadata.name=%s", "unknown"),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, list.Items)
|
||||
@@ -684,9 +672,7 @@ func TestIntegrationTimeIntervalReferentialIntegrity(t *testing.T) {
|
||||
currentRoute := legacyCli.GetRoute(t)
|
||||
currentRuleGroup := legacyCli.GetRulesGroup(t, folderUID, ruleGroup.Name)
|
||||
|
||||
adminK8sClient, err := versioned.NewForConfig(cliCfg)
|
||||
require.NoError(t, err)
|
||||
adminClient := adminK8sClient.NotificationsV0alpha1().TimeIntervals("default")
|
||||
adminClient := newClient(t, helper.Org1.Admin)
|
||||
|
||||
intervals, err := adminClient.List(ctx, v1.ListOptions{})
|
||||
require.NoError(t, err)
|
||||
@@ -710,7 +696,7 @@ func TestIntegrationTimeIntervalReferentialIntegrity(t *testing.T) {
|
||||
|
||||
t.Run("Update", func(t *testing.T) {
|
||||
t.Run("should rename all references if name changes", func(t *testing.T) {
|
||||
renamed := interval.DeepCopy()
|
||||
renamed := interval.Copy().(*v0alpha1.TimeInterval)
|
||||
renamed.Spec.Name += "-new"
|
||||
|
||||
actual, err := adminClient.Update(ctx, renamed, v1.UpdateOptions{})
|
||||
@@ -734,7 +720,7 @@ func TestIntegrationTimeIntervalReferentialIntegrity(t *testing.T) {
|
||||
|
||||
t.Run("should fail if at least one resource is provisioned", func(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
renamed := interval.DeepCopy()
|
||||
renamed := interval.Copy().(*v0alpha1.TimeInterval)
|
||||
renamed.Spec.Name += util.GenerateShortUID()
|
||||
|
||||
t.Run("provisioned route", func(t *testing.T) {
|
||||
@@ -787,24 +773,22 @@ func TestIntegrationTimeIntervalValidation(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
helper := getTestHelper(t)
|
||||
|
||||
adminK8sClient, err := versioned.NewForConfig(helper.Org1.Admin.NewRestConfig())
|
||||
require.NoError(t, err)
|
||||
adminClient := adminK8sClient.NotificationsV0alpha1().TimeIntervals("default")
|
||||
adminClient := newClient(t, helper.Org1.Admin)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
interval v0alpha1.TimeIntervalSpec
|
||||
interval v0alpha1.Spec
|
||||
}{
|
||||
{
|
||||
name: "missing name",
|
||||
interval: v0alpha1.TimeIntervalSpec{
|
||||
interval: v0alpha1.Spec{
|
||||
Name: "",
|
||||
TimeIntervals: v0alpha1.IntervalGenerator{}.GenerateMany(1),
|
||||
TimeIntervals: fakes.IntervalGenerator{}.GenerateMany(1),
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "invalid interval",
|
||||
interval: v0alpha1.TimeIntervalSpec{
|
||||
interval: v0alpha1.Spec{
|
||||
Name: "test",
|
||||
TimeIntervals: []v0alpha1.Interval{
|
||||
{
|
||||
@@ -823,9 +807,25 @@ func TestIntegrationTimeIntervalValidation(t *testing.T) {
|
||||
},
|
||||
Spec: tc.interval,
|
||||
}
|
||||
_, err = adminClient.Create(ctx, i, v1.CreateOptions{})
|
||||
_, err := adminClient.Create(ctx, i, v1.CreateOptions{})
|
||||
require.Error(t, err)
|
||||
require.Truef(t, errors.IsBadRequest(err), "Expected BadRequest, got: %s", err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func newClient(t *testing.T, user apis.User) *apis.TypedClient[v0alpha1.TimeInterval, v0alpha1.TimeIntervalList] {
|
||||
t.Helper()
|
||||
|
||||
client, err := dynamic.NewForConfig(user.NewRestConfig())
|
||||
require.NoError(t, err)
|
||||
|
||||
return &apis.TypedClient[v0alpha1.TimeInterval, v0alpha1.TimeIntervalList]{
|
||||
Client: client.Resource(
|
||||
schema.GroupVersionResource{
|
||||
Group: v0alpha1.Kind().Group(),
|
||||
Version: v0alpha1.Kind().Version(),
|
||||
Resource: v0alpha1.Kind().Plural(),
|
||||
}).Namespace("default"),
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user