diff --git a/pkg/registry/apis/alerting/notifications/timeinterval/conversions.go b/pkg/registry/apis/alerting/notifications/timeinterval/conversions.go index 64d08635b26..15772b5d2f5 100644 --- a/pkg/registry/apis/alerting/notifications/timeinterval/conversions.go +++ b/pkg/registry/apis/alerting/notifications/timeinterval/conversions.go @@ -11,6 +11,7 @@ import ( "github.com/grafana/grafana/pkg/services/apiserver/endpoints/request" "github.com/grafana/grafana/pkg/services/ngalert/api/tooling/definitions" ngmodels "github.com/grafana/grafana/pkg/services/ngalert/models" + "github.com/grafana/grafana/pkg/services/ngalert/provisioning" ) func convertToK8sResources(orgID int64, intervals []definitions.MuteTimeInterval, namespacer request.NamespaceMapper, selector fields.Selector) (*model.TimeIntervalList, error) { @@ -74,14 +75,14 @@ func convertToDomainModel(interval *model.TimeInterval) (definitions.MuteTimeInt result := definitions.MuteTimeInterval{} err = json.Unmarshal(b, &result) if err != nil { - return definitions.MuteTimeInterval{}, err + return definitions.MuteTimeInterval{}, provisioning.MakeErrTimeIntervalInvalid(err) } result.Version = interval.ResourceVersion result.UID = interval.ObjectMeta.Name result.Provenance = definitions.Provenance(ngmodels.ProvenanceNone) err = result.Validate() if err != nil { - return definitions.MuteTimeInterval{}, err + return definitions.MuteTimeInterval{}, provisioning.MakeErrTimeIntervalInvalid(err) } return result, nil } diff --git a/pkg/tests/apis/alerting/notifications/timeinterval/timeinterval_test.go b/pkg/tests/apis/alerting/notifications/timeinterval/timeinterval_test.go index 352d6940402..6ba9df07f5c 100644 --- a/pkg/tests/apis/alerting/notifications/timeinterval/timeinterval_test.go +++ b/pkg/tests/apis/alerting/notifications/timeinterval/timeinterval_test.go @@ -778,3 +778,54 @@ func TestIntegrationTimeIntervalReferentialIntegrity(t *testing.T) { }) }) } + +func TestIntegrationTimeIntervalValidation(t *testing.T) { + if testing.Short() { + t.Skip("skipping integration test") + } + + ctx := context.Background() + helper := getTestHelper(t) + + adminK8sClient, err := versioned.NewForConfig(helper.Org1.Admin.NewRestConfig()) + require.NoError(t, err) + adminClient := adminK8sClient.NotificationsV0alpha1().TimeIntervals("default") + + testCases := []struct { + name string + interval v0alpha1.TimeIntervalSpec + }{ + { + name: "missing name", + interval: v0alpha1.TimeIntervalSpec{ + Name: "", + TimeIntervals: v0alpha1.IntervalGenerator{}.GenerateMany(1), + }, + }, + { + name: "invalid interval", + interval: v0alpha1.TimeIntervalSpec{ + Name: "test", + TimeIntervals: []v0alpha1.Interval{ + { + DaysOfMonth: []string{"1-31"}, + }, + }, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + i := &v0alpha1.TimeInterval{ + ObjectMeta: v1.ObjectMeta{ + Namespace: "default", + }, + Spec: tc.interval, + } + _, err = adminClient.Create(ctx, i, v1.CreateOptions{}) + require.Error(t, err) + require.Truef(t, errors.IsBadRequest(err), "Expected BadRequest, got: %s", err) + }) + } +}